@@ -571,6 +571,44 @@ Instruction *InstCombinerImpl::foldFPSignBitOps(BinaryOperator &I) {
571
571
return nullptr ;
572
572
}
573
573
574
+ Instruction *InstCombinerImpl::foldPowiReassoc (BinaryOperator &I) {
575
+ Value *X, *Y, *Z;
576
+ auto createPowiExpr = [](BinaryOperator &I, InstCombinerImpl &IC, Value *X,
577
+ Value *Y, Value *Z) {
578
+ Value *YZ;
579
+ InstCombiner::BuilderTy &Builder = IC.Builder ;
580
+
581
+ if (auto *C = dyn_cast<ConstantInt>(Z)) {
582
+ if (C->isOne ())
583
+ YZ = Builder.CreateAdd (Y, ConstantInt::get (Y->getType (), 1 ));
584
+ } else
585
+ YZ = Builder.CreateAdd (Y, Z);
586
+
587
+ auto *NewPow = Builder.CreateIntrinsic (
588
+ Intrinsic::powi, {X->getType (), YZ->getType ()}, {X, YZ}, &I);
589
+ return IC.replaceInstUsesWith (I, NewPow);
590
+ };
591
+
592
+ // powi(X, Y) * X --> powi(X, Y+1)
593
+ // X * powi(X, Y) --> powi(X, Y+1)
594
+ if (match (&I, m_c_FMul (m_OneUse (m_Intrinsic<Intrinsic::powi>(m_Value (X),
595
+ m_Value (Y))),
596
+ m_Deferred (X))) &&
597
+ willNotOverflowSignedAdd (Y, ConstantInt::get (Y->getType (), 1 ), I))
598
+ return createPowiExpr (I, *this , X, Y, ConstantInt::get (Y->getType (), 1 ));
599
+
600
+ // powi(x, y) * powi(x, z) -> powi(x, y + z)
601
+ Value *Op0 = I.getOperand (0 );
602
+ Value *Op1 = I.getOperand (1 );
603
+ if (I.isOnlyUserOfAnyOperand () &&
604
+ match (Op0, m_Intrinsic<Intrinsic::powi>(m_Value (X), m_Value (Y))) &&
605
+ match (Op1, m_Intrinsic<Intrinsic::powi>(m_Specific (X), m_Value (Z))) &&
606
+ Y->getType () == Z->getType ())
607
+ return createPowiExpr (I, *this , X, Y, Z);
608
+
609
+ return nullptr ;
610
+ }
611
+
574
612
Instruction *InstCombinerImpl::foldFMulReassoc (BinaryOperator &I) {
575
613
Value *Op0 = I.getOperand (0 );
576
614
Value *Op1 = I.getOperand (1 );
@@ -683,17 +721,8 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) {
683
721
return replaceInstUsesWith (I, Pow);
684
722
}
685
723
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
- }
724
+ if (Instruction *FoldedPowi = foldPowiReassoc (I))
725
+ return FoldedPowi;
697
726
698
727
if (I.isOnlyUserOfAnyOperand ()) {
699
728
// pow(X, Y) * pow(X, Z) -> pow(X, Y + Z)
@@ -711,16 +740,6 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) {
711
740
return replaceInstUsesWith (I, NewPow);
712
741
}
713
742
714
- // powi(x, y) * powi(x, z) -> powi(x, y + z)
715
- if (match (Op0, m_Intrinsic<Intrinsic::powi>(m_Value (X), m_Value (Y))) &&
716
- match (Op1, m_Intrinsic<Intrinsic::powi>(m_Specific (X), m_Value (Z))) &&
717
- Y->getType () == Z->getType ()) {
718
- auto *YZ = Builder.CreateAdd (Y, Z);
719
- auto *NewPow = Builder.CreateIntrinsic (
720
- Intrinsic::powi, {X->getType (), YZ->getType ()}, {X, YZ}, &I);
721
- return replaceInstUsesWith (I, NewPow);
722
- }
723
-
724
743
// exp(X) * exp(Y) -> exp(X + Y)
725
744
if (match (Op0, m_Intrinsic<Intrinsic::exp>(m_Value (X))) &&
726
745
match (Op1, m_Intrinsic<Intrinsic::exp>(m_Value (Y)))) {
0 commit comments