@@ -110,6 +110,9 @@ STATISTIC(NumAddSubHoisted, "Number of add/subtract expressions reassociated "
110
110
" and hoisted out of the loop" );
111
111
STATISTIC (NumFPAssociationsHoisted, " Number of invariant FP expressions "
112
112
" reassociated and hoisted out of the loop" );
113
+ STATISTIC (NumIntAssociationsHoisted,
114
+ " Number of invariant int expressions "
115
+ " reassociated and hoisted out of the loop" );
113
116
114
117
// / Memory promotion is enabled by default.
115
118
static cl::opt<bool >
@@ -135,6 +138,12 @@ static cl::opt<unsigned> FPAssociationUpperLimit(
135
138
" Set upper limit for the number of transformations performed "
136
139
" during a single round of hoisting the reassociated expressions." ));
137
140
141
+ cl::opt<unsigned > IntAssociationUpperLimit (
142
+ " licm-max-num-int-reassociations" , cl::init(5U ), cl::Hidden,
143
+ cl::desc(
144
+ " Set upper limit for the number of transformations performed "
145
+ " during a single round of hoisting the reassociated expressions." ));
146
+
138
147
// Experimental option to allow imprecision in LICM in pathological cases, in
139
148
// exchange for faster compile. This is to be removed if MemorySSA starts to
140
149
// address the same issue. LICM calls MemorySSAWalker's
@@ -2661,21 +2670,29 @@ static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
2661
2670
return false ;
2662
2671
}
2663
2672
2673
+ static bool isReassociableOp (Instruction *I, unsigned IntOpcode,
2674
+ unsigned FPOpcode) {
2675
+ if (I->getOpcode () == IntOpcode)
2676
+ return true ;
2677
+ if (I->getOpcode () == FPOpcode && I->hasAllowReassoc () &&
2678
+ I->hasNoSignedZeros ())
2679
+ return true ;
2680
+ return false ;
2681
+ }
2682
+
2664
2683
// / Try to reassociate expressions like ((A1 * B1) + (A2 * B2) + ...) * C where
2665
2684
// / A1, A2, ... and C are loop invariants into expressions like
2666
2685
// / ((A1 * C * B1) + (A2 * C * B2) + ...) and hoist the (A1 * C), (A2 * C), ...
2667
2686
// / invariant expressions. This functions returns true only if any hoisting has
2668
2687
// / actually occured.
2669
- static bool hoistFPAssociation (Instruction &I, Loop &L,
2670
- ICFLoopSafetyInfo &SafetyInfo,
2671
- MemorySSAUpdater &MSSAU, AssumptionCache *AC,
2672
- DominatorTree *DT) {
2673
- using namespace PatternMatch ;
2674
- Value *VariantOp = nullptr , *InvariantOp = nullptr ;
2675
-
2676
- if (!match (&I, m_FMul (m_Value (VariantOp), m_Value (InvariantOp))) ||
2677
- !I.hasAllowReassoc () || !I.hasNoSignedZeros ())
2688
+ static bool hoistMulAddAssociation (Instruction &I, Loop &L,
2689
+ ICFLoopSafetyInfo &SafetyInfo,
2690
+ MemorySSAUpdater &MSSAU, AssumptionCache *AC,
2691
+ DominatorTree *DT) {
2692
+ if (!isReassociableOp (&I, Instruction::Mul, Instruction::FMul))
2678
2693
return false ;
2694
+ Value *VariantOp = I.getOperand (0 );
2695
+ Value *InvariantOp = I.getOperand (1 );
2679
2696
if (L.isLoopInvariant (VariantOp))
2680
2697
std::swap (VariantOp, InvariantOp);
2681
2698
if (L.isLoopInvariant (VariantOp) || !L.isLoopInvariant (InvariantOp))
@@ -2689,15 +2706,17 @@ static bool hoistFPAssociation(Instruction &I, Loop &L,
2689
2706
Worklist.push_back (VariantBinOp);
2690
2707
while (!Worklist.empty ()) {
2691
2708
BinaryOperator *BO = Worklist.pop_back_val ();
2692
- if (!BO->hasOneUse () || !BO-> hasAllowReassoc () || !BO-> hasNoSignedZeros () )
2709
+ if (!BO->hasOneUse ())
2693
2710
return false ;
2694
- BinaryOperator *Op0, *Op1;
2695
- if (match (BO, m_FAdd (m_BinOp (Op0), m_BinOp (Op1)))) {
2696
- Worklist.push_back (Op0);
2697
- Worklist.push_back (Op1);
2711
+ if (isReassociableOp (BO, Instruction::Add, Instruction::FAdd) &&
2712
+ isa<BinaryOperator>(BO->getOperand (0 )) &&
2713
+ isa<BinaryOperator>(BO->getOperand (1 ))) {
2714
+ Worklist.push_back (cast<BinaryOperator>(BO->getOperand (0 )));
2715
+ Worklist.push_back (cast<BinaryOperator>(BO->getOperand (1 )));
2698
2716
continue ;
2699
2717
}
2700
- if (BO->getOpcode () != Instruction::FMul || L.isLoopInvariant (BO))
2718
+ if (!isReassociableOp (BO, Instruction::Mul, Instruction::FMul) ||
2719
+ L.isLoopInvariant (BO))
2701
2720
return false ;
2702
2721
Use &U0 = BO->getOperandUse (0 );
2703
2722
Use &U1 = BO->getOperandUse (1 );
@@ -2707,7 +2726,10 @@ static bool hoistFPAssociation(Instruction &I, Loop &L,
2707
2726
Changes.push_back (&U1);
2708
2727
else
2709
2728
return false ;
2710
- if (Changes.size () > FPAssociationUpperLimit)
2729
+ unsigned Limit = I.getType ()->isIntOrIntVectorTy ()
2730
+ ? IntAssociationUpperLimit
2731
+ : FPAssociationUpperLimit;
2732
+ if (Changes.size () > Limit)
2711
2733
return false ;
2712
2734
}
2713
2735
if (Changes.empty ())
@@ -2720,7 +2742,12 @@ static bool hoistFPAssociation(Instruction &I, Loop &L,
2720
2742
for (auto *U : Changes) {
2721
2743
assert (L.isLoopInvariant (U->get ()));
2722
2744
Instruction *Ins = cast<Instruction>(U->getUser ());
2723
- U->set (Builder.CreateFMulFMF (U->get (), Factor, Ins, " factor.op.fmul" ));
2745
+ Value *Mul;
2746
+ if (I.getType ()->isIntOrIntVectorTy ())
2747
+ Mul = Builder.CreateMul (U->get (), Factor, " factor.op.mul" );
2748
+ else
2749
+ Mul = Builder.CreateFMulFMF (U->get (), Factor, Ins, " factor.op.fmul" );
2750
+ U->set (Mul);
2724
2751
}
2725
2752
I.replaceAllUsesWith (VariantOp);
2726
2753
eraseInstruction (I, SafetyInfo, MSSAU);
@@ -2754,9 +2781,13 @@ static bool hoistArithmetics(Instruction &I, Loop &L,
2754
2781
return true ;
2755
2782
}
2756
2783
2757
- if (hoistFPAssociation (I, L, SafetyInfo, MSSAU, AC, DT)) {
2784
+ bool IsInt = I.getType ()->isIntOrIntVectorTy ();
2785
+ if (hoistMulAddAssociation (I, L, SafetyInfo, MSSAU, AC, DT)) {
2758
2786
++NumHoisted;
2759
- ++NumFPAssociationsHoisted;
2787
+ if (IsInt)
2788
+ ++NumIntAssociationsHoisted;
2789
+ else
2790
+ ++NumFPAssociationsHoisted;
2760
2791
return true ;
2761
2792
}
2762
2793
0 commit comments