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" 31*e57bf680SSanjoy 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 548ee6a30bSSanjoy Das #define DEBUG_TYPE "implicit-null-checks" 558ee6a30bSSanjoy Das 568ee6a30bSSanjoy Das STATISTIC(NumImplicitNullChecks, 578ee6a30bSSanjoy Das "Number of explicit null checks made implicit"); 588ee6a30bSSanjoy Das 5969fad079SSanjoy Das namespace { 6069fad079SSanjoy Das 6169fad079SSanjoy Das class ImplicitNullChecks : public MachineFunctionPass { 6269fad079SSanjoy Das /// Represents one null check that can be made implicit. 63e173b9aeSSanjoy Das class NullCheck { 6469fad079SSanjoy Das // The memory operation the null check can be folded into. 6569fad079SSanjoy Das MachineInstr *MemOperation; 6669fad079SSanjoy Das 6769fad079SSanjoy Das // The instruction actually doing the null check (Ptr != 0). 6869fad079SSanjoy Das MachineInstr *CheckOperation; 6969fad079SSanjoy Das 7069fad079SSanjoy Das // The block the check resides in. 7169fad079SSanjoy Das MachineBasicBlock *CheckBlock; 7269fad079SSanjoy Das 73572e03a3SEric Christopher // The block branched to if the pointer is non-null. 7469fad079SSanjoy Das MachineBasicBlock *NotNullSucc; 7569fad079SSanjoy Das 76572e03a3SEric Christopher // The block branched to if the pointer is null. 7769fad079SSanjoy Das MachineBasicBlock *NullSucc; 7869fad079SSanjoy Das 79*e57bf680SSanjoy Das // If this is non-null, then MemOperation has a dependency on on this 80*e57bf680SSanjoy Das // instruction; and it needs to be hoisted to execute before MemOperation. 81*e57bf680SSanjoy Das MachineInstr *OnlyDependency; 82*e57bf680SSanjoy Das 83e173b9aeSSanjoy Das public: 8469fad079SSanjoy Das explicit NullCheck(MachineInstr *memOperation, MachineInstr *checkOperation, 8569fad079SSanjoy Das MachineBasicBlock *checkBlock, 8669fad079SSanjoy Das MachineBasicBlock *notNullSucc, 87*e57bf680SSanjoy Das MachineBasicBlock *nullSucc, 88*e57bf680SSanjoy Das MachineInstr *onlyDependency) 8969fad079SSanjoy Das : MemOperation(memOperation), CheckOperation(checkOperation), 90*e57bf680SSanjoy Das CheckBlock(checkBlock), NotNullSucc(notNullSucc), NullSucc(nullSucc), 91*e57bf680SSanjoy Das OnlyDependency(onlyDependency) {} 92e173b9aeSSanjoy Das 93e173b9aeSSanjoy Das MachineInstr *getMemOperation() const { return MemOperation; } 94e173b9aeSSanjoy Das 95e173b9aeSSanjoy Das MachineInstr *getCheckOperation() const { return CheckOperation; } 96e173b9aeSSanjoy Das 97e173b9aeSSanjoy Das MachineBasicBlock *getCheckBlock() const { return CheckBlock; } 98e173b9aeSSanjoy Das 99e173b9aeSSanjoy Das MachineBasicBlock *getNotNullSucc() const { return NotNullSucc; } 100e173b9aeSSanjoy Das 101e173b9aeSSanjoy Das MachineBasicBlock *getNullSucc() const { return NullSucc; } 102*e57bf680SSanjoy Das 103*e57bf680SSanjoy Das MachineInstr *getOnlyDependency() const { return OnlyDependency; } 10469fad079SSanjoy Das }; 10569fad079SSanjoy Das 10669fad079SSanjoy Das const TargetInstrInfo *TII = nullptr; 10769fad079SSanjoy Das const TargetRegisterInfo *TRI = nullptr; 108*e57bf680SSanjoy Das AliasAnalysis *AA = nullptr; 10969fad079SSanjoy Das MachineModuleInfo *MMI = nullptr; 11069fad079SSanjoy Das 11169fad079SSanjoy Das bool analyzeBlockForNullChecks(MachineBasicBlock &MBB, 11269fad079SSanjoy Das SmallVectorImpl<NullCheck> &NullCheckList); 11369fad079SSanjoy Das MachineInstr *insertFaultingLoad(MachineInstr *LoadMI, MachineBasicBlock *MBB, 1144e1d389aSQuentin Colombet MachineBasicBlock *HandlerMBB); 11569fad079SSanjoy Das void rewriteNullChecks(ArrayRef<NullCheck> NullCheckList); 11669fad079SSanjoy Das 11769fad079SSanjoy Das public: 11869fad079SSanjoy Das static char ID; 11969fad079SSanjoy Das 12069fad079SSanjoy Das ImplicitNullChecks() : MachineFunctionPass(ID) { 12169fad079SSanjoy Das initializeImplicitNullChecksPass(*PassRegistry::getPassRegistry()); 12269fad079SSanjoy Das } 12369fad079SSanjoy Das 12469fad079SSanjoy Das bool runOnMachineFunction(MachineFunction &MF) override; 125*e57bf680SSanjoy Das void getAnalysisUsage(AnalysisUsage &AU) const override { 126*e57bf680SSanjoy Das AU.addRequired<AAResultsWrapperPass>(); 127*e57bf680SSanjoy Das MachineFunctionPass::getAnalysisUsage(AU); 128*e57bf680SSanjoy Das } 129ad154c83SDerek Schuff 130ad154c83SDerek Schuff MachineFunctionProperties getRequiredProperties() const override { 131ad154c83SDerek Schuff return MachineFunctionProperties().set( 132ad154c83SDerek Schuff MachineFunctionProperties::Property::AllVRegsAllocated); 133ad154c83SDerek Schuff } 13469fad079SSanjoy Das }; 135edc394f1SSanjoy Das 136edc394f1SSanjoy Das /// \brief Detect re-ordering hazards and dependencies. 137edc394f1SSanjoy Das /// 138edc394f1SSanjoy Das /// This class keeps track of defs and uses, and can be queried if a given 139edc394f1SSanjoy Das /// machine instruction can be re-ordered from after the machine instructions 140edc394f1SSanjoy Das /// seen so far to before them. 141edc394f1SSanjoy Das class HazardDetector { 142*e57bf680SSanjoy Das static MachineInstr *getUnknownMI() { 143*e57bf680SSanjoy Das return DenseMapInfo<MachineInstr *>::getTombstoneKey(); 144*e57bf680SSanjoy Das } 145*e57bf680SSanjoy Das 146*e57bf680SSanjoy Das // Maps physical registers to the instruction defining them. If there has 147*e57bf680SSanjoy Das // been more than one def of an specific register, that register is mapped to 148*e57bf680SSanjoy Das // getUnknownMI(). 149*e57bf680SSanjoy Das DenseMap<unsigned, MachineInstr *> RegDefs; 150edc394f1SSanjoy Das DenseSet<unsigned> RegUses; 151edc394f1SSanjoy Das const TargetRegisterInfo &TRI; 152edc394f1SSanjoy Das bool hasSeenClobber; 153*e57bf680SSanjoy Das AliasAnalysis &AA; 154edc394f1SSanjoy Das 155edc394f1SSanjoy Das public: 156*e57bf680SSanjoy Das explicit HazardDetector(const TargetRegisterInfo &TRI, AliasAnalysis &AA) 157*e57bf680SSanjoy Das : TRI(TRI), hasSeenClobber(false), AA(AA) {} 158edc394f1SSanjoy Das 159edc394f1SSanjoy Das /// \brief Make a note of \p MI for later queries to isSafeToHoist. 160edc394f1SSanjoy Das /// 161edc394f1SSanjoy Das /// May clobber this HazardDetector instance. \see isClobbered. 162edc394f1SSanjoy Das void rememberInstruction(MachineInstr *MI); 163edc394f1SSanjoy Das 164edc394f1SSanjoy Das /// \brief Return true if it is safe to hoist \p MI from after all the 165*e57bf680SSanjoy Das /// instructions seen so far (via rememberInstruction) to before it. If \p MI 166*e57bf680SSanjoy Das /// has one and only one transitive dependency, set \p Dependency to that 167*e57bf680SSanjoy Das /// instruction. If there are more dependencies, return false. 168*e57bf680SSanjoy Das bool isSafeToHoist(MachineInstr *MI, MachineInstr *&Dependency); 169edc394f1SSanjoy Das 170edc394f1SSanjoy Das /// \brief Return true if this instance of HazardDetector has been clobbered 171edc394f1SSanjoy Das /// (i.e. has no more useful information). 172edc394f1SSanjoy Das /// 173edc394f1SSanjoy Das /// A HazardDetecter is clobbered when it sees a construct it cannot 174edc394f1SSanjoy Das /// understand, and it would have to return a conservative answer for all 175edc394f1SSanjoy Das /// future queries. Having a separate clobbered state lets the client code 176edc394f1SSanjoy Das /// bail early, without making queries about all of the future instructions 177edc394f1SSanjoy Das /// (which would have returned the most conservative answer anyway). 178edc394f1SSanjoy Das /// 179edc394f1SSanjoy Das /// Calling rememberInstruction or isSafeToHoist on a clobbered HazardDetector 180edc394f1SSanjoy Das /// is an error. 181edc394f1SSanjoy Das bool isClobbered() { return hasSeenClobber; } 182edc394f1SSanjoy Das }; 183edc394f1SSanjoy Das } 184edc394f1SSanjoy Das 185edc394f1SSanjoy Das 186edc394f1SSanjoy Das void HazardDetector::rememberInstruction(MachineInstr *MI) { 187edc394f1SSanjoy Das assert(!isClobbered() && 188edc394f1SSanjoy Das "Don't add instructions to a clobbered hazard detector"); 189edc394f1SSanjoy Das 190edc394f1SSanjoy Das if (MI->mayStore() || MI->hasUnmodeledSideEffects()) { 191edc394f1SSanjoy Das hasSeenClobber = true; 192edc394f1SSanjoy Das return; 193edc394f1SSanjoy Das } 194edc394f1SSanjoy Das 195edc394f1SSanjoy Das for (auto *MMO : MI->memoperands()) { 196edc394f1SSanjoy Das // Right now we don't want to worry about LLVM's memory model. 197edc394f1SSanjoy Das if (!MMO->isUnordered()) { 198edc394f1SSanjoy Das hasSeenClobber = true; 199edc394f1SSanjoy Das return; 200edc394f1SSanjoy Das } 201edc394f1SSanjoy Das } 202edc394f1SSanjoy Das 203edc394f1SSanjoy Das for (auto &MO : MI->operands()) { 204edc394f1SSanjoy Das if (!MO.isReg() || !MO.getReg()) 205edc394f1SSanjoy Das continue; 206edc394f1SSanjoy Das 207*e57bf680SSanjoy Das if (MO.isDef()) { 208*e57bf680SSanjoy Das auto It = RegDefs.find(MO.getReg()); 209*e57bf680SSanjoy Das if (It == RegDefs.end()) 210*e57bf680SSanjoy Das RegDefs.insert({MO.getReg(), MI}); 211*e57bf680SSanjoy Das else { 212*e57bf680SSanjoy Das assert(It->second && "Found null MI?"); 213*e57bf680SSanjoy Das It->second = getUnknownMI(); 214*e57bf680SSanjoy Das } 215*e57bf680SSanjoy Das } else 216edc394f1SSanjoy Das RegUses.insert(MO.getReg()); 217edc394f1SSanjoy Das } 218edc394f1SSanjoy Das } 219edc394f1SSanjoy Das 220*e57bf680SSanjoy Das bool HazardDetector::isSafeToHoist(MachineInstr *MI, 221*e57bf680SSanjoy Das MachineInstr *&Dependency) { 222edc394f1SSanjoy Das assert(!isClobbered() && "isSafeToHoist cannot do anything useful!"); 223*e57bf680SSanjoy Das Dependency = nullptr; 224edc394f1SSanjoy Das 225edc394f1SSanjoy Das // Right now we don't want to worry about LLVM's memory model. This can be 226edc394f1SSanjoy Das // made more precise later. 227edc394f1SSanjoy Das for (auto *MMO : MI->memoperands()) 228edc394f1SSanjoy Das if (!MMO->isUnordered()) 229edc394f1SSanjoy Das return false; 230edc394f1SSanjoy Das 231edc394f1SSanjoy Das for (auto &MO : MI->operands()) { 232edc394f1SSanjoy Das if (MO.isReg() && MO.getReg()) { 233*e57bf680SSanjoy Das for (auto &RegDef : RegDefs) { 234*e57bf680SSanjoy Das unsigned Reg = RegDef.first; 235*e57bf680SSanjoy Das MachineInstr *MI = RegDef.second; 236*e57bf680SSanjoy Das if (!TRI.regsOverlap(Reg, MO.getReg())) 237*e57bf680SSanjoy Das continue; 238*e57bf680SSanjoy Das 239*e57bf680SSanjoy Das // We found a write-after-write or read-after-write, see if the 240*e57bf680SSanjoy Das // instruction causing this dependency can be hoisted too. 241*e57bf680SSanjoy Das 242*e57bf680SSanjoy Das if (MI == getUnknownMI()) 243*e57bf680SSanjoy Das // We don't have precise dependency information. 244*e57bf680SSanjoy Das return false; 245*e57bf680SSanjoy Das 246*e57bf680SSanjoy Das if (Dependency) { 247*e57bf680SSanjoy Das if (Dependency == MI) 248*e57bf680SSanjoy Das continue; 249*e57bf680SSanjoy Das // We already have one dependency, and we can track only one. 250*e57bf680SSanjoy Das return false; 251*e57bf680SSanjoy Das } 252*e57bf680SSanjoy Das 253*e57bf680SSanjoy Das // Now check if MI is actually a dependency that can be hoisted. 254*e57bf680SSanjoy Das 255*e57bf680SSanjoy Das // We don't want to track transitive dependencies. We already know that 256*e57bf680SSanjoy Das // MI is the only instruction that defines Reg, but we need to be sure 257*e57bf680SSanjoy Das // that it does not use any registers that have been defined (trivially 258*e57bf680SSanjoy Das // checked below by ensuring that there are no register uses), and that 259*e57bf680SSanjoy Das // it is the only def for every register it defines (otherwise we could 260*e57bf680SSanjoy Das // violate a write after write hazard). 261*e57bf680SSanjoy Das auto IsMIOperandSafe = [&](MachineOperand &MO) { 262*e57bf680SSanjoy Das if (!MO.isReg() || !MO.getReg()) 263*e57bf680SSanjoy Das return true; 264*e57bf680SSanjoy Das if (MO.isUse()) 265*e57bf680SSanjoy Das return false; 266*e57bf680SSanjoy Das assert((!MO.isDef() || RegDefs.count(MO.getReg())) && 267*e57bf680SSanjoy Das "All defs must be tracked in RegDefs by now!"); 268*e57bf680SSanjoy Das return !MO.isDef() || RegDefs.find(MO.getReg())->second == MI; 269*e57bf680SSanjoy Das }; 270*e57bf680SSanjoy Das 271*e57bf680SSanjoy Das if (!all_of(MI->operands(), IsMIOperandSafe)) 272*e57bf680SSanjoy Das return false; 273*e57bf680SSanjoy Das 274*e57bf680SSanjoy Das // Now check for speculation safety: 275*e57bf680SSanjoy Das bool SawStore = true; 276*e57bf680SSanjoy Das if (!MI->isSafeToMove(&AA, SawStore) || MI->mayLoad()) 277*e57bf680SSanjoy Das return false; 278*e57bf680SSanjoy Das 279*e57bf680SSanjoy Das Dependency = MI; 280*e57bf680SSanjoy Das } 281edc394f1SSanjoy Das 282edc394f1SSanjoy Das if (MO.isDef()) 283edc394f1SSanjoy Das for (unsigned Reg : RegUses) 284edc394f1SSanjoy Das if (TRI.regsOverlap(Reg, MO.getReg())) 285edc394f1SSanjoy Das return false; // We found a write-after-read 286edc394f1SSanjoy Das } 287edc394f1SSanjoy Das } 288edc394f1SSanjoy Das 289edc394f1SSanjoy Das return true; 290f00654e3SAlexander Kornienko } 29169fad079SSanjoy Das 29269fad079SSanjoy Das bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) { 29369fad079SSanjoy Das TII = MF.getSubtarget().getInstrInfo(); 29469fad079SSanjoy Das TRI = MF.getRegInfo().getTargetRegisterInfo(); 29569fad079SSanjoy Das MMI = &MF.getMMI(); 296*e57bf680SSanjoy Das AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); 29769fad079SSanjoy Das 29869fad079SSanjoy Das SmallVector<NullCheck, 16> NullCheckList; 29969fad079SSanjoy Das 30069fad079SSanjoy Das for (auto &MBB : MF) 30169fad079SSanjoy Das analyzeBlockForNullChecks(MBB, NullCheckList); 30269fad079SSanjoy Das 30369fad079SSanjoy Das if (!NullCheckList.empty()) 30469fad079SSanjoy Das rewriteNullChecks(NullCheckList); 30569fad079SSanjoy Das 30669fad079SSanjoy Das return !NullCheckList.empty(); 30769fad079SSanjoy Das } 30869fad079SSanjoy Das 309*e57bf680SSanjoy Das // Return true if any register aliasing \p Reg is live-in into \p MBB. 310*e57bf680SSanjoy Das static bool AnyAliasLiveIn(const TargetRegisterInfo *TRI, 311*e57bf680SSanjoy Das MachineBasicBlock *MBB, unsigned Reg) { 312*e57bf680SSanjoy Das for (MCRegAliasIterator AR(Reg, TRI, /*IncludeSelf*/ true); AR.isValid(); 313*e57bf680SSanjoy Das ++AR) 314*e57bf680SSanjoy Das if (MBB->isLiveIn(*AR)) 315*e57bf680SSanjoy Das return true; 316*e57bf680SSanjoy Das return false; 317*e57bf680SSanjoy Das } 318*e57bf680SSanjoy Das 31969fad079SSanjoy Das /// Analyze MBB to check if its terminating branch can be turned into an 32069fad079SSanjoy Das /// implicit null check. If yes, append a description of the said null check to 32169fad079SSanjoy Das /// NullCheckList and return true, else return false. 32269fad079SSanjoy Das bool ImplicitNullChecks::analyzeBlockForNullChecks( 32369fad079SSanjoy Das MachineBasicBlock &MBB, SmallVectorImpl<NullCheck> &NullCheckList) { 32469fad079SSanjoy Das typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate; 32569fad079SSanjoy Das 326e8b81649SSanjoy Das MDNode *BranchMD = nullptr; 327e8b81649SSanjoy Das if (auto *BB = MBB.getBasicBlock()) 328e8b81649SSanjoy Das BranchMD = BB->getTerminator()->getMetadata(LLVMContext::MD_make_implicit); 329e8b81649SSanjoy Das 3309c41a93eSSanjoy Das if (!BranchMD) 3319c41a93eSSanjoy Das return false; 3329c41a93eSSanjoy Das 33369fad079SSanjoy Das MachineBranchPredicate MBP; 33469fad079SSanjoy Das 33569fad079SSanjoy Das if (TII->AnalyzeBranchPredicate(MBB, MBP, true)) 33669fad079SSanjoy Das return false; 33769fad079SSanjoy Das 33869fad079SSanjoy Das // Is the predicate comparing an integer to zero? 33969fad079SSanjoy Das if (!(MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 && 34069fad079SSanjoy Das (MBP.Predicate == MachineBranchPredicate::PRED_NE || 34169fad079SSanjoy Das MBP.Predicate == MachineBranchPredicate::PRED_EQ))) 34269fad079SSanjoy Das return false; 34369fad079SSanjoy Das 34469fad079SSanjoy Das // If we cannot erase the test instruction itself, then making the null check 34569fad079SSanjoy Das // implicit does not buy us much. 34669fad079SSanjoy Das if (!MBP.SingleUseCondition) 34769fad079SSanjoy Das return false; 34869fad079SSanjoy Das 34969fad079SSanjoy Das MachineBasicBlock *NotNullSucc, *NullSucc; 35069fad079SSanjoy Das 35169fad079SSanjoy Das if (MBP.Predicate == MachineBranchPredicate::PRED_NE) { 35269fad079SSanjoy Das NotNullSucc = MBP.TrueDest; 35369fad079SSanjoy Das NullSucc = MBP.FalseDest; 35469fad079SSanjoy Das } else { 35569fad079SSanjoy Das NotNullSucc = MBP.FalseDest; 35669fad079SSanjoy Das NullSucc = MBP.TrueDest; 35769fad079SSanjoy Das } 35869fad079SSanjoy Das 35969fad079SSanjoy Das // We handle the simplest case for now. We can potentially do better by using 36069fad079SSanjoy Das // the machine dominator tree. 36169fad079SSanjoy Das if (NotNullSucc->pred_size() != 1) 36269fad079SSanjoy Das return false; 36369fad079SSanjoy Das 36469fad079SSanjoy Das // Starting with a code fragment like: 36569fad079SSanjoy Das // 36669fad079SSanjoy Das // test %RAX, %RAX 36769fad079SSanjoy Das // jne LblNotNull 36869fad079SSanjoy Das // 36969fad079SSanjoy Das // LblNull: 37069fad079SSanjoy Das // callq throw_NullPointerException 37169fad079SSanjoy Das // 37269fad079SSanjoy Das // LblNotNull: 373b7718454SSanjoy Das // Inst0 374b7718454SSanjoy Das // Inst1 375b7718454SSanjoy Das // ... 37669fad079SSanjoy Das // Def = Load (%RAX + <offset>) 37769fad079SSanjoy Das // ... 37869fad079SSanjoy Das // 37969fad079SSanjoy Das // 38069fad079SSanjoy Das // we want to end up with 38169fad079SSanjoy Das // 382ac9c5b19SSanjoy Das // Def = FaultingLoad (%RAX + <offset>), LblNull 38369fad079SSanjoy Das // jmp LblNotNull ;; explicit or fallthrough 38469fad079SSanjoy Das // 38569fad079SSanjoy Das // LblNotNull: 386b7718454SSanjoy Das // Inst0 387b7718454SSanjoy Das // Inst1 38869fad079SSanjoy Das // ... 38969fad079SSanjoy Das // 39069fad079SSanjoy Das // LblNull: 39169fad079SSanjoy Das // callq throw_NullPointerException 39269fad079SSanjoy Das // 393ac9c5b19SSanjoy Das // 394ac9c5b19SSanjoy Das // To see why this is legal, consider the two possibilities: 395ac9c5b19SSanjoy Das // 396ac9c5b19SSanjoy Das // 1. %RAX is null: since we constrain <offset> to be less than PageSize, the 397ac9c5b19SSanjoy Das // load instruction dereferences the null page, causing a segmentation 398ac9c5b19SSanjoy Das // fault. 399ac9c5b19SSanjoy Das // 400ac9c5b19SSanjoy Das // 2. %RAX is not null: in this case we know that the load cannot fault, as 401ac9c5b19SSanjoy Das // otherwise the load would've faulted in the original program too and the 402ac9c5b19SSanjoy Das // original program would've been undefined. 403ac9c5b19SSanjoy Das // 404ac9c5b19SSanjoy Das // This reasoning cannot be extended to justify hoisting through arbitrary 405ac9c5b19SSanjoy Das // control flow. For instance, in the example below (in pseudo-C) 406ac9c5b19SSanjoy Das // 407ac9c5b19SSanjoy Das // if (ptr == null) { throw_npe(); unreachable; } 408ac9c5b19SSanjoy Das // if (some_cond) { return 42; } 409ac9c5b19SSanjoy Das // v = ptr->field; // LD 410ac9c5b19SSanjoy Das // ... 411ac9c5b19SSanjoy Das // 412ac9c5b19SSanjoy Das // we cannot (without code duplication) use the load marked "LD" to null check 413ac9c5b19SSanjoy Das // ptr -- clause (2) above does not apply in this case. In the above program 414ac9c5b19SSanjoy Das // the safety of ptr->field can be dependent on some_cond; and, for instance, 415ac9c5b19SSanjoy Das // ptr could be some non-null invalid reference that never gets loaded from 416ac9c5b19SSanjoy Das // because some_cond is always true. 41769fad079SSanjoy Das 41869fad079SSanjoy Das unsigned PointerReg = MBP.LHS.getReg(); 419b7718454SSanjoy Das 420*e57bf680SSanjoy Das HazardDetector HD(*TRI, *AA); 421b7718454SSanjoy Das 422b7718454SSanjoy Das for (auto MII = NotNullSucc->begin(), MIE = NotNullSucc->end(); MII != MIE; 423b7718454SSanjoy Das ++MII) { 424b7718454SSanjoy Das MachineInstr *MI = &*MII; 425c27a18f3SChad Rosier unsigned BaseReg; 426c27a18f3SChad Rosier int64_t Offset; 427*e57bf680SSanjoy Das MachineInstr *Dependency = nullptr; 428b7718454SSanjoy Das if (TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI)) 429b7718454SSanjoy Das if (MI->mayLoad() && !MI->isPredicable() && BaseReg == PointerReg && 43093d608c3SSanjoy Das Offset < PageSize && MI->getDesc().getNumDefs() <= 1 && 431*e57bf680SSanjoy Das HD.isSafeToHoist(MI, Dependency)) { 432*e57bf680SSanjoy Das 433*e57bf680SSanjoy Das auto DependencyOperandIsOk = [&](MachineOperand &MO) { 434*e57bf680SSanjoy Das assert(!(MO.isReg() && MO.isUse()) && 435*e57bf680SSanjoy Das "No transitive dependendencies please!"); 436*e57bf680SSanjoy Das if (!MO.isReg() || !MO.getReg() || !MO.isDef()) 43769fad079SSanjoy Das return true; 438*e57bf680SSanjoy Das 439*e57bf680SSanjoy Das // Make sure that we won't clobber any live ins to the sibling block 440*e57bf680SSanjoy Das // by hoisting Dependency. For instance, we can't hoist INST to 441*e57bf680SSanjoy Das // before the null check (even if it safe, and does not violate any 442*e57bf680SSanjoy Das // dependencies in the non_null_block) if %rdx is live in to 443*e57bf680SSanjoy Das // _null_block. 444*e57bf680SSanjoy Das // 445*e57bf680SSanjoy Das // test %rcx, %rcx 446*e57bf680SSanjoy Das // je _null_block 447*e57bf680SSanjoy Das // _non_null_block: 448*e57bf680SSanjoy Das // %rdx<def> = INST 449*e57bf680SSanjoy Das // ... 450*e57bf680SSanjoy Das if (AnyAliasLiveIn(TRI, NullSucc, MO.getReg())) 451*e57bf680SSanjoy Das return false; 452*e57bf680SSanjoy Das 453*e57bf680SSanjoy Das // Make sure Dependency isn't re-defining the base register. Then we 454*e57bf680SSanjoy Das // won't get the memory operation on the address we want. 455*e57bf680SSanjoy Das if (TRI->regsOverlap(MO.getReg(), BaseReg)) 456*e57bf680SSanjoy Das return false; 457*e57bf680SSanjoy Das 458*e57bf680SSanjoy Das return true; 459*e57bf680SSanjoy Das }; 460*e57bf680SSanjoy Das 461*e57bf680SSanjoy Das bool DependencyOperandsAreOk = 462*e57bf680SSanjoy Das !Dependency || 463*e57bf680SSanjoy Das all_of(Dependency->operands(), DependencyOperandIsOk); 464*e57bf680SSanjoy Das 465*e57bf680SSanjoy Das if (DependencyOperandsAreOk) { 466*e57bf680SSanjoy Das NullCheckList.emplace_back(MI, MBP.ConditionDef, &MBB, NotNullSucc, 467*e57bf680SSanjoy Das NullSucc, Dependency); 468*e57bf680SSanjoy Das return true; 469*e57bf680SSanjoy Das } 47069fad079SSanjoy Das } 47169fad079SSanjoy Das 472edc394f1SSanjoy Das HD.rememberInstruction(MI); 473edc394f1SSanjoy Das if (HD.isClobbered()) 474b7718454SSanjoy Das return false; 475b7718454SSanjoy Das } 476b7718454SSanjoy Das 47769fad079SSanjoy Das return false; 47869fad079SSanjoy Das } 47969fad079SSanjoy Das 48069fad079SSanjoy Das /// Wrap a machine load instruction, LoadMI, into a FAULTING_LOAD_OP machine 48169fad079SSanjoy Das /// instruction. The FAULTING_LOAD_OP instruction does the same load as LoadMI 4824e1d389aSQuentin Colombet /// (defining the same register), and branches to HandlerMBB if the load 48369fad079SSanjoy Das /// faults. The FAULTING_LOAD_OP instruction is inserted at the end of MBB. 4844e1d389aSQuentin Colombet MachineInstr * 4854e1d389aSQuentin Colombet ImplicitNullChecks::insertFaultingLoad(MachineInstr *LoadMI, 48669fad079SSanjoy Das MachineBasicBlock *MBB, 4874e1d389aSQuentin Colombet MachineBasicBlock *HandlerMBB) { 48893d608c3SSanjoy Das const unsigned NoRegister = 0; // Guaranteed to be the NoRegister value for 48993d608c3SSanjoy Das // all targets. 49093d608c3SSanjoy Das 49169fad079SSanjoy Das DebugLoc DL; 49269fad079SSanjoy Das unsigned NumDefs = LoadMI->getDesc().getNumDefs(); 49393d608c3SSanjoy Das assert(NumDefs <= 1 && "other cases unhandled!"); 49469fad079SSanjoy Das 49593d608c3SSanjoy Das unsigned DefReg = NoRegister; 49693d608c3SSanjoy Das if (NumDefs != 0) { 49793d608c3SSanjoy Das DefReg = LoadMI->defs().begin()->getReg(); 49869fad079SSanjoy Das assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 && 49969fad079SSanjoy Das "expected exactly one def!"); 50093d608c3SSanjoy Das } 50169fad079SSanjoy Das 50269fad079SSanjoy Das auto MIB = BuildMI(MBB, DL, TII->get(TargetOpcode::FAULTING_LOAD_OP), DefReg) 5034e1d389aSQuentin Colombet .addMBB(HandlerMBB) 50469fad079SSanjoy Das .addImm(LoadMI->getOpcode()); 50569fad079SSanjoy Das 50669fad079SSanjoy Das for (auto &MO : LoadMI->uses()) 50769fad079SSanjoy Das MIB.addOperand(MO); 50869fad079SSanjoy Das 50969fad079SSanjoy Das MIB.setMemRefs(LoadMI->memoperands_begin(), LoadMI->memoperands_end()); 51069fad079SSanjoy Das 51169fad079SSanjoy Das return MIB; 51269fad079SSanjoy Das } 51369fad079SSanjoy Das 51469fad079SSanjoy Das /// Rewrite the null checks in NullCheckList into implicit null checks. 51569fad079SSanjoy Das void ImplicitNullChecks::rewriteNullChecks( 51669fad079SSanjoy Das ArrayRef<ImplicitNullChecks::NullCheck> NullCheckList) { 51769fad079SSanjoy Das DebugLoc DL; 51869fad079SSanjoy Das 51969fad079SSanjoy Das for (auto &NC : NullCheckList) { 52069fad079SSanjoy Das // Remove the conditional branch dependent on the null check. 521e173b9aeSSanjoy Das unsigned BranchesRemoved = TII->RemoveBranch(*NC.getCheckBlock()); 52269fad079SSanjoy Das (void)BranchesRemoved; 52369fad079SSanjoy Das assert(BranchesRemoved > 0 && "expected at least one branch!"); 52469fad079SSanjoy Das 525*e57bf680SSanjoy Das if (auto *DepMI = NC.getOnlyDependency()) { 526*e57bf680SSanjoy Das DepMI->removeFromParent(); 527*e57bf680SSanjoy Das NC.getCheckBlock()->insert(NC.getCheckBlock()->end(), DepMI); 528*e57bf680SSanjoy Das } 529*e57bf680SSanjoy Das 53069fad079SSanjoy Das // Insert a faulting load where the conditional branch was originally. We 53169fad079SSanjoy Das // check earlier ensures that this bit of code motion is legal. We do not 53269fad079SSanjoy Das // touch the successors list for any basic block since we haven't changed 53369fad079SSanjoy Das // control flow, we've just made it implicit. 534e173b9aeSSanjoy Das MachineInstr *FaultingLoad = insertFaultingLoad( 535e173b9aeSSanjoy Das NC.getMemOperation(), NC.getCheckBlock(), NC.getNullSucc()); 53626dab3a4SQuentin Colombet // Now the values defined by MemOperation, if any, are live-in of 53726dab3a4SQuentin Colombet // the block of MemOperation. 53826dab3a4SQuentin Colombet // The original load operation may define implicit-defs alongside 53926dab3a4SQuentin Colombet // the loaded value. 540e173b9aeSSanjoy Das MachineBasicBlock *MBB = NC.getMemOperation()->getParent(); 54126dab3a4SQuentin Colombet for (const MachineOperand &MO : FaultingLoad->operands()) { 54226dab3a4SQuentin Colombet if (!MO.isReg() || !MO.isDef()) 54326dab3a4SQuentin Colombet continue; 54426dab3a4SQuentin Colombet unsigned Reg = MO.getReg(); 54526dab3a4SQuentin Colombet if (!Reg || MBB->isLiveIn(Reg)) 54626dab3a4SQuentin Colombet continue; 54712b69919SQuentin Colombet MBB->addLiveIn(Reg); 54812b69919SQuentin Colombet } 549*e57bf680SSanjoy Das 550*e57bf680SSanjoy Das if (auto *DepMI = NC.getOnlyDependency()) { 551*e57bf680SSanjoy Das for (auto &MO : DepMI->operands()) { 552*e57bf680SSanjoy Das if (!MO.isReg() || !MO.getReg() || !MO.isDef()) 553*e57bf680SSanjoy Das continue; 554*e57bf680SSanjoy Das if (!NC.getNotNullSucc()->isLiveIn(MO.getReg())) 555*e57bf680SSanjoy Das NC.getNotNullSucc()->addLiveIn(MO.getReg()); 556*e57bf680SSanjoy Das } 557*e57bf680SSanjoy Das } 558*e57bf680SSanjoy Das 559e173b9aeSSanjoy Das NC.getMemOperation()->eraseFromParent(); 560e173b9aeSSanjoy Das NC.getCheckOperation()->eraseFromParent(); 56169fad079SSanjoy Das 56269fad079SSanjoy Das // Insert an *unconditional* branch to not-null successor. 563e173b9aeSSanjoy Das TII->InsertBranch(*NC.getCheckBlock(), NC.getNotNullSucc(), nullptr, 564e173b9aeSSanjoy Das /*Cond=*/None, DL); 56569fad079SSanjoy Das 5668ee6a30bSSanjoy Das NumImplicitNullChecks++; 56769fad079SSanjoy Das } 56869fad079SSanjoy Das } 56969fad079SSanjoy Das 57069fad079SSanjoy Das char ImplicitNullChecks::ID = 0; 57169fad079SSanjoy Das char &llvm::ImplicitNullChecksID = ImplicitNullChecks::ID; 57269fad079SSanjoy Das INITIALIZE_PASS_BEGIN(ImplicitNullChecks, "implicit-null-checks", 57369fad079SSanjoy Das "Implicit null checks", false, false) 574*e57bf680SSanjoy Das INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) 57569fad079SSanjoy Das INITIALIZE_PASS_END(ImplicitNullChecks, "implicit-null-checks", 57669fad079SSanjoy Das "Implicit null checks", false, false) 577