From c83d754ae2b43bd61b741f319d7fd343ec1c0a07 Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Tue, 20 Mar 2018 02:44:40 +0000 Subject: [PATCH] [ShrinkWrap] Take into account landing pad When scanning the function for CSRs uses and defs, also check if the basic block are landing pads. Consider that landing pads needs the CSRs to be properly set. That way we force the prologue/epilogue to always be pushed out of the problematic "throw" region. The "throw" region is problematic because the jumps are not properly modeled. Fixes PR36513 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@327942 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/ShrinkWrap.cpp | 16 +++++ test/CodeGen/X86/x86-shrink-wrap-unwind.ll | 102 +++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/lib/CodeGen/ShrinkWrap.cpp b/lib/CodeGen/ShrinkWrap.cpp index 85117775bd6..2d854d6b43f 100644 --- a/lib/CodeGen/ShrinkWrap.cpp +++ b/lib/CodeGen/ShrinkWrap.cpp @@ -447,6 +447,22 @@ bool ShrinkWrap::runOnMachineFunction(MachineFunction &MF) { return false; } + if (MBB.isEHPad()) { + // Push the prologue and epilogue outside of + // the region that may throw by making sure + // that all the landing pads are at least at the + // boundary of the save and restore points. + // The problem with exceptions is that the throw + // is not properly modeled and in particular, a + // basic block can jump out from the middle. + updateSaveRestorePoints(MBB, RS.get()); + if (!ArePointsInteresting()) { + DEBUG(dbgs() << "EHPad prevents shrink-wrapping\n"); + return false; + } + continue; + } + for (const MachineInstr &MI : MBB) { if (!useOrDefCSROrFI(MI, RS.get())) continue; diff --git a/test/CodeGen/X86/x86-shrink-wrap-unwind.ll b/test/CodeGen/X86/x86-shrink-wrap-unwind.ll index 579f847914a..bac8393b3ec 100644 --- a/test/CodeGen/X86/x86-shrink-wrap-unwind.ll +++ b/test/CodeGen/X86/x86-shrink-wrap-unwind.ll @@ -222,3 +222,105 @@ __go_ptr_strings_equal.exit: ; preds = %land.rhs.i.i, %if.e declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) #5 attributes #5 = { nounwind readonly ssp uwtable "split-stack" } + +; Check that correctly take into account the jumps to landing pad. +; We used to consider function that may throw like regular +; function calls. +; Therefore, in this example, we were happily inserting the epilogue +; right after the call to throw_exception. Because of that we would not +; execute the epilogue when an execption occur and bad things will +; happen. +; PR36513 +; +; CHECK-LABEL: with_nounwind: +; Prologue +; CHECK: push +; +; Jump to throw_exception: +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: jne [[THROW_LABEL:LBB[0-9_]+]] +; Else return exit +; CHECK: popq +; CHECK-NEXT: retq +; +; CHECK-NEXT: [[THROW_LABEL]]: +; CHECK: callq _throw_exception +; Unreachable block... +; +; Epilogue must be after the landing pad. +; CHECK-NOT: popq +; +; Look for the landing pad label. +; CHECK: LBB{{[0-9_]+}}: +; Epilogue on the landing pad +; CHECK: popq +; CHECK-NEXT: retq +define void @with_nounwind(i1 %cond) nounwind personality i32 (...)* @my_personality { +entry: + br i1 %cond, label %throw, label %return + +throw: + invoke void @throw_exception() + to label %unreachable unwind label %landing + +unreachable: + unreachable + +landing: + %pad = landingpad { i8*, i32 } + catch i8* null + ret void + +return: + ret void +} + +; Check landing pad again. +; This time checks that we can shrink-wrap when the epilogue does not +; span accross several blocks. +; +; CHECK-LABEL: with_nounwind_same_succ: +; +; Jump to throw_exception: +; CHECK: testb $1, %dil +; CHECK-NEXT: je [[RET_LABEL:LBB[0-9_]+]] +; +; Prologue +; CHECK: push +; CHECK: callq _throw_exception +; +; Fallthrough label +; CHECK: [[FALLTHROUGH_LABEL:LBB[0-9_]+]] +; CHECK: nop +; CHECK: popq +; +; CHECK: [[RET_LABEL]] +; CHECK: retq +; +; Look for the landing pad label. +; CHECK: LBB{{[0-9_]+}}: +; Landing pad jumps to fallthrough +; CHECK: jmp [[FALLTHROUGH_LABEL]] +define void @with_nounwind_same_succ(i1 %cond) nounwind personality i32 (...)* @my_personality2 { +entry: + br i1 %cond, label %throw, label %return + +throw: + invoke void @throw_exception() + to label %fallthrough unwind label %landing +landing: + %pad = landingpad { i8*, i32 } + catch i8* null + br label %fallthrough + +fallthrough: + tail call void asm "nop", ""() + br label %return + +return: + ret void +} + +declare void @throw_exception() +declare i32 @my_personality(...) +declare i32 @my_personality2(...) -- 2.11.0