unsigned getNumberOfDimensions() const {
if (Kind == MK_PHI || Kind == MK_ExitPHI || Kind == MK_Value)
return 0;
- return DimensionSizes.size() + 1;
+ return DimensionSizes.size();
}
/// Return the size of dimension @p dim as SCEV*.
//
// Scalars do not have array dimensions and the first dimension of
// a (possibly multi-dimensional) array also does not carry any size
- // information.
+ // information, in case the array is not newly created.
const SCEV *getDimensionSize(unsigned Dim) const {
- assert(Dim > 0 && "Only dimensions larger than zero are sized.");
assert(Dim < getNumberOfDimensions() && "Invalid dimension");
- return DimensionSizes[Dim - 1];
+ return DimensionSizes[Dim];
}
/// Return the size of dimension @p dim as isl_pw_aff.
//
// Scalars do not have array dimensions and the first dimension of
// a (possibly multi-dimensional) array also does not carry any size
- // information.
+ // information, in case the array is not newly created.
__isl_give isl_pw_aff *getDimensionSizePw(unsigned Dim) const {
- assert(Dim > 0 && "Only dimensions larger than zero are sized.");
assert(Dim < getNumberOfDimensions() && "Invalid dimension");
- return isl_pw_aff_copy(DimensionSizesPw[Dim - 1]);
+ return isl_pw_aff_copy(DimensionSizesPw[Dim]);
}
/// Get the canonical element type of this array.
if (Sizes.empty())
return false;
+ SizesSCEV.push_back(nullptr);
+
for (auto V : Sizes)
SizesSCEV.push_back(SE.getSCEV(
ConstantInt::get(IntegerType::getInt64Ty(BasePtr->getContext()), V)));
if (AccItr == InsnToMemAcc.end())
return false;
- std::vector<const SCEV *> Sizes(
- AccItr->second.Shape->DelinearizedSizes.begin(),
- AccItr->second.Shape->DelinearizedSizes.end());
+ std::vector<const SCEV *> Sizes = {nullptr};
+
+ Sizes.insert(Sizes.end(), AccItr->second.Shape->DelinearizedSizes.begin(),
+ AccItr->second.Shape->DelinearizedSizes.end());
// Remove the element size. This information is already provided by the
// ElementSize parameter. In case the element size of this access and the
// element size used for delinearization differs the delinearization is
DestAccFunc = SE.getMinusSCEV(DestAccFunc, DestPtrSCEV);
addArrayAccess(Inst, MemoryAccess::MUST_WRITE, DestPtrSCEV->getValue(),
IntegerType::getInt8Ty(DestPtrVal->getContext()), false,
- {DestAccFunc, LengthVal}, {}, Inst.getValueOperand());
+ {DestAccFunc, LengthVal}, {nullptr}, Inst.getValueOperand());
auto *MemTrans = dyn_cast<MemTransferInst>(MemIntr);
if (!MemTrans)
SrcAccFunc = SE.getMinusSCEV(SrcAccFunc, SrcPtrSCEV);
addArrayAccess(Inst, MemoryAccess::READ, SrcPtrSCEV->getValue(),
IntegerType::getInt8Ty(SrcPtrVal->getContext()), false,
- {SrcAccFunc, LengthVal}, {}, Inst.getValueOperand());
+ {SrcAccFunc, LengthVal}, {nullptr}, Inst.getValueOperand());
return true;
}
auto *ArgBasePtr = cast<SCEVUnknown>(SE.getPointerBase(ArgSCEV));
addArrayAccess(Inst, AccType, ArgBasePtr->getValue(),
- ArgBasePtr->getType(), false, {AF}, {}, CI);
+ ArgBasePtr->getType(), false, {AF}, {nullptr}, CI);
}
return true;
}
AccType = MemoryAccess::MAY_WRITE;
addArrayAccess(Inst, AccType, BasePointer->getValue(), ElementType, IsAffine,
- {AccessFunction}, {}, Val);
+ {AccessFunction}, {nullptr}, Val);
}
void ScopBuilder::buildMemoryAccess(MemAccInst Inst, Loop *L) {
for (auto *GlobalRead : GlobalReads)
for (auto *BP : ArrayBasePointers)
addArrayAccess(MemAccInst(GlobalRead), MemoryAccess::READ, BP,
- BP->getType(), false, {AF}, {}, GlobalRead);
+ BP->getType(), false, {AF}, {nullptr}, GlobalRead);
scop->init(AA, AC, DT, LI);
}
int SharedDims = std::min(NewSizes.size(), DimensionSizes.size());
int ExtraDimsNew = NewSizes.size() - SharedDims;
int ExtraDimsOld = DimensionSizes.size() - SharedDims;
- for (int i = 0; i < SharedDims; i++)
- if (NewSizes[i + ExtraDimsNew] != DimensionSizes[i + ExtraDimsOld])
+
+ for (int i = 0; i < SharedDims; i++) {
+ auto &NewSize = NewSizes[i + ExtraDimsNew];
+ auto &KnownSize = DimensionSizes[i + ExtraDimsOld];
+ if (NewSize && KnownSize && NewSize != KnownSize)
return false;
+ }
if (DimensionSizes.size() >= NewSizes.size())
return true;
isl_pw_aff_free(Size);
DimensionSizesPw.clear();
for (const SCEV *Expr : DimensionSizes) {
+ if (!Expr) {
+ DimensionSizesPw.push_back(nullptr);
+ continue;
+ }
isl_pw_aff *Size = S.getPwAffOnly(Expr);
DimensionSizesPw.push_back(Size);
}
void ScopArrayInfo::print(raw_ostream &OS, bool SizeAsPwAff) const {
OS.indent(8) << *getElementType() << " " << getName();
- if (getNumberOfDimensions() > 0)
+ unsigned u = 0;
+ if (getNumberOfDimensions() > 0 && !getDimensionSize(0)) {
OS << "[*]";
- for (unsigned u = 1; u < getNumberOfDimensions(); u++) {
+ u++;
+ }
+ for (; u < getNumberOfDimensions(); u++) {
OS << "[";
if (SizeAsPwAff) {
void MemoryAccess::buildMemIntrinsicAccessRelation() {
assert(isa<MemIntrinsic>(getAccessInstruction()));
- assert(Subscripts.size() == 2 && Sizes.size() == 0);
+ assert(Subscripts.size() == 2 && Sizes.size() == 1);
auto *SubscriptPWA = getPwAff(Subscripts[0]);
auto *SubscriptMap = isl_map_from_pw_aff(SubscriptPWA);
for (int i = Size - 2; i >= 0; --i) {
isl_space *Space;
isl_map *MapOne, *MapTwo;
- isl_pw_aff *DimSize = getPwAff(Sizes[i]);
+ isl_pw_aff *DimSize = getPwAff(Sizes[i + 1]);
isl_space *SpaceSize = isl_pw_aff_get_space(DimSize);
isl_pw_aff_free(DimSize);
AccessRelation = isl_map_flat_range_product(AccessRelation, SubscriptMap);
}
- if (Sizes.size() >= 1 && !isa<SCEVConstant>(Sizes[0]))
+ if (Sizes.size() >= 2 && !isa<SCEVConstant>(Sizes[1]))
AccessRelation = foldAccess(AccessRelation, Statement);
Space = Statement->getDomainSpace();
std::vector<const SCEV *> SCEVSizes;
for (auto size : Sizes)
- SCEVSizes.push_back(getSE()->getConstant(DimSizeType, size, false));
+ if (size)
+ SCEVSizes.push_back(getSE()->getConstant(DimSizeType, size, false));
+ else
+ SCEVSizes.push_back(nullptr);
auto *SAI =
getOrCreateScopArrayInfo(nullptr, ElementType, SCEVSizes,
if (SAI->getBasePtr())
continue;
+ assert(SAI->getNumberOfDimensions() > 0 && SAI->getDimensionSize(0) &&
+ "The size of the outermost dimension is used to declare newly "
+ "created arrays that require memory allocation.");
+
Type *NewArrayType = nullptr;
- for (unsigned i = SAI->getNumberOfDimensions() - 1; i >= 1; i--) {
+ for (int i = SAI->getNumberOfDimensions() - 1; i >= 0; i--) {
auto *DimSize = SAI->getDimensionSize(i);
unsigned UnsignedDimSize = static_cast<const SCEVConstant *>(DimSize)
->getAPInt()
SmallVector<const SCEV *, 4> Sizes;
isl_ast_build *Build =
isl_ast_build_from_context(isl_set_copy(Prog->context));
+ Sizes.push_back(nullptr);
for (long j = 1; j < Kernel->array[i].array->n_index; j++) {
isl_ast_expr *DimSize = isl_ast_build_expr_from_pw_aff(
Build, isl_pw_aff_copy(Kernel->array[i].array->bound[j]));
Type *ArrayTy = EleTy;
SmallVector<const SCEV *, 4> Sizes;
+ Sizes.push_back(nullptr);
for (unsigned int j = 1; j < Var.array->n_index; ++j) {
isl_val *Val = isl_vec_get_element_val(Var.size, j);
long Bound = isl_val_get_num_si(Val);
Json::Value Array;
Array["name"] = SAI->getName();
- for (unsigned i = 1; i < SAI->getNumberOfDimensions(); i++) {
+ unsigned i = 0;
+ if (!SAI->getDimensionSize(i)) {
+ Array["sizes"].append("*");
+ i++;
+ }
+ for (; i < SAI->getNumberOfDimensions(); i++) {
SAI->getDimensionSize(i)->print(RawStringOstream);
Array["sizes"].append(RawStringOstream.str());
Buffer.clear();
if (SAI->getName() != Array["name"].asCString())
return false;
- if (SAI->getNumberOfDimensions() != Array["sizes"].size() + 1)
+ if (SAI->getNumberOfDimensions() != Array["sizes"].size())
return false;
- for (unsigned i = 0; i < Array["sizes"].size(); i++) {
- SAI->getDimensionSize(i + 1)->print(RawStringOstream);
+ for (unsigned i = 1; i < Array["sizes"].size(); i++) {
+ SAI->getDimensionSize(i)->print(RawStringOstream);
if (RawStringOstream.str() != Array["sizes"][i].asCString())
return false;
Buffer.clear();
/// the matrix multiplication pattern.
///
/// Create an access relation of the following form:
-/// [O0, O1, O2, O3, O4, O5, O6, O7, O8] -> [0, O5 + K * OI, OJ],
+/// [O0, O1, O2, O3, O4, O5, O6, O7, O8] -> [O5 + K * OI, OJ],
/// where K is @p Coeff, I is @p FirstDim, J is @p SecondDim.
///
/// It can be used, for example, to create relations that helps to consequently
unsigned Coeff, unsigned FirstDim,
unsigned SecondDim) {
auto *Ctx = isl_map_get_ctx(MapOldIndVar);
- auto *AccessRelSpace = isl_space_alloc(Ctx, 0, 9, 3);
+ auto *AccessRelSpace = isl_space_alloc(Ctx, 0, 9, 2);
auto *AccessRel = isl_map_universe(isl_space_copy(AccessRelSpace));
auto *ConstrSpace = isl_local_space_from_space(AccessRelSpace);
auto *Constr = isl_constraint_alloc_equality(ConstrSpace);
- Constr = isl_constraint_set_coefficient_si(Constr, isl_dim_out, 1, -1);
+ Constr = isl_constraint_set_coefficient_si(Constr, isl_dim_out, 0, -1);
Constr = isl_constraint_set_coefficient_si(Constr, isl_dim_in, 5, 1);
Constr =
isl_constraint_set_coefficient_si(Constr, isl_dim_in, FirstDim, Coeff);
AccessRel = isl_map_add_constraint(AccessRel, Constr);
- AccessRel = isl_map_fix_si(AccessRel, isl_dim_out, 0, 0);
- AccessRel = isl_map_equate(AccessRel, isl_dim_in, SecondDim, isl_dim_out, 2);
+ AccessRel = isl_map_equate(AccessRel, isl_dim_in, SecondDim, isl_dim_out, 1);
return isl_map_apply_range(MapOldIndVar, AccessRel);
}
; CHECK: double MemRef_B[*][1024]; // Element size 8
; CHECK: double MemRef_beta; // Element size 8
; CHECK: double MemRef_A[*][1056]; // Element size 8
-; CHECK: double D[*][270336]; // Element size 8
-; CHECK: double E[*][270336][200000]; // Element size 8
-; CHECK: i64 F[*][270336]; // Element size 8
+; CHECK: double D[270336]; // Element size 8
+; CHECK: double E[270336][200000]; // Element size 8
+; CHECK: i64 F[270336]; // Element size 8
;
-; CHECK:New access function '{ Stmt_bb12[i0, i1, i2] -> E[0, i2, i0] }' detected in JSCOP file
+; CHECK:New access function '{ Stmt_bb12[i0, i1, i2] -> E[i2, i0] }' detected in JSCOP file
;
; CODEGEN:define internal void @create_arrays(i32 %arg, i32 %arg1, i32 %arg2, double %arg3, double %beta, [1056 x double]* %A, [1024 x double]* %B, [1056 x double]* %arg7) #0 {
; CODEGEN:bb:
;
; CODEGEN: %beta.s2a.reload = load double, double* %beta.s2a
; CODEGEN: %polly.access.cast.E = bitcast [270336 x [200000 x double]]* %E to double*
-; CODEGEN: %polly.access.add.E = add nsw i64 0, %polly.indvar33
-; CODEGEN: %polly.access.mul.E = mul nsw i64 %polly.access.add.E, 200000
-; CODEGEN: %polly.access.add.E36 = add nsw i64 %polly.access.mul.E, %polly.indvar
+; CODEGEN: %polly.access.mul.E = mul nsw i64 %polly.indvar33, 200000
+; CODEGEN: %polly.access.add.E = add nsw i64 %polly.access.mul.E, %polly.indvar
;
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-unknown"
{
"arrays" : [
- {
+ {
"name" : "MemRef_B",
- "sizes" : [ "1024" ],
+ "sizes" : [ "*", "1024" ],
"type" : "double"
},
{
"name" : "MemRef_A",
- "sizes" : [ "1056" ],
+ "sizes" : [ "*", "1056" ],
"type" : "double"
}
],
"arrays" : [
{
"name" : "MemRef_B",
- "sizes" : [ "1024" ],
+ "sizes" : [ "*", "1024" ],
"type" : "double"
},
{
"name" : "MemRef_A",
- "sizes" : [ "1056" ],
+ "sizes" : [ "*", "1056" ],
"type" : "double"
},
{
"accesses" : [
{
"kind" : "read",
- "relation" : "{ Stmt_bb12[i0, i1, i2] -> E[0, i2, i0] }"
+ "relation" : "{ Stmt_bb12[i0, i1, i2] -> E[i2, i0] }"
},
{
"kind" : "read",
"arrays" : [
{
"name" : "MemRef_A",
+ "sizes" : [ "*" ],
"type" : "double"
}
],
"arrays" : [
{
"name" : "MemRef_A",
+ "sizes" : [ "*" ],
"type" : "double"
}
],
; C[i][j] += alpha * A[i][k] * B[k][j];
; }
;
-; CHECK: double Packed_A[*][ { [] -> [(1024)] } ][ { [] -> [(4)] } ]; // Element size 8
-; CHECK: double Packed_B[*][ { [] -> [(3072)] } ][ { [] -> [(8)] } ]; // Element size 8
+; CHECK: double Packed_A[ { [] -> [(1024)] } ][ { [] -> [(4)] } ]; // Element size 8
+; CHECK: double Packed_B[ { [] -> [(3072)] } ][ { [] -> [(8)] } ]; // Element size 8
;
; CHECK: { Stmt_bb14[i0, i1, i2] -> MemRef_arg6[i0, i2] };
-; CHECK: new: { Stmt_bb14[i0, i1, i2] -> Packed_A[0, o1, o2] : 256*floor((-i2 + o1)/256) = -i2 + o1 and 4*floor((-i0 + o2)/4) = -i0 + o2 and 0 <= o2 <= 3 and -3 + i0 - 16*floor((i0)/16) <= 4*floor((o1)/256) <= i0 - 16*floor((i0)/16) };
+; CHECK: new: { Stmt_bb14[i0, i1, i2] -> Packed_A[o0, o1] : 256*floor((-i2 + o0)/256) = -i2 + o0 and 4*floor((-i0 + o1)/4) = -i0 + o1 and 0 <= o1 <= 3 and -3 + i0 - 16*floor((i0)/16) <= 4*floor((o0)/256) <= i0 - 16*floor((i0)/16) };
;
; CHECK: { Stmt_bb14[i0, i1, i2] -> MemRef_arg7[i2, i1] };
-; CHECK: new: { Stmt_bb14[i0, i1, i2] -> Packed_B[0, o1, o2] : 256*floor((-i2 + o1)/256) = -i2 + o1 and 8*floor((-i1 + o2)/8) = -i1 + o2 and 0 <= o2 <= 7 and -7 + i1 - 96*floor((i1)/96) <= 8*floor((o1)/256) <= i1 - 96*floor((i1)/96) };
+; CHECK: new: { Stmt_bb14[i0, i1, i2] -> Packed_B[o0, o1] : 256*floor((-i2 + o0)/256) = -i2 + o0 and 8*floor((-i1 + o1)/8) = -i1 + o1 and 0 <= o1 <= 7 and -7 + i1 - 96*floor((i1)/96) <= 8*floor((o0)/256) <= i1 - 96*floor((i1)/96) };
;
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-unknown"