@@ -1011,16 +1011,15 @@ class AllocOptimize {
1011
1011
AllocOptimize (AllocationInst *TheMemory, SmallVectorImpl<PMOMemoryUse> &Uses,
1012
1012
SmallVectorImpl<SILInstruction *> &Releases);
1013
1013
1014
- bool doIt ();
1014
+ bool optimizeMemoryAccesses ();
1015
+ bool tryToRemoveDeadAllocation ();
1015
1016
1016
1017
private:
1017
1018
bool promoteLoad (SILInstruction *Inst);
1018
1019
void promoteDestroyAddr (DestroyAddrInst *DAI,
1019
1020
MutableArrayRef<AvailableValue> Values);
1020
1021
bool canPromoteDestroyAddr (DestroyAddrInst *DAI,
1021
1022
SmallVectorImpl<AvailableValue> &AvailableValues);
1022
-
1023
- bool tryToRemoveDeadAllocation ();
1024
1023
};
1025
1024
1026
1025
} // end anonymous namespace
@@ -1376,79 +1375,135 @@ bool AllocOptimize::tryToRemoveDeadAllocation() {
1376
1375
return true ;
1377
1376
}
1378
1377
1379
- // / doIt - returns true on error.
1380
- bool AllocOptimize::doIt () {
1381
- bool Changed = false ;
1382
-
1383
- // Don't try to optimize incomplete aggregates.
1384
- if (MemoryType.aggregateHasUnreferenceableStorage ())
1385
- return false ;
1378
+ bool AllocOptimize::optimizeMemoryAccesses () {
1379
+ bool changed = false ;
1386
1380
1387
1381
// If we've successfully checked all of the definitive initialization
1388
1382
// requirements, try to promote loads. This can explode copy_addrs, so the
1389
1383
// use list may change size.
1390
1384
for (unsigned i = 0 ; i != Uses.size (); ++i) {
1391
- auto &Use = Uses[i];
1385
+ auto &use = Uses[i];
1392
1386
// Ignore entries for instructions that got expanded along the way.
1393
- if (Use .Inst && Use .Kind == PMOUseKind::Load) {
1394
- if (promoteLoad (Use .Inst )) {
1387
+ if (use .Inst && use .Kind == PMOUseKind::Load) {
1388
+ if (promoteLoad (use .Inst )) {
1395
1389
Uses[i].Inst = nullptr ; // remove entry if load got deleted.
1396
- Changed = true ;
1390
+ changed = true ;
1397
1391
}
1398
1392
}
1399
1393
}
1400
-
1401
- // If this is an allocation, try to remove it completely.
1402
- Changed |= tryToRemoveDeadAllocation ();
1403
1394
1404
- return Changed;
1395
+ return changed;
1396
+ }
1397
+
1398
+ // ===----------------------------------------------------------------------===//
1399
+ // Top Level Entrypoints
1400
+ // ===----------------------------------------------------------------------===//
1401
+
1402
+ static AllocationInst *getOptimizableAllocation (SILInstruction *i) {
1403
+ if (!isa<AllocBoxInst>(i) && !isa<AllocStackInst>(i)) {
1404
+ return nullptr ;
1405
+ }
1406
+
1407
+ auto *alloc = cast<AllocationInst>(i);
1408
+
1409
+ // If our aggregate has unreferencable storage, we can't optimize. Return
1410
+ // nullptr.
1411
+ if (getMemoryType (alloc).aggregateHasUnreferenceableStorage ())
1412
+ return nullptr ;
1413
+
1414
+ // Otherwise we are good to go. Lets try to optimize this memory!
1415
+ return alloc;
1405
1416
}
1406
1417
1407
- static bool optimizeMemoryAllocations (SILFunction &Fn) {
1408
- bool Changed = false ;
1409
- for (auto &BB : Fn) {
1410
- auto I = BB.begin (), E = BB.end ();
1411
- while (I != E) {
1412
- SILInstruction *Inst = &*I;
1413
- if (!isa<AllocBoxInst>(Inst) && !isa<AllocStackInst>(Inst)) {
1414
- ++I;
1418
+ static bool optimizeMemoryAccesses (SILFunction &fn) {
1419
+ bool changed = false ;
1420
+ for (auto &bb : fn) {
1421
+ auto i = bb.begin (), e = bb.end ();
1422
+ while (i != e) {
1423
+ // First see if i is an allocation that we can optimize. If not, skip it.
1424
+ AllocationInst *alloc = getOptimizableAllocation (&*i);
1425
+ if (!alloc) {
1426
+ ++i;
1415
1427
continue ;
1416
1428
}
1417
- auto Alloc = cast<AllocationInst>(Inst);
1418
1429
1419
- LLVM_DEBUG (llvm::dbgs () << " *** PMO Optimize looking at: " << *Alloc
1420
- << " \n " );
1421
- PMOMemoryObjectInfo MemInfo (Alloc );
1430
+ LLVM_DEBUG (llvm::dbgs () << " *** PMO Optimize Memory Accesses looking at: "
1431
+ << *alloc << " \n " );
1432
+ PMOMemoryObjectInfo memInfo (alloc );
1422
1433
1423
1434
// Set up the datastructure used to collect the uses of the allocation.
1424
- SmallVector<PMOMemoryUse, 16 > Uses ;
1425
- SmallVector<SILInstruction*, 4 > Releases ;
1435
+ SmallVector<PMOMemoryUse, 16 > uses ;
1436
+ SmallVector<SILInstruction *, 4 > destroys ;
1426
1437
1427
1438
// Walk the use list of the pointer, collecting them. If we are not able
1428
1439
// to optimize, skip this value. *NOTE* We may still scalarize values
1429
1440
// inside the value.
1430
- if (!collectPMOElementUsesFrom (MemInfo, Uses, Releases )) {
1431
- ++I ;
1441
+ if (!collectPMOElementUsesFrom (memInfo, uses, destroys )) {
1442
+ ++i ;
1432
1443
continue ;
1433
1444
}
1434
1445
1435
- Changed |= AllocOptimize (Alloc, Uses, Releases).doIt ();
1436
-
1437
- // Carefully move iterator to avoid invalidation problems.
1438
- ++I;
1439
- if (Alloc->use_empty ()) {
1440
- Alloc->eraseFromParent ();
1446
+ AllocOptimize allocOptimize (alloc, uses, destroys);
1447
+ changed |= allocOptimize.optimizeMemoryAccesses ();
1448
+
1449
+ // Move onto the next instruction. We know this is safe since we do not
1450
+ // eliminate allocations here.
1451
+ ++i;
1452
+ }
1453
+ }
1454
+
1455
+ return changed;
1456
+ }
1457
+
1458
+ static bool eliminateDeadAllocations (SILFunction &fn) {
1459
+ bool changed = false ;
1460
+ for (auto &bb : fn) {
1461
+ auto i = bb.begin (), e = bb.end ();
1462
+ while (i != e) {
1463
+ // First see if i is an allocation that we can optimize. If not, skip it.
1464
+ AllocationInst *alloc = getOptimizableAllocation (&*i);
1465
+ if (!alloc) {
1466
+ ++i;
1467
+ continue ;
1468
+ }
1469
+
1470
+ LLVM_DEBUG (llvm::dbgs ()
1471
+ << " *** PMO Dead Allocation Elimination looking at: " << *alloc
1472
+ << " \n " );
1473
+ PMOMemoryObjectInfo memInfo (alloc);
1474
+
1475
+ // Set up the datastructure used to collect the uses of the allocation.
1476
+ SmallVector<PMOMemoryUse, 16 > uses;
1477
+ SmallVector<SILInstruction *, 4 > destroys;
1478
+
1479
+ // Walk the use list of the pointer, collecting them. If we are not able
1480
+ // to optimize, skip this value. *NOTE* We may still scalarize values
1481
+ // inside the value.
1482
+ if (!collectPMOElementUsesFrom (memInfo, uses, destroys)) {
1483
+ ++i;
1484
+ continue ;
1485
+ }
1486
+
1487
+ AllocOptimize allocOptimize (alloc, uses, destroys);
1488
+ changed |= allocOptimize.tryToRemoveDeadAllocation ();
1489
+
1490
+ // Move onto the next instruction. We know this is safe since we do not
1491
+ // eliminate allocations here.
1492
+ ++i;
1493
+ if (alloc->use_empty ()) {
1494
+ alloc->eraseFromParent ();
1441
1495
++NumAllocRemoved;
1442
- Changed = true ;
1496
+ changed = true ;
1443
1497
}
1444
1498
}
1445
1499
}
1446
- return Changed;
1500
+
1501
+ return changed;
1447
1502
}
1448
1503
1449
1504
namespace {
1450
1505
1451
- class PredictableMemoryOptimizations : public SILFunctionTransform {
1506
+ class PredictableMemoryAccessOptimizations : public SILFunctionTransform {
1452
1507
// / The entry point to the transformation.
1453
1508
// /
1454
1509
// / FIXME: This pass should not need to rerun on deserialized
@@ -1457,14 +1512,25 @@ class PredictableMemoryOptimizations : public SILFunctionTransform {
1457
1512
// / either indicates that this pass missing some opportunities the first time,
1458
1513
// / or has a pass order dependency on other early passes.
1459
1514
void run () override {
1460
- if (optimizeMemoryAllocations (*getFunction ()))
1515
+ // TODO: Can we invalidate here just instructions?
1516
+ if (optimizeMemoryAccesses (*getFunction ()))
1517
+ invalidateAnalysis (SILAnalysis::InvalidationKind::FunctionBody);
1518
+ }
1519
+ };
1520
+
1521
+ class PredictableDeadAllocationElimination : public SILFunctionTransform {
1522
+ void run () override {
1523
+ if (eliminateDeadAllocations (*getFunction ()))
1461
1524
invalidateAnalysis (SILAnalysis::InvalidationKind::FunctionBody);
1462
1525
}
1463
1526
};
1464
1527
1465
1528
} // end anonymous namespace
1466
1529
1530
+ SILTransform *swift::createPredictableMemoryAccessOptimizations () {
1531
+ return new PredictableMemoryAccessOptimizations ();
1532
+ }
1467
1533
1468
- SILTransform *swift::createPredictableMemoryOptimizations () {
1469
- return new PredictableMemoryOptimizations ();
1534
+ SILTransform *swift::createPredictableDeadAllocationElimination () {
1535
+ return new PredictableDeadAllocationElimination ();
1470
1536
}
0 commit comments