Skip to content

[InstCombine] Simplify multi use cast of Phi with constant inputs#186621

Open
andjo403 wants to merge 2 commits intollvm:mainfrom
andjo403:multiUseCastOfPhi
Open

[InstCombine] Simplify multi use cast of Phi with constant inputs#186621
andjo403 wants to merge 2 commits intollvm:mainfrom
andjo403:multiUseCastOfPhi

Conversation

@andjo403
Copy link
Contributor

@andjo403 andjo403 requested review from dtcxzyw and nikic March 14, 2026 20:27
@llvmbot llvmbot added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms labels Mar 14, 2026
@llvmbot
Copy link
Member

llvmbot commented Mar 14, 2026

@llvm/pr-subscribers-llvm-transforms

Author: Andreas Jonson (andjo403)

Changes

Regression noticed in #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


Full diff: https://github.com/llvm/llvm-project/pull/186621.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp (+6-1)
  • (modified) llvm/test/Transforms/InstCombine/cast_phi.ll (+100)
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 e8db72c8d849e..59929ee420f49 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:    [[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:    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:    [[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:    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:    [[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:    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
+}

@andjo403 andjo403 force-pushed the multiUseCastOfPhi branch from 393db14 to b264797 Compare March 14, 2026 20:30
@github-actions
Copy link

github-actions bot commented Mar 14, 2026

✅ With the latest revision this PR passed the C/C++ code formatter.

if (Instruction *NV = foldOpIntoPhi(CI, PN))
if (Instruction *NV = foldOpIntoPhi(
CI, PN,
/*AllowMultipleUses=*/
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

possible to set AllowMultipleUses to true as there is a check in foldOpIntoPhi that only allow multi use of the instruction if all inputs is simplified but maybe wast compile time?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants