123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770 |
- #include "polly/Support/SCEVValidator.h"
- #include "polly/ScopDetection.h"
- #include "llvm/Analysis/RegionInfo.h"
- #include "llvm/Analysis/ScalarEvolution.h"
- #include "llvm/Analysis/ScalarEvolutionExpressions.h"
- #include "llvm/Support/Debug.h"
- using namespace llvm;
- using namespace polly;
- #define DEBUG_TYPE "polly-scev-validator"
- namespace SCEVType {
- /// The type of a SCEV
- ///
- /// To check for the validity of a SCEV we assign to each SCEV a type. The
- /// possible types are INT, PARAM, IV and INVALID. The order of the types is
- /// important. The subexpressions of SCEV with a type X can only have a type
- /// that is smaller or equal than X.
- enum TYPE {
- // An integer value.
- INT,
- // An expression that is constant during the execution of the Scop,
- // but that may depend on parameters unknown at compile time.
- PARAM,
- // An expression that may change during the execution of the SCoP.
- IV,
- // An invalid expression.
- INVALID
- };
- } // namespace SCEVType
- /// The result the validator returns for a SCEV expression.
- class ValidatorResult {
- /// The type of the expression
- SCEVType::TYPE Type;
- /// The set of Parameters in the expression.
- ParameterSetTy Parameters;
- public:
- /// The copy constructor
- ValidatorResult(const ValidatorResult &Source) {
- Type = Source.Type;
- Parameters = Source.Parameters;
- }
- /// Construct a result with a certain type and no parameters.
- ValidatorResult(SCEVType::TYPE Type) : Type(Type) {
- assert(Type != SCEVType::PARAM && "Did you forget to pass the parameter");
- }
- /// Construct a result with a certain type and a single parameter.
- ValidatorResult(SCEVType::TYPE Type, const SCEV *Expr) : Type(Type) {
- Parameters.insert(Expr);
- }
- /// Get the type of the ValidatorResult.
- SCEVType::TYPE getType() { return Type; }
- /// Is the analyzed SCEV constant during the execution of the SCoP.
- bool isConstant() { return Type == SCEVType::INT || Type == SCEVType::PARAM; }
- /// Is the analyzed SCEV valid.
- bool isValid() { return Type != SCEVType::INVALID; }
- /// Is the analyzed SCEV of Type IV.
- bool isIV() { return Type == SCEVType::IV; }
- /// Is the analyzed SCEV of Type INT.
- bool isINT() { return Type == SCEVType::INT; }
- /// Is the analyzed SCEV of Type PARAM.
- bool isPARAM() { return Type == SCEVType::PARAM; }
- /// Get the parameters of this validator result.
- const ParameterSetTy &getParameters() { return Parameters; }
- /// Add the parameters of Source to this result.
- void addParamsFrom(const ValidatorResult &Source) {
- Parameters.insert(Source.Parameters.begin(), Source.Parameters.end());
- }
- /// Merge a result.
- ///
- /// This means to merge the parameters and to set the Type to the most
- /// specific Type that matches both.
- void merge(const ValidatorResult &ToMerge) {
- Type = std::max(Type, ToMerge.Type);
- addParamsFrom(ToMerge);
- }
- void print(raw_ostream &OS) {
- switch (Type) {
- case SCEVType::INT:
- OS << "SCEVType::INT";
- break;
- case SCEVType::PARAM:
- OS << "SCEVType::PARAM";
- break;
- case SCEVType::IV:
- OS << "SCEVType::IV";
- break;
- case SCEVType::INVALID:
- OS << "SCEVType::INVALID";
- break;
- }
- }
- };
- raw_ostream &operator<<(raw_ostream &OS, class ValidatorResult &VR) {
- VR.print(OS);
- return OS;
- }
- /// Check if a SCEV is valid in a SCoP.
- struct SCEVValidator
- : public SCEVVisitor<SCEVValidator, class ValidatorResult> {
- private:
- const Region *R;
- Loop *Scope;
- ScalarEvolution &SE;
- InvariantLoadsSetTy *ILS;
- public:
- SCEVValidator(const Region *R, Loop *Scope, ScalarEvolution &SE,
- InvariantLoadsSetTy *ILS)
- : R(R), Scope(Scope), SE(SE), ILS(ILS) {}
- class ValidatorResult visitConstant(const SCEVConstant *Constant) {
- return ValidatorResult(SCEVType::INT);
- }
- class ValidatorResult visitZeroExtendOrTruncateExpr(const SCEV *Expr,
- const SCEV *Operand) {
- ValidatorResult Op = visit(Operand);
- auto Type = Op.getType();
- // If unsigned operations are allowed return the operand, otherwise
- // check if we can model the expression without unsigned assumptions.
- if (PollyAllowUnsignedOperations || Type == SCEVType::INVALID)
- return Op;
- if (Type == SCEVType::IV)
- return ValidatorResult(SCEVType::INVALID);
- return ValidatorResult(SCEVType::PARAM, Expr);
- }
- class ValidatorResult visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
- return visit(Expr->getOperand());
- }
- class ValidatorResult visitTruncateExpr(const SCEVTruncateExpr *Expr) {
- return visitZeroExtendOrTruncateExpr(Expr, Expr->getOperand());
- }
- class ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
- return visitZeroExtendOrTruncateExpr(Expr, Expr->getOperand());
- }
- class ValidatorResult visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
- return visit(Expr->getOperand());
- }
- class ValidatorResult visitAddExpr(const SCEVAddExpr *Expr) {
- ValidatorResult Return(SCEVType::INT);
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
- ValidatorResult Op = visit(Expr->getOperand(i));
- Return.merge(Op);
- // Early exit.
- if (!Return.isValid())
- break;
- }
- return Return;
- }
- class ValidatorResult visitMulExpr(const SCEVMulExpr *Expr) {
- ValidatorResult Return(SCEVType::INT);
- bool HasMultipleParams = false;
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
- ValidatorResult Op = visit(Expr->getOperand(i));
- if (Op.isINT())
- continue;
- if (Op.isPARAM() && Return.isPARAM()) {
- HasMultipleParams = true;
- continue;
- }
- if ((Op.isIV() || Op.isPARAM()) && !Return.isINT()) {
- LLVM_DEBUG(
- dbgs() << "INVALID: More than one non-int operand in MulExpr\n"
- << "\tExpr: " << *Expr << "\n"
- << "\tPrevious expression type: " << Return << "\n"
- << "\tNext operand (" << Op << "): " << *Expr->getOperand(i)
- << "\n");
- return ValidatorResult(SCEVType::INVALID);
- }
- Return.merge(Op);
- }
- if (HasMultipleParams && Return.isValid())
- return ValidatorResult(SCEVType::PARAM, Expr);
- return Return;
- }
- class ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr) {
- if (!Expr->isAffine()) {
- LLVM_DEBUG(dbgs() << "INVALID: AddRec is not affine");
- return ValidatorResult(SCEVType::INVALID);
- }
- ValidatorResult Start = visit(Expr->getStart());
- ValidatorResult Recurrence = visit(Expr->getStepRecurrence(SE));
- if (!Start.isValid())
- return Start;
- if (!Recurrence.isValid())
- return Recurrence;
- auto *L = Expr->getLoop();
- if (R->contains(L) && (!Scope || !L->contains(Scope))) {
- LLVM_DEBUG(
- dbgs() << "INVALID: Loop of AddRec expression boxed in an a "
- "non-affine subregion or has a non-synthesizable exit "
- "value.");
- return ValidatorResult(SCEVType::INVALID);
- }
- if (R->contains(L)) {
- if (Recurrence.isINT()) {
- ValidatorResult Result(SCEVType::IV);
- Result.addParamsFrom(Start);
- return Result;
- }
- LLVM_DEBUG(dbgs() << "INVALID: AddRec within scop has non-int"
- "recurrence part");
- return ValidatorResult(SCEVType::INVALID);
- }
- assert(Recurrence.isConstant() && "Expected 'Recurrence' to be constant");
- // Directly generate ValidatorResult for Expr if 'start' is zero.
- if (Expr->getStart()->isZero())
- return ValidatorResult(SCEVType::PARAM, Expr);
- // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}'
- // if 'start' is not zero.
- const SCEV *ZeroStartExpr = SE.getAddRecExpr(
- SE.getConstant(Expr->getStart()->getType(), 0),
- Expr->getStepRecurrence(SE), Expr->getLoop(), Expr->getNoWrapFlags());
- ValidatorResult ZeroStartResult =
- ValidatorResult(SCEVType::PARAM, ZeroStartExpr);
- ZeroStartResult.addParamsFrom(Start);
- return ZeroStartResult;
- }
- class ValidatorResult visitSMaxExpr(const SCEVSMaxExpr *Expr) {
- ValidatorResult Return(SCEVType::INT);
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
- ValidatorResult Op = visit(Expr->getOperand(i));
- if (!Op.isValid())
- return Op;
- Return.merge(Op);
- }
- return Return;
- }
- class ValidatorResult visitSMinExpr(const SCEVSMinExpr *Expr) {
- ValidatorResult Return(SCEVType::INT);
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
- ValidatorResult Op = visit(Expr->getOperand(i));
- if (!Op.isValid())
- return Op;
- Return.merge(Op);
- }
- return Return;
- }
- class ValidatorResult visitUMaxExpr(const SCEVUMaxExpr *Expr) {
- // We do not support unsigned max operations. If 'Expr' is constant during
- // Scop execution we treat this as a parameter, otherwise we bail out.
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
- ValidatorResult Op = visit(Expr->getOperand(i));
- if (!Op.isConstant()) {
- LLVM_DEBUG(dbgs() << "INVALID: UMaxExpr has a non-constant operand");
- return ValidatorResult(SCEVType::INVALID);
- }
- }
- return ValidatorResult(SCEVType::PARAM, Expr);
- }
- class ValidatorResult visitUMinExpr(const SCEVUMinExpr *Expr) {
- // We do not support unsigned min operations. If 'Expr' is constant during
- // Scop execution we treat this as a parameter, otherwise we bail out.
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
- ValidatorResult Op = visit(Expr->getOperand(i));
- if (!Op.isConstant()) {
- LLVM_DEBUG(dbgs() << "INVALID: UMinExpr has a non-constant operand");
- return ValidatorResult(SCEVType::INVALID);
- }
- }
- return ValidatorResult(SCEVType::PARAM, Expr);
- }
- class ValidatorResult
- visitSequentialUMinExpr(const SCEVSequentialUMinExpr *Expr) {
- // We do not support unsigned min operations. If 'Expr' is constant during
- // Scop execution we treat this as a parameter, otherwise we bail out.
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
- ValidatorResult Op = visit(Expr->getOperand(i));
- if (!Op.isConstant()) {
- LLVM_DEBUG(
- dbgs()
- << "INVALID: SCEVSequentialUMinExpr has a non-constant operand");
- return ValidatorResult(SCEVType::INVALID);
- }
- }
- return ValidatorResult(SCEVType::PARAM, Expr);
- }
- ValidatorResult visitGenericInst(Instruction *I, const SCEV *S) {
- if (R->contains(I)) {
- LLVM_DEBUG(dbgs() << "INVALID: UnknownExpr references an instruction "
- "within the region\n");
- return ValidatorResult(SCEVType::INVALID);
- }
- return ValidatorResult(SCEVType::PARAM, S);
- }
- ValidatorResult visitLoadInstruction(Instruction *I, const SCEV *S) {
- if (R->contains(I) && ILS) {
- ILS->insert(cast<LoadInst>(I));
- return ValidatorResult(SCEVType::PARAM, S);
- }
- return visitGenericInst(I, S);
- }
- ValidatorResult visitDivision(const SCEV *Dividend, const SCEV *Divisor,
- const SCEV *DivExpr,
- Instruction *SDiv = nullptr) {
- // First check if we might be able to model the division, thus if the
- // divisor is constant. If so, check the dividend, otherwise check if
- // the whole division can be seen as a parameter.
- if (isa<SCEVConstant>(Divisor) && !Divisor->isZero())
- return visit(Dividend);
- // For signed divisions use the SDiv instruction to check for a parameter
- // division, for unsigned divisions check the operands.
- if (SDiv)
- return visitGenericInst(SDiv, DivExpr);
- ValidatorResult LHS = visit(Dividend);
- ValidatorResult RHS = visit(Divisor);
- if (LHS.isConstant() && RHS.isConstant())
- return ValidatorResult(SCEVType::PARAM, DivExpr);
- LLVM_DEBUG(
- dbgs() << "INVALID: unsigned division of non-constant expressions");
- return ValidatorResult(SCEVType::INVALID);
- }
- ValidatorResult visitUDivExpr(const SCEVUDivExpr *Expr) {
- if (!PollyAllowUnsignedOperations)
- return ValidatorResult(SCEVType::INVALID);
- auto *Dividend = Expr->getLHS();
- auto *Divisor = Expr->getRHS();
- return visitDivision(Dividend, Divisor, Expr);
- }
- ValidatorResult visitSDivInstruction(Instruction *SDiv, const SCEV *Expr) {
- assert(SDiv->getOpcode() == Instruction::SDiv &&
- "Assumed SDiv instruction!");
- auto *Dividend = SE.getSCEV(SDiv->getOperand(0));
- auto *Divisor = SE.getSCEV(SDiv->getOperand(1));
- return visitDivision(Dividend, Divisor, Expr, SDiv);
- }
- ValidatorResult visitSRemInstruction(Instruction *SRem, const SCEV *S) {
- assert(SRem->getOpcode() == Instruction::SRem &&
- "Assumed SRem instruction!");
- auto *Divisor = SRem->getOperand(1);
- auto *CI = dyn_cast<ConstantInt>(Divisor);
- if (!CI || CI->isZeroValue())
- return visitGenericInst(SRem, S);
- auto *Dividend = SRem->getOperand(0);
- auto *DividendSCEV = SE.getSCEV(Dividend);
- return visit(DividendSCEV);
- }
- ValidatorResult visitUnknown(const SCEVUnknown *Expr) {
- Value *V = Expr->getValue();
- if (!Expr->getType()->isIntegerTy() && !Expr->getType()->isPointerTy()) {
- LLVM_DEBUG(dbgs() << "INVALID: UnknownExpr is not an integer or pointer");
- return ValidatorResult(SCEVType::INVALID);
- }
- if (isa<UndefValue>(V)) {
- LLVM_DEBUG(dbgs() << "INVALID: UnknownExpr references an undef value");
- return ValidatorResult(SCEVType::INVALID);
- }
- if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
- switch (I->getOpcode()) {
- case Instruction::IntToPtr:
- return visit(SE.getSCEVAtScope(I->getOperand(0), Scope));
- case Instruction::Load:
- return visitLoadInstruction(I, Expr);
- case Instruction::SDiv:
- return visitSDivInstruction(I, Expr);
- case Instruction::SRem:
- return visitSRemInstruction(I, Expr);
- default:
- return visitGenericInst(I, Expr);
- }
- }
- if (Expr->getType()->isPointerTy()) {
- if (isa<ConstantPointerNull>(V))
- return ValidatorResult(SCEVType::INT); // "int"
- }
- return ValidatorResult(SCEVType::PARAM, Expr);
- }
- };
- /// Check whether a SCEV refers to an SSA name defined inside a region.
- class SCEVInRegionDependences {
- const Region *R;
- Loop *Scope;
- const InvariantLoadsSetTy &ILS;
- bool AllowLoops;
- bool HasInRegionDeps = false;
- public:
- SCEVInRegionDependences(const Region *R, Loop *Scope, bool AllowLoops,
- const InvariantLoadsSetTy &ILS)
- : R(R), Scope(Scope), ILS(ILS), AllowLoops(AllowLoops) {}
- bool follow(const SCEV *S) {
- if (auto Unknown = dyn_cast<SCEVUnknown>(S)) {
- Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
- if (Inst) {
- // When we invariant load hoist a load, we first make sure that there
- // can be no dependences created by it in the Scop region. So, we should
- // not consider scalar dependences to `LoadInst`s that are invariant
- // load hoisted.
- //
- // If this check is not present, then we create data dependences which
- // are strictly not necessary by tracking the invariant load as a
- // scalar.
- LoadInst *LI = dyn_cast<LoadInst>(Inst);
- if (LI && ILS.contains(LI))
- return false;
- }
- // Return true when Inst is defined inside the region R.
- if (!Inst || !R->contains(Inst))
- return true;
- HasInRegionDeps = true;
- return false;
- }
- if (auto AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
- if (AllowLoops)
- return true;
- auto *L = AddRec->getLoop();
- if (R->contains(L) && !L->contains(Scope)) {
- HasInRegionDeps = true;
- return false;
- }
- }
- return true;
- }
- bool isDone() { return false; }
- bool hasDependences() { return HasInRegionDeps; }
- };
- namespace polly {
- /// Find all loops referenced in SCEVAddRecExprs.
- class SCEVFindLoops {
- SetVector<const Loop *> &Loops;
- public:
- SCEVFindLoops(SetVector<const Loop *> &Loops) : Loops(Loops) {}
- bool follow(const SCEV *S) {
- if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S))
- Loops.insert(AddRec->getLoop());
- return true;
- }
- bool isDone() { return false; }
- };
- void findLoops(const SCEV *Expr, SetVector<const Loop *> &Loops) {
- SCEVFindLoops FindLoops(Loops);
- SCEVTraversal<SCEVFindLoops> ST(FindLoops);
- ST.visitAll(Expr);
- }
- /// Find all values referenced in SCEVUnknowns.
- class SCEVFindValues {
- ScalarEvolution &SE;
- SetVector<Value *> &Values;
- public:
- SCEVFindValues(ScalarEvolution &SE, SetVector<Value *> &Values)
- : SE(SE), Values(Values) {}
- bool follow(const SCEV *S) {
- const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(S);
- if (!Unknown)
- return true;
- Values.insert(Unknown->getValue());
- Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
- if (!Inst || (Inst->getOpcode() != Instruction::SRem &&
- Inst->getOpcode() != Instruction::SDiv))
- return false;
- auto *Dividend = SE.getSCEV(Inst->getOperand(1));
- if (!isa<SCEVConstant>(Dividend))
- return false;
- auto *Divisor = SE.getSCEV(Inst->getOperand(0));
- SCEVFindValues FindValues(SE, Values);
- SCEVTraversal<SCEVFindValues> ST(FindValues);
- ST.visitAll(Dividend);
- ST.visitAll(Divisor);
- return false;
- }
- bool isDone() { return false; }
- };
- void findValues(const SCEV *Expr, ScalarEvolution &SE,
- SetVector<Value *> &Values) {
- SCEVFindValues FindValues(SE, Values);
- SCEVTraversal<SCEVFindValues> ST(FindValues);
- ST.visitAll(Expr);
- }
- bool hasScalarDepsInsideRegion(const SCEV *Expr, const Region *R,
- llvm::Loop *Scope, bool AllowLoops,
- const InvariantLoadsSetTy &ILS) {
- SCEVInRegionDependences InRegionDeps(R, Scope, AllowLoops, ILS);
- SCEVTraversal<SCEVInRegionDependences> ST(InRegionDeps);
- ST.visitAll(Expr);
- return InRegionDeps.hasDependences();
- }
- bool isAffineExpr(const Region *R, llvm::Loop *Scope, const SCEV *Expr,
- ScalarEvolution &SE, InvariantLoadsSetTy *ILS) {
- if (isa<SCEVCouldNotCompute>(Expr))
- return false;
- SCEVValidator Validator(R, Scope, SE, ILS);
- LLVM_DEBUG({
- dbgs() << "\n";
- dbgs() << "Expr: " << *Expr << "\n";
- dbgs() << "Region: " << R->getNameStr() << "\n";
- dbgs() << " -> ";
- });
- ValidatorResult Result = Validator.visit(Expr);
- LLVM_DEBUG({
- if (Result.isValid())
- dbgs() << "VALID\n";
- dbgs() << "\n";
- });
- return Result.isValid();
- }
- static bool isAffineExpr(Value *V, const Region *R, Loop *Scope,
- ScalarEvolution &SE, ParameterSetTy &Params) {
- auto *E = SE.getSCEV(V);
- if (isa<SCEVCouldNotCompute>(E))
- return false;
- SCEVValidator Validator(R, Scope, SE, nullptr);
- ValidatorResult Result = Validator.visit(E);
- if (!Result.isValid())
- return false;
- auto ResultParams = Result.getParameters();
- Params.insert(ResultParams.begin(), ResultParams.end());
- return true;
- }
- bool isAffineConstraint(Value *V, const Region *R, llvm::Loop *Scope,
- ScalarEvolution &SE, ParameterSetTy &Params,
- bool OrExpr) {
- if (auto *ICmp = dyn_cast<ICmpInst>(V)) {
- return isAffineConstraint(ICmp->getOperand(0), R, Scope, SE, Params,
- true) &&
- isAffineConstraint(ICmp->getOperand(1), R, Scope, SE, Params, true);
- } else if (auto *BinOp = dyn_cast<BinaryOperator>(V)) {
- auto Opcode = BinOp->getOpcode();
- if (Opcode == Instruction::And || Opcode == Instruction::Or)
- return isAffineConstraint(BinOp->getOperand(0), R, Scope, SE, Params,
- false) &&
- isAffineConstraint(BinOp->getOperand(1), R, Scope, SE, Params,
- false);
- /* Fall through */
- }
- if (!OrExpr)
- return false;
- return isAffineExpr(V, R, Scope, SE, Params);
- }
- ParameterSetTy getParamsInAffineExpr(const Region *R, Loop *Scope,
- const SCEV *Expr, ScalarEvolution &SE) {
- if (isa<SCEVCouldNotCompute>(Expr))
- return ParameterSetTy();
- InvariantLoadsSetTy ILS;
- SCEVValidator Validator(R, Scope, SE, &ILS);
- ValidatorResult Result = Validator.visit(Expr);
- assert(Result.isValid() && "Requested parameters for an invalid SCEV!");
- return Result.getParameters();
- }
- std::pair<const SCEVConstant *, const SCEV *>
- extractConstantFactor(const SCEV *S, ScalarEvolution &SE) {
- auto *ConstPart = cast<SCEVConstant>(SE.getConstant(S->getType(), 1));
- if (auto *Constant = dyn_cast<SCEVConstant>(S))
- return std::make_pair(Constant, SE.getConstant(S->getType(), 1));
- auto *AddRec = dyn_cast<SCEVAddRecExpr>(S);
- if (AddRec) {
- auto *StartExpr = AddRec->getStart();
- if (StartExpr->isZero()) {
- auto StepPair = extractConstantFactor(AddRec->getStepRecurrence(SE), SE);
- auto *LeftOverAddRec =
- SE.getAddRecExpr(StartExpr, StepPair.second, AddRec->getLoop(),
- AddRec->getNoWrapFlags());
- return std::make_pair(StepPair.first, LeftOverAddRec);
- }
- return std::make_pair(ConstPart, S);
- }
- if (auto *Add = dyn_cast<SCEVAddExpr>(S)) {
- SmallVector<const SCEV *, 4> LeftOvers;
- auto Op0Pair = extractConstantFactor(Add->getOperand(0), SE);
- auto *Factor = Op0Pair.first;
- if (SE.isKnownNegative(Factor)) {
- Factor = cast<SCEVConstant>(SE.getNegativeSCEV(Factor));
- LeftOvers.push_back(SE.getNegativeSCEV(Op0Pair.second));
- } else {
- LeftOvers.push_back(Op0Pair.second);
- }
- for (unsigned u = 1, e = Add->getNumOperands(); u < e; u++) {
- auto OpUPair = extractConstantFactor(Add->getOperand(u), SE);
- // TODO: Use something smarter than equality here, e.g., gcd.
- if (Factor == OpUPair.first)
- LeftOvers.push_back(OpUPair.second);
- else if (Factor == SE.getNegativeSCEV(OpUPair.first))
- LeftOvers.push_back(SE.getNegativeSCEV(OpUPair.second));
- else
- return std::make_pair(ConstPart, S);
- }
- auto *NewAdd = SE.getAddExpr(LeftOvers, Add->getNoWrapFlags());
- return std::make_pair(Factor, NewAdd);
- }
- auto *Mul = dyn_cast<SCEVMulExpr>(S);
- if (!Mul)
- return std::make_pair(ConstPart, S);
- SmallVector<const SCEV *, 4> LeftOvers;
- for (auto *Op : Mul->operands())
- if (isa<SCEVConstant>(Op))
- ConstPart = cast<SCEVConstant>(SE.getMulExpr(ConstPart, Op));
- else
- LeftOvers.push_back(Op);
- return std::make_pair(ConstPart, SE.getMulExpr(LeftOvers));
- }
- const SCEV *tryForwardThroughPHI(const SCEV *Expr, Region &R,
- ScalarEvolution &SE, ScopDetection *SD) {
- if (auto *Unknown = dyn_cast<SCEVUnknown>(Expr)) {
- Value *V = Unknown->getValue();
- auto *PHI = dyn_cast<PHINode>(V);
- if (!PHI)
- return Expr;
- Value *Final = nullptr;
- for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
- BasicBlock *Incoming = PHI->getIncomingBlock(i);
- if (SD->isErrorBlock(*Incoming, R) && R.contains(Incoming))
- continue;
- if (Final)
- return Expr;
- Final = PHI->getIncomingValue(i);
- }
- if (Final)
- return SE.getSCEV(Final);
- }
- return Expr;
- }
- Value *getUniqueNonErrorValue(PHINode *PHI, Region *R, ScopDetection *SD) {
- Value *V = nullptr;
- for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
- BasicBlock *BB = PHI->getIncomingBlock(i);
- if (!SD->isErrorBlock(*BB, *R)) {
- if (V)
- return nullptr;
- V = PHI->getIncomingValue(i);
- }
- }
- return V;
- }
- } // namespace polly
|