@@ -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,31 @@ 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) {
2688
+ static bool hoistMulAddAssociation (Instruction &I, Loop &L,
2689
+ ICFLoopSafetyInfo &SafetyInfo,
2690
+ MemorySSAUpdater &MSSAU, AssumptionCache *AC,
2691
+ DominatorTree *DT) {
2673
2692
using namespace PatternMatch ;
2674
- Value *VariantOp = nullptr , *InvariantOp = nullptr ;
2675
2693
2676
- if (!match (&I, m_FMul (m_Value (VariantOp), m_Value (InvariantOp))) ||
2677
- !I.hasAllowReassoc () || !I.hasNoSignedZeros ())
2694
+ if (!isReassociableOp (&I, Instruction::Mul, Instruction::FMul))
2678
2695
return false ;
2696
+ Value *VariantOp = I.getOperand (0 );
2697
+ Value *InvariantOp = I.getOperand (1 );
2679
2698
if (L.isLoopInvariant (VariantOp))
2680
2699
std::swap (VariantOp, InvariantOp);
2681
2700
if (L.isLoopInvariant (VariantOp) || !L.isLoopInvariant (InvariantOp))
@@ -2689,15 +2708,17 @@ static bool hoistFPAssociation(Instruction &I, Loop &L,
2689
2708
Worklist.push_back (VariantBinOp);
2690
2709
while (!Worklist.empty ()) {
2691
2710
BinaryOperator *BO = Worklist.pop_back_val ();
2692
- if (!BO->hasOneUse () || !BO-> hasAllowReassoc () || !BO-> hasNoSignedZeros () )
2711
+ if (!BO->hasOneUse ())
2693
2712
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);
2713
+ if (isReassociableOp (BO, Instruction::Add, Instruction::FAdd) &&
2714
+ isa<BinaryOperator>(BO->getOperand (0 )) &&
2715
+ isa<BinaryOperator>(BO->getOperand (1 ))) {
2716
+ Worklist.push_back (cast<BinaryOperator>(BO->getOperand (0 )));
2717
+ Worklist.push_back (cast<BinaryOperator>(BO->getOperand (1 )));
2698
2718
continue ;
2699
2719
}
2700
- if (BO->getOpcode () != Instruction::FMul || L.isLoopInvariant (BO))
2720
+ if (!isReassociableOp (BO, Instruction::Mul, Instruction::FMul) ||
2721
+ L.isLoopInvariant (BO))
2701
2722
return false ;
2702
2723
Use &U0 = BO->getOperandUse (0 );
2703
2724
Use &U1 = BO->getOperandUse (1 );
@@ -2707,7 +2728,10 @@ static bool hoistFPAssociation(Instruction &I, Loop &L,
2707
2728
Changes.push_back (&U1);
2708
2729
else
2709
2730
return false ;
2710
- if (Changes.size () > FPAssociationUpperLimit)
2731
+ unsigned Limit = I.getType ()->isIntOrIntVectorTy ()
2732
+ ? IntAssociationUpperLimit
2733
+ : FPAssociationUpperLimit;
2734
+ if (Changes.size () > Limit)
2711
2735
return false ;
2712
2736
}
2713
2737
if (Changes.empty ())
@@ -2720,7 +2744,12 @@ static bool hoistFPAssociation(Instruction &I, Loop &L,
2720
2744
for (auto *U : Changes) {
2721
2745
assert (L.isLoopInvariant (U->get ()));
2722
2746
Instruction *Ins = cast<Instruction>(U->getUser ());
2723
- U->set (Builder.CreateFMulFMF (U->get (), Factor, Ins, " factor.op.fmul" ));
2747
+ Value *Mul;
2748
+ if (I.getType ()->isIntOrIntVectorTy ())
2749
+ Mul = Builder.CreateMul (U->get (), Factor, " factor.op.mul" );
2750
+ else
2751
+ Mul = Builder.CreateFMulFMF (U->get (), Factor, Ins, " factor.op.fmul" );
2752
+ U->set (Mul);
2724
2753
}
2725
2754
I.replaceAllUsesWith (VariantOp);
2726
2755
eraseInstruction (I, SafetyInfo, MSSAU);
@@ -2754,9 +2783,12 @@ static bool hoistArithmetics(Instruction &I, Loop &L,
2754
2783
return true ;
2755
2784
}
2756
2785
2757
- if (hoistFPAssociation (I, L, SafetyInfo, MSSAU, AC, DT)) {
2786
+ if (hoistMulAddAssociation (I, L, SafetyInfo, MSSAU, AC, DT)) {
2758
2787
++NumHoisted;
2759
- ++NumFPAssociationsHoisted;
2788
+ if (I.getType ()->isIntOrIntVectorTy ())
2789
+ ++NumIntAssociationsHoisted;
2790
+ else
2791
+ ++NumFPAssociationsHoisted;
2760
2792
return true ;
2761
2793
}
2762
2794
0 commit comments