@@ -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
@@ -2218,6 +2238,77 @@ bool llvm::promoteLoopAccessesToScalars(
2218
2238
return true ;
2219
2239
}
2220
2240
2241
+ static void foreachMemoryAccess (MemorySSA *MSSA, Loop *L,
2242
+ function_ref<void (Instruction *)> Fn) {
2243
+ for (const BasicBlock *BB : L->blocks ())
2244
+ if (const auto *Accesses = MSSA->getBlockAccesses (BB))
2245
+ for (const auto &Access : *Accesses)
2246
+ if (const auto *MUD = dyn_cast<MemoryUseOrDef>(&Access))
2247
+ Fn (MUD->getMemoryInst ());
2248
+ }
2249
+
2250
+ static SmallVector<SmallSetVector<Value *, 8 >, 0 >
2251
+ collectPromotionCandidates (MemorySSA *MSSA, AliasAnalysis *AA, Loop *L,
2252
+ SmallVectorImpl<Instruction *> &MaybePromotable) {
2253
+ AliasSetTracker AST (*AA);
2254
+
2255
+ auto IsPotentiallyPromotable = [L](const Instruction *I) {
2256
+ if (const auto *SI = dyn_cast<StoreInst>(I))
2257
+ return L->isLoopInvariant (SI->getPointerOperand ());
2258
+ if (const auto *LI = dyn_cast<LoadInst>(I))
2259
+ return L->isLoopInvariant (LI->getPointerOperand ());
2260
+ return false ;
2261
+ };
2262
+
2263
+ // Populate AST with potentially promotable accesses and remove them from
2264
+ // MaybePromotable, so they will not be checked again on the next iteration.
2265
+ SmallPtrSet<Value *, 16 > AttemptingPromotion;
2266
+ llvm::erase_if (MaybePromotable, [&](Instruction *I) {
2267
+ if (IsPotentiallyPromotable (I)) {
2268
+ AttemptingPromotion.insert (I);
2269
+ AST.add (I);
2270
+ return true ;
2271
+ }
2272
+ return false ;
2273
+ });
2274
+
2275
+ // We're only interested in must-alias sets that contain a mod.
2276
+ SmallVector<const AliasSet *, 8 > Sets;
2277
+ for (AliasSet &AS : AST)
2278
+ if (!AS.isForwardingAliasSet () && AS.isMod () && AS.isMustAlias ())
2279
+ Sets.push_back (&AS);
2280
+
2281
+ if (Sets.empty ())
2282
+ return {}; // Nothing to promote...
2283
+
2284
+ // Discard any sets for which there is an aliasing non-promotable access.
2285
+ foreachMemoryAccess (MSSA, L, [&](Instruction *I) {
2286
+ if (AttemptingPromotion.contains (I))
2287
+ return ;
2288
+
2289
+ if (Optional<MemoryLocation> Loc = MemoryLocation::getOrNone (I)) {
2290
+ llvm::erase_if (Sets, [&](const AliasSet *AS) {
2291
+ return AS->aliasesPointer (Loc->Ptr , Loc->Size , Loc->AATags , *AA)
2292
+ != NoAlias;
2293
+ });
2294
+ } else {
2295
+ llvm::erase_if (Sets, [&](const AliasSet *AS) {
2296
+ return AS->aliasesUnknownInst (I, *AA);
2297
+ });
2298
+ }
2299
+ });
2300
+
2301
+ SmallVector<SmallSetVector<Value *, 8 >, 0 > Result;
2302
+ for (const AliasSet *Set : Sets) {
2303
+ SmallSetVector<Value *, 8 > PointerMustAliases;
2304
+ for (const auto &ASI : *Set)
2305
+ PointerMustAliases.insert (ASI.getValue ());
2306
+ Result.push_back (std::move (PointerMustAliases));
2307
+ }
2308
+
2309
+ return Result;
2310
+ }
2311
+
2221
2312
// / Returns an owning pointer to an alias set which incorporates aliasing info
2222
2313
// / from L and all subloops of L.
2223
2314
std::unique_ptr<AliasSetTracker>
@@ -2238,15 +2329,6 @@ LoopInvariantCodeMotion::collectAliasInfoForLoop(Loop *L, LoopInfo *LI,
2238
2329
return CurAST;
2239
2330
}
2240
2331
2241
- std::unique_ptr<AliasSetTracker>
2242
- LoopInvariantCodeMotion::collectAliasInfoForLoopWithMSSA (
2243
- Loop *L, AAResults *AA, MemorySSAUpdater *MSSAU) {
2244
- auto *MSSA = MSSAU->getMemorySSA ();
2245
- auto CurAST = std::make_unique<AliasSetTracker>(*AA, MSSA, L);
2246
- CurAST->addAllInstructionsInLoopUsingMSSA ();
2247
- return CurAST;
2248
- }
2249
-
2250
2332
static bool pointerInvalidatedByLoop (MemoryLocation MemLoc,
2251
2333
AliasSetTracker *CurAST, Loop *CurLoop,
2252
2334
AAResults *AA) {
0 commit comments