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"
31e57bf680SSanjoy Das #include "llvm/Analysis/AliasAnalysis.h"
3269fad079SSanjoy Das #include "llvm/CodeGen/Passes.h"
3369fad079SSanjoy Das #include "llvm/CodeGen/MachineFunction.h"
34b7718454SSanjoy Das #include "llvm/CodeGen/MachineMemOperand.h"
3569fad079SSanjoy Das #include "llvm/CodeGen/MachineOperand.h"
3669fad079SSanjoy Das #include "llvm/CodeGen/MachineFunctionPass.h"
3769fad079SSanjoy Das #include "llvm/CodeGen/MachineInstrBuilder.h"
3869fad079SSanjoy Das #include "llvm/CodeGen/MachineRegisterInfo.h"
3969fad079SSanjoy Das #include "llvm/CodeGen/MachineModuleInfo.h"
4069fad079SSanjoy Das #include "llvm/IR/BasicBlock.h"
4169fad079SSanjoy Das #include "llvm/IR/Instruction.h"
4200038784SChen Li #include "llvm/IR/LLVMContext.h"
4369fad079SSanjoy Das #include "llvm/Support/CommandLine.h"
4469fad079SSanjoy Das #include "llvm/Support/Debug.h"
4569fad079SSanjoy Das #include "llvm/Target/TargetSubtargetInfo.h"
4669fad079SSanjoy Das #include "llvm/Target/TargetInstrInfo.h"
4769fad079SSanjoy Das 
4869fad079SSanjoy Das using namespace llvm;
4969fad079SSanjoy Das 
50c27a18f3SChad Rosier static cl::opt<int> PageSize("imp-null-check-page-size",
51c27a18f3SChad Rosier                              cl::desc("The page size of the target in bytes"),
5269fad079SSanjoy Das                              cl::init(4096));
5369fad079SSanjoy Das 
549a129807SSanjoy Das static cl::opt<unsigned> MaxInstsToConsider(
559a129807SSanjoy Das     "imp-null-max-insts-to-consider",
569a129807SSanjoy Das     cl::desc("The max number of instructions to consider hoisting loads over "
579a129807SSanjoy Das              "(the algorithm is quadratic over this number)"),
589a129807SSanjoy Das     cl::init(8));
599a129807SSanjoy Das 
608ee6a30bSSanjoy Das #define DEBUG_TYPE "implicit-null-checks"
618ee6a30bSSanjoy Das 
628ee6a30bSSanjoy Das STATISTIC(NumImplicitNullChecks,
638ee6a30bSSanjoy Das           "Number of explicit null checks made implicit");
648ee6a30bSSanjoy Das 
6569fad079SSanjoy Das namespace {
6669fad079SSanjoy Das 
6769fad079SSanjoy Das class ImplicitNullChecks : public MachineFunctionPass {
689a129807SSanjoy Das   /// Return true if \c computeDependence can process \p MI.
699a129807SSanjoy Das   static bool canHandle(const MachineInstr *MI);
709a129807SSanjoy Das 
719a129807SSanjoy Das   /// Helper function for \c computeDependence.  Return true if \p A
729a129807SSanjoy Das   /// and \p B do not have any dependences between them, and can be
739a129807SSanjoy Das   /// re-ordered without changing program semantics.
749a129807SSanjoy Das   bool canReorder(const MachineInstr *A, const MachineInstr *B);
759a129807SSanjoy Das 
769a129807SSanjoy Das   /// A data type for representing the result computed by \c
779a129807SSanjoy Das   /// computeDependence.  States whether it is okay to reorder the
789a129807SSanjoy Das   /// instruction passed to \c computeDependence with at most one
799a129807SSanjoy Das   /// depednency.
809a129807SSanjoy Das   struct DependenceResult {
819a129807SSanjoy Das     /// Can we actually re-order \p MI with \p Insts (see \c
829a129807SSanjoy Das     /// computeDependence).
839a129807SSanjoy Das     bool CanReorder;
849a129807SSanjoy Das 
859a129807SSanjoy Das     /// If non-None, then an instruction in \p Insts that also must be
869a129807SSanjoy Das     /// hoisted.
879a129807SSanjoy Das     Optional<ArrayRef<MachineInstr *>::iterator> PotentialDependence;
889a129807SSanjoy Das 
899a129807SSanjoy Das     /*implicit*/ DependenceResult(
909a129807SSanjoy Das         bool CanReorder,
919a129807SSanjoy Das         Optional<ArrayRef<MachineInstr *>::iterator> PotentialDependence)
929a129807SSanjoy Das         : CanReorder(CanReorder), PotentialDependence(PotentialDependence) {
939a129807SSanjoy Das       assert((!PotentialDependence || CanReorder) &&
949a129807SSanjoy Das              "!CanReorder && PotentialDependence.hasValue() not allowed!");
959a129807SSanjoy Das     }
969a129807SSanjoy Das   };
979a129807SSanjoy Das 
989a129807SSanjoy Das   /// Compute a result for the following question: can \p MI be
999a129807SSanjoy Das   /// re-ordered from after \p Insts to before it.
1009a129807SSanjoy Das   ///
1019a129807SSanjoy Das   /// \c canHandle should return true for all instructions in \p
1029a129807SSanjoy Das   /// Insts.
1039a129807SSanjoy Das   DependenceResult computeDependence(const MachineInstr *MI,
1049a129807SSanjoy Das                                      ArrayRef<MachineInstr *> Insts);
1059a129807SSanjoy Das 
10669fad079SSanjoy Das   /// Represents one null check that can be made implicit.
107e173b9aeSSanjoy Das   class NullCheck {
10869fad079SSanjoy Das     // The memory operation the null check can be folded into.
10969fad079SSanjoy Das     MachineInstr *MemOperation;
11069fad079SSanjoy Das 
11169fad079SSanjoy Das     // The instruction actually doing the null check (Ptr != 0).
11269fad079SSanjoy Das     MachineInstr *CheckOperation;
11369fad079SSanjoy Das 
11469fad079SSanjoy Das     // The block the check resides in.
11569fad079SSanjoy Das     MachineBasicBlock *CheckBlock;
11669fad079SSanjoy Das 
117572e03a3SEric Christopher     // The block branched to if the pointer is non-null.
11869fad079SSanjoy Das     MachineBasicBlock *NotNullSucc;
11969fad079SSanjoy Das 
120572e03a3SEric Christopher     // The block branched to if the pointer is null.
12169fad079SSanjoy Das     MachineBasicBlock *NullSucc;
12269fad079SSanjoy Das 
123e57bf680SSanjoy Das     // If this is non-null, then MemOperation has a dependency on on this
124e57bf680SSanjoy Das     // instruction; and it needs to be hoisted to execute before MemOperation.
125e57bf680SSanjoy Das     MachineInstr *OnlyDependency;
126e57bf680SSanjoy Das 
127e173b9aeSSanjoy Das   public:
12869fad079SSanjoy Das     explicit NullCheck(MachineInstr *memOperation, MachineInstr *checkOperation,
12969fad079SSanjoy Das                        MachineBasicBlock *checkBlock,
13069fad079SSanjoy Das                        MachineBasicBlock *notNullSucc,
131e57bf680SSanjoy Das                        MachineBasicBlock *nullSucc,
132e57bf680SSanjoy Das                        MachineInstr *onlyDependency)
13369fad079SSanjoy Das         : MemOperation(memOperation), CheckOperation(checkOperation),
134e57bf680SSanjoy Das           CheckBlock(checkBlock), NotNullSucc(notNullSucc), NullSucc(nullSucc),
135e57bf680SSanjoy Das           OnlyDependency(onlyDependency) {}
136e173b9aeSSanjoy Das 
137e173b9aeSSanjoy Das     MachineInstr *getMemOperation() const { return MemOperation; }
138e173b9aeSSanjoy Das 
139e173b9aeSSanjoy Das     MachineInstr *getCheckOperation() const { return CheckOperation; }
140e173b9aeSSanjoy Das 
141e173b9aeSSanjoy Das     MachineBasicBlock *getCheckBlock() const { return CheckBlock; }
142e173b9aeSSanjoy Das 
143e173b9aeSSanjoy Das     MachineBasicBlock *getNotNullSucc() const { return NotNullSucc; }
144e173b9aeSSanjoy Das 
145e173b9aeSSanjoy Das     MachineBasicBlock *getNullSucc() const { return NullSucc; }
146e57bf680SSanjoy Das 
147e57bf680SSanjoy Das     MachineInstr *getOnlyDependency() const { return OnlyDependency; }
14869fad079SSanjoy Das   };
14969fad079SSanjoy Das 
15069fad079SSanjoy Das   const TargetInstrInfo *TII = nullptr;
15169fad079SSanjoy Das   const TargetRegisterInfo *TRI = nullptr;
152e57bf680SSanjoy Das   AliasAnalysis *AA = nullptr;
15369fad079SSanjoy Das   MachineModuleInfo *MMI = nullptr;
15469fad079SSanjoy Das 
15569fad079SSanjoy Das   bool analyzeBlockForNullChecks(MachineBasicBlock &MBB,
15669fad079SSanjoy Das                                  SmallVectorImpl<NullCheck> &NullCheckList);
15769fad079SSanjoy Das   MachineInstr *insertFaultingLoad(MachineInstr *LoadMI, MachineBasicBlock *MBB,
1584e1d389aSQuentin Colombet                                    MachineBasicBlock *HandlerMBB);
15969fad079SSanjoy Das   void rewriteNullChecks(ArrayRef<NullCheck> NullCheckList);
16069fad079SSanjoy Das 
16150fef432SSanjoy Das   /// Is \p MI a memory operation that can be used to implicitly null check the
16250fef432SSanjoy Das   /// value in \p PointerReg?  \p PrevInsts is the set of instruction seen since
16350fef432SSanjoy Das   /// the explicit null check on \p PointerReg.
16450fef432SSanjoy Das   bool isSuitableMemoryOp(MachineInstr &MI, unsigned PointerReg,
16550fef432SSanjoy Das                           ArrayRef<MachineInstr *> PrevInsts);
16650fef432SSanjoy Das 
16750fef432SSanjoy Das   /// Return true if \p FaultingMI can be hoisted from after the the
16850fef432SSanjoy Das   /// instructions in \p InstsSeenSoFar to before them.  Set \p Dependence to a
16950fef432SSanjoy Das   /// non-null value if we also need to (and legally can) hoist a depedency.
17050fef432SSanjoy Das   bool canHoistLoadInst(MachineInstr *FaultingMI, unsigned PointerReg,
17150fef432SSanjoy Das                         ArrayRef<MachineInstr *> InstsSeenSoFar,
17250fef432SSanjoy Das                         MachineBasicBlock *NullSucc, MachineInstr *&Dependence);
17350fef432SSanjoy Das 
17469fad079SSanjoy Das public:
17569fad079SSanjoy Das   static char ID;
17669fad079SSanjoy Das 
17769fad079SSanjoy Das   ImplicitNullChecks() : MachineFunctionPass(ID) {
17869fad079SSanjoy Das     initializeImplicitNullChecksPass(*PassRegistry::getPassRegistry());
17969fad079SSanjoy Das   }
18069fad079SSanjoy Das 
18169fad079SSanjoy Das   bool runOnMachineFunction(MachineFunction &MF) override;
182e57bf680SSanjoy Das   void getAnalysisUsage(AnalysisUsage &AU) const override {
183e57bf680SSanjoy Das     AU.addRequired<AAResultsWrapperPass>();
184e57bf680SSanjoy Das     MachineFunctionPass::getAnalysisUsage(AU);
185e57bf680SSanjoy Das   }
186ad154c83SDerek Schuff 
187ad154c83SDerek Schuff   MachineFunctionProperties getRequiredProperties() const override {
188ad154c83SDerek Schuff     return MachineFunctionProperties().set(
1891eb47368SMatthias Braun         MachineFunctionProperties::Property::NoVRegs);
190ad154c83SDerek Schuff   }
19169fad079SSanjoy Das };
192edc394f1SSanjoy Das 
193e57bf680SSanjoy Das }
194e57bf680SSanjoy Das 
1959a129807SSanjoy Das bool ImplicitNullChecks::canHandle(const MachineInstr *MI) {
1969a129807SSanjoy Das   if (MI->isCall() || MI->mayStore() || MI->hasUnmodeledSideEffects())
1979a129807SSanjoy Das     return false;
1989a129807SSanjoy Das   auto IsRegMask = [](const MachineOperand &MO) { return MO.isRegMask(); };
1999a129807SSanjoy Das   (void)IsRegMask;
200edc394f1SSanjoy Das 
2019a129807SSanjoy Das   assert(!llvm::any_of(MI->operands(), IsRegMask) &&
2029a129807SSanjoy Das          "Calls were filtered out above!");
203edc394f1SSanjoy Das 
2049a129807SSanjoy Das   auto IsUnordered = [](MachineMemOperand *MMO) { return MMO->isUnordered(); };
2059a129807SSanjoy Das   return llvm::all_of(MI->memoperands(), IsUnordered);
206edc394f1SSanjoy Das }
207edc394f1SSanjoy Das 
2089a129807SSanjoy Das ImplicitNullChecks::DependenceResult
2099a129807SSanjoy Das ImplicitNullChecks::computeDependence(const MachineInstr *MI,
2109a129807SSanjoy Das                                       ArrayRef<MachineInstr *> Block) {
2119a129807SSanjoy Das   assert(llvm::all_of(Block, canHandle) && "Check this first!");
2129a129807SSanjoy Das   assert(!llvm::is_contained(Block, MI) && "Block must be exclusive of MI!");
213edc394f1SSanjoy Das 
2149a129807SSanjoy Das   Optional<ArrayRef<MachineInstr *>::iterator> Dep;
215edc394f1SSanjoy Das 
2169a129807SSanjoy Das   for (auto I = Block.begin(), E = Block.end(); I != E; ++I) {
2179a129807SSanjoy Das     if (canReorder(*I, MI))
218edc394f1SSanjoy Das       continue;
219edc394f1SSanjoy Das 
2209a129807SSanjoy Das     if (Dep == None) {
2219a129807SSanjoy Das       // Found one possible dependency, keep track of it.
2229a129807SSanjoy Das       Dep = I;
2239a129807SSanjoy Das     } else {
2249a129807SSanjoy Das       // We found two dependencies, so bail out.
2259a129807SSanjoy Das       return {false, None};
226edc394f1SSanjoy Das     }
227edc394f1SSanjoy Das   }
228edc394f1SSanjoy Das 
2299a129807SSanjoy Das   return {true, Dep};
2309a129807SSanjoy Das }
231edc394f1SSanjoy Das 
2329a129807SSanjoy Das bool ImplicitNullChecks::canReorder(const MachineInstr *A,
2339a129807SSanjoy Das                                     const MachineInstr *B) {
2349a129807SSanjoy Das   assert(canHandle(A) && canHandle(B) && "Precondition!");
235edc394f1SSanjoy Das 
2369a129807SSanjoy Das   // canHandle makes sure that we _can_ correctly analyze the dependencies
2379a129807SSanjoy Das   // between A and B here -- for instance, we should not be dealing with heap
2389a129807SSanjoy Das   // load-store dependencies here.
2399a129807SSanjoy Das 
2409a129807SSanjoy Das   for (auto MOA : A->operands()) {
2419a129807SSanjoy Das     if (!(MOA.isReg() && MOA.getReg()))
242e57bf680SSanjoy Das       continue;
243e57bf680SSanjoy Das 
2449a129807SSanjoy Das     unsigned RegA = MOA.getReg();
2459a129807SSanjoy Das     for (auto MOB : B->operands()) {
2469a129807SSanjoy Das       if (!(MOB.isReg() && MOB.getReg()))
247e57bf680SSanjoy Das         continue;
2489a129807SSanjoy Das 
2499a129807SSanjoy Das       unsigned RegB = MOB.getReg();
2509a129807SSanjoy Das 
2519a129807SSanjoy Das       if (TRI->regsOverlap(RegA, RegB))
252e57bf680SSanjoy Das         return false;
253e57bf680SSanjoy Das     }
254edc394f1SSanjoy Das   }
255edc394f1SSanjoy Das 
256edc394f1SSanjoy Das   return true;
257f00654e3SAlexander Kornienko }
25869fad079SSanjoy Das 
25969fad079SSanjoy Das bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) {
26069fad079SSanjoy Das   TII = MF.getSubtarget().getInstrInfo();
26169fad079SSanjoy Das   TRI = MF.getRegInfo().getTargetRegisterInfo();
26269fad079SSanjoy Das   MMI = &MF.getMMI();
263e57bf680SSanjoy Das   AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
26469fad079SSanjoy Das 
26569fad079SSanjoy Das   SmallVector<NullCheck, 16> NullCheckList;
26669fad079SSanjoy Das 
26769fad079SSanjoy Das   for (auto &MBB : MF)
26869fad079SSanjoy Das     analyzeBlockForNullChecks(MBB, NullCheckList);
26969fad079SSanjoy Das 
27069fad079SSanjoy Das   if (!NullCheckList.empty())
27169fad079SSanjoy Das     rewriteNullChecks(NullCheckList);
27269fad079SSanjoy Das 
27369fad079SSanjoy Das   return !NullCheckList.empty();
27469fad079SSanjoy Das }
27569fad079SSanjoy Das 
276e57bf680SSanjoy Das // Return true if any register aliasing \p Reg is live-in into \p MBB.
277e57bf680SSanjoy Das static bool AnyAliasLiveIn(const TargetRegisterInfo *TRI,
278e57bf680SSanjoy Das                            MachineBasicBlock *MBB, unsigned Reg) {
279e57bf680SSanjoy Das   for (MCRegAliasIterator AR(Reg, TRI, /*IncludeSelf*/ true); AR.isValid();
280e57bf680SSanjoy Das        ++AR)
281e57bf680SSanjoy Das     if (MBB->isLiveIn(*AR))
282e57bf680SSanjoy Das       return true;
283e57bf680SSanjoy Das   return false;
284e57bf680SSanjoy Das }
285e57bf680SSanjoy Das 
28650fef432SSanjoy Das bool ImplicitNullChecks::isSuitableMemoryOp(
28750fef432SSanjoy Das     MachineInstr &MI, unsigned PointerReg, ArrayRef<MachineInstr *> PrevInsts) {
28850fef432SSanjoy Das   int64_t Offset;
28950fef432SSanjoy Das   unsigned BaseReg;
29050fef432SSanjoy Das 
29150fef432SSanjoy Das   if (!TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI) ||
29250fef432SSanjoy Das       BaseReg != PointerReg)
29350fef432SSanjoy Das     return false;
29450fef432SSanjoy Das 
29550fef432SSanjoy Das   // We want the load to be issued at a sane offset from PointerReg, so that
29650fef432SSanjoy Das   // if PointerReg is null then the load reliably page faults.
29750fef432SSanjoy Das   if (!(MI.mayLoad() && !MI.isPredicable() && Offset < PageSize))
29850fef432SSanjoy Das     return false;
29950fef432SSanjoy Das 
30050fef432SSanjoy Das   // Finally, we need to make sure that the load instruction actually is
30150fef432SSanjoy Das   // loading from PointerReg, and there isn't some re-definition of PointerReg
30250fef432SSanjoy Das   // between the compare and the load.
30350fef432SSanjoy Das   for (auto *PrevMI : PrevInsts)
30450fef432SSanjoy Das     for (auto &PrevMO : PrevMI->operands())
30550fef432SSanjoy Das       if (PrevMO.isReg() && PrevMO.getReg() &&
30650fef432SSanjoy Das           TRI->regsOverlap(PrevMO.getReg(), PointerReg))
30750fef432SSanjoy Das         return false;
30850fef432SSanjoy Das 
30950fef432SSanjoy Das   return true;
31050fef432SSanjoy Das }
31150fef432SSanjoy Das 
31250fef432SSanjoy Das bool ImplicitNullChecks::canHoistLoadInst(
31350fef432SSanjoy Das     MachineInstr *FaultingMI, unsigned PointerReg,
31450fef432SSanjoy Das     ArrayRef<MachineInstr *> InstsSeenSoFar, MachineBasicBlock *NullSucc,
31550fef432SSanjoy Das     MachineInstr *&Dependence) {
31650fef432SSanjoy Das   auto DepResult = computeDependence(FaultingMI, InstsSeenSoFar);
31750fef432SSanjoy Das   if (!DepResult.CanReorder)
31850fef432SSanjoy Das     return false;
31950fef432SSanjoy Das 
32050fef432SSanjoy Das   if (!DepResult.PotentialDependence) {
32150fef432SSanjoy Das     Dependence = nullptr;
32250fef432SSanjoy Das     return true;
32350fef432SSanjoy Das   }
32450fef432SSanjoy Das 
32550fef432SSanjoy Das   auto DependenceItr = *DepResult.PotentialDependence;
32650fef432SSanjoy Das   auto *DependenceMI = *DependenceItr;
32750fef432SSanjoy Das 
32850fef432SSanjoy Das   // We don't want to reason about speculating loads.  Note -- at this point
32950fef432SSanjoy Das   // we should have already filtered out all of the other non-speculatable
33050fef432SSanjoy Das   // things, like calls and stores.
33150fef432SSanjoy Das   assert(canHandle(DependenceMI) && "Should never have reached here!");
33250fef432SSanjoy Das   if (DependenceMI->mayLoad())
33350fef432SSanjoy Das     return false;
33450fef432SSanjoy Das 
33550fef432SSanjoy Das   for (auto &DependenceMO : DependenceMI->operands()) {
33650fef432SSanjoy Das     if (!(DependenceMO.isReg() && DependenceMO.getReg()))
33750fef432SSanjoy Das       continue;
33850fef432SSanjoy Das 
33950fef432SSanjoy Das     // Make sure that we won't clobber any live ins to the sibling block by
34050fef432SSanjoy Das     // hoisting Dependency.  For instance, we can't hoist INST to before the
34150fef432SSanjoy Das     // null check (even if it safe, and does not violate any dependencies in
34250fef432SSanjoy Das     // the non_null_block) if %rdx is live in to _null_block.
34350fef432SSanjoy Das     //
34450fef432SSanjoy Das     //    test %rcx, %rcx
34550fef432SSanjoy Das     //    je _null_block
34650fef432SSanjoy Das     //  _non_null_block:
34750fef432SSanjoy Das     //    %rdx<def> = INST
34850fef432SSanjoy Das     //    ...
34950fef432SSanjoy Das     //
35050fef432SSanjoy Das     // This restriction does not apply to the faulting load inst because in
35150fef432SSanjoy Das     // case the pointer loaded from is in the null page, the load will not
35250fef432SSanjoy Das     // semantically execute, and affect machine state.  That is, if the load
35350fef432SSanjoy Das     // was loading into %rax and it faults, the value of %rax should stay the
35450fef432SSanjoy Das     // same as it would have been had the load not have executed and we'd have
35550fef432SSanjoy Das     // branched to NullSucc directly.
35650fef432SSanjoy Das     if (AnyAliasLiveIn(TRI, NullSucc, DependenceMO.getReg()))
35750fef432SSanjoy Das       return false;
35850fef432SSanjoy Das 
35950fef432SSanjoy Das     // The Dependency can't be re-defining the base register -- then we won't
36050fef432SSanjoy Das     // get the memory operation on the address we want.  This is already
36150fef432SSanjoy Das     // checked in \c IsSuitableMemoryOp.
36250fef432SSanjoy Das     assert(!TRI->regsOverlap(DependenceMO.getReg(), PointerReg) &&
36350fef432SSanjoy Das            "Should have been checked before!");
36450fef432SSanjoy Das   }
36550fef432SSanjoy Das 
36650fef432SSanjoy Das   auto DepDepResult =
36750fef432SSanjoy Das       computeDependence(DependenceMI, {InstsSeenSoFar.begin(), DependenceItr});
36850fef432SSanjoy Das 
36950fef432SSanjoy Das   if (!DepDepResult.CanReorder || DepDepResult.PotentialDependence)
37050fef432SSanjoy Das     return false;
37150fef432SSanjoy Das 
37250fef432SSanjoy Das   Dependence = DependenceMI;
37350fef432SSanjoy Das   return true;
37450fef432SSanjoy Das }
37550fef432SSanjoy Das 
37669fad079SSanjoy Das /// Analyze MBB to check if its terminating branch can be turned into an
37769fad079SSanjoy Das /// implicit null check.  If yes, append a description of the said null check to
37869fad079SSanjoy Das /// NullCheckList and return true, else return false.
37969fad079SSanjoy Das bool ImplicitNullChecks::analyzeBlockForNullChecks(
38069fad079SSanjoy Das     MachineBasicBlock &MBB, SmallVectorImpl<NullCheck> &NullCheckList) {
38169fad079SSanjoy Das   typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate;
38269fad079SSanjoy Das 
383e8b81649SSanjoy Das   MDNode *BranchMD = nullptr;
384e8b81649SSanjoy Das   if (auto *BB = MBB.getBasicBlock())
385e8b81649SSanjoy Das     BranchMD = BB->getTerminator()->getMetadata(LLVMContext::MD_make_implicit);
386e8b81649SSanjoy Das 
3879c41a93eSSanjoy Das   if (!BranchMD)
3889c41a93eSSanjoy Das     return false;
3899c41a93eSSanjoy Das 
39069fad079SSanjoy Das   MachineBranchPredicate MBP;
39169fad079SSanjoy Das 
39271c30a14SJacques Pienaar   if (TII->analyzeBranchPredicate(MBB, MBP, true))
39369fad079SSanjoy Das     return false;
39469fad079SSanjoy Das 
39569fad079SSanjoy Das   // Is the predicate comparing an integer to zero?
39669fad079SSanjoy Das   if (!(MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 &&
39769fad079SSanjoy Das         (MBP.Predicate == MachineBranchPredicate::PRED_NE ||
39869fad079SSanjoy Das          MBP.Predicate == MachineBranchPredicate::PRED_EQ)))
39969fad079SSanjoy Das     return false;
40069fad079SSanjoy Das 
40169fad079SSanjoy Das   // If we cannot erase the test instruction itself, then making the null check
40269fad079SSanjoy Das   // implicit does not buy us much.
40369fad079SSanjoy Das   if (!MBP.SingleUseCondition)
40469fad079SSanjoy Das     return false;
40569fad079SSanjoy Das 
40669fad079SSanjoy Das   MachineBasicBlock *NotNullSucc, *NullSucc;
40769fad079SSanjoy Das 
40869fad079SSanjoy Das   if (MBP.Predicate == MachineBranchPredicate::PRED_NE) {
40969fad079SSanjoy Das     NotNullSucc = MBP.TrueDest;
41069fad079SSanjoy Das     NullSucc = MBP.FalseDest;
41169fad079SSanjoy Das   } else {
41269fad079SSanjoy Das     NotNullSucc = MBP.FalseDest;
41369fad079SSanjoy Das     NullSucc = MBP.TrueDest;
41469fad079SSanjoy Das   }
41569fad079SSanjoy Das 
41669fad079SSanjoy Das   // We handle the simplest case for now.  We can potentially do better by using
41769fad079SSanjoy Das   // the machine dominator tree.
41869fad079SSanjoy Das   if (NotNullSucc->pred_size() != 1)
41969fad079SSanjoy Das     return false;
42069fad079SSanjoy Das 
42169fad079SSanjoy Das   // Starting with a code fragment like:
42269fad079SSanjoy Das   //
42369fad079SSanjoy Das   //   test %RAX, %RAX
42469fad079SSanjoy Das   //   jne LblNotNull
42569fad079SSanjoy Das   //
42669fad079SSanjoy Das   //  LblNull:
42769fad079SSanjoy Das   //   callq throw_NullPointerException
42869fad079SSanjoy Das   //
42969fad079SSanjoy Das   //  LblNotNull:
430b7718454SSanjoy Das   //   Inst0
431b7718454SSanjoy Das   //   Inst1
432b7718454SSanjoy Das   //   ...
43369fad079SSanjoy Das   //   Def = Load (%RAX + <offset>)
43469fad079SSanjoy Das   //   ...
43569fad079SSanjoy Das   //
43669fad079SSanjoy Das   //
43769fad079SSanjoy Das   // we want to end up with
43869fad079SSanjoy Das   //
439ac9c5b19SSanjoy Das   //   Def = FaultingLoad (%RAX + <offset>), LblNull
44069fad079SSanjoy Das   //   jmp LblNotNull ;; explicit or fallthrough
44169fad079SSanjoy Das   //
44269fad079SSanjoy Das   //  LblNotNull:
443b7718454SSanjoy Das   //   Inst0
444b7718454SSanjoy Das   //   Inst1
44569fad079SSanjoy Das   //   ...
44669fad079SSanjoy Das   //
44769fad079SSanjoy Das   //  LblNull:
44869fad079SSanjoy Das   //   callq throw_NullPointerException
44969fad079SSanjoy Das   //
450ac9c5b19SSanjoy Das   //
451ac9c5b19SSanjoy Das   // To see why this is legal, consider the two possibilities:
452ac9c5b19SSanjoy Das   //
453ac9c5b19SSanjoy Das   //  1. %RAX is null: since we constrain <offset> to be less than PageSize, the
454ac9c5b19SSanjoy Das   //     load instruction dereferences the null page, causing a segmentation
455ac9c5b19SSanjoy Das   //     fault.
456ac9c5b19SSanjoy Das   //
457ac9c5b19SSanjoy Das   //  2. %RAX is not null: in this case we know that the load cannot fault, as
458ac9c5b19SSanjoy Das   //     otherwise the load would've faulted in the original program too and the
459ac9c5b19SSanjoy Das   //     original program would've been undefined.
460ac9c5b19SSanjoy Das   //
461ac9c5b19SSanjoy Das   // This reasoning cannot be extended to justify hoisting through arbitrary
462ac9c5b19SSanjoy Das   // control flow.  For instance, in the example below (in pseudo-C)
463ac9c5b19SSanjoy Das   //
464ac9c5b19SSanjoy Das   //    if (ptr == null) { throw_npe(); unreachable; }
465ac9c5b19SSanjoy Das   //    if (some_cond) { return 42; }
466ac9c5b19SSanjoy Das   //    v = ptr->field;  // LD
467ac9c5b19SSanjoy Das   //    ...
468ac9c5b19SSanjoy Das   //
469ac9c5b19SSanjoy Das   // we cannot (without code duplication) use the load marked "LD" to null check
470ac9c5b19SSanjoy Das   // ptr -- clause (2) above does not apply in this case.  In the above program
471ac9c5b19SSanjoy Das   // the safety of ptr->field can be dependent on some_cond; and, for instance,
472ac9c5b19SSanjoy Das   // ptr could be some non-null invalid reference that never gets loaded from
473ac9c5b19SSanjoy Das   // because some_cond is always true.
47469fad079SSanjoy Das 
4759a129807SSanjoy Das   const unsigned PointerReg = MBP.LHS.getReg();
476b7718454SSanjoy Das 
4779a129807SSanjoy Das   SmallVector<MachineInstr *, 8> InstsSeenSoFar;
478b7718454SSanjoy Das 
4799a129807SSanjoy Das   for (auto &MI : *NotNullSucc) {
4809a129807SSanjoy Das     if (!canHandle(&MI) || InstsSeenSoFar.size() >= MaxInstsToConsider)
4819a129807SSanjoy Das       return false;
482e57bf680SSanjoy Das 
4839a129807SSanjoy Das     MachineInstr *Dependence;
48450fef432SSanjoy Das     if (isSuitableMemoryOp(MI, PointerReg, InstsSeenSoFar) &&
48550fef432SSanjoy Das         canHoistLoadInst(&MI, PointerReg, InstsSeenSoFar, NullSucc,
48650fef432SSanjoy Das                          Dependence)) {
4879cfc75c2SDuncan P. N. Exon Smith       NullCheckList.emplace_back(&MI, MBP.ConditionDef, &MBB, NotNullSucc,
4889a129807SSanjoy Das                                  NullSucc, Dependence);
489e57bf680SSanjoy Das       return true;
490e57bf680SSanjoy Das     }
49169fad079SSanjoy Das 
4929a129807SSanjoy Das     InstsSeenSoFar.push_back(&MI);
493b7718454SSanjoy Das   }
494b7718454SSanjoy Das 
49569fad079SSanjoy Das   return false;
49669fad079SSanjoy Das }
49769fad079SSanjoy Das 
49869fad079SSanjoy Das /// Wrap a machine load instruction, LoadMI, into a FAULTING_LOAD_OP machine
49969fad079SSanjoy Das /// instruction.  The FAULTING_LOAD_OP instruction does the same load as LoadMI
5004e1d389aSQuentin Colombet /// (defining the same register), and branches to HandlerMBB if the load
50169fad079SSanjoy Das /// faults.  The FAULTING_LOAD_OP instruction is inserted at the end of MBB.
5024e1d389aSQuentin Colombet MachineInstr *
5034e1d389aSQuentin Colombet ImplicitNullChecks::insertFaultingLoad(MachineInstr *LoadMI,
50469fad079SSanjoy Das                                        MachineBasicBlock *MBB,
5054e1d389aSQuentin Colombet                                        MachineBasicBlock *HandlerMBB) {
50693d608c3SSanjoy Das   const unsigned NoRegister = 0; // Guaranteed to be the NoRegister value for
50793d608c3SSanjoy Das                                  // all targets.
50893d608c3SSanjoy Das 
50969fad079SSanjoy Das   DebugLoc DL;
51069fad079SSanjoy Das   unsigned NumDefs = LoadMI->getDesc().getNumDefs();
51193d608c3SSanjoy Das   assert(NumDefs <= 1 && "other cases unhandled!");
51269fad079SSanjoy Das 
51393d608c3SSanjoy Das   unsigned DefReg = NoRegister;
51493d608c3SSanjoy Das   if (NumDefs != 0) {
51593d608c3SSanjoy Das     DefReg = LoadMI->defs().begin()->getReg();
51669fad079SSanjoy Das     assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 &&
51769fad079SSanjoy Das            "expected exactly one def!");
51893d608c3SSanjoy Das   }
51969fad079SSanjoy Das 
52069fad079SSanjoy Das   auto MIB = BuildMI(MBB, DL, TII->get(TargetOpcode::FAULTING_LOAD_OP), DefReg)
5214e1d389aSQuentin Colombet                  .addMBB(HandlerMBB)
52269fad079SSanjoy Das                  .addImm(LoadMI->getOpcode());
52369fad079SSanjoy Das 
52469fad079SSanjoy Das   for (auto &MO : LoadMI->uses())
525*116bbab4SDiana Picus     MIB.add(MO);
52669fad079SSanjoy Das 
52769fad079SSanjoy Das   MIB.setMemRefs(LoadMI->memoperands_begin(), LoadMI->memoperands_end());
52869fad079SSanjoy Das 
52969fad079SSanjoy Das   return MIB;
53069fad079SSanjoy Das }
53169fad079SSanjoy Das 
53269fad079SSanjoy Das /// Rewrite the null checks in NullCheckList into implicit null checks.
53369fad079SSanjoy Das void ImplicitNullChecks::rewriteNullChecks(
53469fad079SSanjoy Das     ArrayRef<ImplicitNullChecks::NullCheck> NullCheckList) {
53569fad079SSanjoy Das   DebugLoc DL;
53669fad079SSanjoy Das 
53769fad079SSanjoy Das   for (auto &NC : NullCheckList) {
53869fad079SSanjoy Das     // Remove the conditional branch dependent on the null check.
5391b9fc8edSMatt Arsenault     unsigned BranchesRemoved = TII->removeBranch(*NC.getCheckBlock());
54069fad079SSanjoy Das     (void)BranchesRemoved;
54169fad079SSanjoy Das     assert(BranchesRemoved > 0 && "expected at least one branch!");
54269fad079SSanjoy Das 
543e57bf680SSanjoy Das     if (auto *DepMI = NC.getOnlyDependency()) {
544e57bf680SSanjoy Das       DepMI->removeFromParent();
545e57bf680SSanjoy Das       NC.getCheckBlock()->insert(NC.getCheckBlock()->end(), DepMI);
546e57bf680SSanjoy Das     }
547e57bf680SSanjoy Das 
54869fad079SSanjoy Das     // Insert a faulting load where the conditional branch was originally.  We
54969fad079SSanjoy Das     // check earlier ensures that this bit of code motion is legal.  We do not
55069fad079SSanjoy Das     // touch the successors list for any basic block since we haven't changed
55169fad079SSanjoy Das     // control flow, we've just made it implicit.
552e173b9aeSSanjoy Das     MachineInstr *FaultingLoad = insertFaultingLoad(
553e173b9aeSSanjoy Das         NC.getMemOperation(), NC.getCheckBlock(), NC.getNullSucc());
55426dab3a4SQuentin Colombet     // Now the values defined by MemOperation, if any, are live-in of
55526dab3a4SQuentin Colombet     // the block of MemOperation.
55626dab3a4SQuentin Colombet     // The original load operation may define implicit-defs alongside
55726dab3a4SQuentin Colombet     // the loaded value.
558e173b9aeSSanjoy Das     MachineBasicBlock *MBB = NC.getMemOperation()->getParent();
55926dab3a4SQuentin Colombet     for (const MachineOperand &MO : FaultingLoad->operands()) {
56026dab3a4SQuentin Colombet       if (!MO.isReg() || !MO.isDef())
56126dab3a4SQuentin Colombet         continue;
56226dab3a4SQuentin Colombet       unsigned Reg = MO.getReg();
56326dab3a4SQuentin Colombet       if (!Reg || MBB->isLiveIn(Reg))
56426dab3a4SQuentin Colombet         continue;
56512b69919SQuentin Colombet       MBB->addLiveIn(Reg);
56612b69919SQuentin Colombet     }
567e57bf680SSanjoy Das 
568e57bf680SSanjoy Das     if (auto *DepMI = NC.getOnlyDependency()) {
569e57bf680SSanjoy Das       for (auto &MO : DepMI->operands()) {
570e57bf680SSanjoy Das         if (!MO.isReg() || !MO.getReg() || !MO.isDef())
571e57bf680SSanjoy Das           continue;
572e57bf680SSanjoy Das         if (!NC.getNotNullSucc()->isLiveIn(MO.getReg()))
573e57bf680SSanjoy Das           NC.getNotNullSucc()->addLiveIn(MO.getReg());
574e57bf680SSanjoy Das       }
575e57bf680SSanjoy Das     }
576e57bf680SSanjoy Das 
577e173b9aeSSanjoy Das     NC.getMemOperation()->eraseFromParent();
578e173b9aeSSanjoy Das     NC.getCheckOperation()->eraseFromParent();
57969fad079SSanjoy Das 
58069fad079SSanjoy Das     // Insert an *unconditional* branch to not-null successor.
581e8e0f5caSMatt Arsenault     TII->insertBranch(*NC.getCheckBlock(), NC.getNotNullSucc(), nullptr,
582e173b9aeSSanjoy Das                       /*Cond=*/None, DL);
58369fad079SSanjoy Das 
5848ee6a30bSSanjoy Das     NumImplicitNullChecks++;
58569fad079SSanjoy Das   }
58669fad079SSanjoy Das }
58769fad079SSanjoy Das 
5889a129807SSanjoy Das 
58969fad079SSanjoy Das char ImplicitNullChecks::ID = 0;
59069fad079SSanjoy Das char &llvm::ImplicitNullChecksID = ImplicitNullChecks::ID;
59169fad079SSanjoy Das INITIALIZE_PASS_BEGIN(ImplicitNullChecks, "implicit-null-checks",
59269fad079SSanjoy Das                       "Implicit null checks", false, false)
593e57bf680SSanjoy Das INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
59469fad079SSanjoy Das INITIALIZE_PASS_END(ImplicitNullChecks, "implicit-null-checks",
59569fad079SSanjoy Das                     "Implicit null checks", false, false)
596