Skip to content

[InstCombine] Propagate poison pow[i] #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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

badumbatish
Copy link
Contributor

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)

@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

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]
3 participants