Skip to content

Commit 4426a1b

Browse files
authored
[InstCombine] Add log-pow simplification for FP exponent edge case. (#76641)
Fixes #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.
1 parent 94da2b2 commit 4426a1b

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2495,13 +2495,17 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
24952495

24962496
// log(pow(x,y)) -> y*log(x)
24972497
AttributeList NoAttrs;
2498-
if (ArgLb == PowLb || ArgID == Intrinsic::pow) {
2498+
if (ArgLb == PowLb || ArgID == Intrinsic::pow || ArgID == Intrinsic::powi) {
24992499
Value *LogX =
25002500
Log->doesNotAccessMemory()
25012501
? B.CreateCall(Intrinsic::getDeclaration(Mod, LogID, Ty),
25022502
Arg->getOperand(0), "log")
25032503
: emitUnaryFloatFnCall(Arg->getOperand(0), TLI, LogNm, B, NoAttrs);
2504-
Value *MulY = B.CreateFMul(Arg->getArgOperand(1), LogX, "mul");
2504+
Value *Y = Arg->getArgOperand(1);
2505+
// Cast exponent to FP if integer.
2506+
if (ArgID == Intrinsic::powi)
2507+
Y = B.CreateSIToFP(Y, Ty, "cast");
2508+
Value *MulY = B.CreateFMul(Y, LogX, "mul");
25052509
// Since pow() may have side effects, e.g. errno,
25062510
// dead code elimination may not be trusted to remove it.
25072511
substituteInParent(Arg, MulY);

llvm/test/Transforms/InstCombine/log-pow.ll

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,75 @@ define double @log_pow(double %x, double %y) {
1212
ret double %log
1313
}
1414

15+
define double @log_powi_const(double %x) {
16+
; CHECK-LABEL: @log_powi_const(
17+
; CHECK-NEXT: [[LOG1:%.*]] = call fast double @llvm.log.f64(double [[X:%.*]])
18+
; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[LOG1]], -3.000000e+00
19+
; CHECK-NEXT: ret double [[MUL]]
20+
;
21+
%pow = call fast double @llvm.powi.f64.i32(double %x, i32 -3)
22+
%log = call fast double @log(double %pow)
23+
ret double %log
24+
}
25+
26+
define double @log_powi_nonconst(double %x, i32 %y) {
27+
; CHECK-LABEL: @log_powi_nonconst(
28+
; CHECK-NEXT: [[LOG1:%.*]] = call fast double @llvm.log.f64(double [[X:%.*]])
29+
; CHECK-NEXT: [[CAST:%.*]] = sitofp i32 [[Y:%.*]] to double
30+
; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[LOG1]], [[CAST]]
31+
; CHECK-NEXT: ret double [[MUL]]
32+
;
33+
%pow = call fast double @llvm.powi.f64.i32(double %x, i32 %y)
34+
%log = call fast double @log(double %pow)
35+
ret double %log
36+
}
37+
38+
define double @logf64_powi_nonconst(double %x, i32 %y) {
39+
; CHECK-LABEL: @logf64_powi_nonconst(
40+
; CHECK-NEXT: [[LOG1:%.*]] = call fast double @llvm.log.f64(double [[X:%.*]])
41+
; CHECK-NEXT: [[CAST:%.*]] = sitofp i32 [[Y:%.*]] to double
42+
; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[LOG1]], [[CAST]]
43+
; CHECK-NEXT: ret double [[MUL]]
44+
;
45+
%pow = call fast double @llvm.powi.f64.i32(double %x, i32 %y)
46+
%log = call fast double @llvm.log.f64(double %pow)
47+
ret double %log
48+
}
49+
50+
define float @logf_powfi_const(float %x) {
51+
; CHECK-LABEL: @logf_powfi_const(
52+
; CHECK-NEXT: [[LOG1:%.*]] = call fast float @llvm.log.f32(float [[X:%.*]])
53+
; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[LOG1]], -3.000000e+00
54+
; CHECK-NEXT: ret float [[MUL]]
55+
;
56+
%pow = call fast float @llvm.powi.f32.i32(float %x, i32 -3)
57+
%log = call fast float @logf(float %pow)
58+
ret float %log
59+
}
60+
61+
define float @logf_powfi_nonconst(float %x, i32 %y) {
62+
; CHECK-LABEL: @logf_powfi_nonconst(
63+
; CHECK-NEXT: [[LOG1:%.*]] = call fast float @llvm.log.f32(float [[X:%.*]])
64+
; CHECK-NEXT: [[CAST:%.*]] = sitofp i32 [[Y:%.*]] to float
65+
; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[LOG1]], [[CAST]]
66+
; CHECK-NEXT: ret float [[MUL]]
67+
;
68+
%pow = call fast float @llvm.powi.f32.i32(float %x, i32 %y)
69+
%log = call fast float @logf(float %pow)
70+
ret float %log
71+
}
72+
73+
define double @log_powi_not_fast(double %x, i32 %y) {
74+
; CHECK-LABEL: @log_powi_not_fast(
75+
; CHECK-NEXT: [[POW:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
76+
; CHECK-NEXT: [[LOG:%.*]] = call fast double @log(double [[POW]])
77+
; CHECK-NEXT: ret double [[LOG]]
78+
;
79+
%pow = call double @llvm.powi.f64.i32(double %x, i32 %y)
80+
%log = call fast double @log(double %pow)
81+
ret double %log
82+
}
83+
1584
define float @log10f_powf(float %x, float %y) {
1685
; CHECK-LABEL: @log10f_powf(
1786
; CHECK-NEXT: [[LOG1:%.*]] = call fast float @llvm.log10.f32(float [[X:%.*]])
@@ -128,6 +197,8 @@ declare float @exp10f(float) #0
128197
declare <2 x float> @llvm.exp2.v2f32(<2 x float>)
129198
declare double @pow(double, double) #0
130199
declare float @powf(float, float) #0
200+
declare float @llvm.powi.f32.i32(float, i32) #0
201+
declare double @llvm.powi.f64.i32(double, i32) #0
131202
declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>)
132203

133204
attributes #0 = { nounwind readnone }

0 commit comments

Comments
 (0)