Skip to content

Commit 7e3d110

Browse files
committed
[InstCombine] optimize powi(X,Y)/X with Ofast (#67236)
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 #67216 Reviewed By: dtcxzyw, nikic, jcranmer-intel
1 parent 6cbcbec commit 7e3d110

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,6 +1780,21 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
17801780
return replaceInstUsesWith(I, Pow);
17811781
}
17821782

1783+
// powi(X, Y) / X --> powi(X, Y-1)
1784+
// This is legal when (Y - 1) can't wraparound, in which case reassoc and nnan
1785+
// are required.
1786+
// TODO: Multi-use may be also better off creating Powi(x,y-1)
1787+
if (I.hasAllowReassoc() && I.hasNoNaNs() &&
1788+
match(Op0, m_OneUse(m_Intrinsic<Intrinsic::powi>(m_Specific(Op1),
1789+
m_Value(Y)))) &&
1790+
willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) {
1791+
Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType());
1792+
Value *Y1 = Builder.CreateAdd(Y, NegOne);
1793+
Type *Types[] = {Op1->getType(), Y1->getType()};
1794+
Value *Pow = Builder.CreateIntrinsic(Intrinsic::powi, Types, {Op1, Y1}, &I);
1795+
return replaceInstUsesWith(I, Pow);
1796+
}
1797+
17831798
return nullptr;
17841799
}
17851800

llvm/test/Transforms/InstCombine/powi.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,7 @@ define double @different_types_powi(double %x, i32 %y, i64 %z) {
262262

263263
define double @fdiv_pow_powi(double %x) {
264264
; CHECK-LABEL: @fdiv_pow_powi(
265-
; CHECK-NEXT: [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)
266-
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[P1]], [[X]]
265+
; CHECK-NEXT: [[DIV:%.*]] = fmul reassoc nnan double [[X:%.*]], [[X]]
267266
; CHECK-NEXT: ret double [[DIV]]
268267
;
269268
%p1 = call double @llvm.powi.f64.i32(double %x, i32 3)
@@ -273,8 +272,7 @@ define double @fdiv_pow_powi(double %x) {
273272

274273
define float @fdiv_powf_powi(float %x) {
275274
; CHECK-LABEL: @fdiv_powf_powi(
276-
; CHECK-NEXT: [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)
277-
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan float [[P1]], [[X]]
275+
; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan float @llvm.powi.f32.i32(float [[X:%.*]], i32 99)
278276
; CHECK-NEXT: ret float [[DIV]]
279277
;
280278
%p1 = call float @llvm.powi.f32.i32(float %x, i32 100)

0 commit comments

Comments
 (0)