[SCEV] Replace a struct with a function; NFC

We can do this now thanks to C++11 lambdas.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282515 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sanjoy Das 2016-09-27 18:01:48 +00:00
parent 9f114d87fc
commit e42a387356

View File

@ -448,180 +448,163 @@ bool SCEVUnknown::isOffsetOf(Type *&CTy, Constant *&FieldNo) const {
// SCEV Utilities // SCEV Utilities
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
namespace { // Return negative, zero, or positive, if LHS is less than, equal to, or greater
/// SCEVComplexityCompare - Return true if the complexity of the LHS is less // than RHS, respectively. A three-way result allows recursive comparisons to be
/// than the complexity of the RHS. This comparator is used to canonicalize // more efficient.
/// expressions. static int CompareSCEVComplexity(const LoopInfo *const LI, const SCEV *LHS,
class SCEVComplexityCompare { const SCEV *RHS) {
const LoopInfo *const LI; // Fast-path: SCEVs are uniqued so we can do a quick equality check.
public: if (LHS == RHS)
explicit SCEVComplexityCompare(const LoopInfo *li) : LI(li) {} return 0;
// Return true or false if LHS is less than, or at least RHS, respectively. // Primarily, sort the SCEVs by their getSCEVType().
bool operator()(const SCEV *LHS, const SCEV *RHS) const { unsigned LType = LHS->getSCEVType(), RType = RHS->getSCEVType();
return compare(LHS, RHS) < 0; if (LType != RType)
} return (int)LType - (int)RType;
// Return negative, zero, or positive, if LHS is less than, equal to, or // Aside from the getSCEVType() ordering, the particular ordering
// greater than RHS, respectively. A three-way result allows recursive // isn't very important except that it's beneficial to be consistent,
// comparisons to be more efficient. // so that (a + b) and (b + a) don't end up as different expressions.
int compare(const SCEV *LHS, const SCEV *RHS) const { switch (static_cast<SCEVTypes>(LType)) {
// Fast-path: SCEVs are uniqued so we can do a quick equality check. case scUnknown: {
if (LHS == RHS) const SCEVUnknown *LU = cast<SCEVUnknown>(LHS);
return 0; const SCEVUnknown *RU = cast<SCEVUnknown>(RHS);
// Primarily, sort the SCEVs by their getSCEVType(). // Sort SCEVUnknown values with some loose heuristics. TODO: This is
unsigned LType = LHS->getSCEVType(), RType = RHS->getSCEVType(); // not as complete as it could be.
if (LType != RType) const Value *LV = LU->getValue(), *RV = RU->getValue();
return (int)LType - (int)RType;
// Aside from the getSCEVType() ordering, the particular ordering // Order pointer values after integer values. This helps SCEVExpander
// isn't very important except that it's beneficial to be consistent, // form GEPs.
// so that (a + b) and (b + a) don't end up as different expressions. bool LIsPointer = LV->getType()->isPointerTy(),
switch (static_cast<SCEVTypes>(LType)) { RIsPointer = RV->getType()->isPointerTy();
case scUnknown: { if (LIsPointer != RIsPointer)
const SCEVUnknown *LU = cast<SCEVUnknown>(LHS); return (int)LIsPointer - (int)RIsPointer;
const SCEVUnknown *RU = cast<SCEVUnknown>(RHS);
// Sort SCEVUnknown values with some loose heuristics. TODO: This is // Compare getValueID values.
// not as complete as it could be. unsigned LID = LV->getValueID(), RID = RV->getValueID();
const Value *LV = LU->getValue(), *RV = RU->getValue(); if (LID != RID)
return (int)LID - (int)RID;
// Order pointer values after integer values. This helps SCEVExpander // Sort arguments by their position.
// form GEPs. if (const Argument *LA = dyn_cast<Argument>(LV)) {
bool LIsPointer = LV->getType()->isPointerTy(), const Argument *RA = cast<Argument>(RV);
RIsPointer = RV->getType()->isPointerTy(); unsigned LArgNo = LA->getArgNo(), RArgNo = RA->getArgNo();
if (LIsPointer != RIsPointer) return (int)LArgNo - (int)RArgNo;
return (int)LIsPointer - (int)RIsPointer;
// Compare getValueID values.
unsigned LID = LV->getValueID(),
RID = RV->getValueID();
if (LID != RID)
return (int)LID - (int)RID;
// Sort arguments by their position.
if (const Argument *LA = dyn_cast<Argument>(LV)) {
const Argument *RA = cast<Argument>(RV);
unsigned LArgNo = LA->getArgNo(), RArgNo = RA->getArgNo();
return (int)LArgNo - (int)RArgNo;
}
// For instructions, compare their loop depth, and their operand
// count. This is pretty loose.
if (const Instruction *LInst = dyn_cast<Instruction>(LV)) {
const Instruction *RInst = cast<Instruction>(RV);
// Compare loop depths.
const BasicBlock *LParent = LInst->getParent(),
*RParent = RInst->getParent();
if (LParent != RParent) {
unsigned LDepth = LI->getLoopDepth(LParent),
RDepth = LI->getLoopDepth(RParent);
if (LDepth != RDepth)
return (int)LDepth - (int)RDepth;
}
// Compare the number of operands.
unsigned LNumOps = LInst->getNumOperands(),
RNumOps = RInst->getNumOperands();
return (int)LNumOps - (int)RNumOps;
}
return 0;
} }
case scConstant: { // For instructions, compare their loop depth, and their operand
const SCEVConstant *LC = cast<SCEVConstant>(LHS); // count. This is pretty loose.
const SCEVConstant *RC = cast<SCEVConstant>(RHS); if (const Instruction *LInst = dyn_cast<Instruction>(LV)) {
const Instruction *RInst = cast<Instruction>(RV);
// Compare constant values. // Compare loop depths.
const APInt &LA = LC->getAPInt(); const BasicBlock *LParent = LInst->getParent(),
const APInt &RA = RC->getAPInt(); *RParent = RInst->getParent();
unsigned LBitWidth = LA.getBitWidth(), RBitWidth = RA.getBitWidth(); if (LParent != RParent) {
if (LBitWidth != RBitWidth) unsigned LDepth = LI->getLoopDepth(LParent),
return (int)LBitWidth - (int)RBitWidth; RDepth = LI->getLoopDepth(RParent);
return LA.ult(RA) ? -1 : 1;
}
case scAddRecExpr: {
const SCEVAddRecExpr *LA = cast<SCEVAddRecExpr>(LHS);
const SCEVAddRecExpr *RA = cast<SCEVAddRecExpr>(RHS);
// Compare addrec loop depths.
const Loop *LLoop = LA->getLoop(), *RLoop = RA->getLoop();
if (LLoop != RLoop) {
unsigned LDepth = LLoop->getLoopDepth(),
RDepth = RLoop->getLoopDepth();
if (LDepth != RDepth) if (LDepth != RDepth)
return (int)LDepth - (int)RDepth; return (int)LDepth - (int)RDepth;
} }
// Addrec complexity grows with operand count. // Compare the number of operands.
unsigned LNumOps = LA->getNumOperands(), RNumOps = RA->getNumOperands(); unsigned LNumOps = LInst->getNumOperands(),
if (LNumOps != RNumOps) RNumOps = RInst->getNumOperands();
return (int)LNumOps - (int)RNumOps;
// Lexicographically compare.
for (unsigned i = 0; i != LNumOps; ++i) {
long X = compare(LA->getOperand(i), RA->getOperand(i));
if (X != 0)
return X;
}
return 0;
}
case scAddExpr:
case scMulExpr:
case scSMaxExpr:
case scUMaxExpr: {
const SCEVNAryExpr *LC = cast<SCEVNAryExpr>(LHS);
const SCEVNAryExpr *RC = cast<SCEVNAryExpr>(RHS);
// Lexicographically compare n-ary expressions.
unsigned LNumOps = LC->getNumOperands(), RNumOps = RC->getNumOperands();
if (LNumOps != RNumOps)
return (int)LNumOps - (int)RNumOps;
for (unsigned i = 0; i != LNumOps; ++i) {
if (i >= RNumOps)
return 1;
long X = compare(LC->getOperand(i), RC->getOperand(i));
if (X != 0)
return X;
}
return (int)LNumOps - (int)RNumOps; return (int)LNumOps - (int)RNumOps;
} }
case scUDivExpr: { return 0;
const SCEVUDivExpr *LC = cast<SCEVUDivExpr>(LHS); }
const SCEVUDivExpr *RC = cast<SCEVUDivExpr>(RHS);
// Lexicographically compare udiv expressions. case scConstant: {
long X = compare(LC->getLHS(), RC->getLHS()); const SCEVConstant *LC = cast<SCEVConstant>(LHS);
const SCEVConstant *RC = cast<SCEVConstant>(RHS);
// Compare constant values.
const APInt &LA = LC->getAPInt();
const APInt &RA = RC->getAPInt();
unsigned LBitWidth = LA.getBitWidth(), RBitWidth = RA.getBitWidth();
if (LBitWidth != RBitWidth)
return (int)LBitWidth - (int)RBitWidth;
return LA.ult(RA) ? -1 : 1;
}
case scAddRecExpr: {
const SCEVAddRecExpr *LA = cast<SCEVAddRecExpr>(LHS);
const SCEVAddRecExpr *RA = cast<SCEVAddRecExpr>(RHS);
// Compare addrec loop depths.
const Loop *LLoop = LA->getLoop(), *RLoop = RA->getLoop();
if (LLoop != RLoop) {
unsigned LDepth = LLoop->getLoopDepth(), RDepth = RLoop->getLoopDepth();
if (LDepth != RDepth)
return (int)LDepth - (int)RDepth;
}
// Addrec complexity grows with operand count.
unsigned LNumOps = LA->getNumOperands(), RNumOps = RA->getNumOperands();
if (LNumOps != RNumOps)
return (int)LNumOps - (int)RNumOps;
// Lexicographically compare.
for (unsigned i = 0; i != LNumOps; ++i) {
long X = CompareSCEVComplexity(LI, LA->getOperand(i), RA->getOperand(i));
if (X != 0) if (X != 0)
return X; return X;
return compare(LC->getRHS(), RC->getRHS());
} }
case scTruncate: return 0;
case scZeroExtend:
case scSignExtend: {
const SCEVCastExpr *LC = cast<SCEVCastExpr>(LHS);
const SCEVCastExpr *RC = cast<SCEVCastExpr>(RHS);
// Compare cast expressions by operand.
return compare(LC->getOperand(), RC->getOperand());
}
case scCouldNotCompute:
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
}
llvm_unreachable("Unknown SCEV kind!");
} }
};
} // end anonymous namespace case scAddExpr:
case scMulExpr:
case scSMaxExpr:
case scUMaxExpr: {
const SCEVNAryExpr *LC = cast<SCEVNAryExpr>(LHS);
const SCEVNAryExpr *RC = cast<SCEVNAryExpr>(RHS);
// Lexicographically compare n-ary expressions.
unsigned LNumOps = LC->getNumOperands(), RNumOps = RC->getNumOperands();
if (LNumOps != RNumOps)
return (int)LNumOps - (int)RNumOps;
for (unsigned i = 0; i != LNumOps; ++i) {
if (i >= RNumOps)
return 1;
long X = CompareSCEVComplexity(LI, LC->getOperand(i), RC->getOperand(i));
if (X != 0)
return X;
}
return (int)LNumOps - (int)RNumOps;
}
case scUDivExpr: {
const SCEVUDivExpr *LC = cast<SCEVUDivExpr>(LHS);
const SCEVUDivExpr *RC = cast<SCEVUDivExpr>(RHS);
// Lexicographically compare udiv expressions.
long X = CompareSCEVComplexity(LI, LC->getLHS(), RC->getLHS());
if (X != 0)
return X;
return CompareSCEVComplexity(LI, LC->getRHS(), RC->getRHS());
}
case scTruncate:
case scZeroExtend:
case scSignExtend: {
const SCEVCastExpr *LC = cast<SCEVCastExpr>(LHS);
const SCEVCastExpr *RC = cast<SCEVCastExpr>(RHS);
// Compare cast expressions by operand.
return CompareSCEVComplexity(LI, LC->getOperand(), RC->getOperand());
}
case scCouldNotCompute:
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
}
llvm_unreachable("Unknown SCEV kind!");
}
/// Given a list of SCEV objects, order them by their complexity, and group /// Given a list of SCEV objects, order them by their complexity, and group
/// objects of the same complexity together by value. When this routine is /// objects of the same complexity together by value. When this routine is
@ -640,13 +623,16 @@ static void GroupByComplexity(SmallVectorImpl<const SCEV *> &Ops,
// This is the common case, which also happens to be trivially simple. // This is the common case, which also happens to be trivially simple.
// Special case it. // Special case it.
const SCEV *&LHS = Ops[0], *&RHS = Ops[1]; const SCEV *&LHS = Ops[0], *&RHS = Ops[1];
if (SCEVComplexityCompare(LI)(RHS, LHS)) if (CompareSCEVComplexity(LI, RHS, LHS) < 0)
std::swap(LHS, RHS); std::swap(LHS, RHS);
return; return;
} }
// Do the rough sort by complexity. // Do the rough sort by complexity.
std::stable_sort(Ops.begin(), Ops.end(), SCEVComplexityCompare(LI)); std::stable_sort(Ops.begin(), Ops.end(),
[LI](const SCEV *LHS, const SCEV *RHS) {
return CompareSCEVComplexity(LI, LHS, RHS) < 0;
});
// Now that we are sorted by complexity, group elements of the same // Now that we are sorted by complexity, group elements of the same
// complexity. Note that this is, at worst, N^2, but the vector is likely to // complexity. Note that this is, at worst, N^2, but the vector is likely to