Skip to content

Commit 0985202

Browse files
committed
[InstCombine] optimize powi(X,Y) * X with Ofast
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, 4) is replaced by X2 = X * X; X2 * X2 in the further step. Similar to D109954, who requires reassoc. Fixes #69862.
1 parent 160693d commit 0985202

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,18 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) {
683683
return replaceInstUsesWith(I, Pow);
684684
}
685685

686+
// powi(X, Y) * X --> powi(X, Y+1)
687+
// X * powi(X, Y) --> powi(X, Y+1)
688+
if (match(&I, m_c_FMul(m_OneUse(m_Intrinsic<Intrinsic::powi>(m_Value(X),
689+
m_Value(Y))),
690+
m_Deferred(X))) &&
691+
willNotOverflowSignedAdd(Y, ConstantInt::get(Y->getType(), 1), I)) {
692+
auto *Y1 = Builder.CreateAdd(Y, ConstantInt::get(Y->getType(), 1));
693+
auto *NewPow = Builder.CreateIntrinsic(
694+
Intrinsic::powi, {X->getType(), Y1->getType()}, {X, Y1}, &I);
695+
return replaceInstUsesWith(I, NewPow);
696+
}
697+
686698
if (I.isOnlyUserOfAnyOperand()) {
687699
// pow(X, Y) * pow(X, Z) -> pow(X, Y + Z)
688700
if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))) &&

llvm/test/Transforms/InstCombine/powi.ll

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,3 +341,52 @@ define double @fdiv_pow_powi_negative_variable(double %x, i32 %y) {
341341
%div = fdiv reassoc nnan double %p1, %x
342342
ret double %div
343343
}
344+
345+
; powi(X, Y) * X --> powi(X, Y+1)
346+
define double @powi_fmul_powi_x(double noundef %x) {
347+
; CHECK-LABEL: @powi_fmul_powi_x(
348+
; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
349+
; CHECK-NEXT: ret double [[MUL]]
350+
;
351+
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 3)
352+
%mul = fmul reassoc double %p1, %x
353+
ret double %mul
354+
}
355+
356+
; Negative test: Multi-use
357+
define double @powi_fmul_powi_x_multi_use(double noundef %x) {
358+
; CHECK-LABEL: @powi_fmul_powi_x_multi_use(
359+
; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)
360+
; CHECK-NEXT: tail call void @use(double [[P1]])
361+
; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]]
362+
; CHECK-NEXT: ret double [[MUL]]
363+
;
364+
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 3)
365+
tail call void @use(double %p1)
366+
%mul = fmul reassoc double %p1, %x
367+
ret double %mul
368+
}
369+
370+
; Negative test: Miss fmf flag
371+
define double @powi_fmul_powi_x_missing_reassoc(double noundef %x) {
372+
; CHECK-LABEL: @powi_fmul_powi_x_missing_reassoc(
373+
; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)
374+
; CHECK-NEXT: [[MUL:%.*]] = fmul double [[P1]], [[X]]
375+
; CHECK-NEXT: ret double [[MUL]]
376+
;
377+
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 3)
378+
%mul = fmul double %p1, %x
379+
ret double %mul
380+
}
381+
382+
; Negative test: overflow
383+
define double @powi_fmul_powi_x_overflow(double noundef %x) {
384+
; CHECK-LABEL: @powi_fmul_powi_x_overflow(
385+
; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 2147483647)
386+
; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]]
387+
; CHECK-NEXT: ret double [[MUL]]
388+
;
389+
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 2147483647) ; INT_MAX
390+
%mul = fmul reassoc double %p1, %x
391+
ret double %mul
392+
}

0 commit comments

Comments
 (0)