namespace llvm {
class Pass;
+ class Region;
class ScalarEvolution;
}
namespace polly {
+extern bool SCEVCodegen;
+
using namespace llvm;
class ScopStmt;
typedef DenseMap<const Value*, Value*> ValueMapT;
typedef std::vector<ValueMapT> VectorValueMapT;
+/// @brief Check whether an instruction can be synthesized by the code
+/// generator.
+///
+/// Some instructions will be recalculated only from information that is code
+/// generated from the polyhedral representation. For such instructions we do
+/// not need to ensure that their operands are available during code generation.
+///
+/// @param I The instruction to check.
+/// @param LI The LoopInfo analysis.
+/// @param SE The scalar evolution database.
+/// @param R The region out of which SSA names are parameters.
+/// @return If the instruction I can be regenerated from its
+/// scalar evolution representation, return true,
+/// otherwise return false.
+bool canSynthesize(const llvm::Instruction *I, const llvm::LoopInfo *LI,
+ llvm::ScalarEvolution *SE, const llvm::Region *R);
+
/// @brief Generate a new basic block for a polyhedral statement.
///
/// The only public function exposed is generate().
BlockGenerator(IRBuilder<> &B, ScopStmt &Stmt, Pass *P);
- /// @brief Check if an instruction can be 'SCEV-ignored'
- ///
- /// An instruction can be ignored if we can recreate it from its scalar
- /// evolution expression.
- bool isSCEVIgnore(const Instruction *Inst);
-
/// @brief Get the new version of a Value.
///
/// @param Old The old Value.
/// return the loop, otherwise, return null.
llvm::Loop *castToLoop(const llvm::Region &R, llvm::LoopInfo &LI);
-/// @brief Check if the instruction I is the induction variable of a loop.
-///
-/// @param I The instruction to check.
-/// @param LI The LoopInfo analysis.
-///
-/// @return Return true if I is the induction variable of a loop, false
-/// otherwise.
-bool isIndVar(const llvm::Instruction *I, const llvm::LoopInfo *LI);
-
/// @brief Check if the PHINode has any incoming Invoke edge.
///
/// @param PN The PHINode to check.
//
//===----------------------------------------------------------------------===//
-#include "polly/ScopDetection.h"
-
+#include "polly/CodeGen/BlockGenerators.h"
#include "polly/LinkAllPasses.h"
+#include "polly/ScopDetection.h"
#include "polly/Support/ScopHelper.h"
#include "polly/Support/SCEVValidator.h"
bool ScopDetection::isValidInstruction(Instruction &Inst,
DetectionContext &Context) const {
- // Only canonical IVs are allowed.
if (PHINode *PN = dyn_cast<PHINode>(&Inst))
- if (!isIndVar(PN, LI))
- INVALID(IndVar, "Non canonical PHI node: " << Inst);
+ if (!canSynthesize(PN, LI, SE, &Context.CurRegion)) {
+ if (SCEVCodegen)
+ INVALID(IndVar,
+ "SCEV of PHI node refers to SSA names in region: " << Inst);
+ else
+ INVALID(IndVar, "Non canonical PHI node: " << Inst);
+ }
// Scalar dependencies are not allowed.
if (hasScalarDependency(Inst, Context.CurRegion))
#include "polly/CodeGen/BlockGenerators.h"
#include "polly/Support/GICHelper.h"
#include "polly/Support/SCEVValidator.h"
+#include "polly/Support/ScopHelper.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ScalarEvolution.h"
cl::Hidden, cl::value_desc("OpenMP code generation enabled if true"),
cl::init(false), cl::ZeroOrMore);
-static cl::opt<bool>
-SCEVCodegen("polly-codegen-scev", cl::desc("Use SCEV based code generation."),
- cl::Hidden, cl::init(false), cl::ZeroOrMore);
+static cl::opt<bool, true>
+SCEVCodegenF("polly-codegen-scev", cl::desc("Use SCEV based code generation."),
+ cl::Hidden, cl::location(SCEVCodegen), cl::init(false),
+ cl::ZeroOrMore);
+
+bool polly::SCEVCodegen;
+
+bool polly::canSynthesize(const Instruction *I, const llvm::LoopInfo *LI,
+ ScalarEvolution *SE, const Region *R) {
+ if (SCEVCodegen) {
+ if (!I || !SE->isSCEVable(I->getType()))
+ return false;
+
+ if (const SCEV *Scev = SE->getSCEV(const_cast<Instruction *>(I)))
+ if (!isa<SCEVCouldNotCompute>(Scev))
+ if (!hasScalarDepsInsideRegion(Scev, R))
+ return true;
+
+ return false;
+ }
+
+ Loop *L = LI->getLoopFor(I->getParent());
+ return L && I == L->getCanonicalInductionVariable();
+}
+
// Helper class to generate memory location.
namespace {
: Builder(B), Statement(Stmt), P(P), SE(P->getAnalysis<ScalarEvolution>()) {
}
-bool BlockGenerator::isSCEVIgnore(const Instruction *Inst) {
- if (SCEVCodegen && SE.isSCEVable(Inst->getType()))
- if (const SCEV *Scev = SE.getSCEV(const_cast<Instruction *>(Inst)))
- if (!isa<SCEVCouldNotCompute>(Scev))
- return !hasScalarDepsInsideRegion(Scev,
- &Statement.getParent()->getRegion());
-
- return false;
-}
-
Value *BlockGenerator::getNewValue(const Value *Old, ValueMapT &BBMap,
ValueMapT &GlobalMap, LoopToScevMapT <S) {
// We assume constants never change.
return Expanded;
}
- // 'Old' is within the original SCoP, but was not rewritten.
- //
- // Such values appear, if they only calculate information already available in
- // the polyhedral description (e.g. an induction variable increment). They
- // can be safely ignored.
- if (const Instruction *Inst = dyn_cast<Instruction>(Old))
- if (Statement.getParent()->getRegion().contains(Inst->getParent()))
- return NULL;
+ if (const Instruction *Inst = dyn_cast<Instruction>(Old)) {
+ (void) Inst;
+ assert(!Statement.getParent()->getRegion().contains(Inst->getParent()) &&
+ "unexpected scalar dependence in region");
+ }
// Everything else is probably a scop-constant value defined as global,
// function parameter or an instruction not within the scop.
if (Inst->isTerminator())
return;
- if (isSCEVIgnore(Inst))
+ if (canSynthesize(Inst, &P->getAnalysis<LoopInfo>(), &SE,
+ &Statement.getParent()->getRegion()))
return;
if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
if (Inst->isTerminator())
return;
- if (isSCEVIgnore(Inst))
+ if (canSynthesize(Inst, &P->getAnalysis<LoopInfo>(), &SE,
+ &Statement.getParent()->getRegion()))
return;
if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
AU.addRequired<ScopDetection>();
AU.addRequired<ScopInfo>();
AU.addRequired<DataLayout>();
+ AU.addRequired<LoopInfo>();
AU.addPreserved<CloogInfo>();
AU.addPreserved<Dependences>();
AU.addRequired<ScalarEvolution>();
AU.addRequired<ScopDetection>();
AU.addRequired<ScopInfo>();
+ AU.addRequired<LoopInfo>();
AU.addPreserved<Dependences>();
#include "polly/LinkAllPasses.h"
#include "polly/ScopDetection.h"
#include "polly/Support/ScopHelper.h"
+#include "polly/CodeGen/BlockGenerators.h"
#include "polly/CodeGen/Cloog.h"
#include "llvm/Analysis/LoopInfo.h"
continue;
}
- // No need to move induction variable.
- if (isIndVar(Operand, LI)) {
+ if (canSynthesize(Operand, LI, SE, R)) {
DEBUG(dbgs() << "is IV.\n");
continue;
}
const Region *R) {
std::vector<Instruction*> WorkList;
for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE; ++II)
- if (!isSafeToMove(II) && !isIndVar(II, LI))
+ if (!isSafeToMove(II) && !canSynthesize(II, LI, SE, R))
WorkList.push_back(II);
ReplacedMapType ReplacedMap;
if (OpInst == 0) return false;
// Induction variables are valid operands.
- if (isIndVar(OpInst, LI)) return false;
+ if (canSynthesize(OpInst, LI, SE, R)) return false;
// A value from a different BB is used in the same region.
return R->contains(OpInst) && (OpInst->getParent() != CurBB);
bool IndependentBlocks::translateScalarToArray(Instruction *Inst,
const Region *R) {
- if (isIndVar(Inst, LI))
+ if (canSynthesize(Inst, LI, SE, R))
return false;
SmallVector<Instruction*, 4> LoadInside, LoadOutside;
if (isEscapeUse(U, R))
LoadOutside.push_back(U);
- if (isIndVar(U, LI))
+ if (canSynthesize(U, LI, SE, R))
continue;
if (R->contains(UParent) && isEscapeOperand(Inst, UParent, R))
while (!LoadInside.empty()) {
Instruction *U = LoadInside.pop_back_val();
- assert(!isa<PHINode>(U) && "Can not handle PHI node outside!");
+ assert(!isa<PHINode>(U) && "Can not handle PHI node inside!");
SE->forgetValue(U);
LoadInst *L = new LoadInst(Slot, Inst->getName()+".loadarray",
false, U);
II != IE; ++II) {
Instruction *Inst = &*II;
- if (isIndVar(Inst, LI))
+ if (canSynthesize(Inst, LI, SE, R))
continue;
// A value inside the Scop is referenced outside.
return 0;
}
-//===----------------------------------------------------------------------===//
-// Helper functions
-
-bool polly::isIndVar(const Instruction *I, const LoopInfo *LI) {
- Loop *L = LI->getLoopFor(I->getParent());
-
- return L && I == L->getCanonicalInductionVariable();
-}
-
bool polly::hasInvokeEdge(const PHINode *PN) {
for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i)
if (InvokeInst *II = dyn_cast<InvokeInst>(PN->getIncomingValue(i)))
; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -polly-codegen-scev -S < %s | FileCheck %s
; void f(long A[], int N, int *init_ptr) {
; long i, j;
; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -polly-codegen-scev -S < %s | FileCheck %s
; void f(long A[], int N, int *init_ptr) {
; long i, j;
; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -polly-codegen-scev -S < %s | FileCheck %s
; void f(long A[], int N, int *init_ptr) {
; long i, j;
; RUN: opt %loadPolly -basicaa -polly-independent < %s -S | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -polly-codegen-scev < %s -S | FileCheck %s
+
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
; RUN: opt %loadPolly -basicaa -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-detect -analyze -polly-codegen-scev < %s | FileCheck -check-prefix=CHECK-SCEV %s
; void f(long A[], long N, long *init_ptr) {
; long i, j;
}
; CHECK-NOT: Valid Region for Scop
+; CHECK-SCEV: Valid Region for Scop: for.j => for.i.end