}
if (I.isOnlyUserOfAnyOperand()) {
- // pow(x, y) * pow(x, z) -> pow(x, y + z)
+ // pow(X, Y) * pow(X, Z) -> pow(X, Y + Z)
if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))) &&
match(Op1, m_Intrinsic<Intrinsic::pow>(m_Specific(X), m_Value(Z)))) {
auto *YZ = Builder.CreateFAddFMF(Y, Z, &I);
auto *NewPow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, X, YZ, &I);
return replaceInstUsesWith(I, NewPow);
}
+ // pow(X, Y) * pow(Z, Y) -> pow(X * Z, Y)
+ if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))) &&
+ match(Op1, m_Intrinsic<Intrinsic::pow>(m_Value(Z), m_Specific(Y)))) {
+ auto *XZ = Builder.CreateFMulFMF(X, Z, &I);
+ auto *NewPow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, XZ, Y, &I);
+ return replaceInstUsesWith(I, NewPow);
+ }
// powi(x, y) * powi(x, z) -> powi(x, y + z)
if (match(Op0, m_Intrinsic<Intrinsic::powi>(m_Value(X), m_Value(Y))) &&
ret double %mul
}
+; negative test for:
+; (a**b) * (c**b) --> (a*c) ** b (if mul is reassoc)
+
define double @pow_ab_pow_cb(double %a, double %b, double %c) {
; CHECK-LABEL: @pow_ab_pow_cb(
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
ret double %mul
}
+; (a**b) * (c**b) --> (a*c) ** b
+
define double @pow_ab_pow_cb_reassoc(double %a, double %b, double %c) {
; CHECK-LABEL: @pow_ab_pow_cb_reassoc(
-; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
-; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[C:%.*]], double [[B]])
-; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[TMP2]], [[TMP1]]
+; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[C:%.*]], [[A:%.*]]
+; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[TMP1]], double [[B:%.*]])
; CHECK-NEXT: ret double [[MUL]]
;
%1 = call double @llvm.pow.f64(double %a, double %b)
ret double %mul
}
+; (a**b) * (c**b) --> (a*c) ** b
+
define double @pow_ab_pow_cb_reassoc_use1(double %a, double %b, double %c) {
; CHECK-LABEL: @pow_ab_pow_cb_reassoc_use1(
; CHECK-NEXT: [[AB:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
-; CHECK-NEXT: [[CB:%.*]] = call double @llvm.pow.f64(double [[C:%.*]], double [[B]])
-; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[AB]], [[CB]]
+; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[A]], [[C:%.*]]
+; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[TMP1]], double [[B]])
; CHECK-NEXT: call void @use(double [[AB]])
; CHECK-NEXT: ret double [[MUL]]
;
ret double %mul
}
+; (a**b) * (c**b) --> (a*c) ** b
+
define double @pow_ab_pow_cb_reassoc_use2(double %a, double %b, double %c) {
; CHECK-LABEL: @pow_ab_pow_cb_reassoc_use2(
-; CHECK-NEXT: [[AB:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
-; CHECK-NEXT: [[CB:%.*]] = call double @llvm.pow.f64(double [[C:%.*]], double [[B]])
-; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[AB]], [[CB]]
+; CHECK-NEXT: [[CB:%.*]] = call double @llvm.pow.f64(double [[C:%.*]], double [[B:%.*]])
+; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[A:%.*]], [[C]]
+; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[TMP1]], double [[B]])
; CHECK-NEXT: call void @use(double [[CB]])
; CHECK-NEXT: ret double [[MUL]]
;
ret double %mul
}
+; negative test - too many extra uses
+
define double @pow_ab_pow_cb_reassoc_use3(double %a, double %b, double %c) {
; CHECK-LABEL: @pow_ab_pow_cb_reassoc_use3(
; CHECK-NEXT: [[AB:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])