Skip to content

[InstCombine] Propagate poison pow[i], [us]add, [us]sub and [us]mul #146750

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 4, 2025

Conversation

badumbatish
Copy link
Contributor

@badumbatish badumbatish commented Jul 2, 2025

Fixes #146560 as well as propagate poison for [us]add, [us]sub and [us]mul

@badumbatish badumbatish requested a review from nikic as a code owner July 2, 2025 17:38
@badumbatish badumbatish changed the title [InstCombine] Propagate poison powi [InstCombine] Propagate poison pow[i] Jul 2, 2025
@llvmbot llvmbot added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms labels Jul 2, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 2, 2025

@llvm/pr-subscribers-llvm-transforms

Author: jjasmine (badumbatish)

Changes

Fixes #146560.

As the issue is about folding with poison and with power operand like 0.0 and 1.0, I didn't add any optimization for folding pow(x, 0) (is it even allowed? I'm not sure)


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

2 Files Affected:

  • (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+6)
  • (modified) llvm/test/Transforms/InstSimplify/fold-intrinsics.ll (+31-1)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index cb1dae92faf92..c7cbd627117da 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6673,7 +6673,13 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
       if (auto *C1 = dyn_cast<Constant>(Op1))
         return simplifyRelativeLoad(C0, C1, Q.DL);
     break;
+  case Intrinsic::pow:
+    if (isa<PoisonValue>(Op0) || isa<PoisonValue>(Op1))
+      return PoisonValue::get(ReturnType);
+    break;
   case Intrinsic::powi:
