comparison lib/IR/SafepointIRVerifier.cpp @ 148:63bd29f05246

merged
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 14 Aug 2019 19:46:37 +0900
parents c2174574ed3a
children
comparison
equal deleted inserted replaced
146:3fc4d5c3e21e 148:63bd29f05246
1 //===-- SafepointIRVerifier.cpp - Verify gc.statepoint invariants ---------===// 1 //===-- SafepointIRVerifier.cpp - Verify gc.statepoint invariants ---------===//
2 // 2 //
3 // The LLVM Compiler Infrastructure 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // 4 // See https://llvm.org/LICENSE.txt for license information.
5 // This file is distributed under the University of Illinois Open Source 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 // License. See LICENSE.TXT for details.
7 // 6 //
8 //===----------------------------------------------------------------------===// 7 //===----------------------------------------------------------------------===//
9 // 8 //
10 // Run a sanity check on the IR to ensure that Safepoints - if they've been 9 // Run a sanity check on the IR to ensure that Safepoints - if they've been
11 // inserted - were inserted correctly. In particular, look for use of 10 // inserted - were inserted correctly. In particular, look for use of
57 /// when verification fails, report a message to the console (for FileCheck 56 /// when verification fails, report a message to the console (for FileCheck
58 /// usage) and continue execution as if nothing happened. 57 /// usage) and continue execution as if nothing happened.
59 static cl::opt<bool> PrintOnly("safepoint-ir-verifier-print-only", 58 static cl::opt<bool> PrintOnly("safepoint-ir-verifier-print-only",
60 cl::init(false)); 59 cl::init(false));
61 60
62 static void Verify(const Function &F, const DominatorTree &DT);
63
64 namespace { 61 namespace {
62
63 /// This CFG Deadness finds dead blocks and edges. Algorithm starts with a set
64 /// of blocks unreachable from entry then propagates deadness using foldable
65 /// conditional branches without modifying CFG. So GVN does but it changes CFG
66 /// by splitting critical edges. In most cases passes rely on SimplifyCFG to
67 /// clean up dead blocks, but in some cases, like verification or loop passes
68 /// it's not possible.
69 class CFGDeadness {
70 const DominatorTree *DT = nullptr;
71 SetVector<const BasicBlock *> DeadBlocks;
72 SetVector<const Use *> DeadEdges; // Contains all dead edges from live blocks.
73
74 public:
75 /// Return the edge that coresponds to the predecessor.
76 static const Use& getEdge(const_pred_iterator &PredIt) {
77 auto &PU = PredIt.getUse();
78 return PU.getUser()->getOperandUse(PU.getOperandNo());
79 }
80
81 /// Return true if there is at least one live edge that corresponds to the
82 /// basic block InBB listed in the phi node.
83 bool hasLiveIncomingEdge(const PHINode *PN, const BasicBlock *InBB) const {
84 assert(!isDeadBlock(InBB) && "block must be live");
85 const BasicBlock* BB = PN->getParent();
86 bool Listed = false;
87 for (const_pred_iterator PredIt(BB), End(BB, true); PredIt != End; ++PredIt) {
88 if (InBB == *PredIt) {
89 if (!isDeadEdge(&getEdge(PredIt)))
90 return true;
91 Listed = true;
92 }
93 }
94 (void)Listed;
95 assert(Listed && "basic block is not found among incoming blocks");
96 return false;
97 }
98
99
100 bool isDeadBlock(const BasicBlock *BB) const {
101 return DeadBlocks.count(BB);
102 }
103
104 bool isDeadEdge(const Use *U) const {
105 assert(dyn_cast<Instruction>(U->getUser())->isTerminator() &&
106 "edge must be operand of terminator");
107 assert(cast_or_null<BasicBlock>(U->get()) &&
108 "edge must refer to basic block");
109 assert(!isDeadBlock(dyn_cast<Instruction>(U->getUser())->getParent()) &&
110 "isDeadEdge() must be applied to edge from live block");
111 return DeadEdges.count(U);
112 }
113
114 bool hasLiveIncomingEdges(const BasicBlock *BB) const {
115 // Check if all incoming edges are dead.
116 for (const_pred_iterator PredIt(BB), End(BB, true); PredIt != End; ++PredIt) {
117 auto &PU = PredIt.getUse();
118 const Use &U = PU.getUser()->getOperandUse(PU.getOperandNo());
119 if (!isDeadBlock(*PredIt) && !isDeadEdge(&U))
120 return true; // Found a live edge.
121 }
122 return false;
123 }
124
125 void processFunction(const Function &F, const DominatorTree &DT) {
126 this->DT = &DT;
127
128 // Start with all blocks unreachable from entry.
129 for (const BasicBlock &BB : F)
130 if (!DT.isReachableFromEntry(&BB))
131 DeadBlocks.insert(&BB);
132
133 // Top-down walk of the dominator tree
134 ReversePostOrderTraversal<const Function *> RPOT(&F);
135 for (const BasicBlock *BB : RPOT) {
136 const Instruction *TI = BB->getTerminator();
137 assert(TI && "blocks must be well formed");
138
139 // For conditional branches, we can perform simple conditional propagation on
140 // the condition value itself.
141 const BranchInst *BI = dyn_cast<BranchInst>(TI);
142 if (!BI || !BI->isConditional() || !isa<Constant>(BI->getCondition()))
143 continue;
144
145 // If a branch has two identical successors, we cannot declare either dead.
146 if (BI->getSuccessor(0) == BI->getSuccessor(1))
147 continue;
148
149 ConstantInt *Cond = dyn_cast<ConstantInt>(BI->getCondition());
150 if (!Cond)
151 continue;
152
153 addDeadEdge(BI->getOperandUse(Cond->getZExtValue() ? 1 : 2));
154 }
155 }
156
157 protected:
158 void addDeadBlock(const BasicBlock *BB) {
159 SmallVector<const BasicBlock *, 4> NewDead;
160 SmallSetVector<const BasicBlock *, 4> DF;
161
162 NewDead.push_back(BB);
163 while (!NewDead.empty()) {
164 const BasicBlock *D = NewDead.pop_back_val();
165 if (isDeadBlock(D))
166 continue;
167
168 // All blocks dominated by D are dead.
169 SmallVector<BasicBlock *, 8> Dom;
170 DT->getDescendants(const_cast<BasicBlock*>(D), Dom);
171 // Do not need to mark all in and out edges dead
172 // because BB is marked dead and this is enough
173 // to run further.
174 DeadBlocks.insert(Dom.begin(), Dom.end());
175
176 // Figure out the dominance-frontier(D).
177 for (BasicBlock *B : Dom)
178 for (BasicBlock *S : successors(B))
179 if (!isDeadBlock(S) && !hasLiveIncomingEdges(S))
180 NewDead.push_back(S);
181 }
182 }
183
184 void addDeadEdge(const Use &DeadEdge) {
185 if (!DeadEdges.insert(&DeadEdge))
186 return;
187
188 BasicBlock *BB = cast_or_null<BasicBlock>(DeadEdge.get());
189 if (hasLiveIncomingEdges(BB))
190 return;
191
192 addDeadBlock(BB);
193 }
194 };
195 } // namespace
196
197 static void Verify(const Function &F, const DominatorTree &DT,
198 const CFGDeadness &CD);
199
200 namespace llvm {
201 PreservedAnalyses SafepointIRVerifierPass::run(Function &F,
202 FunctionAnalysisManager &AM) {
203 const auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
204 CFGDeadness CD;
205 CD.processFunction(F, DT);
206 Verify(F, DT, CD);
207 return PreservedAnalyses::all();
208 }
209 }
210
211 namespace {
212
65 struct SafepointIRVerifier : public FunctionPass { 213 struct SafepointIRVerifier : public FunctionPass {
66 static char ID; // Pass identification, replacement for typeid 214 static char ID; // Pass identification, replacement for typeid
67 DominatorTree DT;
68 SafepointIRVerifier() : FunctionPass(ID) { 215 SafepointIRVerifier() : FunctionPass(ID) {
69 initializeSafepointIRVerifierPass(*PassRegistry::getPassRegistry()); 216 initializeSafepointIRVerifierPass(*PassRegistry::getPassRegistry());
70 } 217 }
71 218
72 bool runOnFunction(Function &F) override { 219 bool runOnFunction(Function &F) override {
73 DT.recalculate(F); 220 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
74 Verify(F, DT); 221 CFGDeadness CD;
222 CD.processFunction(F, DT);
223 Verify(F, DT, CD);
75 return false; // no modifications 224 return false; // no modifications
76 } 225 }
77 226
78 void getAnalysisUsage(AnalysisUsage &AU) const override { 227 void getAnalysisUsage(AnalysisUsage &AU) const override {
228 AU.addRequiredID(DominatorTreeWrapperPass::ID);
79 AU.setPreservesAll(); 229 AU.setPreservesAll();
80 } 230 }
81 231
82 StringRef getPassName() const override { return "safepoint verifier"; } 232 StringRef getPassName() const override { return "safepoint verifier"; }
83 }; 233 };
93 FunctionPass *llvm::createSafepointIRVerifierPass() { 243 FunctionPass *llvm::createSafepointIRVerifierPass() {
94 return new SafepointIRVerifier(); 244 return new SafepointIRVerifier();
95 } 245 }
96 246
97 INITIALIZE_PASS_BEGIN(SafepointIRVerifier, "verify-safepoint-ir", 247 INITIALIZE_PASS_BEGIN(SafepointIRVerifier, "verify-safepoint-ir",
98 "Safepoint IR Verifier", false, true) 248 "Safepoint IR Verifier", false, false)
249 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
99 INITIALIZE_PASS_END(SafepointIRVerifier, "verify-safepoint-ir", 250 INITIALIZE_PASS_END(SafepointIRVerifier, "verify-safepoint-ir",
100 "Safepoint IR Verifier", false, true) 251 "Safepoint IR Verifier", false, false)
101 252
102 static bool isGCPointerType(Type *T) { 253 static bool isGCPointerType(Type *T) {
103 if (auto *PT = dyn_cast<PointerType>(T)) 254 if (auto *PT = dyn_cast<PointerType>(T))
104 // For the sake of this example GC, we arbitrarily pick addrspace(1) as our 255 // For the sake of this example GC, we arbitrarily pick addrspace(1) as our
105 // GC managed heap. We know that a pointer into this heap needs to be 256 // GC managed heap. We know that a pointer into this heap needs to be
114 if (VectorType *VT = dyn_cast<VectorType>(Ty)) 265 if (VectorType *VT = dyn_cast<VectorType>(Ty))
115 return isGCPointerType(VT->getScalarType()); 266 return isGCPointerType(VT->getScalarType());
116 if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) 267 if (ArrayType *AT = dyn_cast<ArrayType>(Ty))
117 return containsGCPtrType(AT->getElementType()); 268 return containsGCPtrType(AT->getElementType());
118 if (StructType *ST = dyn_cast<StructType>(Ty)) 269 if (StructType *ST = dyn_cast<StructType>(Ty))
119 return std::any_of(ST->subtypes().begin(), ST->subtypes().end(), 270 return llvm::any_of(ST->elements(), containsGCPtrType);
120 containsGCPtrType);
121 return false; 271 return false;
122 } 272 }
123 273
124 // Debugging aid -- prints a [Begin, End) range of values. 274 // Debugging aid -- prints a [Begin, End) range of values.
125 template<typename IteratorTy> 275 template<typename IteratorTy>
290 /// To fix this we need to introduce conception of generations and be able to 440 /// To fix this we need to introduce conception of generations and be able to
291 /// check if two values belong to one generation or not. This way p2 will be 441 /// check if two values belong to one generation or not. This way p2 will be
292 /// considered to be unrelocated and no false alarm will happen. 442 /// considered to be unrelocated and no false alarm will happen.
293 class GCPtrTracker { 443 class GCPtrTracker {
294 const Function &F; 444 const Function &F;
445 const CFGDeadness &CD;
295 SpecificBumpPtrAllocator<BasicBlockState> BSAllocator; 446 SpecificBumpPtrAllocator<BasicBlockState> BSAllocator;
296 DenseMap<const BasicBlock *, BasicBlockState *> BlockMap; 447 DenseMap<const BasicBlock *, BasicBlockState *> BlockMap;
297 // This set contains defs of unrelocated pointers that are proved to be legal 448 // This set contains defs of unrelocated pointers that are proved to be legal
298 // and don't need verification. 449 // and don't need verification.
299 DenseSet<const Instruction *> ValidUnrelocatedDefs; 450 DenseSet<const Instruction *> ValidUnrelocatedDefs;
300 // This set contains poisoned defs. They can be safely ignored during 451 // This set contains poisoned defs. They can be safely ignored during
301 // verification too. 452 // verification too.
302 DenseSet<const Value *> PoisonedDefs; 453 DenseSet<const Value *> PoisonedDefs;
303 454
304 public: 455 public:
305 GCPtrTracker(const Function &F, const DominatorTree &DT); 456 GCPtrTracker(const Function &F, const DominatorTree &DT,
457 const CFGDeadness &CD);
458
459 bool hasLiveIncomingEdge(const PHINode *PN, const BasicBlock *InBB) const {
460 return CD.hasLiveIncomingEdge(PN, InBB);
461 }
306 462
307 BasicBlockState *getBasicBlockState(const BasicBlock *BB); 463 BasicBlockState *getBasicBlockState(const BasicBlock *BB);
308 const BasicBlockState *getBasicBlockState(const BasicBlock *BB) const; 464 const BasicBlockState *getBasicBlockState(const BasicBlock *BB) const;
309 465
310 bool isValuePoisoned(const Value *V) const { return PoisonedDefs.count(V); } 466 bool isValuePoisoned(const Value *V) const { return PoisonedDefs.count(V); }
315 /// It destructively modifies GCPtrTracker so it's passed via rvalue reference 471 /// It destructively modifies GCPtrTracker so it's passed via rvalue reference
316 /// in order to prohibit further usages of GCPtrTracker as it'll be in 472 /// in order to prohibit further usages of GCPtrTracker as it'll be in
317 /// inconsistent state. 473 /// inconsistent state.
318 static void verifyFunction(GCPtrTracker &&Tracker, 474 static void verifyFunction(GCPtrTracker &&Tracker,
319 InstructionVerifier &Verifier); 475 InstructionVerifier &Verifier);
476
477 /// Returns true for reachable and live blocks.
478 bool isMapped(const BasicBlock *BB) const {
479 return BlockMap.find(BB) != BlockMap.end();
480 }
320 481
321 private: 482 private:
322 /// Returns true if the instruction may be safely skipped during verification. 483 /// Returns true if the instruction may be safely skipped during verification.
323 bool instructionMayBeSkipped(const Instruction *I) const; 484 bool instructionMayBeSkipped(const Instruction *I) const;
324 485
370 private: 531 private:
371 void reportInvalidUse(const Value &V, const Instruction &I); 532 void reportInvalidUse(const Value &V, const Instruction &I);
372 }; 533 };
373 } // end anonymous namespace 534 } // end anonymous namespace
374 535
375 GCPtrTracker::GCPtrTracker(const Function &F, const DominatorTree &DT) : F(F) { 536 GCPtrTracker::GCPtrTracker(const Function &F, const DominatorTree &DT,
376 // First, calculate Contribution of each BB. 537 const CFGDeadness &CD) : F(F), CD(CD) {
377 for (const BasicBlock &BB : F) { 538 // Calculate Contribution of each live BB.
378 BasicBlockState *BBS = new (BSAllocator.Allocate()) BasicBlockState; 539 // Allocate BB states for live blocks.
379 for (const auto &I : BB) 540 for (const BasicBlock &BB : F)
380 transferInstruction(I, BBS->Cleared, BBS->Contribution); 541 if (!CD.isDeadBlock(&BB)) {
381 BlockMap[&BB] = BBS; 542 BasicBlockState *BBS = new (BSAllocator.Allocate()) BasicBlockState;
382 } 543 for (const auto &I : BB)
544 transferInstruction(I, BBS->Cleared, BBS->Contribution);
545 BlockMap[&BB] = BBS;
546 }
383 547
384 // Initialize AvailableIn/Out sets of each BB using only information about 548 // Initialize AvailableIn/Out sets of each BB using only information about
385 // dominating BBs. 549 // dominating BBs.
386 for (auto &BBI : BlockMap) { 550 for (auto &BBI : BlockMap) {
387 gatherDominatingDefs(BBI.first, BBI.second->AvailableIn, DT); 551 gatherDominatingDefs(BBI.first, BBI.second->AvailableIn, DT);
394 recalculateBBsStates(); 558 recalculateBBsStates();
395 } 559 }
396 560
397 BasicBlockState *GCPtrTracker::getBasicBlockState(const BasicBlock *BB) { 561 BasicBlockState *GCPtrTracker::getBasicBlockState(const BasicBlock *BB) {
398 auto it = BlockMap.find(BB); 562 auto it = BlockMap.find(BB);
399 assert(it != BlockMap.end() && 563 return it != BlockMap.end() ? it->second : nullptr;
400 "No such BB in BlockMap! Probably BB from another function");
401 return it->second;
402 } 564 }
403 565
404 const BasicBlockState *GCPtrTracker::getBasicBlockState( 566 const BasicBlockState *GCPtrTracker::getBasicBlockState(
405 const BasicBlock *BB) const { 567 const BasicBlock *BB) const {
406 return const_cast<GCPtrTracker *>(this)->getBasicBlockState(BB); 568 return const_cast<GCPtrTracker *>(this)->getBasicBlockState(BB);
417 // We need RPO here to a) report always the first error b) report errors in 579 // We need RPO here to a) report always the first error b) report errors in
418 // same order from run to run. 580 // same order from run to run.
419 ReversePostOrderTraversal<const Function *> RPOT(&Tracker.F); 581 ReversePostOrderTraversal<const Function *> RPOT(&Tracker.F);
420 for (const BasicBlock *BB : RPOT) { 582 for (const BasicBlock *BB : RPOT) {
421 BasicBlockState *BBS = Tracker.getBasicBlockState(BB); 583 BasicBlockState *BBS = Tracker.getBasicBlockState(BB);
584 if (!BBS)
585 continue;
586
422 // We destructively modify AvailableIn as we traverse the block instruction 587 // We destructively modify AvailableIn as we traverse the block instruction
423 // by instruction. 588 // by instruction.
424 AvailableValueSet &AvailableSet = BBS->AvailableIn; 589 AvailableValueSet &AvailableSet = BBS->AvailableIn;
425 for (const Instruction &I : *BB) { 590 for (const Instruction &I : *BB) {
426 if (Tracker.instructionMayBeSkipped(&I)) 591 if (Tracker.instructionMayBeSkipped(&I))
446 611
447 // This loop iterates the AvailableIn/Out sets until it converges. 612 // This loop iterates the AvailableIn/Out sets until it converges.
448 // The AvailableIn and AvailableOut sets decrease as we iterate. 613 // The AvailableIn and AvailableOut sets decrease as we iterate.
449 while (!Worklist.empty()) { 614 while (!Worklist.empty()) {
450 const BasicBlock *BB = Worklist.pop_back_val(); 615 const BasicBlock *BB = Worklist.pop_back_val();
451 BasicBlockState *BBS = BlockMap[BB]; 616 BasicBlockState *BBS = getBasicBlockState(BB);
617 if (!BBS)
618 continue; // Ignore dead successors.
452 619
453 size_t OldInCount = BBS->AvailableIn.size(); 620 size_t OldInCount = BBS->AvailableIn.size();
454 for (const BasicBlock *PBB : predecessors(BB)) 621 for (const_pred_iterator PredIt(BB), End(BB, true); PredIt != End; ++PredIt) {
455 set_intersect(BBS->AvailableIn, BlockMap[PBB]->AvailableOut); 622 const BasicBlock *PBB = *PredIt;
623 BasicBlockState *PBBS = getBasicBlockState(PBB);
624 if (PBBS && !CD.isDeadEdge(&CFGDeadness::getEdge(PredIt)))
625 set_intersect(BBS->AvailableIn, PBBS->AvailableOut);
626 }
456 627
457 assert(OldInCount >= BBS->AvailableIn.size() && "invariant!"); 628 assert(OldInCount >= BBS->AvailableIn.size() && "invariant!");
458 629
459 bool InputsChanged = OldInCount != BBS->AvailableIn.size(); 630 bool InputsChanged = OldInCount != BBS->AvailableIn.size();
460 bool ContributionChanged = 631 bool ContributionChanged =
489 // If both is true, output is poisoned. 660 // If both is true, output is poisoned.
490 bool HasRelocatedInputs = false; 661 bool HasRelocatedInputs = false;
491 bool HasUnrelocatedInputs = false; 662 bool HasUnrelocatedInputs = false;
492 for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { 663 for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
493 const BasicBlock *InBB = PN->getIncomingBlock(i); 664 const BasicBlock *InBB = PN->getIncomingBlock(i);
665 if (!isMapped(InBB) ||
666 !CD.hasLiveIncomingEdge(PN, InBB))
667 continue; // Skip dead block or dead edge.
668
494 const Value *InValue = PN->getIncomingValue(i); 669 const Value *InValue = PN->getIncomingValue(i);
495 670
496 if (isNotExclusivelyConstantDerived(InValue)) { 671 if (isNotExclusivelyConstantDerived(InValue)) {
497 if (isValuePoisoned(InValue)) { 672 if (isValuePoisoned(InValue)) {
498 // If any of inputs is poisoned, output is always poisoned too. 673 // If any of inputs is poisoned, output is always poisoned too.
533 // Remove def of unrelocated pointer from Contribution of this BB and 708 // Remove def of unrelocated pointer from Contribution of this BB and
534 // trigger update of all its successors. 709 // trigger update of all its successors.
535 Contribution.erase(&I); 710 Contribution.erase(&I);
536 PoisonedDefs.erase(&I); 711 PoisonedDefs.erase(&I);
537 ValidUnrelocatedDefs.insert(&I); 712 ValidUnrelocatedDefs.insert(&I);
538 DEBUG(dbgs() << "Removing urelocated " << I << " from Contribution of " 713 LLVM_DEBUG(dbgs() << "Removing urelocated " << I
539 << BB->getName() << "\n"); 714 << " from Contribution of " << BB->getName() << "\n");
540 ContributionChanged = true; 715 ContributionChanged = true;
541 } else if (PoisonedPointerDef) { 716 } else if (PoisonedPointerDef) {
542 // Mark pointer as poisoned, remove its def from Contribution and trigger 717 // Mark pointer as poisoned, remove its def from Contribution and trigger
543 // update of all successors. 718 // update of all successors.
544 Contribution.erase(&I); 719 Contribution.erase(&I);
545 PoisonedDefs.insert(&I); 720 PoisonedDefs.insert(&I);
546 DEBUG(dbgs() << "Removing poisoned " << I << " from Contribution of " 721 LLVM_DEBUG(dbgs() << "Removing poisoned " << I << " from Contribution of "
547 << BB->getName() << "\n"); 722 << BB->getName() << "\n");
548 ContributionChanged = true; 723 ContributionChanged = true;
549 } else { 724 } else {
550 bool Cleared = false; 725 bool Cleared = false;
551 transferInstruction(I, Cleared, AvailableSet); 726 transferInstruction(I, Cleared, AvailableSet);
552 (void)Cleared; 727 (void)Cleared;
558 void GCPtrTracker::gatherDominatingDefs(const BasicBlock *BB, 733 void GCPtrTracker::gatherDominatingDefs(const BasicBlock *BB,
559 AvailableValueSet &Result, 734 AvailableValueSet &Result,
560 const DominatorTree &DT) { 735 const DominatorTree &DT) {
561 DomTreeNode *DTN = DT[const_cast<BasicBlock *>(BB)]; 736 DomTreeNode *DTN = DT[const_cast<BasicBlock *>(BB)];
562 737
738 assert(DTN && "Unreachable blocks are ignored");
563 while (DTN->getIDom()) { 739 while (DTN->getIDom()) {
564 DTN = DTN->getIDom(); 740 DTN = DTN->getIDom();
565 const auto &Defs = BlockMap[DTN->getBlock()]->Contribution; 741 auto BBS = getBasicBlockState(DTN->getBlock());
742 assert(BBS && "immediate dominator cannot be dead for a live block");
743 const auto &Defs = BBS->Contribution;
566 Result.insert(Defs.begin(), Defs.end()); 744 Result.insert(Defs.begin(), Defs.end());
567 // If this block is 'Cleared', then nothing LiveIn to this block can be 745 // If this block is 'Cleared', then nothing LiveIn to this block can be
568 // available after this block completes. Note: This turns out to be 746 // available after this block completes. Note: This turns out to be
569 // really important for reducing memory consuption of the initial available 747 // really important for reducing memory consuption of the initial available
570 // sets and thus peak memory usage by this verifier. 748 // sets and thus peak memory usage by this verifier.
571 if (BlockMap[DTN->getBlock()]->Cleared) 749 if (BBS->Cleared)
572 return; 750 return;
573 } 751 }
574 752
575 for (const Argument &A : BB->getParent()->args()) 753 for (const Argument &A : BB->getParent()->args())
576 if (containsGCPtrType(A.getType())) 754 if (containsGCPtrType(A.getType()))
592 AvailableValueSet Temp = BBS.Contribution; 770 AvailableValueSet Temp = BBS.Contribution;
593 set_union(Temp, AvailableIn); 771 set_union(Temp, AvailableIn);
594 AvailableOut = std::move(Temp); 772 AvailableOut = std::move(Temp);
595 } 773 }
596 774
597 DEBUG(dbgs() << "Transfered block " << BB->getName() << " from "; 775 LLVM_DEBUG(dbgs() << "Transfered block " << BB->getName() << " from ";
598 PrintValueSet(dbgs(), AvailableIn.begin(), AvailableIn.end()); 776 PrintValueSet(dbgs(), AvailableIn.begin(), AvailableIn.end());
599 dbgs() << " to "; 777 dbgs() << " to ";
600 PrintValueSet(dbgs(), AvailableOut.begin(), AvailableOut.end()); 778 PrintValueSet(dbgs(), AvailableOut.begin(), AvailableOut.end());
601 dbgs() << "\n";); 779 dbgs() << "\n";);
602 } 780 }
603 781
604 void GCPtrTracker::transferInstruction(const Instruction &I, bool &Cleared, 782 void GCPtrTracker::transferInstruction(const Instruction &I, bool &Cleared,
605 AvailableValueSet &Available) { 783 AvailableValueSet &Available) {
606 if (isStatepoint(I)) { 784 if (isStatepoint(I)) {
615 const AvailableValueSet &AvailableSet) { 793 const AvailableValueSet &AvailableSet) {
616 if (const PHINode *PN = dyn_cast<PHINode>(&I)) { 794 if (const PHINode *PN = dyn_cast<PHINode>(&I)) {
617 if (containsGCPtrType(PN->getType())) 795 if (containsGCPtrType(PN->getType()))
618 for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { 796 for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
619 const BasicBlock *InBB = PN->getIncomingBlock(i); 797 const BasicBlock *InBB = PN->getIncomingBlock(i);
798 const BasicBlockState *InBBS = Tracker->getBasicBlockState(InBB);
799 if (!InBBS ||
800 !Tracker->hasLiveIncomingEdge(PN, InBB))
801 continue; // Skip dead block or dead edge.
802
620 const Value *InValue = PN->getIncomingValue(i); 803 const Value *InValue = PN->getIncomingValue(i);
621 804
622 if (isNotExclusivelyConstantDerived(InValue) && 805 if (isNotExclusivelyConstantDerived(InValue) &&
623 !Tracker->getBasicBlockState(InBB)->AvailableOut.count(InValue)) 806 !InBBS->AvailableOut.count(InValue))
624 reportInvalidUse(*InValue, *PN); 807 reportInvalidUse(*InValue, *PN);
625 } 808 }
626 } else if (isa<CmpInst>(I) && 809 } else if (isa<CmpInst>(I) &&
627 containsGCPtrType(I.getOperand(0)->getType())) { 810 containsGCPtrType(I.getOperand(0)->getType())) {
628 Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); 811 Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
695 if (!PrintOnly) 878 if (!PrintOnly)
696 abort(); 879 abort();
697 AnyInvalidUses = true; 880 AnyInvalidUses = true;
698 } 881 }
699 882
700 static void Verify(const Function &F, const DominatorTree &DT) { 883 static void Verify(const Function &F, const DominatorTree &DT,
701 DEBUG(dbgs() << "Verifying gc pointers in function: " << F.getName() << "\n"); 884 const CFGDeadness &CD) {
885 LLVM_DEBUG(dbgs() << "Verifying gc pointers in function: " << F.getName()
886 << "\n");
702 if (PrintOnly) 887 if (PrintOnly)
703 dbgs() << "Verifying gc pointers in function: " << F.getName() << "\n"; 888 dbgs() << "Verifying gc pointers in function: " << F.getName() << "\n";
704 889
705 GCPtrTracker Tracker(F, DT); 890 GCPtrTracker Tracker(F, DT, CD);
706 891
707 // We now have all the information we need to decide if the use of a heap 892 // We now have all the information we need to decide if the use of a heap
708 // reference is legal or not, given our safepoint semantics. 893 // reference is legal or not, given our safepoint semantics.
709 894
710 InstructionVerifier Verifier; 895 InstructionVerifier Verifier;