[llvm-reduce] Do not crash when accessing landingpads of invokes.
authorFlorian Hahn <flo@fhahn.com>
Fri, 18 Nov 2022 15:19:50 +0000 (15:19 +0000)
committerFlorian Hahn <flo@fhahn.com>
Fri, 18 Nov 2022 15:19:50 +0000 (15:19 +0000)
Unconditionally removing landing pads results in invalid IR,
if there is a different `invoke` that uses it. Update the code
to only remove the landing pad if the current invoke is the only
user. Also carefully avoid creating plain branches to bbs with
landing pads we couldn't remove.

Reviewed By: arsenm, aeubanks

Differential Revision: https://reviews.llvm.org/D138072

llvm/test/tools/llvm-reduce/invoke-with-missing-landingpad.ll [new file with mode: 0644]
llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp

diff --git a/llvm/test/tools/llvm-reduce/invoke-with-missing-landingpad.ll b/llvm/test/tools/llvm-reduce/invoke-with-missing-landingpad.ll
new file mode 100644 (file)
index 0000000..6c306c1
--- /dev/null
@@ -0,0 +1,37 @@
+; RUN: llvm-reduce --delta-passes=basic-blocks --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s  -abort-on-invalid-reduction -o %t
+; RUN: FileCheck <%t %s
+
+; CHECK-INTERESTINGNESS: call void @foo()
+
+; CHECK: define void @test() personality ptr null {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   br label %cont
+; CHECK-EMPTY:
+; CHECK-NEXT: cont:
+; CHECK-NEXT:   br label %exit
+; CHECK-EMPTY:
+; CHECK-NEXT: exit:
+; CHECK-NEXT:   call void @foo()
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+
+define void @test() personality ptr null {
+entry:
+  invoke void @foo()
+          to label %cont unwind label %lpad
+
+cont:
+  invoke void @foo()
+          to label %exit unwind label %lpad
+
+lpad:
+  %0 = landingpad { ptr, i32 }
+          cleanup
+  ret void
+
+exit:
+  call void @foo()
+  ret void
+}
+
+declare void @foo()
index bc7a23d..cb518a9 100644 (file)
@@ -48,8 +48,20 @@ static void replaceBranchTerminator(BasicBlock &BB,
   bool IsBranch = isa<BranchInst>(Term);
   if (InvokeInst *Invoke = dyn_cast<InvokeInst>(Term)) {
     LandingPadInst *LP = Invoke->getLandingPadInst();
-    LP->replaceAllUsesWith(getDefaultValue(LP->getType()));
-    LP->eraseFromParent();
+    // Remove landingpad instruction if the containing block isn't used by other
+    // invokes.
+    if (none_of(LP->getParent()->users(), [Invoke](User *U) {
+          return U != Invoke && isa<InvokeInst>(U);
+        })) {
+      LP->replaceAllUsesWith(getDefaultValue(LP->getType()));
+      LP->eraseFromParent();
+    } else if (!ChunkSuccessors.empty() &&
+               ChunkSuccessors[0] == LP->getParent()) {
+      // If the selected successor is the landing pad, clear the chunk
+      // successors to avoid creating a regular branch to the landing pad which
+      // would result in invalid IR.
+      ChunkSuccessors.clear();
+    }
     IsBranch = true;
   }