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());
172 return visit(Expr->getOperand());
178 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
193 bool HasMultipleParams =
false;
195 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
202 HasMultipleParams =
true;
208 dbgs() <<
"INVALID: More than one non-int operand in MulExpr\n"
209 <<
"\tExpr: " << *Expr <<
"\n"
210 <<
"\tPrevious expression type: " << Return <<
"\n"
211 <<
"\tNext operand (" << Op <<
"): " << *Expr->getOperand(i)
220 if (HasMultipleParams && Return.
isValid())
227 if (!Expr->isAffine()) {
228 POLLY_DEBUG(dbgs() <<
"INVALID: AddRec is not affine");
241 auto *L = Expr->getLoop();
242 if (
R->contains(L) && (!
Scope || !L->contains(
Scope))) {
244 dbgs() <<
"INVALID: Loop of AddRec expression boxed in an a "
245 "non-affine subregion or has a non-synthesizable exit "
250 if (
R->contains(L)) {
251 if (Recurrence.
isINT()) {
257 POLLY_DEBUG(dbgs() <<
"INVALID: AddRec within scop has non-int"
265 if (Expr->getStart()->isZero())
270 const SCEV *ZeroStartExpr =
SE.getAddRecExpr(
271 SE.getConstant(Expr->getStart()->getType(), 0),
272 Expr->getStepRecurrence(
SE), Expr->getLoop(), Expr->getNoWrapFlags());
278 return ZeroStartResult;
284 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
299 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
314 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
318 POLLY_DEBUG(dbgs() <<
"INVALID: UMaxExpr has a non-constant operand");
329 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
333 POLLY_DEBUG(dbgs() <<
"INVALID: UMinExpr has a non-constant operand");
344 for (
int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
350 <<
"INVALID: SCEVSequentialUMinExpr has a non-constant operand");
359 if (
R->contains(I)) {
360 POLLY_DEBUG(dbgs() <<
"INVALID: UnknownExpr references an instruction "
361 "within the region\n");
369 if (
R->contains(I) &&
ILS) {
370 ILS->insert(cast<LoadInst>(I));
379 Instruction *SDiv =
nullptr) {
384 if (isa<SCEVConstant>(Divisor) && !Divisor->isZero())
385 return visit(Dividend);
398 dbgs() <<
"INVALID: unsigned division of non-constant expressions");
406 auto *Dividend = Expr->getLHS();
407 auto *Divisor = Expr->getRHS();
412 assert(SDiv->getOpcode() == Instruction::SDiv &&
413 "Assumed SDiv instruction!");
415 auto *Dividend =
SE.getSCEV(SDiv->getOperand(0));
416 auto *Divisor =
SE.getSCEV(SDiv->getOperand(1));
421 assert(SRem->getOpcode() == Instruction::SRem &&
422 "Assumed SRem instruction!");
424 auto *Divisor = SRem->getOperand(1);
425 auto *CI = dyn_cast<ConstantInt>(Divisor);
426 if (!CI || CI->isZeroValue())
429 auto *Dividend = SRem->getOperand(0);
430 auto *DividendSCEV =
SE.getSCEV(Dividend);
431 return visit(DividendSCEV);
435 Value *V = Expr->getValue();
437 if (!Expr->getType()->isIntegerTy() && !Expr->getType()->isPointerTy()) {
439 dbgs() <<
"INVALID: UnknownExpr is not an integer or pointer");
443 if (isa<UndefValue>(V)) {
444 POLLY_DEBUG(dbgs() <<
"INVALID: UnknownExpr references an undef value");
448 if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
449 switch (I->getOpcode()) {
450 case Instruction::IntToPtr:
451 return visit(
SE.getSCEVAtScope(I->getOperand(0),
Scope));
452 case Instruction::Load:
454 case Instruction::SDiv:
456 case Instruction::SRem:
463 if (Expr->getType()->isPointerTy()) {
464 if (isa<ConstantPointerNull>(V))
486 if (
auto Unknown = dyn_cast<SCEVUnknown>(
S)) {
487 Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
498 LoadInst *LI = dyn_cast<LoadInst>(Inst);
499 if (LI &&
ILS.contains(LI))
504 if (!Inst || !
R->contains(Inst))
511 if (
auto AddRec = dyn_cast<SCEVAddRecExpr>(
S)) {
515 auto *L = AddRec->getLoop();
516 if (
R->contains(L) && !L->contains(
Scope)) {
536 if (
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(
S))
537 Loops.insert(AddRec->getLoop());
545 SCEVTraversal<SCEVFindLoops> ST(FindLoops);
559 const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(
S);
563 Values.insert(Unknown->getValue());
564 Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
565 if (!Inst || (Inst->getOpcode() != Instruction::SRem &&
566 Inst->getOpcode() != Instruction::SDiv))
569 auto *Dividend =
SE.getSCEV(Inst->getOperand(1));
570 if (!isa<SCEVConstant>(Dividend))
573 auto *Divisor =
SE.getSCEV(Inst->getOperand(0));
575 SCEVTraversal<SCEVFindValues> ST(FindValues);
576 ST.visitAll(Dividend);
577 ST.visitAll(Divisor);
585 SetVector<Value *> &Values) {
587 SCEVTraversal<SCEVFindValues> ST(FindValues);
592 llvm::Loop *Scope,
bool AllowLoops,
595 SCEVTraversal<SCEVInRegionDependences> ST(InRegionDeps);
597 return InRegionDeps.hasDependences();
602 if (isa<SCEVCouldNotCompute>(Expr))
608 dbgs() <<
"Expr: " << *Expr <<
"\n";
609 dbgs() <<
"Region: " << R->getNameStr() <<
"\n";
616 if (Result.isValid())
621 return Result.isValid();
626 auto *E = SE.getSCEV(V);
627 if (isa<SCEVCouldNotCompute>(E))
636 Params.insert(ResultParams.begin(), ResultParams.end());
644 if (
auto *ICmp = dyn_cast<ICmpInst>(V)) {
648 }
else if (
auto *BinOp = dyn_cast<BinaryOperator>(V)) {
649 auto Opcode = BinOp->getOpcode();
650 if (Opcode == Instruction::And || Opcode == Instruction::Or)
661 return ::isAffineExpr(V, R, Scope, SE, Params);
666 ScalarEvolution &SE) {
667 if (isa<SCEVCouldNotCompute>(Expr))
673 assert(Result.
isValid() &&
"Requested parameters for an invalid SCEV!");
678std::pair<const SCEVConstant *, const SCEV *>
680 auto *ConstPart = cast<SCEVConstant>(SE.getConstant(
S->getType(), 1));
682 if (
auto *Constant = dyn_cast<SCEVConstant>(
S))
683 return std::make_pair(Constant, SE.getConstant(
S->getType(), 1));
685 auto *AddRec = dyn_cast<SCEVAddRecExpr>(
S);
687 auto *StartExpr = AddRec->getStart();
688 if (StartExpr->isZero()) {
690 auto *LeftOverAddRec =
691 SE.getAddRecExpr(StartExpr, StepPair.second, AddRec->getLoop(),
692 AddRec->getNoWrapFlags());
693 return std::make_pair(StepPair.first, LeftOverAddRec);
695 return std::make_pair(ConstPart,
S);
698 if (
auto *Add = dyn_cast<SCEVAddExpr>(
S)) {
699 SmallVector<const SCEV *, 4> LeftOvers;
701 auto *Factor = Op0Pair.first;
702 if (SE.isKnownNegative(Factor)) {
703 Factor = cast<SCEVConstant>(SE.getNegativeSCEV(Factor));
704 LeftOvers.push_back(SE.getNegativeSCEV(Op0Pair.second));
706 LeftOvers.push_back(Op0Pair.second);
709 for (
unsigned u = 1, e = Add->getNumOperands(); u < e; u++) {
712 if (Factor == OpUPair.first)
713 LeftOvers.push_back(OpUPair.second);
714 else if (Factor == SE.getNegativeSCEV(OpUPair.first))
715 LeftOvers.push_back(SE.getNegativeSCEV(OpUPair.second));
717 return std::make_pair(ConstPart,
S);
720 auto *NewAdd = SE.getAddExpr(LeftOvers, Add->getNoWrapFlags());
721 return std::make_pair(Factor, NewAdd);
724 auto *Mul = dyn_cast<SCEVMulExpr>(
S);
726 return std::make_pair(ConstPart,
S);
728 SmallVector<const SCEV *, 4> LeftOvers;
729 for (
auto *Op : Mul->operands())
730 if (isa<SCEVConstant>(Op))
731 ConstPart = cast<SCEVConstant>(SE.getMulExpr(ConstPart, Op));
733 LeftOvers.push_back(Op);
735 return std::make_pair(ConstPart, SE.getMulExpr(LeftOvers));
741 if (
auto *Unknown = dyn_cast<SCEVUnknown>(Expr)) {
742 Value *V = Unknown->getValue();
743 auto *
PHI = dyn_cast<PHINode>(V);
747 Value *Final =
nullptr;
749 for (
unsigned i = 0; i <
PHI->getNumIncomingValues(); i++) {
750 BasicBlock *Incoming =
PHI->getIncomingBlock(i);
751 if (SD->
isErrorBlock(*Incoming, R) && R.contains(Incoming))
755 Final =
PHI->getIncomingValue(i);
759 return SE.getSCEV(Final);
767 for (
unsigned i = 0; i <
PHI->getNumIncomingValues(); i++) {
768 BasicBlock *BB =
PHI->getIncomingBlock(i);
772 V =
PHI->getIncomingValue(i);
raw_ostream & operator<<(raw_ostream &OS, ValidatorResult &VR)
static bool isAffineExpr(Value *V, const Region *R, Loop *Scope, ScalarEvolution &SE, ParameterSetTy &Params)
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 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.
This file contains the declaration of the PolyhedralInfo class, which will provide an interface to ex...
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.
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.
llvm::SetVector< llvm::AssertingVH< llvm::LoadInst > > InvariantLoadsSetTy
Type for a set of invariant loads.
std::pair< const llvm::SCEVConstant *, const llvm::SCEV * > extractConstantFactor(const llvm::SCEV *M, llvm::ScalarEvolution &SE)
Extract the constant factors from the multiplication M.
llvm::SetVector< const llvm::SCEV * > ParameterSetTy
Set type for parameters.
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.