Optionally model read-only scalars
Even though read-only accesses to scalars outside of a scop do not need to be modeled to derive valid transformations or to generate valid sequential code, but information about them is useful when we considering memory footprint analysis and/or kernel offloading. llvm-svn: 243981
This commit is contained in:
parent
b89951457d
commit
dcc3b435ab
|
@ -39,21 +39,20 @@ class IslExprBuilder;
|
|||
typedef DenseMap<const Value *, Value *> ValueMapT;
|
||||
typedef std::vector<ValueMapT> 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
|
||||
|
|
|
@ -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<bool> 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<Instruction>(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;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,12 +42,12 @@ static cl::opt<bool> 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<Instruction *>(I)))
|
||||
if (const SCEV *Scev = SE->getSCEV(const_cast<Value *>(V)))
|
||||
if (!isa<SCEVCouldNotCompute>(Scev))
|
||||
if (!hasScalarDepsInsideRegion(Scev, R))
|
||||
return true;
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue