Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp =================================================================== --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -694,8 +694,26 @@ } } +// 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 @@ 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 @@ // 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. Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h =================================================================== --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h @@ -101,6 +101,11 @@ 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()) Index: llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll =================================================================== --- llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll +++ llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll @@ -436,13 +436,17 @@ ; 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 @@ 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 @@ 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 void @__cxa_end_catch() declare void @__clang_call_terminate(i8*) declare void @_ZSt9terminatev() + +attributes #0 = { nounwind }