@@ -41,14 +41,18 @@ using namespace llvm;
41
41
42
42
namespace {
43
43
class WebAssemblyRegStackify final : public MachineFunctionPass {
44
+ bool Optimize;
45
+
44
46
StringRef getPassName () const override {
45
47
return " WebAssembly Register Stackify" ;
46
48
}
47
49
48
50
void getAnalysisUsage (AnalysisUsage &AU) const override {
49
51
AU.setPreservesCFG ();
50
- AU.addRequired <MachineDominatorTreeWrapperPass>();
51
- AU.addRequired <LiveIntervalsWrapperPass>();
52
+ if (Optimize) {
53
+ AU.addRequired <LiveIntervalsWrapperPass>();
54
+ AU.addRequired <MachineDominatorTreeWrapperPass>();
55
+ }
52
56
AU.addPreserved <MachineBlockFrequencyInfoWrapperPass>();
53
57
AU.addPreserved <SlotIndexesWrapperPass>();
54
58
AU.addPreserved <LiveIntervalsWrapperPass>();
@@ -61,7 +65,9 @@ class WebAssemblyRegStackify final : public MachineFunctionPass {
61
65
62
66
public:
63
67
static char ID; // Pass identification, replacement for typeid
64
- WebAssemblyRegStackify () : MachineFunctionPass(ID) {}
68
+ WebAssemblyRegStackify (CodeGenOptLevel OptLevel)
69
+ : MachineFunctionPass(ID), Optimize(OptLevel != CodeGenOptLevel::None) {}
70
+ WebAssemblyRegStackify () : WebAssemblyRegStackify(CodeGenOptLevel::Default) {}
65
71
};
66
72
} // end anonymous namespace
67
73
@@ -70,8 +76,8 @@ INITIALIZE_PASS(WebAssemblyRegStackify, DEBUG_TYPE,
70
76
" Reorder instructions to use the WebAssembly value stack" ,
71
77
false , false )
72
78
73
- FunctionPass *llvm::createWebAssemblyRegStackify() {
74
- return new WebAssemblyRegStackify ();
79
+ FunctionPass *llvm::createWebAssemblyRegStackify(CodeGenOptLevel OptLevel ) {
80
+ return new WebAssemblyRegStackify (OptLevel );
75
81
}
76
82
77
83
// Decorate the given instruction with implicit operands that enforce the
@@ -96,8 +102,7 @@ static void imposeStackOrdering(MachineInstr *MI) {
96
102
static void convertImplicitDefToConstZero (MachineInstr *MI,
97
103
MachineRegisterInfo &MRI,
98
104
const TargetInstrInfo *TII,
99
- MachineFunction &MF,
100
- LiveIntervals &LIS) {
105
+ MachineFunction &MF) {
101
106
assert (MI->getOpcode () == TargetOpcode::IMPLICIT_DEF);
102
107
103
108
const auto *RegClass = MRI.getRegClass (MI->getOperand (0 ).getReg ());
@@ -262,36 +267,52 @@ static bool shouldRematerialize(const MachineInstr &Def,
262
267
// LiveIntervals to handle complex cases.
263
268
static MachineInstr *getVRegDef (unsigned Reg, const MachineInstr *Insert,
264
269
const MachineRegisterInfo &MRI,
265
- const LiveIntervals & LIS) {
270
+ const LiveIntervals * LIS) {
266
271
// Most registers are in SSA form here so we try a quick MRI query first.
267
272
if (MachineInstr *Def = MRI.getUniqueVRegDef (Reg))
268
273
return Def;
269
274
270
275
// MRI doesn't know what the Def is. Try asking LIS.
271
- if (const VNInfo *ValNo = LIS.getInterval (Reg).getVNInfoBefore (
272
- LIS.getInstructionIndex (*Insert)))
273
- return LIS.getInstructionFromIndex (ValNo->def );
276
+ if (LIS != nullptr ) {
277
+ SlotIndex InstIndex = LIS->getInstructionIndex (*Insert);
278
+ if (const VNInfo *ValNo = LIS->getInterval (Reg).getVNInfoBefore (InstIndex))
279
+ return LIS->getInstructionFromIndex (ValNo->def );
280
+ }
274
281
275
282
return nullptr ;
276
283
}
277
284
278
285
// Test whether Reg, as defined at Def, has exactly one use. This is a
279
286
// generalization of MachineRegisterInfo::hasOneNonDBGUse that uses
280
- // LiveIntervals to handle complex cases.
281
- static bool hasOneNonDBGUse (unsigned Reg, MachineInstr *Def,
282
- MachineRegisterInfo &MRI, MachineDominatorTree &MDT,
283
- LiveIntervals &LIS) {
287
+ // LiveIntervals to handle complex cases in optimized code.
288
+ static bool hasSingleUse (unsigned Reg, MachineRegisterInfo &MRI,
289
+ WebAssemblyFunctionInfo &MFI, bool Optimize,
290
+ MachineInstr *Def, LiveIntervals *LIS) {
291
+ if (!Optimize) {
292
+ // We don't want to stackify DBG_VALUE operands since WASM stack locations
293
+ // are less useful and less widely supported than WASM local locations.
294
+ if (!MRI.hasOneUse (Reg))
295
+ return false ;
296
+ // The frame base always has an implicit DBG use as DW_AT_frame_base.
297
+ if (MFI.isFrameBaseVirtual () && MFI.getFrameBaseVreg () == Reg)
298
+ return false ;
299
+ return true ;
300
+ }
301
+
284
302
// Most registers are in SSA form here so we try a quick MRI query first.
285
303
if (MRI.hasOneNonDBGUse (Reg))
286
304
return true ;
287
305
306
+ if (LIS == nullptr )
307
+ return false ;
308
+
288
309
bool HasOne = false ;
289
- const LiveInterval &LI = LIS. getInterval (Reg);
310
+ const LiveInterval &LI = LIS-> getInterval (Reg);
290
311
const VNInfo *DefVNI =
291
- LI.getVNInfoAt (LIS. getInstructionIndex (*Def).getRegSlot ());
312
+ LI.getVNInfoAt (LIS-> getInstructionIndex (*Def).getRegSlot ());
292
313
assert (DefVNI);
293
314
for (auto &I : MRI.use_nodbg_operands (Reg)) {
294
- const auto &Result = LI.Query (LIS. getInstructionIndex (*I.getParent ()));
315
+ const auto &Result = LI.Query (LIS-> getInstructionIndex (*I.getParent ()));
295
316
if (Result.valueIn () == DefVNI) {
296
317
if (!Result.isKill ())
297
318
return false ;
@@ -311,7 +332,7 @@ static bool hasOneNonDBGUse(unsigned Reg, MachineInstr *Def,
311
332
static bool isSafeToMove (const MachineOperand *Def, const MachineOperand *Use,
312
333
const MachineInstr *Insert,
313
334
const WebAssemblyFunctionInfo &MFI,
314
- const MachineRegisterInfo &MRI) {
335
+ const MachineRegisterInfo &MRI, bool Optimize ) {
315
336
const MachineInstr *DefI = Def->getParent ();
316
337
const MachineInstr *UseI = Use->getParent ();
317
338
assert (DefI->getParent () == Insert->getParent ());
@@ -357,6 +378,12 @@ static bool isSafeToMove(const MachineOperand *Def, const MachineOperand *Use,
357
378
if (NextI == Insert)
358
379
return true ;
359
380
381
+ // When not optimizing, we only handle the trivial case above
382
+ // to guarantee no impact to debugging and to avoid spending
383
+ // compile time.
384
+ if (!Optimize)
385
+ return false ;
386
+
360
387
// 'catch' and 'catch_all' should be the first instruction of a BB and cannot
361
388
// move.
362
389
if (WebAssembly::isCatch (DefI->getOpcode ()))
@@ -520,14 +547,15 @@ static void shrinkToUses(LiveInterval &LI, LiveIntervals &LIS) {
520
547
// / dependencies; move the def down and nest it with the current instruction.
521
548
static MachineInstr *moveForSingleUse (unsigned Reg, MachineOperand &Op,
522
549
MachineInstr *Def, MachineBasicBlock &MBB,
523
- MachineInstr *Insert, LiveIntervals & LIS,
550
+ MachineInstr *Insert, LiveIntervals * LIS,
524
551
WebAssemblyFunctionInfo &MFI,
525
552
MachineRegisterInfo &MRI) {
526
553
LLVM_DEBUG (dbgs () << " Move for single use: " ; Def->dump ());
527
554
528
555
WebAssemblyDebugValueManager DefDIs (Def);
529
556
DefDIs.sink (Insert);
530
- LIS.handleMove (*Def);
557
+ if (LIS != nullptr )
558
+ LIS->handleMove (*Def);
531
559
532
560
if (MRI.hasOneDef (Reg) && MRI.hasOneNonDBGUse (Reg)) {
533
561
// No one else is using this register for anything so we can just stackify
@@ -540,17 +568,18 @@ static MachineInstr *moveForSingleUse(unsigned Reg, MachineOperand &Op,
540
568
Op.setReg (NewReg);
541
569
DefDIs.updateReg (NewReg);
542
570
543
- // Tell LiveIntervals about the new register.
544
- LIS.createAndComputeVirtRegInterval (NewReg);
571
+ if (LIS != nullptr ) {
572
+ // Tell LiveIntervals about the new register.
573
+ LIS->createAndComputeVirtRegInterval (NewReg);
545
574
546
- // Tell LiveIntervals about the changes to the old register.
547
- LiveInterval &LI = LIS.getInterval (Reg);
548
- LI.removeSegment (LIS.getInstructionIndex (*Def).getRegSlot (),
549
- LIS.getInstructionIndex (*Op.getParent ()).getRegSlot (),
550
- /* RemoveDeadValNo=*/ true );
575
+ // Tell LiveIntervals about the changes to the old register.
576
+ LiveInterval &LI = LIS->getInterval (Reg);
577
+ LI.removeSegment (LIS->getInstructionIndex (*Def).getRegSlot (),
578
+ LIS->getInstructionIndex (*Op.getParent ()).getRegSlot (),
579
+ /* RemoveDeadValNo=*/ true );
580
+ }
551
581
552
582
MFI.stackifyVReg (MRI, NewReg);
553
-
554
583
LLVM_DEBUG (dbgs () << " - Replaced register: " ; Def->dump ());
555
584
}
556
585
@@ -567,11 +596,12 @@ static MachineInstr *getPrevNonDebugInst(MachineInstr *MI) {
567
596
568
597
// / A trivially cloneable instruction; clone it and nest the new copy with the
569
598
// / current instruction.
570
- static MachineInstr *rematerializeCheapDef (
571
- unsigned Reg, MachineOperand &Op, MachineInstr &Def, MachineBasicBlock &MBB,
572
- MachineBasicBlock::instr_iterator Insert, LiveIntervals &LIS,
573
- WebAssemblyFunctionInfo &MFI, MachineRegisterInfo &MRI,
574
- const WebAssemblyInstrInfo *TII, const WebAssemblyRegisterInfo *TRI) {
599
+ static MachineInstr *
600
+ rematerializeCheapDef (unsigned Reg, MachineOperand &Op, MachineInstr &Def,
601
+ MachineBasicBlock::instr_iterator Insert,
602
+ LiveIntervals &LIS, WebAssemblyFunctionInfo &MFI,
603
+ MachineRegisterInfo &MRI,
604
+ const WebAssemblyInstrInfo *TII) {
575
605
LLVM_DEBUG (dbgs () << " Rematerializing cheap def: " ; Def.dump ());
576
606
LLVM_DEBUG (dbgs () << " - for use in " ; Op.getParent ()->dump ());
577
607
@@ -811,9 +841,12 @@ bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) {
811
841
MachineRegisterInfo &MRI = MF.getRegInfo ();
812
842
WebAssemblyFunctionInfo &MFI = *MF.getInfo <WebAssemblyFunctionInfo>();
813
843
const auto *TII = MF.getSubtarget <WebAssemblySubtarget>().getInstrInfo ();
814
- const auto *TRI = MF.getSubtarget <WebAssemblySubtarget>().getRegisterInfo ();
815
- auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree ();
816
- auto &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS ();
844
+ MachineDominatorTree *MDT = nullptr ;
845
+ LiveIntervals *LIS = nullptr ;
846
+ if (Optimize) {
847
+ MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree ();
848
+ LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS ();
849
+ }
817
850
818
851
// Walk the instructions from the bottom up. Currently we don't look past
819
852
// block boundaries, and the blocks aren't ordered so the block visitation
@@ -876,23 +909,28 @@ bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) {
876
909
// supports intra-block moves) and it's MachineSink's job to catch all
877
910
// the sinking opportunities anyway.
878
911
bool SameBlock = DefI->getParent () == &MBB;
879
- bool CanMove = SameBlock && isSafeToMove (Def, &Use, Insert, MFI, MRI) &&
912
+ bool CanMove = SameBlock &&
913
+ isSafeToMove (Def, &Use, Insert, MFI, MRI, Optimize) &&
880
914
!TreeWalker.isOnStack (Reg);
881
- if (CanMove && hasOneNonDBGUse (Reg, DefI, MRI, MDT , LIS)) {
915
+ if (CanMove && hasSingleUse (Reg, MRI, MFI, Optimize, DefI , LIS)) {
882
916
Insert = moveForSingleUse (Reg, Use, DefI, MBB, Insert, LIS, MFI, MRI);
883
917
884
918
// If we are removing the frame base reg completely, remove the debug
885
919
// info as well.
886
920
// TODO: Encode this properly as a stackified value.
887
- if (MFI.isFrameBaseVirtual () && MFI.getFrameBaseVreg () == Reg)
921
+ if (MFI.isFrameBaseVirtual () && MFI.getFrameBaseVreg () == Reg) {
922
+ assert (
923
+ Optimize &&
924
+ " Stackifying away frame base in unoptimized code not expected" );
888
925
MFI.clearFrameBaseVreg ();
889
- } else if (shouldRematerialize (*DefI, TII)) {
890
- Insert =
891
- rematerializeCheapDef (Reg, Use, *DefI, MBB, Insert->getIterator (),
892
- LIS, MFI, MRI, TII, TRI);
893
- } else if (CanMove && oneUseDominatesOtherUses (Reg, Use, MBB, MRI, MDT,
894
- LIS, MFI)) {
895
- Insert = moveAndTeeForMultiUse (Reg, Use, DefI, MBB, Insert, LIS, MFI,
926
+ }
927
+ } else if (Optimize && shouldRematerialize (*DefI, TII)) {
928
+ Insert = rematerializeCheapDef (Reg, Use, *DefI, Insert->getIterator (),
929
+ *LIS, MFI, MRI, TII);
930
+ } else if (Optimize && CanMove &&
931
+ oneUseDominatesOtherUses (Reg, Use, MBB, MRI, *MDT, *LIS,
932
+ MFI)) {
933
+ Insert = moveAndTeeForMultiUse (Reg, Use, DefI, MBB, Insert, *LIS, MFI,
896
934
MRI, TII);
897
935
} else {
898
936
// We failed to stackify the operand. If the problem was ordering
@@ -915,7 +953,8 @@ bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) {
915
953
Register DefReg = SubsequentDef->getReg ();
916
954
Register UseReg = SubsequentUse->getReg ();
917
955
// TODO: This single-use restriction could be relaxed by using tees
918
- if (DefReg != UseReg || !MRI.hasOneNonDBGUse (DefReg))
956
+ if (DefReg != UseReg ||
957
+ !hasSingleUse (DefReg, MRI, MFI, Optimize, nullptr , nullptr ))
919
958
break ;
920
959
MFI.stackifyVReg (MRI, DefReg);
921
960
++SubsequentDef;
@@ -926,7 +965,7 @@ bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) {
926
965
// to a constant 0 so that the def is explicit, and the push/pop
927
966
// correspondence is maintained.
928
967
if (Insert->getOpcode () == TargetOpcode::IMPLICIT_DEF)
929
- convertImplicitDefToConstZero (Insert, MRI, TII, MF, LIS );
968
+ convertImplicitDefToConstZero (Insert, MRI, TII, MF);
930
969
931
970
// We stackified an operand. Add the defining instruction's operands to
932
971
// the worklist stack now to continue to build an ever deeper tree.
0 commit comments