[llvm] [InstCombine] Simplify multi use cast of Phi with constant inputs (PR #186621)
Andreas Jonson via llvm-commits
llvm-commits at lists.llvm.org
Sat Mar 14 13:27:38 PDT 2026
https://github.com/andjo403 created https://github.com/llvm/llvm-project/pull/186621
Regression noticed in https://github.com/llvm/llvm-project/pull/184182
for icmp there is a similar fold here https://github.com/andjo403/llvm-project/blob/393db14ac027412180d94ddcd35fb25b09a45913/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp#L1346-L1361
>From 579fe671a22c336663b26235f224ea28d1ee0f2b Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sat, 14 Mar 2026 21:17:31 +0100
Subject: [PATCH 1/2] [InstCombine] Pre commit tests (NFC)
---
llvm/test/Transforms/InstCombine/cast_phi.ll | 100 +++++++++++++++++++
1 file changed, 100 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/cast_phi.ll b/llvm/test/Transforms/InstCombine/cast_phi.ll
index e8db72c8d849e..d82180a222ccc 100644
--- a/llvm/test/Transforms/InstCombine/cast_phi.ll
+++ b/llvm/test/Transforms/InstCombine/cast_phi.ll
@@ -378,3 +378,103 @@ exit:
%ext = zext i8 %iv to i32
ret i32 %ext
}
+
+
+declare void @use8(i8)
+declare void @use32(i32)
+
+define i32 @zext_constants_multi_use(i8 %x) {
+; CHECK-LABEL: @zext_constants_multi_use(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 42
+; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
+; CHECK: t:
+; CHECK-NEXT: br label [[EXIT:%.*]]
+; CHECK: f:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[P:%.*]] = phi i8 [ 5, [[T]] ], [ -1, [[F]] ]
+; CHECK-NEXT: call void @use8(i8 [[P]])
+; CHECK-NEXT: [[R:%.*]] = zext i8 [[P]] to i32
+; CHECK-NEXT: ret i32 [[R]]
+;
+entry:
+ %cmp = icmp eq i8 %x, 42
+ br i1 %cmp, label %t, label %f
+
+t:
+ br label %exit
+
+f:
+ br label %exit
+
+exit:
+ %p = phi i8 [ 5, %t ], [ -1, %f ]
+ call void @use8(i8 %p)
+ %r = zext i8 %p to i32
+ ret i32 %r
+}
+
+define i32 @sext_constants_multi_use(i8 %x) {
+; CHECK-LABEL: @sext_constants_multi_use(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 42
+; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
+; CHECK: t:
+; CHECK-NEXT: br label [[EXIT:%.*]]
+; CHECK: f:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[P:%.*]] = phi i8 [ 5, [[T]] ], [ -1, [[F]] ]
+; CHECK-NEXT: call void @use8(i8 [[P]])
+; CHECK-NEXT: [[R:%.*]] = sext i8 [[P]] to i32
+; CHECK-NEXT: ret i32 [[R]]
+;
+entry:
+ %cmp = icmp eq i8 %x, 42
+ br i1 %cmp, label %t, label %f
+
+t:
+ br label %exit
+
+f:
+ br label %exit
+
+exit:
+ %p = phi i8 [ 5, %t ], [ -1, %f ]
+ call void @use8(i8 %p)
+ %r = sext i8 %p to i32
+ ret i32 %r
+}
+
+define i8 @trunc_constants_multi_use(i8 %x) {
+; CHECK-LABEL: @trunc_constants_multi_use(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 42
+; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
+; CHECK: t:
+; CHECK-NEXT: br label [[EXIT:%.*]]
+; CHECK: f:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[P:%.*]] = phi i32 [ 5, [[T]] ], [ -1, [[F]] ]
+; CHECK-NEXT: call void @use32(i32 [[P]])
+; CHECK-NEXT: [[R:%.*]] = trunc nsw i32 [[P]] to i8
+; CHECK-NEXT: ret i8 [[R]]
+;
+entry:
+ %cmp = icmp eq i8 %x, 42
+ br i1 %cmp, label %t, label %f
+
+t:
+ br label %exit
+
+f:
+ br label %exit
+
+exit:
+ %p = phi i32 [ 5, %t ], [ -1, %f ]
+ call void @use32(i32 %p)
+ %r = trunc i32 %p to i8
+ ret i8 %r
+}
>From 393db14ac027412180d94ddcd35fb25b09a45913 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sat, 14 Mar 2026 21:22:15 +0100
Subject: [PATCH 2/2] [InstCombine] Simplify multi use cast of Phi with
constant inputs
---
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | 7 ++++++-
llvm/test/Transforms/InstCombine/cast_phi.ll | 6 +++---
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index f2a2e21f6fc95..fcd46b3ba4a17 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -237,7 +237,12 @@ Instruction *InstCombinerImpl::commonCastTransforms(CastInst &CI) {
// legal type.
if (!Src->getType()->isIntegerTy() || !CI.getType()->isIntegerTy() ||
shouldChangeType(CI.getSrcTy(), CI.getType()))
- if (Instruction *NV = foldOpIntoPhi(CI, PN))
+ if (Instruction *NV =
+ foldOpIntoPhi(CI, PN,
+ is_contained({Instruction::Trunc, Instruction::ZExt,
+ Instruction::SExt},
+ CI.getOpcode()) &&
+ all_of(PN->operands(), IsaPred<ConstantInt>)))
return NV;
}
diff --git a/llvm/test/Transforms/InstCombine/cast_phi.ll b/llvm/test/Transforms/InstCombine/cast_phi.ll
index d82180a222ccc..59929ee420f49 100644
--- a/llvm/test/Transforms/InstCombine/cast_phi.ll
+++ b/llvm/test/Transforms/InstCombine/cast_phi.ll
@@ -393,9 +393,9 @@ define i32 @zext_constants_multi_use(i8 %x) {
; CHECK: f:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
+; CHECK-NEXT: [[R:%.*]] = phi i32 [ 5, [[T]] ], [ 255, [[F]] ]
; CHECK-NEXT: [[P:%.*]] = phi i8 [ 5, [[T]] ], [ -1, [[F]] ]
; CHECK-NEXT: call void @use8(i8 [[P]])
-; CHECK-NEXT: [[R:%.*]] = zext i8 [[P]] to i32
; CHECK-NEXT: ret i32 [[R]]
;
entry:
@@ -425,9 +425,9 @@ define i32 @sext_constants_multi_use(i8 %x) {
; CHECK: f:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
+; CHECK-NEXT: [[R:%.*]] = phi i32 [ 5, [[T]] ], [ -1, [[F]] ]
; CHECK-NEXT: [[P:%.*]] = phi i8 [ 5, [[T]] ], [ -1, [[F]] ]
; CHECK-NEXT: call void @use8(i8 [[P]])
-; CHECK-NEXT: [[R:%.*]] = sext i8 [[P]] to i32
; CHECK-NEXT: ret i32 [[R]]
;
entry:
@@ -457,9 +457,9 @@ define i8 @trunc_constants_multi_use(i8 %x) {
; CHECK: f:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
+; CHECK-NEXT: [[R:%.*]] = phi i8 [ 5, [[T]] ], [ -1, [[F]] ]
; CHECK-NEXT: [[P:%.*]] = phi i32 [ 5, [[T]] ], [ -1, [[F]] ]
; CHECK-NEXT: call void @use32(i32 [[P]])
-; CHECK-NEXT: [[R:%.*]] = trunc nsw i32 [[P]] to i8
; CHECK-NEXT: ret i8 [[R]]
;
entry:
More information about the llvm-commits
mailing list