Skip to content

Commit 25da8e5

Browse files
authored
Reapply "[LICM] Fold associative binary ops to promote code hoisting (#81608)" (#100377)
This reapplies a more strict version of f2ccf80. Perform the transformation "(LV op C1) op C2" ==> "LV op (C1 op C2)" where op is an associative binary op, LV is a loop variant, and C1 and C2 are loop invariants, and hoist (C1 op C2) into the preheader. For now this fold is restricted to ADDs.
1 parent 7a3bc44 commit 25da8e5

File tree

4 files changed

+459
-157
lines changed

4 files changed

+459
-157
lines changed

llvm/lib/Transforms/Scalar/LICM.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ STATISTIC(NumFPAssociationsHoisted, "Number of invariant FP expressions "
113113
STATISTIC(NumIntAssociationsHoisted,
114114
"Number of invariant int expressions "
115115
"reassociated and hoisted out of the loop");
116+
STATISTIC(NumBOAssociationsHoisted, "Number of invariant BinaryOp expressions "
117+
"reassociated and hoisted out of the loop");
116118

117119
/// Memory promotion is enabled by default.
118120
static cl::opt<bool>
@@ -2779,6 +2781,68 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L,
27792781
return true;
27802782
}
27812783

2784+
/// Reassociate associative binary expressions of the form
2785+
///
2786+
/// 1. "(LV op C1) op C2" ==> "LV op (C1 op C2)"
2787+
///
2788+
/// where op is an associative binary op, LV is a loop variant, and C1 and C2
2789+
/// are loop invariants that we want to hoist.
2790+
///
2791+
/// TODO: This can be extended to more cases such as
2792+
/// 2. "C1 op (C2 op LV)" ==> "(C1 op C2) op LV"
2793+
/// 3. "(C1 op LV) op C2" ==> "LV op (C1 op C2)" if op is commutative
2794+
/// 4. "C1 op (LV op C2)" ==> "(C1 op C2) op LV" if op is commutative
2795+
static bool hoistBOAssociation(Instruction &I, Loop &L,
2796+
ICFLoopSafetyInfo &SafetyInfo,
2797+
MemorySSAUpdater &MSSAU, AssumptionCache *AC,
2798+
DominatorTree *DT) {
2799+
auto *BO = dyn_cast<BinaryOperator>(&I);
2800+
if (!BO || !BO->isAssociative())
2801+
return false;
2802+
2803+
// Only fold ADDs for now.
2804+
Instruction::BinaryOps Opcode = BO->getOpcode();
2805+
if (Opcode != Instruction::Add)
2806+
return false;
2807+
2808+
auto *BO0 = dyn_cast<BinaryOperator>(BO->getOperand(0));
2809+
if (!BO0 || BO0->getOpcode() != Opcode || !BO0->isAssociative())
2810+
return false;
2811+
2812+
// Transform: "(LV op C1) op C2" ==> "LV op (C1 op C2)"
2813+
Value *LV = BO0->getOperand(0);
2814+
Value *C1 = BO0->getOperand(1);
2815+
Value *C2 = BO->getOperand(1);
2816+
2817+
if (L.isLoopInvariant(LV) || !L.isLoopInvariant(C1) || !L.isLoopInvariant(C2))
2818+
return false;
2819+
2820+
auto *Preheader = L.getLoopPreheader();
2821+
assert(Preheader && "Loop is not in simplify form?");
2822+
2823+
auto *Inv = BinaryOperator::Create(Opcode, C1, C2, "invariant.op",
2824+
Preheader->getTerminator());
2825+
auto *NewBO =
2826+
BinaryOperator::Create(Opcode, LV, Inv, BO->getName() + ".reass", BO);
2827+
2828+
// Copy NUW for ADDs if both instructions have it.
2829+
if (Opcode == Instruction::Add && BO->hasNoUnsignedWrap() &&
2830+
BO0->hasNoUnsignedWrap()) {
2831+
Inv->setHasNoUnsignedWrap(true);
2832+
NewBO->setHasNoUnsignedWrap(true);
2833+
}
2834+
2835+
BO->replaceAllUsesWith(NewBO);
2836+
eraseInstruction(*BO, SafetyInfo, MSSAU);
2837+
2838+
// (LV op C1) might not be erased if it has more uses than the one we just
2839+
// replaced.
2840+
if (BO0->use_empty())
2841+
eraseInstruction(*BO0, SafetyInfo, MSSAU);
2842+
2843+
return true;
2844+
}
2845+
27822846
static bool hoistArithmetics(Instruction &I, Loop &L,
27832847
ICFLoopSafetyInfo &SafetyInfo,
27842848
MemorySSAUpdater &MSSAU, AssumptionCache *AC,
@@ -2816,6 +2880,12 @@ static bool hoistArithmetics(Instruction &I, Loop &L,
28162880
return true;
28172881
}
28182882

2883+
if (hoistBOAssociation(I, L, SafetyInfo, MSSAU, AC, DT)) {
2884+
++NumHoisted;
2885+
++NumBOAssociationsHoisted;
2886+
return true;
2887+
}
2888+
28192889
return false;
28202890
}
28212891

0 commit comments

Comments
 (0)