[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:32:34 PDT 2023


https://github.com/vfdff created https://github.com/llvm/llvm-project/pull/69807

Follow PR67236, Powi(x,C1)/Powi(x,C2) --> Powi(x,C1-C2) when (C1-C2) isn't wraparound.

>From f845359783d5dd5931827072e65e8aebb0745b6e Mon Sep 17 00:00:00 2001
From: zhongyunde 00443407 <zhongyunde at huawei.com>
Date: Fri, 20 Oct 2023 21:32:26 -0400
Subject: [PATCH] [InstCombine] optimize powi(X,C1)/powi(X,C2) with Ofast

Follow PR67236, Powi(x,C1)/Powi(x,C2) --> Powi(x,C1-C2) when (C1-C2)
isn't wraparound.
---
 .../InstCombine/InstCombineMulDivRem.cpp      | 18 +++++++
 llvm/test/Transforms/InstCombine/powi.ll      | 52 +++++++++++++++++++
 2 files changed, 70 insertions(+)

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
+}



More information about the llvm-commits mailing list