diff --git a/polly/include/polly/CodeGen/BlockGenerators.h b/polly/include/polly/CodeGen/BlockGenerators.h index ea3f6dff075d..015e6cc3f2df 100644 --- a/polly/include/polly/CodeGen/BlockGenerators.h +++ b/polly/include/polly/CodeGen/BlockGenerators.h @@ -39,21 +39,20 @@ class IslExprBuilder; typedef DenseMap ValueMapT; typedef std::vector VectorValueMapT; -/// @brief Check whether an instruction can be synthesized by the code -/// generator. +/// @brief Check whether a value an 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. +/// Some value 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 V The value 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, +bool canSynthesize(const llvm::Value *V, const llvm::LoopInfo *LI, llvm::ScalarEvolution *SE, const llvm::Region *R); /// @brief Return true iff @p V is an intrinsic that we ignore during code diff --git a/polly/lib/Analysis/TempScopInfo.cpp b/polly/lib/Analysis/TempScopInfo.cpp index 6b170840f41f..ee52ace67c7f 100644 --- a/polly/lib/Analysis/TempScopInfo.cpp +++ b/polly/lib/Analysis/TempScopInfo.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "polly/TempScopInfo.h" +#include "polly/Options.h" #include "polly/CodeGen/BlockGenerators.h" #include "polly/LinkAllPasses.h" #include "polly/ScopDetection.h" @@ -34,6 +35,11 @@ using namespace llvm; using namespace polly; +static cl::opt ModelReadOnlyScalars( + "polly-analyze-read-only-scalars", + cl::desc("Model read-only scalar values in the scop description"), + cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory)); + #define DEBUG_TYPE "polly-analyze-ir" //===----------------------------------------------------------------------===// @@ -209,6 +215,21 @@ bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R, AccFuncMap[UseParent].push_back(std::make_pair(ScalarAccess, UI)); } + if (ModelReadOnlyScalars) { + for (Value *Op : Inst->operands()) { + if (canSynthesize(Op, LI, SE, R)) + continue; + + if (Instruction *OpInst = dyn_cast(Op)) + if (R->contains(OpInst)) + continue; + + IRAccess ScalarAccess(IRAccess::READ, Op, ZeroOffset, 1, true); + AccFuncMap[Inst->getParent()].push_back( + std::make_pair(ScalarAccess, Inst)); + } + } + return AnyCrossStmtUse; } diff --git a/polly/lib/CodeGen/BlockGenerators.cpp b/polly/lib/CodeGen/BlockGenerators.cpp index 22722a5726b3..33e66a1114d8 100644 --- a/polly/lib/CodeGen/BlockGenerators.cpp +++ b/polly/lib/CodeGen/BlockGenerators.cpp @@ -42,12 +42,12 @@ static cl::opt Aligned("enable-polly-aligned", cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); -bool polly::canSynthesize(const Instruction *I, const llvm::LoopInfo *LI, +bool polly::canSynthesize(const Value *V, const llvm::LoopInfo *LI, ScalarEvolution *SE, const Region *R) { - if (!I || !SE->isSCEVable(I->getType())) + if (!V || !SE->isSCEVable(V->getType())) return false; - if (const SCEV *Scev = SE->getSCEV(const_cast(I))) + if (const SCEV *Scev = SE->getSCEV(const_cast(V))) if (!isa(Scev)) if (!hasScalarDepsInsideRegion(Scev, R)) return true; diff --git a/polly/test/ScopInfo/read-only-scalars.ll b/polly/test/ScopInfo/read-only-scalars.ll new file mode 100644 index 000000000000..766d4d9e0593 --- /dev/null +++ b/polly/test/ScopInfo/read-only-scalars.ll @@ -0,0 +1,32 @@ +; RUN: opt %loadPolly -polly-analyze-read-only-scalars=false -polly-scops -analyze < %s | FileCheck %s +; RUN: opt %loadPolly -polly-analyze-read-only-scalars=true -polly-scops -analyze < %s | FileCheck %s -check-prefix=SCALARS + +; CHECK-NOT: Memref_scalar + +; SCALARS: float MemRef_scalar[*] // Element size 4 + +; SCALARS: ReadAccess := [Reduction Type: NONE] [Scalar: 1] +; SCALARS: { Stmt_stmt1[i0] -> MemRef_scalar[] }; + +define void @foo(float* noalias %A, float %scalar) { +entry: + br label %loop + +loop: + %indvar = phi i64 [0, %entry], [%indvar.next, %loop.backedge] + br label %stmt1 + +stmt1: + %val = load float, float* %A + %sum = fadd float %val, %scalar + store float %sum, float* %A + br label %loop.backedge + +loop.backedge: + %indvar.next = add i64 %indvar, 1 + %cond = icmp sle i64 %indvar, 100 + br i1 %cond, label %loop, label %exit + +exit: + ret void +}