169fad079SSanjoy Das //===-- ImplicitNullChecks.cpp - Fold null checks into memory accesses ----===//
269fad079SSanjoy Das //
369fad079SSanjoy Das //                     The LLVM Compiler Infrastructure
469fad079SSanjoy Das //
569fad079SSanjoy Das // This file is distributed under the University of Illinois Open Source
669fad079SSanjoy Das // License. See LICENSE.TXT for details.
769fad079SSanjoy Das //
869fad079SSanjoy Das //===----------------------------------------------------------------------===//
969fad079SSanjoy Das //
1069fad079SSanjoy Das // This pass turns explicit null checks of the form
1169fad079SSanjoy Das //
1269fad079SSanjoy Das //   test %r10, %r10
1369fad079SSanjoy Das //   je throw_npe
1469fad079SSanjoy Das //   movl (%r10), %esi
1569fad079SSanjoy Das //   ...
1669fad079SSanjoy Das //
1769fad079SSanjoy Das // to
1869fad079SSanjoy Das //
1969fad079SSanjoy Das //   faulting_load_op("movl (%r10), %esi", throw_npe)
2069fad079SSanjoy Das //   ...
2169fad079SSanjoy Das //
2269fad079SSanjoy Das // With the help of a runtime that understands the .fault_maps section,
2369fad079SSanjoy Das // faulting_load_op branches to throw_npe if executing movl (%r10), %esi incurs
2469fad079SSanjoy Das // a page fault.
2569fad079SSanjoy Das //
2669fad079SSanjoy Das //===----------------------------------------------------------------------===//
2769fad079SSanjoy Das 
28b7718454SSanjoy Das #include "llvm/ADT/DenseSet.h"
2969fad079SSanjoy Das #include "llvm/ADT/SmallVector.h"
308ee6a30bSSanjoy Das #include "llvm/ADT/Statistic.h"
3169fad079SSanjoy Das #include "llvm/CodeGen/Passes.h"
3269fad079SSanjoy Das #include "llvm/CodeGen/MachineFunction.h"
33b7718454SSanjoy Das #include "llvm/CodeGen/MachineMemOperand.h"
3469fad079SSanjoy Das #include "llvm/CodeGen/MachineOperand.h"
3569fad079SSanjoy Das #include "llvm/CodeGen/MachineFunctionPass.h"
3669fad079SSanjoy Das #include "llvm/CodeGen/MachineInstrBuilder.h"
3769fad079SSanjoy Das #include "llvm/CodeGen/MachineRegisterInfo.h"
3869fad079SSanjoy Das #include "llvm/CodeGen/MachineModuleInfo.h"
3969fad079SSanjoy Das #include "llvm/IR/BasicBlock.h"
4069fad079SSanjoy Das #include "llvm/IR/Instruction.h"
4100038784SChen Li #include "llvm/IR/LLVMContext.h"
4269fad079SSanjoy Das #include "llvm/Support/CommandLine.h"
4369fad079SSanjoy Das #include "llvm/Support/Debug.h"
4469fad079SSanjoy Das #include "llvm/Target/TargetSubtargetInfo.h"
4569fad079SSanjoy Das #include "llvm/Target/TargetInstrInfo.h"
4669fad079SSanjoy Das 
4769fad079SSanjoy Das using namespace llvm;
4869fad079SSanjoy Das 
49c27a18f3SChad Rosier static cl::opt<int> PageSize("imp-null-check-page-size",
50c27a18f3SChad Rosier                              cl::desc("The page size of the target in bytes"),
5169fad079SSanjoy Das                              cl::init(4096));
5269fad079SSanjoy Das 
538ee6a30bSSanjoy Das #define DEBUG_TYPE "implicit-null-checks"
548ee6a30bSSanjoy Das 
558ee6a30bSSanjoy Das STATISTIC(NumImplicitNullChecks,
568ee6a30bSSanjoy Das           "Number of explicit null checks made implicit");
578ee6a30bSSanjoy Das 
5869fad079SSanjoy Das namespace {
5969fad079SSanjoy Das 
6069fad079SSanjoy Das class ImplicitNullChecks : public MachineFunctionPass {
6169fad079SSanjoy Das   /// Represents one null check that can be made implicit.
62*e173b9aeSSanjoy Das   class NullCheck {
6369fad079SSanjoy Das     // The memory operation the null check can be folded into.
6469fad079SSanjoy Das     MachineInstr *MemOperation;
6569fad079SSanjoy Das 
6669fad079SSanjoy Das     // The instruction actually doing the null check (Ptr != 0).
6769fad079SSanjoy Das     MachineInstr *CheckOperation;
6869fad079SSanjoy Das 
6969fad079SSanjoy Das     // The block the check resides in.
7069fad079SSanjoy Das     MachineBasicBlock *CheckBlock;
7169fad079SSanjoy Das 
72572e03a3SEric Christopher     // The block branched to if the pointer is non-null.
7369fad079SSanjoy Das     MachineBasicBlock *NotNullSucc;
7469fad079SSanjoy Das 
75572e03a3SEric Christopher     // The block branched to if the pointer is null.
7669fad079SSanjoy Das     MachineBasicBlock *NullSucc;
7769fad079SSanjoy Das 
78*e173b9aeSSanjoy Das   public:
7969fad079SSanjoy Das     explicit NullCheck(MachineInstr *memOperation, MachineInstr *checkOperation,
8069fad079SSanjoy Das                        MachineBasicBlock *checkBlock,
8169fad079SSanjoy Das                        MachineBasicBlock *notNullSucc,
8269fad079SSanjoy Das                        MachineBasicBlock *nullSucc)
8369fad079SSanjoy Das         : MemOperation(memOperation), CheckOperation(checkOperation),
8469fad079SSanjoy Das           CheckBlock(checkBlock), NotNullSucc(notNullSucc), NullSucc(nullSucc) {
8569fad079SSanjoy Das     }
86*e173b9aeSSanjoy Das 
87*e173b9aeSSanjoy Das     MachineInstr *getMemOperation() const { return MemOperation; }
88*e173b9aeSSanjoy Das 
89*e173b9aeSSanjoy Das     MachineInstr *getCheckOperation() const { return CheckOperation; }
90*e173b9aeSSanjoy Das 
91*e173b9aeSSanjoy Das     MachineBasicBlock *getCheckBlock() const { return CheckBlock; }
92*e173b9aeSSanjoy Das 
93*e173b9aeSSanjoy Das     MachineBasicBlock *getNotNullSucc() const { return NotNullSucc; }
94*e173b9aeSSanjoy Das 
95*e173b9aeSSanjoy Das     MachineBasicBlock *getNullSucc() const { return NullSucc; }
9669fad079SSanjoy Das   };
9769fad079SSanjoy Das 
9869fad079SSanjoy Das   const TargetInstrInfo *TII = nullptr;
9969fad079SSanjoy Das   const TargetRegisterInfo *TRI = nullptr;
10069fad079SSanjoy Das   MachineModuleInfo *MMI = nullptr;
10169fad079SSanjoy Das 
10269fad079SSanjoy Das   bool analyzeBlockForNullChecks(MachineBasicBlock &MBB,
10369fad079SSanjoy Das                                  SmallVectorImpl<NullCheck> &NullCheckList);
10469fad079SSanjoy Das   MachineInstr *insertFaultingLoad(MachineInstr *LoadMI, MachineBasicBlock *MBB,
1054e1d389aSQuentin Colombet                                    MachineBasicBlock *HandlerMBB);
10669fad079SSanjoy Das   void rewriteNullChecks(ArrayRef<NullCheck> NullCheckList);
10769fad079SSanjoy Das 
10869fad079SSanjoy Das public:
10969fad079SSanjoy Das   static char ID;
11069fad079SSanjoy Das 
11169fad079SSanjoy Das   ImplicitNullChecks() : MachineFunctionPass(ID) {
11269fad079SSanjoy Das     initializeImplicitNullChecksPass(*PassRegistry::getPassRegistry());
11369fad079SSanjoy Das   }
11469fad079SSanjoy Das 
11569fad079SSanjoy Das   bool runOnMachineFunction(MachineFunction &MF) override;
116ad154c83SDerek Schuff 
117ad154c83SDerek Schuff   MachineFunctionProperties getRequiredProperties() const override {
118ad154c83SDerek Schuff     return MachineFunctionProperties().set(
119ad154c83SDerek Schuff         MachineFunctionProperties::Property::AllVRegsAllocated);
120ad154c83SDerek Schuff   }
12169fad079SSanjoy Das };
122edc394f1SSanjoy Das 
123edc394f1SSanjoy Das /// \brief Detect re-ordering hazards and dependencies.
124edc394f1SSanjoy Das ///
125edc394f1SSanjoy Das /// This class keeps track of defs and uses, and can be queried if a given
126edc394f1SSanjoy Das /// machine instruction can be re-ordered from after the machine instructions
127edc394f1SSanjoy Das /// seen so far to before them.
128edc394f1SSanjoy Das class HazardDetector {
129edc394f1SSanjoy Das   DenseSet<unsigned> RegDefs;
130edc394f1SSanjoy Das   DenseSet<unsigned> RegUses;
131edc394f1SSanjoy Das   const TargetRegisterInfo &TRI;
132edc394f1SSanjoy Das   bool hasSeenClobber;
133edc394f1SSanjoy Das 
134edc394f1SSanjoy Das public:
135edc394f1SSanjoy Das   explicit HazardDetector(const TargetRegisterInfo &TRI) :
136edc394f1SSanjoy Das     TRI(TRI), hasSeenClobber(false) {}
137edc394f1SSanjoy Das 
138edc394f1SSanjoy Das   /// \brief Make a note of \p MI for later queries to isSafeToHoist.
139edc394f1SSanjoy Das   ///
140edc394f1SSanjoy Das   /// May clobber this HazardDetector instance.  \see isClobbered.
141edc394f1SSanjoy Das   void rememberInstruction(MachineInstr *MI);
142edc394f1SSanjoy Das 
143edc394f1SSanjoy Das   /// \brief Return true if it is safe to hoist \p MI from after all the
144edc394f1SSanjoy Das   /// instructions seen so far (via rememberInstruction) to before it.
145edc394f1SSanjoy Das   bool isSafeToHoist(MachineInstr *MI);
146edc394f1SSanjoy Das 
147edc394f1SSanjoy Das   /// \brief Return true if this instance of HazardDetector has been clobbered
148edc394f1SSanjoy Das   /// (i.e. has no more useful information).
149edc394f1SSanjoy Das   ///
150edc394f1SSanjoy Das   /// A HazardDetecter is clobbered when it sees a construct it cannot
151edc394f1SSanjoy Das   /// understand, and it would have to return a conservative answer for all
152edc394f1SSanjoy Das   /// future queries.  Having a separate clobbered state lets the client code
153edc394f1SSanjoy Das   /// bail early, without making queries about all of the future instructions
154edc394f1SSanjoy Das   /// (which would have returned the most conservative answer anyway).
155edc394f1SSanjoy Das   ///
156edc394f1SSanjoy Das   /// Calling rememberInstruction or isSafeToHoist on a clobbered HazardDetector
157edc394f1SSanjoy Das   /// is an error.
158edc394f1SSanjoy Das   bool isClobbered() { return hasSeenClobber; }
159edc394f1SSanjoy Das };
160edc394f1SSanjoy Das }
161edc394f1SSanjoy Das 
162edc394f1SSanjoy Das 
163edc394f1SSanjoy Das void HazardDetector::rememberInstruction(MachineInstr *MI) {
164edc394f1SSanjoy Das   assert(!isClobbered() &&
165edc394f1SSanjoy Das          "Don't add instructions to a clobbered hazard detector");
166edc394f1SSanjoy Das 
167edc394f1SSanjoy Das   if (MI->mayStore() || MI->hasUnmodeledSideEffects()) {
168edc394f1SSanjoy Das     hasSeenClobber = true;
169edc394f1SSanjoy Das     return;
170edc394f1SSanjoy Das   }
171edc394f1SSanjoy Das 
172edc394f1SSanjoy Das   for (auto *MMO : MI->memoperands()) {
173edc394f1SSanjoy Das     // Right now we don't want to worry about LLVM's memory model.
174edc394f1SSanjoy Das     if (!MMO->isUnordered()) {
175edc394f1SSanjoy Das       hasSeenClobber = true;
176edc394f1SSanjoy Das       return;
177edc394f1SSanjoy Das     }
178edc394f1SSanjoy Das   }
179edc394f1SSanjoy Das 
180edc394f1SSanjoy Das   for (auto &MO : MI->operands()) {
181edc394f1SSanjoy Das     if (!MO.isReg() || !MO.getReg())
182edc394f1SSanjoy Das       continue;
183edc394f1SSanjoy Das 
184edc394f1SSanjoy Das     if (MO.isDef())
185edc394f1SSanjoy Das       RegDefs.insert(MO.getReg());
186edc394f1SSanjoy Das     else
187edc394f1SSanjoy Das       RegUses.insert(MO.getReg());
188edc394f1SSanjoy Das   }
189edc394f1SSanjoy Das }
190edc394f1SSanjoy Das 
191edc394f1SSanjoy Das bool HazardDetector::isSafeToHoist(MachineInstr *MI) {
192edc394f1SSanjoy Das   assert(!isClobbered() && "isSafeToHoist cannot do anything useful!");
193edc394f1SSanjoy Das 
194edc394f1SSanjoy Das   // Right now we don't want to worry about LLVM's memory model.  This can be
195edc394f1SSanjoy Das   // made more precise later.
196edc394f1SSanjoy Das   for (auto *MMO : MI->memoperands())
197edc394f1SSanjoy Das     if (!MMO->isUnordered())
198edc394f1SSanjoy Das       return false;
199edc394f1SSanjoy Das 
200edc394f1SSanjoy Das   for (auto &MO : MI->operands()) {
201edc394f1SSanjoy Das     if (MO.isReg() && MO.getReg()) {
202edc394f1SSanjoy Das       for (unsigned Reg : RegDefs)
203edc394f1SSanjoy Das         if (TRI.regsOverlap(Reg, MO.getReg()))
204edc394f1SSanjoy Das           return false;  // We found a write-after-write or read-after-write
205edc394f1SSanjoy Das 
206edc394f1SSanjoy Das       if (MO.isDef())
207edc394f1SSanjoy Das         for (unsigned Reg : RegUses)
208edc394f1SSanjoy Das           if (TRI.regsOverlap(Reg, MO.getReg()))
209edc394f1SSanjoy Das             return false;  // We found a write-after-read
210edc394f1SSanjoy Das     }
211edc394f1SSanjoy Das   }
212edc394f1SSanjoy Das 
213edc394f1SSanjoy Das   return true;
214f00654e3SAlexander Kornienko }
21569fad079SSanjoy Das 
21669fad079SSanjoy Das bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) {
21769fad079SSanjoy Das   TII = MF.getSubtarget().getInstrInfo();
21869fad079SSanjoy Das   TRI = MF.getRegInfo().getTargetRegisterInfo();
21969fad079SSanjoy Das   MMI = &MF.getMMI();
22069fad079SSanjoy Das 
22169fad079SSanjoy Das   SmallVector<NullCheck, 16> NullCheckList;
22269fad079SSanjoy Das 
22369fad079SSanjoy Das   for (auto &MBB : MF)
22469fad079SSanjoy Das     analyzeBlockForNullChecks(MBB, NullCheckList);
22569fad079SSanjoy Das 
22669fad079SSanjoy Das   if (!NullCheckList.empty())
22769fad079SSanjoy Das     rewriteNullChecks(NullCheckList);
22869fad079SSanjoy Das 
22969fad079SSanjoy Das   return !NullCheckList.empty();
23069fad079SSanjoy Das }
23169fad079SSanjoy Das 
23269fad079SSanjoy Das /// Analyze MBB to check if its terminating branch can be turned into an
23369fad079SSanjoy Das /// implicit null check.  If yes, append a description of the said null check to
23469fad079SSanjoy Das /// NullCheckList and return true, else return false.
23569fad079SSanjoy Das bool ImplicitNullChecks::analyzeBlockForNullChecks(
23669fad079SSanjoy Das     MachineBasicBlock &MBB, SmallVectorImpl<NullCheck> &NullCheckList) {
23769fad079SSanjoy Das   typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate;
23869fad079SSanjoy Das 
239e8b81649SSanjoy Das   MDNode *BranchMD = nullptr;
240e8b81649SSanjoy Das   if (auto *BB = MBB.getBasicBlock())
241e8b81649SSanjoy Das     BranchMD = BB->getTerminator()->getMetadata(LLVMContext::MD_make_implicit);
242e8b81649SSanjoy Das 
2439c41a93eSSanjoy Das   if (!BranchMD)
2449c41a93eSSanjoy Das     return false;
2459c41a93eSSanjoy Das 
24669fad079SSanjoy Das   MachineBranchPredicate MBP;
24769fad079SSanjoy Das 
24869fad079SSanjoy Das   if (TII->AnalyzeBranchPredicate(MBB, MBP, true))
24969fad079SSanjoy Das     return false;
25069fad079SSanjoy Das 
25169fad079SSanjoy Das   // Is the predicate comparing an integer to zero?
25269fad079SSanjoy Das   if (!(MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 &&
25369fad079SSanjoy Das         (MBP.Predicate == MachineBranchPredicate::PRED_NE ||
25469fad079SSanjoy Das          MBP.Predicate == MachineBranchPredicate::PRED_EQ)))
25569fad079SSanjoy Das     return false;
25669fad079SSanjoy Das 
25769fad079SSanjoy Das   // If we cannot erase the test instruction itself, then making the null check
25869fad079SSanjoy Das   // implicit does not buy us much.
25969fad079SSanjoy Das   if (!MBP.SingleUseCondition)
26069fad079SSanjoy Das     return false;
26169fad079SSanjoy Das 
26269fad079SSanjoy Das   MachineBasicBlock *NotNullSucc, *NullSucc;
26369fad079SSanjoy Das 
26469fad079SSanjoy Das   if (MBP.Predicate == MachineBranchPredicate::PRED_NE) {
26569fad079SSanjoy Das     NotNullSucc = MBP.TrueDest;
26669fad079SSanjoy Das     NullSucc = MBP.FalseDest;
26769fad079SSanjoy Das   } else {
26869fad079SSanjoy Das     NotNullSucc = MBP.FalseDest;
26969fad079SSanjoy Das     NullSucc = MBP.TrueDest;
27069fad079SSanjoy Das   }
27169fad079SSanjoy Das 
27269fad079SSanjoy Das   // We handle the simplest case for now.  We can potentially do better by using
27369fad079SSanjoy Das   // the machine dominator tree.
27469fad079SSanjoy Das   if (NotNullSucc->pred_size() != 1)
27569fad079SSanjoy Das     return false;
27669fad079SSanjoy Das 
27769fad079SSanjoy Das   // Starting with a code fragment like:
27869fad079SSanjoy Das   //
27969fad079SSanjoy Das   //   test %RAX, %RAX
28069fad079SSanjoy Das   //   jne LblNotNull
28169fad079SSanjoy Das   //
28269fad079SSanjoy Das   //  LblNull:
28369fad079SSanjoy Das   //   callq throw_NullPointerException
28469fad079SSanjoy Das   //
28569fad079SSanjoy Das   //  LblNotNull:
286b7718454SSanjoy Das   //   Inst0
287b7718454SSanjoy Das   //   Inst1
288b7718454SSanjoy Das   //   ...
28969fad079SSanjoy Das   //   Def = Load (%RAX + <offset>)
29069fad079SSanjoy Das   //   ...
29169fad079SSanjoy Das   //
29269fad079SSanjoy Das   //
29369fad079SSanjoy Das   // we want to end up with
29469fad079SSanjoy Das   //
295ac9c5b19SSanjoy Das   //   Def = FaultingLoad (%RAX + <offset>), LblNull
29669fad079SSanjoy Das   //   jmp LblNotNull ;; explicit or fallthrough
29769fad079SSanjoy Das   //
29869fad079SSanjoy Das   //  LblNotNull:
299b7718454SSanjoy Das   //   Inst0
300b7718454SSanjoy Das   //   Inst1
30169fad079SSanjoy Das   //   ...
30269fad079SSanjoy Das   //
30369fad079SSanjoy Das   //  LblNull:
30469fad079SSanjoy Das   //   callq throw_NullPointerException
30569fad079SSanjoy Das   //
306ac9c5b19SSanjoy Das   //
307ac9c5b19SSanjoy Das   // To see why this is legal, consider the two possibilities:
308ac9c5b19SSanjoy Das   //
309ac9c5b19SSanjoy Das   //  1. %RAX is null: since we constrain <offset> to be less than PageSize, the
310ac9c5b19SSanjoy Das   //     load instruction dereferences the null page, causing a segmentation
311ac9c5b19SSanjoy Das   //     fault.
312ac9c5b19SSanjoy Das   //
313ac9c5b19SSanjoy Das   //  2. %RAX is not null: in this case we know that the load cannot fault, as
314ac9c5b19SSanjoy Das   //     otherwise the load would've faulted in the original program too and the
315ac9c5b19SSanjoy Das   //     original program would've been undefined.
316ac9c5b19SSanjoy Das   //
317ac9c5b19SSanjoy Das   // This reasoning cannot be extended to justify hoisting through arbitrary
318ac9c5b19SSanjoy Das   // control flow.  For instance, in the example below (in pseudo-C)
319ac9c5b19SSanjoy Das   //
320ac9c5b19SSanjoy Das   //    if (ptr == null) { throw_npe(); unreachable; }
321ac9c5b19SSanjoy Das   //    if (some_cond) { return 42; }
322ac9c5b19SSanjoy Das   //    v = ptr->field;  // LD
323ac9c5b19SSanjoy Das   //    ...
324ac9c5b19SSanjoy Das   //
325ac9c5b19SSanjoy Das   // we cannot (without code duplication) use the load marked "LD" to null check
326ac9c5b19SSanjoy Das   // ptr -- clause (2) above does not apply in this case.  In the above program
327ac9c5b19SSanjoy Das   // the safety of ptr->field can be dependent on some_cond; and, for instance,
328ac9c5b19SSanjoy Das   // ptr could be some non-null invalid reference that never gets loaded from
329ac9c5b19SSanjoy Das   // because some_cond is always true.
33069fad079SSanjoy Das 
33169fad079SSanjoy Das   unsigned PointerReg = MBP.LHS.getReg();
332b7718454SSanjoy Das 
333edc394f1SSanjoy Das   HazardDetector HD(*TRI);
334b7718454SSanjoy Das 
335b7718454SSanjoy Das   for (auto MII = NotNullSucc->begin(), MIE = NotNullSucc->end(); MII != MIE;
336b7718454SSanjoy Das        ++MII) {
337b7718454SSanjoy Das     MachineInstr *MI = &*MII;
338c27a18f3SChad Rosier     unsigned BaseReg;
339c27a18f3SChad Rosier     int64_t Offset;
340b7718454SSanjoy Das     if (TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI))
341b7718454SSanjoy Das       if (MI->mayLoad() && !MI->isPredicable() && BaseReg == PointerReg &&
34293d608c3SSanjoy Das           Offset < PageSize && MI->getDesc().getNumDefs() <= 1 &&
343edc394f1SSanjoy Das           HD.isSafeToHoist(MI)) {
344b7718454SSanjoy Das         NullCheckList.emplace_back(MI, MBP.ConditionDef, &MBB, NotNullSucc,
34569fad079SSanjoy Das                                    NullSucc);
34669fad079SSanjoy Das         return true;
34769fad079SSanjoy Das       }
34869fad079SSanjoy Das 
349edc394f1SSanjoy Das     HD.rememberInstruction(MI);
350edc394f1SSanjoy Das     if (HD.isClobbered())
351b7718454SSanjoy Das       return false;
352b7718454SSanjoy Das   }
353b7718454SSanjoy Das 
35469fad079SSanjoy Das   return false;
35569fad079SSanjoy Das }
35669fad079SSanjoy Das 
35769fad079SSanjoy Das /// Wrap a machine load instruction, LoadMI, into a FAULTING_LOAD_OP machine
35869fad079SSanjoy Das /// instruction.  The FAULTING_LOAD_OP instruction does the same load as LoadMI
3594e1d389aSQuentin Colombet /// (defining the same register), and branches to HandlerMBB if the load
36069fad079SSanjoy Das /// faults.  The FAULTING_LOAD_OP instruction is inserted at the end of MBB.
3614e1d389aSQuentin Colombet MachineInstr *
3624e1d389aSQuentin Colombet ImplicitNullChecks::insertFaultingLoad(MachineInstr *LoadMI,
36369fad079SSanjoy Das                                        MachineBasicBlock *MBB,
3644e1d389aSQuentin Colombet                                        MachineBasicBlock *HandlerMBB) {
36593d608c3SSanjoy Das   const unsigned NoRegister = 0; // Guaranteed to be the NoRegister value for
36693d608c3SSanjoy Das                                  // all targets.
36793d608c3SSanjoy Das 
36869fad079SSanjoy Das   DebugLoc DL;
36969fad079SSanjoy Das   unsigned NumDefs = LoadMI->getDesc().getNumDefs();
37093d608c3SSanjoy Das   assert(NumDefs <= 1 && "other cases unhandled!");
37169fad079SSanjoy Das 
37293d608c3SSanjoy Das   unsigned DefReg = NoRegister;
37393d608c3SSanjoy Das   if (NumDefs != 0) {
37493d608c3SSanjoy Das     DefReg = LoadMI->defs().begin()->getReg();
37569fad079SSanjoy Das     assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 &&
37669fad079SSanjoy Das            "expected exactly one def!");
37793d608c3SSanjoy Das   }
37869fad079SSanjoy Das 
37969fad079SSanjoy Das   auto MIB = BuildMI(MBB, DL, TII->get(TargetOpcode::FAULTING_LOAD_OP), DefReg)
3804e1d389aSQuentin Colombet                  .addMBB(HandlerMBB)
38169fad079SSanjoy Das                  .addImm(LoadMI->getOpcode());
38269fad079SSanjoy Das 
38369fad079SSanjoy Das   for (auto &MO : LoadMI->uses())
38469fad079SSanjoy Das     MIB.addOperand(MO);
38569fad079SSanjoy Das 
38669fad079SSanjoy Das   MIB.setMemRefs(LoadMI->memoperands_begin(), LoadMI->memoperands_end());
38769fad079SSanjoy Das 
38869fad079SSanjoy Das   return MIB;
38969fad079SSanjoy Das }
39069fad079SSanjoy Das 
39169fad079SSanjoy Das /// Rewrite the null checks in NullCheckList into implicit null checks.
39269fad079SSanjoy Das void ImplicitNullChecks::rewriteNullChecks(
39369fad079SSanjoy Das     ArrayRef<ImplicitNullChecks::NullCheck> NullCheckList) {
39469fad079SSanjoy Das   DebugLoc DL;
39569fad079SSanjoy Das 
39669fad079SSanjoy Das   for (auto &NC : NullCheckList) {
39769fad079SSanjoy Das     // Remove the conditional branch dependent on the null check.
398*e173b9aeSSanjoy Das     unsigned BranchesRemoved = TII->RemoveBranch(*NC.getCheckBlock());
39969fad079SSanjoy Das     (void)BranchesRemoved;
40069fad079SSanjoy Das     assert(BranchesRemoved > 0 && "expected at least one branch!");
40169fad079SSanjoy Das 
40269fad079SSanjoy Das     // Insert a faulting load where the conditional branch was originally.  We
40369fad079SSanjoy Das     // check earlier ensures that this bit of code motion is legal.  We do not
40469fad079SSanjoy Das     // touch the successors list for any basic block since we haven't changed
40569fad079SSanjoy Das     // control flow, we've just made it implicit.
406*e173b9aeSSanjoy Das     MachineInstr *FaultingLoad = insertFaultingLoad(
407*e173b9aeSSanjoy Das         NC.getMemOperation(), NC.getCheckBlock(), NC.getNullSucc());
40826dab3a4SQuentin Colombet     // Now the values defined by MemOperation, if any, are live-in of
40926dab3a4SQuentin Colombet     // the block of MemOperation.
41026dab3a4SQuentin Colombet     // The original load operation may define implicit-defs alongside
41126dab3a4SQuentin Colombet     // the loaded value.
412*e173b9aeSSanjoy Das     MachineBasicBlock *MBB = NC.getMemOperation()->getParent();
41326dab3a4SQuentin Colombet     for (const MachineOperand &MO : FaultingLoad->operands()) {
41426dab3a4SQuentin Colombet       if (!MO.isReg() || !MO.isDef())
41526dab3a4SQuentin Colombet         continue;
41626dab3a4SQuentin Colombet       unsigned Reg = MO.getReg();
41726dab3a4SQuentin Colombet       if (!Reg || MBB->isLiveIn(Reg))
41826dab3a4SQuentin Colombet         continue;
41912b69919SQuentin Colombet       MBB->addLiveIn(Reg);
42012b69919SQuentin Colombet     }
421*e173b9aeSSanjoy Das     NC.getMemOperation()->eraseFromParent();
422*e173b9aeSSanjoy Das     NC.getCheckOperation()->eraseFromParent();
42369fad079SSanjoy Das 
42469fad079SSanjoy Das     // Insert an *unconditional* branch to not-null successor.
425*e173b9aeSSanjoy Das     TII->InsertBranch(*NC.getCheckBlock(), NC.getNotNullSucc(), nullptr,
426*e173b9aeSSanjoy Das                       /*Cond=*/None, DL);
42769fad079SSanjoy Das 
4288ee6a30bSSanjoy Das     NumImplicitNullChecks++;
42969fad079SSanjoy Das   }
43069fad079SSanjoy Das }
43169fad079SSanjoy Das 
43269fad079SSanjoy Das char ImplicitNullChecks::ID = 0;
43369fad079SSanjoy Das char &llvm::ImplicitNullChecksID = ImplicitNullChecks::ID;
43469fad079SSanjoy Das INITIALIZE_PASS_BEGIN(ImplicitNullChecks, "implicit-null-checks",
43569fad079SSanjoy Das                       "Implicit null checks", false, false)
43669fad079SSanjoy Das INITIALIZE_PASS_END(ImplicitNullChecks, "implicit-null-checks",
43769fad079SSanjoy Das                     "Implicit null checks", false, false)
438