[llvm] 18ff1ec - Reland [SimplifyCFG] `markAliveBlocks()`: recognize that normal dest of `invoke`d `noreturn` function is `unreachable`

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 4 15:58:38 PST 2022


Author: Roman Lebedev
Date: 2022-02-05T02:58:19+03:00
New Revision: 18ff1ec3c3c63889e476c5495647de41ac2870aa

URL: https://github.com/llvm/llvm-project/commit/18ff1ec3c3c63889e476c5495647de41ac2870aa
DIFF: https://github.com/llvm/llvm-project/commit/18ff1ec3c3c63889e476c5495647de41ac2870aa.diff

LOG: Reland [SimplifyCFG] `markAliveBlocks()`: recognize that normal dest of `invoke`d `noreturn` function is `unreachable`

As per LangRef's definition of `noreturn` attribute:
```
noreturn
  This function attribute indicates that the function never returns
  normally, hence through a return instruction.
  This produces undefined behavior at runtime if the function
  ever does dynamically return. nnotated functions may still
  raise an exception, i.a., nounwind is not implied.
```

So if we `invoke` a `noreturn` function, and the normal destination
of an invoke is not an `unreachable`, point it at the new `unreachable`
block.

The change/fix from the original commit is that we now actually create
the new block, and don't just repurpose the original block,
because said normal destination block could have other users.

This reverts commit db1176ce66cf276b45ac3b90ea6b5ce62de56be7,
relanding commit 598833c987593ce192fa827f162cae8c867c9d43.

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/Local.cpp
    llvm/test/CodeGen/X86/catchret-regmask.ll
    llvm/test/Transforms/SimplifyCFG/invoke.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 9a10535c93101..4326fa8bd3c27 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -2349,19 +2349,42 @@ static bool markAliveBlocks(Function &F,
           isa<UndefValue>(Callee)) {
         changeToUnreachable(II, false, DTU);
         Changed = true;
-      } else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) {
-        if (II->use_empty() && II->onlyReadsMemory()) {
-          // jump to the normal destination branch.
-          BasicBlock *NormalDestBB = II->getNormalDest();
-          BasicBlock *UnwindDestBB = II->getUnwindDest();
-          BranchInst::Create(NormalDestBB, II);
-          UnwindDestBB->removePredecessor(II->getParent());
-          II->eraseFromParent();
+      } else {
+        if (II->doesNotReturn() &&
+            !isa<UnreachableInst>(II->getNormalDest()->front())) {
+          // If we found an invoke of a no-return function,
+          // create a new empty basic block with an `unreachable` terminator,
+          // and set it as the normal destination for the invoke,
+          // unless that is already the case.
+          // Note that the original normal destination could have other uses.
+          BasicBlock *OrigNormalDest = II->getNormalDest();
+          OrigNormalDest->removePredecessor(II->getParent());
+          LLVMContext &Ctx = II->getContext();
+          BasicBlock *UnreachableNormalDest = BasicBlock::Create(
+              Ctx, OrigNormalDest->getName() + ".unreachable",
+              II->getFunction(), OrigNormalDest);
+          new UnreachableInst(Ctx, UnreachableNormalDest);
+          II->setNormalDest(UnreachableNormalDest);
           if (DTU)
-            DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDestBB}});
-        } else
-          changeToCall(II, DTU);
-        Changed = true;
+            DTU->applyUpdates(
+                {{DominatorTree::Delete, BB, OrigNormalDest},
+                 {DominatorTree::Insert, BB, UnreachableNormalDest}});
+          Changed = true;
+        }
+        if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) {
+          if (II->use_empty() && II->onlyReadsMemory()) {
+            // jump to the normal destination branch.
+            BasicBlock *NormalDestBB = II->getNormalDest();
+            BasicBlock *UnwindDestBB = II->getUnwindDest();
+            BranchInst::Create(NormalDestBB, II);
+            UnwindDestBB->removePredecessor(II->getParent());
+            II->eraseFromParent();
+            if (DTU)
+              DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDestBB}});
+          } else
+            changeToCall(II, DTU);
+          Changed = true;
+        }
       }
     } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(Terminator)) {
       // Remove catchpads which cannot be reached.

diff  --git a/llvm/test/CodeGen/X86/catchret-regmask.ll b/llvm/test/CodeGen/X86/catchret-regmask.ll
index 4af57e109f183..20212a2bf032d 100644
--- a/llvm/test/CodeGen/X86/catchret-regmask.ll
+++ b/llvm/test/CodeGen/X86/catchret-regmask.ll
@@ -4,7 +4,7 @@ target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-pc-windows-msvc"
 
 declare i32 @__CxxFrameHandler3(...)
-declare void @throw() noreturn uwtable
+declare void @throw() uwtable
 declare i8* @getval()
 declare void @llvm.trap()
 

diff  --git a/llvm/test/Transforms/SimplifyCFG/invoke.ll b/llvm/test/Transforms/SimplifyCFG/invoke.ll
index 7e713bb531d8d..e3bee6f8ac432 100644
--- a/llvm/test/Transforms/SimplifyCFG/invoke.ll
+++ b/llvm/test/Transforms/SimplifyCFG/invoke.ll
@@ -196,10 +196,9 @@ define void @invoke_of_noreturn() personality i8* bitcast (i32 (...)* @__gxx_per
 ; CHECK-LABEL: @invoke_of_noreturn(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    invoke void @simple_throw()
-; CHECK-NEXT:    to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
-; CHECK:       invoke.cont:
-; CHECK-NEXT:    call void @sideeffect(i32 0)
-; CHECK-NEXT:    ret void
+; CHECK-NEXT:    to label [[INVOKE_CONT_UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
+; CHECK:       invoke.cont.unreachable:
+; CHECK-NEXT:    unreachable
 ; CHECK:       lpad:
 ; CHECK-NEXT:    [[EH:%.*]] = landingpad { i8*, i32 }
 ; CHECK-NEXT:    cleanup
@@ -225,10 +224,11 @@ define void @invoke_of_noreturn_with_shared_normal_destination(i1 %c) personalit
 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[INVOKE:%.*]], label [[INVOKE_CONT:%.*]]
 ; CHECK:       invoke:
 ; CHECK-NEXT:    invoke void @simple_throw()
-; CHECK-NEXT:    to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+; CHECK-NEXT:    to label [[INVOKE_CONT_UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
+; CHECK:       invoke.cont.unreachable:
+; CHECK-NEXT:    unreachable
 ; CHECK:       invoke.cont:
-; CHECK-NEXT:    [[R:%.*]] = phi i32 [ 0, [[INVOKE]] ], [ -1, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    call void @sideeffect(i32 [[R]])
+; CHECK-NEXT:    call void @sideeffect(i32 -1)
 ; CHECK-NEXT:    ret void
 ; CHECK:       lpad:
 ; CHECK-NEXT:    [[EH:%.*]] = landingpad { i8*, i32 }


        


More information about the llvm-commits mailing list