File indexing completed on 2026-05-10 08:43:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 #ifndef LLVM_ANALYSIS_MEMORYSSA_H
0086 #define LLVM_ANALYSIS_MEMORYSSA_H
0087
0088 #include "llvm/ADT/DenseMap.h"
0089 #include "llvm/ADT/SmallPtrSet.h"
0090 #include "llvm/ADT/SmallVector.h"
0091 #include "llvm/ADT/ilist_node.h"
0092 #include "llvm/ADT/iterator_range.h"
0093 #include "llvm/Analysis/AliasAnalysis.h"
0094 #include "llvm/Analysis/MemoryLocation.h"
0095 #include "llvm/Analysis/PHITransAddr.h"
0096 #include "llvm/IR/DerivedUser.h"
0097 #include "llvm/IR/Dominators.h"
0098 #include "llvm/IR/Type.h"
0099 #include "llvm/IR/User.h"
0100 #include "llvm/Pass.h"
0101 #include <algorithm>
0102 #include <cassert>
0103 #include <cstddef>
0104 #include <iterator>
0105 #include <memory>
0106 #include <utility>
0107
0108 namespace llvm {
0109
0110 template <class GraphType> struct GraphTraits;
0111 class Function;
0112 class Loop;
0113 class LLVMContext;
0114 class MemoryAccess;
0115 class MemorySSAWalker;
0116 class Module;
0117 class raw_ostream;
0118
0119 namespace MSSAHelpers {
0120
0121 struct AllAccessTag {};
0122 struct DefsOnlyTag {};
0123
0124 }
0125
0126 enum : unsigned {
0127
0128
0129 INVALID_MEMORYACCESS_ID = -1U
0130 };
0131
0132 template <class T> class memoryaccess_def_iterator_base;
0133 using memoryaccess_def_iterator = memoryaccess_def_iterator_base<MemoryAccess>;
0134 using const_memoryaccess_def_iterator =
0135 memoryaccess_def_iterator_base<const MemoryAccess>;
0136
0137
0138
0139 class MemoryAccess
0140 : public DerivedUser,
0141 public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>,
0142 public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>> {
0143 public:
0144 using AllAccessType =
0145 ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>;
0146 using DefsOnlyType =
0147 ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>;
0148
0149 MemoryAccess(const MemoryAccess &) = delete;
0150 MemoryAccess &operator=(const MemoryAccess &) = delete;
0151
0152 void *operator new(size_t) = delete;
0153
0154
0155
0156 static bool classof(const Value *V) {
0157 unsigned ID = V->getValueID();
0158 return ID == MemoryUseVal || ID == MemoryPhiVal || ID == MemoryDefVal;
0159 }
0160
0161 BasicBlock *getBlock() const { return Block; }
0162
0163 void print(raw_ostream &OS) const;
0164 void dump() const;
0165
0166
0167 using iterator = user_iterator;
0168 using const_iterator = const_user_iterator;
0169
0170
0171
0172
0173 memoryaccess_def_iterator defs_begin();
0174 const_memoryaccess_def_iterator defs_begin() const;
0175 memoryaccess_def_iterator defs_end();
0176 const_memoryaccess_def_iterator defs_end() const;
0177
0178
0179
0180 AllAccessType::self_iterator getIterator() {
0181 return this->AllAccessType::getIterator();
0182 }
0183 AllAccessType::const_self_iterator getIterator() const {
0184 return this->AllAccessType::getIterator();
0185 }
0186 AllAccessType::reverse_self_iterator getReverseIterator() {
0187 return this->AllAccessType::getReverseIterator();
0188 }
0189 AllAccessType::const_reverse_self_iterator getReverseIterator() const {
0190 return this->AllAccessType::getReverseIterator();
0191 }
0192 DefsOnlyType::self_iterator getDefsIterator() {
0193 return this->DefsOnlyType::getIterator();
0194 }
0195 DefsOnlyType::const_self_iterator getDefsIterator() const {
0196 return this->DefsOnlyType::getIterator();
0197 }
0198 DefsOnlyType::reverse_self_iterator getReverseDefsIterator() {
0199 return this->DefsOnlyType::getReverseIterator();
0200 }
0201 DefsOnlyType::const_reverse_self_iterator getReverseDefsIterator() const {
0202 return this->DefsOnlyType::getReverseIterator();
0203 }
0204
0205 protected:
0206 friend class MemoryDef;
0207 friend class MemoryPhi;
0208 friend class MemorySSA;
0209 friend class MemoryUse;
0210 friend class MemoryUseOrDef;
0211
0212
0213
0214 void setBlock(BasicBlock *BB) { Block = BB; }
0215
0216
0217
0218 inline unsigned getID() const;
0219
0220 MemoryAccess(LLVMContext &C, unsigned Vty, DeleteValueTy DeleteValue,
0221 BasicBlock *BB, AllocInfo AllocInfo)
0222 : DerivedUser(Type::getVoidTy(C), Vty, AllocInfo, DeleteValue),
0223 Block(BB) {}
0224
0225
0226 ~MemoryAccess() = default;
0227
0228 private:
0229 BasicBlock *Block;
0230 };
0231
0232 template <>
0233 struct ilist_alloc_traits<MemoryAccess> {
0234 static void deleteNode(MemoryAccess *MA) { MA->deleteValue(); }
0235 };
0236
0237 inline raw_ostream &operator<<(raw_ostream &OS, const MemoryAccess &MA) {
0238 MA.print(OS);
0239 return OS;
0240 }
0241
0242
0243
0244
0245
0246
0247
0248
0249 class MemoryUseOrDef : public MemoryAccess {
0250 public:
0251 void *operator new(size_t) = delete;
0252
0253 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
0254
0255
0256 Instruction *getMemoryInst() const { return MemoryInstruction; }
0257
0258
0259 MemoryAccess *getDefiningAccess() const { return getOperand(0); }
0260
0261 static bool classof(const Value *MA) {
0262 return MA->getValueID() == MemoryUseVal || MA->getValueID() == MemoryDefVal;
0263 }
0264
0265
0266 inline bool isOptimized() const;
0267
0268 inline MemoryAccess *getOptimized() const;
0269
0270 inline void setOptimized(MemoryAccess *);
0271
0272
0273
0274
0275 inline void resetOptimized();
0276
0277 protected:
0278 friend class MemorySSA;
0279 friend class MemorySSAUpdater;
0280
0281 MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
0282 DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB,
0283 AllocInfo AllocInfo)
0284 : MemoryAccess(C, Vty, DeleteValue, BB, AllocInfo),
0285 MemoryInstruction(MI) {
0286 setDefiningAccess(DMA);
0287 }
0288
0289
0290 ~MemoryUseOrDef() = default;
0291
0292 void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
0293 if (!Optimized) {
0294 setOperand(0, DMA);
0295 return;
0296 }
0297 setOptimized(DMA);
0298 }
0299
0300 private:
0301 Instruction *MemoryInstruction;
0302 };
0303
0304
0305
0306
0307
0308
0309 class MemoryUse final : public MemoryUseOrDef {
0310 constexpr static IntrusiveOperandsAllocMarker AllocMarker{1};
0311
0312 public:
0313 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
0314
0315 MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
0316 : MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB, AllocMarker) {}
0317
0318
0319 void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
0320 void operator delete(void *Ptr) { User::operator delete(Ptr); }
0321
0322 static bool classof(const Value *MA) {
0323 return MA->getValueID() == MemoryUseVal;
0324 }
0325
0326 void print(raw_ostream &OS) const;
0327
0328 void setOptimized(MemoryAccess *DMA) {
0329 OptimizedID = DMA->getID();
0330 setOperand(0, DMA);
0331 }
0332
0333
0334
0335
0336 bool isOptimized() const {
0337 return getDefiningAccess() && OptimizedID == getDefiningAccess()->getID();
0338 }
0339
0340 MemoryAccess *getOptimized() const {
0341 return getDefiningAccess();
0342 }
0343
0344 void resetOptimized() {
0345 OptimizedID = INVALID_MEMORYACCESS_ID;
0346 }
0347
0348 protected:
0349 friend class MemorySSA;
0350
0351 private:
0352 static void deleteMe(DerivedUser *Self);
0353
0354 unsigned OptimizedID = INVALID_MEMORYACCESS_ID;
0355 };
0356
0357 template <>
0358 struct OperandTraits<MemoryUse> : public FixedNumOperandTraits<MemoryUse, 1> {};
0359 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUse, MemoryAccess)
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370 class MemoryDef final : public MemoryUseOrDef {
0371 constexpr static IntrusiveOperandsAllocMarker AllocMarker{2};
0372
0373 public:
0374 friend class MemorySSA;
0375
0376 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
0377
0378 MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
0379 unsigned Ver)
0380 : MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB, AllocMarker),
0381 ID(Ver) {}
0382
0383
0384 void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
0385 void operator delete(void *Ptr) { User::operator delete(Ptr); }
0386
0387 static bool classof(const Value *MA) {
0388 return MA->getValueID() == MemoryDefVal;
0389 }
0390
0391 void setOptimized(MemoryAccess *MA) {
0392 setOperand(1, MA);
0393 OptimizedID = MA->getID();
0394 }
0395
0396 MemoryAccess *getOptimized() const {
0397 return cast_or_null<MemoryAccess>(getOperand(1));
0398 }
0399
0400 bool isOptimized() const {
0401 return getOptimized() && OptimizedID == getOptimized()->getID();
0402 }
0403
0404 void resetOptimized() {
0405 OptimizedID = INVALID_MEMORYACCESS_ID;
0406 setOperand(1, nullptr);
0407 }
0408
0409 void print(raw_ostream &OS) const;
0410
0411 unsigned getID() const { return ID; }
0412
0413 private:
0414 static void deleteMe(DerivedUser *Self);
0415
0416 const unsigned ID;
0417 unsigned OptimizedID = INVALID_MEMORYACCESS_ID;
0418 };
0419
0420 template <>
0421 struct OperandTraits<MemoryDef> : public FixedNumOperandTraits<MemoryDef, 2> {};
0422 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryDef, MemoryAccess)
0423
0424 template <>
0425 struct OperandTraits<MemoryUseOrDef> {
0426 static Use *op_begin(MemoryUseOrDef *MUD) {
0427 if (auto *MU = dyn_cast<MemoryUse>(MUD))
0428 return OperandTraits<MemoryUse>::op_begin(MU);
0429 return OperandTraits<MemoryDef>::op_begin(cast<MemoryDef>(MUD));
0430 }
0431
0432 static Use *op_end(MemoryUseOrDef *MUD) {
0433 if (auto *MU = dyn_cast<MemoryUse>(MUD))
0434 return OperandTraits<MemoryUse>::op_end(MU);
0435 return OperandTraits<MemoryDef>::op_end(cast<MemoryDef>(MUD));
0436 }
0437
0438 static unsigned operands(const MemoryUseOrDef *MUD) {
0439 if (const auto *MU = dyn_cast<MemoryUse>(MUD))
0440 return OperandTraits<MemoryUse>::operands(MU);
0441 return OperandTraits<MemoryDef>::operands(cast<MemoryDef>(MUD));
0442 }
0443 };
0444 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess)
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478 class MemoryPhi final : public MemoryAccess {
0479 constexpr static HungOffOperandsAllocMarker AllocMarker{};
0480
0481
0482 void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
0483
0484 public:
0485 void operator delete(void *Ptr) { User::operator delete(Ptr); }
0486
0487
0488 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
0489
0490 MemoryPhi(LLVMContext &C, BasicBlock *BB, unsigned Ver, unsigned NumPreds = 0)
0491 : MemoryAccess(C, MemoryPhiVal, deleteMe, BB, AllocMarker), ID(Ver),
0492 ReservedSpace(NumPreds) {
0493 allocHungoffUses(ReservedSpace);
0494 }
0495
0496
0497
0498 using block_iterator = BasicBlock **;
0499 using const_block_iterator = BasicBlock *const *;
0500
0501 block_iterator block_begin() {
0502 return reinterpret_cast<block_iterator>(op_begin() + ReservedSpace);
0503 }
0504
0505 const_block_iterator block_begin() const {
0506 return reinterpret_cast<const_block_iterator>(op_begin() + ReservedSpace);
0507 }
0508
0509 block_iterator block_end() { return block_begin() + getNumOperands(); }
0510
0511 const_block_iterator block_end() const {
0512 return block_begin() + getNumOperands();
0513 }
0514
0515 iterator_range<block_iterator> blocks() {
0516 return make_range(block_begin(), block_end());
0517 }
0518
0519 iterator_range<const_block_iterator> blocks() const {
0520 return make_range(block_begin(), block_end());
0521 }
0522
0523 op_range incoming_values() { return operands(); }
0524
0525 const_op_range incoming_values() const { return operands(); }
0526
0527
0528 unsigned getNumIncomingValues() const { return getNumOperands(); }
0529
0530
0531 MemoryAccess *getIncomingValue(unsigned I) const { return getOperand(I); }
0532 void setIncomingValue(unsigned I, MemoryAccess *V) {
0533 assert(V && "PHI node got a null value!");
0534 setOperand(I, V);
0535 }
0536
0537 static unsigned getOperandNumForIncomingValue(unsigned I) { return I; }
0538 static unsigned getIncomingValueNumForOperand(unsigned I) { return I; }
0539
0540
0541 BasicBlock *getIncomingBlock(unsigned I) const { return block_begin()[I]; }
0542
0543
0544
0545 BasicBlock *getIncomingBlock(const Use &U) const {
0546 assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?");
0547 return getIncomingBlock(unsigned(&U - op_begin()));
0548 }
0549
0550
0551
0552 BasicBlock *getIncomingBlock(MemoryAccess::const_user_iterator I) const {
0553 return getIncomingBlock(I.getUse());
0554 }
0555
0556 void setIncomingBlock(unsigned I, BasicBlock *BB) {
0557 assert(BB && "PHI node got a null basic block!");
0558 block_begin()[I] = BB;
0559 }
0560
0561
0562 void addIncoming(MemoryAccess *V, BasicBlock *BB) {
0563 if (getNumOperands() == ReservedSpace)
0564 growOperands();
0565
0566 setNumHungOffUseOperands(getNumOperands() + 1);
0567 setIncomingValue(getNumOperands() - 1, V);
0568 setIncomingBlock(getNumOperands() - 1, BB);
0569 }
0570
0571
0572
0573 int getBasicBlockIndex(const BasicBlock *BB) const {
0574 for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
0575 if (block_begin()[I] == BB)
0576 return I;
0577 return -1;
0578 }
0579
0580 MemoryAccess *getIncomingValueForBlock(const BasicBlock *BB) const {
0581 int Idx = getBasicBlockIndex(BB);
0582 assert(Idx >= 0 && "Invalid basic block argument!");
0583 return getIncomingValue(Idx);
0584 }
0585
0586
0587 void unorderedDeleteIncoming(unsigned I) {
0588 unsigned E = getNumOperands();
0589 assert(I < E && "Cannot remove out of bounds Phi entry.");
0590
0591
0592 assert(E >= 2 && "Cannot only remove incoming values in MemoryPhis with "
0593 "at least 2 values.");
0594 setIncomingValue(I, getIncomingValue(E - 1));
0595 setIncomingBlock(I, block_begin()[E - 1]);
0596 setOperand(E - 1, nullptr);
0597 block_begin()[E - 1] = nullptr;
0598 setNumHungOffUseOperands(getNumOperands() - 1);
0599 }
0600
0601
0602
0603 template <typename Fn> void unorderedDeleteIncomingIf(Fn &&Pred) {
0604 for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
0605 if (Pred(getIncomingValue(I), getIncomingBlock(I))) {
0606 unorderedDeleteIncoming(I);
0607 E = getNumOperands();
0608 --I;
0609 }
0610 assert(getNumOperands() >= 1 &&
0611 "Cannot remove all incoming blocks in a MemoryPhi.");
0612 }
0613
0614
0615 void unorderedDeleteIncomingBlock(const BasicBlock *BB) {
0616 unorderedDeleteIncomingIf(
0617 [&](const MemoryAccess *, const BasicBlock *B) { return BB == B; });
0618 }
0619
0620
0621
0622 void unorderedDeleteIncomingValue(const MemoryAccess *MA) {
0623 unorderedDeleteIncomingIf(
0624 [&](const MemoryAccess *M, const BasicBlock *) { return MA == M; });
0625 }
0626
0627 static bool classof(const Value *V) {
0628 return V->getValueID() == MemoryPhiVal;
0629 }
0630
0631 void print(raw_ostream &OS) const;
0632
0633 unsigned getID() const { return ID; }
0634
0635 protected:
0636 friend class MemorySSA;
0637
0638
0639
0640
0641 void allocHungoffUses(unsigned N) {
0642 User::allocHungoffUses(N, true);
0643 }
0644
0645 private:
0646
0647 const unsigned ID;
0648 unsigned ReservedSpace;
0649
0650
0651
0652 void growOperands() {
0653 unsigned E = getNumOperands();
0654
0655 ReservedSpace = std::max(E + E / 2, 2u);
0656 growHungoffUses(ReservedSpace, true);
0657 }
0658
0659 static void deleteMe(DerivedUser *Self);
0660 };
0661
0662 inline unsigned MemoryAccess::getID() const {
0663 assert((isa<MemoryDef>(this) || isa<MemoryPhi>(this)) &&
0664 "only memory defs and phis have ids");
0665 if (const auto *MD = dyn_cast<MemoryDef>(this))
0666 return MD->getID();
0667 return cast<MemoryPhi>(this)->getID();
0668 }
0669
0670 inline bool MemoryUseOrDef::isOptimized() const {
0671 if (const auto *MD = dyn_cast<MemoryDef>(this))
0672 return MD->isOptimized();
0673 return cast<MemoryUse>(this)->isOptimized();
0674 }
0675
0676 inline MemoryAccess *MemoryUseOrDef::getOptimized() const {
0677 if (const auto *MD = dyn_cast<MemoryDef>(this))
0678 return MD->getOptimized();
0679 return cast<MemoryUse>(this)->getOptimized();
0680 }
0681
0682 inline void MemoryUseOrDef::setOptimized(MemoryAccess *MA) {
0683 if (auto *MD = dyn_cast<MemoryDef>(this))
0684 MD->setOptimized(MA);
0685 else
0686 cast<MemoryUse>(this)->setOptimized(MA);
0687 }
0688
0689 inline void MemoryUseOrDef::resetOptimized() {
0690 if (auto *MD = dyn_cast<MemoryDef>(this))
0691 MD->resetOptimized();
0692 else
0693 cast<MemoryUse>(this)->resetOptimized();
0694 }
0695
0696 template <> struct OperandTraits<MemoryPhi> : public HungoffOperandTraits {};
0697 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess)
0698
0699
0700
0701 class MemorySSA {
0702 public:
0703 MemorySSA(Function &, AliasAnalysis *, DominatorTree *);
0704 MemorySSA(Loop &, AliasAnalysis *, DominatorTree *);
0705
0706
0707
0708 MemorySSA(MemorySSA &&) = delete;
0709
0710 ~MemorySSA();
0711
0712 MemorySSAWalker *getWalker();
0713 MemorySSAWalker *getSkipSelfWalker();
0714
0715
0716
0717
0718
0719 MemoryUseOrDef *getMemoryAccess(const Instruction *I) const {
0720 return cast_or_null<MemoryUseOrDef>(ValueToMemoryAccess.lookup(I));
0721 }
0722
0723 MemoryPhi *getMemoryAccess(const BasicBlock *BB) const {
0724 return cast_or_null<MemoryPhi>(ValueToMemoryAccess.lookup(cast<Value>(BB)));
0725 }
0726
0727 DominatorTree &getDomTree() const { return *DT; }
0728
0729 void dump() const;
0730 void print(raw_ostream &) const;
0731
0732
0733
0734
0735
0736
0737
0738
0739 inline bool isLiveOnEntryDef(const MemoryAccess *MA) const {
0740 return MA == LiveOnEntryDef.get();
0741 }
0742
0743 inline MemoryAccess *getLiveOnEntryDef() const {
0744 return LiveOnEntryDef.get();
0745 }
0746
0747
0748
0749
0750
0751
0752 using AccessList = iplist<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>;
0753 using DefsList =
0754 simple_ilist<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>;
0755
0756
0757
0758
0759 const AccessList *getBlockAccesses(const BasicBlock *BB) const {
0760 return getWritableBlockAccesses(BB);
0761 }
0762
0763
0764
0765
0766
0767 const DefsList *getBlockDefs(const BasicBlock *BB) const {
0768 return getWritableBlockDefs(BB);
0769 }
0770
0771
0772
0773 bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const;
0774
0775
0776
0777 bool dominates(const MemoryAccess *A, const MemoryAccess *B) const;
0778
0779
0780
0781 bool dominates(const MemoryAccess *A, const Use &B) const;
0782
0783 enum class VerificationLevel { Fast, Full };
0784
0785
0786 void verifyMemorySSA(VerificationLevel = VerificationLevel::Fast) const;
0787
0788
0789
0790 enum InsertionPlace { Beginning, End, BeforeTerminator };
0791
0792
0793
0794
0795
0796
0797 void ensureOptimizedUses();
0798
0799 AliasAnalysis &getAA() { return *AA; }
0800
0801 protected:
0802
0803 friend class MemorySSAUpdater;
0804
0805 template <typename IterT>
0806 void verifyOrderingDominationAndDefUses(
0807 IterT Blocks, VerificationLevel = VerificationLevel::Fast) const;
0808 template <typename IterT> void verifyDominationNumbers(IterT Blocks) const;
0809 template <typename IterT> void verifyPrevDefInPhis(IterT Blocks) const;
0810
0811
0812 AccessList *getWritableBlockAccesses(const BasicBlock *BB) const {
0813 auto It = PerBlockAccesses.find(BB);
0814 return It == PerBlockAccesses.end() ? nullptr : It->second.get();
0815 }
0816
0817
0818 DefsList *getWritableBlockDefs(const BasicBlock *BB) const {
0819 auto It = PerBlockDefs.find(BB);
0820 return It == PerBlockDefs.end() ? nullptr : It->second.get();
0821 }
0822
0823
0824
0825
0826
0827 void moveTo(MemoryUseOrDef *What, BasicBlock *BB, AccessList::iterator Where);
0828 void moveTo(MemoryAccess *What, BasicBlock *BB, InsertionPlace Point);
0829
0830
0831 void renamePass(BasicBlock *BB, MemoryAccess *IncomingVal,
0832 SmallPtrSetImpl<BasicBlock *> &Visited) {
0833 renamePass(DT->getNode(BB), IncomingVal, Visited, true, true);
0834 }
0835
0836 void removeFromLookups(MemoryAccess *);
0837 void removeFromLists(MemoryAccess *, bool ShouldDelete = true);
0838 void insertIntoListsForBlock(MemoryAccess *, const BasicBlock *,
0839 InsertionPlace);
0840 void insertIntoListsBefore(MemoryAccess *, const BasicBlock *,
0841 AccessList::iterator);
0842 MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *,
0843 const MemoryUseOrDef *Template = nullptr,
0844 bool CreationMustSucceed = true);
0845
0846 private:
0847 class ClobberWalkerBase;
0848 class CachingWalker;
0849 class SkipSelfWalker;
0850 class OptimizeUses;
0851
0852 CachingWalker *getWalkerImpl();
0853 template <typename IterT>
0854 void buildMemorySSA(BatchAAResults &BAA, IterT Blocks);
0855
0856 void prepareForMoveTo(MemoryAccess *, BasicBlock *);
0857 void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const;
0858
0859 using AccessMap = DenseMap<const BasicBlock *, std::unique_ptr<AccessList>>;
0860 using DefsMap = DenseMap<const BasicBlock *, std::unique_ptr<DefsList>>;
0861
0862 void markUnreachableAsLiveOnEntry(BasicBlock *BB);
0863 MemoryPhi *createMemoryPhi(BasicBlock *BB);
0864 template <typename AliasAnalysisType>
0865 MemoryUseOrDef *createNewAccess(Instruction *, AliasAnalysisType *,
0866 const MemoryUseOrDef *Template = nullptr);
0867 void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &);
0868 MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *, bool);
0869 void renameSuccessorPhis(BasicBlock *, MemoryAccess *, bool);
0870 void renamePass(DomTreeNode *, MemoryAccess *IncomingVal,
0871 SmallPtrSetImpl<BasicBlock *> &Visited,
0872 bool SkipVisited = false, bool RenameAllUses = false);
0873 AccessList *getOrCreateAccessList(const BasicBlock *);
0874 DefsList *getOrCreateDefsList(const BasicBlock *);
0875 void renumberBlock(const BasicBlock *) const;
0876 AliasAnalysis *AA = nullptr;
0877 DominatorTree *DT;
0878 Function *F = nullptr;
0879 Loop *L = nullptr;
0880
0881
0882 DenseMap<const Value *, MemoryAccess *> ValueToMemoryAccess;
0883
0884
0885
0886
0887
0888
0889
0890 AccessMap PerBlockAccesses;
0891 DefsMap PerBlockDefs;
0892 std::unique_ptr<MemoryAccess, ValueDeleter> LiveOnEntryDef;
0893
0894
0895
0896
0897 mutable SmallPtrSet<const BasicBlock *, 16> BlockNumberingValid;
0898 mutable DenseMap<const MemoryAccess *, unsigned long> BlockNumbering;
0899
0900
0901 std::unique_ptr<ClobberWalkerBase> WalkerBase;
0902 std::unique_ptr<CachingWalker> Walker;
0903 std::unique_ptr<SkipSelfWalker> SkipWalker;
0904 unsigned NextID = 0;
0905 bool IsOptimized = false;
0906 };
0907
0908
0909
0910
0911
0912
0913 extern bool VerifyMemorySSA;
0914
0915
0916 class MemorySSAUtil {
0917 protected:
0918 friend class GVNHoist;
0919 friend class MemorySSAWalker;
0920
0921
0922 static bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
0923 AliasAnalysis &AA);
0924 };
0925
0926
0927
0928 class MemorySSAAnalysis : public AnalysisInfoMixin<MemorySSAAnalysis> {
0929 friend AnalysisInfoMixin<MemorySSAAnalysis>;
0930
0931 static AnalysisKey Key;
0932
0933 public:
0934
0935
0936
0937 struct Result {
0938 Result(std::unique_ptr<MemorySSA> &&MSSA) : MSSA(std::move(MSSA)) {}
0939
0940 MemorySSA &getMSSA() { return *MSSA; }
0941
0942 std::unique_ptr<MemorySSA> MSSA;
0943
0944 bool invalidate(Function &F, const PreservedAnalyses &PA,
0945 FunctionAnalysisManager::Invalidator &Inv);
0946 };
0947
0948 Result run(Function &F, FunctionAnalysisManager &AM);
0949 };
0950
0951
0952 class MemorySSAPrinterPass : public PassInfoMixin<MemorySSAPrinterPass> {
0953 raw_ostream &OS;
0954 bool EnsureOptimizedUses;
0955
0956 public:
0957 explicit MemorySSAPrinterPass(raw_ostream &OS, bool EnsureOptimizedUses)
0958 : OS(OS), EnsureOptimizedUses(EnsureOptimizedUses) {}
0959
0960 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0961
0962 static bool isRequired() { return true; }
0963 };
0964
0965
0966 class MemorySSAWalkerPrinterPass
0967 : public PassInfoMixin<MemorySSAWalkerPrinterPass> {
0968 raw_ostream &OS;
0969
0970 public:
0971 explicit MemorySSAWalkerPrinterPass(raw_ostream &OS) : OS(OS) {}
0972
0973 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0974
0975 static bool isRequired() { return true; }
0976 };
0977
0978
0979 struct MemorySSAVerifierPass : PassInfoMixin<MemorySSAVerifierPass> {
0980 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0981 static bool isRequired() { return true; }
0982 };
0983
0984
0985 class MemorySSAWrapperPass : public FunctionPass {
0986 public:
0987 MemorySSAWrapperPass();
0988
0989 static char ID;
0990
0991 bool runOnFunction(Function &) override;
0992 void releaseMemory() override;
0993 MemorySSA &getMSSA() { return *MSSA; }
0994 const MemorySSA &getMSSA() const { return *MSSA; }
0995
0996 void getAnalysisUsage(AnalysisUsage &AU) const override;
0997
0998 void verifyAnalysis() const override;
0999 void print(raw_ostream &OS, const Module *M = nullptr) const override;
1000
1001 private:
1002 std::unique_ptr<MemorySSA> MSSA;
1003 };
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 class MemorySSAWalker {
1017 public:
1018 MemorySSAWalker(MemorySSA *);
1019 virtual ~MemorySSAWalker() = default;
1020
1021 using MemoryAccessSet = SmallVector<MemoryAccess *, 8>;
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045 MemoryAccess *getClobberingMemoryAccess(const Instruction *I,
1046 BatchAAResults &AA) {
1047 MemoryAccess *MA = MSSA->getMemoryAccess(I);
1048 assert(MA && "Handed an instruction that MemorySSA doesn't recognize?");
1049 return getClobberingMemoryAccess(MA, AA);
1050 }
1051
1052
1053
1054 virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
1055 BatchAAResults &AA) = 0;
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068 virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
1069 const MemoryLocation &,
1070 BatchAAResults &AA) = 0;
1071
1072 MemoryAccess *getClobberingMemoryAccess(const Instruction *I) {
1073 BatchAAResults BAA(MSSA->getAA());
1074 return getClobberingMemoryAccess(I, BAA);
1075 }
1076
1077 MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA) {
1078 BatchAAResults BAA(MSSA->getAA());
1079 return getClobberingMemoryAccess(MA, BAA);
1080 }
1081
1082 MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA,
1083 const MemoryLocation &Loc) {
1084 BatchAAResults BAA(MSSA->getAA());
1085 return getClobberingMemoryAccess(MA, Loc, BAA);
1086 }
1087
1088
1089
1090
1091
1092
1093 virtual void invalidateInfo(MemoryAccess *) {}
1094
1095 protected:
1096 friend class MemorySSA;
1097
1098 MemorySSA *MSSA;
1099 };
1100
1101
1102
1103 class DoNothingMemorySSAWalker final : public MemorySSAWalker {
1104 public:
1105
1106
1107 using MemorySSAWalker::getClobberingMemoryAccess;
1108
1109 MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
1110 BatchAAResults &) override;
1111 MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
1112 const MemoryLocation &,
1113 BatchAAResults &) override;
1114 };
1115
1116 using MemoryAccessPair = std::pair<MemoryAccess *, MemoryLocation>;
1117 using ConstMemoryAccessPair = std::pair<const MemoryAccess *, MemoryLocation>;
1118
1119
1120
1121 template <class T>
1122 class memoryaccess_def_iterator_base
1123 : public iterator_facade_base<memoryaccess_def_iterator_base<T>,
1124 std::forward_iterator_tag, T, ptrdiff_t, T *,
1125 T *> {
1126 using BaseT = typename memoryaccess_def_iterator_base::iterator_facade_base;
1127
1128 public:
1129 memoryaccess_def_iterator_base(T *Start) : Access(Start) {}
1130 memoryaccess_def_iterator_base() = default;
1131
1132 bool operator==(const memoryaccess_def_iterator_base &Other) const {
1133 return Access == Other.Access && (!Access || ArgNo == Other.ArgNo);
1134 }
1135
1136
1137
1138
1139
1140
1141
1142 BasicBlock *getPhiArgBlock() const {
1143 MemoryPhi *MP = dyn_cast<MemoryPhi>(Access);
1144 assert(MP && "Tried to get phi arg block when not iterating over a PHI");
1145 return MP->getIncomingBlock(ArgNo);
1146 }
1147
1148 typename std::iterator_traits<BaseT>::pointer operator*() const {
1149 assert(Access && "Tried to access past the end of our iterator");
1150
1151
1152 if (const MemoryPhi *MP = dyn_cast<MemoryPhi>(Access))
1153 return MP->getIncomingValue(ArgNo);
1154 return cast<MemoryUseOrDef>(Access)->getDefiningAccess();
1155 }
1156
1157 using BaseT::operator++;
1158 memoryaccess_def_iterator_base &operator++() {
1159 assert(Access && "Hit end of iterator");
1160 if (const MemoryPhi *MP = dyn_cast<MemoryPhi>(Access)) {
1161 if (++ArgNo >= MP->getNumIncomingValues()) {
1162 ArgNo = 0;
1163 Access = nullptr;
1164 }
1165 } else {
1166 Access = nullptr;
1167 }
1168 return *this;
1169 }
1170
1171 private:
1172 T *Access = nullptr;
1173 unsigned ArgNo = 0;
1174 };
1175
1176 inline memoryaccess_def_iterator MemoryAccess::defs_begin() {
1177 return memoryaccess_def_iterator(this);
1178 }
1179
1180 inline const_memoryaccess_def_iterator MemoryAccess::defs_begin() const {
1181 return const_memoryaccess_def_iterator(this);
1182 }
1183
1184 inline memoryaccess_def_iterator MemoryAccess::defs_end() {
1185 return memoryaccess_def_iterator();
1186 }
1187
1188 inline const_memoryaccess_def_iterator MemoryAccess::defs_end() const {
1189 return const_memoryaccess_def_iterator();
1190 }
1191
1192
1193
1194 template <> struct GraphTraits<MemoryAccess *> {
1195 using NodeRef = MemoryAccess *;
1196 using ChildIteratorType = memoryaccess_def_iterator;
1197
1198 static NodeRef getEntryNode(NodeRef N) { return N; }
1199 static ChildIteratorType child_begin(NodeRef N) { return N->defs_begin(); }
1200 static ChildIteratorType child_end(NodeRef N) { return N->defs_end(); }
1201 };
1202
1203 template <> struct GraphTraits<Inverse<MemoryAccess *>> {
1204 using NodeRef = MemoryAccess *;
1205 using ChildIteratorType = MemoryAccess::iterator;
1206
1207 static NodeRef getEntryNode(NodeRef N) { return N; }
1208 static ChildIteratorType child_begin(NodeRef N) { return N->user_begin(); }
1209 static ChildIteratorType child_end(NodeRef N) { return N->user_end(); }
1210 };
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220 class upward_defs_iterator
1221 : public iterator_facade_base<upward_defs_iterator,
1222 std::forward_iterator_tag,
1223 const MemoryAccessPair> {
1224 using BaseT = upward_defs_iterator::iterator_facade_base;
1225
1226 public:
1227 upward_defs_iterator(const MemoryAccessPair &Info, DominatorTree *DT)
1228 : DefIterator(Info.first), Location(Info.second),
1229 OriginalAccess(Info.first), DT(DT) {
1230 CurrentPair.first = nullptr;
1231
1232 WalkingPhi = Info.first && isa<MemoryPhi>(Info.first);
1233 fillInCurrentPair();
1234 }
1235
1236 upward_defs_iterator() { CurrentPair.first = nullptr; }
1237
1238 bool operator==(const upward_defs_iterator &Other) const {
1239 return DefIterator == Other.DefIterator;
1240 }
1241
1242 typename std::iterator_traits<BaseT>::reference operator*() const {
1243 assert(DefIterator != OriginalAccess->defs_end() &&
1244 "Tried to access past the end of our iterator");
1245 return CurrentPair;
1246 }
1247
1248 using BaseT::operator++;
1249 upward_defs_iterator &operator++() {
1250 assert(DefIterator != OriginalAccess->defs_end() &&
1251 "Tried to access past the end of the iterator");
1252 ++DefIterator;
1253 if (DefIterator != OriginalAccess->defs_end())
1254 fillInCurrentPair();
1255 return *this;
1256 }
1257
1258 BasicBlock *getPhiArgBlock() const { return DefIterator.getPhiArgBlock(); }
1259
1260 private:
1261
1262
1263
1264 bool IsGuaranteedLoopInvariant(const Value *Ptr) const;
1265
1266 void fillInCurrentPair() {
1267 CurrentPair.first = *DefIterator;
1268 CurrentPair.second = Location;
1269 if (WalkingPhi && Location.Ptr) {
1270 PHITransAddr Translator(
1271 const_cast<Value *>(Location.Ptr),
1272 OriginalAccess->getBlock()->getDataLayout(), nullptr);
1273
1274 if (Value *Addr =
1275 Translator.translateValue(OriginalAccess->getBlock(),
1276 DefIterator.getPhiArgBlock(), DT, true))
1277 if (Addr != CurrentPair.second.Ptr)
1278 CurrentPair.second = CurrentPair.second.getWithNewPtr(Addr);
1279
1280
1281
1282
1283
1284
1285 if (!IsGuaranteedLoopInvariant(CurrentPair.second.Ptr))
1286 CurrentPair.second = CurrentPair.second.getWithNewSize(
1287 LocationSize::beforeOrAfterPointer());
1288 }
1289 }
1290
1291 MemoryAccessPair CurrentPair;
1292 memoryaccess_def_iterator DefIterator;
1293 MemoryLocation Location;
1294 MemoryAccess *OriginalAccess = nullptr;
1295 DominatorTree *DT = nullptr;
1296 bool WalkingPhi = false;
1297 };
1298
1299 inline upward_defs_iterator
1300 upward_defs_begin(const MemoryAccessPair &Pair, DominatorTree &DT) {
1301 return upward_defs_iterator(Pair, &DT);
1302 }
1303
1304 inline upward_defs_iterator upward_defs_end() { return upward_defs_iterator(); }
1305
1306 inline iterator_range<upward_defs_iterator>
1307 upward_defs(const MemoryAccessPair &Pair, DominatorTree &DT) {
1308 return make_range(upward_defs_begin(Pair, DT), upward_defs_end());
1309 }
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324 template <class T, bool UseOptimizedChain = false>
1325 struct def_chain_iterator
1326 : public iterator_facade_base<def_chain_iterator<T, UseOptimizedChain>,
1327 std::forward_iterator_tag, MemoryAccess *> {
1328 def_chain_iterator() : MA(nullptr) {}
1329 def_chain_iterator(T MA) : MA(MA) {}
1330
1331 T operator*() const { return MA; }
1332
1333 def_chain_iterator &operator++() {
1334
1335 if (auto *MUD = dyn_cast<MemoryUseOrDef>(MA)) {
1336 if (UseOptimizedChain && MUD->isOptimized())
1337 MA = MUD->getOptimized();
1338 else
1339 MA = MUD->getDefiningAccess();
1340 } else {
1341 MA = nullptr;
1342 }
1343
1344 return *this;
1345 }
1346
1347 bool operator==(const def_chain_iterator &O) const { return MA == O.MA; }
1348
1349 private:
1350 T MA;
1351 };
1352
1353 template <class T>
1354 inline iterator_range<def_chain_iterator<T>>
1355 def_chain(T MA, MemoryAccess *UpTo = nullptr) {
1356 #ifdef EXPENSIVE_CHECKS
1357 assert((!UpTo || find(def_chain(MA), UpTo) != def_chain_iterator<T>()) &&
1358 "UpTo isn't in the def chain!");
1359 #endif
1360 return make_range(def_chain_iterator<T>(MA), def_chain_iterator<T>(UpTo));
1361 }
1362
1363 template <class T>
1364 inline iterator_range<def_chain_iterator<T, true>> optimized_def_chain(T MA) {
1365 return make_range(def_chain_iterator<T, true>(MA),
1366 def_chain_iterator<T, true>(nullptr));
1367 }
1368
1369 }
1370
1371 #endif