已开启
cj-barrier-opt: 修改BarrierNeed 算法 #596
睡觉对我很重要创建于 27 天前
cj-barrier-opt: 修改BarrierNeed 算法 #596
已开启
共 1 个文件变更+78-221
| @@ -18,7 +18,6 @@ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | - | ||
| 22 | 21 | ||
| 23 | 22 | ||
| 24 | 23 | ||
| @@ -70,228 +69,103 @@ static bool isNewMallocCall(CallBase *CB) { | |||
| 70 | 69 | ||
| 71 | class BarrierNeed { | 70 | class BarrierNeed { |
| 72 | public: | 71 | public: |
| 73 | - explicit BarrierNeed(Instruction *Begin, Instruction *End, LoopInfo *LI, | 72 | + explicit BarrierNeed( |
| 74 | - DenseMap<BasicBlock *, bool> &BBSafepointMaps) | 73 | + Instruction *Begin, Instruction *End, |
| 75 | - : Begin(Begin), End(End), BeginLoop(LI->getLoopFor(Begin->getParent())), | 74 | + const DenseMap<BasicBlock *, bool> &BBSafepointMaps) |
| 76 | - EndLoop(LI->getLoopFor(End->getParent())), LI(LI), | 75 | + : Begin(Begin), End(End), BBSafepointMaps(BBSafepointMaps) {} |
| 77 | - BBSafepointMaps(BBSafepointMaps) { | ||
| 78 | - SameParentLoop = getSameParentLoop(BeginLoop); | ||
| 79 | - }; | ||
| 80 | ~BarrierNeed() = default; | 76 | ~BarrierNeed() = default; |
| 81 | 77 | ||
| 82 | bool run() { | 78 | bool run() { |
| 83 | - if (isBeginSingleLoop()) { | 79 | + BasicBlock *BeginBB = Begin->getParent(); |
| 84 | - return true; | ||
| 85 | - } | ||
| 86 | - SmallVector<BasicBlock *> LoopLatches; | ||
| 87 | - if (SameParentLoop != nullptr) { | ||
| 88 | - SameParentLoop->getLoopLatches(LoopLatches); | ||
| 89 | - } | ||
| 90 | - Worklist.insert(Begin->getParent()); | ||
| 91 | BasicBlock *EndBB = End->getParent(); | 80 | BasicBlock *EndBB = End->getParent(); |
| 92 | - while (!Worklist.empty()) { | 81 | + if (BeginBB == EndBB) { |
| 93 | - BasicBlock *BB = Worklist.pop_back_val(); | 82 | + return hasSafepoint(Begin->getIterator(), End->getIterator()); |
| 94 | - if (BBSafepointFlow.count(EndBB) > 0) { | 83 | + } |
| 95 | - return BBSafepointFlow[EndBB]; | 84 | + |
| 96 | - } | 85 | + SmallPtrSet<BasicBlock *, 16> CanReachEnd; |
| 97 | - if (BBSafepointFlow.count(BB) > 0) { | 86 | + SmallVector<BasicBlock *> ReachabilityWorklist; |
| 98 | - continue; | 87 | + CanReachEnd.insert(EndBB); |
| 99 | - } | 88 | + ReachabilityWorklist.push_back(EndBB); |
| 100 | - if ((BB == End->getParent()) && (scanEndBB())) { | 89 | + while (!ReachabilityWorklist.empty()) { |
| 101 | - return BBSafepointFlow[EndBB]; | 90 | + BasicBlock *BB = ReachabilityWorklist.pop_back_val(); |
| 102 | - } else if (BB == Begin->getParent()) { | 91 | + for (BasicBlock *Pred : predecessors(BB)) { |
| 103 | - scanBeginBB(); | 92 | + if (CanReachEnd.insert(Pred).second) { |
| 104 | - } else { | 93 | + ReachabilityWorklist.push_back(Pred); |
| 105 | - if (!calculateSafepoint(BB, BBSafepointMaps[BB])) { | ||
| 106 | - continue; | ||
| 107 | } | 94 | } |
| 108 | } | 95 | } |
| 109 | - if (SameParentLoop != nullptr && isLoopLatch(BB, LoopLatches)) { | ||
| 110 | - continue; | ||
已过期 原始逻辑太繁琐了 , 对于 遇到loop的情况, 并不是所有的都会用到 scanlooppath(), ![]() ![]() | |||
| 111 | - } | ||
| 112 | - scanSuccPath(BB); | ||
| 113 | } | 96 | } |
| 114 | - return (BBSafepointFlow.find(End->getParent()) == BBSafepointFlow.end()); | 97 | + |
| 98 | + // Keep the verifier conservative when End is not reachable from Begin. | ||
| 99 | + if (!CanReachEnd.contains(BeginBB)) { | ||
| 100 | + return true; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + SetVector<BasicBlock *> Worklist; | ||
| 104 | + SmallPtrSet<BasicBlock *, 16> Reached; | ||
| 105 | + DenseMap<BasicBlock *, bool> SafepointFlow; | ||
| 106 | + Reached.insert(BeginBB); | ||
| 107 | + SafepointFlow[BeginBB] = localSafepoint(BeginBB); | ||
| 108 | + Worklist.insert(BeginBB); | ||
| 109 | + | ||
| 110 | + while (!Worklist.empty()) { | ||
| 111 | + BasicBlock *BB = Worklist.pop_back_val(); | ||
| 112 | + bool BBFlow = SafepointFlow.lookup(BB); | ||
| 113 | + for (BasicBlock *Succ : successors(BB)) { | ||
| 114 | + if (!CanReachEnd.contains(Succ)) { | ||
| 115 | + continue; | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + bool NewFlow = BBFlow || localSafepoint(Succ); | ||
| 119 | + bool FirstVisit = Reached.insert(Succ).second; | ||
| 120 | + if (!FirstVisit && (!NewFlow || SafepointFlow.lookup(Succ))) { | ||
| 121 | + continue; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + SafepointFlow[Succ] = NewFlow; | ||
| 125 | + if (Succ == EndBB) { | ||
| 126 | + continue; | ||
| 127 | + } | ||
| 128 | + Worklist.insert(Succ); | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + // If CFG reachability and traversal disagree, conservatively keep the | ||
| 133 | + // barrier. Otherwise the fixed-point value at End is the answer. | ||
| 134 | + return !Reached.contains(EndBB) || SafepointFlow.lookup(EndBB); | ||
| 115 | } | 135 | } |
| 116 | 136 | ||
| 117 | private: | 137 | private: |
| 118 | Instruction *Begin; | 138 | Instruction *Begin; |
| 119 | Instruction *End; | 139 | Instruction *End; |
| 120 | - Loop *BeginLoop; | 140 | + const DenseMap<BasicBlock *, bool> &BBSafepointMaps; |
| 121 | - Loop *EndLoop; | ||
| 122 | - Loop *SameParentLoop; | ||
| 123 | - LoopInfo *LI; | ||
| 124 | - SetVector<BasicBlock *> Worklist; | ||
| 125 | - // Calculate if path have a safepoint. | ||
| 126 | - // If this BB has safepoint depends on himself and its predecessors in path. | ||
| 127 | - DenseMap<BasicBlock *, bool> BBSafepointFlow; | ||
| 128 | - DenseMap<BasicBlock *, bool> BBSafepointMaps; | ||
| 129 | 141 | ||
| 130 | - // Judge if Begin is in a loop alone or Beginloop is a subloop of Endloop. | 142 | + bool hasSafepoint(BasicBlock::iterator First, |
| 131 | - // In these cases, we need to judge if Beginloop has safepoint. | 143 | + BasicBlock::iterator Last) const { |
| 132 | - bool isBeginSingleLoop() { | 144 | + for (auto It = First; It != Last; ++It) { |
| 133 | - // Begin is not in a loop. | 145 | + if (auto *CB = dyn_cast<CallBase>(&*It)) { |
| 134 | - if (BeginLoop == nullptr) { | ||
| 135 | - return false; | ||
| 136 | - } | ||
| 137 | - // Begin is in a loop, End is not in a loop. | ||
| 138 | - if (EndLoop == nullptr) { | ||
| 139 | - return true; | ||
| 140 | - } | ||
| 141 | - // Endloop is a subloop of Beginloop. | ||
| 142 | - if (BeginLoop->contains(EndLoop)) { | ||
| 143 | - return false; | ||
| 144 | - } | ||
| 145 | - // Beginloop is subloop of Endloop. | ||
| 146 | - // Or Beginloop and Endloop are two completely unrelated loops. | ||
| 147 | - return true; | ||
| 148 | - } | ||
| 149 | - | ||
| 150 | - // Judge if BeginLoop and EndLoop are in a same parent loop. | ||
| 151 | - // In this case, we only need to scan the parent loop, | ||
| 152 | - // and when we meet the looplatch of the parent loop, break. | ||
| 153 | - Loop *getSameParentLoop(Loop *L) { | ||
| 154 | - if (L == nullptr) { | ||
| 155 | - return nullptr; | ||
| 156 | - } | ||
| 157 | - if (L->contains(EndLoop)) { | ||
| 158 | - return L; | ||
| 159 | - } | ||
| 160 | - return getSameParentLoop(L->getParentLoop()); | ||
| 161 | - } | ||
| 162 | - | ||
| 163 | - // Judge if we have deal with this BB or this BB is in path to End. | ||
| 164 | - bool isNotDealPathSucc(BasicBlock *BB) { | ||
| 165 | - BasicBlock *EndBB = End->getParent(); | ||
| 166 | - if (BB->isLandingPad()) { | ||
| 167 | - return false; | ||
| 168 | - } | ||
| 169 | - if (Worklist.contains(BB)) { | ||
| 170 | - return false; | ||
| 171 | - } | ||
| 172 | - if (BBSafepointFlow.count(BB) > 0) { | ||
| 173 | - return false; | ||
| 174 | - } | ||
| 175 | - return isPotentiallyReachable(BB, EndBB); | ||
| 176 | - } | ||
| 177 | - | ||
| 178 | - void scanSuccPath(BasicBlock *BB) { | ||
| 179 | - for (auto Succ : successors(BB)) { | ||
| 180 | - if (!isNotDealPathSucc(Succ)) { | ||
| 181 | - continue; | ||
| 182 | - } | ||
| 183 | - Loop *SuccLoop = LI->getLoopFor(Succ); | ||
| 184 | - // Judge if Succ is a node of the same big loop. | ||
| 185 | - // If Succ is a node of the same big loop, Succ is a node of path. | ||
| 186 | - // Otherwise, SuccLoop is a loop node of path. | ||
| 187 | - if ((SuccLoop != nullptr && SameParentLoop != nullptr && | ||
| 188 | - SuccLoop != SameParentLoop) || | ||
已过期 当 Begin 和 End 位于同一个共同 loop 时,并不会 使用scanpathloop() ![]() ![]() | |||
| 189 | - (SuccLoop != nullptr && SameParentLoop == nullptr)) { | ||
| 190 | - scanPathLoop(SuccLoop); | ||
| 191 | - continue; | ||
| 192 | - } | ||
| 193 | - Worklist.insert(Succ); | ||
| 194 | - } | ||
| 195 | - } | ||
| 196 | - | ||
| 197 | - void scanBeginBB() { | ||
| 198 | - bool IsSafepoint = false; | ||
| 199 | - BasicBlock *BeginBB = Begin->getParent(); | ||
| 200 | - for (auto It = Begin->getIterator(), E = BeginBB->end(); It != E; ++It) { | ||
| 201 | - if (auto CB = dyn_cast<CallBase>(&*It)) { | ||
| 202 | if (isSafepointCall(CB)) { | 146 | if (isSafepointCall(CB)) { |
| 203 | - IsSafepoint = true; | 147 | + return true; |
| 204 | - } | ||
| 205 | - } | ||
| 206 | - if (It->isTerminator()) { | ||
| 207 | - calculateSafepoint(BeginBB, IsSafepoint); | ||
| 208 | - } | ||
| 209 | - } | ||
| 210 | - } | ||
| 211 | - | ||
| 212 | - bool scanEndBB() { | ||
| 213 | - bool IsSafepoint = false; | ||
| 214 | - BasicBlock *BeginBB = Begin->getParent(); | ||
| 215 | - BasicBlock *EndBB = End->getParent(); | ||
| 216 | - for (auto It = EndBB == BeginBB ? Begin->getIterator() : EndBB->begin(), | ||
| 217 | - E = EndBB->end(); | ||
| 218 | - It != E; ++It) { | ||
| 219 | - if (It == End->getIterator()) { | ||
| 220 | - return calculateSafepoint(End->getParent(), IsSafepoint); | ||
| 221 | - } | ||
| 222 | - if (auto CB = dyn_cast<CallBase>(&*It)) { | ||
| 223 | - if (isSafepointCall(CB)) { | ||
| 224 | - IsSafepoint = true; | ||
| 225 | } | 148 | } |
| 226 | } | 149 | } |
| 227 | } | 150 | } |
| 228 | return false; | 151 | return false; |
| 229 | } | 152 | } |
| 230 | 153 | ||
| 231 | - void scanPathLoop(Loop *CurLoop) { | 154 | + bool localSafepoint(BasicBlock *BB) const { |
| 232 | - bool IsSafepointLoop = false; | 155 | + if (BB == Begin->getParent()) { |
| 233 | - for (auto BB : CurLoop->getBlocks()) { | 156 | + return hasSafepoint(Begin->getIterator(), BB->end()); |
| 234 | - IsSafepointLoop |= BBSafepointMaps[BB]; | ||
| 235 | } | 157 | } |
| 236 | - scanPreForSafepoint(CurLoop->getHeader(), IsSafepointLoop, CurLoop); | 158 | + if (BB == End->getParent()) { |
| 237 | - for (auto BB : CurLoop->getBlocks()) { | 159 | + return hasSafepoint(BB->begin(), End->getIterator()); |
| 238 | - BBSafepointFlow[BB] = IsSafepointLoop; | ||
| 239 | - Worklist.insert(BB); | ||
| 240 | } | 160 | } |
| 241 | - SmallVector<BasicBlock *> ExitBlocks; | 161 | + return BBSafepointMaps.lookup(BB); |
| 242 | - CurLoop->getExitBlocks(ExitBlocks); | ||
| 243 | - for (auto Exit : ExitBlocks) { | ||
| 244 | - if (!isNotDealPathSucc(Exit)) { | ||
| 245 | - continue; | ||
| 246 | - } | ||
| 247 | - Worklist.insert(Exit); | ||
| 248 | - } | ||
| 249 | - } | ||
| 250 | - | ||
| 251 | - bool calculateSafepoint(BasicBlock *BB, bool &IsSafepoint) { | ||
| 252 | - BasicBlock *BeginBB = Begin->getParent(); | ||
| 253 | - if (BB == BeginBB) { | ||
| 254 | - BBSafepointFlow[BB] = IsSafepoint; | ||
| 255 | - return true; | ||
| 256 | - } | ||
| 257 | - if (!scanPreForSafepoint(BB, IsSafepoint, nullptr)) { | ||
| 258 | - return false; | ||
| 259 | - } | ||
| 260 | - BBSafepointFlow[BB] = IsSafepoint; | ||
| 261 | - return true; | ||
| 262 | - } | ||
| 263 | - | ||
| 264 | - bool scanPreForSafepoint(BasicBlock *BB, bool &IsSafepoint, Loop *L) { | ||
| 265 | - BasicBlock *BeginBB = Begin->getParent(); | ||
| 266 | - for (auto Pre : predecessors(BB)) { | ||
| 267 | - if (L != nullptr && L->contains(Pre)) { | ||
| 268 | - continue; | ||
| 269 | - } | ||
| 270 | - if (!isPotentiallyReachable(BeginBB, Pre)) { | ||
| 271 | - continue; | ||
| 272 | - } | ||
| 273 | - if (BBSafepointFlow.find(Pre) == BBSafepointFlow.end()) { | ||
| 274 | - return false; | ||
| 275 | - } | ||
| 276 | - IsSafepoint |= BBSafepointFlow[Pre]; | ||
| 277 | - } | ||
| 278 | - return true; | ||
| 279 | - } | ||
| 280 | - | ||
| 281 | - bool isLoopLatch(BasicBlock *BB, SmallVector<BasicBlock *> &LoopLatches) { | ||
| 282 | - for (auto LoopLatch : LoopLatches) { | ||
| 283 | - if (BB == LoopLatch) { | ||
| 284 | - return true; | ||
| 285 | - } | ||
| 286 | - } | ||
| 287 | - return false; | ||
| 288 | } | 162 | } |
| 289 | }; | 163 | }; |
| 290 | 164 | ||
| 291 | class BarriersCheck { | 165 | class BarriersCheck { |
| 292 | public: | 166 | public: |
| 293 | - BarriersCheck(Function *F, LoopInfo *LI) : F(F), LI(LI), | 167 | + explicit BarriersCheck(Function *F) |
| 294 | - DL(F->getParent()->getDataLayout()) {}; | 168 | + : F(F), DL(F->getParent()->getDataLayout()) {}; |
| 295 | ~BarriersCheck() = default; | 169 | ~BarriersCheck() = default; |
| 296 | 170 | ||
| 297 | bool run() { | 171 | bool run() { |
| @@ -328,7 +202,6 @@ public: | |||
| 328 | 202 | ||
| 329 | private: | 203 | private: |
| 330 | Function *F; | 204 | Function *F; |
| 331 | - LoopInfo *LI; | ||
| 332 | const DataLayout &DL; | 205 | const DataLayout &DL; |
| 333 | // Record gcwrite and gcwrite.agg | 206 | // Record gcwrite and gcwrite.agg |
| 334 | DenseSet<CallBase *> BarrierSet; | 207 | DenseSet<CallBase *> BarrierSet; |
| @@ -807,7 +680,7 @@ private: | |||
| 807 | return true; | 680 | return true; |
| 808 | 681 | ||
| 809 | Instruction *Begin = getNextNode(CB); | 682 | Instruction *Begin = getNextNode(CB); |
| 810 | - BarrierNeed BN(Begin, Cur, LI, BBSafepointMaps); | 683 | + BarrierNeed BN(Begin, Cur, BBSafepointMaps); |
| 811 | NeedBarrier |= BN.run(); | 684 | NeedBarrier |= BN.run(); |
| 812 | } | 685 | } |
| 813 | 686 | ||
| @@ -843,8 +716,7 @@ private: | |||
| 843 | } | 716 | } |
| 844 | }; | 717 | }; |
| 845 | 718 | ||
| 846 | -static bool optCJBarrierModule(Module &M, | 719 | +static bool optCJBarrierModule(Module &M) { |
| 847 | - function_ref<LoopInfo &(Function &)> GetLI) { | ||
| 848 | bool Changed = false; | 720 | bool Changed = false; |
| 849 | 721 | ||
| 850 | for (Function &F : M) { | 722 | for (Function &F : M) { |
| @@ -852,21 +724,16 @@ static bool optCJBarrierModule(Module &M, | |||
| 852 | continue; | 724 | continue; |
| 853 | } | 725 | } |
| 854 | if (F.hasCangjieGC()) { | 726 | if (F.hasCangjieGC()) { |
| 855 | - auto &LI = GetLI(F); | 727 | + BarriersCheck BC(&F); |
| 856 | - BarriersCheck BC(&F, &LI); | ||
| 857 | Changed |= BC.run(); | 728 | Changed |= BC.run(); |
| 858 | } | 729 | } |
| 859 | } | 730 | } |
| 860 | return Changed; | 731 | return Changed; |
| 861 | } | 732 | } |
| 862 | 733 | ||
| 863 | -PreservedAnalyses CJBarrierOpt::run(Module &M, ModuleAnalysisManager &AM) const { | 734 | +PreservedAnalyses CJBarrierOpt::run(Module &M, |
| 864 | - FunctionAnalysisManager &FAM = | 735 | + ModuleAnalysisManager & /*AM*/) const { |
| 865 | - AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); | 736 | + if (optCJBarrierModule(M)) { |
| 866 | - auto GetLoopInfo = [&FAM](Function &F) -> LoopInfo & { | ||
| 867 | - return FAM.getResult<LoopAnalysis>(F); | ||
| 868 | - }; | ||
| 869 | - if (optCJBarrierModule(M, GetLoopInfo)) { | ||
| 870 | return PreservedAnalyses::none(); | 737 | return PreservedAnalyses::none(); |
| 871 | } | 738 | } |
| 872 | return PreservedAnalyses::all(); | 739 | return PreservedAnalyses::all(); |
| @@ -883,18 +750,9 @@ public: | |||
| 883 | } | 750 | } |
| 884 | ~CJBarrierOptLegacyPass() = default; | 751 | ~CJBarrierOptLegacyPass() = default; |
| 885 | 752 | ||
| 886 | - bool runOnModule(Module &M) override { | 753 | + bool runOnModule(Module &M) override { return optCJBarrierModule(M); } |
| 887 | - bool Changed = false; | ||
| 888 | - auto GetLoopInfo = [this, &Changed](Function &F) -> LoopInfo & { | ||
| 889 | - return this->getAnalysis<LoopInfoWrapperPass>(F, &Changed).getLoopInfo(); | ||
| 890 | - }; | ||
| 891 | - return optCJBarrierModule(M, GetLoopInfo); | ||
| 892 | - } | ||
| 893 | 754 | ||
| 894 | - void getAnalysisUsage(AnalysisUsage &AU) const override { | 755 | + void getAnalysisUsage(AnalysisUsage & /*AU*/) const override {} |
| 895 | - AU.addRequired<LoopInfoWrapperPass>(); | ||
| 896 | - AU.addPreserved<LoopInfoWrapperPass>(); | ||
| 897 | - } | ||
| 898 | }; | 756 | }; |
| 899 | } // namespace | 757 | } // namespace |
| 900 | 758 | ||
| @@ -906,6 +764,5 @@ ModulePass *llvm::createCJBarrierOptLegacyPass() { | |||
| 906 | 764 | ||
| 907 | INITIALIZE_PASS_BEGIN(CJBarrierOptLegacyPass, "cj-barrier-opt", | 765 | INITIALIZE_PASS_BEGIN(CJBarrierOptLegacyPass, "cj-barrier-opt", |
| 908 | "CJ Barrier Opt", false, false) | 766 | "CJ Barrier Opt", false, false) |
| 909 | -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) | ||
| 910 | INITIALIZE_PASS_END(CJBarrierOptLegacyPass, "cj-barrier-opt", | 767 | INITIALIZE_PASS_END(CJBarrierOptLegacyPass, "cj-barrier-opt", |
| 911 | "CJ Barrier Opt", false, false) | 768 | "CJ Barrier Opt", false, false) |


原始的逻辑中, 复杂的地方在于 对于 loop的判断,对于 begin 跟end 是否 在同一个块中会分成两种情况。 新实现的逻辑 先 收集ReachabilityWorklist 去去掉 在同一个loop中, 这样会显得清爽很多。