2011-11-07 20:58:54 +08:00
|
|
|
|
|
|
|
#include "polly/Support/SCEVValidator.h"
|
2013-03-19 04:21:13 +08:00
|
|
|
#include "polly/ScopInfo.h"
|
2015-05-09 17:13:42 +08:00
|
|
|
#include "llvm/Analysis/RegionInfo.h"
|
2011-11-07 20:58:54 +08:00
|
|
|
#include "llvm/Analysis/ScalarEvolution.h"
|
|
|
|
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
2014-04-22 11:30:19 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2011-11-08 23:41:28 +08:00
|
|
|
|
2011-11-07 20:58:54 +08:00
|
|
|
using namespace llvm;
|
2015-10-08 04:17:36 +08:00
|
|
|
using namespace polly;
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2014-04-22 11:30:19 +08:00
|
|
|
#define DEBUG_TYPE "polly-scev-validator"
|
|
|
|
|
2011-11-07 20:58:54 +08:00
|
|
|
namespace SCEVType {
|
2013-02-22 16:21:52 +08:00
|
|
|
/// @brief 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
|
|
|
|
};
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
|
2011-11-17 20:56:17 +08:00
|
|
|
/// @brief The result the validator returns for a SCEV expression.
|
2011-11-17 20:56:19 +08:00
|
|
|
class ValidatorResult {
|
2011-11-17 20:56:17 +08:00
|
|
|
/// @brief The type of the expression
|
2011-11-17 20:56:21 +08:00
|
|
|
SCEVType::TYPE Type;
|
2011-11-17 20:56:17 +08:00
|
|
|
|
|
|
|
/// @brief The set of Parameters in the expression.
|
2016-04-25 21:33:07 +08:00
|
|
|
ParameterSetTy Parameters;
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
public:
|
2011-11-17 20:56:17 +08:00
|
|
|
/// @brief The copy constructor
|
2011-11-17 20:56:21 +08:00
|
|
|
ValidatorResult(const ValidatorResult &Source) {
|
|
|
|
Type = Source.Type;
|
|
|
|
Parameters = Source.Parameters;
|
2013-02-22 16:21:52 +08:00
|
|
|
}
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2011-11-17 20:56:17 +08:00
|
|
|
/// @brief Construct a result with a certain type and no parameters.
|
2012-03-16 18:16:28 +08:00
|
|
|
ValidatorResult(SCEVType::TYPE Type) : Type(Type) {
|
|
|
|
assert(Type != SCEVType::PARAM && "Did you forget to pass the parameter");
|
2013-02-22 16:21:52 +08:00
|
|
|
}
|
2011-11-17 20:56:17 +08:00
|
|
|
|
|
|
|
/// @brief Construct a result with a certain type and a single parameter.
|
2011-11-17 20:56:21 +08:00
|
|
|
ValidatorResult(SCEVType::TYPE Type, const SCEV *Expr) : Type(Type) {
|
2016-04-25 21:33:07 +08:00
|
|
|
Parameters.insert(Expr);
|
2013-02-22 16:21:52 +08:00
|
|
|
}
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2012-09-08 22:00:37 +08:00
|
|
|
/// @brief Get the type of the ValidatorResult.
|
2013-02-22 16:21:52 +08:00
|
|
|
SCEVType::TYPE getType() { return Type; }
|
2012-09-08 22:00:37 +08:00
|
|
|
|
2011-11-17 20:56:17 +08:00
|
|
|
/// @brief Is the analyzed SCEV constant during the execution of the SCoP.
|
2013-02-22 16:21:52 +08:00
|
|
|
bool isConstant() { return Type == SCEVType::INT || Type == SCEVType::PARAM; }
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2011-11-17 20:56:17 +08:00
|
|
|
/// @brief Is the analyzed SCEV valid.
|
2013-02-22 16:21:52 +08:00
|
|
|
bool isValid() { return Type != SCEVType::INVALID; }
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2011-11-17 20:56:21 +08:00
|
|
|
/// @brief Is the analyzed SCEV of Type IV.
|
2013-02-22 16:21:52 +08:00
|
|
|
bool isIV() { return Type == SCEVType::IV; }
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2011-11-17 20:56:21 +08:00
|
|
|
/// @brief Is the analyzed SCEV of Type INT.
|
2013-02-22 16:21:52 +08:00
|
|
|
bool isINT() { return Type == SCEVType::INT; }
|
2011-11-08 23:41:28 +08:00
|
|
|
|
2012-09-08 22:00:37 +08:00
|
|
|
/// @brief Is the analyzed SCEV of Type PARAM.
|
2013-02-22 16:21:52 +08:00
|
|
|
bool isPARAM() { return Type == SCEVType::PARAM; }
|
2012-09-08 22:00:37 +08:00
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
/// @brief Get the parameters of this validator result.
|
2016-04-25 21:33:07 +08:00
|
|
|
const ParameterSetTy &getParameters() { return Parameters; }
|
2011-11-17 20:56:19 +08:00
|
|
|
|
2011-11-17 20:56:17 +08:00
|
|
|
/// @brief Add the parameters of Source to this result.
|
2015-02-27 03:33:42 +08:00
|
|
|
void addParamsFrom(const ValidatorResult &Source) {
|
2016-04-25 21:33:07 +08:00
|
|
|
Parameters.insert(Source.Parameters.begin(), Source.Parameters.end());
|
2011-11-08 23:41:28 +08:00
|
|
|
}
|
2011-11-17 20:56:19 +08:00
|
|
|
|
|
|
|
/// @brief Merge a result.
|
|
|
|
///
|
2011-11-17 20:56:21 +08:00
|
|
|
/// This means to merge the parameters and to set the Type to the most
|
|
|
|
/// specific Type that matches both.
|
2015-02-27 03:33:42 +08:00
|
|
|
void merge(const ValidatorResult &ToMerge) {
|
2011-11-17 20:56:21 +08:00
|
|
|
Type = std::max(Type, ToMerge.Type);
|
2011-11-17 20:56:19 +08:00
|
|
|
addParamsFrom(ToMerge);
|
|
|
|
}
|
2012-03-16 18:12:37 +08:00
|
|
|
|
|
|
|
void print(raw_ostream &OS) {
|
|
|
|
switch (Type) {
|
2013-02-22 16:21:52 +08:00
|
|
|
case SCEVType::INT:
|
|
|
|
OS << "SCEVType::INT";
|
2012-03-16 18:12:37 +08:00
|
|
|
break;
|
2013-02-22 16:21:52 +08:00
|
|
|
case SCEVType::PARAM:
|
|
|
|
OS << "SCEVType::PARAM";
|
2012-03-16 18:12:37 +08:00
|
|
|
break;
|
2013-02-22 16:21:52 +08:00
|
|
|
case SCEVType::IV:
|
|
|
|
OS << "SCEVType::IV";
|
2012-03-16 18:12:37 +08:00
|
|
|
break;
|
2013-02-22 16:21:52 +08:00
|
|
|
case SCEVType::INVALID:
|
|
|
|
OS << "SCEVType::INVALID";
|
2012-03-16 18:12:37 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-11-07 20:58:54 +08:00
|
|
|
};
|
|
|
|
|
2012-03-16 18:12:37 +08:00
|
|
|
raw_ostream &operator<<(raw_ostream &OS, class ValidatorResult &VR) {
|
|
|
|
VR.print(OS);
|
|
|
|
return OS;
|
|
|
|
}
|
|
|
|
|
2011-11-07 20:58:54 +08:00
|
|
|
/// Check if a SCEV is valid in a SCoP.
|
2013-06-23 09:29:29 +08:00
|
|
|
struct SCEVValidator
|
|
|
|
: public SCEVVisitor<SCEVValidator, class ValidatorResult> {
|
2011-11-07 20:58:54 +08:00
|
|
|
private:
|
|
|
|
const Region *R;
|
2016-03-04 06:10:47 +08:00
|
|
|
Loop *Scope;
|
2011-11-07 20:58:54 +08:00
|
|
|
ScalarEvolution &SE;
|
2015-10-08 04:17:36 +08:00
|
|
|
InvariantLoadsSetTy *ILS;
|
2011-11-07 20:58:54 +08:00
|
|
|
|
|
|
|
public:
|
2016-03-04 06:10:47 +08:00
|
|
|
SCEVValidator(const Region *R, Loop *Scope, ScalarEvolution &SE,
|
2016-04-25 21:32:36 +08:00
|
|
|
InvariantLoadsSetTy *ILS)
|
|
|
|
: R(R), Scope(Scope), SE(SE), ILS(ILS) {}
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
class ValidatorResult visitConstant(const SCEVConstant *Constant) {
|
2011-11-07 20:58:54 +08:00
|
|
|
return ValidatorResult(SCEVType::INT);
|
|
|
|
}
|
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
class ValidatorResult visitTruncateExpr(const SCEVTruncateExpr *Expr) {
|
2016-05-12 23:13:49 +08:00
|
|
|
return visit(Expr->getOperand());
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
class ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
|
Model zext-extend instructions
A zero-extended value can be interpreted as a piecewise defined signed
value. If the value was non-negative it stays the same, otherwise it
is the sum of the original value and 2^n where n is the bit-width of
the original (or operand) type. Examples:
zext i8 127 to i32 -> { [127] }
zext i8 -1 to i32 -> { [256 + (-1)] } = { [255] }
zext i8 %v to i32 -> [v] -> { [v] | v >= 0; [256 + v] | v < 0 }
However, LLVM/Scalar Evolution uses zero-extend (potentially lead by a
truncate) to represent some forms of modulo computation. The left-hand side
of the condition in the code below would result in the SCEV
"zext i1 <false, +, true>for.body" which is just another description
of the C expression "i & 1 != 0" or, equivalently, "i % 2 != 0".
for (i = 0; i < N; i++)
if (i & 1 != 0 /* == i % 2 */)
/* do something */
If we do not make the modulo explicit but only use the mechanism described
above we will get the very restrictive assumption "N < 3", because for all
values of N >= 3 the SCEVAddRecExpr operand of the zero-extend would wrap.
Alternatively, we can make the modulo in the operand explicit in the
resulting piecewise function and thereby avoid the assumption on N. For the
example this would result in the following piecewise affine function:
{ [i0] -> [(1)] : 2*floor((-1 + i0)/2) = -1 + i0;
[i0] -> [(0)] : 2*floor((i0)/2) = i0 }
To this end we can first determine if the (immediate) operand of the
zero-extend can wrap and, in case it might, we will use explicit modulo
semantic to compute the result instead of emitting non-wrapping assumptions.
Note that operands with large bit-widths are less likely to be negative
because it would result in a very large access offset or loop bound after the
zero-extend. To this end one can optimistically assume the operand to be
positive and avoid the piecewise definition if the bit-width is bigger than
some threshold (here MaxZextSmallBitWidth).
We choose to go with a hybrid solution of all modeling techniques described
above. For small bit-widths (up to MaxZextSmallBitWidth) we will model the
wrapping explicitly and use a piecewise defined function. However, if the
bit-width is bigger than MaxZextSmallBitWidth we will employ overflow
assumptions and assume the "former negative" piece will not exist.
llvm-svn: 267408
2016-04-25 22:01:36 +08:00
|
|
|
return visit(Expr->getOperand());
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
class ValidatorResult visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
|
2011-11-07 20:58:54 +08:00
|
|
|
return visit(Expr->getOperand());
|
|
|
|
}
|
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
class ValidatorResult visitAddExpr(const SCEVAddExpr *Expr) {
|
2011-11-07 20:58:54 +08:00
|
|
|
ValidatorResult Return(SCEVType::INT);
|
|
|
|
|
|
|
|
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
|
|
|
|
ValidatorResult Op = visit(Expr->getOperand(i));
|
2011-11-17 20:56:19 +08:00
|
|
|
Return.merge(Op);
|
2012-09-08 22:00:37 +08:00
|
|
|
|
|
|
|
// Early exit.
|
|
|
|
if (!Return.isValid())
|
|
|
|
break;
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return Return;
|
|
|
|
}
|
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
class ValidatorResult visitMulExpr(const SCEVMulExpr *Expr) {
|
2011-11-07 20:58:54 +08:00
|
|
|
ValidatorResult Return(SCEVType::INT);
|
|
|
|
|
2013-04-14 21:15:59 +08:00
|
|
|
bool HasMultipleParams = false;
|
|
|
|
|
2011-11-07 20:58:54 +08:00
|
|
|
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
|
|
|
|
ValidatorResult Op = visit(Expr->getOperand(i));
|
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
if (Op.isINT())
|
2011-11-07 20:58:54 +08:00
|
|
|
continue;
|
|
|
|
|
2013-04-10 15:42:28 +08:00
|
|
|
if (Op.isPARAM() && Return.isPARAM()) {
|
2013-05-07 15:30:56 +08:00
|
|
|
HasMultipleParams = true;
|
2013-04-10 15:42:28 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-02-22 16:21:52 +08:00
|
|
|
if ((Op.isIV() || Op.isPARAM()) && !Return.isINT()) {
|
2012-09-08 22:00:37 +08:00
|
|
|
DEBUG(dbgs() << "INVALID: More than one non-int operand in MulExpr\n"
|
|
|
|
<< "\tExpr: " << *Expr << "\n"
|
|
|
|
<< "\tPrevious expression type: " << Return << "\n"
|
2013-02-22 16:21:52 +08:00
|
|
|
<< "\tNext operand (" << Op
|
|
|
|
<< "): " << *Expr->getOperand(i) << "\n");
|
2012-09-08 22:00:37 +08:00
|
|
|
|
2011-11-07 20:58:54 +08:00
|
|
|
return ValidatorResult(SCEVType::INVALID);
|
2012-09-08 22:00:37 +08:00
|
|
|
}
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
Return.merge(Op);
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
|
2015-04-05 22:57:50 +08:00
|
|
|
if (HasMultipleParams && Return.isValid())
|
2013-04-14 21:15:59 +08:00
|
|
|
return ValidatorResult(SCEVType::PARAM, Expr);
|
|
|
|
|
2011-11-07 20:58:54 +08:00
|
|
|
return Return;
|
|
|
|
}
|
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
class ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr) {
|
2012-09-08 22:00:37 +08:00
|
|
|
if (!Expr->isAffine()) {
|
|
|
|
DEBUG(dbgs() << "INVALID: AddRec is not affine");
|
2011-11-07 20:58:54 +08:00
|
|
|
return ValidatorResult(SCEVType::INVALID);
|
2012-09-08 22:00:37 +08:00
|
|
|
}
|
2011-11-07 20:58:54 +08:00
|
|
|
|
|
|
|
ValidatorResult Start = visit(Expr->getStart());
|
|
|
|
ValidatorResult Recurrence = visit(Expr->getStepRecurrence(SE));
|
|
|
|
|
2012-09-08 22:00:37 +08:00
|
|
|
if (!Start.isValid())
|
|
|
|
return Start;
|
|
|
|
|
|
|
|
if (!Recurrence.isValid())
|
|
|
|
return Recurrence;
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2016-03-04 06:10:52 +08:00
|
|
|
auto *L = Expr->getLoop();
|
|
|
|
if (R->contains(L) && (!Scope || !L->contains(Scope))) {
|
|
|
|
DEBUG(dbgs() << "INVALID: AddRec out of a loop whose exit value is not "
|
|
|
|
"synthesizable");
|
|
|
|
return ValidatorResult(SCEVType::INVALID);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (R->contains(L)) {
|
2011-11-17 20:56:14 +08:00
|
|
|
if (Recurrence.isINT()) {
|
|
|
|
ValidatorResult Result(SCEVType::IV);
|
|
|
|
Result.addParamsFrom(Start);
|
|
|
|
return Result;
|
|
|
|
}
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2012-09-08 22:00:37 +08:00
|
|
|
DEBUG(dbgs() << "INVALID: AddRec within scop has non-int"
|
|
|
|
"recurrence part");
|
2011-11-17 20:56:14 +08:00
|
|
|
return ValidatorResult(SCEVType::INVALID);
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
|
2013-02-22 16:21:52 +08:00
|
|
|
assert(Start.isConstant() && Recurrence.isConstant() &&
|
|
|
|
"Expected 'Start' and 'Recurrence' to be constant");
|
2013-08-05 23:14:15 +08:00
|
|
|
|
|
|
|
// 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),
|
2015-04-27 03:55:21 +08:00
|
|
|
Expr->getStepRecurrence(SE), Expr->getLoop(), Expr->getNoWrapFlags());
|
2013-08-05 23:14:15 +08:00
|
|
|
|
|
|
|
ValidatorResult ZeroStartResult =
|
|
|
|
ValidatorResult(SCEVType::PARAM, ZeroStartExpr);
|
|
|
|
ZeroStartResult.addParamsFrom(Start);
|
|
|
|
|
|
|
|
return ZeroStartResult;
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
class ValidatorResult visitSMaxExpr(const SCEVSMaxExpr *Expr) {
|
2013-12-10 05:51:46 +08:00
|
|
|
ValidatorResult Return(SCEVType::INT);
|
2011-11-07 20:58:54 +08:00
|
|
|
|
|
|
|
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
|
|
|
|
ValidatorResult Op = visit(Expr->getOperand(i));
|
|
|
|
|
|
|
|
if (!Op.isValid())
|
2012-09-08 22:00:37 +08:00
|
|
|
return Op;
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
Return.merge(Op);
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return Return;
|
|
|
|
}
|
|
|
|
|
2011-11-17 20:56:19 +08:00
|
|
|
class ValidatorResult visitUMaxExpr(const SCEVUMaxExpr *Expr) {
|
2016-05-12 23:15:50 +08:00
|
|
|
// We do not support unsigned max operations. If 'Expr' is constant during
|
|
|
|
// Scop execution we treat this as a parameter, otherwise we bail out.
|
2011-11-07 20:58:54 +08:00
|
|
|
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
|
|
|
|
ValidatorResult Op = visit(Expr->getOperand(i));
|
|
|
|
|
2012-09-08 22:00:37 +08:00
|
|
|
if (!Op.isConstant()) {
|
|
|
|
DEBUG(dbgs() << "INVALID: UMaxExpr has a non-constant operand");
|
2011-11-07 20:58:54 +08:00
|
|
|
return ValidatorResult(SCEVType::INVALID);
|
2012-09-08 22:00:37 +08:00
|
|
|
}
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
|
2012-03-16 18:16:28 +08:00
|
|
|
return ValidatorResult(SCEVType::PARAM, Expr);
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
|
2015-02-11 22:54:50 +08:00
|
|
|
ValidatorResult visitGenericInst(Instruction *I, const SCEV *S) {
|
|
|
|
if (R->contains(I)) {
|
|
|
|
DEBUG(dbgs() << "INVALID: UnknownExpr references an instruction "
|
|
|
|
"within the region\n");
|
|
|
|
return ValidatorResult(SCEVType::INVALID);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ValidatorResult(SCEVType::PARAM, S);
|
|
|
|
}
|
|
|
|
|
2015-10-08 04:17:36 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-04-29 19:53:35 +08:00
|
|
|
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))
|
|
|
|
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);
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "INVALID: unsigned division of non-constant expressions");
|
|
|
|
return ValidatorResult(SCEVType::INVALID);
|
|
|
|
}
|
|
|
|
|
|
|
|
ValidatorResult visitUDivExpr(const SCEVUDivExpr *Expr) {
|
|
|
|
auto *Dividend = Expr->getLHS();
|
|
|
|
auto *Divisor = Expr->getRHS();
|
|
|
|
return visitDivision(Dividend, Divisor, Expr);
|
|
|
|
}
|
|
|
|
|
|
|
|
ValidatorResult visitSDivInstruction(Instruction *SDiv, const SCEV *Expr) {
|
2015-02-11 22:54:50 +08:00
|
|
|
assert(SDiv->getOpcode() == Instruction::SDiv &&
|
|
|
|
"Assumed SDiv instruction!");
|
|
|
|
|
2016-04-29 19:53:35 +08:00
|
|
|
auto *Dividend = SE.getSCEV(SDiv->getOperand(0));
|
|
|
|
auto *Divisor = SE.getSCEV(SDiv->getOperand(1));
|
|
|
|
return visitDivision(Dividend, Divisor, Expr, SDiv);
|
2015-02-11 22:54:50 +08:00
|
|
|
}
|
|
|
|
|
2015-06-24 12:13:29 +08:00
|
|
|
ValidatorResult visitSRemInstruction(Instruction *SRem, const SCEV *S) {
|
2015-09-14 19:14:23 +08:00
|
|
|
assert(SRem->getOpcode() == Instruction::SRem &&
|
|
|
|
"Assumed SRem instruction!");
|
|
|
|
|
|
|
|
auto *Divisor = SRem->getOperand(1);
|
|
|
|
auto *CI = dyn_cast<ConstantInt>(Divisor);
|
|
|
|
if (!CI)
|
|
|
|
return visitGenericInst(SRem, S);
|
|
|
|
|
|
|
|
auto *Dividend = SRem->getOperand(0);
|
|
|
|
auto *DividendSCEV = SE.getSCEV(Dividend);
|
|
|
|
return visit(DividendSCEV);
|
2015-06-24 12:13:29 +08:00
|
|
|
}
|
|
|
|
|
2011-11-17 20:56:10 +08:00
|
|
|
ValidatorResult visitUnknown(const SCEVUnknown *Expr) {
|
2011-11-07 20:58:54 +08:00
|
|
|
Value *V = Expr->getValue();
|
|
|
|
|
2016-04-10 17:50:10 +08:00
|
|
|
if (!Expr->getType()->isIntegerTy() && !Expr->getType()->isPointerTy()) {
|
|
|
|
DEBUG(dbgs() << "INVALID: UnknownExpr is not an integer or pointer");
|
2012-03-17 00:36:47 +08:00
|
|
|
return ValidatorResult(SCEVType::INVALID);
|
2012-09-08 22:00:37 +08:00
|
|
|
}
|
2012-03-17 00:36:47 +08:00
|
|
|
|
2012-09-08 22:00:37 +08:00
|
|
|
if (isa<UndefValue>(V)) {
|
|
|
|
DEBUG(dbgs() << "INVALID: UnknownExpr references an undef value");
|
2011-11-07 20:58:54 +08:00
|
|
|
return ValidatorResult(SCEVType::INVALID);
|
2012-09-08 22:00:37 +08:00
|
|
|
}
|
2011-11-07 20:58:54 +08:00
|
|
|
|
2015-02-11 22:54:50 +08:00
|
|
|
if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
|
|
|
|
switch (I->getOpcode()) {
|
2015-10-08 04:17:36 +08:00
|
|
|
case Instruction::Load:
|
|
|
|
return visitLoadInstruction(I, Expr);
|
2015-02-11 22:54:50 +08:00
|
|
|
case Instruction::SDiv:
|
|
|
|
return visitSDivInstruction(I, Expr);
|
2015-06-24 12:13:29 +08:00
|
|
|
case Instruction::SRem:
|
|
|
|
return visitSRemInstruction(I, Expr);
|
2015-02-11 22:54:50 +08:00
|
|
|
default:
|
|
|
|
return visitGenericInst(I, Expr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-10 20:45:03 +08:00
|
|
|
return ValidatorResult(SCEVType::PARAM, Expr);
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-03-19 04:21:13 +08:00
|
|
|
/// @brief Check whether a SCEV refers to an SSA name defined inside a region.
|
2016-04-18 23:46:27 +08:00
|
|
|
class SCEVInRegionDependences {
|
|
|
|
const Region *R;
|
|
|
|
Loop *Scope;
|
|
|
|
bool AllowLoops;
|
|
|
|
bool HasInRegionDeps = false;
|
2013-03-19 04:21:13 +08:00
|
|
|
|
2016-04-18 23:46:27 +08:00
|
|
|
public:
|
2016-03-02 05:44:06 +08:00
|
|
|
SCEVInRegionDependences(const Region *R, Loop *Scope, bool AllowLoops)
|
|
|
|
: R(R), Scope(Scope), AllowLoops(AllowLoops) {}
|
2013-03-19 04:21:13 +08:00
|
|
|
|
2016-04-18 23:46:27 +08:00
|
|
|
bool follow(const SCEV *S) {
|
|
|
|
if (auto Unknown = dyn_cast<SCEVUnknown>(S)) {
|
|
|
|
Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
|
2013-03-19 04:21:13 +08:00
|
|
|
|
2016-04-18 23:46:27 +08:00
|
|
|
// Return true when Inst is defined inside the region R.
|
|
|
|
if (Inst && R->contains(Inst)) {
|
|
|
|
HasInRegionDeps = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (auto AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
|
|
|
|
if (!AllowLoops) {
|
|
|
|
if (!Scope) {
|
|
|
|
HasInRegionDeps = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto *L = AddRec->getLoop();
|
|
|
|
if (R->contains(L) && !L->contains(Scope)) {
|
|
|
|
HasInRegionDeps = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2016-03-02 05:44:06 +08:00
|
|
|
}
|
2016-04-18 23:46:27 +08:00
|
|
|
return true;
|
2013-03-19 04:21:13 +08:00
|
|
|
}
|
2016-04-18 23:46:27 +08:00
|
|
|
bool isDone() { return false; }
|
|
|
|
bool hasDependences() { return HasInRegionDeps; }
|
2013-03-19 04:21:13 +08:00
|
|
|
};
|
|
|
|
|
2011-11-07 20:58:54 +08:00
|
|
|
namespace polly {
|
2014-11-16 05:32:53 +08:00
|
|
|
/// 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 {
|
2016-04-08 18:25:58 +08:00
|
|
|
ScalarEvolution &SE;
|
2014-11-16 05:32:53 +08:00
|
|
|
SetVector<Value *> &Values;
|
|
|
|
|
|
|
|
public:
|
2016-04-08 18:25:58 +08:00
|
|
|
SCEVFindValues(ScalarEvolution &SE, SetVector<Value *> &Values)
|
|
|
|
: SE(SE), Values(Values) {}
|
2014-11-16 05:32:53 +08:00
|
|
|
|
|
|
|
bool follow(const SCEV *S) {
|
2016-04-08 18:25:58 +08:00
|
|
|
const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(S);
|
|
|
|
if (!Unknown)
|
|
|
|
return true;
|
|
|
|
|
2016-04-09 22:30:11 +08:00
|
|
|
Values.insert(Unknown->getValue());
|
2016-04-08 18:25:58 +08:00
|
|
|
Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
|
|
|
|
if (!Inst || (Inst->getOpcode() != Instruction::SRem &&
|
2016-04-09 22:30:11 +08:00
|
|
|
Inst->getOpcode() != Instruction::SDiv))
|
2016-04-08 18:25:58 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
auto *Dividend = SE.getSCEV(Inst->getOperand(1));
|
2016-04-09 22:30:11 +08:00
|
|
|
if (!isa<SCEVConstant>(Dividend))
|
2016-04-08 18:25:58 +08:00
|
|
|
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;
|
2014-11-16 05:32:53 +08:00
|
|
|
}
|
|
|
|
bool isDone() { return false; }
|
|
|
|
};
|
|
|
|
|
2016-04-08 18:25:58 +08:00
|
|
|
void findValues(const SCEV *Expr, ScalarEvolution &SE,
|
|
|
|
SetVector<Value *> &Values) {
|
|
|
|
SCEVFindValues FindValues(SE, Values);
|
2014-11-16 05:32:53 +08:00
|
|
|
SCEVTraversal<SCEVFindValues> ST(FindValues);
|
|
|
|
ST.visitAll(Expr);
|
|
|
|
}
|
|
|
|
|
2016-03-02 05:44:06 +08:00
|
|
|
bool hasScalarDepsInsideRegion(const SCEV *Expr, const Region *R,
|
|
|
|
llvm::Loop *Scope, bool AllowLoops) {
|
2016-04-18 23:46:27 +08:00
|
|
|
SCEVInRegionDependences InRegionDeps(R, Scope, AllowLoops);
|
|
|
|
SCEVTraversal<SCEVInRegionDependences> ST(InRegionDeps);
|
|
|
|
ST.visitAll(Expr);
|
|
|
|
return InRegionDeps.hasDependences();
|
2013-03-23 09:05:07 +08:00
|
|
|
}
|
2013-03-19 04:21:13 +08:00
|
|
|
|
2016-03-04 06:10:47 +08:00
|
|
|
bool isAffineExpr(const Region *R, llvm::Loop *Scope, const SCEV *Expr,
|
2016-04-25 21:32:36 +08:00
|
|
|
ScalarEvolution &SE, InvariantLoadsSetTy *ILS) {
|
2013-03-23 09:05:07 +08:00
|
|
|
if (isa<SCEVCouldNotCompute>(Expr))
|
2013-02-22 16:21:52 +08:00
|
|
|
return false;
|
|
|
|
|
2016-04-25 21:32:36 +08:00
|
|
|
SCEVValidator Validator(R, Scope, SE, ILS);
|
2014-10-23 07:00:03 +08:00
|
|
|
DEBUG({
|
|
|
|
dbgs() << "\n";
|
|
|
|
dbgs() << "Expr: " << *Expr << "\n";
|
|
|
|
dbgs() << "Region: " << R->getNameStr() << "\n";
|
|
|
|
dbgs() << " -> ";
|
|
|
|
});
|
2013-02-22 16:21:52 +08:00
|
|
|
|
|
|
|
ValidatorResult Result = Validator.visit(Expr);
|
|
|
|
|
2014-10-23 07:00:03 +08:00
|
|
|
DEBUG({
|
|
|
|
if (Result.isValid())
|
|
|
|
dbgs() << "VALID\n";
|
|
|
|
dbgs() << "\n";
|
|
|
|
});
|
2013-02-22 16:21:52 +08:00
|
|
|
|
|
|
|
return Result.isValid();
|
|
|
|
}
|
2011-11-08 23:41:28 +08:00
|
|
|
|
2016-05-10 22:00:57 +08:00
|
|
|
static bool isAffineExpr(Value *V, const Region *R, Loop *Scope,
|
|
|
|
ScalarEvolution &SE, ParameterSetTy &Params) {
|
2015-11-12 11:25:01 +08:00
|
|
|
auto *E = SE.getSCEV(V);
|
|
|
|
if (isa<SCEVCouldNotCompute>(E))
|
|
|
|
return false;
|
|
|
|
|
2016-04-25 21:32:36 +08:00
|
|
|
SCEVValidator Validator(R, Scope, SE, nullptr);
|
2015-11-12 11:25:01 +08:00
|
|
|
ValidatorResult Result = Validator.visit(E);
|
2016-05-10 22:00:57 +08:00
|
|
|
if (!Result.isValid())
|
2015-11-12 11:25:01 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
auto ResultParams = Result.getParameters();
|
2016-04-25 21:33:07 +08:00
|
|
|
Params.insert(ResultParams.begin(), ResultParams.end());
|
2015-11-12 11:25:01 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-05-10 22:00:57 +08:00
|
|
|
bool isAffineConstraint(Value *V, const Region *R, llvm::Loop *Scope,
|
|
|
|
ScalarEvolution &SE, ParameterSetTy &Params,
|
|
|
|
bool OrExpr) {
|
2015-11-12 11:25:01 +08:00
|
|
|
if (auto *ICmp = dyn_cast<ICmpInst>(V)) {
|
2016-05-10 22:00:57 +08:00
|
|
|
return isAffineConstraint(ICmp->getOperand(0), R, Scope, SE, Params,
|
|
|
|
true) &&
|
|
|
|
isAffineConstraint(ICmp->getOperand(1), R, Scope, SE, Params, true);
|
2015-11-12 11:25:01 +08:00
|
|
|
} else if (auto *BinOp = dyn_cast<BinaryOperator>(V)) {
|
|
|
|
auto Opcode = BinOp->getOpcode();
|
|
|
|
if (Opcode == Instruction::And || Opcode == Instruction::Or)
|
2016-05-10 22:00:57 +08:00
|
|
|
return isAffineConstraint(BinOp->getOperand(0), R, Scope, SE, Params,
|
|
|
|
false) &&
|
|
|
|
isAffineConstraint(BinOp->getOperand(1), R, Scope, SE, Params,
|
|
|
|
false);
|
2015-11-12 11:25:01 +08:00
|
|
|
/* Fall through */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!OrExpr)
|
|
|
|
return false;
|
|
|
|
|
2016-05-10 22:00:57 +08:00
|
|
|
return isAffineExpr(V, R, Scope, SE, Params);
|
2015-11-12 11:25:01 +08:00
|
|
|
}
|
|
|
|
|
2016-04-25 21:33:07 +08:00
|
|
|
ParameterSetTy getParamsInAffineExpr(const Region *R, Loop *Scope,
|
|
|
|
const SCEV *Expr, ScalarEvolution &SE) {
|
2013-02-22 16:21:52 +08:00
|
|
|
if (isa<SCEVCouldNotCompute>(Expr))
|
2016-04-25 21:33:07 +08:00
|
|
|
return ParameterSetTy();
|
2011-11-08 23:41:28 +08:00
|
|
|
|
2015-10-08 04:17:36 +08:00
|
|
|
InvariantLoadsSetTy ILS;
|
2016-04-25 21:32:36 +08:00
|
|
|
SCEVValidator Validator(R, Scope, SE, &ILS);
|
2013-02-22 16:21:52 +08:00
|
|
|
ValidatorResult Result = Validator.visit(Expr);
|
2015-05-04 00:03:01 +08:00
|
|
|
assert(Result.isValid() && "Requested parameters for an invalid SCEV!");
|
2011-11-08 23:41:28 +08:00
|
|
|
|
2013-02-22 16:21:52 +08:00
|
|
|
return Result.getParameters();
|
|
|
|
}
|
2015-03-30 04:45:09 +08:00
|
|
|
|
2016-02-15 06:30:56 +08:00
|
|
|
std::pair<const SCEVConstant *, const SCEV *>
|
2015-03-30 04:45:09 +08:00
|
|
|
extractConstantFactor(const SCEV *S, ScalarEvolution &SE) {
|
|
|
|
|
2016-02-15 06:30:56 +08:00
|
|
|
auto *LeftOver = SE.getConstant(S->getType(), 1);
|
|
|
|
auto *ConstPart = cast<SCEVConstant>(SE.getConstant(S->getType(), 1));
|
|
|
|
|
|
|
|
if (auto *Constant = dyn_cast<SCEVConstant>(S))
|
|
|
|
return std::make_pair(Constant, LeftOver);
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2015-03-30 04:45:09 +08:00
|
|
|
|
2016-04-26 03:09:10 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-02-15 06:30:56 +08:00
|
|
|
auto *Mul = dyn_cast<SCEVMulExpr>(S);
|
|
|
|
if (!Mul)
|
2015-03-30 04:45:09 +08:00
|
|
|
return std::make_pair(ConstPart, S);
|
|
|
|
|
2016-02-15 06:30:56 +08:00
|
|
|
for (auto *Op : Mul->operands())
|
2015-03-30 04:45:09 +08:00
|
|
|
if (isa<SCEVConstant>(Op))
|
2016-02-15 06:30:56 +08:00
|
|
|
ConstPart = cast<SCEVConstant>(SE.getMulExpr(ConstPart, Op));
|
2015-03-30 04:45:09 +08:00
|
|
|
else
|
|
|
|
LeftOver = SE.getMulExpr(LeftOver, Op);
|
|
|
|
|
|
|
|
return std::make_pair(ConstPart, LeftOver);
|
|
|
|
}
|
2011-11-07 20:58:54 +08:00
|
|
|
}
|