Fix the modifiable access creation
+ Remove the class IslGenerator which duplicates the functionality of
IslExprBuilder.
+ Use the IslExprBuilder to create code for memory access relations.
+ Also handle array types during access creation.
+ Enable scev codegen for one of the transformed memory access tests,
thus access creation without canonical induction variables available.
+ Update one test case to the new output.
llvm-svn: 214659
diff --git a/polly/lib/CodeGen/BlockGenerators.cpp b/polly/lib/CodeGen/BlockGenerators.cpp
index 7284e24..66d90d9 100644
--- a/polly/lib/CodeGen/BlockGenerators.cpp
+++ b/polly/lib/CodeGen/BlockGenerators.cpp
@@ -15,9 +15,12 @@
#include "polly/ScopInfo.h"
#include "isl/aff.h"
+#include "isl/ast.h"
+#include "isl/ast_build.h"
#include "isl/set.h"
#include "polly/CodeGen/BlockGenerators.h"
#include "polly/CodeGen/CodeGeneration.h"
+#include "polly/CodeGen/IslExprBuilder.h"
#include "polly/Options.h"
#include "polly/Support/GICHelper.h"
#include "polly/Support/SCEVValidator.h"
@@ -63,103 +66,11 @@
return L && I == L->getCanonicalInductionVariable() && R->contains(L);
}
-// Helper class to generate memory location.
-namespace {
-class IslGenerator {
-public:
- IslGenerator(PollyIRBuilder &Builder, std::vector<Value *> &IVS)
- : Builder(Builder), IVS(IVS) {}
- Value *generateIslVal(__isl_take isl_val *Val);
- Value *generateIslAff(__isl_take isl_aff *Aff);
- Value *generateIslPwAff(__isl_take isl_pw_aff *PwAff);
-
-private:
- typedef struct {
- Value *Result;
- class IslGenerator *Generator;
- } IslGenInfo;
-
- PollyIRBuilder &Builder;
- std::vector<Value *> &IVS;
- static int mergeIslAffValues(__isl_take isl_set *Set, __isl_take isl_aff *Aff,
- void *User);
-};
-}
-
-Value *IslGenerator::generateIslVal(__isl_take isl_val *Val) {
- Value *IntValue = Builder.getInt(APIntFromVal(Val));
- return IntValue;
-}
-
-Value *IslGenerator::generateIslAff(__isl_take isl_aff *Aff) {
- Value *Result;
- Value *ConstValue;
- isl_val *Val;
-
- Val = isl_aff_get_constant_val(Aff);
- ConstValue = generateIslVal(Val);
- Type *Ty = Builder.getInt64Ty();
-
- // FIXME: We should give the constant and coefficients the right type. Here
- // we force it into i64.
- Result = Builder.CreateSExtOrBitCast(ConstValue, Ty);
-
- unsigned int NbInputDims = isl_aff_dim(Aff, isl_dim_in);
-
- assert((IVS.size() == NbInputDims) &&
- "The Dimension of Induction Variables must match the dimension of the "
- "affine space.");
-
- for (unsigned int i = 0; i < NbInputDims; ++i) {
- Value *CoefficientValue;
- Val = isl_aff_get_coefficient_val(Aff, isl_dim_in, i);
-
- if (isl_val_is_zero(Val)) {
- isl_val_free(Val);
- continue;
- }
-
- CoefficientValue = generateIslVal(Val);
- CoefficientValue = Builder.CreateIntCast(CoefficientValue, Ty, true);
- Value *IV = Builder.CreateIntCast(IVS[i], Ty, true);
- Value *PAdd = Builder.CreateMul(CoefficientValue, IV, "p_mul_coeff");
- Result = Builder.CreateAdd(Result, PAdd, "p_sum_coeff");
- }
-
- isl_aff_free(Aff);
-
- return Result;
-}
-
-int IslGenerator::mergeIslAffValues(__isl_take isl_set *Set,
- __isl_take isl_aff *Aff, void *User) {
- IslGenInfo *GenInfo = (IslGenInfo *)User;
-
- assert((GenInfo->Result == nullptr) &&
- "Result is already set. Currently only single isl_aff is supported");
- assert(isl_set_plain_is_universe(Set) &&
- "Code generation failed because the set is not universe");
-
- GenInfo->Result = GenInfo->Generator->generateIslAff(Aff);
-
- isl_set_free(Set);
- return 0;
-}
-
-Value *IslGenerator::generateIslPwAff(__isl_take isl_pw_aff *PwAff) {
- IslGenInfo User;
- User.Result = nullptr;
- User.Generator = this;
- isl_pw_aff_foreach_piece(PwAff, mergeIslAffValues, &User);
- assert(User.Result && "Code generation for isl_pw_aff failed");
-
- isl_pw_aff_free(PwAff);
- return User.Result;
-}
-
-BlockGenerator::BlockGenerator(PollyIRBuilder &B, ScopStmt &Stmt, Pass *P)
- : Builder(B), Statement(Stmt), P(P), SE(P->getAnalysis<ScalarEvolution>()) {
-}
+BlockGenerator::BlockGenerator(PollyIRBuilder &B, ScopStmt &Stmt, Pass *P,
+ isl_ast_build *Build,
+ IslExprBuilder *ExprBuilder)
+ : Builder(B), Statement(Stmt), P(P), SE(P->getAnalysis<ScalarEvolution>()),
+ Build(Build), ExprBuilder(ExprBuilder) {}
Value *BlockGenerator::lookupAvailableValue(const Value *Old, ValueMapT &BBMap,
ValueMapT &GlobalMap) const {
@@ -252,41 +163,30 @@
NewInst->setName("p_" + Inst->getName());
}
-std::vector<Value *> BlockGenerator::getMemoryAccessIndex(
- __isl_keep isl_map *AccessRelation, Value *BaseAddress, ValueMapT &BBMap,
- ValueMapT &GlobalMap, LoopToScevMapT <S, Loop *L) {
- assert((isl_map_dim(AccessRelation, isl_dim_out) == 1) &&
- "Only single dimensional access functions supported");
+Value *BlockGenerator::getNewAccessOperand(const MemoryAccess &MA) {
+ isl_pw_multi_aff *PWSchedule, *PWAccRel;
+ isl_union_map *ScheduleU;
+ isl_map *Schedule, *AccRel;
+ isl_ast_expr *Expr;
- std::vector<Value *> IVS;
- for (unsigned i = 0; i < Statement.getNumIterators(); ++i) {
- const Value *OriginalIV = Statement.getInductionVariableForDimension(i);
- Value *NewIV = getNewValue(OriginalIV, BBMap, GlobalMap, LTS, L);
- IVS.push_back(NewIV);
- }
+ assert(ExprBuilder && Build &&
+ "Cannot generate new value without IslExprBuilder!");
- isl_pw_aff *PwAff = isl_map_dim_max(isl_map_copy(AccessRelation), 0);
- IslGenerator IslGen(Builder, IVS);
- Value *OffsetValue = IslGen.generateIslPwAff(PwAff);
+ AccRel = MA.getNewAccessRelation();
+ assert(AccRel && "We generate new code only for new access relations!");
- Type *Ty = Builder.getInt64Ty();
- OffsetValue = Builder.CreateIntCast(OffsetValue, Ty, true);
+ ScheduleU = isl_ast_build_get_schedule(Build);
+ ScheduleU = isl_union_map_intersect_domain(
+ ScheduleU, isl_union_set_from_set(MA.getStatement()->getDomain()));
+ Schedule = isl_map_from_union_map(ScheduleU);
- std::vector<Value *> IndexArray;
- Value *NullValue = Constant::getNullValue(Ty);
- IndexArray.push_back(NullValue);
- IndexArray.push_back(OffsetValue);
- return IndexArray;
-}
+ PWSchedule = isl_pw_multi_aff_from_map(isl_map_reverse(Schedule));
+ PWAccRel = isl_pw_multi_aff_from_map(AccRel);
+ PWAccRel = isl_pw_multi_aff_pullback_pw_multi_aff(PWAccRel, PWSchedule);
-Value *BlockGenerator::getNewAccessOperand(
- __isl_keep isl_map *NewAccessRelation, Value *BaseAddress, ValueMapT &BBMap,
- ValueMapT &GlobalMap, LoopToScevMapT <S, Loop *L) {
- std::vector<Value *> IndexArray = getMemoryAccessIndex(
- NewAccessRelation, BaseAddress, BBMap, GlobalMap, LTS, L);
- Value *NewOperand =
- Builder.CreateGEP(BaseAddress, IndexArray, "p_newarrayidx_");
- return NewOperand;
+ Expr = isl_ast_build_access_from_pw_multi_aff(Build, PWAccRel);
+
+ return ExprBuilder->create(Expr);
}
Value *BlockGenerator::generateLocationAccessed(const Instruction *Inst,
@@ -294,26 +194,17 @@
ValueMapT &BBMap,
ValueMapT &GlobalMap,
LoopToScevMapT <S) {
- const MemoryAccess &Access = Statement.getAccessFor(Inst);
- isl_map *CurrentAccessRelation = Access.getAccessRelation();
- isl_map *NewAccessRelation = Access.getNewAccessRelation();
-
- assert(isl_map_has_equal_space(CurrentAccessRelation, NewAccessRelation) &&
- "Current and new access function use different spaces");
+ const MemoryAccess &MA = Statement.getAccessFor(Inst);
+ isl_map *NewAccRel = MA.getNewAccessRelation();
Value *NewPointer;
-
- if (!NewAccessRelation) {
+ if (NewAccRel)
+ NewPointer = getNewAccessOperand(MA);
+ else
NewPointer =
getNewValue(Pointer, BBMap, GlobalMap, LTS, getLoopForInst(Inst));
- } else {
- Value *BaseAddress = Access.getBaseAddr();
- NewPointer = getNewAccessOperand(NewAccessRelation, BaseAddress, BBMap,
- GlobalMap, LTS, getLoopForInst(Inst));
- }
- isl_map_free(CurrentAccessRelation);
- isl_map_free(NewAccessRelation);
+ isl_map_free(NewAccRel);
return NewPointer;
}
@@ -397,8 +288,8 @@
ScopStmt &Stmt,
__isl_keep isl_map *Schedule,
Pass *P)
- : BlockGenerator(B, Stmt, P), GlobalMaps(GlobalMaps), VLTS(VLTS),
- Schedule(Schedule) {
+ : BlockGenerator(B, Stmt, P, nullptr, nullptr), GlobalMaps(GlobalMaps),
+ VLTS(VLTS), Schedule(Schedule) {
assert(GlobalMaps.size() > 1 && "Only one vector lane found");
assert(Schedule && "No statement domain provided");
}