if (Instruction *Mul = foldFDivPowDivisor(I, Builder))
return Mul;
+ // pow(X, Y) / X --> pow(X, Y-1)
+ if (I.hasAllowReassoc() &&
+ match(Op0, m_OneUse(m_Intrinsic<Intrinsic::pow>(m_Specific(Op1),
+ m_Value(Y))))) {
+ Value *Y1 =
+ Builder.CreateFAddFMF(Y, ConstantFP::get(I.getType(), -1.0), &I);
+ Value *Pow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, Op1, Y1, &I);
+ return replaceInstUsesWith(I, Pow);
+ }
+
return nullptr;
}
ret double %m
}
+; negative test for:
+; pow(a,b) * 1.0/a --> pow(a, b-1) (requires reassoc)
+
define double @pow_ab_recip_a(double %a, double %b) {
; CHECK-LABEL: @pow_ab_recip_a(
; CHECK-NEXT: [[R:%.*]] = fdiv double 1.000000e+00, [[A:%.*]]
ret double %m
}
+; pow(a,b) / a --> pow(a, b-1) (requires reassoc)
+
define double @pow_ab_recip_a_reassoc(double %a, double %b) {
; CHECK-LABEL: @pow_ab_recip_a_reassoc(
-; CHECK-NEXT: [[P:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
-; CHECK-NEXT: [[M:%.*]] = fdiv reassoc double [[P]], [[A]]
+; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], -1.000000e+00
+; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
; CHECK-NEXT: ret double [[M]]
;
%r = fdiv double 1.0, %a
ret double %m
}
+; pow(a,b) / a --> pow(a, b-1) (requires reassoc)
+
define double @pow_ab_recip_a_reassoc_commute(double %a, double %b) {
; CHECK-LABEL: @pow_ab_recip_a_reassoc_commute(
-; CHECK-NEXT: [[P:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
-; CHECK-NEXT: [[M:%.*]] = fdiv reassoc double [[P]], [[A]]
+; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], -1.000000e+00
+; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
; CHECK-NEXT: ret double [[M]]
;
%r = fdiv double 1.0, %a
ret double %m
}
+; TODO: extra use prevents conversion to fmul, so this needs a different pattern match.
+
define double @pow_ab_recip_a_reassoc_use1(double %a, double %b) {
; CHECK-LABEL: @pow_ab_recip_a_reassoc_use1(
; CHECK-NEXT: [[R:%.*]] = fdiv double 1.000000e+00, [[A:%.*]]
ret double %m
}
+; negative test - extra pow uses not allowed
+
define double @pow_ab_recip_a_reassoc_use2(double %a, double %b) {
; CHECK-LABEL: @pow_ab_recip_a_reassoc_use2(
; CHECK-NEXT: [[P:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
ret double %m
}
+; negative test - extra pow uses not allowed
+
define double @pow_ab_recip_a_reassoc_use3(double %a, double %b) {
; CHECK-LABEL: @pow_ab_recip_a_reassoc_use3(
; CHECK-NEXT: [[R:%.*]] = fdiv double 1.000000e+00, [[A:%.*]]