File: | lib/Target/X86/X86WinAllocaExpander.cpp |
Warning: | line 272, column 7 Value stored to 'AmountReg' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===----- X86WinAllocaExpander.cpp - Expand WinAlloca pseudo instruction -===// |
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 defines a pass that expands WinAlloca pseudo-instructions. |
10 | // |
11 | // It performs a conservative analysis to determine whether each allocation |
12 | // falls within a region of the stack that is safe to use, or whether stack |
13 | // probes must be emitted. |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #include "X86.h" |
18 | #include "X86InstrBuilder.h" |
19 | #include "X86InstrInfo.h" |
20 | #include "X86MachineFunctionInfo.h" |
21 | #include "X86Subtarget.h" |
22 | #include "llvm/ADT/PostOrderIterator.h" |
23 | #include "llvm/CodeGen/MachineFunctionPass.h" |
24 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
25 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
26 | #include "llvm/CodeGen/Passes.h" |
27 | #include "llvm/CodeGen/TargetInstrInfo.h" |
28 | #include "llvm/IR/Function.h" |
29 | #include "llvm/Support/raw_ostream.h" |
30 | |
31 | using namespace llvm; |
32 | |
33 | namespace { |
34 | |
35 | class X86WinAllocaExpander : public MachineFunctionPass { |
36 | public: |
37 | X86WinAllocaExpander() : MachineFunctionPass(ID) {} |
38 | |
39 | bool runOnMachineFunction(MachineFunction &MF) override; |
40 | |
41 | private: |
42 | /// Strategies for lowering a WinAlloca. |
43 | enum Lowering { TouchAndSub, Sub, Probe }; |
44 | |
45 | /// Deterministic-order map from WinAlloca instruction to desired lowering. |
46 | typedef MapVector<MachineInstr*, Lowering> LoweringMap; |
47 | |
48 | /// Compute which lowering to use for each WinAlloca instruction. |
49 | void computeLowerings(MachineFunction &MF, LoweringMap& Lowerings); |
50 | |
51 | /// Get the appropriate lowering based on current offset and amount. |
52 | Lowering getLowering(int64_t CurrentOffset, int64_t AllocaAmount); |
53 | |
54 | /// Lower a WinAlloca instruction. |
55 | void lower(MachineInstr* MI, Lowering L); |
56 | |
57 | MachineRegisterInfo *MRI; |
58 | const X86Subtarget *STI; |
59 | const TargetInstrInfo *TII; |
60 | const X86RegisterInfo *TRI; |
61 | unsigned StackPtr; |
62 | unsigned SlotSize; |
63 | int64_t StackProbeSize; |
64 | bool NoStackArgProbe; |
65 | |
66 | StringRef getPassName() const override { return "X86 WinAlloca Expander"; } |
67 | static char ID; |
68 | }; |
69 | |
70 | char X86WinAllocaExpander::ID = 0; |
71 | |
72 | } // end anonymous namespace |
73 | |
74 | FunctionPass *llvm::createX86WinAllocaExpander() { |
75 | return new X86WinAllocaExpander(); |
76 | } |
77 | |
78 | /// Return the allocation amount for a WinAlloca instruction, or -1 if unknown. |
79 | static int64_t getWinAllocaAmount(MachineInstr *MI, MachineRegisterInfo *MRI) { |
80 | assert(MI->getOpcode() == X86::WIN_ALLOCA_32 ||((MI->getOpcode() == X86::WIN_ALLOCA_32 || MI->getOpcode () == X86::WIN_ALLOCA_64) ? static_cast<void> (0) : __assert_fail ("MI->getOpcode() == X86::WIN_ALLOCA_32 || MI->getOpcode() == X86::WIN_ALLOCA_64" , "/build/llvm-toolchain-snapshot-9~svn358520/lib/Target/X86/X86WinAllocaExpander.cpp" , 81, __PRETTY_FUNCTION__)) |
81 | MI->getOpcode() == X86::WIN_ALLOCA_64)((MI->getOpcode() == X86::WIN_ALLOCA_32 || MI->getOpcode () == X86::WIN_ALLOCA_64) ? static_cast<void> (0) : __assert_fail ("MI->getOpcode() == X86::WIN_ALLOCA_32 || MI->getOpcode() == X86::WIN_ALLOCA_64" , "/build/llvm-toolchain-snapshot-9~svn358520/lib/Target/X86/X86WinAllocaExpander.cpp" , 81, __PRETTY_FUNCTION__)); |
82 | assert(MI->getOperand(0).isReg())((MI->getOperand(0).isReg()) ? static_cast<void> (0) : __assert_fail ("MI->getOperand(0).isReg()", "/build/llvm-toolchain-snapshot-9~svn358520/lib/Target/X86/X86WinAllocaExpander.cpp" , 82, __PRETTY_FUNCTION__)); |
83 | |
84 | unsigned AmountReg = MI->getOperand(0).getReg(); |
85 | MachineInstr *Def = MRI->getUniqueVRegDef(AmountReg); |
86 | |
87 | // Look through copies. |
88 | while (Def && Def->isCopy() && Def->getOperand(1).isReg()) |
89 | Def = MRI->getUniqueVRegDef(Def->getOperand(1).getReg()); |
90 | |
91 | if (!Def || |
92 | (Def->getOpcode() != X86::MOV32ri && Def->getOpcode() != X86::MOV64ri) || |
93 | !Def->getOperand(1).isImm()) |
94 | return -1; |
95 | |
96 | return Def->getOperand(1).getImm(); |
97 | } |
98 | |
99 | X86WinAllocaExpander::Lowering |
100 | X86WinAllocaExpander::getLowering(int64_t CurrentOffset, |
101 | int64_t AllocaAmount) { |
102 | // For a non-constant amount or a large amount, we have to probe. |
103 | if (AllocaAmount < 0 || AllocaAmount > StackProbeSize) |
104 | return Probe; |
105 | |
106 | // If it fits within the safe region of the stack, just subtract. |
107 | if (CurrentOffset + AllocaAmount <= StackProbeSize) |
108 | return Sub; |
109 | |
110 | // Otherwise, touch the current tip of the stack, then subtract. |
111 | return TouchAndSub; |
112 | } |
113 | |
114 | static bool isPushPop(const MachineInstr &MI) { |
115 | switch (MI.getOpcode()) { |
116 | case X86::PUSH32i8: |
117 | case X86::PUSH32r: |
118 | case X86::PUSH32rmm: |
119 | case X86::PUSH32rmr: |
120 | case X86::PUSHi32: |
121 | case X86::PUSH64i8: |
122 | case X86::PUSH64r: |
123 | case X86::PUSH64rmm: |
124 | case X86::PUSH64rmr: |
125 | case X86::PUSH64i32: |
126 | case X86::POP32r: |
127 | case X86::POP64r: |
128 | return true; |
129 | default: |
130 | return false; |
131 | } |
132 | } |
133 | |
134 | void X86WinAllocaExpander::computeLowerings(MachineFunction &MF, |
135 | LoweringMap &Lowerings) { |
136 | // Do a one-pass reverse post-order walk of the CFG to conservatively estimate |
137 | // the offset between the stack pointer and the lowest touched part of the |
138 | // stack, and use that to decide how to lower each WinAlloca instruction. |
139 | |
140 | // Initialize OutOffset[B], the stack offset at exit from B, to something big. |
141 | DenseMap<MachineBasicBlock *, int64_t> OutOffset; |
142 | for (MachineBasicBlock &MBB : MF) |
143 | OutOffset[&MBB] = INT32_MAX(2147483647); |
144 | |
145 | // Note: we don't know the offset at the start of the entry block since the |
146 | // prologue hasn't been inserted yet, and how much that will adjust the stack |
147 | // pointer depends on register spills, which have not been computed yet. |
148 | |
149 | // Compute the reverse post-order. |
150 | ReversePostOrderTraversal<MachineFunction*> RPO(&MF); |
151 | |
152 | for (MachineBasicBlock *MBB : RPO) { |
153 | int64_t Offset = -1; |
154 | for (MachineBasicBlock *Pred : MBB->predecessors()) |
155 | Offset = std::max(Offset, OutOffset[Pred]); |
156 | if (Offset == -1) Offset = INT32_MAX(2147483647); |
157 | |
158 | for (MachineInstr &MI : *MBB) { |
159 | if (MI.getOpcode() == X86::WIN_ALLOCA_32 || |
160 | MI.getOpcode() == X86::WIN_ALLOCA_64) { |
161 | // A WinAlloca moves StackPtr, and potentially touches it. |
162 | int64_t Amount = getWinAllocaAmount(&MI, MRI); |
163 | Lowering L = getLowering(Offset, Amount); |
164 | Lowerings[&MI] = L; |
165 | switch (L) { |
166 | case Sub: |
167 | Offset += Amount; |
168 | break; |
169 | case TouchAndSub: |
170 | Offset = Amount; |
171 | break; |
172 | case Probe: |
173 | Offset = 0; |
174 | break; |
175 | } |
176 | } else if (MI.isCall() || isPushPop(MI)) { |
177 | // Calls, pushes and pops touch the tip of the stack. |
178 | Offset = 0; |
179 | } else if (MI.getOpcode() == X86::ADJCALLSTACKUP32 || |
180 | MI.getOpcode() == X86::ADJCALLSTACKUP64) { |
181 | Offset -= MI.getOperand(0).getImm(); |
182 | } else if (MI.getOpcode() == X86::ADJCALLSTACKDOWN32 || |
183 | MI.getOpcode() == X86::ADJCALLSTACKDOWN64) { |
184 | Offset += MI.getOperand(0).getImm(); |
185 | } else if (MI.modifiesRegister(StackPtr, TRI)) { |
186 | // Any other modification of SP means we've lost track of it. |
187 | Offset = INT32_MAX(2147483647); |
188 | } |
189 | } |
190 | |
191 | OutOffset[MBB] = Offset; |
192 | } |
193 | } |
194 | |
195 | static unsigned getSubOpcode(bool Is64Bit, int64_t Amount) { |
196 | if (Is64Bit) |
197 | return isInt<8>(Amount) ? X86::SUB64ri8 : X86::SUB64ri32; |
198 | return isInt<8>(Amount) ? X86::SUB32ri8 : X86::SUB32ri; |
199 | } |
200 | |
201 | void X86WinAllocaExpander::lower(MachineInstr* MI, Lowering L) { |
202 | DebugLoc DL = MI->getDebugLoc(); |
203 | MachineBasicBlock *MBB = MI->getParent(); |
204 | MachineBasicBlock::iterator I = *MI; |
205 | |
206 | int64_t Amount = getWinAllocaAmount(MI, MRI); |
207 | if (Amount == 0) { |
208 | MI->eraseFromParent(); |
209 | return; |
210 | } |
211 | |
212 | bool Is64Bit = STI->is64Bit(); |
213 | assert(SlotSize == 4 || SlotSize == 8)((SlotSize == 4 || SlotSize == 8) ? static_cast<void> ( 0) : __assert_fail ("SlotSize == 4 || SlotSize == 8", "/build/llvm-toolchain-snapshot-9~svn358520/lib/Target/X86/X86WinAllocaExpander.cpp" , 213, __PRETTY_FUNCTION__)); |
214 | unsigned RegA = (SlotSize == 8) ? X86::RAX : X86::EAX; |
215 | |
216 | switch (L) { |
217 | case TouchAndSub: |
218 | assert(Amount >= SlotSize)((Amount >= SlotSize) ? static_cast<void> (0) : __assert_fail ("Amount >= SlotSize", "/build/llvm-toolchain-snapshot-9~svn358520/lib/Target/X86/X86WinAllocaExpander.cpp" , 218, __PRETTY_FUNCTION__)); |
219 | |
220 | // Use a push to touch the top of the stack. |
221 | BuildMI(*MBB, I, DL, TII->get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) |
222 | .addReg(RegA, RegState::Undef); |
223 | Amount -= SlotSize; |
224 | if (!Amount) |
225 | break; |
226 | |
227 | // Fall through to make any remaining adjustment. |
228 | LLVM_FALLTHROUGH[[clang::fallthrough]]; |
229 | case Sub: |
230 | assert(Amount > 0)((Amount > 0) ? static_cast<void> (0) : __assert_fail ("Amount > 0", "/build/llvm-toolchain-snapshot-9~svn358520/lib/Target/X86/X86WinAllocaExpander.cpp" , 230, __PRETTY_FUNCTION__)); |
231 | if (Amount == SlotSize) { |
232 | // Use push to save size. |
233 | BuildMI(*MBB, I, DL, TII->get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) |
234 | .addReg(RegA, RegState::Undef); |
235 | } else { |
236 | // Sub. |
237 | BuildMI(*MBB, I, DL, TII->get(getSubOpcode(Is64Bit, Amount)), StackPtr) |
238 | .addReg(StackPtr) |
239 | .addImm(Amount); |
240 | } |
241 | break; |
242 | case Probe: |
243 | if (!NoStackArgProbe) { |
244 | // The probe lowering expects the amount in RAX/EAX. |
245 | BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY), RegA) |
246 | .addReg(MI->getOperand(0).getReg()); |
247 | |
248 | // Do the probe. |
249 | STI->getFrameLowering()->emitStackProbe(*MBB->getParent(), *MBB, MI, DL, |
250 | /*InPrologue=*/false); |
251 | } else { |
252 | // Sub |
253 | BuildMI(*MBB, I, DL, TII->get(Is64Bit ? X86::SUB64rr : X86::SUB32rr), |
254 | StackPtr) |
255 | .addReg(StackPtr) |
256 | .addReg(MI->getOperand(0).getReg()); |
257 | } |
258 | break; |
259 | } |
260 | |
261 | unsigned AmountReg = MI->getOperand(0).getReg(); |
262 | MI->eraseFromParent(); |
263 | |
264 | // Delete the definition of AmountReg, possibly walking a chain of copies. |
265 | for (;;) { |
266 | if (!MRI->use_empty(AmountReg)) |
267 | break; |
268 | MachineInstr *AmountDef = MRI->getUniqueVRegDef(AmountReg); |
269 | if (!AmountDef) |
270 | break; |
271 | if (AmountDef->isCopy() && AmountDef->getOperand(1).isReg()) |
272 | AmountReg = AmountDef->getOperand(1).isReg(); |
Value stored to 'AmountReg' is never read | |
273 | AmountDef->eraseFromParent(); |
274 | break; |
275 | } |
276 | } |
277 | |
278 | bool X86WinAllocaExpander::runOnMachineFunction(MachineFunction &MF) { |
279 | if (!MF.getInfo<X86MachineFunctionInfo>()->hasWinAlloca()) |
280 | return false; |
281 | |
282 | MRI = &MF.getRegInfo(); |
283 | STI = &MF.getSubtarget<X86Subtarget>(); |
284 | TII = STI->getInstrInfo(); |
285 | TRI = STI->getRegisterInfo(); |
286 | StackPtr = TRI->getStackRegister(); |
287 | SlotSize = TRI->getSlotSize(); |
288 | |
289 | StackProbeSize = 4096; |
290 | if (MF.getFunction().hasFnAttribute("stack-probe-size")) { |
291 | MF.getFunction() |
292 | .getFnAttribute("stack-probe-size") |
293 | .getValueAsString() |
294 | .getAsInteger(0, StackProbeSize); |
295 | } |
296 | NoStackArgProbe = MF.getFunction().hasFnAttribute("no-stack-arg-probe"); |
297 | if (NoStackArgProbe) |
298 | StackProbeSize = INT64_MAX(9223372036854775807L); |
299 | |
300 | LoweringMap Lowerings; |
301 | computeLowerings(MF, Lowerings); |
302 | for (auto &P : Lowerings) |
303 | lower(P.first, P.second); |
304 | |
305 | return true; |
306 | } |