@@ -64,6 +64,7 @@ class WebAssemblyCFGStackify final : public MachineFunctionPass {
64
64
void placeBlockMarker (MachineBasicBlock &MBB);
65
65
void placeLoopMarker (MachineBasicBlock &MBB);
66
66
void placeTryMarker (MachineBasicBlock &MBB);
67
+ void removeUnnecessaryInstrs (MachineFunction &MF);
67
68
void rewriteDepthImmediates (MachineFunction &MF);
68
69
void fixEndsAtEndOfFunction (MachineFunction &MF);
69
70
@@ -76,11 +77,12 @@ class WebAssemblyCFGStackify final : public MachineFunctionPass {
76
77
// <EH pad, TRY marker> map
77
78
DenseMap<const MachineBasicBlock *, MachineInstr *> EHPadToTry;
78
79
79
- // Helper functions to register scope information created by marker
80
- // instructions.
80
+ // Helper functions to register / unregister scope information created by
81
+ // marker instructions.
81
82
void registerScope (MachineInstr *Begin, MachineInstr *End);
82
83
void registerTryScope (MachineInstr *Begin, MachineInstr *End,
83
84
MachineBasicBlock *EHPad);
85
+ void unregisterScope (MachineInstr *Begin);
84
86
85
87
public:
86
88
static char ID; // Pass identification, replacement for typeid
@@ -175,6 +177,20 @@ void WebAssemblyCFGStackify::registerTryScope(MachineInstr *Begin,
175
177
EHPadToTry[EHPad] = Begin;
176
178
}
177
179
180
+ void WebAssemblyCFGStackify::unregisterScope (MachineInstr *Begin) {
181
+ assert (BeginToEnd.count (Begin));
182
+ MachineInstr *End = BeginToEnd[Begin];
183
+ assert (EndToBegin.count (End));
184
+ BeginToEnd.erase (Begin);
185
+ EndToBegin.erase (End);
186
+ MachineBasicBlock *EHPad = TryToEHPad.lookup (Begin);
187
+ if (EHPad) {
188
+ assert (EHPadToTry.count (EHPad));
189
+ TryToEHPad.erase (Begin);
190
+ EHPadToTry.erase (EHPad);
191
+ }
192
+ }
193
+
178
194
// / Insert a BLOCK marker for branches to MBB (if needed).
179
195
void WebAssemblyCFGStackify::placeBlockMarker (MachineBasicBlock &MBB) {
180
196
// This should have been handled in placeTryMarker.
@@ -585,6 +601,76 @@ void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) {
585
601
ScopeTops[Number] = Header;
586
602
}
587
603
604
+ void WebAssemblyCFGStackify::removeUnnecessaryInstrs (MachineFunction &MF) {
605
+ const auto &TII = *MF.getSubtarget <WebAssemblySubtarget>().getInstrInfo ();
606
+
607
+ // When there is an unconditional branch right before a catch instruction and
608
+ // it branches to the end of end_try marker, we don't need the branch, because
609
+ // it there is no exception, the control flow transfers to that point anyway.
610
+ // bb0:
611
+ // try
612
+ // ...
613
+ // br bb2 <- Not necessary
614
+ // bb1:
615
+ // catch
616
+ // ...
617
+ // bb2:
618
+ // end
619
+ for (auto &MBB : MF) {
620
+ if (!MBB.isEHPad ())
621
+ continue ;
622
+
623
+ MachineBasicBlock *TBB = nullptr , *FBB = nullptr ;
624
+ SmallVector<MachineOperand, 4 > Cond;
625
+ MachineBasicBlock *EHPadLayoutPred =
626
+ &*std::prev (MachineFunction::iterator (&MBB));
627
+ MachineBasicBlock *Cont = BeginToEnd[EHPadToTry[&MBB]]->getParent ();
628
+ bool Analyzable = !TII.analyzeBranch (*EHPadLayoutPred, TBB, FBB, Cond);
629
+ if (Analyzable && ((Cond.empty () && TBB && TBB == Cont) ||
630
+ (!Cond.empty () && FBB && FBB == Cont)))
631
+ TII.removeBranch (*EHPadLayoutPred);
632
+ }
633
+
634
+ // When there are block / end_block markers that overlap with try / end_try
635
+ // markers, and the block and try markers' return types are the same, the
636
+ // block /end_block markers are not necessary, because try / end_try markers
637
+ // also can serve as boundaries for branches.
638
+ // block <- Not necessary
639
+ // try
640
+ // ...
641
+ // catch
642
+ // ...
643
+ // end
644
+ // end <- Not necessary
645
+ SmallVector<MachineInstr *, 32 > ToDelete;
646
+ for (auto &MBB : MF) {
647
+ for (auto &MI : MBB) {
648
+ if (MI.getOpcode () != WebAssembly::TRY)
649
+ continue ;
650
+
651
+ MachineInstr *Try = &MI, *EndTry = BeginToEnd[Try];
652
+ MachineBasicBlock *TryBB = Try->getParent ();
653
+ MachineBasicBlock *Cont = EndTry->getParent ();
654
+ int64_t RetType = Try->getOperand (0 ).getImm ();
655
+ for (auto B = MachineBasicBlock::iterator (Try),
656
+ E = std::next (MachineBasicBlock::iterator (EndTry));
657
+ B != TryBB->begin () && E != Cont->end () &&
658
+ std::prev (B)->getOpcode () == WebAssembly::BLOCK &&
659
+ E->getOpcode () == WebAssembly::END_BLOCK &&
660
+ std::prev (B)->getOperand (0 ).getImm () == RetType;
661
+ --B, ++E) {
662
+ ToDelete.push_back (&*std::prev (B));
663
+ ToDelete.push_back (&*E);
664
+ }
665
+ }
666
+ }
667
+ for (auto *MI : ToDelete) {
668
+ if (MI->getOpcode () == WebAssembly::BLOCK)
669
+ unregisterScope (MI);
670
+ MI->eraseFromParent ();
671
+ }
672
+ }
673
+
588
674
static unsigned
589
675
getDepth (const SmallVectorImpl<const MachineBasicBlock *> &Stack,
590
676
const MachineBasicBlock *MBB) {
@@ -747,6 +833,7 @@ bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
747
833
LLVM_DEBUG (dbgs () << " ********** CFG Stackifying **********\n "
748
834
" ********** Function: "
749
835
<< MF.getName () << ' \n ' );
836
+ const MCAsmInfo *MCAI = MF.getTarget ().getMCAsmInfo ();
750
837
751
838
releaseMemory ();
752
839
@@ -756,6 +843,11 @@ bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
756
843
// Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes.
757
844
placeMarkers (MF);
758
845
846
+ if (MCAI->getExceptionHandlingType () == ExceptionHandling::Wasm &&
847
+ MF.getFunction ().hasPersonalityFn ())
848
+ // Remove unnecessary instructions.
849
+ removeUnnecessaryInstrs (MF);
850
+
759
851
// Convert MBB operands in terminators to relative depth immediates.
760
852
rewriteDepthImmediates (MF);
761
853
0 commit comments