• Home
  • Raw
  • Download

Lines Matching +full:dependency +full:- +full:check

1 //===-- ImplicitNullChecks.cpp - Fold null checks into memory accesses ----===//
8 //===----------------------------------------------------------------------===//
26 //===----------------------------------------------------------------------===//
50 static cl::opt<int> PageSize("imp-null-check-page-size",
54 #define DEBUG_TYPE "implicit-null-checks"
62 /// Represents one null check that can be made implicit.
64 // The memory operation the null check can be folded into.
67 // The instruction actually doing the null check (Ptr != 0).
70 // The block the check resides in.
73 // The block branched to if the pointer is non-null.
79 // If this is non-null, then MemOperation has a dependency on on this
136 /// \brief Detect re-ordering hazards and dependencies.
139 /// machine instruction can be re-ordered from after the machine instructions
166 /// has one and only one transitive dependency, set \p Dependency to that
168 bool isSafeToHoist(MachineInstr *MI, MachineInstr *&Dependency);
190 if (MI->mayStore() || MI->hasUnmodeledSideEffects()) { in rememberInstruction()
195 for (auto *MMO : MI->memoperands()) { in rememberInstruction()
197 if (!MMO->isUnordered()) { in rememberInstruction()
203 for (auto &MO : MI->operands()) { in rememberInstruction()
212 assert(It->second && "Found null MI?"); in rememberInstruction()
213 It->second = getUnknownMI(); in rememberInstruction()
221 MachineInstr *&Dependency) { in isSafeToHoist() argument
223 Dependency = nullptr; in isSafeToHoist()
227 for (auto *MMO : MI->memoperands()) in isSafeToHoist()
228 if (!MMO->isUnordered()) in isSafeToHoist()
231 for (auto &MO : MI->operands()) { in isSafeToHoist()
239 // We found a write-after-write or read-after-write, see if the in isSafeToHoist()
240 // instruction causing this dependency can be hoisted too. in isSafeToHoist()
243 // We don't have precise dependency information. in isSafeToHoist()
246 if (Dependency) { in isSafeToHoist()
247 if (Dependency == MI) in isSafeToHoist()
249 // We already have one dependency, and we can track only one. in isSafeToHoist()
253 // Now check if MI is actually a dependency that can be hoisted. in isSafeToHoist()
268 return !MO.isDef() || RegDefs.find(MO.getReg())->second == MI; in isSafeToHoist()
271 if (!all_of(MI->operands(), IsMIOperandSafe)) in isSafeToHoist()
274 // Now check for speculation safety: in isSafeToHoist()
276 if (!MI->isSafeToMove(&AA, SawStore) || MI->mayLoad()) in isSafeToHoist()
279 Dependency = MI; in isSafeToHoist()
285 return false; // We found a write-after-read in isSafeToHoist()
309 // Return true if any register aliasing \p Reg is live-in into \p MBB.
314 if (MBB->isLiveIn(*AR)) in AnyAliasLiveIn()
319 /// Analyze MBB to check if its terminating branch can be turned into an
320 /// implicit null check. If yes, append a description of the said null check to
328 BranchMD = BB->getTerminator()->getMetadata(LLVMContext::MD_make_implicit); in analyzeBlockForNullChecks()
335 if (TII->analyzeBranchPredicate(MBB, MBP, true)) in analyzeBlockForNullChecks()
344 // If we cannot erase the test instruction itself, then making the null check in analyzeBlockForNullChecks()
361 if (NotNullSucc->pred_size() != 1) in analyzeBlockForNullChecks()
405 // control flow. For instance, in the example below (in pseudo-C) in analyzeBlockForNullChecks()
409 // v = ptr->field; // LD in analyzeBlockForNullChecks()
412 // we cannot (without code duplication) use the load marked "LD" to null check in analyzeBlockForNullChecks()
413 // ptr -- clause (2) above does not apply in this case. In the above program in analyzeBlockForNullChecks()
414 // the safety of ptr->field can be dependent on some_cond; and, for instance, in analyzeBlockForNullChecks()
415 // ptr could be some non-null invalid reference that never gets loaded from in analyzeBlockForNullChecks()
422 for (auto MII = NotNullSucc->begin(), MIE = NotNullSucc->end(); MII != MIE; in analyzeBlockForNullChecks()
427 MachineInstr *Dependency = nullptr; in analyzeBlockForNullChecks() local
428 if (TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI)) in analyzeBlockForNullChecks()
431 HD.isSafeToHoist(&MI, Dependency)) { in analyzeBlockForNullChecks()
440 // by hoisting Dependency. For instance, we can't hoist INST to in analyzeBlockForNullChecks()
441 // before the null check (even if it safe, and does not violate any in analyzeBlockForNullChecks()
453 // Make sure Dependency isn't re-defining the base register. Then we in analyzeBlockForNullChecks()
455 if (TRI->regsOverlap(MO.getReg(), BaseReg)) in analyzeBlockForNullChecks()
462 !Dependency || in analyzeBlockForNullChecks()
463 all_of(Dependency->operands(), DependencyOperandIsOk); in analyzeBlockForNullChecks()
467 NullSucc, Dependency); in analyzeBlockForNullChecks()
492 unsigned NumDefs = LoadMI->getDesc().getNumDefs(); in insertFaultingLoad()
497 DefReg = LoadMI->defs().begin()->getReg(); in insertFaultingLoad()
498 assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 && in insertFaultingLoad()
502 auto MIB = BuildMI(MBB, DL, TII->get(TargetOpcode::FAULTING_LOAD_OP), DefReg) in insertFaultingLoad()
504 .addImm(LoadMI->getOpcode()); in insertFaultingLoad()
506 for (auto &MO : LoadMI->uses()) in insertFaultingLoad()
509 MIB.setMemRefs(LoadMI->memoperands_begin(), LoadMI->memoperands_end()); in insertFaultingLoad()
520 // Remove the conditional branch dependent on the null check. in rewriteNullChecks()
521 unsigned BranchesRemoved = TII->RemoveBranch(*NC.getCheckBlock()); in rewriteNullChecks()
526 DepMI->removeFromParent(); in rewriteNullChecks()
527 NC.getCheckBlock()->insert(NC.getCheckBlock()->end(), DepMI); in rewriteNullChecks()
531 // check earlier ensures that this bit of code motion is legal. We do not in rewriteNullChecks()
536 // Now the values defined by MemOperation, if any, are live-in of in rewriteNullChecks()
538 // The original load operation may define implicit-defs alongside in rewriteNullChecks()
540 MachineBasicBlock *MBB = NC.getMemOperation()->getParent(); in rewriteNullChecks()
541 for (const MachineOperand &MO : FaultingLoad->operands()) { in rewriteNullChecks()
545 if (!Reg || MBB->isLiveIn(Reg)) in rewriteNullChecks()
547 MBB->addLiveIn(Reg); in rewriteNullChecks()
551 for (auto &MO : DepMI->operands()) { in rewriteNullChecks()
554 if (!NC.getNotNullSucc()->isLiveIn(MO.getReg())) in rewriteNullChecks()
555 NC.getNotNullSucc()->addLiveIn(MO.getReg()); in rewriteNullChecks()
559 NC.getMemOperation()->eraseFromParent(); in rewriteNullChecks()
560 NC.getCheckOperation()->eraseFromParent(); in rewriteNullChecks()
562 // Insert an *unconditional* branch to not-null successor. in rewriteNullChecks()
563 TII->InsertBranch(*NC.getCheckBlock(), NC.getNotNullSucc(), nullptr, in rewriteNullChecks()
572 INITIALIZE_PASS_BEGIN(ImplicitNullChecks, "implicit-null-checks",
575 INITIALIZE_PASS_END(ImplicitNullChecks, "implicit-null-checks",