diff options
author | Chen Zheng <czhengsz@cn.ibm.com> | 2020-11-01 20:55:05 -0500 |
---|---|---|
committer | Chen Zheng <czhengsz@cn.ibm.com> | 2020-11-01 21:13:27 -0500 |
commit | 24a31922ce2ab1ae9e6bda1a315774010bf402d6 (patch) | |
tree | 25daf9f77a760e91c7e616b4277100f584b338f3 /llvm/lib/CodeGen/MachineSink.cpp | |
parent | 1d178d600af77599b398930a640991c9c965a47c (diff) | |
download | llvm-24a31922ce2ab1ae9e6bda1a315774010bf402d6.zip llvm-24a31922ce2ab1ae9e6bda1a315774010bf402d6.tar.gz llvm-24a31922ce2ab1ae9e6bda1a315774010bf402d6.tar.bz2 |
[MachineSink] sink more profitable loads
Reviewed By: qcolombet
Differential Revision: https://reviews.llvm.org/D86864
Diffstat (limited to 'llvm/lib/CodeGen/MachineSink.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MachineSink.cpp | 84 |
1 files changed, 82 insertions, 2 deletions
diff --git a/llvm/lib/CodeGen/MachineSink.cpp b/llvm/lib/CodeGen/MachineSink.cpp index 1914075..0c7c1cb 100644 --- a/llvm/lib/CodeGen/MachineSink.cpp +++ b/llvm/lib/CodeGen/MachineSink.cpp @@ -127,6 +127,12 @@ namespace { /// current block. DenseSet<DebugVariable> SeenDbgVars; + std::map<std::pair<MachineBasicBlock *, MachineBasicBlock *>, bool> + HasStoreCache; + std::map<std::pair<MachineBasicBlock *, MachineBasicBlock *>, + std::vector<MachineInstr *>> + StoreInstrCache; + public: static char ID; // Pass identification @@ -159,6 +165,9 @@ namespace { MachineBasicBlock *From, MachineBasicBlock *To); + bool hasStoreBetween(MachineBasicBlock *From, MachineBasicBlock *To, + MachineInstr &MI); + /// Postpone the splitting of the given critical /// edge (\p From, \p To). /// @@ -359,6 +368,9 @@ bool MachineSinking::runOnMachineFunction(MachineFunction &MF) { EverMadeChange = true; } + HasStoreCache.clear(); + StoreInstrCache.clear(); + // Now clear any kill flags for recorded registers. for (auto I : RegsToClearKillFlags) MRI->clearKillFlags(I); @@ -919,6 +931,73 @@ static void performSink(MachineInstr &MI, MachineBasicBlock &SuccToSinkTo, } } +/// hasStoreBetween - check if there is store betweeen straight line blocks From +/// and To. +bool MachineSinking::hasStoreBetween(MachineBasicBlock *From, + MachineBasicBlock *To, MachineInstr &MI) { + // Make sure From and To are in straight line which means From dominates To + // and To post dominates From. + if (!DT->dominates(From, To) || !PDT->dominates(To, From)) + return true; + + auto BlockPair = std::make_pair(From, To); + + // Does these two blocks pair be queried before and have a definite cached + // result? + if (HasStoreCache.find(BlockPair) != HasStoreCache.end()) + return HasStoreCache[BlockPair]; + + if (StoreInstrCache.find(BlockPair) != StoreInstrCache.end()) + return std::any_of( + StoreInstrCache[BlockPair].begin(), StoreInstrCache[BlockPair].end(), + [&](MachineInstr *I) { return I->mayAlias(AA, MI, false); }); + + bool SawStore = false; + bool HasAliasedStore = false; + DenseSet<MachineBasicBlock *> HandledBlocks; + // Go through all reachable blocks from From. + for (MachineBasicBlock *BB : depth_first(From)) { + // We insert the instruction at the start of block To, so no need to worry + // about stores inside To. + // Store in block From should be already considered when just enter function + // SinkInstruction. + if (BB == To || BB == From) + continue; + + // We already handle this BB in previous iteration. + if (HandledBlocks.count(BB)) + continue; + + HandledBlocks.insert(BB); + // To post dominates BB, it must be a path from block From. + if (PDT->dominates(To, BB)) { + for (MachineInstr &I : *BB) { + // Treat as alias conservatively for a call or an ordered memory + // operation. + if (I.isCall() || I.hasOrderedMemoryRef()) { + HasStoreCache[BlockPair] = true; + return true; + } + + if (I.mayStore()) { + SawStore = true; + // We still have chance to sink MI if all stores between are not + // aliased to MI. + // Cache all store instructions, so that we don't need to go through + // all From reachable blocks for next load instruction. + if (I.mayAlias(AA, MI, false)) + HasAliasedStore = true; + StoreInstrCache[BlockPair].push_back(&I); + } + } + } + } + // If there is no store at all, cache the result. + if (!SawStore) + HasStoreCache[BlockPair] = false; + return HasAliasedStore; +} + /// SinkInstruction - Determine whether it is safe to sink the specified machine /// instruction out of its current block into a successor. bool MachineSinking::SinkInstruction(MachineInstr &MI, bool &SawStore, @@ -979,8 +1058,9 @@ bool MachineSinking::SinkInstruction(MachineInstr &MI, bool &SawStore, // We cannot sink a load across a critical edge - there may be stores in // other code paths. bool TryBreak = false; - bool store = true; - if (!MI.isSafeToMove(AA, store)) { + bool Store = + MI.mayLoad() ? hasStoreBetween(ParentBlock, SuccToSinkTo, MI) : true; + if (!MI.isSafeToMove(AA, Store)) { LLVM_DEBUG(dbgs() << " *** NOTE: Won't sink load along critical edge.\n"); TryBreak = true; } |