• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef COMPILER_OPTIMIZER_OPTIMIZATIONS_REGALLOC_SPILL_FILLS_RESOLVER_H
17 #define COMPILER_OPTIMIZER_OPTIMIZATIONS_REGALLOC_SPILL_FILLS_RESOLVER_H
18 
19 #include "compiler/optimizer/ir/graph_visitor.h"
20 #include "optimizer/ir/inst.h"
21 #include "utils/arena_containers.h"
22 
23 namespace panda::compiler {
24 class RegAllocBase;
25 
26 /*
27  * There are 3 spill-fill location types:
28  * - general register
29  * - vector register
30  * - stack slot
31  *
32  * Each spill-fill's source and destination is described by index inside these locations;
33  *
34  * Since  all destinations are unique, we can use them as keys for table, which collects information about
35  * all moves:
36  * - genenral register index maps to table key one by one
37  * - vector register index offsets on number of genenral registers (MAX_NUM_REGS)
38  * - stack slot index offsets on number of all registers (MAX_NUM_REGS + MAX_NUM_VREGS)
39  *
40  * Iterating over this table `SpillFillsResolver` builds non-conflict chains of spill-fills.
41  * Building process is described before `SpillFillsResolver::Reorder()` method.
42  */
43 class SpillFillsResolver : public GraphVisitor {
44     static_assert(sizeof(Register) == sizeof(StackSlot), "Register and StackSlot should be the same size");
45 
46     using LocationIndex = uint16_t;
47     static constexpr auto INVALID_LOCATION_INDEX = std::numeric_limits<LocationIndex>::max();
48 
49     struct LocationInfo {
50         LocationType location;
51         LocationIndex idx;
52     };
53 
54     struct MoveInfo {
55         LocationIndex src;
56         DataType::Type reg_type;
57     };
58 
59 public:
60     explicit SpillFillsResolver(Graph *graph);
61     SpillFillsResolver(Graph *graph, Register resolver, size_t regs_count, size_t vregs_count = 0);
62     NO_COPY_SEMANTIC(SpillFillsResolver);
63     NO_MOVE_SEMANTIC(SpillFillsResolver);
64     ~SpillFillsResolver() override = default;
65 
66     const ArenaVector<BasicBlock *> &GetBlocksToVisit() const override;
67 
68     void Run();
69 
70     void Resolve(SpillFillInst *spill_fill_inst);
71 
72     void ResolveIfRequired(SpillFillInst *spill_fill_inst);
73 
74     Graph *GetGraph() const;
75 
76 protected:
77     static void VisitSpillFill(GraphVisitor *visitor, Inst *inst);
78 
79 private:
80     bool NeedToResolve(const ArenaVector<SpillFillData> &spill_fills);
81     void ResolveCallSpillFill(SpillFillInst *spill_fill_inst);
82     void CollectSpillFillsData(SpillFillInst *spill_fill_inst);
83     void Reorder(SpillFillInst *spill_fill_inst);
84     LocationIndex CheckAndResolveCyclicDependency(LocationIndex dst_first);
85     template <bool ciclyc>
86     void AddMovesChain(LocationIndex dst, ArenaVector<LocationIndex> *remap, SpillFillInst *spill_fill_inst);
87     LocationIndex GetResolver(DataType::Type type);
88 
89     // Get table index by Location type
Map(Location location)90     LocationIndex Map(Location location)
91     {
92         if (location.IsRegister()) {
93             return location.GetValue();
94         }
95         if (location.IsFpRegister()) {
96             return location.GetValue() + VREGS_TABLE_OFFSET;
97         }
98         if (location.IsStack()) {
99             return location.GetValue() + SLOTS_TABLE_OFFSET;
100         }
101         ASSERT(location.IsStackParameter());
102         return location.GetValue() + PARAMETER_SLOTS_OFFSET;
103     }
104 
105     // Fetch location type and element number inside this location from table index
ToLocation(LocationIndex reg)106     Location ToLocation(LocationIndex reg)
107     {
108         if (reg >= PARAMETER_SLOTS_OFFSET) {
109             return Location::MakeStackParameter(reg - PARAMETER_SLOTS_OFFSET);
110         }
111         if (reg >= SLOTS_TABLE_OFFSET) {
112             return Location::MakeStackSlot(reg - SLOTS_TABLE_OFFSET);
113         }
114         if (reg >= VREGS_TABLE_OFFSET) {
115             return Location::MakeFpRegister(reg - VREGS_TABLE_OFFSET);
116         }
117         return Location::MakeRegister(reg);
118     }
119 
IsPairedReg(Arch arch,DataType::Type type)120     static inline bool IsPairedReg(Arch arch, DataType::Type type)
121     {
122         return arch != Arch::NONE && !Is64BitsArch(arch) && Is64Bits(type, arch);
123     }
124 
125 private:
126     Graph *graph_ {nullptr};
127     ArenaVector<MoveInfo> moves_table_;
128     ArenaVector<uint8_t> loads_count_;
129     // Group of moves which can be safely inserted before all others
130     ArenaVector<SpillFillData> pre_moves_;
131     // Group of moves which can be safely inserted after all others
132     ArenaVector<SpillFillData> post_moves_;
133     Register resolver_;
134 
135     const size_t VREGS_TABLE_OFFSET;
136     const size_t SLOTS_TABLE_OFFSET;
137     const size_t PARAMETER_SLOTS_OFFSET;
138     const size_t LOCATIONS_COUNT;
139     ArenaVector<bool> reg_write_;
140     ArenaVector<bool> stack_write_;
141 
142 #include "optimizer/ir/visitor.inc"
143 };
144 }  // namespace panda::compiler
145 
146 #endif  // COMPILER_OPTIMIZER_OPTIMIZATIONS_REGALLOC_SPILL_FILLS_RESOLVER_H
147