forked from OSchip/llvm-project
SCEVValidator: Add debug output that gives the reason for invalid expressions
llvm-svn: 163472
This commit is contained in:
parent
6eaafb7288
commit
eeb776a41f
|
@ -251,7 +251,7 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
|
|||
AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);
|
||||
|
||||
if (!isAffineExpr(&Context.CurRegion, AccessFunction, *SE, BaseValue) && !AllowNonAffine)
|
||||
INVALID(AffFunc, "Non affine access function" << *AccessFunction);
|
||||
INVALID(AffFunc, "Non affine access function: " << *AccessFunction);
|
||||
|
||||
// FIXME: Alias Analysis thinks IntToPtrInst aliases with alloca instructions
|
||||
// created by IndependentBlocks Pass.
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
#include "polly/Support/SCEVValidator.h"
|
||||
|
||||
#define DEBUG_TYPE "polly-scev-validator"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Analysis/ScalarEvolution.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
||||
#include "llvm/Analysis/RegionInfo.h"
|
||||
|
@ -41,10 +43,6 @@ class ValidatorResult {
|
|||
std::vector<const SCEV*> Parameters;
|
||||
|
||||
public:
|
||||
|
||||
/// @brief Create an invalid result.
|
||||
ValidatorResult() : Type(SCEVType::INVALID) {};
|
||||
|
||||
/// @brief The copy constructor
|
||||
ValidatorResult(const ValidatorResult &Source) {
|
||||
Type = Source.Type;
|
||||
|
@ -61,6 +59,11 @@ public:
|
|||
Parameters.push_back(Expr);
|
||||
};
|
||||
|
||||
/// @brief Get the type of the ValidatorResult.
|
||||
SCEVType::TYPE getType() {
|
||||
return Type;
|
||||
}
|
||||
|
||||
/// @brief Is the analyzed SCEV constant during the execution of the SCoP.
|
||||
bool isConstant() {
|
||||
return Type == SCEVType::INT || Type == SCEVType::PARAM;
|
||||
|
@ -81,6 +84,11 @@ public:
|
|||
return Type == SCEVType::INT;
|
||||
}
|
||||
|
||||
/// @brief Is the analyzed SCEV of Type PARAM.
|
||||
bool isPARAM() {
|
||||
return Type == SCEVType::PARAM;
|
||||
}
|
||||
|
||||
/// @brief Get the parameters of this validator result.
|
||||
std::vector<const SCEV*> getParameters() {
|
||||
return Parameters;
|
||||
|
@ -105,16 +113,16 @@ public:
|
|||
void print(raw_ostream &OS) {
|
||||
switch (Type) {
|
||||
case SCEVType::INT:
|
||||
OS << "SCEVType::INT\n";
|
||||
OS << "SCEVType::INT";
|
||||
break;
|
||||
case SCEVType::PARAM:
|
||||
OS << "SCEVType::PARAM\n";
|
||||
OS << "SCEVType::PARAM";
|
||||
break;
|
||||
case SCEVType::IV:
|
||||
OS << "SCEVType::IV\n";
|
||||
OS << "SCEVType::IV";
|
||||
break;
|
||||
case SCEVType::INVALID:
|
||||
OS << "SCEVType::INVALID\n";
|
||||
OS << "SCEVType::INVALID";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -145,25 +153,41 @@ public:
|
|||
class ValidatorResult visitTruncateExpr(const SCEVTruncateExpr *Expr) {
|
||||
ValidatorResult Op = visit(Expr->getOperand());
|
||||
|
||||
// We currently do not represent a truncate expression as an affine
|
||||
// expression. If it is constant during Scop execution, we treat it as a
|
||||
// parameter, otherwise we bail out.
|
||||
if (Op.isConstant())
|
||||
return ValidatorResult(SCEVType::PARAM, Expr);
|
||||
switch (Op.getType()) {
|
||||
case SCEVType::INT:
|
||||
case SCEVType::PARAM:
|
||||
// We currently do not represent a truncate expression as an affine
|
||||
// expression. If it is constant during Scop execution, we treat it as a
|
||||
// parameter.
|
||||
return ValidatorResult(SCEVType::PARAM, Expr);
|
||||
case SCEVType::IV:
|
||||
DEBUG(dbgs() << "INVALID: Truncation of SCEVType::IV expression");
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
case SCEVType::INVALID:
|
||||
return Op;
|
||||
}
|
||||
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
llvm_unreachable("Unknown SCEVType");
|
||||
}
|
||||
|
||||
class ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
|
||||
ValidatorResult Op = visit(Expr->getOperand());
|
||||
|
||||
// We currently do not represent a zero extend expression as an affine
|
||||
// expression. If it is constant during Scop execution, we treat it as a
|
||||
// parameter, otherwise we bail out.
|
||||
if (Op.isConstant())
|
||||
return ValidatorResult(SCEVType::PARAM, Expr);
|
||||
switch (Op.getType()) {
|
||||
case SCEVType::INT:
|
||||
case SCEVType::PARAM:
|
||||
// We currently do not represent a truncate expression as an affine
|
||||
// expression. If it is constant during Scop execution, we treat it as a
|
||||
// parameter.
|
||||
return ValidatorResult(SCEVType::PARAM, Expr);
|
||||
case SCEVType::IV:
|
||||
DEBUG(dbgs() << "INVALID: ZeroExtend of SCEVType::IV expression");
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
case SCEVType::INVALID:
|
||||
return Op;
|
||||
}
|
||||
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
llvm_unreachable("Unknown SCEVType");
|
||||
}
|
||||
|
||||
class ValidatorResult visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
|
||||
|
@ -179,11 +203,11 @@ public:
|
|||
|
||||
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
|
||||
ValidatorResult Op = visit(Expr->getOperand(i));
|
||||
|
||||
if (!Op.isValid())
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
|
||||
Return.merge(Op);
|
||||
|
||||
// Early exit.
|
||||
if (!Return.isValid())
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Check for NSW and NUW.
|
||||
|
@ -199,8 +223,15 @@ public:
|
|||
if (Op.isINT())
|
||||
continue;
|
||||
|
||||
if (!Op.isValid() || !Return.isINT())
|
||||
if ((Op.isIV() || Op.isPARAM()) && !Return.isINT() ) {
|
||||
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);
|
||||
}
|
||||
|
@ -219,18 +250,24 @@ public:
|
|||
if (LHS.isConstant() && RHS.isConstant())
|
||||
return ValidatorResult(SCEVType::PARAM, Expr);
|
||||
|
||||
DEBUG(dbgs() << "INVALID: unsigned division of non-constant expressions");
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
}
|
||||
|
||||
class ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr) {
|
||||
if (!Expr->isAffine())
|
||||
if (!Expr->isAffine()) {
|
||||
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() || !Recurrence.isConstant())
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
if (!Start.isValid())
|
||||
return Start;
|
||||
|
||||
if (!Recurrence.isValid())
|
||||
return Recurrence;
|
||||
|
||||
if (R->contains(Expr->getLoop())) {
|
||||
if (Recurrence.isINT()) {
|
||||
|
@ -239,13 +276,14 @@ public:
|
|||
return Result;
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "INVALID: AddRec within scop has non-int"
|
||||
"recurrence part");
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
}
|
||||
|
||||
if (Start.isConstant())
|
||||
return ValidatorResult(SCEVType::PARAM, Expr);
|
||||
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
assert (Start.isConstant() && Recurrence.isConstant()
|
||||
&& "Expected 'Start' and 'Recurrence' to be constant");
|
||||
return ValidatorResult(SCEVType::PARAM, Expr);
|
||||
}
|
||||
|
||||
class ValidatorResult visitSMaxExpr(const SCEVSMaxExpr *Expr) {
|
||||
|
@ -255,7 +293,7 @@ public:
|
|||
ValidatorResult Op = visit(Expr->getOperand(i));
|
||||
|
||||
if (!Op.isValid())
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
return Op;
|
||||
|
||||
Return.merge(Op);
|
||||
}
|
||||
|
@ -269,8 +307,10 @@ public:
|
|||
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
|
||||
ValidatorResult Op = visit(Expr->getOperand(i));
|
||||
|
||||
if (!Op.isConstant())
|
||||
if (!Op.isConstant()) {
|
||||
DEBUG(dbgs() << "INVALID: UMaxExpr has a non-constant operand");
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
return ValidatorResult(SCEVType::PARAM, Expr);
|
||||
|
@ -286,18 +326,27 @@ public:
|
|||
// A[i] = 1;
|
||||
//
|
||||
// See test/CodeGen/20120316-InvalidCast.ll
|
||||
if (!Expr->getType()->isIntegerTy())
|
||||
if (!Expr->getType()->isIntegerTy()) {
|
||||
DEBUG(dbgs() << "INVALID: UnknownExpr is not an integer type");
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
}
|
||||
|
||||
if (isa<UndefValue>(V))
|
||||
if (isa<UndefValue>(V)) {
|
||||
DEBUG(dbgs() << "INVALID: UnknownExpr references an undef value");
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
}
|
||||
|
||||
if (Instruction *I = dyn_cast<Instruction>(Expr->getValue()))
|
||||
if (R->contains(I))
|
||||
if (R->contains(I)) {
|
||||
DEBUG(dbgs() << "INVALID: UnknownExpr references an instruction "
|
||||
"within the region\n");
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
}
|
||||
|
||||
if (BaseAddress == V)
|
||||
if (BaseAddress == V) {
|
||||
DEBUG(dbgs() << "INVALID: UnknownExpr references BaseAddress\n");
|
||||
return ValidatorResult(SCEVType::INVALID);
|
||||
}
|
||||
|
||||
return ValidatorResult(SCEVType::PARAM, Expr);
|
||||
}
|
||||
|
@ -310,8 +359,20 @@ namespace polly {
|
|||
return false;
|
||||
|
||||
SCEVValidator Validator(R, SE, BaseAddress);
|
||||
DEBUG(
|
||||
dbgs() << "\n";
|
||||
dbgs() << "Expr: " << *Expr << "\n";
|
||||
dbgs() << "Region: " << R->getNameStr() << "\n";
|
||||
dbgs() << " -> ");
|
||||
|
||||
ValidatorResult Result = Validator.visit(Expr);
|
||||
|
||||
DEBUG(
|
||||
if (Result.isValid())
|
||||
dbgs() << "VALID\n";
|
||||
dbgs() << "\n";
|
||||
);
|
||||
|
||||
return Result.isValid();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue