[llvm] [InstCombine] Fix crash on dereferencing null insertion point (PR #216363)

Hendrik Hübner via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 15 03:08:55 PDT 2026


https://github.com/HendrikHuebner updated https://github.com/llvm/llvm-project/pull/216363

>From 050f0025725712f7cc5f4bf38aba1b51809312b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hendrik=20H=C3=BCbner?= <hhuebner at hhuebnerMacBookPro.local>
Date: Fri, 14 Aug 2026 18:49:56 +0200
Subject: [PATCH 1/4] [InstCombine] Assert on missing inversion insertion point

---
 .../Transforms/InstCombine/InstCombineAndOrXor.cpp  | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b6f4a55c07e8a..7757ce2e2c389 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -4996,14 +4996,18 @@ static Instruction *canonicalizeAbs(BinaryOperator &Xor,
 static bool canFreelyInvert(InstCombiner &IC, Value *Op,
                             Instruction *IgnoredUser) {
   auto *I = dyn_cast<Instruction>(Op);
-  return I && IC.isFreeToInvert(I, /*WillInvertAllUses=*/true) &&
+  return I && I->getInsertionPointAfterDef() &&
+         IC.isFreeToInvert(I, /*WillInvertAllUses=*/true) &&
          IC.canFreelyInvertAllUsersOf(I, IgnoredUser);
 }
 
 static Value *freelyInvert(InstCombinerImpl &IC, Value *Op,
                            Instruction *IgnoredUser) {
   auto *I = cast<Instruction>(Op);
-  IC.Builder.SetInsertPoint(*I->getInsertionPointAfterDef());
+  auto InsertPt = I->getInsertionPointAfterDef();
+  assert(InsertPt &&
+         "freelyInvert requires an instruction with a valid insertion point");
+  IC.Builder.SetInsertPoint(*InsertPt);
   Value *NotOp = IC.Builder.CreateNot(Op, Op->getName() + ".not");
   Op->replaceUsesWithIf(NotOp,
                         [NotOp](Use &U) { return U.getUser() != NotOp; });
@@ -5047,7 +5051,10 @@ bool InstCombinerImpl::sinkNotIntoLogicalOp(Instruction &I) {
   Op0 = freelyInvert(*this, Op0, &I);
   Op1 = freelyInvert(*this, Op1, &I);
 
-  Builder.SetInsertPoint(*I.getInsertionPointAfterDef());
+  auto InsertPt = I.getInsertionPointAfterDef();
+  assert(InsertPt &&
+         "sinkNotIntoLogicalOp requires an instruction with a valid insertion point");
+  Builder.SetInsertPoint(*InsertPt);
   Value *NewLogicOp;
   if (IsBinaryOp) {
     NewLogicOp = Builder.CreateBinOp(NewOpc, Op0, Op1, I.getName() + ".not");

>From d1c5bb99e3db6e6227a7424b77b88a4fa4d30576 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hendrik=20H=C3=BCbner?= <hhuebner at hhuebnerMacBookPro.local>
Date: Fri, 14 Aug 2026 19:34:03 +0200
Subject: [PATCH 2/4] fmt and test

---
 .../InstCombine/InstCombineAndOrXor.cpp       |  4 ++--
 .../Transforms/InstCombine/free-inversion.ll  | 24 +++++++++++++++++++
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 7757ce2e2c389..b9352b32a4c7b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -5052,8 +5052,8 @@ bool InstCombinerImpl::sinkNotIntoLogicalOp(Instruction &I) {
   Op1 = freelyInvert(*this, Op1, &I);
 
   auto InsertPt = I.getInsertionPointAfterDef();
-  assert(InsertPt &&
-         "sinkNotIntoLogicalOp requires an instruction with a valid insertion point");
+  assert(InsertPt && "sinkNotIntoLogicalOp requires an instruction with a "
+		     "valid insertion point");
   Builder.SetInsertPoint(*InsertPt);
   Value *NewLogicOp;
   if (IsBinaryOp) {
diff --git a/llvm/test/Transforms/InstCombine/free-inversion.ll b/llvm/test/Transforms/InstCombine/free-inversion.ll
index 2e8e75c3ab3ef..ea1b27ff9efdd 100644
--- a/llvm/test/Transforms/InstCombine/free-inversion.ll
+++ b/llvm/test/Transforms/InstCombine/free-inversion.ll
@@ -760,3 +760,27 @@ define i64 @PR71390(i64 %v) {
   %not5 = xor i64 %and4, -1
   ret i64 %not5
 }
+
+define i1 @freely_invert_catchswitch(i8 %x) personality ptr null {
+; CHECK-LABEL: @freely_invert_catchswitch(
+; CHECK:       d:
+; CHECK-NEXT:    [[NOTP:%.*]] = phi i1 [ false, [[N:%.*]] ], [ true, [[E:%.*]] ]
+; CHECK-NEXT:    [[S:%.*]] = catchswitch within none [label %c] unwind to caller
+;
+e:
+  invoke void @use.i1(i1 true) to label %n unwind label %d
+n:
+  invoke void @use.i1(i1 true) to label %ret unwind label %d
+ret:
+  ret i1 false
+d:
+  %p = phi i1 [ true, %n ], [ false, %e ]
+  %s = catchswitch within none [label %c] unwind to caller
+c:
+  catchpad within %s [ptr null]
+  %z = icmp eq i8 %x, 0
+  %y = select i1 %p, i1 %z, i1 false
+  %w = xor i1 %y, true
+  call void @llvm.assume(i1 %w)
+  ret i1 false
+}

>From 83f059ebdb98c83a7f617e32111b2cf6529fcf97 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hendrik=20H=C3=BCbner?= <hhuebner at hhuebnerMacBookPro.local>
Date: Fri, 14 Aug 2026 19:46:50 +0200
Subject: [PATCH 3/4] fmt

---
 llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b9352b32a4c7b..7bc0d7d2f11b8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -5053,7 +5053,7 @@ bool InstCombinerImpl::sinkNotIntoLogicalOp(Instruction &I) {
 
   auto InsertPt = I.getInsertionPointAfterDef();
   assert(InsertPt && "sinkNotIntoLogicalOp requires an instruction with a "
-		     "valid insertion point");
+                     "valid insertion point");
   Builder.SetInsertPoint(*InsertPt);
   Value *NewLogicOp;
   if (IsBinaryOp) {

>From f4c8a1c3308c9393d37ec479f0e42038c37878b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hendrik=20H=C3=BCbner?= <hhuebner at hhuebnerMacBookPro.local>
Date: Sat, 15 Aug 2026 12:08:42 +0200
Subject: [PATCH 4/4] new assertions

---
 .../Transforms/InstCombine/free-inversion.ll   | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/free-inversion.ll b/llvm/test/Transforms/InstCombine/free-inversion.ll
index ea1b27ff9efdd..8e4aa73e436ec 100644
--- a/llvm/test/Transforms/InstCombine/free-inversion.ll
+++ b/llvm/test/Transforms/InstCombine/free-inversion.ll
@@ -763,9 +763,23 @@ define i64 @PR71390(i64 %v) {
 
 define i1 @freely_invert_catchswitch(i8 %x) personality ptr null {
 ; CHECK-LABEL: @freely_invert_catchswitch(
+; CHECK-NEXT:  e:
+; CHECK-NEXT:    invoke void @use.i1(i1 true)
+; CHECK-NEXT:            to label [[N:%.*]] unwind label [[D:%.*]]
+; CHECK:       n:
+; CHECK-NEXT:    invoke void @use.i1(i1 true)
+; CHECK-NEXT:            to label [[RET:%.*]] unwind label [[D]]
+; CHECK:       ret:
+; CHECK-NEXT:    ret i1 false
 ; CHECK:       d:
-; CHECK-NEXT:    [[NOTP:%.*]] = phi i1 [ false, [[N:%.*]] ], [ true, [[E:%.*]] ]
-; CHECK-NEXT:    [[S:%.*]] = catchswitch within none [label %c] unwind to caller
+; CHECK-NEXT:    [[NOTP:%.*]] = phi i1 [ false, [[N]] ], [ true, [[E:%.*]] ]
+; CHECK-NEXT:    [[S:%.*]] = catchswitch within none [label [[C:%.*]]] unwind to caller
+; CHECK:       c:
+; CHECK-NEXT:    [[TMP0:%.*]] = catchpad within [[S]] [ptr null]
+; CHECK-NEXT:    [[Z:%.*]] = icmp ne i8 [[X:%.*]], 0
+; CHECK-NEXT:    [[Y:%.*]] = select i1 [[NOTP]], i1 true, i1 [[Z]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[Y]])
+; CHECK-NEXT:    ret i1 false
 ;
 e:
   invoke void @use.i1(i1 true) to label %n unwind label %d



More information about the llvm-commits mailing list