[llvm] [InstCombine] Add log-pow simplification for FP exponent edge case. (PR #76641)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 8 08:25:06 PST 2024


https://github.com/tanmaysachan updated https://github.com/llvm/llvm-project/pull/76641

>From 10bc58b9c784971786a2ba11f6547c64422e9a85 Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Sun, 31 Dec 2023 11:19:16 +0530
Subject: [PATCH 1/9] Add log-powi simplification tests.

* Current tests do not cover ideal behaviour for the expression `log(powi(x, y)) --> y * log(x)` where y is an integer.
---
 llvm/test/Transforms/InstCombine/log-pow.ll | 23 +++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/log-pow.ll b/llvm/test/Transforms/InstCombine/log-pow.ll
index 58f04da280beee..c4972f5a0253cb 100644
--- a/llvm/test/Transforms/InstCombine/log-pow.ll
+++ b/llvm/test/Transforms/InstCombine/log-pow.ll
@@ -12,6 +12,28 @@ define double @log_pow(double %x, double %y) {
   ret double %log
 }
 
+define double @log_powi_const(double %x) {
+; CHECK-LABEL: @log_powi_const(
+; CHECK-NEXT:    [[LOG1:%.*]] = call fast double @llvm.log.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast double [[LOG1]], -3.000000e+00
+; CHECK-NEXT:    ret double [[MUL]]
+;
+  %pow = call fast double @llvm.powi.f64.i32(double %x, i32 -3)
+  %log = call fast double @log(double %pow)
+  ret double %log
+}
+
+define double @log_powi_nonconst(double %x, i32 %y) {
+; CHECK-LABEL: @log_powi_nonconst(
+; CHECK-NEXT:    [[LOG1:%.*]] = call fast double @llvm.log.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CAST:%.*]] = sitofp i32 [[Y:%.*]] to double
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast double [[LOG1]], [[CAST]]
+; CHECK-NEXT:    ret double [[MUL]]
+  %pow = call fast double @llvm.powi.f64.i32(double %x, i32 %y)
+  %log = call fast double @log(double %pow)
+  ret double %log
+}
+
 define float @log10f_powf(float %x, float %y) {
 ; CHECK-LABEL: @log10f_powf(
 ; CHECK-NEXT:    [[LOG1:%.*]] = call fast float @llvm.log10.f32(float [[X:%.*]])
@@ -128,6 +150,7 @@ declare float @exp10f(float) #0
 declare <2 x float> @llvm.exp2.v2f32(<2 x float>)
 declare double @pow(double, double) #0
 declare float @powf(float, float) #0
+declare double @llvm.powi.f64.i32(double, i32) #0
 declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>)
 
 attributes #0 = { nounwind readnone }

>From 50437a585b8f6965d2997ff8672fcc8c4463655a Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Sun, 31 Dec 2023 11:21:42 +0530
Subject: [PATCH 2/9] Fix missed optimization for log-pow.

* Current simplification for `log(pow(x, y)) --> y * log(x)` does not work for `powi()`.
* This patch adds a cast for exponent to FP if it is integer, which enables this optimization.
---
 llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 760a626c8b6fcb..5aaa1d9d09ce3d 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2495,13 +2495,21 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
 
   // log(pow(x,y)) -> y*log(x)
   AttributeList NoAttrs;
-  if (ArgLb == PowLb || ArgID == Intrinsic::pow) {
+  if (ArgLb == PowLb || ArgID == Intrinsic::pow || ArgID == Intrinsic::powi) {
     Value *LogX =
         Log->doesNotAccessMemory()
             ? B.CreateCall(Intrinsic::getDeclaration(Mod, LogID, Ty),
                            Arg->getOperand(0), "log")
             : emitUnaryFloatFnCall(Arg->getOperand(0), TLI, LogNm, B, NoAttrs);
-    Value *MulY = B.CreateFMul(Arg->getArgOperand(1), LogX, "mul");
+    Value *Y = Arg->getArgOperand(1);
+    // Cast exponent to FP if integer.
+    if (ArgID == Intrinsic::powi) {
+      if (ConstantInt *C = dyn_cast<ConstantInt>(Y))
+        Y = ConstantFoldCastOperand(Instruction::SIToFP, C, Log->getType(), DL);
+      else
+        Y = B.CreateCast(Instruction::SIToFP, Y, Ty, "cast");
+    }
+    Value *MulY = B.CreateFMul(Y, LogX, "mul");
     // Since pow() may have side effects, e.g. errno,
     // dead code elimination may not be trusted to remove it.
     substituteInParent(Arg, MulY);

>From 556cfbbec54d5b85d318109fff8c3cce5e9584ab Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Wed, 3 Jan 2024 20:41:14 +0530
Subject: [PATCH 3/9] fixup! Fix missed optimization for log-pow.

---
 llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 5aaa1d9d09ce3d..d19a5dc9994b7b 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2505,7 +2505,7 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
     // Cast exponent to FP if integer.
     if (ArgID == Intrinsic::powi) {
       if (ConstantInt *C = dyn_cast<ConstantInt>(Y))
-        Y = ConstantFoldCastOperand(Instruction::SIToFP, C, Log->getType(), DL);
+        Y = ConstantFoldCastOperand(Instruction::SIToFP, C, Ty, DL);
       else
         Y = B.CreateCast(Instruction::SIToFP, Y, Ty, "cast");
     }

>From 39c428a696af89d4a01eccb2ee057e48098d9bbe Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Wed, 3 Jan 2024 23:18:52 +0530
Subject: [PATCH 4/9] fixup! fixup! Fix missed optimization for log-pow.

---
 llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index d19a5dc9994b7b..3b65d8da52250c 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2503,12 +2503,8 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
             : emitUnaryFloatFnCall(Arg->getOperand(0), TLI, LogNm, B, NoAttrs);
     Value *Y = Arg->getArgOperand(1);
     // Cast exponent to FP if integer.
-    if (ArgID == Intrinsic::powi) {
-      if (ConstantInt *C = dyn_cast<ConstantInt>(Y))
-        Y = ConstantFoldCastOperand(Instruction::SIToFP, C, Ty, DL);
-      else
+    if (ArgID == Intrinsic::powi)
         Y = B.CreateCast(Instruction::SIToFP, Y, Ty, "cast");
-    }
     Value *MulY = B.CreateFMul(Y, LogX, "mul");
     // Since pow() may have side effects, e.g. errno,
     // dead code elimination may not be trusted to remove it.

>From 229602efe4d840764972e851044d3d95cc9ef780 Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Thu, 4 Jan 2024 00:06:35 +0530
Subject: [PATCH 5/9] fixup! fixup! fixup! Fix missed optimization for log-pow.

---
 llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 3b65d8da52250c..35693ebb4cc189 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2504,7 +2504,7 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
     Value *Y = Arg->getArgOperand(1);
     // Cast exponent to FP if integer.
     if (ArgID == Intrinsic::powi)
-        Y = B.CreateCast(Instruction::SIToFP, Y, Ty, "cast");
+      Y = B.CreateCast(Instruction::SIToFP, Y, Ty, "cast");
     Value *MulY = B.CreateFMul(Y, LogX, "mul");
     // Since pow() may have side effects, e.g. errno,
     // dead code elimination may not be trusted to remove it.

>From 8aff100c60de976309e8f432ad694e887732fb03 Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Thu, 4 Jan 2024 18:40:30 +0530
Subject: [PATCH 6/9] Add float32 and non-fast tests

---
 llvm/test/Transforms/InstCombine/log-pow.ll | 33 +++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/log-pow.ll b/llvm/test/Transforms/InstCombine/log-pow.ll
index c4972f5a0253cb..a4c2a5939d5b61 100644
--- a/llvm/test/Transforms/InstCombine/log-pow.ll
+++ b/llvm/test/Transforms/InstCombine/log-pow.ll
@@ -34,6 +34,38 @@ define double @log_powi_nonconst(double %x, i32 %y) {
   ret double %log
 }
 
+define float @logf_powfi_const(float %x) {
+; CHECK-LABEL: @logf_powfi_const(
+; CHECK-NEXT:    [[LOG1:%.*]] = call fast float @llvm.log.f32(float [[X:%.*]])
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[LOG1]], -3.000000e+00
+; CHECK-NEXT:    ret float [[MUL]]
+  %pow = call fast float @llvm.powi.f32.i32(float %x, i32 -3)
+  %log = call fast float @logf(float %pow)
+  ret float %log
+}
+
+define float @logf_powfi_nonconst(float %x, i32 %y) {
+; CHECK-LABEL: @logf_powfi_nonconst(
+; CHECK-NEXT:    [[LOG1:%.*]] = call fast float @llvm.log.f32(float [[X:%.*]])
+; CHECK-NEXT:    [[CAST:%.*]] = sitofp i32 [[Y:%.*]] to float
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[LOG1]], [[CAST]]
+; CHECK-NEXT:    ret float [[MUL]]
+  %pow = call fast float @llvm.powi.f32.i32(float %x, i32 %y)
+  %log = call fast float @logf(float %pow)
+  ret float %log
+}
+
+define double @log_powi_not_fast(double %x, i32 %y) {
+; CHECK-LABEL: @log_powi_not_fast(
+; CHECK-NEXT:    [[POW:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[LOG:%.*]] = call fast double @log(double [[POW]])
+; CHECK-NEXT:    ret double [[LOG]]
+;
+  %pow = call double @llvm.powi.f64.i32(double %x, i32 %y)
+  %log = call fast double @log(double %pow)
+  ret double %log
+}
+
 define float @log10f_powf(float %x, float %y) {
 ; CHECK-LABEL: @log10f_powf(
 ; CHECK-NEXT:    [[LOG1:%.*]] = call fast float @llvm.log10.f32(float [[X:%.*]])
@@ -150,6 +182,7 @@ declare float @exp10f(float) #0
 declare <2 x float> @llvm.exp2.v2f32(<2 x float>)
 declare double @pow(double, double) #0
 declare float @powf(float, float) #0
+declare float @llvm.powi.f32.i32(float, i32) #0
 declare double @llvm.powi.f64.i32(double, i32) #0
 declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>)
 

>From 68c37d77e5a16fb4bfdef8c9f3aa808b032336e0 Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Thu, 4 Jan 2024 18:43:30 +0530
Subject: [PATCH 7/9] fixup! Add float32 and non-fast tests

---
 llvm/test/Transforms/InstCombine/log-pow.ll | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/log-pow.ll b/llvm/test/Transforms/InstCombine/log-pow.ll
index a4c2a5939d5b61..fe8be1f4bf0a2c 100644
--- a/llvm/test/Transforms/InstCombine/log-pow.ll
+++ b/llvm/test/Transforms/InstCombine/log-pow.ll
@@ -29,6 +29,7 @@ define double @log_powi_nonconst(double %x, i32 %y) {
 ; CHECK-NEXT:    [[CAST:%.*]] = sitofp i32 [[Y:%.*]] to double
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul fast double [[LOG1]], [[CAST]]
 ; CHECK-NEXT:    ret double [[MUL]]
+;
   %pow = call fast double @llvm.powi.f64.i32(double %x, i32 %y)
   %log = call fast double @log(double %pow)
   ret double %log
@@ -39,6 +40,7 @@ define float @logf_powfi_const(float %x) {
 ; CHECK-NEXT:    [[LOG1:%.*]] = call fast float @llvm.log.f32(float [[X:%.*]])
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[LOG1]], -3.000000e+00
 ; CHECK-NEXT:    ret float [[MUL]]
+;
   %pow = call fast float @llvm.powi.f32.i32(float %x, i32 -3)
   %log = call fast float @logf(float %pow)
   ret float %log
@@ -50,6 +52,7 @@ define float @logf_powfi_nonconst(float %x, i32 %y) {
 ; CHECK-NEXT:    [[CAST:%.*]] = sitofp i32 [[Y:%.*]] to float
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[LOG1]], [[CAST]]
 ; CHECK-NEXT:    ret float [[MUL]]
+;
   %pow = call fast float @llvm.powi.f32.i32(float %x, i32 %y)
   %log = call fast float @logf(float %pow)
   ret float %log

>From 614759c14d7071ae0b5138d2cfdf75e42bd106eb Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Thu, 4 Jan 2024 21:11:46 +0530
Subject: [PATCH 8/9] fixup! fixup! Add float32 and non-fast tests

---
 llvm/test/Transforms/InstCombine/log-pow.ll | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/log-pow.ll b/llvm/test/Transforms/InstCombine/log-pow.ll
index fe8be1f4bf0a2c..1dfe5c944eee75 100644
--- a/llvm/test/Transforms/InstCombine/log-pow.ll
+++ b/llvm/test/Transforms/InstCombine/log-pow.ll
@@ -35,6 +35,18 @@ define double @log_powi_nonconst(double %x, i32 %y) {
   ret double %log
 }
 
+define double @logf64_powi_nonconst(double %x, i32 %y) {
+; CHECK-LABEL: @logf64_powi_nonconst(
+; CHECK-NEXT:    [[LOG1:%.*]] = call fast double @llvm.log.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CAST:%.*]] = sitofp i32 [[Y:%.*]] to double
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast double [[LOG1]], [[CAST]]
+; CHECK-NEXT:    ret double [[MUL]]
+;
+  %pow = call fast double @llvm.powi.f64.i32(double %x, i32 %y)
+  %log = call fast double @llvm.log.f64(double %pow)
+  ret double %log
+}
+
 define float @logf_powfi_const(float %x) {
 ; CHECK-LABEL: @logf_powfi_const(
 ; CHECK-NEXT:    [[LOG1:%.*]] = call fast float @llvm.log.f32(float [[X:%.*]])

>From 0897dd9f4ab0ce93c38bac846f406b673754960b Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Mon, 8 Jan 2024 21:54:46 +0530
Subject: [PATCH 9/9] fixup! fixup! fixup! Add float32 and non-fast tests

---
 llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 35693ebb4cc189..efff9651956048 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2504,7 +2504,7 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
     Value *Y = Arg->getArgOperand(1);
     // Cast exponent to FP if integer.
     if (ArgID == Intrinsic::powi)
-      Y = B.CreateCast(Instruction::SIToFP, Y, Ty, "cast");
+      Y = B.CreateSIToFP(Y, Ty, "cast");
     Value *MulY = B.CreateFMul(Y, LogX, "mul");
     // Since pow() may have side effects, e.g. errno,
     // dead code elimination may not be trusted to remove it.



More information about the llvm-commits mailing list