+    if (isa<PoisonValue>(Op0) || isa<PoisonValue>(Op1))
+      return PoisonValue::get(ReturnType);
     if (auto *Power = dyn_cast<ConstantInt>(Op1)) {
       // powi(x, 0) -> 1.0
       if (Power->isZero())
diff --git a/llvm/test/Transforms/InstSimplify/fold-intrinsics.ll b/llvm/test/Transforms/InstSimplify/fold-intrinsics.ll
index e45aa3fd09ce0..1fd47af6946cb 100644
--- a/llvm/test/Transforms/InstSimplify/fold-intrinsics.ll
+++ b/llvm/test/Transforms/InstSimplify/fold-intrinsics.ll
@@ -33,7 +33,7 @@ define void @powi(double %V, ptr%P) {
 define void @powi_i16(float %V, ptr%P) {
 ; CHECK-LABEL: @powi_i16(
 ; CHECK-NEXT:    store volatile float 1.000000e+00, ptr [[P:%.*]], align 4
-; CHECK-NEXT:    store volatile float [[V:%.*]], ptr [[P]], align 4
+; CHECK-NEXT:    store volatile float [[D:%.*]], ptr [[P]], align 4
 ; CHECK-NEXT:    ret void
 ;
   %B = tail call float @llvm.powi.f32.i16(float %V, i16 0) nounwind
@@ -44,3 +44,33 @@ define void @powi_i16(float %V, ptr%P) {
 
   ret void
 }
+
+define void @pow_poison_i16(i16 %arg_int,float %arg_flt, ptr %P) {
+; CHECK-LABEL: @pow_poison_i16(
+; CHECK-NEXT:    store volatile float poison, ptr [[P:%.*]], align 4
+; CHECK-NEXT:    store volatile float poison, ptr [[P]], align 4
+; CHECK-NEXT:    store volatile float poison, ptr [[P]], align 4
+; CHECK-NEXT:    store volatile float poison, ptr [[P]], align 4
+; CHECK-NEXT:    store volatile float poison, ptr [[P]], align 4
+; CHECK-NEXT:    store volatile float poison, ptr [[P]], align 4
+; CHECK-NEXT:    ret void
+;
+  %2 = tail call float @llvm.powi.f32.i16(float poison, i16 %arg_int) nounwind
+  store volatile float %2, ptr %P
+
+  %3 = tail call float @llvm.pow(float poison, float %arg_flt) nounwind
+  store volatile float %3, ptr %P
+
+  %4 = tail call float @llvm.powi.f32.i16(float %arg_flt, i16 poison) nounwind
+  store volatile float %4, ptr %P
+
+  %5 = tail call float @llvm.pow(float %arg_flt, float poison) nounwind
+  store volatile float %5, ptr %P
+
+  %6 = tail call float @llvm.powi.f32.i16(float poison, i16 poison) nounwind
+  store volatile float %6, ptr %P
+
+  %7 = tail call float @llvm.pow(float poison, float poison) nounwind
+  store volatile float %7, ptr %P
+  ret void
+}

@llvmbot
Copy link
Member

llvmbot commented Jul 2, 2025

@llvm/pr-subscribers-llvm-analysis

Author: jjasmine (badumbatish)

Changes

Fixes #146560.

As the issue is about folding with poison and with power operand like 0.0 and 1.0, I didn't add any optimization for folding pow(x, 0) (is it even allowed? I'm not sure)


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

2 Files Affected:

  • (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+6)
  • (modified) llvm/test/Transforms/InstSimplify/fold-intrinsics.ll (+31-1)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index cb1dae92faf92..c7cbd627117da 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6673,7 +6673,13 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
       if (auto *C1 = dyn_cast<Constant>(Op1))
         return simplifyRelativeLoad(C0, C1, Q.DL);
     break;
+  case Intrinsic::pow:
+    if (isa<PoisonValue>(Op0) || isa<PoisonValue>(Op1))
+      return PoisonValue::get(ReturnType);
+    break;
   case Intrinsic::powi:
+    if (isa<PoisonValue>(Op0) || isa<PoisonValue>(Op1))
+      return PoisonValue::get(ReturnType);
     if (auto *Power = dyn_cast<ConstantInt>(Op1)) {
       // powi(x, 0) -> 1.0
       if (Power->isZero())
diff --git a/llvm/test/Transforms/InstSimplify/fold-intrinsics.ll b/llvm/test/Transforms/InstSimplify/fold-intrinsics.ll
index e45aa3fd09ce0..1fd47af6946cb 100644
--- a/llvm/test/Transforms/InstSimplify/fold-intrinsics.ll
+++ b/llvm/test/Transforms/InstSimplify/fold-intrinsics.ll
@@ -33,7 +33,7 @@ define void @powi(double %V, ptr%P) {
 define void @powi_i16(float %V, ptr%P) {
 ; CHECK-LABEL: @powi_i16(
 ; CHECK-NEXT:    store volatile float 1.000000e+00, ptr [[P:%.*]], align 4
-; CHECK-NEXT:    store volatile float [[V:%.*]], ptr [[P]], align 4
+; CHECK-NEXT:    store volatile float [[D:%.*]], ptr [[P]], align 4
 ; CHECK-NEXT:    ret void
 ;
   %B = tail call float @llvm.powi.f32.i16(float %V, i16 0) nounwind
@@ -44,3 +44,33 @@ define void @powi_i16(float %V, ptr%P) {
 
   ret void
 }
+
+define void @pow_poison_i16(i16 %arg_int,float %arg_flt, ptr %P) {
+; CHECK-LABEL: @pow_poison_i16(
+; CHECK-NEXT:    store volatile float poison, ptr [[P:%.*]], align 4
+; CHECK-NEXT:    store volatile float poison, ptr [[P]], align 4
+; CHECK-NEXT:    store volatile float poison, ptr [[P]], align 4
+; CHECK-NEXT:    store volatile float poison, ptr [[P]], align 4
+; CHECK-NEXT:    store volatile float poison, ptr [[P]], align 4
+; CHECK-NEXT:    store volatile float poison, ptr [[P]], align 4
+; CHECK-NEXT:    ret void
+;
+  %2 = tail call float @llvm.powi.f32.i16(float poison, i16 %arg_int) nounwind
+  store volatile float %2, ptr %P
+
+  %3 = tail call float @llvm.pow(float poison, float %arg_flt) nounwind
+  store volatile float %3, ptr %P
+
+  %4 = tail call float @llvm.powi.f32.i16(float %arg_flt, i16 poison) nounwind
+  store volatile float %4, ptr %P
+
+  %5 = tail call float @llvm.pow(float %arg_flt, float poison) nounwind
+  store volatile float %5, ptr %P
+
+  %6 = tail call float @llvm.powi.f32.i16(float poison, i16 poison) nounwind
+  store volatile float %6, ptr %P
+
+  %7 = tail call float @llvm.pow(float poison, float poison) nounwind
+  store volatile float %7, ptr %P
+  ret void
+}

@badumbatish
Copy link
Contributor Author

will add vector type into test case

@lukel97
Copy link
Contributor

lukel97 commented Jul 2, 2025

Is it possible to handle this in ConstantFolding? That way IRBuilder etc. will automatically fold it to poison without the need to run InstSimplify, see: #141821 (review)

@badumbatish
Copy link
Contributor Author

on it

@badumbatish
Copy link
Contributor Author

badumbatish commented Jul 2, 2025

@lukel97 ok i digged around and prototyped in the codebase a bit, and together with this comment

But I guess we'll still need to figure out how to handle the case whenever not all arguments are constant, e.g only one operand is poison. Should that be handled by ValueTracking?

Yeah. Generally we should handle these cases in propagatesPoison and simplifyIntrinsic...

I think these are not in ConstantFolding at the moment. but in InstructionSimplify.

I tried handling this in ConstantFolding but it was clunky with how the Operands array to be passed in is <Const*>, requiring both arguments to pow[i] to both be poison to be foldable.

Tagging @dtcxzyw for some directions

Copy link
Contributor

@lukel97 lukel97 left a comment

Choose a reason for hiding this comment

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

Ah I see what you mean about having a possibly non-constant arg. In that case I think having it in InstSimplify is fine.

LGTM but please wait for another reviewer

@lukel97 lukel97 requested a review from dtcxzyw July 3, 2025 10:16
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

I don't want to add more of these one-off special cases which result in different poison-propagation support between ValueTracking, ConstantFolding and InstSimplify. I've put up #146878 to consolidate ValueTracking and ConstantFolding. We can then do the same for InstSimplify. And then this should just become a matter of adding extra intrinsics to the list.

@badumbatish badumbatish force-pushed the propagate_poison_powi branch from 407b63b to 6fd04bf Compare July 3, 2025 18:39
@badumbatish
Copy link
Contributor Author

rebased and refactored. waiting for your pr to be merged.

badumbatish added 7 commits July 4, 2025 09:12
Refactor support for pow[i] poison folding by rebasing on Nikic's
changes and implement the changes in InstructionSimplify.

Fix a few test case and added more Intrinsics to switch case in
ValueTracking.
@badumbatish badumbatish force-pushed the propagate_poison_powi branch from 8fc29ae to d2244eb Compare July 4, 2025 16:26
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

LGTM

@badumbatish badumbatish changed the title [InstCombine] Propagate poison pow[i] [InstCombine] Propagate poison pow[i], [us]add, [us]sub and [us]mul Jul 4, 2025
Copy link
Contributor

@lukel97 lukel97 left a comment

Choose a reason for hiding this comment

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

LGTM, I think there's a few fold to poison cases in simplifyBinaryIntrinsic can probably be removed afterwards as an NFC

@lukel97 lukel97 merged commit 07286b1 into llvm:main Jul 4, 2025
9 checks passed
@badumbatish badumbatish deleted the propagate_poison_powi branch July 4, 2025 22:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:analysis Includes value tracking, cost tables and constant folding llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Poison not propagate through @llvm.pow[i]
4 participants