Changeset View
Changeset View
Standalone View
Standalone View
lib/Analysis/ScalarEvolution.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 2,201 Lines • ▼ Show 20 Lines | static uint64_t Choose(uint64_t n, uint64_t k, bool &Overflow) { | ||||
uint64_t r = 1; | uint64_t r = 1; | ||||
for (uint64_t i = 1; i <= k; ++i) { | for (uint64_t i = 1; i <= k; ++i) { | ||||
r = umul_ov(r, n-(i-1), Overflow); | r = umul_ov(r, n-(i-1), Overflow); | ||||
r /= i; | r /= i; | ||||
} | } | ||||
return r; | return r; | ||||
} | } | ||||
/// Determine if any of the operands in this SCEV are a constant or if | |||||
nlewycky: I forget; are expr's guaranteed to be "GroupByComplexity"'d? If so, ContainsConstantSomewhere… | |||||
/// any of the add or multiply expressions in this SCEV contain a constant. | |||||
static bool ContainsConstantSomewhere(const SCEV* Expr) { | |||||
majnemerUnsubmitted Not Done ReplyInline ActionsPlease give this function a name that starts with a lower case letter. Also, pointers bind to the variable name. majnemer: Please give this function a name that starts with a lower case letter. Also, pointers bind to… | |||||
Not Done ReplyInline Actions"SCEV* StartExpr" should be "SCEV *StartExpr". nlewycky: "SCEV* StartExpr" should be "SCEV *StartExpr". | |||||
if (isa<SCEVConstant>(Expr)) | |||||
return true; | |||||
const SCEVNAryExpr * Target = dyn_cast<const SCEVNAryExpr>(Expr); | |||||
majnemerUnsubmitted Not Done ReplyInline ActionsIt's more natural in LLVM to write: const auto *Target = dyn_cast<SCEVNAryExpr>(Expr); majnemer: It's more natural in LLVM to write:
const auto *Target = dyn_cast<SCEVNAryExpr>(Expr); | |||||
if (!Target) | |||||
return false; | |||||
for (auto Operand = Target->op_begin(), | |||||
E = Target->op_end(); Operand != E; ++Operand) | |||||
majnemerUnsubmitted Not Done ReplyInline ActionsThis would probably read easier as: for (const SCEV *Operand : Target->operands()) majnemer: This would probably read easier as:
for (const SCEV *Operand : Target->operands()) | |||||
Not Done ReplyInline ActionsThis cast is guaranteed to succeed because of the if isa's above. Use cast<> instead of dyn_cast<>. nlewycky: This cast is guaranteed to succeed because of the if isa's above. Use cast<> instead of… | |||||
if ((isa<SCEVAddExpr>(*Operand)) || (isa<SCEVMulExpr>(*Operand))) { | |||||
majnemerUnsubmitted Not Done ReplyInline ActionsThese extra parens look strange. majnemer: These extra parens look strange. | |||||
if (ContainsConstantSomewhere(*Operand)) | |||||
return true; | |||||
} else if (isa<SCEVConstant>(*Operand)) { | |||||
return true; | |||||
} | |||||
majnemerUnsubmitted Not Done ReplyInline ActionsI think this would look a little more natural: for (const SCEV *Operand : Target->operands()) { if (isa<SCEVConstant>(*Operand)) return true; if (isa<SCEVAddExpr>(*Operand) || isa<SCEVMulExpr>(*Operand)) if (containsConstantSomewhere(*Operand)) return true; } majnemer: I think this would look a little more natural:
for (const SCEV *Operand : Target->operands… | |||||
return false; | |||||
} | |||||
/// getMulExpr - Get a canonical multiply expression, or something simpler if | /// getMulExpr - Get a canonical multiply expression, or something simpler if | ||||
/// possible. | /// possible. | ||||
const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops, | const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops, | ||||
SCEV::NoWrapFlags Flags) { | SCEV::NoWrapFlags Flags) { | ||||
assert(Flags == maskFlags(Flags, SCEV::FlagNUW | SCEV::FlagNSW) && | assert(Flags == maskFlags(Flags, SCEV::FlagNUW | SCEV::FlagNSW) && | ||||
"only nuw or nsw allowed"); | "only nuw or nsw allowed"); | ||||
assert(!Ops.empty() && "Cannot get empty mul!"); | assert(!Ops.empty() && "Cannot get empty mul!"); | ||||
if (Ops.size() == 1) return Ops[0]; | if (Ops.size() == 1) return Ops[0]; | ||||
Show All 23 Lines | #endif | ||||
GroupByComplexity(Ops, LI); | GroupByComplexity(Ops, LI); | ||||
// If there are any constants, fold them together. | // If there are any constants, fold them together. | ||||
unsigned Idx = 0; | unsigned Idx = 0; | ||||
if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(Ops[0])) { | if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(Ops[0])) { | ||||
// C1*(C2+V) -> C1*C2 + C1*V | // C1*(C2+V) -> C1*C2 + C1*V | ||||
if (Ops.size() == 2) | if (Ops.size() == 2) | ||||
if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[1])) | if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[1])) | ||||
if (Add->getNumOperands() == 2 && | // if any of Add's ops are Adds or Muls with a constant | ||||
isa<SCEVConstant>(Add->getOperand(0))) | // then apply this transformation as well | ||||
nlewyckyUnsubmitted Not Done ReplyInline ActionsCapitalize 'If', remove extra space before 'then'. nlewycky: Capitalize 'If', remove extra space before 'then'. | |||||
if (Add->getNumOperands() == 2) | |||||
if (ContainsConstantSomewhere(Add)) | |||||
return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)), | return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)), | ||||
getMulExpr(LHSC, Add->getOperand(1))); | getMulExpr(LHSC, Add->getOperand(1))); | ||||
++Idx; | ++Idx; | ||||
while (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(Ops[Idx])) { | while (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(Ops[Idx])) { | ||||
// We found two constants, fold them together! | // We found two constants, fold them together! | ||||
ConstantInt *Fold = ConstantInt::get(getContext(), | ConstantInt *Fold = ConstantInt::get(getContext(), | ||||
LHSC->getValue()->getValue() * | LHSC->getValue()->getValue() * | ||||
RHSC->getValue()->getValue()); | RHSC->getValue()->getValue()); | ||||
Ops[0] = getConstant(Fold); | Ops[0] = getConstant(Fold); | ||||
▲ Show 20 Lines • Show All 6,020 Lines • Show Last 20 Lines |
I forget; are expr's guaranteed to be "GroupByComplexity"'d? If so, ContainsConstantSomewhere can be optimized greatly. If there's any constant, it's guaranteed to be in a group at the end. You only recurse on Add and Mul, so if you've gone past those (to umax, smax, unknown or could-not-compute, you can stop).
Also, please iterate with a worklist instead of recursing. Create a SmallVector<SCEV*>, push your starting element into it, use pop_back_val to grab the latest one off the top of the list. If you're worried about revisiting the same thing multiple times, add a SmallSet<SCEV*> and test whether inserting the new element succeeds -- if it doesn't, it's already in the set.