@@ -2804,18 +2804,12 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L,
2804
2804
// / Reassociate binary expressions of the form
2805
2805
// /
2806
2806
// / 1. "(LV op C1) op C2" ==> "LV op (C1 op C2)" if op is an associative BinOp
2807
- // /
2808
- // / where LV is a loop variant, and C1 and C2 are loop invariants that we want
2809
- // / to hoist.
2810
- // /
2811
2807
// / 2. "(C1 op LV) op C2" ==> "LV op (C1 op C2)" if op is a commutative BinOp
2808
+ // / 3. "C2 op (C1 op LV)" ==> "(C2 op C1) op LV" if op an associative BinOp
2809
+ // / 4. "C2 op (LV op C1)" ==> "(C2 op C1) op LV" if op is a commutative BinOp
2812
2810
// /
2813
2811
// / where LV is a loop variant, and C1 and C2 are loop invariants that we want
2814
2812
// / to hoist.
2815
- // /
2816
- // / TODO: This can be extended to more cases such as
2817
- // / 1. "C1 op (C2 op LV)" ==> "(C1 op C2) op LV" if op an associative BinOp
2818
- // / 2. "C1 op (LV op C2)" ==> "(C1 op C2) op LV" if op is a commutative BinOp
2819
2813
static bool hoistBOAssociation (Instruction &I, Loop &L,
2820
2814
ICFLoopSafetyInfo &SafetyInfo,
2821
2815
MemorySSAUpdater &MSSAU, AssumptionCache *AC,
@@ -2829,21 +2823,24 @@ static bool hoistBOAssociation(Instruction &I, Loop &L,
2829
2823
if (Opcode != Instruction::Add && Opcode != Instruction::Mul)
2830
2824
return false ;
2831
2825
2832
- auto *BO0 = dyn_cast<BinaryOperator>(BO->getOperand (0 ));
2826
+ bool BinOpInRHS = isa<BinaryOperator>(BO->getOperand (1 ));
2827
+ auto *BO0 = dyn_cast<BinaryOperator>(BO->getOperand (BinOpInRHS));
2833
2828
if (!BO0 || BO0->getOpcode () != Opcode || BO0->hasNUsesOrMore (3 ))
2834
2829
return false ;
2835
2830
2836
2831
Value *LV = BO0->getOperand (0 );
2837
2832
Value *C1 = BO0->getOperand (1 );
2838
- Value *C2 = BO->getOperand (1 );
2833
+ Value *C2 = BO->getOperand (!BinOpInRHS );
2839
2834
2840
2835
if (!L.isLoopInvariant (C2))
2841
2836
return false ;
2837
+ bool BothAssociative = BO->isAssociative () && BO0->isAssociative ();
2838
+ bool BothCommutative = BO->isCommutative () && BO0->isCommutative ();
2842
2839
if (!L.isLoopInvariant (LV) && L.isLoopInvariant (C1)) {
2843
- if (!BO-> isAssociative ( ) || !BO0-> isAssociative ( ))
2840
+ if ((!BinOpInRHS && !BothAssociative ) || (BinOpInRHS && !BothCommutative ))
2844
2841
return false ;
2845
2842
} else if (L.isLoopInvariant (LV) && !L.isLoopInvariant (C1)) {
2846
- if (!BO-> isCommutative ( ) || !BO0-> isCommutative ( ))
2843
+ if ((!BinOpInRHS && !BothCommutative ) || (BinOpInRHS && !BothAssociative ))
2847
2844
return false ;
2848
2845
std::swap (LV, C1);
2849
2846
} else
@@ -2852,11 +2849,19 @@ static bool hoistBOAssociation(Instruction &I, Loop &L,
2852
2849
auto *Preheader = L.getLoopPreheader ();
2853
2850
assert (Preheader && " Loop is not in simplify form?" );
2854
2851
2852
+ // To create C2 op C1, instead of C1 op C2.
2853
+ if (BinOpInRHS)
2854
+ std::swap (C1, C2);
2855
+
2855
2856
IRBuilder<> Builder (Preheader->getTerminator ());
2856
2857
auto *Inv = Builder.CreateBinOp (Opcode, C1, C2, " invariant.op" );
2857
2858
2858
- auto *NewBO = BinaryOperator::Create (
2859
- Opcode, LV, Inv, BO->getName () + " .reass" , BO->getIterator ());
2859
+ auto *NewBO =
2860
+ BinOpInRHS
2861
+ ? BinaryOperator::Create (Opcode, Inv, LV, BO->getName () + " .reass" ,
2862
+ BO->getIterator ())
2863
+ : BinaryOperator::Create (Opcode, LV, Inv, BO->getName () + " .reass" ,
2864
+ BO->getIterator ());
2860
2865
2861
2866
// Copy NUW for ADDs if both instructions have it.
2862
2867
if (Opcode == Instruction::Add && BO->hasNoUnsignedWrap () &&
0 commit comments