4#include "llvm/Analysis/RegionInfo.h"
5#include "llvm/Analysis/ScalarEvolution.h"
6#include "llvm/Analysis/ScalarEvolutionExpressions.h"
7#include "llvm/Support/Debug.h"
13#define DEBUG_TYPE "polly-scev-validator"
101 OS <<
"SCEVType::INT";
104 OS <<
"SCEVType::PARAM";
107 OS <<
"SCEVType::IV";
110 OS <<
"SCEVType::INVALID";
140 POLLY_DEBUG(dbgs() <<
"INVALID: VScale is not supported");
145 const SCEV *Operand) {
160 return visit(Expr->getOperand());
164 return visit(Expr->getOperand());
176 return visit(Expr->getOperand());
182 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
197 bool HasMultipleParams =
false;
199 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
206 HasMultipleParams =
true;
212 dbgs() <<
"INVALID: More than one non-int operand in MulExpr\n"
213 <<
"\tExpr: " << *Expr <<
"\n"
214 <<
"\tPrevious expression type: " << Return <<
"\n"
215 <<
"\tNext operand (" << Op <<
"): " << *Expr->getOperand(i)
224 if (HasMultipleParams && Return.
isValid())
231 if (!Expr->isAffine()) {
232 POLLY_DEBUG(dbgs() <<
"INVALID: AddRec is not affine");
245 auto *L = Expr->getLoop();
246 if (
R->contains(L) && (!
Scope || !L->contains(
Scope))) {
248 dbgs() <<
"INVALID: Loop of AddRec expression boxed in an a "
249 "non-affine subregion or has a non-synthesizable exit "
254 if (
R->contains(L)) {
255 if (Recurrence.
isINT()) {
261 POLLY_DEBUG(dbgs() <<
"INVALID: AddRec within scop has non-int"
269 if (Expr->getStart()->isZero())
274 const SCEV *ZeroStartExpr =
SE.getAddRecExpr(
275 SE.getConstant(Expr->getStart()->getType(), 0),
276 Expr->getStepRecurrence(
SE), Expr->getLoop(), Expr->getNoWrapFlags());
282 return ZeroStartResult;
288 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
303 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
318 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
322 POLLY_DEBUG(dbgs() <<
"INVALID: UMaxExpr has a non-constant operand");
333 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
337 POLLY_DEBUG(dbgs() <<
"INVALID: UMinExpr has a non-constant operand");
348 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
354 <<
"INVALID: SCEVSequentialUMinExpr has a non-constant operand");
363 if (
R->contains(I)) {
364 POLLY_DEBUG(dbgs() <<
"INVALID: UnknownExpr references an instruction "
365 "within the region\n");
373 if (
R->contains(I) &&
ILS) {
374 ILS->insert(cast<LoadInst>(I));
383 Instruction *SDiv =
nullptr) {
388 if (isa<SCEVConstant>(Divisor) && !Divisor->isZero())
389 return visit(Dividend);
402 dbgs() <<
"INVALID: unsigned division of non-constant expressions");
410 const SCEV *Dividend = Expr->getLHS();
411 const SCEV *Divisor = Expr->getRHS();
416 assert(SDiv->getOpcode() == Instruction::SDiv &&
417 "Assumed SDiv instruction!");
419 const SCEV *Dividend =
SE.getSCEV(SDiv->getOperand(0));
420 const SCEV *Divisor =
SE.getSCEV(SDiv->getOperand(1));
425 assert(SRem->getOpcode() == Instruction::SRem &&
426 "Assumed SRem instruction!");
428 auto *Divisor = SRem->getOperand(1);
429 auto *CI = dyn_cast<ConstantInt>(Divisor);
430 if (!CI || CI->isZeroValue())
433 auto *Dividend = SRem->getOperand(0);
434 const SCEV *DividendSCEV =
SE.getSCEV(Dividend);
435 return visit(DividendSCEV);
439 Value *V = Expr->getValue();
441 if (!Expr->getType()->isIntegerTy() && !Expr->getType()->isPointerTy()) {
443 dbgs() <<
"INVALID: UnknownExpr is not an integer or pointer");
447 if (isa<UndefValue>(V)) {
448 POLLY_DEBUG(dbgs() <<
"INVALID: UnknownExpr references an undef value");
452 if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
453 switch (I->getOpcode()) {
454 case Instruction::IntToPtr:
455 return visit(
SE.getSCEVAtScope(I->getOperand(0),
Scope));
456 case Instruction::Load:
458 case Instruction::SDiv:
460 case Instruction::SRem:
467 if (Expr->getType()->isPointerTy()) {
468 if (isa<ConstantPointerNull>(V))
490 if (
auto Unknown = dyn_cast<SCEVUnknown>(
S)) {
491 Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
502 LoadInst *LI = dyn_cast<LoadInst>(Inst);
503 if (LI &&
ILS.contains(LI))
508 if (!Inst || !
R->contains(Inst))
515 if (
auto AddRec = dyn_cast<SCEVAddRecExpr>(
S)) {
519 auto *L = AddRec->getLoop();
520 if (
R->contains(L) && !L->contains(
Scope)) {
540 if (
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(
S))
541 Loops.insert(AddRec->getLoop());
549 SCEVTraversal<SCEVFindLoops> ST(FindLoops);
563 const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(
S);
567 Values.insert(Unknown->getValue());
568 Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
569 if (!Inst || (Inst->getOpcode() != Instruction::SRem &&
570 Inst->getOpcode() != Instruction::SDiv))
573 const SCEV *Dividend =
SE.getSCEV(Inst->getOperand(1));
574 if (!isa<SCEVConstant>(Dividend))
577 const SCEV *Divisor =
SE.getSCEV(Inst->getOperand(0));
579 SCEVTraversal<SCEVFindValues> ST(FindValues);
580 ST.visitAll(Dividend);
581 ST.visitAll(Divisor);
589 SetVector<Value *> &Values) {
591 SCEVTraversal<SCEVFindValues> ST(FindValues);
596 llvm::Loop *Scope,
bool AllowLoops,
599 SCEVTraversal<SCEVInRegionDependences> ST(InRegionDeps);
601 return InRegionDeps.hasDependences();
606 if (isa<SCEVCouldNotCompute>(Expr))
612 dbgs() <<
"Expr: " << *Expr <<
"\n";
613 dbgs() <<
"Region: " << R->getNameStr() <<
"\n";
620 if (Result.isValid())
630 const SCEV *E = SE.getSCEV(V);
631 if (isa<SCEVCouldNotCompute>(E))
640 Params.insert_range(ResultParams);
648 if (
auto *ICmp = dyn_cast<ICmpInst>(V)) {
652 }
else if (
auto *BinOp = dyn_cast<BinaryOperator>(V)) {
653 auto Opcode = BinOp->getOpcode();
654 if (Opcode == Instruction::And || Opcode == Instruction::Or)
665 return ::isAffineExpr(V, R, Scope, SE, Params);
670 ScalarEvolution &SE) {
671 if (isa<SCEVCouldNotCompute>(Expr))
677 assert(Result.
isValid() &&
"Requested parameters for an invalid SCEV!");
682std::pair<const SCEVConstant *, const SCEV *>
684 auto *ConstPart = cast<SCEVConstant>(SE.getConstant(
S->getType(), 1));
686 if (
auto *Constant = dyn_cast<SCEVConstant>(
S))
687 return std::make_pair(Constant, SE.getConstant(
S->getType(), 1));
689 auto *AddRec = dyn_cast<SCEVAddRecExpr>(
S);
691 const SCEV *StartExpr = AddRec->getStart();
692 if (StartExpr->isZero()) {
694 const SCEV *LeftOverAddRec =
695 SE.getAddRecExpr(StartExpr, StepPair.second, AddRec->getLoop(),
696 AddRec->getNoWrapFlags());
697 return std::make_pair(StepPair.first, LeftOverAddRec);
699 return std::make_pair(ConstPart,
S);
702 if (
auto *Add = dyn_cast<SCEVAddExpr>(
S)) {
703 SmallVector<const SCEV *, 4> LeftOvers;
705 auto *Factor = Op0Pair.first;
706 if (SE.isKnownNegative(Factor)) {
707 Factor = cast<SCEVConstant>(SE.getNegativeSCEV(Factor));
708 LeftOvers.push_back(SE.getNegativeSCEV(Op0Pair.second));
710 LeftOvers.push_back(Op0Pair.second);
713 for (
unsigned u = 1, e = Add->getNumOperands(); u < e; u++) {
716 if (Factor == OpUPair.first)
717 LeftOvers.push_back(OpUPair.second);
718 else if (Factor == SE.getNegativeSCEV(OpUPair.first))
719 LeftOvers.push_back(SE.getNegativeSCEV(OpUPair.second));
721 return std::make_pair(ConstPart,
S);
724 const SCEV *NewAdd = SE.getAddExpr(LeftOvers, Add->getNoWrapFlags());
725 return std::make_pair(Factor, NewAdd);
728 auto *Mul = dyn_cast<SCEVMulExpr>(
S);
730 return std::make_pair(ConstPart,
S);
732 SmallVector<const SCEV *, 4> LeftOvers;
733 for (
const SCEV *Op : Mul->operands())
734 if (isa<SCEVConstant>(Op))
735 ConstPart = cast<SCEVConstant>(SE.getMulExpr(ConstPart, Op));
737 LeftOvers.push_back(Op);
739 return std::make_pair(ConstPart, SE.getMulExpr(LeftOvers));
745 if (
auto *Unknown = dyn_cast<SCEVUnknown>(Expr)) {
746 Value *V = Unknown->getValue();
747 auto *
PHI = dyn_cast<PHINode>(V);
751 Value *Final =
nullptr;
753 for (
unsigned i = 0; i <
PHI->getNumIncomingValues(); i++) {
754 BasicBlock *Incoming =
PHI->getIncomingBlock(i);
755 if (SD->
isErrorBlock(*Incoming, R) && R.contains(Incoming))
759 Final =
PHI->getIncomingValue(i);
763 return SE.getSCEV(Final);
771 for (
unsigned i = 0; i <
PHI->getNumIncomingValues(); i++) {
772 BasicBlock *BB =
PHI->getIncomingBlock(i);
776 V =
PHI->getIncomingValue(i);
Find all loops referenced in SCEVAddRecExprs.
SetVector< const Loop * > & Loops
SCEVFindLoops(SetVector< const Loop * > &Loops)
bool follow(const SCEV *S)
Find all values referenced in SCEVUnknowns.
SCEVFindValues(ScalarEvolution &SE, SetVector< Value * > &Values)
bool follow(const SCEV *S)
SetVector< Value * > & Values
Check whether a SCEV refers to an SSA name defined inside a region.
const InvariantLoadsSetTy & ILS
bool follow(const SCEV *S)
SCEVInRegionDependences(const Region *R, Loop *Scope, bool AllowLoops, const InvariantLoadsSetTy &ILS)
Check if a SCEV is valid in a SCoP.
ValidatorResult visitAddExpr(const SCEVAddExpr *Expr)
ValidatorResult visitUMaxExpr(const SCEVUMaxExpr *Expr)
ValidatorResult visitSMinExpr(const SCEVSMinExpr *Expr)
ValidatorResult visitDivision(const SCEV *Dividend, const SCEV *Divisor, const SCEV *DivExpr, Instruction *SDiv=nullptr)
ValidatorResult visitUnknown(const SCEVUnknown *Expr)
ValidatorResult visitTruncateExpr(const SCEVTruncateExpr *Expr)
ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr)
ValidatorResult visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Expr)
ValidatorResult visitMulExpr(const SCEVMulExpr *Expr)
ValidatorResult visitUDivExpr(const SCEVUDivExpr *Expr)
ValidatorResult visitSequentialUMinExpr(const SCEVSequentialUMinExpr *Expr)
ValidatorResult visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr)
SCEVValidator(const Region *R, Loop *Scope, ScalarEvolution &SE, InvariantLoadsSetTy *ILS)
ValidatorResult visitConstant(const SCEVConstant *Constant)
ValidatorResult visitLoadInstruction(Instruction *I, const SCEV *S)
ValidatorResult visitSDivInstruction(Instruction *SDiv, const SCEV *Expr)
ValidatorResult visitUMinExpr(const SCEVUMinExpr *Expr)
ValidatorResult visitGenericInst(Instruction *I, const SCEV *S)
ValidatorResult visitSignExtendExpr(const SCEVSignExtendExpr *Expr)
ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr)
ValidatorResult visitSRemInstruction(Instruction *SRem, const SCEV *S)
ValidatorResult visitVScale(const SCEVVScale *VScale)
ValidatorResult visitSMaxExpr(const SCEVSMaxExpr *Expr)
ValidatorResult visitZeroExtendOrTruncateExpr(const SCEV *Expr, const SCEV *Operand)
InvariantLoadsSetTy * ILS
The result the validator returns for a SCEV expression.
ValidatorResult(SCEVType::TYPE Type)
Construct a result with a certain type and no parameters.
void addParamsFrom(const ValidatorResult &Source)
Add the parameters of Source to this result.
void merge(const ValidatorResult &ToMerge)
Merge a result.
bool isPARAM()
Is the analyzed SCEV of Type PARAM.
SCEVType::TYPE Type
The type of the expression.
SCEVType::TYPE getType()
Get the type of the ValidatorResult.
bool isValid()
Is the analyzed SCEV valid.
bool isIV()
Is the analyzed SCEV of Type IV.
void print(raw_ostream &OS)
bool isINT()
Is the analyzed SCEV of Type INT.
ValidatorResult(const ValidatorResult &Source)
The copy constructor.
bool isConstant()
Is the analyzed SCEV constant during the execution of the SCoP.
const ParameterSetTy & getParameters()
Get the parameters of this validator result.
ValidatorResult(SCEVType::TYPE Type, const SCEV *Expr)
Construct a result with a certain type and a single parameter.
ParameterSetTy Parameters
The set of Parameters in the expression.
Pass to detect the maximal static control parts (Scops) of a function.
bool isErrorBlock(llvm::BasicBlock &BB, const llvm::Region &R)
Check if the block is a error block.
bool isAffineConstraint(llvm::Value *V, const llvm::Region *R, llvm::Loop *Scope, llvm::ScalarEvolution &SE, ParameterSetTy &Params, bool OrExpr=false)
Check if V describes an affine constraint in R.
void findValues(const llvm::SCEV *Expr, llvm::ScalarEvolution &SE, llvm::SetVector< llvm::Value * > &Values)
Find the values referenced by SCEVUnknowns in a given SCEV expression.
void findLoops(const llvm::SCEV *Expr, llvm::SetVector< const llvm::Loop * > &Loops)
Find the loops referenced from a SCEV expression.
llvm::SetVector< llvm::AssertingVH< llvm::LoadInst > > InvariantLoadsSetTy
Type for a set of invariant loads.
llvm::SetVector< const llvm::SCEV * > ParameterSetTy
Set type for parameters.
bool isAffineExpr(const llvm::Region *R, llvm::Loop *Scope, const llvm::SCEV *Expression, llvm::ScalarEvolution &SE, InvariantLoadsSetTy *ILS=nullptr)
@ Value
MemoryKind::Value: Models an llvm::Value.
@ PHI
MemoryKind::PHI: Models PHI nodes within the SCoP.
const llvm::SCEV * tryForwardThroughPHI(const llvm::SCEV *Expr, llvm::Region &R, llvm::ScalarEvolution &SE, ScopDetection *SD)
Try to look through PHI nodes, where some incoming edges come from error blocks.
raw_ostream & operator<<(raw_ostream &OS, MemoryAccess::ReductionType RT)
std::pair< const llvm::SCEVConstant *, const llvm::SCEV * > extractConstantFactor(const llvm::SCEV *M, llvm::ScalarEvolution &SE)
Extract the constant factors from the multiplication M.
ParameterSetTy getParamsInAffineExpr(const llvm::Region *R, llvm::Loop *Scope, const llvm::SCEV *Expression, llvm::ScalarEvolution &SE)
bool hasScalarDepsInsideRegion(const llvm::SCEV *Expr, const llvm::Region *R, llvm::Loop *Scope, bool AllowLoops, const InvariantLoadsSetTy &ILS)
Returns true when the SCEV contains references to instructions within the region.
bool PollyAllowUnsignedOperations
llvm::Value * getUniqueNonErrorValue(llvm::PHINode *PHI, llvm::Region *R, ScopDetection *SD)
Return a unique non-error block incoming value for PHI if available.