[llvm] [InstCombine] fix assertion failure in intrinsic distributive laws (PR #216483)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 15 10:11:58 PDT 2026
https://github.com/im-lunex updated https://github.com/llvm/llvm-project/pull/216483
>From bb78d0e2214c27df844d87c833967ce326a8c2b9 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Sat, 15 Aug 2026 17:18:50 +0600
Subject: [PATCH 1/3] fix assertion failure in intrinsic distributive laws
---
.../InstCombine/InstCombineCalls.cpp | 16 ++++++++--------
.../intrinsic-distributive-laws-crash.ll | 19 +++++++++++++++++++
2 files changed, 27 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 7fee08ad21d28..9d23008131c3b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1853,24 +1853,24 @@ foldIntrinsicUsingDistributiveLaws(IntrinsicInst *II,
return nullptr;
}
- BinaryOperator *NewBinop;
+ Value *NewBinop; // dont decide BinaryOperator now
if (A == C &&
leftDistributesOverRight(InnerOpcode, HasNUW, HasNSW, TopLevelOpcode)) {
Value *NewIntrinsic = Builder.CreateBinaryIntrinsic(TopLevelOpcode, B, D);
- NewBinop =
- cast<BinaryOperator>(Builder.CreateBinOp(InnerOpcode, A, NewIntrinsic));
+ NewBinop = Builder.CreateBinOp(InnerOpcode, A, NewIntrinsic);
} else if (B == D && rightDistributesOverLeft(InnerOpcode, HasNUW, HasNSW,
TopLevelOpcode)) {
Value *NewIntrinsic = Builder.CreateBinaryIntrinsic(TopLevelOpcode, A, C);
- NewBinop =
- cast<BinaryOperator>(Builder.CreateBinOp(InnerOpcode, NewIntrinsic, B));
+ NewBinop = Builder.CreateBinOp(InnerOpcode, NewIntrinsic, B);
} else {
return nullptr;
}
- NewBinop->setHasNoUnsignedWrap(HasNUW);
- NewBinop->setHasNoSignedWrap(HasNSW);
-
+ // check if NewBinop is actually a BinaryOperator
+ if (BinaryOperator *NBO = dyn_cast<BinaryOperator>(NewBinop)) {
+ NBO->setHasNoUnsignedWrap(HasNUW);
+ NBO->setHasNoSignedWrap(HasNSW);
+ }
return NewBinop;
}
diff --git a/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll b/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll
new file mode 100644
index 0000000000000..8f9a097825da7
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=instcombine %s | FileCheck %s
+
+declare i32 @llvm.smin.i32(i32, i32)
+
+define i32 @test_intrinsic_distributive_laws_crash(i32 %g, i32 %h, i32 %i) {
+; CHECK-LABEL: @test_intrinsic_distributive_laws_crash(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[G:%.*]], [[H:%.*]]
+; CHECK-NEXT: [[INNER_MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[G]], i32 [[I:%.*]])
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i32 0, i32 [[INNER_MIN]]
+; CHECK-NEXT: ret i32 [[RESULT]]
+;
+entry:
+ %cmp1 = icmp slt i32 %g, %h
+ %inner_min = call i32 @llvm.smin.i32(i32 %g, i32 %i)
+ %result = select i1 %cmp1, i32 0, i32 %inner_min
+ ret i32 %result
+}
>From b93ba051c27fdcaa4ba92bcc8bcb0ec9f60da0b5 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Sat, 15 Aug 2026 17:47:27 +0600
Subject: [PATCH 2/3] improve the test
---
.../intrinsic-distributive-laws-crash.ll | 23 +++++++++----------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll b/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll
index 8f9a097825da7..b69f6842b06e8 100644
--- a/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll
+++ b/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll
@@ -1,19 +1,18 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=instcombine %s | FileCheck %s
+ at g = global i32 0
+
declare i32 @llvm.smin.i32(i32, i32)
-define i32 @test_intrinsic_distributive_laws_crash(i32 %g, i32 %h, i32 %i) {
-; CHECK-LABEL: @test_intrinsic_distributive_laws_crash(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[G:%.*]], [[H:%.*]]
-; CHECK-NEXT: [[INNER_MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[G]], i32 [[I:%.*]])
-; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i32 0, i32 [[INNER_MIN]]
-; CHECK-NEXT: ret i32 [[RESULT]]
+define i32 @test_constexpr_distributive_crash() {
+; CHECK-LABEL: @test_constexpr_distributive_crash(
+; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.smin.i32(i32 add (i32 ptrtoint (ptr @g to i32), i32 10), i32 add (i32 ptrtoint (ptr @g to i32), i32 20))
+; CHECK-NEXT: ret i32 [[RES]]
;
-entry:
- %cmp1 = icmp slt i32 %g, %h
- %inner_min = call i32 @llvm.smin.i32(i32 %g, i32 %i)
- %result = select i1 %cmp1, i32 0, i32 %inner_min
- ret i32 %result
+ %res = call i32 @llvm.smin.i32(
+ i32 add nsw (i32 ptrtoint (ptr @g to i32), i32 10),
+ i32 add nsw (i32 ptrtoint (ptr @g to i32), i32 20)
+ )
+ ret i32 %res
}
>From e4c62e9fd8ebe0221d538539eba6148c85ce4ba3 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Sat, 15 Aug 2026 22:53:02 +0600
Subject: [PATCH 3/3] add test
---
.../intrinsic-distributive-laws-crash.ll | 140 +++++++++++++++---
1 file changed, 123 insertions(+), 17 deletions(-)
diff --git a/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll b/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll
index b69f6842b06e8..e87ac5cf69daa 100644
--- a/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll
+++ b/llvm/test/Transforms/InstCombine/intrinsic-distributive-laws-crash.ll
@@ -1,18 +1,124 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=instcombine %s | FileCheck %s
-
- at g = global i32 0
-
-declare i32 @llvm.smin.i32(i32, i32)
-
-define i32 @test_constexpr_distributive_crash() {
-; CHECK-LABEL: @test_constexpr_distributive_crash(
-; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.smin.i32(i32 add (i32 ptrtoint (ptr @g to i32), i32 10), i32 add (i32 ptrtoint (ptr @g to i32), i32 20))
-; CHECK-NEXT: ret i32 [[RES]]
-;
- %res = call i32 @llvm.smin.i32(
- i32 add nsw (i32 ptrtoint (ptr @g to i32), i32 10),
- i32 add nsw (i32 ptrtoint (ptr @g to i32), i32 20)
- )
- ret i32 %res
+; RUN: opt -passes='default<O1>' -S %s -o /dev/null
+; REQUIRES: asserts
+; ModuleID = 'repro_0.ll'
+source_filename = "repro.cpp"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at c = external global i32
+ at b = external global i8
+
+; Function Attrs: nounwind uwtable
+declare void @d() #0
+
+; Function Attrs: nounwind uwtable
+define i32 @e(i32 noundef %g, i32 noundef %h, i32 noundef %i) #0 {
+entry:
+ %g.addr = alloca i32, align 4
+ %h.addr = alloca i32, align 4
+ %i.addr = alloca i32, align 4
+ %f = alloca i32, align 4
+ store i32 %g, ptr %g.addr, align 4
+ store i32 %h, ptr %h.addr, align 4
+ store i32 %i, ptr %i.addr, align 4
+ %0 = load i32, ptr %g.addr, align 4
+ %1 = load i32, ptr %h.addr, align 4
+ %cmp = icmp slt i32 %0, %1
+ br i1 %cmp, label %cond.true, label %cond.false
+
+cond.true: ; preds = %entry
+ ret i32 0
+
+cond.false: ; preds = %entry
+ %2 = load i32, ptr %g.addr, align 4
+ %3 = load i32, ptr %i.addr, align 4
+ %cmp1 = icmp sgt i32 %2, %3
+ %4 = load i32, ptr %i.addr, align 4
+ %5 = load i32, ptr %g.addr, align 4
+ %cond = select i1 %cmp1, i32 %4, i32 %5
+ br label %cond.end
+
+cond.true2: ; No predecessors!
+ br label %cond.end
+
+cond.false3: ; No predecessors!
+ br label %cond.end
+
+cond.end: ; preds = %cond.false3, %cond.true2, %cond.false
+ store i32 %cond, ptr %f, align 4
+ %6 = load i32, ptr %f, align 4
+ ret i32 %6
}
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
+declare void @llvm.lifetime.start.p0(ptr captures(none)) #1
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
+declare void @llvm.lifetime.end.p0(ptr captures(none)) #1
+
+; Function Attrs: nounwind uwtable
+define void @j() #0 {
+entry:
+ %k = alloca i32, align 4
+ %l = alloca i32, align 4
+ %m = alloca ptr, align 8
+ store i32 893196426, ptr %k, align 4
+ store i32 826450915, ptr %l, align 4
+ br label %do.body
+
+do.body: ; preds = %do.body, %entry
+ store ptr %k, ptr %m, align 8
+ %0 = load i32, ptr %k, align 4
+ %conv = sext i32 %0 to i64
+ %shl = shl i64 %conv, 52
+ %shr = ashr i64 %shl, 52
+ %sub = sub nsw i64 0, %shr
+ %conv1 = trunc i64 %sub to i32
+ %1 = load i32, ptr %k, align 4
+ %conv2 = sext i32 %1 to i64
+ %shl3 = shl i64 %conv2, 32
+ %shr4 = ashr i64 %shl3, 32
+ %shl5 = shl i64 %shr4, 52
+ %shr6 = ashr i64 %shl5, 52
+ %conv7 = trunc i64 %shr6 to i32
+ %add = add nsw i32 2, %conv7
+ %2 = load i32, ptr %k, align 4
+ %conv8 = sext i32 %2 to i64
+ %shl9 = shl i64 %conv8, 32
+ %shr10 = ashr i64 %shl9, 32
+ %shl11 = shl i64 %shr10, 52
+ %shr12 = ashr i64 %shl11, 52
+ %conv13 = trunc i64 %shr12 to i32
+ %sub14 = sub nsw i32 2, %conv13
+ %call = call i32 @e(i32 noundef %conv1, i32 noundef %add, i32 noundef %sub14)
+ store i32 %call, ptr @c, align 4
+ %3 = load i32, ptr %l, align 4
+ store i32 %3, ptr %k, align 4
+ %4 = load ptr, ptr %m, align 8
+ %5 = load i32, ptr %4, align 4
+ %6 = load i8, ptr @b, align 1
+ %conv15 = sext i8 %6 to i32
+ %sub16 = sub nsw i32 %5, %conv15
+ %sub17 = sub nsw i32 %sub16, 7
+ %tobool = icmp ne i32 %sub17, 0
+ %lnot = xor i1 %tobool, true
+ br i1 %lnot, label %do.body, label %do.end
+
+do.end: ; preds = %do.body
+ %7 = load i32, ptr null, align 4
+ %tobool18 = icmp ne i32 %7, 0
+ br i1 %tobool18, label %if.then, label %if.end
+
+if.then: ; preds = %do.end
+ store ptr %l, ptr %m, align 8
+ br label %if.end
+
+if.end: ; preds = %if.then, %do.end
+ call void @d()
+ %8 = load ptr, ptr %m, align 8
+ %9 = load i32, ptr %8, align 4
+ ret void
+}
+
+attributes #0 = { nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
More information about the llvm-commits
mailing list