@@ -185,6 +185,12 @@ static void moveInstructionBefore(Instruction &I, Instruction &Dest,
185
185
ICFLoopSafetyInfo &SafetyInfo,
186
186
MemorySSAUpdater *MSSAU, ScalarEvolution *SE);
187
187
188
+ static void foreachMemoryAccess (MemorySSA *MSSA, Loop *L,
189
+ function_ref<void (Instruction *)> Fn);
190
+ static SmallVector<SmallSetVector<Value *, 8 >, 0 >
191
+ collectPromotionCandidates (MemorySSA *MSSA, AliasAnalysis *AA, Loop *L,
192
+ SmallVectorImpl<Instruction *> &MaybePromotable);
193
+
188
194
namespace {
189
195
struct LoopInvariantCodeMotion {
190
196
bool runOnLoop (Loop *L, AAResults *AA, LoopInfo *LI, DominatorTree *DT,
@@ -203,9 +209,6 @@ struct LoopInvariantCodeMotion {
203
209
204
210
std::unique_ptr<AliasSetTracker>
205
211
collectAliasInfoForLoop (Loop *L, LoopInfo *LI, AAResults *AA);
206
- std::unique_ptr<AliasSetTracker>
207
- collectAliasInfoForLoopWithMSSA (Loop *L, AAResults *AA,
208
- MemorySSAUpdater *MSSAU);
209
212
};
210
213
211
214
struct LegacyLICMPass : public LoopPass {
@@ -430,31 +433,48 @@ bool LoopInvariantCodeMotion::runOnLoop(
430
433
PredIteratorCache PIC;
431
434
432
435
bool Promoted = false ;
433
-
434
- // Build an AST using MSSA.
435
- if (!CurAST.get ())
436
- CurAST = collectAliasInfoForLoopWithMSSA (L, AA, MSSAU.get ());
437
-
438
- // Loop over all of the alias sets in the tracker object.
439
- for (AliasSet &AS : *CurAST) {
440
- // We can promote this alias set if it has a store, if it is a "Must"
441
- // alias set, if the pointer is loop invariant, and if we are not
442
- // eliminating any volatile loads or stores.
443
- if (AS.isForwardingAliasSet () || !AS.isMod () || !AS.isMustAlias () ||
444
- !L->isLoopInvariant (AS.begin ()->getValue ()))
445
- continue ;
446
-
447
- assert (
448
- !AS.empty () &&
449
- " Must alias set should have at least one pointer element in it!" );
450
-
451
- SmallSetVector<Value *, 8 > PointerMustAliases;
452
- for (const auto &ASI : AS)
453
- PointerMustAliases.insert (ASI.getValue ());
454
-
455
- Promoted |= promoteLoopAccessesToScalars (
456
- PointerMustAliases, ExitBlocks, InsertPts, MSSAInsertPts, PIC, LI,
457
- DT, TLI, L, CurAST.get (), MSSAU.get (), &SafetyInfo, ORE);
436
+ if (CurAST.get ()) {
437
+ // Loop over all of the alias sets in the tracker object.
438
+ for (AliasSet &AS : *CurAST) {
439
+ // We can promote this alias set if it has a store, if it is a "Must"
440
+ // alias set, if the pointer is loop invariant, and if we are not
441
+ // eliminating any volatile loads or stores.
442
+ if (AS.isForwardingAliasSet () || !AS.isMod () || !AS.isMustAlias () ||
443
+ !L->isLoopInvariant (AS.begin ()->getValue ()))
444
+ continue ;
445
+
446
+ assert (
447
+ !AS.empty () &&
448
+ " Must alias set should have at least one pointer element in it!" );
449
+
450
+ SmallSetVector<Value *, 8 > PointerMustAliases;
451
+ for (const auto &ASI : AS)
452
+ PointerMustAliases.insert (ASI.getValue ());
453
+
454
+ Promoted |= promoteLoopAccessesToScalars (
455
+ PointerMustAliases, ExitBlocks, InsertPts, MSSAInsertPts, PIC, LI,
456
+ DT, TLI, L, CurAST.get (), MSSAU.get (), &SafetyInfo, ORE);
457
+ }
458
+ } else {
459
+ SmallVector<Instruction *, 16 > MaybePromotable;
460
+ foreachMemoryAccess (MSSA, L, [&](Instruction *I) {
461
+ MaybePromotable.push_back (I);
462
+ });
463
+
464
+ // Promoting one set of accesses may make the pointers for another set
465
+ // loop invariant, so run this in a loop (with the MaybePromotable set
466
+ // decreasing in size over time).
467
+ bool LocalPromoted;
468
+ do {
469
+ LocalPromoted = false ;
470
+ for (const SmallSetVector<Value *, 8 > &PointerMustAliases :
471
+ collectPromotionCandidates (MSSA, AA, L, MaybePromotable)) {
472
+ LocalPromoted |= promoteLoopAccessesToScalars (
473
+ PointerMustAliases, ExitBlocks, InsertPts, MSSAInsertPts, PIC,
474
+ LI, DT, TLI, L, /* AST*/ nullptr , MSSAU.get (), &SafetyInfo, ORE);
475
+ }
476
+ Promoted |= LocalPromoted;
477
+ } while (LocalPromoted);
458
478
}
459
479
460
480
// Once we have promoted values across the loop body we have to
@@ -2217,6 +2237,77 @@ bool llvm::promoteLoopAccessesToScalars(
2217
2237
return true ;
2218
2238
}
2219
2239
2240
+ static void foreachMemoryAccess (MemorySSA *MSSA, Loop *L,
2241
+ function_ref<void (Instruction *)> Fn) {
2242
+ for (const BasicBlock *BB : L->blocks ())
2243
+ if (const auto *Accesses = MSSA->getBlockAccesses (BB))
2244
+ for (const auto &Access : *Accesses)
2245
+ if (const auto *MUD = dyn_cast<MemoryUseOrDef>(&Access))
2246
+ Fn (MUD->getMemoryInst ());
2247
+ }
2248
+
2249
+ static SmallVector<SmallSetVector<Value *, 8 >, 0 >
2250
+ collectPromotionCandidates (MemorySSA *MSSA, AliasAnalysis *AA, Loop *L,
2251
+ SmallVectorImpl<Instruction *> &MaybePromotable) {
2252
+ AliasSetTracker AST (*AA);
2253
+
2254
+ auto IsPotentiallyPromotable = [L](const Instruction *I) {
2255
+ if (const auto *SI = dyn_cast<StoreInst>(I))
2256
+ return L->isLoopInvariant (SI->getPointerOperand ());
2257
+ if (const auto *LI = dyn_cast<LoadInst>(I))
2258
+ return L->isLoopInvariant (LI->getPointerOperand ());
2259
+ return false ;
2260
+ };
2261
+
2262
+ // Populate AST with potentially promotable accesses and remove them from
2263
+ // MaybePromotable, so they will not be checked again on the next iteration.
2264
+ SmallPtrSet<Value *, 16 > AttemptingPromotion;
2265
+ llvm::erase_if (MaybePromotable, [&](Instruction *I) {
2266
+ if (IsPotentiallyPromotable (I)) {
2267
+ AttemptingPromotion.insert (I);
2268
+ AST.add (I);
2269
+ return true ;
2270
+ }
2271
+ return false ;
2272
+ });
2273
+
2274
+ // We're only interested in must-alias sets that contain a mod.
2275
+ SmallVector<const AliasSet *, 8 > Sets;
2276
+ for (AliasSet &AS : AST)
2277
+ if (!AS.isForwardingAliasSet () && AS.isMod () && AS.isMustAlias ())
2278
+ Sets.push_back (&AS);
2279
+
2280
+ if (Sets.empty ())
2281
+ return {}; // Nothing to promote...
2282
+
2283
+ // Discard any sets for which there is an aliasing non-promotable access.
2284
+ foreachMemoryAccess (MSSA, L, [&](Instruction *I) {
2285
+ if (AttemptingPromotion.contains (I))
2286
+ return ;
2287
+
2288
+ if (Optional<MemoryLocation> Loc = MemoryLocation::getOrNone (I)) {
2289
+ llvm::erase_if (Sets, [&](const AliasSet *AS) {
2290
+ return AS->aliasesPointer (Loc->Ptr , Loc->Size , Loc->AATags , *AA)
2291
+ != NoAlias;
2292
+ });
2293
+ } else {
2294
+ llvm::erase_if (Sets, [&](const AliasSet *AS) {
2295
+ return AS->aliasesUnknownInst (I, *AA);
2296
+ });
2297
+ }
2298
+ });
2299
+
2300
+ SmallVector<SmallSetVector<Value *, 8 >, 0 > Result;
2301
+ for (const AliasSet *Set : Sets) {
2302
+ SmallSetVector<Value *, 8 > PointerMustAliases;
2303
+ for (const auto &ASI : *Set)
2304
+ PointerMustAliases.insert (ASI.getValue ());
2305
+ Result.push_back (std::move (PointerMustAliases));
2306
+ }
2307
+
2308
+ return Result;
2309
+ }
2310
+
2220
2311
// / Returns an owning pointer to an alias set which incorporates aliasing info
2221
2312
// / from L and all subloops of L.
2222
2313
std::unique_ptr<AliasSetTracker>
@@ -2237,15 +2328,6 @@ LoopInvariantCodeMotion::collectAliasInfoForLoop(Loop *L, LoopInfo *LI,
2237
2328
return CurAST;
2238
2329
}
2239
2330
2240
- std::unique_ptr<AliasSetTracker>
2241
- LoopInvariantCodeMotion::collectAliasInfoForLoopWithMSSA (
2242
- Loop *L, AAResults *AA, MemorySSAUpdater *MSSAU) {
2243
- auto *MSSA = MSSAU->getMemorySSA ();
2244
- auto CurAST = std::make_unique<AliasSetTracker>(*AA, MSSA, L);
2245
- CurAST->addAllInstructionsInLoopUsingMSSA ();
2246
- return CurAST;
2247
- }
2248
-
2249
2331
static bool pointerInvalidatedByLoop (MemoryLocation MemLoc,
2250
2332
AliasSetTracker *CurAST, Loop *CurLoop,
2251
2333
AAResults *AA) {
0 commit comments