From a4b0d863f94612ce83fd9cae7143e24adb67f668 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Mon, 20 Jul 2015 20:31:39 +0000 Subject: [PATCH] [ImplicitNullChecks] Work with implicit defs. Summary: This change generalizes the implicit null checks pass to work with instructions that don't have any explicit register defs. This lets us use X86's `cmp` against memory as faulting load instructions. Reviewers: reames, JosephTremoulet Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D11286 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242703 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/ImplicitNullChecks.cpp | 17 ++++++--- lib/Target/X86/X86MCInstLower.cpp | 5 ++- test/CodeGen/X86/implicit-null-check.ll | 51 ++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 9 deletions(-) diff --git a/lib/CodeGen/ImplicitNullChecks.cpp b/lib/CodeGen/ImplicitNullChecks.cpp index 93e04876a8f..fbe057791c5 100644 --- a/lib/CodeGen/ImplicitNullChecks.cpp +++ b/lib/CodeGen/ImplicitNullChecks.cpp @@ -238,7 +238,7 @@ bool ImplicitNullChecks::analyzeBlockForNullChecks( unsigned BaseReg, Offset; if (TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI)) if (MI->mayLoad() && !MI->isPredicable() && BaseReg == PointerReg && - Offset < PageSize && MI->getDesc().getNumDefs() == 1 && + Offset < PageSize && MI->getDesc().getNumDefs() <= 1 && IsSafeToHoist(MI)) { NullCheckList.emplace_back(MI, MBP.ConditionDef, &MBB, NotNullSucc, NullSucc); @@ -281,14 +281,19 @@ bool ImplicitNullChecks::analyzeBlockForNullChecks( MachineInstr *ImplicitNullChecks::insertFaultingLoad(MachineInstr *LoadMI, MachineBasicBlock *MBB, MCSymbol *HandlerLabel) { + const unsigned NoRegister = 0; // Guaranteed to be the NoRegister value for + // all targets. + DebugLoc DL; unsigned NumDefs = LoadMI->getDesc().getNumDefs(); - assert(NumDefs == 1 && "other cases unhandled!"); - (void)NumDefs; + assert(NumDefs <= 1 && "other cases unhandled!"); - unsigned DefReg = LoadMI->defs().begin()->getReg(); - assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 && - "expected exactly one def!"); + unsigned DefReg = NoRegister; + if (NumDefs != 0) { + DefReg = LoadMI->defs().begin()->getReg(); + assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 && + "expected exactly one def!"); + } auto MIB = BuildMI(MBB, DL, TII->get(TargetOpcode::FAULTING_LOAD_OP), DefReg) .addSym(HandlerLabel) diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index 1b37457a87c..68977d38e15 100644 --- a/lib/Target/X86/X86MCInstLower.cpp +++ b/lib/Target/X86/X86MCInstLower.cpp @@ -875,7 +875,10 @@ void X86AsmPrinter::LowerFAULTING_LOAD_OP(const MachineInstr &MI, MCInst LoadMI; LoadMI.setOpcode(LoadOpcode); - LoadMI.addOperand(MCOperand::createReg(LoadDefRegister)); + + if (LoadDefRegister != X86::NoRegister) + LoadMI.addOperand(MCOperand::createReg(LoadDefRegister)); + for (auto I = MI.operands_begin() + LoadOperandsBeginIdx, E = MI.operands_end(); I != E; ++I) diff --git a/test/CodeGen/X86/implicit-null-check.ll b/test/CodeGen/X86/implicit-null-check.ll index fd7a902eefc..8b905f5d23b 100644 --- a/test/CodeGen/X86/implicit-null-check.ll +++ b/test/CodeGen/X86/implicit-null-check.ll @@ -101,6 +101,40 @@ define i32 @imp_null_check_hoist_over_unrelated_load(i32* %x, i32* %y, i32* %z) ret i32 %t1 } +define i32 @imp_null_check_via_mem_comparision(i32* %x, i32 %val) { +; CHECK-LABEL: _imp_null_check_via_mem_comparision +; CHECK: Ltmp9: +; CHECK: cmpl %esi, 4(%rdi) +; CHECK: jge LBB4_2 +; CHECK: movl $100, %eax +; CHECK: retq +; CHECK: Ltmp8: +; CHECK: movl $42, %eax +; CHECK: retq +; CHECK: LBB4_2: +; CHECK: movl $200, %eax +; CHECK: retq + + entry: + %c = icmp eq i32* %x, null + br i1 %c, label %is_null, label %not_null, !make.implicit !0 + + is_null: + ret i32 42 + + not_null: + %x.loc = getelementptr i32, i32* %x, i32 1 + %t = load i32, i32* %x.loc + %m = icmp slt i32 %t, %val + br i1 %m, label %ret_100, label %ret_200 + + ret_100: + ret i32 100 + + ret_200: + ret i32 200 +} + !0 = !{} ; CHECK-LABEL: __LLVM_FaultMaps: @@ -113,7 +147,7 @@ define i32 @imp_null_check_hoist_over_unrelated_load(i32* %x, i32* %y, i32* %z) ; CHECK-NEXT: .short 0 ; # functions: -; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 5 ; FunctionAddr: ; CHECK-NEXT: .quad _imp_null_check_add_result @@ -167,9 +201,22 @@ define i32 @imp_null_check_hoist_over_unrelated_load(i32* %x, i32* %y, i32* %z) ; Fault[0].HandlerOffset: ; CHECK-NEXT: .long Ltmp0-_imp_null_check_load +; FunctionAddr: +; CHECK-NEXT: .quad _imp_null_check_via_mem_comparision +; NumFaultingPCs +; CHECK-NEXT: .long 1 +; Reserved: +; CHECK-NEXT: .long 0 +; Fault[0].Type: +; CHECK-NEXT: .long 1 +; Fault[0].FaultOffset: +; CHECK-NEXT: .long Ltmp9-_imp_null_check_via_mem_comparision +; Fault[0].HandlerOffset: +; CHECK-NEXT: .long Ltmp8-_imp_null_check_via_mem_comparision + ; OBJDUMP: FaultMap table: ; OBJDUMP-NEXT: Version: 0x1 -; OBJDUMP-NEXT: NumFunctions: 4 +; OBJDUMP-NEXT: NumFunctions: 5 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 5 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1 -- 2.34.1