Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- llvm/CodeGen/VirtRegMap.h - Virtual Register Map ---------*- C++ -*-===// |
2 | // |
||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
4 | // See https://llvm.org/LICENSE.txt for license information. |
||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | // |
||
9 | // This file implements a virtual register map. This maps virtual registers to |
||
10 | // physical registers and virtual registers to stack slots. It is created and |
||
11 | // updated by a register allocator and then used by a machine code rewriter that |
||
12 | // adds spill code and rewrites virtual into physical register references. |
||
13 | // |
||
14 | //===----------------------------------------------------------------------===// |
||
15 | |||
16 | #ifndef LLVM_CODEGEN_VIRTREGMAP_H |
||
17 | #define LLVM_CODEGEN_VIRTREGMAP_H |
||
18 | |||
19 | #include "llvm/ADT/IndexedMap.h" |
||
20 | #include "llvm/CodeGen/MachineFunctionPass.h" |
||
21 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
||
22 | #include "llvm/CodeGen/TileShapeInfo.h" |
||
23 | #include "llvm/Pass.h" |
||
24 | #include <cassert> |
||
25 | |||
26 | namespace llvm { |
||
27 | |||
28 | class MachineFunction; |
||
29 | class MachineRegisterInfo; |
||
30 | class raw_ostream; |
||
31 | class TargetInstrInfo; |
||
32 | |||
33 | class VirtRegMap : public MachineFunctionPass { |
||
34 | public: |
||
35 | enum { |
||
36 | NO_PHYS_REG = 0, |
||
37 | NO_STACK_SLOT = (1L << 30)-1, |
||
38 | MAX_STACK_SLOT = (1L << 18)-1 |
||
39 | }; |
||
40 | |||
41 | private: |
||
42 | MachineRegisterInfo *MRI = nullptr; |
||
43 | const TargetInstrInfo *TII = nullptr; |
||
44 | const TargetRegisterInfo *TRI = nullptr; |
||
45 | MachineFunction *MF = nullptr; |
||
46 | |||
47 | /// Virt2PhysMap - This is a virtual to physical register |
||
48 | /// mapping. Each virtual register is required to have an entry in |
||
49 | /// it; even spilled virtual registers (the register mapped to a |
||
50 | /// spilled register is the temporary used to load it from the |
||
51 | /// stack). |
||
52 | IndexedMap<Register, VirtReg2IndexFunctor> Virt2PhysMap; |
||
53 | |||
54 | /// Virt2StackSlotMap - This is virtual register to stack slot |
||
55 | /// mapping. Each spilled virtual register has an entry in it |
||
56 | /// which corresponds to the stack slot this register is spilled |
||
57 | /// at. |
||
58 | IndexedMap<int, VirtReg2IndexFunctor> Virt2StackSlotMap; |
||
59 | |||
60 | /// Virt2SplitMap - This is virtual register to splitted virtual register |
||
61 | /// mapping. |
||
62 | IndexedMap<unsigned, VirtReg2IndexFunctor> Virt2SplitMap; |
||
63 | |||
64 | /// Virt2ShapeMap - For X86 AMX register whose register is bound shape |
||
65 | /// information. |
||
66 | DenseMap<unsigned, ShapeT> Virt2ShapeMap; |
||
67 | |||
68 | /// createSpillSlot - Allocate a spill slot for RC from MFI. |
||
69 | unsigned createSpillSlot(const TargetRegisterClass *RC); |
||
70 | |||
71 | public: |
||
72 | static char ID; |
||
73 | |||
74 | VirtRegMap() |
||
75 | : MachineFunctionPass(ID), Virt2PhysMap(NO_PHYS_REG), |
||
76 | Virt2StackSlotMap(NO_STACK_SLOT), Virt2SplitMap(0) {} |
||
77 | VirtRegMap(const VirtRegMap &) = delete; |
||
78 | VirtRegMap &operator=(const VirtRegMap &) = delete; |
||
79 | |||
80 | bool runOnMachineFunction(MachineFunction &MF) override; |
||
81 | |||
82 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
||
83 | AU.setPreservesAll(); |
||
84 | MachineFunctionPass::getAnalysisUsage(AU); |
||
85 | } |
||
86 | |||
87 | MachineFunction &getMachineFunction() const { |
||
88 | assert(MF && "getMachineFunction called before runOnMachineFunction"); |
||
89 | return *MF; |
||
90 | } |
||
91 | |||
92 | MachineRegisterInfo &getRegInfo() const { return *MRI; } |
||
93 | const TargetRegisterInfo &getTargetRegInfo() const { return *TRI; } |
||
94 | |||
95 | void grow(); |
||
96 | |||
97 | /// returns true if the specified virtual register is |
||
98 | /// mapped to a physical register |
||
99 | bool hasPhys(Register virtReg) const { |
||
100 | return getPhys(virtReg) != NO_PHYS_REG; |
||
101 | } |
||
102 | |||
103 | /// returns the physical register mapped to the specified |
||
104 | /// virtual register |
||
105 | MCRegister getPhys(Register virtReg) const { |
||
106 | assert(virtReg.isVirtual()); |
||
107 | return MCRegister::from(Virt2PhysMap[virtReg.id()]); |
||
108 | } |
||
109 | |||
110 | /// creates a mapping for the specified virtual register to |
||
111 | /// the specified physical register |
||
112 | void assignVirt2Phys(Register virtReg, MCPhysReg physReg); |
||
113 | |||
114 | bool isShapeMapEmpty() const { return Virt2ShapeMap.empty(); } |
||
115 | |||
116 | bool hasShape(Register virtReg) const { |
||
117 | return getShape(virtReg).isValid(); |
||
118 | } |
||
119 | |||
120 | ShapeT getShape(Register virtReg) const { |
||
121 | assert(virtReg.isVirtual()); |
||
122 | return Virt2ShapeMap.lookup(virtReg); |
||
123 | } |
||
124 | |||
125 | void assignVirt2Shape(Register virtReg, ShapeT shape) { |
||
126 | Virt2ShapeMap[virtReg.id()] = shape; |
||
127 | } |
||
128 | |||
129 | /// clears the specified virtual register's, physical |
||
130 | /// register mapping |
||
131 | void clearVirt(Register virtReg) { |
||
132 | assert(virtReg.isVirtual()); |
||
133 | assert(Virt2PhysMap[virtReg.id()] != NO_PHYS_REG && |
||
134 | "attempt to clear a not assigned virtual register"); |
||
135 | Virt2PhysMap[virtReg.id()] = NO_PHYS_REG; |
||
136 | } |
||
137 | |||
138 | /// clears all virtual to physical register mappings |
||
139 | void clearAllVirt() { |
||
140 | Virt2PhysMap.clear(); |
||
141 | grow(); |
||
142 | } |
||
143 | |||
144 | /// returns true if VirtReg is assigned to its preferred physreg. |
||
145 | bool hasPreferredPhys(Register VirtReg) const; |
||
146 | |||
147 | /// returns true if VirtReg has a known preferred register. |
||
148 | /// This returns false if VirtReg has a preference that is a virtual |
||
149 | /// register that hasn't been assigned yet. |
||
150 | bool hasKnownPreference(Register VirtReg) const; |
||
151 | |||
152 | /// records virtReg is a split live interval from SReg. |
||
153 | void setIsSplitFromReg(Register virtReg, Register SReg) { |
||
154 | Virt2SplitMap[virtReg.id()] = SReg; |
||
155 | if (hasShape(SReg)) { |
||
156 | Virt2ShapeMap[virtReg.id()] = getShape(SReg); |
||
157 | } |
||
158 | } |
||
159 | |||
160 | /// returns the live interval virtReg is split from. |
||
161 | Register getPreSplitReg(Register virtReg) const { |
||
162 | return Virt2SplitMap[virtReg.id()]; |
||
163 | } |
||
164 | |||
165 | /// getOriginal - Return the original virtual register that VirtReg descends |
||
166 | /// from through splitting. |
||
167 | /// A register that was not created by splitting is its own original. |
||
168 | /// This operation is idempotent. |
||
169 | Register getOriginal(Register VirtReg) const { |
||
170 | Register Orig = getPreSplitReg(VirtReg); |
||
171 | return Orig ? Orig : VirtReg; |
||
172 | } |
||
173 | |||
174 | /// returns true if the specified virtual register is not |
||
175 | /// mapped to a stack slot or rematerialized. |
||
176 | bool isAssignedReg(Register virtReg) const { |
||
177 | if (getStackSlot(virtReg) == NO_STACK_SLOT) |
||
178 | return true; |
||
179 | // Split register can be assigned a physical register as well as a |
||
180 | // stack slot or remat id. |
||
181 | return (Virt2SplitMap[virtReg.id()] && |
||
182 | Virt2PhysMap[virtReg.id()] != NO_PHYS_REG); |
||
183 | } |
||
184 | |||
185 | /// returns the stack slot mapped to the specified virtual |
||
186 | /// register |
||
187 | int getStackSlot(Register virtReg) const { |
||
188 | assert(virtReg.isVirtual()); |
||
189 | return Virt2StackSlotMap[virtReg.id()]; |
||
190 | } |
||
191 | |||
192 | /// create a mapping for the specifed virtual register to |
||
193 | /// the next available stack slot |
||
194 | int assignVirt2StackSlot(Register virtReg); |
||
195 | |||
196 | /// create a mapping for the specified virtual register to |
||
197 | /// the specified stack slot |
||
198 | void assignVirt2StackSlot(Register virtReg, int SS); |
||
199 | |||
200 | void print(raw_ostream &OS, const Module* M = nullptr) const override; |
||
201 | void dump() const; |
||
202 | }; |
||
203 | |||
204 | inline raw_ostream &operator<<(raw_ostream &OS, const VirtRegMap &VRM) { |
||
205 | VRM.print(OS); |
||
206 | return OS; |
||
207 | } |
||
208 | |||
209 | } // end llvm namespace |
||
210 | |||
211 | #endif // LLVM_CODEGEN_VIRTREGMAP_H |