[llvm] [InstCombine] optimize powi(X,Y)/X with Ofast (PR #67236)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 27 03:48:28 PDT 2023


https://github.com/vfdff updated https://github.com/llvm/llvm-project/pull/67236

>From 87d42d2e99c7e480414dfdfa13ac79e3499c4a44 Mon Sep 17 00:00:00 2001
From: zhongyunde 00443407 <zhongyunde at huawei.com>
Date: Sun, 24 Sep 2023 02:34:09 -0400
Subject: [PATCH 1/2] [InstCombine] Precommit tests for PR67216

---
 llvm/test/Transforms/InstCombine/powi.ll | 61 ++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/powi.ll b/llvm/test/Transforms/InstCombine/powi.ll
index 20fe25c50a3ffc0..1ceb1b8b1cfd80d 100644
--- a/llvm/test/Transforms/InstCombine/powi.ll
+++ b/llvm/test/Transforms/InstCombine/powi.ll
@@ -2,6 +2,7 @@
 ; RUN: opt -passes=instcombine -S < %s | FileCheck %s
 
 declare double @llvm.powi.f64.i32(double, i32)
+declare float @llvm.powi.f32.i32(float, i32)
 declare double @llvm.powi.f64.i64(double, i64)
 declare double @llvm.fabs.f64(double)
 declare double @llvm.copysign.f64(double, double)
@@ -258,3 +259,63 @@ define double @different_types_powi(double %x, i32 %y, i64 %z) {
   %mul = fmul reassoc double %p2, %p1
   ret double %mul
 }
+
+define double @fdiv_pow_powi(double %x) {
+; CHECK-LABEL: @fdiv_pow_powi(
+; CHECK-NEXT:    [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf double [[P1]], [[X]]
+; CHECK-NEXT:    ret double [[DIV]]
+;
+  %p1 = call double @llvm.powi.f64.i32(double %x, i32 3)
+  %div = fdiv reassoc ninf double %p1, %x
+  ret double %div
+}
+
+define float @fdiv_powf_powi(float %x) {
+; CHECK-LABEL: @fdiv_powf_powi(
+; CHECK-NEXT:    [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf float [[P1]], [[X]]
+; CHECK-NEXT:    ret float [[DIV]]
+;
+  %p1 = call float @llvm.powi.f32.i32(float %x, i32 100)
+  %div = fdiv reassoc ninf float %p1, %x
+  ret float %div
+}
+
+; TODO: Multi-use may be also better off creating Powi(x,y-1) then creating
+; (mul, Powi(x,y-1),x) to replace the Powi(x,y).
+define double @fdiv_pow_powi_multi_use(double %x) {
+; CHECK-LABEL: @fdiv_pow_powi_multi_use(
+; CHECK-NEXT:    [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf double [[P1]], [[X]]
+; CHECK-NEXT:    tail call void @use(double [[P1]])
+; CHECK-NEXT:    ret double [[DIV]]
+;
+  %p1 = call double @llvm.powi.f64.i32(double %x, i32 3)
+  %div = fdiv reassoc ninf double %p1, %x
+  tail call void @use(double %p1)
+  ret double %div
+}
+
+; Negative test: Don't have fmf flag for both instructions
+define float @fdiv_powf_powi_missing_reassoc(float %x) {
+; CHECK-LABEL: @fdiv_powf_powi_missing_reassoc(
+; CHECK-NEXT:    [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv ninf float [[P1]], [[X]]
+; CHECK-NEXT:    ret float [[DIV]]
+;
+  %p1 = call float @llvm.powi.f32.i32(float %x, i32 100)
+  %div = fdiv ninf float %p1, %x
+  ret float %div
+}
+
+define float @fdiv_powf_powi_missing_ninf(float %x) {
+; CHECK-LABEL: @fdiv_powf_powi_missing_ninf(
+; CHECK-NEXT:    [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc float [[P1]], [[X]]
+; CHECK-NEXT:    ret float [[DIV]]
+;
+  %p1 = call float @llvm.powi.f32.i32(float %x, i32 100)
+  %div = fdiv reassoc float %p1, %x
+  ret float %div
+}

>From 2a2db12cea020479b45fd4f862326a64c1cb4562 Mon Sep 17 00:00:00 2001
From: zhongyunde 00443407 <zhongyunde at huawei.com>
Date: Sat, 23 Sep 2023 06:40:12 -0400
Subject: [PATCH 2/2] [InstCombine] optimize powi(X,Y)/X with Ofast

Try to transform the powi(X, Y) / X into powi(X, Y-1) with Ofast.
For this case, when the Y is 3, then powi(X, 2) is replaced by X * X in
the further step.
Fixes https://github.com/llvm/llvm-project/pull/67216
---
 .../Transforms/InstCombine/InstCombineMulDivRem.cpp | 13 +++++++++++++
 llvm/test/Transforms/InstCombine/powi.ll            |  6 ++----
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index dc091ec7c60e8dd..27ba4b6ac05f294 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1764,6 +1764,19 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
     return replaceInstUsesWith(I, Pow);
   }
 
+  // powi(X, Y) / X --> powi(X, Y-1)
+  // Require 'ninf' assuming that makes powi(X, -INT_MIN) acceptable
+  // Todo: Multi-use may be also better off creating Powi(x,y-1)
+  if (I.hasNoInfs() && I.hasAllowReassoc() &&
+      match(Op0, m_OneUse(m_Intrinsic<Intrinsic::powi>(m_Specific(Op1),
+                                                       m_Value(Y))))) {
+    Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType());
+    Value *Y1 = Builder.CreateAdd(Y, NegOne);
+    Type *Types[] = {Op1->getType(), Y1->getType()};
+    Value *Pow = Builder.CreateIntrinsic(Intrinsic::powi, Types, {Op1, Y1}, &I);
+    return replaceInstUsesWith(I, Pow);
+  }
+
   return nullptr;
 }
 
diff --git a/llvm/test/Transforms/InstCombine/powi.ll b/llvm/test/Transforms/InstCombine/powi.ll
index 1ceb1b8b1cfd80d..f0aee909f796a08 100644
--- a/llvm/test/Transforms/InstCombine/powi.ll
+++ b/llvm/test/Transforms/InstCombine/powi.ll
@@ -262,8 +262,7 @@ define double @different_types_powi(double %x, i32 %y, i64 %z) {
 
 define double @fdiv_pow_powi(double %x) {
 ; CHECK-LABEL: @fdiv_pow_powi(
-; CHECK-NEXT:    [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)
-; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf double [[P1]], [[X]]
+; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc ninf double [[X:%.*]], [[X]]
 ; CHECK-NEXT:    ret double [[DIV]]
 ;
   %p1 = call double @llvm.powi.f64.i32(double %x, i32 3)
@@ -273,8 +272,7 @@ define double @fdiv_pow_powi(double %x) {
 
 define float @fdiv_powf_powi(float %x) {
 ; CHECK-LABEL: @fdiv_powf_powi(
-; CHECK-NEXT:    [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)
-; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf float [[P1]], [[X]]
+; CHECK-NEXT:    [[DIV:%.*]] = call reassoc ninf float @llvm.powi.f32.i32(float [[X:%.*]], i32 99)
 ; CHECK-NEXT:    ret float [[DIV]]
 ;
   %p1 = call float @llvm.powi.f32.i32(float %x, i32 100)



More information about the llvm-commits mailing list