forked from OSchip/llvm-project
[NARY-REASSOCIATE][NFC] Simplify min/max handling
In order to explore different variants of reassociation current implementation uses "swap in a loop" approach. Unfortunately, the implementation is more complicated than it could be. This is an attempt to streamline the code. New approach is to extract core functionality into a helper function and call it explicitly as many times as required. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D112128
This commit is contained in:
parent
36ec848dc7
commit
1a8ec24efb
|
@ -282,8 +282,12 @@ NaryReassociatePass::matchAndReassociateMinOrMax(Instruction *I,
|
||||||
m_Value(LHS), m_Value(RHS));
|
m_Value(LHS), m_Value(RHS));
|
||||||
if (match(I, MinMaxMatcher)) {
|
if (match(I, MinMaxMatcher)) {
|
||||||
OrigSCEV = SE->getSCEV(I);
|
OrigSCEV = SE->getSCEV(I);
|
||||||
return dyn_cast_or_null<Instruction>(
|
if (auto *NewMinMax = dyn_cast_or_null<Instruction>(
|
||||||
tryReassociateMinOrMax(I, MinMaxMatcher, LHS, RHS));
|
tryReassociateMinOrMax(I, MinMaxMatcher, LHS, RHS)))
|
||||||
|
return NewMinMax;
|
||||||
|
if (auto *NewMinMax = dyn_cast_or_null<Instruction>(
|
||||||
|
tryReassociateMinOrMax(I, MinMaxMatcher, RHS, LHS)))
|
||||||
|
return NewMinMax;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -596,61 +600,60 @@ Value *NaryReassociatePass::tryReassociateMinOrMax(Instruction *I,
|
||||||
Value *LHS, Value *RHS) {
|
Value *LHS, Value *RHS) {
|
||||||
Value *A = nullptr, *B = nullptr;
|
Value *A = nullptr, *B = nullptr;
|
||||||
MaxMinT m_MaxMin(m_Value(A), m_Value(B));
|
MaxMinT m_MaxMin(m_Value(A), m_Value(B));
|
||||||
for (unsigned int i = 0; i < 2; ++i) {
|
|
||||||
if (!LHS->hasNUsesOrMore(3) && match(LHS, m_MaxMin)) {
|
|
||||||
Value *C = RHS;
|
|
||||||
const SCEV *AExpr = SE->getSCEV(A), *BExpr = SE->getSCEV(B);
|
|
||||||
const SCEV *CExpr = SE->getSCEV(C);
|
|
||||||
for (unsigned int j = 0; j < 2; ++j) {
|
|
||||||
if (j == 0) {
|
|
||||||
if (BExpr == CExpr)
|
|
||||||
continue;
|
|
||||||
// Transform 'I = (A op B) op C' to 'I = (A op C) op B' on the
|
|
||||||
// first iteration.
|
|
||||||
std::swap(BExpr, CExpr);
|
|
||||||
std::swap(B, C);
|
|
||||||
} else {
|
|
||||||
if (AExpr == CExpr)
|
|
||||||
continue;
|
|
||||||
// Transform 'I = (A op C) op B' to 'I = (B op C) op A' on the second
|
|
||||||
// iteration.
|
|
||||||
std::swap(AExpr, CExpr);
|
|
||||||
std::swap(A, C);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The optimization is profitable only if LHS can be removed in the end.
|
if (LHS->hasNUsesOrMore(3) ||
|
||||||
// In other words LHS should be used (directly or indirectly) by I only.
|
// The optimization is profitable only if LHS can be removed in the end.
|
||||||
if (llvm::any_of(LHS->users(), [&](auto *U) {
|
// In other words LHS should be used (directly or indirectly) by I only.
|
||||||
return U != I && !(U->hasOneUser() && *U->users().begin() == I);
|
llvm::any_of(LHS->users(),
|
||||||
}))
|
[&](auto *U) {
|
||||||
continue;
|
return U != I &&
|
||||||
|
!(U->hasOneUser() && *U->users().begin() == I);
|
||||||
|
}) ||
|
||||||
|
!match(LHS, m_MaxMin))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
SCEVExpander Expander(*SE, *DL, "nary-reassociate");
|
auto tryCombination = [&](Value *A, const SCEV *AExpr, Value *B,
|
||||||
SmallVector<const SCEV *, 2> Ops1{ BExpr, AExpr };
|
const SCEV *BExpr, Value *C,
|
||||||
const SCEVTypes SCEVType = convertToSCEVype(m_MaxMin);
|
const SCEV *CExpr) -> Value * {
|
||||||
const SCEV *R1Expr = SE->getMinMaxExpr(SCEVType, Ops1);
|
SmallVector<const SCEV *, 2> Ops1{BExpr, AExpr};
|
||||||
|
const SCEVTypes SCEVType = convertToSCEVype(m_MaxMin);
|
||||||
|
const SCEV *R1Expr = SE->getMinMaxExpr(SCEVType, Ops1);
|
||||||
|
|
||||||
Instruction *R1MinMax = findClosestMatchingDominator(R1Expr, I);
|
Instruction *R1MinMax = findClosestMatchingDominator(R1Expr, I);
|
||||||
|
|
||||||
if (!R1MinMax)
|
if (!R1MinMax)
|
||||||
continue;
|
return nullptr;
|
||||||
|
|
||||||
LLVM_DEBUG(dbgs() << "NARY: Found common sub-expr: " << *R1MinMax
|
LLVM_DEBUG(dbgs() << "NARY: Found common sub-expr: " << *R1MinMax << "\n");
|
||||||
<< "\n");
|
|
||||||
|
|
||||||
SmallVector<const SCEV *, 2> Ops2{SE->getUnknown(C),
|
SmallVector<const SCEV *, 2> Ops2{SE->getUnknown(C),
|
||||||
SE->getUnknown(R1MinMax)};
|
SE->getUnknown(R1MinMax)};
|
||||||
const SCEV *R2Expr = SE->getMinMaxExpr(SCEVType, Ops2);
|
const SCEV *R2Expr = SE->getMinMaxExpr(SCEVType, Ops2);
|
||||||
|
|
||||||
Value *NewMinMax = Expander.expandCodeFor(R2Expr, I->getType(), I);
|
SCEVExpander Expander(*SE, *DL, "nary-reassociate");
|
||||||
NewMinMax->setName(Twine(I->getName()).concat(".nary"));
|
Value *NewMinMax = Expander.expandCodeFor(R2Expr, I->getType(), I);
|
||||||
|
NewMinMax->setName(Twine(I->getName()).concat(".nary"));
|
||||||
|
|
||||||
LLVM_DEBUG(dbgs() << "NARY: Deleting: " << *I << "\n"
|
LLVM_DEBUG(dbgs() << "NARY: Deleting: " << *I << "\n"
|
||||||
<< "NARY: Inserting: " << *NewMinMax << "\n");
|
<< "NARY: Inserting: " << *NewMinMax << "\n");
|
||||||
return NewMinMax;
|
return NewMinMax;
|
||||||
}
|
};
|
||||||
}
|
|
||||||
std::swap(LHS, RHS);
|
const SCEV *AExpr = SE->getSCEV(A);
|
||||||
|
const SCEV *BExpr = SE->getSCEV(B);
|
||||||
|
const SCEV *RHSExpr = SE->getSCEV(RHS);
|
||||||
|
|
||||||
|
if (BExpr != RHSExpr) {
|
||||||
|
// Try (A op RHS) op B
|
||||||
|
if (auto *NewMinMax = tryCombination(A, AExpr, RHS, RHSExpr, B, BExpr))
|
||||||
|
return NewMinMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (AExpr != RHSExpr) {
|
||||||
|
// Try (RHS op B) op A
|
||||||
|
if (auto *NewMinMax = tryCombination(RHS, RHSExpr, B, BExpr, A, AExpr))
|
||||||
|
return NewMinMax;
|
||||||
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue