From 61d5c76a181360ca8f039b2f6c914a18540684b5 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Tue, 1 Oct 2019 06:21:53 +0000 Subject: [PATCH] [WebAssembly] Unstackify regs after fixing unwinding mismatches Summary: Fixing unwind mismatches for exception handling can result in splicing existing BBs and moving some of instructions to new BBs. In this case some of stackified def registers in the original BB can be used in the split BB. For example, we have this BB and suppose %r0 is a stackified register. ``` bb.1: %r0 = call @foo ... use %r0 ... ``` After fixing unwind mismatches in CFGStackify, `bb.1` can be split and some instructions can be moved to a newly created BB: ``` bb.1: %r0 = call @foo bb.split (new): ... use %r0 ... ``` In this case we should make %r0 un-stackified, because its use is now in another BB. When spliting a BB, this CL unstackifies all def registers that have uses in the new split BB. Reviewers: dschuff Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D68218 llvm-svn: 373301 --- .../Target/WebAssembly/WebAssemblyCFGStackify.cpp | 20 ++++++++++++++++++++ .../WebAssembly/WebAssemblyMachineFunctionInfo.h | 5 +++++ llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll | 14 ++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index 6c38dea..6b20946 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -694,8 +694,26 @@ void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) { } } +// When MBB is split into MBB and Split, we should unstackify defs in MBB that +// have their uses in Split. +static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, + MachineBasicBlock &Split, + WebAssemblyFunctionInfo &MFI, + MachineRegisterInfo &MRI) { + for (auto &MI : Split) { + for (auto &MO : MI.explicit_uses()) { + if (!MO.isReg() || Register::isPhysicalRegister(MO.getReg())) + continue; + if (MachineInstr *Def = MRI.getUniqueVRegDef(MO.getReg())) + if (Def->getParent() == &MBB) + MFI.unstackifyVReg(MO.getReg()); + } + } +} + bool WebAssemblyCFGStackify::fixUnwindMismatches(MachineFunction &MF) { const auto &TII = *MF.getSubtarget().getInstrInfo(); + auto &MFI = *MF.getInfo(); MachineRegisterInfo &MRI = MF.getRegInfo(); // Linearizing the control flow by placing TRY / END_TRY markers can create @@ -1007,6 +1025,7 @@ bool WebAssemblyCFGStackify::fixUnwindMismatches(MachineFunction &MF) { BrDest->insert(BrDest->end(), EndTry->removeFromParent()); // Take out the handler body from EH pad to the new branch destination BB. BrDest->splice(BrDest->end(), EHPad, SplitPos, EHPad->end()); + unstackifyVRegsUsedInSplitBB(*EHPad, *BrDest, MFI, MRI); // Fix predecessor-successor relationship. BrDest->transferSuccessors(EHPad); EHPad->addSuccessor(BrDest); @@ -1122,6 +1141,7 @@ bool WebAssemblyCFGStackify::fixUnwindMismatches(MachineFunction &MF) { // new nested continuation BB. NestedCont->splice(NestedCont->end(), MBB, std::next(RangeEnd->getIterator()), MBB->end()); + unstackifyVRegsUsedInSplitBB(*MBB, *NestedCont, MFI, MRI); registerTryScope(NestedTry, NestedEndTry, NestedEHPad); // Fix predecessor-successor relationship. diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h index 91e5055..16e2f43 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h @@ -101,6 +101,11 @@ public: VRegStackified.resize(I + 1); VRegStackified.set(I); } + void unstackifyVReg(unsigned VReg) { + auto I = Register::virtReg2Index(VReg); + if (I < VRegStackified.size()) + VRegStackified.reset(I); + } bool isVRegStackified(unsigned VReg) const { auto I = Register::virtReg2Index(VReg); if (I >= VRegStackified.size()) diff --git a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll index 9cb5a05..104e324 100644 --- a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll +++ b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll @@ -436,13 +436,17 @@ try.cont: ; preds = %catch.start1, %catc ; the right destination (label4), from which we rethrow the exception to the ; caller. +; And the return value of 'baz' should NOT be stackified because the BB is split +; during fixing unwind mismatches. + ; NOSORT-LABEL: test6 ; NOSORT: try ; NOSORT: call foo ; --- Nested try/catch/end_try starts ; NOSORT: try ; NOSORT: call bar -; NOSORT: call bar +; NOSORT: i32.call ${{[0-9]+}}=, baz +; NOSORT-NOT: i32.call $push{{.*}}=, baz ; NOSORT: catch $[[REG:[0-9]+]]= ; NOSORT: br 1 # 1: down to label35 ; NOSORT: end_try @@ -460,7 +464,8 @@ bb0: bb1: ; preds = %bb0 call void @bar() - call void @bar() + %call = call i32 @baz() + call void @nothrow(i32 %call) #0 ret void catch.dispatch0: ; preds = %bb0 @@ -618,6 +623,9 @@ try.cont: ; preds = %catch.start1, %catc declare void @foo() declare void @bar() +declare i32 @baz() +; Function Attrs: nounwind +declare void @nothrow(i32) #0 declare i32 @__gxx_wasm_personality_v0(...) declare i8* @llvm.wasm.get.exception(token) declare i32 @llvm.wasm.get.ehselector(token) @@ -627,3 +635,5 @@ declare i8* @__cxa_begin_catch(i8*) declare void @__cxa_end_catch() declare void @__clang_call_terminate(i8*) declare void @_ZSt9terminatev() + +attributes #0 = { nounwind } -- 2.7.4