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 
16115e50b51SSanjoy Das   enum SuitabilityResult { SR_Suitable, SR_Unsuitable, SR_Impossible };
16215e50b51SSanjoy Das 
16315e50b51SSanjoy Das   /// Return SR_Suitable if \p MI a memory operation that can be used to
16415e50b51SSanjoy Das   /// implicitly null check the value in \p PointerReg, SR_Unsuitable if
16515e50b51SSanjoy Das   /// \p MI cannot be used to null check and SR_Impossible if there is
16615e50b51SSanjoy Das   /// no sense to continue lookup due to any other instruction will not be able
16715e50b51SSanjoy Das   /// to be used. \p PrevInsts is the set of instruction seen since
16850fef432SSanjoy Das   /// the explicit null check on \p PointerReg.
16915e50b51SSanjoy Das   SuitabilityResult isSuitableMemoryOp(MachineInstr &MI, unsigned PointerReg,
17050fef432SSanjoy Das                                        ArrayRef<MachineInstr *> PrevInsts);
17150fef432SSanjoy Das 
17250fef432SSanjoy Das   /// Return true if \p FaultingMI can be hoisted from after the the
17350fef432SSanjoy Das   /// instructions in \p InstsSeenSoFar to before them.  Set \p Dependence to a
17450fef432SSanjoy Das   /// non-null value if we also need to (and legally can) hoist a depedency.
17550fef432SSanjoy Das   bool canHoistLoadInst(MachineInstr *FaultingMI, unsigned PointerReg,
17650fef432SSanjoy Das                         ArrayRef<MachineInstr *> InstsSeenSoFar,
17750fef432SSanjoy Das                         MachineBasicBlock *NullSucc, MachineInstr *&Dependence);
17850fef432SSanjoy Das 
17969fad079SSanjoy Das public:
18069fad079SSanjoy Das   static char ID;
18169fad079SSanjoy Das 
18269fad079SSanjoy Das   ImplicitNullChecks() : MachineFunctionPass(ID) {
18369fad079SSanjoy Das     initializeImplicitNullChecksPass(*PassRegistry::getPassRegistry());
18469fad079SSanjoy Das   }
18569fad079SSanjoy Das 
18669fad079SSanjoy Das   bool runOnMachineFunction(MachineFunction &MF) override;
187e57bf680SSanjoy Das   void getAnalysisUsage(AnalysisUsage &AU) const override {
188e57bf680SSanjoy Das     AU.addRequired<AAResultsWrapperPass>();
189e57bf680SSanjoy Das     MachineFunctionPass::getAnalysisUsage(AU);
190e57bf680SSanjoy Das   }
191ad154c83SDerek Schuff 
192ad154c83SDerek Schuff   MachineFunctionProperties getRequiredProperties() const override {
193ad154c83SDerek Schuff     return MachineFunctionProperties().set(
1941eb47368SMatthias Braun         MachineFunctionProperties::Property::NoVRegs);
195ad154c83SDerek Schuff   }
19669fad079SSanjoy Das };
197edc394f1SSanjoy Das 
198e57bf680SSanjoy Das }
199e57bf680SSanjoy Das 
2009a129807SSanjoy Das bool ImplicitNullChecks::canHandle(const MachineInstr *MI) {
2019a129807SSanjoy Das   if (MI->isCall() || MI->mayStore() || MI->hasUnmodeledSideEffects())
2029a129807SSanjoy Das     return false;
2039a129807SSanjoy Das   auto IsRegMask = [](const MachineOperand &MO) { return MO.isRegMask(); };
2049a129807SSanjoy Das   (void)IsRegMask;
205edc394f1SSanjoy Das 
2069a129807SSanjoy Das   assert(!llvm::any_of(MI->operands(), IsRegMask) &&
2079a129807SSanjoy Das          "Calls were filtered out above!");
208edc394f1SSanjoy Das 
2099a129807SSanjoy Das   auto IsUnordered = [](MachineMemOperand *MMO) { return MMO->isUnordered(); };
2109a129807SSanjoy Das   return llvm::all_of(MI->memoperands(), IsUnordered);
211edc394f1SSanjoy Das }
212edc394f1SSanjoy Das 
2139a129807SSanjoy Das ImplicitNullChecks::DependenceResult
2149a129807SSanjoy Das ImplicitNullChecks::computeDependence(const MachineInstr *MI,
2159a129807SSanjoy Das                                       ArrayRef<MachineInstr *> Block) {
2169a129807SSanjoy Das   assert(llvm::all_of(Block, canHandle) && "Check this first!");
2179a129807SSanjoy Das   assert(!llvm::is_contained(Block, MI) && "Block must be exclusive of MI!");
218edc394f1SSanjoy Das 
2199a129807SSanjoy Das   Optional<ArrayRef<MachineInstr *>::iterator> Dep;
220edc394f1SSanjoy Das 
2219a129807SSanjoy Das   for (auto I = Block.begin(), E = Block.end(); I != E; ++I) {
2229a129807SSanjoy Das     if (canReorder(*I, MI))
223edc394f1SSanjoy Das       continue;
224edc394f1SSanjoy Das 
2259a129807SSanjoy Das     if (Dep == None) {
2269a129807SSanjoy Das       // Found one possible dependency, keep track of it.
2279a129807SSanjoy Das       Dep = I;
2289a129807SSanjoy Das     } else {
2299a129807SSanjoy Das       // We found two dependencies, so bail out.
2309a129807SSanjoy Das       return {false, None};
231edc394f1SSanjoy Das     }
232edc394f1SSanjoy Das   }
233edc394f1SSanjoy Das 
2349a129807SSanjoy Das   return {true, Dep};
2359a129807SSanjoy Das }
236edc394f1SSanjoy Das 
2379a129807SSanjoy Das bool ImplicitNullChecks::canReorder(const MachineInstr *A,
2389a129807SSanjoy Das                                     const MachineInstr *B) {
2399a129807SSanjoy Das   assert(canHandle(A) && canHandle(B) && "Precondition!");
240edc394f1SSanjoy Das 
2419a129807SSanjoy Das   // canHandle makes sure that we _can_ correctly analyze the dependencies
2429a129807SSanjoy Das   // between A and B here -- for instance, we should not be dealing with heap
2439a129807SSanjoy Das   // load-store dependencies here.
2449a129807SSanjoy Das 
2459a129807SSanjoy Das   for (auto MOA : A->operands()) {
2469a129807SSanjoy Das     if (!(MOA.isReg() && MOA.getReg()))
247e57bf680SSanjoy Das       continue;
248e57bf680SSanjoy Das 
2499a129807SSanjoy Das     unsigned RegA = MOA.getReg();
2509a129807SSanjoy Das     for (auto MOB : B->operands()) {
2519a129807SSanjoy Das       if (!(MOB.isReg() && MOB.getReg()))
252e57bf680SSanjoy Das         continue;
2539a129807SSanjoy Das 
2549a129807SSanjoy Das       unsigned RegB = MOB.getReg();
2559a129807SSanjoy Das 
256*08da2e28SSanjoy Das       if (TRI->regsOverlap(RegA, RegB) && (MOA.isDef() || MOB.isDef()))
257e57bf680SSanjoy Das         return false;
258e57bf680SSanjoy Das     }
259edc394f1SSanjoy Das   }
260edc394f1SSanjoy Das 
261edc394f1SSanjoy Das   return true;
262f00654e3SAlexander Kornienko }
26369fad079SSanjoy Das 
26469fad079SSanjoy Das bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) {
26569fad079SSanjoy Das   TII = MF.getSubtarget().getInstrInfo();
26669fad079SSanjoy Das   TRI = MF.getRegInfo().getTargetRegisterInfo();
26769fad079SSanjoy Das   MMI = &MF.getMMI();
268e57bf680SSanjoy Das   AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
26969fad079SSanjoy Das 
27069fad079SSanjoy Das   SmallVector<NullCheck, 16> NullCheckList;
27169fad079SSanjoy Das 
27269fad079SSanjoy Das   for (auto &MBB : MF)
27369fad079SSanjoy Das     analyzeBlockForNullChecks(MBB, NullCheckList);
27469fad079SSanjoy Das 
27569fad079SSanjoy Das   if (!NullCheckList.empty())
27669fad079SSanjoy Das     rewriteNullChecks(NullCheckList);
27769fad079SSanjoy Das 
27869fad079SSanjoy Das   return !NullCheckList.empty();
27969fad079SSanjoy Das }
28069fad079SSanjoy Das 
281e57bf680SSanjoy Das // Return true if any register aliasing \p Reg is live-in into \p MBB.
282e57bf680SSanjoy Das static bool AnyAliasLiveIn(const TargetRegisterInfo *TRI,
283e57bf680SSanjoy Das                            MachineBasicBlock *MBB, unsigned Reg) {
284e57bf680SSanjoy Das   for (MCRegAliasIterator AR(Reg, TRI, /*IncludeSelf*/ true); AR.isValid();
285e57bf680SSanjoy Das        ++AR)
286e57bf680SSanjoy Das     if (MBB->isLiveIn(*AR))
287e57bf680SSanjoy Das       return true;
288e57bf680SSanjoy Das   return false;
289e57bf680SSanjoy Das }
290e57bf680SSanjoy Das 
29115e50b51SSanjoy Das ImplicitNullChecks::SuitabilityResult
29215e50b51SSanjoy Das ImplicitNullChecks::isSuitableMemoryOp(MachineInstr &MI, unsigned PointerReg,
29315e50b51SSanjoy Das                                        ArrayRef<MachineInstr *> PrevInsts) {
29450fef432SSanjoy Das   int64_t Offset;
29550fef432SSanjoy Das   unsigned BaseReg;
29650fef432SSanjoy Das 
29750fef432SSanjoy Das   if (!TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI) ||
29850fef432SSanjoy Das       BaseReg != PointerReg)
29915e50b51SSanjoy Das     return SR_Unsuitable;
30050fef432SSanjoy Das 
30150fef432SSanjoy Das   // We want the load to be issued at a sane offset from PointerReg, so that
30250fef432SSanjoy Das   // if PointerReg is null then the load reliably page faults.
30350fef432SSanjoy Das   if (!(MI.mayLoad() && !MI.isPredicable() && Offset < PageSize))
30415e50b51SSanjoy Das     return SR_Unsuitable;
30550fef432SSanjoy Das 
30650fef432SSanjoy Das   // Finally, we need to make sure that the load instruction actually is
30750fef432SSanjoy Das   // loading from PointerReg, and there isn't some re-definition of PointerReg
30850fef432SSanjoy Das   // between the compare and the load.
30915e50b51SSanjoy Das   // If PointerReg has been redefined before then there is no sense to continue
31015e50b51SSanjoy Das   // lookup due to this condition will fail for any further instruction.
31150fef432SSanjoy Das   for (auto *PrevMI : PrevInsts)
31250fef432SSanjoy Das     for (auto &PrevMO : PrevMI->operands())
313*08da2e28SSanjoy Das       if (PrevMO.isReg() && PrevMO.getReg() && PrevMO.isDef() &&
31450fef432SSanjoy Das           TRI->regsOverlap(PrevMO.getReg(), PointerReg))
31515e50b51SSanjoy Das         return SR_Impossible;
31650fef432SSanjoy Das 
31715e50b51SSanjoy Das   return SR_Suitable;
31850fef432SSanjoy Das }
31950fef432SSanjoy Das 
32050fef432SSanjoy Das bool ImplicitNullChecks::canHoistLoadInst(
32150fef432SSanjoy Das     MachineInstr *FaultingMI, unsigned PointerReg,
32250fef432SSanjoy Das     ArrayRef<MachineInstr *> InstsSeenSoFar, MachineBasicBlock *NullSucc,
32350fef432SSanjoy Das     MachineInstr *&Dependence) {
32450fef432SSanjoy Das   auto DepResult = computeDependence(FaultingMI, InstsSeenSoFar);
32550fef432SSanjoy Das   if (!DepResult.CanReorder)
32650fef432SSanjoy Das     return false;
32750fef432SSanjoy Das 
32850fef432SSanjoy Das   if (!DepResult.PotentialDependence) {
32950fef432SSanjoy Das     Dependence = nullptr;
33050fef432SSanjoy Das     return true;
33150fef432SSanjoy Das   }
33250fef432SSanjoy Das 
33350fef432SSanjoy Das   auto DependenceItr = *DepResult.PotentialDependence;
33450fef432SSanjoy Das   auto *DependenceMI = *DependenceItr;
33550fef432SSanjoy Das 
33650fef432SSanjoy Das   // We don't want to reason about speculating loads.  Note -- at this point
33750fef432SSanjoy Das   // we should have already filtered out all of the other non-speculatable
33850fef432SSanjoy Das   // things, like calls and stores.
33950fef432SSanjoy Das   assert(canHandle(DependenceMI) && "Should never have reached here!");
34050fef432SSanjoy Das   if (DependenceMI->mayLoad())
34150fef432SSanjoy Das     return false;
34250fef432SSanjoy Das 
34350fef432SSanjoy Das   for (auto &DependenceMO : DependenceMI->operands()) {
34450fef432SSanjoy Das     if (!(DependenceMO.isReg() && DependenceMO.getReg()))
34550fef432SSanjoy Das       continue;
34650fef432SSanjoy Das 
34750fef432SSanjoy Das     // Make sure that we won't clobber any live ins to the sibling block by
34850fef432SSanjoy Das     // hoisting Dependency.  For instance, we can't hoist INST to before the
34950fef432SSanjoy Das     // null check (even if it safe, and does not violate any dependencies in
35050fef432SSanjoy Das     // the non_null_block) if %rdx is live in to _null_block.
35150fef432SSanjoy Das     //
35250fef432SSanjoy Das     //    test %rcx, %rcx
35350fef432SSanjoy Das     //    je _null_block
35450fef432SSanjoy Das     //  _non_null_block:
35550fef432SSanjoy Das     //    %rdx<def> = INST
35650fef432SSanjoy Das     //    ...
35750fef432SSanjoy Das     //
35850fef432SSanjoy Das     // This restriction does not apply to the faulting load inst because in
35950fef432SSanjoy Das     // case the pointer loaded from is in the null page, the load will not
36050fef432SSanjoy Das     // semantically execute, and affect machine state.  That is, if the load
36150fef432SSanjoy Das     // was loading into %rax and it faults, the value of %rax should stay the
36250fef432SSanjoy Das     // same as it would have been had the load not have executed and we'd have
36350fef432SSanjoy Das     // branched to NullSucc directly.
36450fef432SSanjoy Das     if (AnyAliasLiveIn(TRI, NullSucc, DependenceMO.getReg()))
36550fef432SSanjoy Das       return false;
36650fef432SSanjoy Das 
36750fef432SSanjoy Das     // The Dependency can't be re-defining the base register -- then we won't
36850fef432SSanjoy Das     // get the memory operation on the address we want.  This is already
36950fef432SSanjoy Das     // checked in \c IsSuitableMemoryOp.
370*08da2e28SSanjoy Das     assert(!(DependenceMO.isDef() &&
371*08da2e28SSanjoy Das              TRI->regsOverlap(DependenceMO.getReg(), PointerReg)) &&
37250fef432SSanjoy Das            "Should have been checked before!");
37350fef432SSanjoy Das   }
37450fef432SSanjoy Das 
37550fef432SSanjoy Das   auto DepDepResult =
37650fef432SSanjoy Das       computeDependence(DependenceMI, {InstsSeenSoFar.begin(), DependenceItr});
37750fef432SSanjoy Das 
37850fef432SSanjoy Das   if (!DepDepResult.CanReorder || DepDepResult.PotentialDependence)
37950fef432SSanjoy Das     return false;
38050fef432SSanjoy Das 
38150fef432SSanjoy Das   Dependence = DependenceMI;
38250fef432SSanjoy Das   return true;
38350fef432SSanjoy Das }
38450fef432SSanjoy Das 
38569fad079SSanjoy Das /// Analyze MBB to check if its terminating branch can be turned into an
38669fad079SSanjoy Das /// implicit null check.  If yes, append a description of the said null check to
38769fad079SSanjoy Das /// NullCheckList and return true, else return false.
38869fad079SSanjoy Das bool ImplicitNullChecks::analyzeBlockForNullChecks(
38969fad079SSanjoy Das     MachineBasicBlock &MBB, SmallVectorImpl<NullCheck> &NullCheckList) {
39069fad079SSanjoy Das   typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate;
39169fad079SSanjoy Das 
392e8b81649SSanjoy Das   MDNode *BranchMD = nullptr;
393e8b81649SSanjoy Das   if (auto *BB = MBB.getBasicBlock())
394e8b81649SSanjoy Das     BranchMD = BB->getTerminator()->getMetadata(LLVMContext::MD_make_implicit);
395e8b81649SSanjoy Das 
3969c41a93eSSanjoy Das   if (!BranchMD)
3979c41a93eSSanjoy Das     return false;
3989c41a93eSSanjoy Das 
39969fad079SSanjoy Das   MachineBranchPredicate MBP;
40069fad079SSanjoy Das 
40171c30a14SJacques Pienaar   if (TII->analyzeBranchPredicate(MBB, MBP, true))
40269fad079SSanjoy Das     return false;
40369fad079SSanjoy Das 
40469fad079SSanjoy Das   // Is the predicate comparing an integer to zero?
40569fad079SSanjoy Das   if (!(MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 &&
40669fad079SSanjoy Das         (MBP.Predicate == MachineBranchPredicate::PRED_NE ||
40769fad079SSanjoy Das          MBP.Predicate == MachineBranchPredicate::PRED_EQ)))
40869fad079SSanjoy Das     return false;
40969fad079SSanjoy Das 
41069fad079SSanjoy Das   // If we cannot erase the test instruction itself, then making the null check
41169fad079SSanjoy Das   // implicit does not buy us much.
41269fad079SSanjoy Das   if (!MBP.SingleUseCondition)
41369fad079SSanjoy Das     return false;
41469fad079SSanjoy Das 
41569fad079SSanjoy Das   MachineBasicBlock *NotNullSucc, *NullSucc;
41669fad079SSanjoy Das 
41769fad079SSanjoy Das   if (MBP.Predicate == MachineBranchPredicate::PRED_NE) {
41869fad079SSanjoy Das     NotNullSucc = MBP.TrueDest;
41969fad079SSanjoy Das     NullSucc = MBP.FalseDest;
42069fad079SSanjoy Das   } else {
42169fad079SSanjoy Das     NotNullSucc = MBP.FalseDest;
42269fad079SSanjoy Das     NullSucc = MBP.TrueDest;
42369fad079SSanjoy Das   }
42469fad079SSanjoy Das 
42569fad079SSanjoy Das   // We handle the simplest case for now.  We can potentially do better by using
42669fad079SSanjoy Das   // the machine dominator tree.
42769fad079SSanjoy Das   if (NotNullSucc->pred_size() != 1)
42869fad079SSanjoy Das     return false;
42969fad079SSanjoy Das 
43069fad079SSanjoy Das   // Starting with a code fragment like:
43169fad079SSanjoy Das   //
43269fad079SSanjoy Das   //   test %RAX, %RAX
43369fad079SSanjoy Das   //   jne LblNotNull
43469fad079SSanjoy Das   //
43569fad079SSanjoy Das   //  LblNull:
43669fad079SSanjoy Das   //   callq throw_NullPointerException
43769fad079SSanjoy Das   //
43869fad079SSanjoy Das   //  LblNotNull:
439b7718454SSanjoy Das   //   Inst0
440b7718454SSanjoy Das   //   Inst1
441b7718454SSanjoy Das   //   ...
44269fad079SSanjoy Das   //   Def = Load (%RAX + <offset>)
44369fad079SSanjoy Das   //   ...
44469fad079SSanjoy Das   //
44569fad079SSanjoy Das   //
44669fad079SSanjoy Das   // we want to end up with
44769fad079SSanjoy Das   //
448ac9c5b19SSanjoy Das   //   Def = FaultingLoad (%RAX + <offset>), LblNull
44969fad079SSanjoy Das   //   jmp LblNotNull ;; explicit or fallthrough
45069fad079SSanjoy Das   //
45169fad079SSanjoy Das   //  LblNotNull:
452b7718454SSanjoy Das   //   Inst0
453b7718454SSanjoy Das   //   Inst1
45469fad079SSanjoy Das   //   ...
45569fad079SSanjoy Das   //
45669fad079SSanjoy Das   //  LblNull:
45769fad079SSanjoy Das   //   callq throw_NullPointerException
45869fad079SSanjoy Das   //
459ac9c5b19SSanjoy Das   //
460ac9c5b19SSanjoy Das   // To see why this is legal, consider the two possibilities:
461ac9c5b19SSanjoy Das   //
462ac9c5b19SSanjoy Das   //  1. %RAX is null: since we constrain <offset> to be less than PageSize, the
463ac9c5b19SSanjoy Das   //     load instruction dereferences the null page, causing a segmentation
464ac9c5b19SSanjoy Das   //     fault.
465ac9c5b19SSanjoy Das   //
466ac9c5b19SSanjoy Das   //  2. %RAX is not null: in this case we know that the load cannot fault, as
467ac9c5b19SSanjoy Das   //     otherwise the load would've faulted in the original program too and the
468ac9c5b19SSanjoy Das   //     original program would've been undefined.
469ac9c5b19SSanjoy Das   //
470ac9c5b19SSanjoy Das   // This reasoning cannot be extended to justify hoisting through arbitrary
471ac9c5b19SSanjoy Das   // control flow.  For instance, in the example below (in pseudo-C)
472ac9c5b19SSanjoy Das   //
473ac9c5b19SSanjoy Das   //    if (ptr == null) { throw_npe(); unreachable; }
474ac9c5b19SSanjoy Das   //    if (some_cond) { return 42; }
475ac9c5b19SSanjoy Das   //    v = ptr->field;  // LD
476ac9c5b19SSanjoy Das   //    ...
477ac9c5b19SSanjoy Das   //
478ac9c5b19SSanjoy Das   // we cannot (without code duplication) use the load marked "LD" to null check
479ac9c5b19SSanjoy Das   // ptr -- clause (2) above does not apply in this case.  In the above program
480ac9c5b19SSanjoy Das   // the safety of ptr->field can be dependent on some_cond; and, for instance,
481ac9c5b19SSanjoy Das   // ptr could be some non-null invalid reference that never gets loaded from
482ac9c5b19SSanjoy Das   // because some_cond is always true.
48369fad079SSanjoy Das 
4849a129807SSanjoy Das   const unsigned PointerReg = MBP.LHS.getReg();
485b7718454SSanjoy Das 
4869a129807SSanjoy Das   SmallVector<MachineInstr *, 8> InstsSeenSoFar;
487b7718454SSanjoy Das 
4889a129807SSanjoy Das   for (auto &MI : *NotNullSucc) {
4899a129807SSanjoy Das     if (!canHandle(&MI) || InstsSeenSoFar.size() >= MaxInstsToConsider)
4909a129807SSanjoy Das       return false;
491e57bf680SSanjoy Das 
4929a129807SSanjoy Das     MachineInstr *Dependence;
49315e50b51SSanjoy Das     SuitabilityResult SR = isSuitableMemoryOp(MI, PointerReg, InstsSeenSoFar);
49415e50b51SSanjoy Das     if (SR == SR_Impossible)
49515e50b51SSanjoy Das       return false;
49615e50b51SSanjoy Das     if (SR == SR_Suitable && canHoistLoadInst(&MI, PointerReg, InstsSeenSoFar,
49715e50b51SSanjoy Das                                               NullSucc, Dependence)) {
4989cfc75c2SDuncan P. N. Exon Smith       NullCheckList.emplace_back(&MI, MBP.ConditionDef, &MBB, NotNullSucc,
4999a129807SSanjoy Das                                  NullSucc, Dependence);
500e57bf680SSanjoy Das       return true;
501e57bf680SSanjoy Das     }
50269fad079SSanjoy Das 
5039a129807SSanjoy Das     InstsSeenSoFar.push_back(&MI);
504b7718454SSanjoy Das   }
505b7718454SSanjoy Das 
50669fad079SSanjoy Das   return false;
50769fad079SSanjoy Das }
50869fad079SSanjoy Das 
50969fad079SSanjoy Das /// Wrap a machine load instruction, LoadMI, into a FAULTING_LOAD_OP machine
51069fad079SSanjoy Das /// instruction.  The FAULTING_LOAD_OP instruction does the same load as LoadMI
5114e1d389aSQuentin Colombet /// (defining the same register), and branches to HandlerMBB if the load
51269fad079SSanjoy Das /// faults.  The FAULTING_LOAD_OP instruction is inserted at the end of MBB.
5134e1d389aSQuentin Colombet MachineInstr *
5144e1d389aSQuentin Colombet ImplicitNullChecks::insertFaultingLoad(MachineInstr *LoadMI,
51569fad079SSanjoy Das                                        MachineBasicBlock *MBB,
5164e1d389aSQuentin Colombet                                        MachineBasicBlock *HandlerMBB) {
51793d608c3SSanjoy Das   const unsigned NoRegister = 0; // Guaranteed to be the NoRegister value for
51893d608c3SSanjoy Das                                  // all targets.
51993d608c3SSanjoy Das 
52069fad079SSanjoy Das   DebugLoc DL;
52169fad079SSanjoy Das   unsigned NumDefs = LoadMI->getDesc().getNumDefs();
52293d608c3SSanjoy Das   assert(NumDefs <= 1 && "other cases unhandled!");
52369fad079SSanjoy Das 
52493d608c3SSanjoy Das   unsigned DefReg = NoRegister;
52593d608c3SSanjoy Das   if (NumDefs != 0) {
52693d608c3SSanjoy Das     DefReg = LoadMI->defs().begin()->getReg();
52769fad079SSanjoy Das     assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 &&
52869fad079SSanjoy Das            "expected exactly one def!");
52993d608c3SSanjoy Das   }
53069fad079SSanjoy Das 
53169fad079SSanjoy Das   auto MIB = BuildMI(MBB, DL, TII->get(TargetOpcode::FAULTING_LOAD_OP), DefReg)
5324e1d389aSQuentin Colombet                  .addMBB(HandlerMBB)
53369fad079SSanjoy Das                  .addImm(LoadMI->getOpcode());
53469fad079SSanjoy Das 
53569fad079SSanjoy Das   for (auto &MO : LoadMI->uses())
536116bbab4SDiana Picus     MIB.add(MO);
53769fad079SSanjoy Das 
53869fad079SSanjoy Das   MIB.setMemRefs(LoadMI->memoperands_begin(), LoadMI->memoperands_end());
53969fad079SSanjoy Das 
54069fad079SSanjoy Das   return MIB;
54169fad079SSanjoy Das }
54269fad079SSanjoy Das 
54369fad079SSanjoy Das /// Rewrite the null checks in NullCheckList into implicit null checks.
54469fad079SSanjoy Das void ImplicitNullChecks::rewriteNullChecks(
54569fad079SSanjoy Das     ArrayRef<ImplicitNullChecks::NullCheck> NullCheckList) {
54669fad079SSanjoy Das   DebugLoc DL;
54769fad079SSanjoy Das 
54869fad079SSanjoy Das   for (auto &NC : NullCheckList) {
54969fad079SSanjoy Das     // Remove the conditional branch dependent on the null check.
5501b9fc8edSMatt Arsenault     unsigned BranchesRemoved = TII->removeBranch(*NC.getCheckBlock());
55169fad079SSanjoy Das     (void)BranchesRemoved;
55269fad079SSanjoy Das     assert(BranchesRemoved > 0 && "expected at least one branch!");
55369fad079SSanjoy Das 
554e57bf680SSanjoy Das     if (auto *DepMI = NC.getOnlyDependency()) {
555e57bf680SSanjoy Das       DepMI->removeFromParent();
556e57bf680SSanjoy Das       NC.getCheckBlock()->insert(NC.getCheckBlock()->end(), DepMI);
557e57bf680SSanjoy Das     }
558e57bf680SSanjoy Das 
55969fad079SSanjoy Das     // Insert a faulting load where the conditional branch was originally.  We
56069fad079SSanjoy Das     // check earlier ensures that this bit of code motion is legal.  We do not
56169fad079SSanjoy Das     // touch the successors list for any basic block since we haven't changed
56269fad079SSanjoy Das     // control flow, we've just made it implicit.
563e173b9aeSSanjoy Das     MachineInstr *FaultingLoad = insertFaultingLoad(
564e173b9aeSSanjoy Das         NC.getMemOperation(), NC.getCheckBlock(), NC.getNullSucc());
56526dab3a4SQuentin Colombet     // Now the values defined by MemOperation, if any, are live-in of
56626dab3a4SQuentin Colombet     // the block of MemOperation.
56726dab3a4SQuentin Colombet     // The original load operation may define implicit-defs alongside
56826dab3a4SQuentin Colombet     // the loaded value.
569e173b9aeSSanjoy Das     MachineBasicBlock *MBB = NC.getMemOperation()->getParent();
57026dab3a4SQuentin Colombet     for (const MachineOperand &MO : FaultingLoad->operands()) {
57126dab3a4SQuentin Colombet       if (!MO.isReg() || !MO.isDef())
57226dab3a4SQuentin Colombet         continue;
57326dab3a4SQuentin Colombet       unsigned Reg = MO.getReg();
57426dab3a4SQuentin Colombet       if (!Reg || MBB->isLiveIn(Reg))
57526dab3a4SQuentin Colombet         continue;
57612b69919SQuentin Colombet       MBB->addLiveIn(Reg);
57712b69919SQuentin Colombet     }
578e57bf680SSanjoy Das 
579e57bf680SSanjoy Das     if (auto *DepMI = NC.getOnlyDependency()) {
580e57bf680SSanjoy Das       for (auto &MO : DepMI->operands()) {
581e57bf680SSanjoy Das         if (!MO.isReg() || !MO.getReg() || !MO.isDef())
582e57bf680SSanjoy Das           continue;
583e57bf680SSanjoy Das         if (!NC.getNotNullSucc()->isLiveIn(MO.getReg()))
584e57bf680SSanjoy Das           NC.getNotNullSucc()->addLiveIn(MO.getReg());
585e57bf680SSanjoy Das       }
586e57bf680SSanjoy Das     }
587e57bf680SSanjoy Das 
588e173b9aeSSanjoy Das     NC.getMemOperation()->eraseFromParent();
589e173b9aeSSanjoy Das     NC.getCheckOperation()->eraseFromParent();
59069fad079SSanjoy Das 
59169fad079SSanjoy Das     // Insert an *unconditional* branch to not-null successor.
592e8e0f5caSMatt Arsenault     TII->insertBranch(*NC.getCheckBlock(), NC.getNotNullSucc(), nullptr,
593e173b9aeSSanjoy Das                       /*Cond=*/None, DL);
59469fad079SSanjoy Das 
5958ee6a30bSSanjoy Das     NumImplicitNullChecks++;
59669fad079SSanjoy Das   }
59769fad079SSanjoy Das }
59869fad079SSanjoy Das 
5999a129807SSanjoy Das 
60069fad079SSanjoy Das char ImplicitNullChecks::ID = 0;
60169fad079SSanjoy Das char &llvm::ImplicitNullChecksID = ImplicitNullChecks::ID;
60269fad079SSanjoy Das INITIALIZE_PASS_BEGIN(ImplicitNullChecks, "implicit-null-checks",
60369fad079SSanjoy Das                       "Implicit null checks", false, false)
604e57bf680SSanjoy Das INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
60569fad079SSanjoy Das INITIALIZE_PASS_END(ImplicitNullChecks, "implicit-null-checks",
60669fad079SSanjoy Das                     "Implicit null checks", false, false)
607