diff options
Diffstat (limited to 'lib/CodeGen/ImplicitNullChecks.cpp')
| -rw-r--r-- | lib/CodeGen/ImplicitNullChecks.cpp | 66 | 
1 files changed, 41 insertions, 25 deletions
diff --git a/lib/CodeGen/ImplicitNullChecks.cpp b/lib/CodeGen/ImplicitNullChecks.cpp index e308f49ec4e8..308b6d293d3d 100644 --- a/lib/CodeGen/ImplicitNullChecks.cpp +++ b/lib/CodeGen/ImplicitNullChecks.cpp @@ -1,4 +1,4 @@ -//===-- ImplicitNullChecks.cpp - Fold null checks into memory accesses ----===// +//===- ImplicitNullChecks.cpp - Fold null checks into memory accesses -----===//  //  //                     The LLVM Compiler Infrastructure  // @@ -26,38 +26,50 @@  //  //===----------------------------------------------------------------------===// -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/SmallVector.h"  #include "llvm/ADT/Statistic.h"  #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/MemoryLocation.h"  #include "llvm/CodeGen/FaultMaps.h" +#include "llvm/CodeGen/MachineBasicBlock.h"  #include "llvm/CodeGen/MachineFunction.h"  #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h"  #include "llvm/CodeGen/MachineInstrBuilder.h"  #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineModuleInfo.h"  #include "llvm/CodeGen/MachineOperand.h"  #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h"  #include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Instruction.h" +#include "llvm/IR/DebugLoc.h"  #include "llvm/IR/LLVMContext.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Pass.h"  #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetSubtargetInfo.h" +#include <cassert> +#include <cstdint> +#include <iterator>  using namespace llvm;  static cl::opt<int> PageSize("imp-null-check-page-size",                               cl::desc("The page size of the target in bytes"), -                             cl::init(4096)); +                             cl::init(4096), cl::Hidden);  static cl::opt<unsigned> MaxInstsToConsider(      "imp-null-max-insts-to-consider",      cl::desc("The max number of instructions to consider hoisting loads over "               "(the algorithm is quadratic over this number)"), -    cl::init(8)); +    cl::Hidden, cl::init(8));  #define DEBUG_TYPE "implicit-null-checks" @@ -152,7 +164,6 @@ class ImplicitNullChecks : public MachineFunctionPass {    const TargetInstrInfo *TII = nullptr;    const TargetRegisterInfo *TRI = nullptr;    AliasAnalysis *AA = nullptr; -  MachineModuleInfo *MMI = nullptr;    MachineFrameInfo *MFI = nullptr;    bool analyzeBlockForNullChecks(MachineBasicBlock &MBB, @@ -166,6 +177,7 @@ class ImplicitNullChecks : public MachineFunctionPass {      AR_MayAlias,      AR_WillAliasEverything    }; +    /// Returns AR_NoAlias if \p MI memory operation does not alias with    /// \p PrevMI, AR_MayAlias if they may alias and AR_WillAliasEverything if    /// they may alias and any further memory operation may alias with \p PrevMI. @@ -176,6 +188,7 @@ class ImplicitNullChecks : public MachineFunctionPass {      SR_Unsuitable,      SR_Impossible    }; +    /// Return SR_Suitable if \p MI a memory operation that can be used to    /// implicitly null check the value in \p PointerReg, SR_Unsuitable if    /// \p MI cannot be used to null check and SR_Impossible if there is @@ -200,6 +213,7 @@ public:    }    bool runOnMachineFunction(MachineFunction &MF) override; +    void getAnalysisUsage(AnalysisUsage &AU) const override {      AU.addRequired<AAResultsWrapperPass>();      MachineFunctionPass::getAnalysisUsage(AU); @@ -211,7 +225,7 @@ public:    }  }; -} +} // end anonymous namespace  bool ImplicitNullChecks::canHandle(const MachineInstr *MI) {    if (MI->isCall() || MI->hasUnmodeledSideEffects()) @@ -230,7 +244,7 @@ ImplicitNullChecks::DependenceResult  ImplicitNullChecks::computeDependence(const MachineInstr *MI,                                        ArrayRef<MachineInstr *> Block) {    assert(llvm::all_of(Block, canHandle) && "Check this first!"); -  assert(!llvm::is_contained(Block, MI) && "Block must be exclusive of MI!"); +  assert(!is_contained(Block, MI) && "Block must be exclusive of MI!");    Optional<ArrayRef<MachineInstr *>::iterator> Dep; @@ -280,7 +294,6 @@ bool ImplicitNullChecks::canReorder(const MachineInstr *A,  bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) {    TII = MF.getSubtarget().getInstrInfo();    TRI = MF.getRegInfo().getTargetRegisterInfo(); -  MMI = &MF.getMMI();    MFI = &MF.getFrameInfo();    AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); @@ -356,7 +369,7 @@ ImplicitNullChecks::isSuitableMemoryOp(MachineInstr &MI, unsigned PointerReg,    // We want the mem access to be issued at a sane offset from PointerReg,    // so that if PointerReg is null then the access reliably page faults.    if (!((MI.mayLoad() || MI.mayStore()) && !MI.isPredicable() && -        Offset < PageSize)) +        -PageSize < Offset && Offset < PageSize))      return SR_Unsuitable;    // Finally, check whether the current memory access aliases with previous one. @@ -390,8 +403,10 @@ bool ImplicitNullChecks::canHoistInst(MachineInstr *FaultingMI,    // We don't want to reason about speculating loads.  Note -- at this point    // we should have already filtered out all of the other non-speculatable    // things, like calls and stores. +  // We also do not want to hoist stores because it might change the memory +  // while the FaultingMI may result in faulting.    assert(canHandle(DependenceMI) && "Should never have reached here!"); -  if (DependenceMI->mayLoad()) +  if (DependenceMI->mayLoadOrStore())      return false;    for (auto &DependenceMO : DependenceMI->operands()) { @@ -406,7 +421,7 @@ bool ImplicitNullChecks::canHoistInst(MachineInstr *FaultingMI,      //    test %rcx, %rcx      //    je _null_block      //  _non_null_block: -    //    %rdx<def> = INST +    //    %rdx = INST      //    ...      //      // This restriction does not apply to the faulting load inst because in @@ -441,7 +456,7 @@ bool ImplicitNullChecks::canHoistInst(MachineInstr *FaultingMI,  /// NullCheckList and return true, else return false.  bool ImplicitNullChecks::analyzeBlockForNullChecks(      MachineBasicBlock &MBB, SmallVectorImpl<NullCheck> &NullCheckList) { -  typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate; +  using MachineBranchPredicate = TargetInstrInfo::MachineBranchPredicate;    MDNode *BranchMD = nullptr;    if (auto *BB = MBB.getBasicBlock()) @@ -483,7 +498,7 @@ bool ImplicitNullChecks::analyzeBlockForNullChecks(    // Starting with a code fragment like:    // -  //   test %RAX, %RAX +  //   test %rax, %rax    //   jne LblNotNull    //    //  LblNull: @@ -493,13 +508,13 @@ bool ImplicitNullChecks::analyzeBlockForNullChecks(    //   Inst0    //   Inst1    //   ... -  //   Def = Load (%RAX + <offset>) +  //   Def = Load (%rax + <offset>)    //   ...    //    //    // we want to end up with    // -  //   Def = FaultingLoad (%RAX + <offset>), LblNull +  //   Def = FaultingLoad (%rax + <offset>), LblNull    //   jmp LblNotNull ;; explicit or fallthrough    //    //  LblNotNull: @@ -513,11 +528,11 @@ bool ImplicitNullChecks::analyzeBlockForNullChecks(    //    // To see why this is legal, consider the two possibilities:    // -  //  1. %RAX is null: since we constrain <offset> to be less than PageSize, the +  //  1. %rax is null: since we constrain <offset> to be less than PageSize, the    //     load instruction dereferences the null page, causing a segmentation    //     fault.    // -  //  2. %RAX is not null: in this case we know that the load cannot fault, as +  //  2. %rax is not null: in this case we know that the load cannot fault, as    //     otherwise the load would've faulted in the original program too and the    //     original program would've been undefined.    // @@ -555,7 +570,7 @@ bool ImplicitNullChecks::analyzeBlockForNullChecks(      }      // If MI re-defines the PointerReg then we cannot move further. -    if (any_of(MI.operands(), [&](MachineOperand &MO) { +    if (llvm::any_of(MI.operands(), [&](MachineOperand &MO) {            return MO.isReg() && MO.getReg() && MO.isDef() &&                   TRI->regsOverlap(MO.getReg(), PointerReg);          })) @@ -674,9 +689,10 @@ void ImplicitNullChecks::rewriteNullChecks(    }  } -  char ImplicitNullChecks::ID = 0; +  char &llvm::ImplicitNullChecksID = ImplicitNullChecks::ID; +  INITIALIZE_PASS_BEGIN(ImplicitNullChecks, DEBUG_TYPE,                        "Implicit null checks", false, false)  INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)  | 
