|
84 | 84 | #include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
85 | 85 | #include "llvm/Transforms/Utils/Local.h"
|
86 | 86 | #include "llvm/Transforms/Utils/PromoteMemToReg.h"
|
| 87 | +#include "llvm/Transforms/Utils/SSAUpdater.h" |
87 | 88 | #include <algorithm>
|
88 | 89 | #include <cassert>
|
89 | 90 | #include <cstddef>
|
@@ -1401,9 +1402,8 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
|
1401 | 1402 | Function *Callee = CB.getCalledFunction();
|
1402 | 1403 | if (Callee && CB.arg_size() == Callee->arg_size() &&
|
1403 | 1404 | !CB.hasOperandBundles() && all_of(enumerate(CB.args()), [&](auto V) {
|
1404 |
| - return V.value() != *U || |
1405 |
| - (Callee->getArg(V.index())->hasNoCaptureAttr() && |
1406 |
| - Callee->getArg(V.index())->onlyReadsMemory()); |
| 1405 | + return V.value() != *U || (CB.doesNotCapture(V.index()) && |
| 1406 | + CB.onlyReadsMemory(V.index())); |
1407 | 1407 | })) {
|
1408 | 1408 | PI.setEscapedReadOnly(&CB);
|
1409 | 1409 | return;
|
@@ -5479,51 +5479,71 @@ void SROA::clobberUse(Use &U) {
|
5479 | 5479 | }
|
5480 | 5480 | }
|
5481 | 5481 |
|
5482 |
| -bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) { |
5483 |
| - for (auto &P : AS.partitions()) { |
5484 |
| - StoreInst *Store = nullptr; |
5485 |
| - // Make sure all the slices inside the partition are the full width. |
5486 |
| - if (any_of(P, [&P](Slice &S) { |
5487 |
| - return S.beginOffset() != P.beginOffset() || |
5488 |
| - S.beginOffset() != P.beginOffset(); |
5489 |
| - })) |
5490 |
| - continue; |
| 5482 | +// A basic LoadAndStorePromoter that does not remove store nodes. |
| 5483 | +class BasicLoadAndStorePromoter : public LoadAndStorePromoter { |
| 5484 | +public: |
| 5485 | + BasicLoadAndStorePromoter(ArrayRef<const Instruction *> Insts, SSAUpdater &S) |
| 5486 | + : LoadAndStorePromoter(Insts, S) {} |
| 5487 | + bool shouldDelete(Instruction *I) const override { |
| 5488 | + return !isa<StoreInst>(I); |
| 5489 | + } |
| 5490 | +}; |
5491 | 5491 |
|
5492 |
| - // Check there is a single store and nothing else other than loads. |
5493 |
| - for (Slice &S : P) { |
5494 |
| - if (S.isDead()) |
5495 |
| - continue; |
5496 |
| - if (auto *St = dyn_cast<StoreInst>(S.getUse()->getUser())) { |
5497 |
| - if (Store) { |
5498 |
| - Store = nullptr; |
5499 |
| - break; |
5500 |
| - } |
5501 |
| - Store = St; |
5502 |
| - } else if (!isa<LoadInst>(S.getUse()->getUser()) && |
5503 |
| - !isAssumeLikeIntrinsic( |
5504 |
| - cast<Instruction>(S.getUse()->getUser()))) { |
5505 |
| - Store = nullptr; |
5506 |
| - break; |
| 5492 | +bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) { |
| 5493 | + // Look through each "partition", looking for slices with the same start/end |
| 5494 | + // that do not overlap with any before them. The slices are sorted by |
| 5495 | + // increasing beginOffset. We don't use AS.partitions(), as it will use a more |
| 5496 | + // sophisticated algorithm that takes splittable slices into account. |
| 5497 | + auto PartitionBegin = AS.begin(); |
| 5498 | + auto PartitionEnd = PartitionBegin; |
| 5499 | + uint64_t BeginOffset = PartitionBegin->beginOffset(); |
| 5500 | + uint64_t EndOffset = PartitionBegin->endOffset(); |
| 5501 | + while (PartitionBegin != AS.end()) { |
| 5502 | + bool AllSameAndValid = true; |
| 5503 | + SmallVector<Instruction *> Insts; |
| 5504 | + Type *PartitionType = nullptr; |
| 5505 | + while (PartitionEnd != AS.end() && |
| 5506 | + (PartitionEnd->beginOffset() < EndOffset || |
| 5507 | + PartitionEnd->endOffset() <= EndOffset)) { |
| 5508 | + EndOffset = std::max(EndOffset, PartitionEnd->endOffset()); |
| 5509 | + if (AllSameAndValid) { |
| 5510 | + AllSameAndValid &= PartitionEnd->beginOffset() == BeginOffset && |
| 5511 | + PartitionEnd->endOffset() == EndOffset; |
| 5512 | + Instruction *User = |
| 5513 | + cast<Instruction>(PartitionEnd->getUse()->getUser()); |
| 5514 | + if (isa<LoadInst>(User) || isa<StoreInst>(User)) { |
| 5515 | + // LoadAndStorePromoter requires all the types are the same. |
| 5516 | + Type *UserTy = getLoadStoreType(User); |
| 5517 | + if (PartitionType && UserTy != PartitionType) |
| 5518 | + AllSameAndValid = false; |
| 5519 | + PartitionType = UserTy; |
| 5520 | + Insts.push_back(User); |
| 5521 | + } else if (!isAssumeLikeIntrinsic(User)) |
| 5522 | + AllSameAndValid = false; |
5507 | 5523 | }
|
| 5524 | + ++PartitionEnd; |
5508 | 5525 | }
|
5509 | 5526 |
|
5510 |
| - if (!Store) |
5511 |
| - continue; |
5512 |
| - |
5513 |
| - // Replace loads by the value that was stored. |
5514 |
| - for (Slice &S : P) { |
5515 |
| - if (auto *Ld = dyn_cast<LoadInst>(S.getUse()->getUser())) { |
5516 |
| - if (DTU->getDomTree().dominates(Store, Ld)) { |
5517 |
| - if (Store->getValueOperand()->getType() == Ld->getType()) { |
5518 |
| - LLVM_DEBUG(dbgs() << " Replacing " << *Ld << " with " |
5519 |
| - << *Store->getValueOperand() << "\n"); |
5520 |
| - Ld->replaceAllUsesWith(Store->getValueOperand()); |
5521 |
| - } |
5522 |
| - } |
5523 |
| - } |
| 5527 | + // So long as all the slices start and end offsets matched, update loads to |
| 5528 | + // the values stored in the partition. |
| 5529 | + if (AllSameAndValid && !Insts.empty()) { |
| 5530 | + LLVM_DEBUG(dbgs() << "Propagate values on slice [" << BeginOffset << ", " |
| 5531 | + << EndOffset << ")\n"); |
| 5532 | + SmallVector<PHINode *, 4> NewPHIs; |
| 5533 | + SSAUpdater SSA(&NewPHIs); |
| 5534 | + BasicLoadAndStorePromoter Promoter(Insts, SSA); |
| 5535 | + // Add a zero value at the point of the alloca, to prevent the SSA updater |
| 5536 | + // replacing loads with poison which would not be valid for padded loads. |
| 5537 | + SSA.AddAvailableValue(AI.getParent(), |
| 5538 | + Constant::getNullValue(PartitionType)); |
| 5539 | + Promoter.run(Insts); |
5524 | 5540 | }
|
5525 |
| - } |
5526 | 5541 |
|
| 5542 | + // Step on to the next partition. |
| 5543 | + PartitionBegin = PartitionEnd; |
| 5544 | + BeginOffset = PartitionBegin->beginOffset(); |
| 5545 | + EndOffset = PartitionBegin->endOffset(); |
| 5546 | + } |
5527 | 5547 | return true;
|
5528 | 5548 | }
|
5529 | 5549 |
|
|
0 commit comments