forked from OSchip/llvm-project
change interface for isStride
isStride now takes a partial schedule as input. Patch from Tobias Grosser <tobias@grosser.es>. llvm-svn: 170419
This commit is contained in:
parent
bad01549b6
commit
a00a029115
|
@ -152,12 +152,16 @@ public:
|
||||||
/// used for one vector lane. The number of elements in the
|
/// used for one vector lane. The number of elements in the
|
||||||
/// vector defines the width of the generated vector
|
/// vector defines the width of the generated vector
|
||||||
/// instructions.
|
/// instructions.
|
||||||
|
/// @param Schedule A map from the statement to a schedule where the
|
||||||
|
/// innermost dimension is the dimension of the innermost
|
||||||
|
/// loop containing the statemenet.
|
||||||
/// @param P A reference to the pass this function is called from.
|
/// @param P A reference to the pass this function is called from.
|
||||||
/// The pass is needed to update other analysis.
|
/// The pass is needed to update other analysis.
|
||||||
static void generate(IRBuilder<> &B, ScopStmt &Stmt,
|
static void generate(IRBuilder<> &B, ScopStmt &Stmt,
|
||||||
VectorValueMapT &GlobalMaps, __isl_keep isl_set *Domain,
|
VectorValueMapT &GlobalMaps,
|
||||||
|
__isl_keep isl_map *Schedule,
|
||||||
Pass *P) {
|
Pass *P) {
|
||||||
VectorBlockGenerator Generator(B, GlobalMaps, Stmt, Domain, P);
|
VectorBlockGenerator Generator(B, GlobalMaps, Stmt, Schedule, P);
|
||||||
Generator.copyBB();
|
Generator.copyBB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,10 +173,13 @@ private:
|
||||||
// all referenes to the old instructions with their recalculated values.
|
// all referenes to the old instructions with their recalculated values.
|
||||||
VectorValueMapT &GlobalMaps;
|
VectorValueMapT &GlobalMaps;
|
||||||
|
|
||||||
isl_set *Domain;
|
// A map from the statement to a schedule where the innermost dimension is the
|
||||||
|
// dimension of the innermost loop containing the statemenet.
|
||||||
|
isl_map *Schedule;
|
||||||
|
|
||||||
VectorBlockGenerator(IRBuilder<> &B, VectorValueMapT &GlobalMaps,
|
VectorBlockGenerator(IRBuilder<> &B, VectorValueMapT &GlobalMaps,
|
||||||
ScopStmt &Stmt, __isl_keep isl_set *Domain, Pass *P);
|
ScopStmt &Stmt, __isl_keep isl_map *Schedule,
|
||||||
|
Pass *P);
|
||||||
|
|
||||||
int getVectorWidth();
|
int getVectorWidth();
|
||||||
|
|
||||||
|
|
|
@ -148,20 +148,27 @@ public:
|
||||||
/// @brief Get the new access function imported from JSCOP file
|
/// @brief Get the new access function imported from JSCOP file
|
||||||
isl_map *getNewAccessRelation() const;
|
isl_map *getNewAccessRelation() const;
|
||||||
|
|
||||||
/// @brief Get the stride of this memory access in the specified domain
|
/// Get the stride of this memory access in the specified Schedule. Schedule
|
||||||
/// subset.
|
/// is a map from the statement to a schedule where the innermost dimension is
|
||||||
isl_set *getStride(__isl_take const isl_set *domainSubset) const;
|
/// the dimension of the innermost loop containing the statemenet.
|
||||||
|
isl_set *getStride(__isl_take const isl_map *Schedule) const;
|
||||||
|
|
||||||
/// @brief Is the stride of the access equal to a certain width.
|
/// Is the stride of the access equal to a certain width? Schedule is a map
|
||||||
bool isStrideX(__isl_take const isl_set *DomainSubset, int StrideWidth) const;
|
/// from the statement to a schedule where the innermost dimension is the
|
||||||
|
/// dimension of the innermost loop containing the statemenet.
|
||||||
|
bool isStrideX(__isl_take const isl_map *Schedule, int StrideWidth) const;
|
||||||
|
|
||||||
/// @brief Is consecutive memory accessed for a given
|
/// Is consecutive memory accessed for a given statement instance set?
|
||||||
/// statement instance set?
|
/// Schedule is a map from the statement to a schedule where the innermost
|
||||||
bool isStrideOne(__isl_take const isl_set *domainSubset) const;
|
/// dimension is the dimension of the innermost loop containing the
|
||||||
|
/// statemenet.
|
||||||
|
bool isStrideOne(__isl_take const isl_map *Schedule) const;
|
||||||
|
|
||||||
/// @brief Is always the same memory accessed for a given
|
/// Is always the same memory accessed for a given statement instance set?
|
||||||
/// statement instance set?
|
/// Schedule is a map from the statement to a schedule where the innermost
|
||||||
bool isStrideZero(__isl_take const isl_set *domainSubset) const;
|
/// dimension is the dimension of the innermost loop containing the
|
||||||
|
/// statemenet.
|
||||||
|
bool isStrideZero(__isl_take const isl_map *Schedule) const;
|
||||||
|
|
||||||
/// @brief Get the statement that contains this memory access.
|
/// @brief Get the statement that contains this memory access.
|
||||||
ScopStmt *getStatement() const { return statement; }
|
ScopStmt *getStatement() const { return statement; }
|
||||||
|
|
|
@ -389,41 +389,30 @@ static isl_map *getEqualAndLarger(isl_space *setDomain) {
|
||||||
return Map;
|
return Map;
|
||||||
}
|
}
|
||||||
|
|
||||||
isl_set *MemoryAccess::getStride(__isl_take const isl_set *domainSubset) const {
|
isl_set *MemoryAccess::getStride(__isl_take const isl_map *Schedule) const {
|
||||||
isl_map *accessRelation = getAccessRelation();
|
isl_map *S = const_cast<isl_map*>(Schedule);
|
||||||
isl_set *scatteringDomain = const_cast<isl_set*>(domainSubset);
|
isl_map *AccessRelation = getAccessRelation();
|
||||||
isl_map *scattering = getStatement()->getScattering();
|
isl_space *Space = isl_space_range(isl_map_get_space(S));
|
||||||
|
isl_map *NextScatt = getEqualAndLarger(Space);
|
||||||
|
|
||||||
scattering = isl_map_reverse(scattering);
|
S = isl_map_reverse(S);
|
||||||
int difference = isl_map_n_in(scattering) - isl_set_n_dim(scatteringDomain);
|
NextScatt = isl_map_lexmin(NextScatt);
|
||||||
scattering = isl_map_project_out(scattering, isl_dim_in,
|
|
||||||
isl_set_n_dim(scatteringDomain),
|
|
||||||
difference);
|
|
||||||
|
|
||||||
// Remove all names of the scattering dimensions, as the names may be lost
|
NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(S));
|
||||||
// anyways during the project. This leads to consistent results.
|
NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(AccessRelation));
|
||||||
scattering = isl_map_set_tuple_name(scattering, isl_dim_in, "");
|
NextScatt = isl_map_apply_domain(NextScatt, S);
|
||||||
scatteringDomain = isl_set_set_tuple_name(scatteringDomain, "");
|
NextScatt = isl_map_apply_domain(NextScatt, AccessRelation);
|
||||||
|
|
||||||
isl_map *nextScatt = getEqualAndLarger(isl_set_get_space(scatteringDomain));
|
isl_set *Deltas = isl_map_deltas(NextScatt);
|
||||||
nextScatt = isl_map_lexmin(nextScatt);
|
return Deltas;
|
||||||
|
|
||||||
scattering = isl_map_intersect_domain(scattering, scatteringDomain);
|
|
||||||
|
|
||||||
nextScatt = isl_map_apply_range(nextScatt, isl_map_copy(scattering));
|
|
||||||
nextScatt = isl_map_apply_range(nextScatt, isl_map_copy(accessRelation));
|
|
||||||
nextScatt = isl_map_apply_domain(nextScatt, scattering);
|
|
||||||
nextScatt = isl_map_apply_domain(nextScatt, accessRelation);
|
|
||||||
|
|
||||||
return isl_map_deltas(nextScatt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryAccess::isStrideX(__isl_take const isl_set *DomainSubset,
|
bool MemoryAccess::isStrideX(__isl_take const isl_map *Schedule,
|
||||||
int StrideWidth) const {
|
int StrideWidth) const {
|
||||||
isl_set *Stride, *StrideX;
|
isl_set *Stride, *StrideX;
|
||||||
bool IsStrideX;
|
bool IsStrideX;
|
||||||
|
|
||||||
Stride = getStride(DomainSubset);
|
Stride = getStride(Schedule);
|
||||||
StrideX = isl_set_universe(isl_set_get_space(Stride));
|
StrideX = isl_set_universe(isl_set_get_space(Stride));
|
||||||
StrideX = isl_set_fix_si(StrideX, isl_dim_set, 0, StrideWidth);
|
StrideX = isl_set_fix_si(StrideX, isl_dim_set, 0, StrideWidth);
|
||||||
IsStrideX = isl_set_is_equal(Stride, StrideX);
|
IsStrideX = isl_set_is_equal(Stride, StrideX);
|
||||||
|
@ -434,12 +423,12 @@ bool MemoryAccess::isStrideX(__isl_take const isl_set *DomainSubset,
|
||||||
return IsStrideX;
|
return IsStrideX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryAccess::isStrideZero(const isl_set *DomainSubset) const {
|
bool MemoryAccess::isStrideZero(const isl_map *Schedule) const {
|
||||||
return isStrideX(DomainSubset, 0);
|
return isStrideX(Schedule, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryAccess::isStrideOne(const isl_set *DomainSubset) const {
|
bool MemoryAccess::isStrideOne(const isl_map *Schedule) const {
|
||||||
return isStrideX(DomainSubset, 1);
|
return isStrideX(Schedule, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryAccess::setNewAccessRelation(isl_map *newAccess) {
|
void MemoryAccess::setNewAccessRelation(isl_map *newAccess) {
|
||||||
|
|
|
@ -562,12 +562,14 @@ void BlockGenerator::copyBB(ValueMapT &GlobalMap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorBlockGenerator::VectorBlockGenerator(IRBuilder<> &B,
|
VectorBlockGenerator::VectorBlockGenerator(IRBuilder<> &B,
|
||||||
VectorValueMapT &GlobalMaps, ScopStmt &Stmt, __isl_keep isl_set *Domain,
|
VectorValueMapT &GlobalMaps,
|
||||||
Pass *P) : BlockGenerator(B, Stmt, P), GlobalMaps(GlobalMaps),
|
ScopStmt &Stmt,
|
||||||
Domain(Domain) {
|
__isl_keep isl_map *Schedule,
|
||||||
assert(GlobalMaps.size() > 1 && "Only one vector lane found");
|
Pass *P)
|
||||||
assert(Domain && "No statement domain provided");
|
: BlockGenerator(B, Stmt, P), GlobalMaps(GlobalMaps), Schedule(Schedule) {
|
||||||
}
|
assert(GlobalMaps.size() > 1 && "Only one vector lane found");
|
||||||
|
assert(Schedule && "No statement domain provided");
|
||||||
|
}
|
||||||
|
|
||||||
Value *VectorBlockGenerator::getVectorValue(const Value *Old,
|
Value *VectorBlockGenerator::getVectorValue(const Value *Old,
|
||||||
ValueMapT &VectorMap,
|
ValueMapT &VectorMap,
|
||||||
|
@ -675,9 +677,9 @@ void VectorBlockGenerator::generateLoad(const LoadInst *Load,
|
||||||
MemoryAccess &Access = Statement.getAccessFor(Load);
|
MemoryAccess &Access = Statement.getAccessFor(Load);
|
||||||
|
|
||||||
Value *NewLoad;
|
Value *NewLoad;
|
||||||
if (Access.isStrideZero(isl_set_copy(Domain)))
|
if (Access.isStrideZero(isl_map_copy(Schedule)))
|
||||||
NewLoad = generateStrideZeroLoad(Load, ScalarMaps[0]);
|
NewLoad = generateStrideZeroLoad(Load, ScalarMaps[0]);
|
||||||
else if (Access.isStrideOne(isl_set_copy(Domain)))
|
else if (Access.isStrideOne(isl_map_copy(Schedule)))
|
||||||
NewLoad = generateStrideOneLoad(Load, ScalarMaps[0]);
|
NewLoad = generateStrideOneLoad(Load, ScalarMaps[0]);
|
||||||
else
|
else
|
||||||
NewLoad = generateUnknownStrideLoad(Load, ScalarMaps);
|
NewLoad = generateUnknownStrideLoad(Load, ScalarMaps);
|
||||||
|
@ -726,7 +728,7 @@ void VectorBlockGenerator::copyStore(const StoreInst *Store,
|
||||||
Value *Vector = getVectorValue(Store->getValueOperand(), VectorMap,
|
Value *Vector = getVectorValue(Store->getValueOperand(), VectorMap,
|
||||||
ScalarMaps);
|
ScalarMaps);
|
||||||
|
|
||||||
if (Access.isStrideOne(isl_set_copy(Domain))) {
|
if (Access.isStrideOne(isl_map_copy(Schedule))) {
|
||||||
Type *VectorPtrType = getVectorPtrTy(Pointer, VectorWidth);
|
Type *VectorPtrType = getVectorPtrTy(Pointer, VectorWidth);
|
||||||
Value *NewPointer = getNewValue(Pointer, ScalarMaps[0], GlobalMaps[0]);
|
Value *NewPointer = getNewValue(Pointer, ScalarMaps[0], GlobalMaps[0]);
|
||||||
|
|
||||||
|
|
|
@ -394,6 +394,19 @@ void ClastStmtCodeGen::codegenSubstitutions(const clast_stmt *Assignment,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Takes the cloog specific domain and translates it into a map Statement ->
|
||||||
|
// PartialSchedule, where the PartialSchedule contains all the dimensions that
|
||||||
|
// have been code generated up to this point.
|
||||||
|
static __isl_give isl_map *extractPartialSchedule(ScopStmt *Statement,
|
||||||
|
isl_set *Domain) {
|
||||||
|
isl_map *Schedule = Statement->getScattering();
|
||||||
|
int ScheduledDimensions = isl_set_dim(Domain, isl_dim_set);
|
||||||
|
int UnscheduledDimensions = isl_map_dim(Schedule, isl_dim_out) - ScheduledDimensions;
|
||||||
|
|
||||||
|
return isl_map_project_out(Schedule, isl_dim_out, ScheduledDimensions,
|
||||||
|
UnscheduledDimensions);
|
||||||
|
}
|
||||||
|
|
||||||
void ClastStmtCodeGen::codegen(const clast_user_stmt *u,
|
void ClastStmtCodeGen::codegen(const clast_user_stmt *u,
|
||||||
std::vector<Value*> *IVS , const char *iterator,
|
std::vector<Value*> *IVS , const char *iterator,
|
||||||
isl_set *Domain) {
|
isl_set *Domain) {
|
||||||
|
@ -422,7 +435,9 @@ void ClastStmtCodeGen::codegen(const clast_user_stmt *u,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorBlockGenerator::generate(Builder, *Statement, VectorMap, Domain, P);
|
isl_map *Schedule = extractPartialSchedule(Statement, Domain);
|
||||||
|
VectorBlockGenerator::generate(Builder, *Statement, VectorMap, Schedule, P);
|
||||||
|
isl_map_free(Schedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClastStmtCodeGen::codegen(const clast_block *b) {
|
void ClastStmtCodeGen::codegen(const clast_block *b) {
|
||||||
|
|
Loading…
Reference in New Issue