@@ -1154,6 +1154,195 @@ void ScopBuilder::addArrayAccess(ScopStmt *Stmt, MemAccInst MemAccInst,
1154
1154
MemAccess->setFortranArrayDescriptor (FAD);
1155
1155
}
1156
1156
1157
+ // / Check if @p Expr is divisible by @p Size.
1158
+ static bool isDivisible (const SCEV *Expr, unsigned Size , ScalarEvolution &SE) {
1159
+ assert (Size != 0 );
1160
+ if (Size == 1 )
1161
+ return true ;
1162
+
1163
+ // Only one factor needs to be divisible.
1164
+ if (auto *MulExpr = dyn_cast<SCEVMulExpr>(Expr)) {
1165
+ for (auto *FactorExpr : MulExpr->operands ())
1166
+ if (isDivisible (FactorExpr, Size , SE))
1167
+ return true ;
1168
+ return false ;
1169
+ }
1170
+
1171
+ // For other n-ary expressions (Add, AddRec, Max,...) all operands need
1172
+ // to be divisible.
1173
+ if (auto *NAryExpr = dyn_cast<SCEVNAryExpr>(Expr)) {
1174
+ for (auto *OpExpr : NAryExpr->operands ())
1175
+ if (!isDivisible (OpExpr, Size , SE))
1176
+ return false ;
1177
+ return true ;
1178
+ }
1179
+
1180
+ auto *SizeSCEV = SE.getConstant (Expr->getType (), Size );
1181
+ auto *UDivSCEV = SE.getUDivExpr (Expr, SizeSCEV);
1182
+ auto *MulSCEV = SE.getMulExpr (UDivSCEV, SizeSCEV);
1183
+ return MulSCEV == Expr;
1184
+ }
1185
+
1186
+ void ScopBuilder::foldSizeConstantsToRight () {
1187
+ isl::union_set Accessed = scop->getAccesses ().range ();
1188
+
1189
+ for (auto Array : scop->arrays ()) {
1190
+ if (Array->getNumberOfDimensions () <= 1 )
1191
+ continue ;
1192
+
1193
+ isl::space Space = Array->getSpace ();
1194
+ Space = Space.align_params (Accessed.get_space ());
1195
+
1196
+ if (!Accessed.contains (Space))
1197
+ continue ;
1198
+
1199
+ isl::set Elements = Accessed.extract_set (Space);
1200
+ isl::map Transform = isl::map::universe (Array->getSpace ().map_from_set ());
1201
+
1202
+ std::vector<int > Int;
1203
+ int Dims = Elements.dim (isl::dim::set);
1204
+ for (int i = 0 ; i < Dims; i++) {
1205
+ isl::set DimOnly = isl::set (Elements).project_out (isl::dim::set, 0 , i);
1206
+ DimOnly = DimOnly.project_out (isl::dim::set, 1 , Dims - i - 1 );
1207
+ DimOnly = DimOnly.lower_bound_si (isl::dim::set, 0 , 0 );
1208
+
1209
+ isl::basic_set DimHull = DimOnly.affine_hull ();
1210
+
1211
+ if (i == Dims - 1 ) {
1212
+ Int.push_back (1 );
1213
+ Transform = Transform.equate (isl::dim::in, i, isl::dim::out, i);
1214
+ continue ;
1215
+ }
1216
+
1217
+ if (DimHull.dim (isl::dim::div ) == 1 ) {
1218
+ isl::aff Diff = DimHull.get_div (0 );
1219
+ isl::val Val = Diff.get_denominator_val ();
1220
+
1221
+ int ValInt = 1 ;
1222
+ if (Val.is_int ()) {
1223
+ auto ValAPInt = APIntFromVal (Val);
1224
+ if (ValAPInt.isSignedIntN (32 ))
1225
+ ValInt = ValAPInt.getSExtValue ();
1226
+ } else {
1227
+ }
1228
+
1229
+ Int.push_back (ValInt);
1230
+ isl::constraint C = isl::constraint::alloc_equality (
1231
+ isl::local_space (Transform.get_space ()));
1232
+ C = C.set_coefficient_si (isl::dim::out, i, ValInt);
1233
+ C = C.set_coefficient_si (isl::dim::in, i, -1 );
1234
+ Transform = Transform.add_constraint (C);
1235
+ continue ;
1236
+ }
1237
+
1238
+ isl::basic_set ZeroSet = isl::basic_set (DimHull);
1239
+ ZeroSet = ZeroSet.fix_si (isl::dim::set, 0 , 0 );
1240
+
1241
+ int ValInt = 1 ;
1242
+ if (ZeroSet.is_equal (DimHull)) {
1243
+ ValInt = 0 ;
1244
+ }
1245
+
1246
+ Int.push_back (ValInt);
1247
+ Transform = Transform.equate (isl::dim::in, i, isl::dim::out, i);
1248
+ }
1249
+
1250
+ isl::set MappedElements = isl::map (Transform).domain ();
1251
+ if (!Elements.is_subset (MappedElements))
1252
+ continue ;
1253
+
1254
+ bool CanFold = true ;
1255
+ if (Int[0 ] <= 1 )
1256
+ CanFold = false ;
1257
+
1258
+ unsigned NumDims = Array->getNumberOfDimensions ();
1259
+ for (unsigned i = 1 ; i < NumDims - 1 ; i++)
1260
+ if (Int[0 ] != Int[i] && Int[i])
1261
+ CanFold = false ;
1262
+
1263
+ if (!CanFold)
1264
+ continue ;
1265
+
1266
+ for (auto &Access : scop->access_functions ())
1267
+ if (Access->getScopArrayInfo () == Array)
1268
+ Access->setAccessRelation (
1269
+ Access->getAccessRelation ().apply_range (Transform));
1270
+
1271
+ std::vector<const SCEV *> Sizes;
1272
+ for (unsigned i = 0 ; i < NumDims; i++) {
1273
+ auto Size = Array->getDimensionSize (i);
1274
+
1275
+ if (i == NumDims - 1 )
1276
+ Size = SE.getMulExpr (Size , SE.getConstant (Size ->getType (), Int[0 ]));
1277
+ Sizes.push_back (Size );
1278
+ }
1279
+
1280
+ Array->updateSizes (Sizes, false /* CheckConsistency */ );
1281
+ }
1282
+ }
1283
+
1284
+ void ScopBuilder::markFortranArrays () {
1285
+ for (ScopStmt &Stmt : *scop) {
1286
+ for (MemoryAccess *MemAcc : Stmt) {
1287
+ Value *FAD = MemAcc->getFortranArrayDescriptor ();
1288
+ if (!FAD)
1289
+ continue ;
1290
+
1291
+ // TODO: const_cast-ing to edit
1292
+ ScopArrayInfo *SAI =
1293
+ const_cast <ScopArrayInfo *>(MemAcc->getLatestScopArrayInfo ());
1294
+ assert (SAI && " memory access into a Fortran array does not "
1295
+ " have an associated ScopArrayInfo" );
1296
+ SAI->applyAndSetFAD (FAD);
1297
+ }
1298
+ }
1299
+ }
1300
+
1301
+ void ScopBuilder::finalizeAccesses () {
1302
+ updateAccessDimensionality ();
1303
+ foldSizeConstantsToRight ();
1304
+ foldAccessRelations ();
1305
+ assumeNoOutOfBounds ();
1306
+ markFortranArrays ();
1307
+ }
1308
+
1309
+ void ScopBuilder::updateAccessDimensionality () {
1310
+ // Check all array accesses for each base pointer and find a (virtual) element
1311
+ // size for the base pointer that divides all access functions.
1312
+ for (ScopStmt &Stmt : *scop)
1313
+ for (MemoryAccess *Access : Stmt) {
1314
+ if (!Access->isArrayKind ())
1315
+ continue ;
1316
+ ScopArrayInfo *Array =
1317
+ const_cast <ScopArrayInfo *>(Access->getScopArrayInfo ());
1318
+
1319
+ if (Array->getNumberOfDimensions () != 1 )
1320
+ continue ;
1321
+ unsigned DivisibleSize = Array->getElemSizeInBytes ();
1322
+ const SCEV *Subscript = Access->getSubscript (0 );
1323
+ while (!isDivisible (Subscript, DivisibleSize, SE))
1324
+ DivisibleSize /= 2 ;
1325
+ auto *Ty = IntegerType::get (SE.getContext (), DivisibleSize * 8 );
1326
+ Array->updateElementType (Ty);
1327
+ }
1328
+
1329
+ for (auto &Stmt : *scop)
1330
+ for (auto &Access : Stmt)
1331
+ Access->updateDimensionality ();
1332
+ }
1333
+
1334
+ void ScopBuilder::foldAccessRelations () {
1335
+ for (auto &Stmt : *scop)
1336
+ for (auto &Access : Stmt)
1337
+ Access->foldAccessRelation ();
1338
+ }
1339
+
1340
+ void ScopBuilder::assumeNoOutOfBounds () {
1341
+ for (auto &Stmt : *scop)
1342
+ for (auto &Access : Stmt)
1343
+ Access->assumeNoOutOfBound ();
1344
+ }
1345
+
1157
1346
void ScopBuilder::ensureValueWrite (Instruction *Inst) {
1158
1347
// Find the statement that defines the value of Inst. That statement has to
1159
1348
// write the value to make it available to those statements that read it.
@@ -2367,7 +2556,7 @@ void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) {
2367
2556
2368
2557
scop->buildSchedule (LI);
2369
2558
2370
- scop-> finalizeAccesses ();
2559
+ finalizeAccesses ();
2371
2560
2372
2561
scop->realignParams ();
2373
2562
addUserContext ();
0 commit comments