[llvm] [InstCombine] optimize powi(X, C1)/powi(X, C2) with Ofast (PR #69807)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 20 20:33:33 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Allen (vfdff)
<details>
<summary>Changes</summary>
Follow PR67236, Powi(x,C1)/Powi(x,C2) --> Powi(x,C1-C2) when (C1-C2) isn't wraparound.
---
Full diff: https://github.com/llvm/llvm-project/pull/69807.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (+18)
- (modified) llvm/test/Transforms/InstCombine/powi.ll (+52)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index bc784390c23be49..1078a68a2d612fe 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1795,6 +1795,24 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
return replaceInstUsesWith(I, Pow);
}
+ // Powi(x,C1)/Powi(x,C2) --> Powi(x,C1-C2)
+ // This is legal when (C1-C2) isn't wraparound, in which case reassoc and nnan
+ // are required.
+ ConstantInt *C1, *C2;
+ if (I.hasAllowReassoc() && I.hasNoNaNs() &&
+ match(Op0, m_OneUse(m_Intrinsic<Intrinsic::powi>(m_Value(X),
+ m_ConstantInt(C1)))) &&
+ match(Op1, m_OneUse(m_Intrinsic<Intrinsic::powi>(m_Specific(X),
+ m_ConstantInt(C2))))) {
+ auto *DiffC = cast<ConstantInt>(Builder.CreateSub(C1, C2));
+ if (!DiffC->isNegative()) {
+ Type *Types[] = {X->getType(), DiffC->getType()};
+ Value *Pow =
+ Builder.CreateIntrinsic(Intrinsic::powi, Types, {X, DiffC}, &I);
+ return replaceInstUsesWith(I, Pow);
+ }
+ }
+
return nullptr;
}
diff --git a/llvm/test/Transforms/InstCombine/powi.ll b/llvm/test/Transforms/InstCombine/powi.ll
index 89efbb6f4536113..81f446185f6dc9a 100644
--- a/llvm/test/Transforms/InstCombine/powi.ll
+++ b/llvm/test/Transforms/InstCombine/powi.ll
@@ -341,3 +341,55 @@ define double @fdiv_pow_powi_negative_variable(double %x, i32 %y) {
%div = fdiv reassoc nnan double %p1, %x
ret double %div
}
+
+; Fold Powi(x,C1)/Powi(x,C2) to Powi(x,C1-C2) when (C1-C2) isn't wraparound
+define double @fdiv_powi_powi(double %x) {
+; CHECK-LABEL: @fdiv_powi_powi(
+; CHECK-NEXT: [[DIV:%.*]] = fmul reassoc nnan double [[X:%.*]], [[X]]
+; CHECK-NEXT: ret double [[DIV]]
+;
+ %p1 = call double @llvm.powi.f64.i32(double %x, i32 5)
+ %p2 = call double @llvm.powi.f64.i32(double %x, i32 3)
+ %div = fdiv reassoc nnan double %p1, %p2
+ ret double %div
+}
+
+; Negative test: (C1-C2) is wraparound
+define double @fdiv_powi_powi_wraparound(double %x) {
+; CHECK-LABEL: @fdiv_powi_powi_wraparound(
+; CHECK-NEXT: [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)
+; CHECK-NEXT: [[P2:%.*]] = call double @llvm.powi.f64.i32(double [[X]], i32 5)
+; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[P1]], [[P2]]
+; CHECK-NEXT: ret double [[DIV]]
+;
+ %p1 = call double @llvm.powi.f64.i32(double %x, i32 3)
+ %p2 = call double @llvm.powi.f64.i32(double %x, i32 5)
+ %div = fdiv reassoc nnan double %p1, %p2
+ ret double %div
+}
+
+define double @fdiv_powi_powi_missing_reassoc(double %x) {
+; CHECK-LABEL: @fdiv_powi_powi_missing_reassoc(
+; CHECK-NEXT: [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 15)
+; CHECK-NEXT: [[P2:%.*]] = call double @llvm.powi.f64.i32(double [[X]], i32 3)
+; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan double [[P1]], [[P2]]
+; CHECK-NEXT: ret double [[DIV]]
+;
+ %p1 = call double @llvm.powi.f64.i32(double %x, i32 15)
+ %p2 = call double @llvm.powi.f64.i32(double %x, i32 3)
+ %div = fdiv nnan double %p1, %p2
+ ret double %div
+}
+
+define double @fdiv_powi_powi_missing_nnan(double %x) {
+; CHECK-LABEL: @fdiv_powi_powi_missing_nnan(
+; CHECK-NEXT: [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 15)
+; CHECK-NEXT: [[P2:%.*]] = call double @llvm.powi.f64.i32(double [[X]], i32 3)
+; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[P1]], [[P2]]
+; CHECK-NEXT: ret double [[DIV]]
+;
+ %p1 = call double @llvm.powi.f64.i32(double %x, i32 15)
+ %p2 = call double @llvm.powi.f64.i32(double %x, i32 3)
+ %div = fdiv reassoc double %p1, %p2
+ ret double %div
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/69807
More information about the llvm-commits
mailing list