已开启
cj-barrier-opt: 修改BarrierNeed 算法 #596
睡觉对我很重要创建于 27 天前
cj-barrier-opt: 修改BarrierNeed 算法 #596
已开启
睡觉对我很重要创建于 27 天前
1 个文件变更+78-221
@@ -18,7 +18,6 @@
18#include "llvm/ADT/SetVector.h"18#include "llvm/ADT/SetVector.h"
19#include "llvm/ADT/SmallPtrSet.h"19#include "llvm/ADT/SmallPtrSet.h"
20#include "llvm/Analysis/CFG.h"20#include "llvm/Analysis/CFG.h"
21-#include "llvm/Analysis/LoopInfo.h"
22#include "llvm/Analysis/ValueTracking.h"21#include "llvm/Analysis/ValueTracking.h"
23#include "llvm/IR/Attributes.h"22#include "llvm/IR/Attributes.h"
24#include "llvm/IR/Constants.h"23#include "llvm/IR/Constants.h"
@@ -70,228 +69,103 @@ static bool isNewMallocCall(CallBase *CB) {
70 69 
71class BarrierNeed {70class BarrierNeed {
72public:71public:
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()) {
睡觉对我很重要

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

likedislike
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(),

likedislike
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 
117private:137private:
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()

likedislike
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 
291class BarriersCheck {165class BarriersCheck {
292public:166public:
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 
329private:203private:
330 Function *F;204 Function *F;
331- LoopInfo *LI;
332 const DataLayout &DL;205 const DataLayout &DL;
333 // Record gcwrite and gcwrite.agg206 // 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} // namespace757} // namespace
900 758 
@@ -906,6 +764,5 @@ ModulePass *llvm::createCJBarrierOptLegacyPass() {
906 764 
907INITIALIZE_PASS_BEGIN(CJBarrierOptLegacyPass, "cj-barrier-opt",765INITIALIZE_PASS_BEGIN(CJBarrierOptLegacyPass, "cj-barrier-opt",
908 "CJ Barrier Opt", false, false)766 "CJ Barrier Opt", false, false)
909-INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
910INITIALIZE_PASS_END(CJBarrierOptLegacyPass, "cj-barrier-opt",767INITIALIZE_PASS_END(CJBarrierOptLegacyPass, "cj-barrier-opt",
911 "CJ Barrier Opt", false, false)768 "CJ Barrier Opt", false, false)