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

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 17 01:50:14 PST 2024


Author: Tanmay
Date: 2024-01-17T16:50:10+07:00
New Revision: 4426a1b7593a6e15caa09006d2446c95c19b5193

URL: https://github.com/llvm/llvm-project/commit/4426a1b7593a6e15caa09006d2446c95c19b5193
DIFF: https://github.com/llvm/llvm-project/commit/4426a1b7593a6e15caa09006d2446c95c19b5193.diff

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

Fixes https://github.com/llvm/llvm-project/issues/76549

The cause of the optimization miss was -
1. `optimizePow` converting almost integer FP exponents to integer, and
turning `pow` to `powi`.
2. `optimizeLog` not accepting `Intrinsic::powi` as a target.

This patch converts constantInt back to constantFP where applicable and
adds a test.

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
    llvm/test/Transforms/InstCombine/log-pow.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index a7cd68e860e467b..52eef9ab58a4d92 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2495,13 +2495,17 @@ 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)
+      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.
     substituteInParent(Arg, MulY);

diff  --git a/llvm/test/Transforms/InstCombine/log-pow.ll b/llvm/test/Transforms/InstCombine/log-pow.ll
index 58f04da280beee7..1dfe5c944eee75b 100644
--- a/llvm/test/Transforms/InstCombine/log-pow.ll
+++ b/llvm/test/Transforms/InstCombine/log-pow.ll
@@ -12,6 +12,75 @@ 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 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:%.*]])
+; 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:%.*]])
@@ -128,6 +197,8 @@ 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>)
 
 attributes #0 = { nounwind readnone }


        


More information about the llvm-commits mailing list