blob: 8a00d544f481495e6a155938c8d2a5c7834ccaa8 [file] [log] [blame]
Dan Gohman1462faa2015-11-16 16:18:28 +00001//===-- WebAssemblyRegStackify.cpp - Register Stackification --------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file implements a register stacking pass.
12///
13/// This pass reorders instructions to put register uses and defs in an order
14/// such that they form single-use expression trees. Registers fitting this form
15/// are then marked as "stackified", meaning references to them are replaced by
16/// "push" and "pop" from the stack.
17///
Dan Gohman31448f12015-12-08 03:43:03 +000018/// This is primarily a code size optimization, since temporary values on the
Dan Gohman1462faa2015-11-16 16:18:28 +000019/// expression don't need to be named.
20///
21//===----------------------------------------------------------------------===//
22
23#include "WebAssembly.h"
Dan Gohman4ba48162015-11-18 16:12:01 +000024#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" // for WebAssembly::ARGUMENT_*
Dan Gohman7a6b9822015-11-29 22:32:02 +000025#include "WebAssemblyMachineFunctionInfo.h"
Dan Gohmanb6fd39a2016-01-19 16:59:23 +000026#include "WebAssemblySubtarget.h"
Dan Gohman81719f82015-11-25 16:55:01 +000027#include "llvm/Analysis/AliasAnalysis.h"
Dan Gohman8887d1f2015-12-25 00:31:02 +000028#include "llvm/CodeGen/LiveIntervalAnalysis.h"
Dan Gohman1462faa2015-11-16 16:18:28 +000029#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
Dan Gohmanadf28172016-01-28 01:22:44 +000030#include "llvm/CodeGen/MachineDominators.h"
31#include "llvm/CodeGen/MachineInstrBuilder.h"
Dan Gohman1462faa2015-11-16 16:18:28 +000032#include "llvm/CodeGen/MachineRegisterInfo.h"
33#include "llvm/CodeGen/Passes.h"
34#include "llvm/Support/Debug.h"
35#include "llvm/Support/raw_ostream.h"
36using namespace llvm;
37
38#define DEBUG_TYPE "wasm-reg-stackify"
39
40namespace {
41class WebAssemblyRegStackify final : public MachineFunctionPass {
42 const char *getPassName() const override {
43 return "WebAssembly Register Stackify";
44 }
45
46 void getAnalysisUsage(AnalysisUsage &AU) const override {
47 AU.setPreservesCFG();
Dan Gohman81719f82015-11-25 16:55:01 +000048 AU.addRequired<AAResultsWrapperPass>();
Dan Gohmanadf28172016-01-28 01:22:44 +000049 AU.addRequired<MachineDominatorTree>();
Dan Gohman8887d1f2015-12-25 00:31:02 +000050 AU.addRequired<LiveIntervals>();
Dan Gohman1462faa2015-11-16 16:18:28 +000051 AU.addPreserved<MachineBlockFrequencyInfo>();
Dan Gohman8887d1f2015-12-25 00:31:02 +000052 AU.addPreserved<SlotIndexes>();
53 AU.addPreserved<LiveIntervals>();
Dan Gohman8887d1f2015-12-25 00:31:02 +000054 AU.addPreservedID(LiveVariablesID);
Dan Gohmanadf28172016-01-28 01:22:44 +000055 AU.addPreserved<MachineDominatorTree>();
Dan Gohman1462faa2015-11-16 16:18:28 +000056 MachineFunctionPass::getAnalysisUsage(AU);
57 }
58
59 bool runOnMachineFunction(MachineFunction &MF) override;
60
61public:
62 static char ID; // Pass identification, replacement for typeid
63 WebAssemblyRegStackify() : MachineFunctionPass(ID) {}
64};
65} // end anonymous namespace
66
67char WebAssemblyRegStackify::ID = 0;
68FunctionPass *llvm::createWebAssemblyRegStackify() {
69 return new WebAssemblyRegStackify();
70}
71
Dan Gohmanb0992da2015-11-20 02:19:12 +000072// Decorate the given instruction with implicit operands that enforce the
Dan Gohman8887d1f2015-12-25 00:31:02 +000073// expression stack ordering constraints for an instruction which is on
74// the expression stack.
75static void ImposeStackOrdering(MachineInstr *MI) {
Dan Gohman4da4abd2015-12-05 00:51:40 +000076 // Write the opaque EXPR_STACK register.
77 if (!MI->definesRegister(WebAssembly::EXPR_STACK))
78 MI->addOperand(MachineOperand::CreateReg(WebAssembly::EXPR_STACK,
79 /*isDef=*/true,
80 /*isImp=*/true));
Dan Gohman4da4abd2015-12-05 00:51:40 +000081
82 // Also read the opaque EXPR_STACK register.
Dan Gohmana712a6c2015-12-14 22:37:23 +000083 if (!MI->readsRegister(WebAssembly::EXPR_STACK))
84 MI->addOperand(MachineOperand::CreateReg(WebAssembly::EXPR_STACK,
85 /*isDef=*/false,
86 /*isImp=*/true));
Dan Gohmanb0992da2015-11-20 02:19:12 +000087}
88
Dan Gohman8887d1f2015-12-25 00:31:02 +000089// Test whether it's safe to move Def to just before Insert.
Dan Gohman81719f82015-11-25 16:55:01 +000090// TODO: Compute memory dependencies in a way that doesn't require always
91// walking the block.
92// TODO: Compute memory dependencies in a way that uses AliasAnalysis to be
93// more precise.
94static bool IsSafeToMove(const MachineInstr *Def, const MachineInstr *Insert,
Dan Gohmanadf28172016-01-28 01:22:44 +000095 AliasAnalysis &AA, const LiveIntervals &LIS,
96 const MachineRegisterInfo &MRI) {
Dan Gohman391a98a2015-12-03 23:07:03 +000097 assert(Def->getParent() == Insert->getParent());
Dan Gohman81719f82015-11-25 16:55:01 +000098 bool SawStore = false, SawSideEffects = false;
99 MachineBasicBlock::const_iterator D(Def), I(Insert);
Dan Gohman8887d1f2015-12-25 00:31:02 +0000100
101 // Check for register dependencies.
102 for (const MachineOperand &MO : Def->operands()) {
103 if (!MO.isReg() || MO.isUndef())
104 continue;
105 unsigned Reg = MO.getReg();
106
107 // If the register is dead here and at Insert, ignore it.
108 if (MO.isDead() && Insert->definesRegister(Reg) &&
109 !Insert->readsRegister(Reg))
110 continue;
111
112 if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000113 // Ignore ARGUMENTS; it's just used to keep the ARGUMENT_* instructions
114 // from moving down, and we've already checked for that.
115 if (Reg == WebAssembly::ARGUMENTS)
116 continue;
Dan Gohman8887d1f2015-12-25 00:31:02 +0000117 // If the physical register is never modified, ignore it.
118 if (!MRI.isPhysRegModified(Reg))
119 continue;
120 // Otherwise, it's a physical register with unknown liveness.
121 return false;
122 }
123
124 // Ask LiveIntervals whether moving this virtual register use or def to
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000125 // Insert will change which value numbers are seen.
Dan Gohman8887d1f2015-12-25 00:31:02 +0000126 const LiveInterval &LI = LIS.getInterval(Reg);
Dan Gohmanb6fd39a2016-01-19 16:59:23 +0000127 VNInfo *DefVNI =
JF Bastien13d3b9b2016-02-27 16:38:23 +0000128 MO.isDef() ? LI.getVNInfoAt(LIS.getInstructionIndex(*Def).getRegSlot())
129 : LI.getVNInfoBefore(LIS.getInstructionIndex(*Def));
Dan Gohman8887d1f2015-12-25 00:31:02 +0000130 assert(DefVNI && "Instruction input missing value number");
JF Bastien13d3b9b2016-02-27 16:38:23 +0000131 VNInfo *InsVNI = LI.getVNInfoBefore(LIS.getInstructionIndex(*Insert));
Dan Gohman8887d1f2015-12-25 00:31:02 +0000132 if (InsVNI && DefVNI != InsVNI)
133 return false;
134 }
135
Derek Schufff8f8f092016-02-16 21:44:19 +0000136 SawStore = Def->isCall() || Def->mayStore();
Dan Gohman8887d1f2015-12-25 00:31:02 +0000137 // Check for memory dependencies and side effects.
Dan Gohman81719f82015-11-25 16:55:01 +0000138 for (--I; I != D; --I)
Dan Gohman7e649172016-01-20 04:21:16 +0000139 SawSideEffects |= !I->isSafeToMove(&AA, SawStore);
Dan Gohman81719f82015-11-25 16:55:01 +0000140 return !(SawStore && Def->mayLoad() && !Def->isInvariantLoad(&AA)) &&
141 !(SawSideEffects && !Def->isSafeToMove(&AA, SawStore));
142}
143
Dan Gohmanadf28172016-01-28 01:22:44 +0000144/// Test whether OneUse, a use of Reg, dominates all of Reg's other uses.
145static bool OneUseDominatesOtherUses(unsigned Reg, const MachineOperand &OneUse,
146 const MachineBasicBlock &MBB,
147 const MachineRegisterInfo &MRI,
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000148 const MachineDominatorTree &MDT,
149 LiveIntervals &LIS) {
150 const LiveInterval &LI = LIS.getInterval(Reg);
151
152 const MachineInstr *OneUseInst = OneUse.getParent();
153 VNInfo *OneUseVNI = LI.getVNInfoBefore(LIS.getInstructionIndex(*OneUseInst));
154
Dan Gohmanadf28172016-01-28 01:22:44 +0000155 for (const MachineOperand &Use : MRI.use_operands(Reg)) {
156 if (&Use == &OneUse)
157 continue;
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000158
Dan Gohmanadf28172016-01-28 01:22:44 +0000159 const MachineInstr *UseInst = Use.getParent();
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000160 VNInfo *UseVNI = LI.getVNInfoBefore(LIS.getInstructionIndex(*UseInst));
161
162 if (UseVNI != OneUseVNI)
163 continue;
164
Dan Gohmanadf28172016-01-28 01:22:44 +0000165 const MachineInstr *OneUseInst = OneUse.getParent();
166 if (UseInst->getOpcode() == TargetOpcode::PHI) {
167 // Test that the PHI use, which happens on the CFG edge rather than
168 // within the PHI's own block, is dominated by the one selected use.
169 const MachineBasicBlock *Pred =
170 UseInst->getOperand(&Use - &UseInst->getOperand(0) + 1).getMBB();
171 if (!MDT.dominates(&MBB, Pred))
172 return false;
173 } else if (UseInst == OneUseInst) {
174 // Another use in the same instruction. We need to ensure that the one
175 // selected use happens "before" it.
176 if (&OneUse > &Use)
177 return false;
178 } else {
179 // Test that the use is dominated by the one selected use.
180 if (!MDT.dominates(OneUseInst, UseInst))
181 return false;
182 }
183 }
184 return true;
185}
186
187/// Get the appropriate tee_local opcode for the given register class.
188static unsigned GetTeeLocalOpcode(const TargetRegisterClass *RC) {
189 if (RC == &WebAssembly::I32RegClass)
190 return WebAssembly::TEE_LOCAL_I32;
191 if (RC == &WebAssembly::I64RegClass)
192 return WebAssembly::TEE_LOCAL_I64;
193 if (RC == &WebAssembly::F32RegClass)
194 return WebAssembly::TEE_LOCAL_F32;
195 if (RC == &WebAssembly::F64RegClass)
196 return WebAssembly::TEE_LOCAL_F64;
197 llvm_unreachable("Unexpected register class");
198}
199
200/// A single-use def in the same block with no intervening memory or register
201/// dependencies; move the def down and nest it with the current instruction.
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000202static MachineInstr *MoveForSingleUse(unsigned Reg, MachineOperand& Op,
203 MachineInstr *Def,
Dan Gohmanadf28172016-01-28 01:22:44 +0000204 MachineBasicBlock &MBB,
205 MachineInstr *Insert, LiveIntervals &LIS,
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000206 WebAssemblyFunctionInfo &MFI,
207 MachineRegisterInfo &MRI) {
Dan Gohmanadf28172016-01-28 01:22:44 +0000208 MBB.splice(Insert, &MBB, Def);
JF Bastien1afd1e22016-02-28 15:33:53 +0000209 LIS.handleMove(*Def);
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000210
211 if (MRI.hasOneDef(Reg)) {
212 MFI.stackifyVReg(Reg);
213 } else {
214 unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(Reg));
215 Def->getOperand(0).setReg(NewReg);
216 Op.setReg(NewReg);
217
218 // Tell LiveIntervals about the new register.
219 LIS.createAndComputeVirtRegInterval(NewReg);
220
221 // Tell LiveIntervals about the changes to the old register.
222 LiveInterval &LI = LIS.getInterval(Reg);
223 LIS.removeVRegDefAt(LI, LIS.getInstructionIndex(*Def).getRegSlot());
224 LIS.shrinkToUses(&LI);
225
226 MFI.stackifyVReg(NewReg);
227 }
228
Dan Gohmanadf28172016-01-28 01:22:44 +0000229 ImposeStackOrdering(Def);
230 return Def;
231}
232
233/// A trivially cloneable instruction; clone it and nest the new copy with the
234/// current instruction.
235static MachineInstr *
236RematerializeCheapDef(unsigned Reg, MachineOperand &Op, MachineInstr *Def,
237 MachineBasicBlock &MBB, MachineInstr *Insert,
238 LiveIntervals &LIS, WebAssemblyFunctionInfo &MFI,
239 MachineRegisterInfo &MRI, const WebAssemblyInstrInfo *TII,
240 const WebAssemblyRegisterInfo *TRI) {
241 unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(Reg));
242 TII->reMaterialize(MBB, Insert, NewReg, 0, Def, *TRI);
243 Op.setReg(NewReg);
244 MachineInstr *Clone = &*std::prev(MachineBasicBlock::instr_iterator(Insert));
JF Bastien13d3b9b2016-02-27 16:38:23 +0000245 LIS.InsertMachineInstrInMaps(*Clone);
Dan Gohmanadf28172016-01-28 01:22:44 +0000246 LIS.createAndComputeVirtRegInterval(NewReg);
247 MFI.stackifyVReg(NewReg);
248 ImposeStackOrdering(Clone);
249
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000250 // Shrink the interval.
251 bool IsDead = MRI.use_empty(Reg);
252 if (!IsDead) {
253 LiveInterval &LI = LIS.getInterval(Reg);
254 LIS.shrinkToUses(&LI);
255 IsDead = !LI.liveAt(LIS.getInstructionIndex(*Def).getDeadSlot());
256 }
257
Dan Gohmanadf28172016-01-28 01:22:44 +0000258 // If that was the last use of the original, delete the original.
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000259 if (IsDead) {
JF Bastien13d3b9b2016-02-27 16:38:23 +0000260 SlotIndex Idx = LIS.getInstructionIndex(*Def).getRegSlot();
Dan Gohmanadf28172016-01-28 01:22:44 +0000261 LIS.removePhysRegDefAt(WebAssembly::ARGUMENTS, Idx);
Dan Gohmanadf28172016-01-28 01:22:44 +0000262 LIS.removeInterval(Reg);
JF Bastien13d3b9b2016-02-27 16:38:23 +0000263 LIS.RemoveMachineInstrFromMaps(*Def);
Dan Gohmanadf28172016-01-28 01:22:44 +0000264 Def->eraseFromParent();
Dan Gohmanadf28172016-01-28 01:22:44 +0000265 }
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000266
Dan Gohmanadf28172016-01-28 01:22:44 +0000267 return Clone;
268}
269
270/// A multiple-use def in the same block with no intervening memory or register
271/// dependencies; move the def down, nest it with the current instruction, and
272/// insert a tee_local to satisfy the rest of the uses. As an illustration,
273/// rewrite this:
274///
275/// Reg = INST ... // Def
276/// INST ..., Reg, ... // Insert
277/// INST ..., Reg, ...
278/// INST ..., Reg, ...
279///
280/// to this:
281///
Dan Gohman8aa237c2016-02-16 15:17:21 +0000282/// DefReg = INST ... // Def (to become the new Insert)
283/// TeeReg, NewReg = TEE_LOCAL_... DefReg
Dan Gohmanadf28172016-01-28 01:22:44 +0000284/// INST ..., TeeReg, ... // Insert
285/// INST ..., NewReg, ...
286/// INST ..., NewReg, ...
287///
Dan Gohman8aa237c2016-02-16 15:17:21 +0000288/// with DefReg and TeeReg stackified. This eliminates a get_local from the
Dan Gohmanadf28172016-01-28 01:22:44 +0000289/// resulting code.
290static MachineInstr *MoveAndTeeForMultiUse(
291 unsigned Reg, MachineOperand &Op, MachineInstr *Def, MachineBasicBlock &MBB,
292 MachineInstr *Insert, LiveIntervals &LIS, WebAssemblyFunctionInfo &MFI,
293 MachineRegisterInfo &MRI, const WebAssemblyInstrInfo *TII) {
294 MBB.splice(Insert, &MBB, Def);
JF Bastien1afd1e22016-02-28 15:33:53 +0000295 LIS.handleMove(*Def);
Dan Gohmanadf28172016-01-28 01:22:44 +0000296 const auto *RegClass = MRI.getRegClass(Reg);
297 unsigned NewReg = MRI.createVirtualRegister(RegClass);
298 unsigned TeeReg = MRI.createVirtualRegister(RegClass);
Dan Gohman8aa237c2016-02-16 15:17:21 +0000299 unsigned DefReg = MRI.createVirtualRegister(RegClass);
Dan Gohmanadf28172016-01-28 01:22:44 +0000300 MRI.replaceRegWith(Reg, NewReg);
301 MachineInstr *Tee = BuildMI(MBB, Insert, Insert->getDebugLoc(),
302 TII->get(GetTeeLocalOpcode(RegClass)), TeeReg)
303 .addReg(NewReg, RegState::Define)
Dan Gohman8aa237c2016-02-16 15:17:21 +0000304 .addReg(DefReg);
Dan Gohmanadf28172016-01-28 01:22:44 +0000305 Op.setReg(TeeReg);
Dan Gohman8aa237c2016-02-16 15:17:21 +0000306 Def->getOperand(0).setReg(DefReg);
JF Bastien13d3b9b2016-02-27 16:38:23 +0000307 LIS.InsertMachineInstrInMaps(*Tee);
Dan Gohman8aa237c2016-02-16 15:17:21 +0000308 LIS.removeInterval(Reg);
Dan Gohmanadf28172016-01-28 01:22:44 +0000309 LIS.createAndComputeVirtRegInterval(NewReg);
310 LIS.createAndComputeVirtRegInterval(TeeReg);
Dan Gohman8aa237c2016-02-16 15:17:21 +0000311 LIS.createAndComputeVirtRegInterval(DefReg);
312 MFI.stackifyVReg(DefReg);
Dan Gohmanadf28172016-01-28 01:22:44 +0000313 MFI.stackifyVReg(TeeReg);
314 ImposeStackOrdering(Def);
315 ImposeStackOrdering(Tee);
316 return Def;
317}
318
319namespace {
320/// A stack for walking the tree of instructions being built, visiting the
321/// MachineOperands in DFS order.
322class TreeWalkerState {
323 typedef MachineInstr::mop_iterator mop_iterator;
324 typedef std::reverse_iterator<mop_iterator> mop_reverse_iterator;
325 typedef iterator_range<mop_reverse_iterator> RangeTy;
326 SmallVector<RangeTy, 4> Worklist;
327
328public:
329 explicit TreeWalkerState(MachineInstr *Insert) {
330 const iterator_range<mop_iterator> &Range = Insert->explicit_uses();
331 if (Range.begin() != Range.end())
332 Worklist.push_back(reverse(Range));
333 }
334
335 bool Done() const { return Worklist.empty(); }
336
337 MachineOperand &Pop() {
338 RangeTy &Range = Worklist.back();
339 MachineOperand &Op = *Range.begin();
340 Range = drop_begin(Range, 1);
341 if (Range.begin() == Range.end())
342 Worklist.pop_back();
343 assert((Worklist.empty() ||
344 Worklist.back().begin() != Worklist.back().end()) &&
345 "Empty ranges shouldn't remain in the worklist");
346 return Op;
347 }
348
349 /// Push Instr's operands onto the stack to be visited.
350 void PushOperands(MachineInstr *Instr) {
351 const iterator_range<mop_iterator> &Range(Instr->explicit_uses());
352 if (Range.begin() != Range.end())
353 Worklist.push_back(reverse(Range));
354 }
355
356 /// Some of Instr's operands are on the top of the stack; remove them and
357 /// re-insert them starting from the beginning (because we've commuted them).
358 void ResetTopOperands(MachineInstr *Instr) {
359 assert(HasRemainingOperands(Instr) &&
360 "Reseting operands should only be done when the instruction has "
361 "an operand still on the stack");
362 Worklist.back() = reverse(Instr->explicit_uses());
363 }
364
365 /// Test whether Instr has operands remaining to be visited at the top of
366 /// the stack.
367 bool HasRemainingOperands(const MachineInstr *Instr) const {
368 if (Worklist.empty())
369 return false;
370 const RangeTy &Range = Worklist.back();
371 return Range.begin() != Range.end() && Range.begin()->getParent() == Instr;
372 }
Dan Gohmanfbfe5ec2016-01-28 03:59:09 +0000373
374 /// Test whether the given register is present on the stack, indicating an
375 /// operand in the tree that we haven't visited yet. Moving a definition of
376 /// Reg to a point in the tree after that would change its value.
377 bool IsOnStack(unsigned Reg) const {
378 for (const RangeTy &Range : Worklist)
379 for (const MachineOperand &MO : Range)
380 if (MO.isReg() && MO.getReg() == Reg)
381 return true;
382 return false;
383 }
Dan Gohmanadf28172016-01-28 01:22:44 +0000384};
385
386/// State to keep track of whether commuting is in flight or whether it's been
387/// tried for the current instruction and didn't work.
388class CommutingState {
389 /// There are effectively three states: the initial state where we haven't
390 /// started commuting anything and we don't know anything yet, the tenative
391 /// state where we've commuted the operands of the current instruction and are
392 /// revisting it, and the declined state where we've reverted the operands
393 /// back to their original order and will no longer commute it further.
394 bool TentativelyCommuting;
395 bool Declined;
396
397 /// During the tentative state, these hold the operand indices of the commuted
398 /// operands.
399 unsigned Operand0, Operand1;
400
401public:
402 CommutingState() : TentativelyCommuting(false), Declined(false) {}
403
404 /// Stackification for an operand was not successful due to ordering
405 /// constraints. If possible, and if we haven't already tried it and declined
406 /// it, commute Insert's operands and prepare to revisit it.
407 void MaybeCommute(MachineInstr *Insert, TreeWalkerState &TreeWalker,
408 const WebAssemblyInstrInfo *TII) {
409 if (TentativelyCommuting) {
410 assert(!Declined &&
411 "Don't decline commuting until you've finished trying it");
412 // Commuting didn't help. Revert it.
413 TII->commuteInstruction(Insert, /*NewMI=*/false, Operand0, Operand1);
414 TentativelyCommuting = false;
415 Declined = true;
416 } else if (!Declined && TreeWalker.HasRemainingOperands(Insert)) {
417 Operand0 = TargetInstrInfo::CommuteAnyOperandIndex;
418 Operand1 = TargetInstrInfo::CommuteAnyOperandIndex;
419 if (TII->findCommutedOpIndices(Insert, Operand0, Operand1)) {
420 // Tentatively commute the operands and try again.
421 TII->commuteInstruction(Insert, /*NewMI=*/false, Operand0, Operand1);
422 TreeWalker.ResetTopOperands(Insert);
423 TentativelyCommuting = true;
424 Declined = false;
425 }
426 }
427 }
428
429 /// Stackification for some operand was successful. Reset to the default
430 /// state.
431 void Reset() {
432 TentativelyCommuting = false;
433 Declined = false;
434 }
435};
436} // end anonymous namespace
437
Dan Gohman1462faa2015-11-16 16:18:28 +0000438bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) {
439 DEBUG(dbgs() << "********** Register Stackifying **********\n"
440 "********** Function: "
441 << MF.getName() << '\n');
442
443 bool Changed = false;
444 MachineRegisterInfo &MRI = MF.getRegInfo();
445 WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
Dan Gohmanb6fd39a2016-01-19 16:59:23 +0000446 const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
447 const auto *TRI = MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
Dan Gohman81719f82015-11-25 16:55:01 +0000448 AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
Dan Gohmanadf28172016-01-28 01:22:44 +0000449 MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
Dan Gohman8887d1f2015-12-25 00:31:02 +0000450 LiveIntervals &LIS = getAnalysis<LiveIntervals>();
Dan Gohmand70e5902015-12-08 03:30:42 +0000451
Dan Gohman1462faa2015-11-16 16:18:28 +0000452 // Walk the instructions from the bottom up. Currently we don't look past
453 // block boundaries, and the blocks aren't ordered so the block visitation
454 // order isn't significant, but we may want to change this in the future.
455 for (MachineBasicBlock &MBB : MF) {
Dan Gohman8f59cf72016-01-06 18:29:35 +0000456 // Don't use a range-based for loop, because we modify the list as we're
457 // iterating over it and the end iterator may change.
458 for (auto MII = MBB.rbegin(); MII != MBB.rend(); ++MII) {
459 MachineInstr *Insert = &*MII;
Dan Gohman1462faa2015-11-16 16:18:28 +0000460 // Don't nest anything inside a phi.
461 if (Insert->getOpcode() == TargetOpcode::PHI)
462 break;
463
Dan Gohman81719f82015-11-25 16:55:01 +0000464 // Don't nest anything inside an inline asm, because we don't have
465 // constraints for $push inputs.
466 if (Insert->getOpcode() == TargetOpcode::INLINEASM)
Dan Gohman595e8ab2016-02-22 17:45:20 +0000467 continue;
468
469 // Ignore debugging intrinsics.
470 if (Insert->getOpcode() == TargetOpcode::DBG_VALUE)
471 continue;
Dan Gohman81719f82015-11-25 16:55:01 +0000472
Dan Gohman1462faa2015-11-16 16:18:28 +0000473 // Iterate through the inputs in reverse order, since we'll be pulling
Dan Gohman53d13992015-12-02 18:08:49 +0000474 // operands off the stack in LIFO order.
Dan Gohmanadf28172016-01-28 01:22:44 +0000475 CommutingState Commuting;
476 TreeWalkerState TreeWalker(Insert);
477 while (!TreeWalker.Done()) {
478 MachineOperand &Op = TreeWalker.Pop();
479
Dan Gohman1462faa2015-11-16 16:18:28 +0000480 // We're only interested in explicit virtual register operands.
Dan Gohmanadf28172016-01-28 01:22:44 +0000481 if (!Op.isReg())
Dan Gohman1462faa2015-11-16 16:18:28 +0000482 continue;
483
484 unsigned Reg = Op.getReg();
Dan Gohmanadf28172016-01-28 01:22:44 +0000485 assert(Op.isUse() && "explicit_uses() should only iterate over uses");
486 assert(!Op.isImplicit() &&
487 "explicit_uses() should only iterate over explicit operands");
488 if (TargetRegisterInfo::isPhysicalRegister(Reg))
Dan Gohman1462faa2015-11-16 16:18:28 +0000489 continue;
490
Dan Gohmanadf28172016-01-28 01:22:44 +0000491 // Identify the definition for this register at this point. Most
492 // registers are in SSA form here so we try a quick MRI query first.
493 MachineInstr *Def = MRI.getUniqueVRegDef(Reg);
494 if (!Def) {
495 // MRI doesn't know what the Def is. Try asking LIS.
496 const VNInfo *ValNo = LIS.getInterval(Reg).getVNInfoBefore(
JF Bastien13d3b9b2016-02-27 16:38:23 +0000497 LIS.getInstructionIndex(*Insert));
Dan Gohmanadf28172016-01-28 01:22:44 +0000498 if (!ValNo)
499 continue;
500 Def = LIS.getInstructionFromIndex(ValNo->def);
501 if (!Def)
502 continue;
503 }
504
Dan Gohman81719f82015-11-25 16:55:01 +0000505 // Don't nest an INLINE_ASM def into anything, because we don't have
506 // constraints for $pop outputs.
507 if (Def->getOpcode() == TargetOpcode::INLINEASM)
508 continue;
509
510 // Don't nest PHIs inside of anything.
511 if (Def->getOpcode() == TargetOpcode::PHI)
512 continue;
513
Dan Gohman4ba48162015-11-18 16:12:01 +0000514 // Argument instructions represent live-in registers and not real
515 // instructions.
516 if (Def->getOpcode() == WebAssembly::ARGUMENT_I32 ||
517 Def->getOpcode() == WebAssembly::ARGUMENT_I64 ||
518 Def->getOpcode() == WebAssembly::ARGUMENT_F32 ||
519 Def->getOpcode() == WebAssembly::ARGUMENT_F64)
520 continue;
521
Dan Gohmanadf28172016-01-28 01:22:44 +0000522 // Decide which strategy to take. Prefer to move a single-use value
523 // over cloning it, and prefer cloning over introducing a tee_local.
524 // For moving, we require the def to be in the same block as the use;
525 // this makes things simpler (LiveIntervals' handleMove function only
526 // supports intra-block moves) and it's MachineSink's job to catch all
527 // the sinking opportunities anyway.
528 bool SameBlock = Def->getParent() == &MBB;
Dan Gohmanfbfe5ec2016-01-28 03:59:09 +0000529 bool CanMove = SameBlock && IsSafeToMove(Def, Insert, AA, LIS, MRI) &&
530 !TreeWalker.IsOnStack(Reg);
Dan Gohmanadf28172016-01-28 01:22:44 +0000531 if (CanMove && MRI.hasOneUse(Reg)) {
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000532 Insert = MoveForSingleUse(Reg, Op, Def, MBB, Insert, LIS, MFI, MRI);
Dan Gohmanb6fd39a2016-01-19 16:59:23 +0000533 } else if (Def->isAsCheapAsAMove() &&
534 TII->isTriviallyReMaterializable(Def, &AA)) {
Dan Gohmanadf28172016-01-28 01:22:44 +0000535 Insert = RematerializeCheapDef(Reg, Op, Def, MBB, Insert, LIS, MFI,
536 MRI, TII, TRI);
537 } else if (CanMove &&
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000538 OneUseDominatesOtherUses(Reg, Op, MBB, MRI, MDT, LIS)) {
Dan Gohmanadf28172016-01-28 01:22:44 +0000539 Insert = MoveAndTeeForMultiUse(Reg, Op, Def, MBB, Insert, LIS, MFI,
540 MRI, TII);
541 } else {
542 // We failed to stackify the operand. If the problem was ordering
543 // constraints, Commuting may be able to help.
544 if (!CanMove && SameBlock)
545 Commuting.MaybeCommute(Insert, TreeWalker, TII);
546 // Proceed to the next operand.
547 continue;
Dan Gohmanb6fd39a2016-01-19 16:59:23 +0000548 }
Dan Gohmanadf28172016-01-28 01:22:44 +0000549
550 // We stackified an operand. Add the defining instruction's operands to
551 // the worklist stack now to continue to build an ever deeper tree.
552 Commuting.Reset();
553 TreeWalker.PushOperands(Insert);
Dan Gohman1462faa2015-11-16 16:18:28 +0000554 }
Dan Gohmanadf28172016-01-28 01:22:44 +0000555
556 // If we stackified any operands, skip over the tree to start looking for
557 // the next instruction we can build a tree on.
558 if (Insert != &*MII) {
Dan Gohman8f59cf72016-01-06 18:29:35 +0000559 ImposeStackOrdering(&*MII);
Dan Gohmanadf28172016-01-28 01:22:44 +0000560 MII = std::prev(
Hans Wennborg369ebfe2016-03-14 11:04:15 +0000561 llvm::make_reverse_iterator(MachineBasicBlock::iterator(Insert)));
Dan Gohmanadf28172016-01-28 01:22:44 +0000562 Changed = true;
563 }
Dan Gohman1462faa2015-11-16 16:18:28 +0000564 }
565 }
566
Dan Gohmanadf28172016-01-28 01:22:44 +0000567 // If we used EXPR_STACK anywhere, add it to the live-in sets everywhere so
568 // that it never looks like a use-before-def.
Dan Gohmanb0992da2015-11-20 02:19:12 +0000569 if (Changed) {
570 MF.getRegInfo().addLiveIn(WebAssembly::EXPR_STACK);
571 for (MachineBasicBlock &MBB : MF)
572 MBB.addLiveIn(WebAssembly::EXPR_STACK);
573 }
574
Dan Gohman7bafa0e2015-11-20 02:33:24 +0000575#ifndef NDEBUG
Dan Gohmanb6fd39a2016-01-19 16:59:23 +0000576 // Verify that pushes and pops are performed in LIFO order.
Dan Gohman7bafa0e2015-11-20 02:33:24 +0000577 SmallVector<unsigned, 0> Stack;
578 for (MachineBasicBlock &MBB : MF) {
579 for (MachineInstr &MI : MBB) {
Dan Gohman0cfb5f82016-05-10 04:24:02 +0000580 if (MI.isDebugValue())
581 continue;
Dan Gohman7bafa0e2015-11-20 02:33:24 +0000582 for (MachineOperand &MO : reverse(MI.explicit_operands())) {
Dan Gohman7a6b9822015-11-29 22:32:02 +0000583 if (!MO.isReg())
584 continue;
Dan Gohmanadf28172016-01-28 01:22:44 +0000585 unsigned Reg = MO.getReg();
Dan Gohman7bafa0e2015-11-20 02:33:24 +0000586
Dan Gohmanadf28172016-01-28 01:22:44 +0000587 if (MFI.isVRegStackified(Reg)) {
Dan Gohman7bafa0e2015-11-20 02:33:24 +0000588 if (MO.isDef())
Dan Gohmanadf28172016-01-28 01:22:44 +0000589 Stack.push_back(Reg);
Dan Gohman7bafa0e2015-11-20 02:33:24 +0000590 else
Dan Gohmanadf28172016-01-28 01:22:44 +0000591 assert(Stack.pop_back_val() == Reg &&
592 "Register stack pop should be paired with a push");
Dan Gohman7bafa0e2015-11-20 02:33:24 +0000593 }
594 }
595 }
596 // TODO: Generalize this code to support keeping values on the stack across
597 // basic block boundaries.
Dan Gohmanadf28172016-01-28 01:22:44 +0000598 assert(Stack.empty() &&
599 "Register stack pushes and pops should be balanced");
Dan Gohman7bafa0e2015-11-20 02:33:24 +0000600 }
601#endif
602
Dan Gohman1462faa2015-11-16 16:18:28 +0000603 return Changed;
604}