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.
6269fad079SSanjoy Das   struct 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 
7869fad079SSanjoy Das     NullCheck()
7969fad079SSanjoy Das         : MemOperation(), CheckOperation(), CheckBlock(), NotNullSucc(),
8069fad079SSanjoy Das           NullSucc() {}
8169fad079SSanjoy Das 
8269fad079SSanjoy Das     explicit NullCheck(MachineInstr *memOperation, MachineInstr *checkOperation,
8369fad079SSanjoy Das                        MachineBasicBlock *checkBlock,
8469fad079SSanjoy Das                        MachineBasicBlock *notNullSucc,
8569fad079SSanjoy Das                        MachineBasicBlock *nullSucc)
8669fad079SSanjoy Das         : MemOperation(memOperation), CheckOperation(checkOperation),
8769fad079SSanjoy Das           CheckBlock(checkBlock), NotNullSucc(notNullSucc), NullSucc(nullSucc) {
8869fad079SSanjoy Das     }
8969fad079SSanjoy Das   };
9069fad079SSanjoy Das 
9169fad079SSanjoy Das   const TargetInstrInfo *TII = nullptr;
9269fad079SSanjoy Das   const TargetRegisterInfo *TRI = nullptr;
9369fad079SSanjoy Das   MachineModuleInfo *MMI = nullptr;
9469fad079SSanjoy Das 
9569fad079SSanjoy Das   bool analyzeBlockForNullChecks(MachineBasicBlock &MBB,
9669fad079SSanjoy Das                                  SmallVectorImpl<NullCheck> &NullCheckList);
9769fad079SSanjoy Das   MachineInstr *insertFaultingLoad(MachineInstr *LoadMI, MachineBasicBlock *MBB,
98*4e1d389aSQuentin Colombet                                    MachineBasicBlock *HandlerMBB);
9969fad079SSanjoy Das   void rewriteNullChecks(ArrayRef<NullCheck> NullCheckList);
10069fad079SSanjoy Das 
10169fad079SSanjoy Das public:
10269fad079SSanjoy Das   static char ID;
10369fad079SSanjoy Das 
10469fad079SSanjoy Das   ImplicitNullChecks() : MachineFunctionPass(ID) {
10569fad079SSanjoy Das     initializeImplicitNullChecksPass(*PassRegistry::getPassRegistry());
10669fad079SSanjoy Das   }
10769fad079SSanjoy Das 
10869fad079SSanjoy Das   bool runOnMachineFunction(MachineFunction &MF) override;
109ad154c83SDerek Schuff 
110ad154c83SDerek Schuff   MachineFunctionProperties getRequiredProperties() const override {
111ad154c83SDerek Schuff     return MachineFunctionProperties().set(
112ad154c83SDerek Schuff         MachineFunctionProperties::Property::AllVRegsAllocated);
113ad154c83SDerek Schuff   }
11469fad079SSanjoy Das };
115edc394f1SSanjoy Das 
116edc394f1SSanjoy Das /// \brief Detect re-ordering hazards and dependencies.
117edc394f1SSanjoy Das ///
118edc394f1SSanjoy Das /// This class keeps track of defs and uses, and can be queried if a given
119edc394f1SSanjoy Das /// machine instruction can be re-ordered from after the machine instructions
120edc394f1SSanjoy Das /// seen so far to before them.
121edc394f1SSanjoy Das class HazardDetector {
122edc394f1SSanjoy Das   DenseSet<unsigned> RegDefs;
123edc394f1SSanjoy Das   DenseSet<unsigned> RegUses;
124edc394f1SSanjoy Das   const TargetRegisterInfo &TRI;
125edc394f1SSanjoy Das   bool hasSeenClobber;
126edc394f1SSanjoy Das 
127edc394f1SSanjoy Das public:
128edc394f1SSanjoy Das   explicit HazardDetector(const TargetRegisterInfo &TRI) :
129edc394f1SSanjoy Das     TRI(TRI), hasSeenClobber(false) {}
130edc394f1SSanjoy Das 
131edc394f1SSanjoy Das   /// \brief Make a note of \p MI for later queries to isSafeToHoist.
132edc394f1SSanjoy Das   ///
133edc394f1SSanjoy Das   /// May clobber this HazardDetector instance.  \see isClobbered.
134edc394f1SSanjoy Das   void rememberInstruction(MachineInstr *MI);
135edc394f1SSanjoy Das 
136edc394f1SSanjoy Das   /// \brief Return true if it is safe to hoist \p MI from after all the
137edc394f1SSanjoy Das   /// instructions seen so far (via rememberInstruction) to before it.
138edc394f1SSanjoy Das   bool isSafeToHoist(MachineInstr *MI);
139edc394f1SSanjoy Das 
140edc394f1SSanjoy Das   /// \brief Return true if this instance of HazardDetector has been clobbered
141edc394f1SSanjoy Das   /// (i.e. has no more useful information).
142edc394f1SSanjoy Das   ///
143edc394f1SSanjoy Das   /// A HazardDetecter is clobbered when it sees a construct it cannot
144edc394f1SSanjoy Das   /// understand, and it would have to return a conservative answer for all
145edc394f1SSanjoy Das   /// future queries.  Having a separate clobbered state lets the client code
146edc394f1SSanjoy Das   /// bail early, without making queries about all of the future instructions
147edc394f1SSanjoy Das   /// (which would have returned the most conservative answer anyway).
148edc394f1SSanjoy Das   ///
149edc394f1SSanjoy Das   /// Calling rememberInstruction or isSafeToHoist on a clobbered HazardDetector
150edc394f1SSanjoy Das   /// is an error.
151edc394f1SSanjoy Das   bool isClobbered() { return hasSeenClobber; }
152edc394f1SSanjoy Das };
153edc394f1SSanjoy Das }
154edc394f1SSanjoy Das 
155edc394f1SSanjoy Das 
156edc394f1SSanjoy Das void HazardDetector::rememberInstruction(MachineInstr *MI) {
157edc394f1SSanjoy Das   assert(!isClobbered() &&
158edc394f1SSanjoy Das          "Don't add instructions to a clobbered hazard detector");
159edc394f1SSanjoy Das 
160edc394f1SSanjoy Das   if (MI->mayStore() || MI->hasUnmodeledSideEffects()) {
161edc394f1SSanjoy Das     hasSeenClobber = true;
162edc394f1SSanjoy Das     return;
163edc394f1SSanjoy Das   }
164edc394f1SSanjoy Das 
165edc394f1SSanjoy Das   for (auto *MMO : MI->memoperands()) {
166edc394f1SSanjoy Das     // Right now we don't want to worry about LLVM's memory model.
167edc394f1SSanjoy Das     if (!MMO->isUnordered()) {
168edc394f1SSanjoy Das       hasSeenClobber = true;
169edc394f1SSanjoy Das       return;
170edc394f1SSanjoy Das     }
171edc394f1SSanjoy Das   }
172edc394f1SSanjoy Das 
173edc394f1SSanjoy Das   for (auto &MO : MI->operands()) {
174edc394f1SSanjoy Das     if (!MO.isReg() || !MO.getReg())
175edc394f1SSanjoy Das       continue;
176edc394f1SSanjoy Das 
177edc394f1SSanjoy Das     if (MO.isDef())
178edc394f1SSanjoy Das       RegDefs.insert(MO.getReg());
179edc394f1SSanjoy Das     else
180edc394f1SSanjoy Das       RegUses.insert(MO.getReg());
181edc394f1SSanjoy Das   }
182edc394f1SSanjoy Das }
183edc394f1SSanjoy Das 
184edc394f1SSanjoy Das bool HazardDetector::isSafeToHoist(MachineInstr *MI) {
185edc394f1SSanjoy Das   assert(!isClobbered() && "isSafeToHoist cannot do anything useful!");
186edc394f1SSanjoy Das 
187edc394f1SSanjoy Das   // Right now we don't want to worry about LLVM's memory model.  This can be
188edc394f1SSanjoy Das   // made more precise later.
189edc394f1SSanjoy Das   for (auto *MMO : MI->memoperands())
190edc394f1SSanjoy Das     if (!MMO->isUnordered())
191edc394f1SSanjoy Das       return false;
192edc394f1SSanjoy Das 
193edc394f1SSanjoy Das   for (auto &MO : MI->operands()) {
194edc394f1SSanjoy Das     if (MO.isReg() && MO.getReg()) {
195edc394f1SSanjoy Das       for (unsigned Reg : RegDefs)
196edc394f1SSanjoy Das         if (TRI.regsOverlap(Reg, MO.getReg()))
197edc394f1SSanjoy Das           return false;  // We found a write-after-write or read-after-write
198edc394f1SSanjoy Das 
199edc394f1SSanjoy Das       if (MO.isDef())
200edc394f1SSanjoy Das         for (unsigned Reg : RegUses)
201edc394f1SSanjoy Das           if (TRI.regsOverlap(Reg, MO.getReg()))
202edc394f1SSanjoy Das             return false;  // We found a write-after-read
203edc394f1SSanjoy Das     }
204edc394f1SSanjoy Das   }
205edc394f1SSanjoy Das 
206edc394f1SSanjoy Das   return true;
207f00654e3SAlexander Kornienko }
20869fad079SSanjoy Das 
20969fad079SSanjoy Das bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) {
21069fad079SSanjoy Das   TII = MF.getSubtarget().getInstrInfo();
21169fad079SSanjoy Das   TRI = MF.getRegInfo().getTargetRegisterInfo();
21269fad079SSanjoy Das   MMI = &MF.getMMI();
21369fad079SSanjoy Das 
21469fad079SSanjoy Das   SmallVector<NullCheck, 16> NullCheckList;
21569fad079SSanjoy Das 
21669fad079SSanjoy Das   for (auto &MBB : MF)
21769fad079SSanjoy Das     analyzeBlockForNullChecks(MBB, NullCheckList);
21869fad079SSanjoy Das 
21969fad079SSanjoy Das   if (!NullCheckList.empty())
22069fad079SSanjoy Das     rewriteNullChecks(NullCheckList);
22169fad079SSanjoy Das 
22269fad079SSanjoy Das   return !NullCheckList.empty();
22369fad079SSanjoy Das }
22469fad079SSanjoy Das 
22569fad079SSanjoy Das /// Analyze MBB to check if its terminating branch can be turned into an
22669fad079SSanjoy Das /// implicit null check.  If yes, append a description of the said null check to
22769fad079SSanjoy Das /// NullCheckList and return true, else return false.
22869fad079SSanjoy Das bool ImplicitNullChecks::analyzeBlockForNullChecks(
22969fad079SSanjoy Das     MachineBasicBlock &MBB, SmallVectorImpl<NullCheck> &NullCheckList) {
23069fad079SSanjoy Das   typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate;
23169fad079SSanjoy Das 
232e8b81649SSanjoy Das   MDNode *BranchMD = nullptr;
233e8b81649SSanjoy Das   if (auto *BB = MBB.getBasicBlock())
234e8b81649SSanjoy Das     BranchMD = BB->getTerminator()->getMetadata(LLVMContext::MD_make_implicit);
235e8b81649SSanjoy Das 
2369c41a93eSSanjoy Das   if (!BranchMD)
2379c41a93eSSanjoy Das     return false;
2389c41a93eSSanjoy Das 
23969fad079SSanjoy Das   MachineBranchPredicate MBP;
24069fad079SSanjoy Das 
24169fad079SSanjoy Das   if (TII->AnalyzeBranchPredicate(MBB, MBP, true))
24269fad079SSanjoy Das     return false;
24369fad079SSanjoy Das 
24469fad079SSanjoy Das   // Is the predicate comparing an integer to zero?
24569fad079SSanjoy Das   if (!(MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 &&
24669fad079SSanjoy Das         (MBP.Predicate == MachineBranchPredicate::PRED_NE ||
24769fad079SSanjoy Das          MBP.Predicate == MachineBranchPredicate::PRED_EQ)))
24869fad079SSanjoy Das     return false;
24969fad079SSanjoy Das 
25069fad079SSanjoy Das   // If we cannot erase the test instruction itself, then making the null check
25169fad079SSanjoy Das   // implicit does not buy us much.
25269fad079SSanjoy Das   if (!MBP.SingleUseCondition)
25369fad079SSanjoy Das     return false;
25469fad079SSanjoy Das 
25569fad079SSanjoy Das   MachineBasicBlock *NotNullSucc, *NullSucc;
25669fad079SSanjoy Das 
25769fad079SSanjoy Das   if (MBP.Predicate == MachineBranchPredicate::PRED_NE) {
25869fad079SSanjoy Das     NotNullSucc = MBP.TrueDest;
25969fad079SSanjoy Das     NullSucc = MBP.FalseDest;
26069fad079SSanjoy Das   } else {
26169fad079SSanjoy Das     NotNullSucc = MBP.FalseDest;
26269fad079SSanjoy Das     NullSucc = MBP.TrueDest;
26369fad079SSanjoy Das   }
26469fad079SSanjoy Das 
26569fad079SSanjoy Das   // We handle the simplest case for now.  We can potentially do better by using
26669fad079SSanjoy Das   // the machine dominator tree.
26769fad079SSanjoy Das   if (NotNullSucc->pred_size() != 1)
26869fad079SSanjoy Das     return false;
26969fad079SSanjoy Das 
27069fad079SSanjoy Das   // Starting with a code fragment like:
27169fad079SSanjoy Das   //
27269fad079SSanjoy Das   //   test %RAX, %RAX
27369fad079SSanjoy Das   //   jne LblNotNull
27469fad079SSanjoy Das   //
27569fad079SSanjoy Das   //  LblNull:
27669fad079SSanjoy Das   //   callq throw_NullPointerException
27769fad079SSanjoy Das   //
27869fad079SSanjoy Das   //  LblNotNull:
279b7718454SSanjoy Das   //   Inst0
280b7718454SSanjoy Das   //   Inst1
281b7718454SSanjoy Das   //   ...
28269fad079SSanjoy Das   //   Def = Load (%RAX + <offset>)
28369fad079SSanjoy Das   //   ...
28469fad079SSanjoy Das   //
28569fad079SSanjoy Das   //
28669fad079SSanjoy Das   // we want to end up with
28769fad079SSanjoy Das   //
288ac9c5b19SSanjoy Das   //   Def = FaultingLoad (%RAX + <offset>), LblNull
28969fad079SSanjoy Das   //   jmp LblNotNull ;; explicit or fallthrough
29069fad079SSanjoy Das   //
29169fad079SSanjoy Das   //  LblNotNull:
292b7718454SSanjoy Das   //   Inst0
293b7718454SSanjoy Das   //   Inst1
29469fad079SSanjoy Das   //   ...
29569fad079SSanjoy Das   //
29669fad079SSanjoy Das   //  LblNull:
29769fad079SSanjoy Das   //   callq throw_NullPointerException
29869fad079SSanjoy Das   //
299ac9c5b19SSanjoy Das   //
300ac9c5b19SSanjoy Das   // To see why this is legal, consider the two possibilities:
301ac9c5b19SSanjoy Das   //
302ac9c5b19SSanjoy Das   //  1. %RAX is null: since we constrain <offset> to be less than PageSize, the
303ac9c5b19SSanjoy Das   //     load instruction dereferences the null page, causing a segmentation
304ac9c5b19SSanjoy Das   //     fault.
305ac9c5b19SSanjoy Das   //
306ac9c5b19SSanjoy Das   //  2. %RAX is not null: in this case we know that the load cannot fault, as
307ac9c5b19SSanjoy Das   //     otherwise the load would've faulted in the original program too and the
308ac9c5b19SSanjoy Das   //     original program would've been undefined.
309ac9c5b19SSanjoy Das   //
310ac9c5b19SSanjoy Das   // This reasoning cannot be extended to justify hoisting through arbitrary
311ac9c5b19SSanjoy Das   // control flow.  For instance, in the example below (in pseudo-C)
312ac9c5b19SSanjoy Das   //
313ac9c5b19SSanjoy Das   //    if (ptr == null) { throw_npe(); unreachable; }
314ac9c5b19SSanjoy Das   //    if (some_cond) { return 42; }
315ac9c5b19SSanjoy Das   //    v = ptr->field;  // LD
316ac9c5b19SSanjoy Das   //    ...
317ac9c5b19SSanjoy Das   //
318ac9c5b19SSanjoy Das   // we cannot (without code duplication) use the load marked "LD" to null check
319ac9c5b19SSanjoy Das   // ptr -- clause (2) above does not apply in this case.  In the above program
320ac9c5b19SSanjoy Das   // the safety of ptr->field can be dependent on some_cond; and, for instance,
321ac9c5b19SSanjoy Das   // ptr could be some non-null invalid reference that never gets loaded from
322ac9c5b19SSanjoy Das   // because some_cond is always true.
32369fad079SSanjoy Das 
32469fad079SSanjoy Das   unsigned PointerReg = MBP.LHS.getReg();
325b7718454SSanjoy Das 
326edc394f1SSanjoy Das   HazardDetector HD(*TRI);
327b7718454SSanjoy Das 
328b7718454SSanjoy Das   for (auto MII = NotNullSucc->begin(), MIE = NotNullSucc->end(); MII != MIE;
329b7718454SSanjoy Das        ++MII) {
330b7718454SSanjoy Das     MachineInstr *MI = &*MII;
331c27a18f3SChad Rosier     unsigned BaseReg;
332c27a18f3SChad Rosier     int64_t Offset;
333b7718454SSanjoy Das     if (TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI))
334b7718454SSanjoy Das       if (MI->mayLoad() && !MI->isPredicable() && BaseReg == PointerReg &&
33593d608c3SSanjoy Das           Offset < PageSize && MI->getDesc().getNumDefs() <= 1 &&
336edc394f1SSanjoy Das           HD.isSafeToHoist(MI)) {
337b7718454SSanjoy Das         NullCheckList.emplace_back(MI, MBP.ConditionDef, &MBB, NotNullSucc,
33869fad079SSanjoy Das                                    NullSucc);
33969fad079SSanjoy Das         return true;
34069fad079SSanjoy Das       }
34169fad079SSanjoy Das 
342edc394f1SSanjoy Das     HD.rememberInstruction(MI);
343edc394f1SSanjoy Das     if (HD.isClobbered())
344b7718454SSanjoy Das       return false;
345b7718454SSanjoy Das   }
346b7718454SSanjoy Das 
34769fad079SSanjoy Das   return false;
34869fad079SSanjoy Das }
34969fad079SSanjoy Das 
35069fad079SSanjoy Das /// Wrap a machine load instruction, LoadMI, into a FAULTING_LOAD_OP machine
35169fad079SSanjoy Das /// instruction.  The FAULTING_LOAD_OP instruction does the same load as LoadMI
352*4e1d389aSQuentin Colombet /// (defining the same register), and branches to HandlerMBB if the load
35369fad079SSanjoy Das /// faults.  The FAULTING_LOAD_OP instruction is inserted at the end of MBB.
354*4e1d389aSQuentin Colombet MachineInstr *
355*4e1d389aSQuentin Colombet ImplicitNullChecks::insertFaultingLoad(MachineInstr *LoadMI,
35669fad079SSanjoy Das                                        MachineBasicBlock *MBB,
357*4e1d389aSQuentin Colombet                                        MachineBasicBlock *HandlerMBB) {
35893d608c3SSanjoy Das   const unsigned NoRegister = 0; // Guaranteed to be the NoRegister value for
35993d608c3SSanjoy Das                                  // all targets.
36093d608c3SSanjoy Das 
36169fad079SSanjoy Das   DebugLoc DL;
36269fad079SSanjoy Das   unsigned NumDefs = LoadMI->getDesc().getNumDefs();
36393d608c3SSanjoy Das   assert(NumDefs <= 1 && "other cases unhandled!");
36469fad079SSanjoy Das 
36593d608c3SSanjoy Das   unsigned DefReg = NoRegister;
36693d608c3SSanjoy Das   if (NumDefs != 0) {
36793d608c3SSanjoy Das     DefReg = LoadMI->defs().begin()->getReg();
36869fad079SSanjoy Das     assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 &&
36969fad079SSanjoy Das            "expected exactly one def!");
37093d608c3SSanjoy Das   }
37169fad079SSanjoy Das 
37269fad079SSanjoy Das   auto MIB = BuildMI(MBB, DL, TII->get(TargetOpcode::FAULTING_LOAD_OP), DefReg)
373*4e1d389aSQuentin Colombet                  .addMBB(HandlerMBB)
37469fad079SSanjoy Das                  .addImm(LoadMI->getOpcode());
37569fad079SSanjoy Das 
37669fad079SSanjoy Das   for (auto &MO : LoadMI->uses())
37769fad079SSanjoy Das     MIB.addOperand(MO);
37869fad079SSanjoy Das 
37969fad079SSanjoy Das   MIB.setMemRefs(LoadMI->memoperands_begin(), LoadMI->memoperands_end());
38069fad079SSanjoy Das 
38169fad079SSanjoy Das   return MIB;
38269fad079SSanjoy Das }
38369fad079SSanjoy Das 
38469fad079SSanjoy Das /// Rewrite the null checks in NullCheckList into implicit null checks.
38569fad079SSanjoy Das void ImplicitNullChecks::rewriteNullChecks(
38669fad079SSanjoy Das     ArrayRef<ImplicitNullChecks::NullCheck> NullCheckList) {
38769fad079SSanjoy Das   DebugLoc DL;
38869fad079SSanjoy Das 
38969fad079SSanjoy Das   for (auto &NC : NullCheckList) {
39069fad079SSanjoy Das     // Remove the conditional branch dependent on the null check.
39169fad079SSanjoy Das     unsigned BranchesRemoved = TII->RemoveBranch(*NC.CheckBlock);
39269fad079SSanjoy Das     (void)BranchesRemoved;
39369fad079SSanjoy Das     assert(BranchesRemoved > 0 && "expected at least one branch!");
39469fad079SSanjoy Das 
39569fad079SSanjoy Das     // Insert a faulting load where the conditional branch was originally.  We
39669fad079SSanjoy Das     // check earlier ensures that this bit of code motion is legal.  We do not
39769fad079SSanjoy Das     // touch the successors list for any basic block since we haven't changed
39869fad079SSanjoy Das     // control flow, we've just made it implicit.
39912b69919SQuentin Colombet     MachineInstr *FaultingLoad =
400*4e1d389aSQuentin Colombet         insertFaultingLoad(NC.MemOperation, NC.CheckBlock, NC.NullSucc);
40112b69919SQuentin Colombet     // Now the value of the MemOperation, if any, is live-in of block
40212b69919SQuentin Colombet     // of MemOperation.
40312b69919SQuentin Colombet     unsigned Reg = FaultingLoad->getOperand(0).getReg();
40412b69919SQuentin Colombet     if (Reg) {
40512b69919SQuentin Colombet       MachineBasicBlock *MBB = NC.MemOperation->getParent();
40612b69919SQuentin Colombet       if (!MBB->isLiveIn(Reg))
40712b69919SQuentin Colombet         MBB->addLiveIn(Reg);
40812b69919SQuentin Colombet     }
409c3a8e398SSanjoy Das     NC.MemOperation->eraseFromParent();
41069fad079SSanjoy Das     NC.CheckOperation->eraseFromParent();
41169fad079SSanjoy Das 
41269fad079SSanjoy Das     // Insert an *unconditional* branch to not-null successor.
41369fad079SSanjoy Das     TII->InsertBranch(*NC.CheckBlock, NC.NotNullSucc, nullptr, /*Cond=*/None,
41469fad079SSanjoy Das                       DL);
41569fad079SSanjoy Das 
4168ee6a30bSSanjoy Das     NumImplicitNullChecks++;
41769fad079SSanjoy Das   }
41869fad079SSanjoy Das }
41969fad079SSanjoy Das 
42069fad079SSanjoy Das char ImplicitNullChecks::ID = 0;
42169fad079SSanjoy Das char &llvm::ImplicitNullChecksID = ImplicitNullChecks::ID;
42269fad079SSanjoy Das INITIALIZE_PASS_BEGIN(ImplicitNullChecks, "implicit-null-checks",
42369fad079SSanjoy Das                       "Implicit null checks", false, false)
42469fad079SSanjoy Das INITIALIZE_PASS_END(ImplicitNullChecks, "implicit-null-checks",
42569fad079SSanjoy Das                     "Implicit null checks", false, false)
426