2011-04-29 14:27:02 +08:00
|
|
|
//===----- ScopDetection.cpp - Detect Scops --------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Detect the maximal Scops of a function.
|
|
|
|
//
|
|
|
|
// A static control part (Scop) is a subgraph of the control flow graph (CFG)
|
|
|
|
// that only has statically known control flow and can therefore be described
|
|
|
|
// within the polyhedral model.
|
|
|
|
//
|
|
|
|
// Every Scop fullfills these restrictions:
|
|
|
|
//
|
|
|
|
// * It is a single entry single exit region
|
|
|
|
//
|
|
|
|
// * Only affine linear bounds in the loops
|
|
|
|
//
|
|
|
|
// Every natural loop in a Scop must have a number of loop iterations that can
|
|
|
|
// be described as an affine linear function in surrounding loop iterators or
|
|
|
|
// parameters. (A parameter is a scalar that does not change its value during
|
|
|
|
// execution of the Scop).
|
|
|
|
//
|
|
|
|
// * Only comparisons of affine linear expressions in conditions
|
|
|
|
//
|
|
|
|
// * All loops and conditions perfectly nested
|
|
|
|
//
|
|
|
|
// The control flow needs to be structured such that it could be written using
|
|
|
|
// just 'for' and 'if' statements, without the need for any 'goto', 'break' or
|
|
|
|
// 'continue'.
|
|
|
|
//
|
|
|
|
// * Side effect free functions call
|
|
|
|
//
|
|
|
|
// Only function calls and intrinsics that do not have side effects are allowed
|
|
|
|
// (readnone).
|
|
|
|
//
|
|
|
|
// The Scop detection finds the largest Scops by checking if the largest
|
|
|
|
// region is a Scop. If this is not the case, its canonical subregions are
|
|
|
|
// checked until a region is a Scop. It is now tried to extend this Scop by
|
|
|
|
// creating a larger non canonical region.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-03-21 02:03:18 +08:00
|
|
|
#include "polly/CodeGen/BlockGenerators.h"
|
2011-04-29 14:27:02 +08:00
|
|
|
#include "polly/LinkAllPasses.h"
|
2013-05-07 15:31:10 +08:00
|
|
|
#include "polly/Options.h"
|
2013-03-21 02:03:18 +08:00
|
|
|
#include "polly/ScopDetection.h"
|
2011-11-07 20:58:54 +08:00
|
|
|
#include "polly/Support/SCEVValidator.h"
|
2013-05-07 16:11:54 +08:00
|
|
|
#include "polly/Support/ScopHelper.h"
|
2011-04-29 14:27:02 +08:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
|
|
|
#include "llvm/Analysis/AliasAnalysis.h"
|
2011-11-10 06:35:00 +08:00
|
|
|
#include "llvm/Analysis/LoopInfo.h"
|
2011-04-29 14:27:02 +08:00
|
|
|
#include "llvm/Analysis/RegionIterator.h"
|
2011-11-10 06:35:00 +08:00
|
|
|
#include "llvm/Analysis/ScalarEvolution.h"
|
2011-11-10 20:44:50 +08:00
|
|
|
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
2011-04-29 14:27:02 +08:00
|
|
|
#include "llvm/Assembly/Writer.h"
|
2013-05-07 16:11:54 +08:00
|
|
|
#include "llvm/DebugInfo.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
#define DEBUG_TYPE "polly-detect"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
|
2011-11-08 23:41:28 +08:00
|
|
|
#include <set>
|
|
|
|
|
2011-04-29 14:27:02 +08:00
|
|
|
using namespace llvm;
|
|
|
|
using namespace polly;
|
|
|
|
|
2013-05-31 01:47:32 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
DetectScopsWithoutLoops("polly-detect-scops-in-functions-without-loops",
|
|
|
|
cl::desc("Detect scops in functions without loops"),
|
|
|
|
cl::Hidden, cl::init(false), cl::cat(PollyCategory));
|
|
|
|
|
2013-06-04 00:35:37 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
DetectRegionsWithoutLoops("polly-detect-scops-in-regions-without-loops",
|
|
|
|
cl::desc("Detect scops in regions without loops"),
|
|
|
|
cl::Hidden, cl::init(false), cl::cat(PollyCategory));
|
|
|
|
|
2011-10-23 19:17:06 +08:00
|
|
|
static cl::opt<std::string>
|
2013-05-07 15:31:10 +08:00
|
|
|
OnlyFunction("polly-only-func", cl::desc("Only run on a single function"),
|
|
|
|
cl::value_desc("function-name"), cl::ValueRequired, cl::init(""),
|
|
|
|
cl::cat(PollyCategory));
|
2011-10-23 19:17:06 +08:00
|
|
|
|
2011-11-10 20:47:26 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
IgnoreAliasing("polly-ignore-aliasing",
|
|
|
|
cl::desc("Ignore possible aliasing of the array bases"),
|
2013-05-07 15:31:10 +08:00
|
|
|
cl::Hidden, cl::init(false), cl::cat(PollyCategory));
|
2011-10-23 19:17:06 +08:00
|
|
|
|
2013-05-07 15:31:10 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
ReportLevel("polly-report",
|
|
|
|
cl::desc("Print information about the activities of Polly"),
|
|
|
|
cl::init(false), cl::cat(PollyCategory));
|
2012-11-02 00:45:20 +08:00
|
|
|
|
2011-12-20 18:43:14 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
AllowNonAffine("polly-allow-nonaffine",
|
|
|
|
cl::desc("Allow non affine access functions in arrays"),
|
2013-05-07 15:31:10 +08:00
|
|
|
cl::Hidden, cl::init(false), cl::cat(PollyCategory));
|
2011-12-20 18:43:14 +08:00
|
|
|
|
2013-07-25 11:02:29 +08:00
|
|
|
static cl::opt<bool, true>
|
|
|
|
TrackFailures("polly-detect-track-failures",
|
|
|
|
cl::desc("Track failure strings in detecting scop regions"),
|
|
|
|
cl::location(PollyTrackFailures), cl::Hidden, cl::init(false),
|
|
|
|
cl::cat(PollyCategory));
|
|
|
|
|
|
|
|
bool polly::PollyTrackFailures = false;
|
|
|
|
|
2011-04-29 14:27:02 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Statistics.
|
|
|
|
|
|
|
|
STATISTIC(ValidRegion, "Number of regions that a valid part of Scop");
|
|
|
|
|
2013-01-15 06:40:23 +08:00
|
|
|
#define BADSCOP_STAT(NAME, DESC) \
|
|
|
|
STATISTIC(Bad##NAME##ForScop, "Number of bad regions for Scop: " DESC)
|
|
|
|
|
|
|
|
#define INVALID(NAME, MESSAGE) \
|
|
|
|
do { \
|
2013-07-25 11:02:29 +08:00
|
|
|
if (PollyTrackFailures) { \
|
|
|
|
std::string Buf; \
|
|
|
|
raw_string_ostream fmt(Buf); \
|
|
|
|
fmt << MESSAGE; \
|
|
|
|
fmt.flush(); \
|
|
|
|
LastFailure = Buf; \
|
|
|
|
} \
|
2013-01-15 06:40:23 +08:00
|
|
|
DEBUG(dbgs() << MESSAGE); \
|
|
|
|
DEBUG(dbgs() << "\n"); \
|
2013-11-16 09:07:06 +08:00
|
|
|
assert(!Context.Verifying && #NAME); \
|
2013-01-15 06:40:23 +08:00
|
|
|
if (!Context.Verifying) \
|
|
|
|
++Bad##NAME##ForScop; \
|
2013-03-20 05:44:07 +08:00
|
|
|
} while (0)
|
2011-11-10 21:21:43 +08:00
|
|
|
|
2013-01-15 06:40:23 +08:00
|
|
|
#define INVALID_NOVERIFY(NAME, MESSAGE) \
|
|
|
|
do { \
|
2013-07-25 11:02:29 +08:00
|
|
|
if (PollyTrackFailures) { \
|
|
|
|
std::string Buf; \
|
|
|
|
raw_string_ostream fmt(Buf); \
|
|
|
|
fmt << MESSAGE; \
|
|
|
|
fmt.flush(); \
|
|
|
|
LastFailure = Buf; \
|
|
|
|
} \
|
2013-01-15 06:40:23 +08:00
|
|
|
DEBUG(dbgs() << MESSAGE); \
|
|
|
|
DEBUG(dbgs() << "\n"); \
|
|
|
|
/* DISABLED: assert(!Context.Verifying && #NAME); */ \
|
|
|
|
if (!Context.Verifying) \
|
|
|
|
++Bad##NAME##ForScop; \
|
2013-03-20 05:44:07 +08:00
|
|
|
} while (0)
|
2011-10-08 08:30:48 +08:00
|
|
|
|
2013-01-15 06:40:23 +08:00
|
|
|
BADSCOP_STAT(CFG, "CFG too complex");
|
|
|
|
BADSCOP_STAT(IndVar, "Non canonical induction variable in loop");
|
2013-06-12 06:20:40 +08:00
|
|
|
BADSCOP_STAT(IndEdge, "Found invalid region entering edges");
|
2013-01-15 06:40:23 +08:00
|
|
|
BADSCOP_STAT(LoopBound, "Loop bounds can not be computed");
|
|
|
|
BADSCOP_STAT(FuncCall, "Function call with side effects appeared");
|
|
|
|
BADSCOP_STAT(AffFunc, "Expression not affine");
|
|
|
|
BADSCOP_STAT(Alias, "Found base address alias");
|
2013-04-16 16:04:42 +08:00
|
|
|
BADSCOP_STAT(SimpleLoop, "Loop not in -loop-simplify form");
|
2013-01-15 06:40:23 +08:00
|
|
|
BADSCOP_STAT(Other, "Others");
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ScopDetection.
|
|
|
|
bool ScopDetection::isMaxRegionInScop(const Region &R) const {
|
|
|
|
// The Region is valid only if it could be found in the set.
|
|
|
|
return ValidRegions.count(&R);
|
|
|
|
}
|
|
|
|
|
2011-10-08 08:30:55 +08:00
|
|
|
std::string ScopDetection::regionIsInvalidBecause(const Region *R) const {
|
|
|
|
if (!InvalidRegions.count(R))
|
|
|
|
return "";
|
|
|
|
|
|
|
|
return InvalidRegions.find(R)->second;
|
|
|
|
}
|
|
|
|
|
2013-05-07 15:30:56 +08:00
|
|
|
bool ScopDetection::isValidCFG(BasicBlock &BB,
|
|
|
|
DetectionContext &Context) const {
|
2011-04-29 14:27:02 +08:00
|
|
|
Region &RefRegion = Context.CurRegion;
|
|
|
|
TerminatorInst *TI = BB.getTerminator();
|
|
|
|
|
|
|
|
// Return instructions are only valid if the region is the top level region.
|
|
|
|
if (isa<ReturnInst>(TI) && !RefRegion.getExit() && TI->getNumOperands() == 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
BranchInst *Br = dyn_cast<BranchInst>(TI);
|
|
|
|
|
2013-07-22 11:50:33 +08:00
|
|
|
if (!Br) {
|
2011-11-17 22:52:36 +08:00
|
|
|
INVALID(CFG, "Non branch instruction terminates BB: " + BB.getName());
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2013-01-15 06:40:23 +08:00
|
|
|
if (Br->isUnconditional())
|
|
|
|
return true;
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
Value *Condition = Br->getCondition();
|
|
|
|
|
|
|
|
// UndefValue is not allowed as condition.
|
2013-07-22 11:50:33 +08:00
|
|
|
if (isa<UndefValue>(Condition)) {
|
2012-12-30 07:47:38 +08:00
|
|
|
INVALID(AffFunc, "Condition based on 'undef' value in BB: " + BB.getName());
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
// Only Constant and ICmpInst are allowed as condition.
|
2013-07-22 11:50:33 +08:00
|
|
|
if (!(isa<Constant>(Condition) || isa<ICmpInst>(Condition))) {
|
2013-03-23 09:05:07 +08:00
|
|
|
INVALID(AffFunc, "Condition in BB '" + BB.getName() +
|
2013-04-10 14:55:45 +08:00
|
|
|
"' neither constant nor an icmp instruction");
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
// Allow perfectly nested conditions.
|
|
|
|
assert(Br->getNumSuccessors() == 2 && "Unexpected number of successors");
|
|
|
|
|
|
|
|
if (ICmpInst *ICmp = dyn_cast<ICmpInst>(Condition)) {
|
|
|
|
// Unsigned comparisons are not allowed. They trigger overflow problems
|
|
|
|
// in the code generation.
|
|
|
|
//
|
|
|
|
// TODO: This is not sufficient and just hides bugs. However it does pretty
|
|
|
|
// well.
|
2012-12-30 07:47:38 +08:00
|
|
|
if (ICmp->isUnsigned())
|
2011-04-29 14:27:02 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Are both operands of the ICmp affine?
|
2013-01-15 06:40:23 +08:00
|
|
|
if (isa<UndefValue>(ICmp->getOperand(0)) ||
|
2013-07-22 11:50:33 +08:00
|
|
|
isa<UndefValue>(ICmp->getOperand(1))) {
|
2011-11-17 22:52:36 +08:00
|
|
|
INVALID(AffFunc, "undef operand in branch at BB: " + BB.getName());
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
scop detection: properly instantiate SCEVs to the place where they are used
Fix inspired from c2d4a0627e95c34a819b9d4ffb4db62daa78dade.
Given the following code
for (i = 0; i < 10; i++) {
;
}
S: A[i] = 0
When translate the data reference A[i] in statement S using scev, we need to
retrieve the scev of 'i' at the location of 'S'. If we do not do this the
scev that we obtain will be expressed as {0,+,1}_for and will reference loop
iterators that do not surround 'S'. What we really want is the scev to be
instantiated to the value of 'i' after the loop. This value is {10}.
This used to crash in:
int loopDimension = getLoopDepth(Expr->getLoop());
isl_aff *LAff = isl_aff_set_coefficient_si(
isl_aff_zero_on_domain(LocalSpace), isl_dim_in, loopDimension, 1);
(gdb) p Expr->dump()
{8,+,8}<nw><%do.body>
(gdb) p getLoopDepth(Expr->getLoop())
$5 = 0
isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces);
isl_local_space *LocalSpace = isl_local_space_from_space(Space);
As we are trying to create a memory access in a stmt that is outside all loops,
LocalSpace has 0 dimensions:
(gdb) p NbLoopSpaces
$12 = 0
(gdb) p Statement.BB->dump()
if.then: ; preds = %do.end
%0 = load float* %add.ptr, align 4
store float %0, float* %q.1.reg2mem, align 4
br label %if.end.single_exit
and so the scev for %add.ptr should be taken at the place where it is used,
i.e., it should be the value on the last iteration of the do.body loop, and not
"{8,+,8}<nw><%do.body>".
llvm-svn: 179148
2013-04-10 12:05:18 +08:00
|
|
|
Loop *L = LI->getLoopFor(ICmp->getParent());
|
|
|
|
const SCEV *LHS = SE->getSCEVAtScope(ICmp->getOperand(0), L);
|
|
|
|
const SCEV *RHS = SE->getSCEVAtScope(ICmp->getOperand(1), L);
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2011-11-10 20:45:11 +08:00
|
|
|
if (!isAffineExpr(&Context.CurRegion, LHS, *SE) ||
|
2013-07-22 11:50:33 +08:00
|
|
|
!isAffineExpr(&Context.CurRegion, RHS, *SE)) {
|
2013-07-28 17:05:20 +08:00
|
|
|
INVALID(AffFunc, "Non affine branch in BB '" << BB.getName()
|
|
|
|
<< "' with LHS: " << *LHS
|
|
|
|
<< " and RHS: " << *RHS);
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Allow loop exit conditions.
|
|
|
|
Loop *L = LI->getLoopFor(&BB);
|
|
|
|
if (L && L->getExitingBlock() == &BB)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Allow perfectly nested conditions.
|
|
|
|
Region *R = RI->getRegionFor(&BB);
|
2013-07-22 11:50:33 +08:00
|
|
|
if (R->getEntry() != &BB) {
|
2011-11-17 22:52:36 +08:00
|
|
|
INVALID(CFG, "Not well structured condition at BB: " + BB.getName());
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ScopDetection::isValidCallInst(CallInst &CI) {
|
|
|
|
if (CI.mayHaveSideEffects() || CI.doesNotReturn())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (CI.doesNotAccessMemory())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
Function *CalledFunction = CI.getCalledFunction();
|
|
|
|
|
|
|
|
// Indirect calls are not supported.
|
|
|
|
if (CalledFunction == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// TODO: Intrinsics.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-07-25 11:02:29 +08:00
|
|
|
std::string ScopDetection::formatInvalidAlias(AliasSet &AS) const {
|
|
|
|
std::string Message;
|
|
|
|
raw_string_ostream OS(Message);
|
|
|
|
|
|
|
|
OS << "Possible aliasing: ";
|
|
|
|
|
|
|
|
std::vector<Value *> Pointers;
|
|
|
|
|
|
|
|
for (AliasSet::iterator AI = AS.begin(), AE = AS.end(); AI != AE; ++AI)
|
|
|
|
Pointers.push_back(AI.getPointer());
|
|
|
|
|
|
|
|
std::sort(Pointers.begin(), Pointers.end());
|
|
|
|
|
|
|
|
for (std::vector<Value *>::iterator PI = Pointers.begin(),
|
|
|
|
PE = Pointers.end();
|
|
|
|
;) {
|
|
|
|
Value *V = *PI;
|
|
|
|
|
|
|
|
if (V->getName().size() == 0)
|
|
|
|
OS << "\"" << *V << "\"";
|
|
|
|
else
|
|
|
|
OS << "\"" << V->getName() << "\"";
|
|
|
|
|
|
|
|
++PI;
|
|
|
|
|
|
|
|
if (PI != PE)
|
|
|
|
OS << ", ";
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OS.str();
|
|
|
|
}
|
|
|
|
|
2011-04-29 14:27:02 +08:00
|
|
|
bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
|
|
|
|
DetectionContext &Context) const {
|
2011-11-10 20:45:03 +08:00
|
|
|
Value *Ptr = getPointerOperand(Inst);
|
scop detection: properly instantiate SCEVs to the place where they are used
Fix inspired from c2d4a0627e95c34a819b9d4ffb4db62daa78dade.
Given the following code
for (i = 0; i < 10; i++) {
;
}
S: A[i] = 0
When translate the data reference A[i] in statement S using scev, we need to
retrieve the scev of 'i' at the location of 'S'. If we do not do this the
scev that we obtain will be expressed as {0,+,1}_for and will reference loop
iterators that do not surround 'S'. What we really want is the scev to be
instantiated to the value of 'i' after the loop. This value is {10}.
This used to crash in:
int loopDimension = getLoopDepth(Expr->getLoop());
isl_aff *LAff = isl_aff_set_coefficient_si(
isl_aff_zero_on_domain(LocalSpace), isl_dim_in, loopDimension, 1);
(gdb) p Expr->dump()
{8,+,8}<nw><%do.body>
(gdb) p getLoopDepth(Expr->getLoop())
$5 = 0
isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces);
isl_local_space *LocalSpace = isl_local_space_from_space(Space);
As we are trying to create a memory access in a stmt that is outside all loops,
LocalSpace has 0 dimensions:
(gdb) p NbLoopSpaces
$12 = 0
(gdb) p Statement.BB->dump()
if.then: ; preds = %do.end
%0 = load float* %add.ptr, align 4
store float %0, float* %q.1.reg2mem, align 4
br label %if.end.single_exit
and so the scev for %add.ptr should be taken at the place where it is used,
i.e., it should be the value on the last iteration of the do.body loop, and not
"{8,+,8}<nw><%do.body>".
llvm-svn: 179148
2013-04-10 12:05:18 +08:00
|
|
|
Loop *L = LI->getLoopFor(Inst.getParent());
|
|
|
|
const SCEV *AccessFunction = SE->getSCEVAtScope(Ptr, L);
|
2011-11-10 20:44:50 +08:00
|
|
|
const SCEVUnknown *BasePointer;
|
2011-11-10 20:45:03 +08:00
|
|
|
Value *BaseValue;
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2011-11-10 20:44:50 +08:00
|
|
|
BasePointer = dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction));
|
|
|
|
|
2013-07-22 11:50:33 +08:00
|
|
|
if (!BasePointer) {
|
2011-11-10 20:44:50 +08:00
|
|
|
INVALID(AffFunc, "No base pointer");
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-11-10 20:44:50 +08:00
|
|
|
|
|
|
|
BaseValue = BasePointer->getValue();
|
|
|
|
|
2013-07-22 11:50:33 +08:00
|
|
|
if (isa<UndefValue>(BaseValue)) {
|
2011-11-10 20:44:50 +08:00
|
|
|
INVALID(AffFunc, "Undefined base pointer");
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-11-10 20:44:50 +08:00
|
|
|
|
|
|
|
AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);
|
|
|
|
|
2013-06-23 09:29:29 +08:00
|
|
|
if (!AllowNonAffine &&
|
2013-07-22 11:50:33 +08:00
|
|
|
!isAffineExpr(&Context.CurRegion, AccessFunction, *SE, BaseValue)) {
|
2012-09-08 22:00:37 +08:00
|
|
|
INVALID(AffFunc, "Non affine access function: " << *AccessFunction);
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
// FIXME: Alias Analysis thinks IntToPtrInst aliases with alloca instructions
|
|
|
|
// created by IndependentBlocks Pass.
|
2013-07-22 11:50:33 +08:00
|
|
|
if (isa<IntToPtrInst>(BaseValue)) {
|
2011-11-10 20:45:03 +08:00
|
|
|
INVALID(Other, "Find bad intToptr prt: " << *BaseValue);
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2013-07-04 06:50:36 +08:00
|
|
|
if (IgnoreAliasing)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Check if the base pointer of the memory access does alias with
|
|
|
|
// any other pointer. This cannot be handled at the moment.
|
2013-07-15 02:09:43 +08:00
|
|
|
AliasSet &AS =
|
|
|
|
Context.AST.getAliasSetForPointer(BaseValue, AliasAnalysis::UnknownSize,
|
|
|
|
Inst.getMetadata(LLVMContext::MD_tbaa));
|
2013-07-04 06:50:36 +08:00
|
|
|
|
|
|
|
// INVALID triggers an assertion in verifying mode, if it detects that a
|
|
|
|
// SCoP was detected by SCoP detection and that this SCoP was invalidated by
|
|
|
|
// a pass that stated it would preserve the SCoPs. We disable this check as
|
|
|
|
// the independent blocks pass may create memory references which seem to
|
|
|
|
// alias, if -basicaa is not available. They actually do not, but as we can
|
|
|
|
// not proof this without -basicaa we would fail. We disable this check to
|
|
|
|
// not cause irrelevant verification failures.
|
|
|
|
if (!AS.isMustAlias()) {
|
2013-07-25 11:02:29 +08:00
|
|
|
INVALID_NOVERIFY(Alias, formatInvalidAlias(AS));
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
2013-02-04 23:46:25 +08:00
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ScopDetection::isValidInstruction(Instruction &Inst,
|
|
|
|
DetectionContext &Context) const {
|
|
|
|
if (PHINode *PN = dyn_cast<PHINode>(&Inst))
|
2013-03-21 02:03:18 +08:00
|
|
|
if (!canSynthesize(PN, LI, SE, &Context.CurRegion)) {
|
2013-07-22 11:50:33 +08:00
|
|
|
if (SCEVCodegen) {
|
2013-03-21 02:03:18 +08:00
|
|
|
INVALID(IndVar,
|
|
|
|
"SCEV of PHI node refers to SSA names in region: " << Inst);
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
} else {
|
2013-03-21 02:03:18 +08:00
|
|
|
INVALID(IndVar, "Non canonical PHI node: " << Inst);
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2013-03-21 02:03:18 +08:00
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
// We only check the call instruction but not invoke instruction.
|
|
|
|
if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
|
|
|
|
if (isValidCallInst(*CI))
|
|
|
|
return true;
|
|
|
|
|
2011-10-08 08:49:30 +08:00
|
|
|
INVALID(FuncCall, "Call instruction: " << Inst);
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
2011-04-29 14:27:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!Inst.mayWriteToMemory() && !Inst.mayReadFromMemory()) {
|
2013-07-22 11:50:33 +08:00
|
|
|
if (!isa<AllocaInst>(Inst))
|
|
|
|
return true;
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2013-07-22 11:50:33 +08:00
|
|
|
INVALID(Other, "Alloca instruction: " << Inst);
|
|
|
|
return false;
|
2011-04-29 14:27:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check the access function.
|
|
|
|
if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
|
|
|
|
return isValidMemoryAccess(Inst, Context);
|
|
|
|
|
|
|
|
// We do not know this instruction, therefore we assume it is invalid.
|
2011-10-08 08:30:48 +08:00
|
|
|
INVALID(Other, "Unknown instruction: " << Inst);
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
2011-04-29 14:27:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ScopDetection::isValidLoop(Loop *L, DetectionContext &Context) const {
|
2013-03-22 00:14:50 +08:00
|
|
|
if (!SCEVCodegen) {
|
|
|
|
// If code generation is not in scev based mode, we need to ensure that
|
|
|
|
// each loop has a canonical induction variable.
|
|
|
|
PHINode *IndVar = L->getCanonicalInductionVariable();
|
2013-07-22 11:50:33 +08:00
|
|
|
if (!IndVar) {
|
2013-03-22 00:14:50 +08:00
|
|
|
INVALID(IndVar,
|
|
|
|
"No canonical IV at loop header: " << L->getHeader()->getName());
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2013-03-22 00:14:50 +08:00
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
// Is the loop count affine?
|
|
|
|
const SCEV *LoopCount = SE->getBackedgeTakenCount(L);
|
2013-07-22 11:50:33 +08:00
|
|
|
if (!isAffineExpr(&Context.CurRegion, LoopCount, *SE)) {
|
2013-06-23 09:29:29 +08:00
|
|
|
INVALID(LoopBound, "Non affine loop bound '" << *LoopCount << "' in loop: "
|
|
|
|
<< L->getHeader()->getName());
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Region *ScopDetection::expandRegion(Region &R) {
|
2012-04-07 23:14:28 +08:00
|
|
|
// Initial no valid region was found (greater than R)
|
|
|
|
Region *LastValidRegion = NULL;
|
2012-12-30 07:47:38 +08:00
|
|
|
Region *ExpandedRegion = R.getExpandedRegion();
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
DEBUG(dbgs() << "\tExpanding " << R.getNameStr() << "\n");
|
|
|
|
|
2012-04-07 23:14:28 +08:00
|
|
|
while (ExpandedRegion) {
|
|
|
|
DetectionContext Context(*ExpandedRegion, *AA, false /* verifying */);
|
|
|
|
DEBUG(dbgs() << "\t\tTrying " << ExpandedRegion->getNameStr() << "\n");
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2012-04-07 23:14:28 +08:00
|
|
|
// Check the exit first (cheap)
|
2011-04-29 14:27:02 +08:00
|
|
|
if (isValidExit(Context)) {
|
2012-04-07 23:14:28 +08:00
|
|
|
// If the exit is valid check all blocks
|
|
|
|
// - if true, a valid region was found => store it + keep expanding
|
|
|
|
// - if false, .tbd. => stop (should this really end the loop?)
|
|
|
|
if (!allBlocksValid(Context))
|
|
|
|
break;
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2012-04-07 23:14:28 +08:00
|
|
|
// Delete unnecessary regions (allocated by getExpandedRegion)
|
|
|
|
if (LastValidRegion)
|
|
|
|
delete LastValidRegion;
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2013-04-10 14:55:45 +08:00
|
|
|
// Store this region, because it is the greatest valid (encountered so
|
|
|
|
// far).
|
2012-04-07 23:14:28 +08:00
|
|
|
LastValidRegion = ExpandedRegion;
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2012-04-07 23:14:28 +08:00
|
|
|
// Create and test the next greater region (if any)
|
|
|
|
ExpandedRegion = ExpandedRegion->getExpandedRegion();
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2012-04-07 23:14:28 +08:00
|
|
|
} else {
|
|
|
|
// Create and test the next greater region (if any)
|
|
|
|
Region *TmpRegion = ExpandedRegion->getExpandedRegion();
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2012-04-07 23:14:28 +08:00
|
|
|
// Delete unnecessary regions (allocated by getExpandedRegion)
|
|
|
|
delete ExpandedRegion;
|
|
|
|
|
|
|
|
ExpandedRegion = TmpRegion;
|
|
|
|
}
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2013-11-17 03:34:11 +08:00
|
|
|
DEBUG({
|
|
|
|
if (LastValidRegion)
|
|
|
|
dbgs() << "\tto " << LastValidRegion->getNameStr() << "\n";
|
|
|
|
else
|
|
|
|
dbgs() << "\tExpanding " << R.getNameStr() << " failed\n";
|
|
|
|
});
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2012-04-07 23:14:28 +08:00
|
|
|
return LastValidRegion;
|
2011-04-29 14:27:02 +08:00
|
|
|
}
|
2013-06-04 00:35:37 +08:00
|
|
|
static bool regionWithoutLoops(Region &R, LoopInfo *LI) {
|
|
|
|
for (Region::block_iterator I = R.block_begin(), E = R.block_end(); I != E;
|
|
|
|
++I)
|
|
|
|
if (R.contains(LI->getLoopFor(*I)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
void ScopDetection::findScops(Region &R) {
|
2013-06-04 00:35:37 +08:00
|
|
|
|
|
|
|
if (!DetectRegionsWithoutLoops && regionWithoutLoops(R, LI))
|
|
|
|
return;
|
|
|
|
|
2011-04-29 14:27:02 +08:00
|
|
|
DetectionContext Context(R, *AA, false /*verifying*/);
|
|
|
|
|
2011-11-10 20:45:15 +08:00
|
|
|
LastFailure = "";
|
|
|
|
|
2011-04-29 14:27:02 +08:00
|
|
|
if (isValidRegion(Context)) {
|
|
|
|
++ValidRegion;
|
|
|
|
ValidRegions.insert(&R);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-08 08:30:55 +08:00
|
|
|
InvalidRegions[&R] = LastFailure;
|
|
|
|
|
2011-04-29 14:27:02 +08:00
|
|
|
for (Region::iterator I = R.begin(), E = R.end(); I != E; ++I)
|
|
|
|
findScops(**I);
|
|
|
|
|
|
|
|
// Try to expand regions.
|
|
|
|
//
|
|
|
|
// As the region tree normally only contains canonical regions, non canonical
|
|
|
|
// regions that form a Scop are not found. Therefore, those non canonical
|
|
|
|
// regions are checked by expanding the canonical ones.
|
|
|
|
|
2013-02-05 19:56:05 +08:00
|
|
|
std::vector<Region *> ToExpand;
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
for (Region::iterator I = R.begin(), E = R.end(); I != E; ++I)
|
|
|
|
ToExpand.push_back(*I);
|
|
|
|
|
2013-02-05 17:40:22 +08:00
|
|
|
for (std::vector<Region *>::iterator RI = ToExpand.begin(),
|
|
|
|
RE = ToExpand.end();
|
|
|
|
RI != RE; ++RI) {
|
2011-04-29 14:27:02 +08:00
|
|
|
Region *CurrentRegion = *RI;
|
|
|
|
|
|
|
|
// Skip invalid regions. Regions may become invalid, if they are element of
|
|
|
|
// an already expanded region.
|
|
|
|
if (ValidRegions.find(CurrentRegion) == ValidRegions.end())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Region *ExpandedR = expandRegion(*CurrentRegion);
|
|
|
|
|
|
|
|
if (!ExpandedR)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
R.addSubRegion(ExpandedR, true);
|
|
|
|
ValidRegions.insert(ExpandedR);
|
|
|
|
ValidRegions.erase(CurrentRegion);
|
|
|
|
|
|
|
|
for (Region::iterator I = ExpandedR->begin(), E = ExpandedR->end(); I != E;
|
|
|
|
++I)
|
|
|
|
ValidRegions.erase(*I);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ScopDetection::allBlocksValid(DetectionContext &Context) const {
|
|
|
|
Region &R = Context.CurRegion;
|
|
|
|
|
2013-06-12 06:20:32 +08:00
|
|
|
for (Region::block_iterator I = R.block_begin(), E = R.block_end(); I != E;
|
|
|
|
++I) {
|
|
|
|
Loop *L = LI->getLoopFor(*I);
|
|
|
|
if (L && L->getHeader() == *I && !isValidLoop(L, Context))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-06-12 06:20:27 +08:00
|
|
|
for (Region::block_iterator I = R.block_begin(), E = R.block_end(); I != E;
|
|
|
|
++I)
|
|
|
|
if (!isValidCFG(**I, Context))
|
|
|
|
return false;
|
|
|
|
|
2013-06-15 04:20:43 +08:00
|
|
|
for (Region::block_iterator BI = R.block_begin(), E = R.block_end(); BI != E;
|
|
|
|
++BI)
|
|
|
|
for (BasicBlock::iterator I = (*BI)->begin(), E = --(*BI)->end(); I != E;
|
|
|
|
++I)
|
|
|
|
if (!isValidInstruction(*I, Context))
|
|
|
|
return false;
|
2011-04-29 14:27:02 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ScopDetection::isValidExit(DetectionContext &Context) const {
|
|
|
|
Region &R = Context.CurRegion;
|
|
|
|
|
|
|
|
// PHI nodes are not allowed in the exit basic block.
|
|
|
|
if (BasicBlock *Exit = R.getExit()) {
|
|
|
|
BasicBlock::iterator I = Exit->begin();
|
2013-07-22 11:50:33 +08:00
|
|
|
if (I != Exit->end() && isa<PHINode>(*I)) {
|
2011-10-08 08:30:48 +08:00
|
|
|
INVALID(Other, "PHI node in exit BB");
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ScopDetection::isValidRegion(DetectionContext &Context) const {
|
|
|
|
Region &R = Context.CurRegion;
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Checking region: " << R.getNameStr() << "\n\t");
|
|
|
|
|
|
|
|
// The toplevel region is no valid region.
|
2013-04-02 14:41:48 +08:00
|
|
|
if (R.isTopLevelRegion()) {
|
2013-03-23 09:05:07 +08:00
|
|
|
DEBUG(dbgs() << "Top level region is invalid"; dbgs() << "\n");
|
2011-04-29 14:27:02 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-05-07 15:30:56 +08:00
|
|
|
if (!R.getEnteringBlock()) {
|
2013-06-12 06:20:40 +08:00
|
|
|
BasicBlock *entry = R.getEntry();
|
|
|
|
Loop *L = LI->getLoopFor(entry);
|
|
|
|
|
|
|
|
if (L) {
|
2013-07-22 11:50:33 +08:00
|
|
|
if (!L->isLoopSimplifyForm()) {
|
2013-06-12 06:20:40 +08:00
|
|
|
INVALID(SimpleLoop, "Loop not in simplify form is invalid!");
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2013-06-12 06:20:40 +08:00
|
|
|
|
|
|
|
for (pred_iterator PI = pred_begin(entry), PE = pred_end(entry); PI != PE;
|
|
|
|
++PI) {
|
|
|
|
// Region entering edges come from the same loop but outside the region
|
|
|
|
// are not allowed.
|
2013-07-22 11:50:33 +08:00
|
|
|
if (L->contains(*PI) && !R.contains(*PI)) {
|
2013-06-12 06:20:40 +08:00
|
|
|
INVALID(IndEdge, "Region has invalid entering edges!");
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2013-06-12 06:20:40 +08:00
|
|
|
}
|
|
|
|
}
|
2013-04-16 16:04:42 +08:00
|
|
|
}
|
|
|
|
|
2012-04-11 02:12:19 +08:00
|
|
|
// SCoP cannot contain the entry block of the function, because we need
|
2011-04-29 14:27:02 +08:00
|
|
|
// to insert alloca instruction there when translate scalar to array.
|
2013-07-22 11:50:33 +08:00
|
|
|
if (R.getEntry() == &(R.getEntry()->getParent()->getEntryBlock())) {
|
2011-10-08 08:30:48 +08:00
|
|
|
INVALID(Other, "Region containing entry block of function is invalid!");
|
2013-07-22 11:50:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-29 14:27:02 +08:00
|
|
|
|
2012-04-07 20:29:17 +08:00
|
|
|
if (!isValidExit(Context))
|
2011-04-29 14:27:02 +08:00
|
|
|
return false;
|
|
|
|
|
2012-04-07 20:29:17 +08:00
|
|
|
if (!allBlocksValid(Context))
|
2011-04-29 14:27:02 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "OK\n");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ScopDetection::isValidFunction(llvm::Function &F) {
|
2011-05-06 10:38:20 +08:00
|
|
|
return !InvalidFunctions.count(&F);
|
2011-04-29 14:27:02 +08:00
|
|
|
}
|
|
|
|
|
2012-11-02 00:45:20 +08:00
|
|
|
void ScopDetection::getDebugLocation(const Region *R, unsigned &LineBegin,
|
|
|
|
unsigned &LineEnd, std::string &FileName) {
|
|
|
|
LineBegin = -1;
|
|
|
|
LineEnd = 0;
|
|
|
|
|
|
|
|
for (Region::const_block_iterator RI = R->block_begin(), RE = R->block_end();
|
|
|
|
RI != RE; ++RI)
|
|
|
|
for (BasicBlock::iterator BI = (*RI)->begin(), BE = (*RI)->end(); BI != BE;
|
|
|
|
++BI) {
|
|
|
|
DebugLoc DL = BI->getDebugLoc();
|
|
|
|
if (DL.isUnknown())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
DIScope Scope(DL.getScope(BI->getContext()));
|
|
|
|
|
|
|
|
if (FileName.empty())
|
|
|
|
FileName = Scope.getFilename();
|
|
|
|
|
|
|
|
unsigned NewLine = DL.getLine();
|
|
|
|
|
|
|
|
LineBegin = std::min(LineBegin, NewLine);
|
|
|
|
LineEnd = std::max(LineEnd, NewLine);
|
|
|
|
break;
|
2012-12-30 07:47:38 +08:00
|
|
|
}
|
2012-11-02 00:45:20 +08:00
|
|
|
}
|
|
|
|
|
2013-03-05 03:49:51 +08:00
|
|
|
void ScopDetection::printLocations(llvm::Function &F) {
|
|
|
|
int NumberOfScops = std::distance(begin(), end());
|
|
|
|
|
|
|
|
if (NumberOfScops)
|
|
|
|
outs() << ":: Static control regions in " << F.getName() << "\n";
|
|
|
|
|
2012-11-02 00:45:20 +08:00
|
|
|
for (iterator RI = begin(), RE = end(); RI != RE; ++RI) {
|
|
|
|
unsigned LineEntry, LineExit;
|
|
|
|
std::string FileName;
|
|
|
|
|
|
|
|
getDebugLocation(*RI, LineEntry, LineExit, FileName);
|
|
|
|
|
|
|
|
if (FileName.empty()) {
|
|
|
|
outs() << "Scop detected at unknown location. Compile with debug info "
|
2013-02-05 17:40:22 +08:00
|
|
|
"(-g) to get more precise information. \n";
|
2012-11-02 00:45:20 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-03-05 03:49:51 +08:00
|
|
|
outs() << FileName << ":" << LineEntry
|
|
|
|
<< ": Start of static control region\n";
|
|
|
|
outs() << FileName << ":" << LineExit << ": End of static control region\n";
|
2012-11-02 00:45:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-29 14:27:02 +08:00
|
|
|
bool ScopDetection::runOnFunction(llvm::Function &F) {
|
2013-05-31 01:47:32 +08:00
|
|
|
LI = &getAnalysis<LoopInfo>();
|
|
|
|
if (!DetectScopsWithoutLoops && LI->empty())
|
|
|
|
return false;
|
|
|
|
|
2011-04-29 14:27:02 +08:00
|
|
|
AA = &getAnalysis<AliasAnalysis>();
|
|
|
|
SE = &getAnalysis<ScalarEvolution>();
|
|
|
|
RI = &getAnalysis<RegionInfo>();
|
|
|
|
Region *TopRegion = RI->getTopLevelRegion();
|
|
|
|
|
2011-10-23 19:17:06 +08:00
|
|
|
releaseMemory();
|
|
|
|
|
2011-11-17 22:52:36 +08:00
|
|
|
if (OnlyFunction != "" && F.getName() != OnlyFunction)
|
2011-10-23 19:17:06 +08:00
|
|
|
return false;
|
|
|
|
|
2012-12-30 07:47:38 +08:00
|
|
|
if (!isValidFunction(F))
|
2011-04-29 14:27:02 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
findScops(*TopRegion);
|
2012-11-02 00:45:20 +08:00
|
|
|
|
|
|
|
if (ReportLevel >= 1)
|
2013-03-05 03:49:51 +08:00
|
|
|
printLocations(F);
|
2012-11-02 00:45:20 +08:00
|
|
|
|
2011-04-29 14:27:02 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void polly::ScopDetection::verifyRegion(const Region &R) const {
|
|
|
|
assert(isMaxRegionInScop(R) && "Expect R is a valid region.");
|
2013-02-05 19:56:05 +08:00
|
|
|
DetectionContext Context(const_cast<Region &>(R), *AA, true /*verifying*/);
|
2011-04-29 14:27:02 +08:00
|
|
|
isValidRegion(Context);
|
|
|
|
}
|
|
|
|
|
|
|
|
void polly::ScopDetection::verifyAnalysis() const {
|
|
|
|
for (RegionSet::const_iterator I = ValidRegions.begin(),
|
2013-02-05 17:40:22 +08:00
|
|
|
E = ValidRegions.end();
|
|
|
|
I != E; ++I)
|
2011-04-29 14:27:02 +08:00
|
|
|
verifyRegion(**I);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScopDetection::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
AU.addRequired<DominatorTree>();
|
|
|
|
AU.addRequired<PostDominatorTree>();
|
|
|
|
AU.addRequired<LoopInfo>();
|
|
|
|
AU.addRequired<ScalarEvolution>();
|
|
|
|
// We also need AA and RegionInfo when we are verifying analysis.
|
|
|
|
AU.addRequiredTransitive<AliasAnalysis>();
|
|
|
|
AU.addRequiredTransitive<RegionInfo>();
|
|
|
|
AU.setPreservesAll();
|
|
|
|
}
|
|
|
|
|
2013-03-23 09:05:07 +08:00
|
|
|
void ScopDetection::print(raw_ostream &OS, const Module *) const {
|
2011-04-29 14:27:02 +08:00
|
|
|
for (RegionSet::const_iterator I = ValidRegions.begin(),
|
2013-02-05 17:40:22 +08:00
|
|
|
E = ValidRegions.end();
|
|
|
|
I != E; ++I)
|
2011-04-29 14:27:02 +08:00
|
|
|
OS << "Valid Region for Scop: " << (*I)->getNameStr() << '\n';
|
|
|
|
|
|
|
|
OS << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScopDetection::releaseMemory() {
|
|
|
|
ValidRegions.clear();
|
2011-10-08 08:30:55 +08:00
|
|
|
InvalidRegions.clear();
|
2011-05-06 10:38:20 +08:00
|
|
|
// Do not clear the invalid function set.
|
2011-04-29 14:27:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
char ScopDetection::ID = 0;
|
|
|
|
|
2013-03-23 09:05:07 +08:00
|
|
|
Pass *polly::createScopDetectionPass() { return new ScopDetection(); }
|
|
|
|
|
2011-10-08 08:30:40 +08:00
|
|
|
INITIALIZE_PASS_BEGIN(ScopDetection, "polly-detect",
|
|
|
|
"Polly - Detect static control parts (SCoPs)", false,
|
2013-03-23 09:05:07 +08:00
|
|
|
false);
|
|
|
|
INITIALIZE_AG_DEPENDENCY(AliasAnalysis);
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(DominatorTree);
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(LoopInfo);
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(PostDominatorTree);
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(RegionInfo);
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
|
2011-10-08 08:30:40 +08:00
|
|
|
INITIALIZE_PASS_END(ScopDetection, "polly-detect",
|
|
|
|
"Polly - Detect static control parts (SCoPs)", false, false)
|