Index: lib/CodeGen/ImplicitNullChecks.cpp =================================================================== --- lib/CodeGen/ImplicitNullChecks.cpp +++ lib/CodeGen/ImplicitNullChecks.cpp @@ -491,6 +491,30 @@ NullSucc = MBP.TrueDest; } + // The following code fragment: + // + // mov %rax, %rcx + // test %rax, %rax + // %rax = ... + // je throw_npe + // mov(%rcx), %r9 + // mov(%rax), %r10 + // + // gets incorrectly converted into: + // + // mov %rax, %rcx + // %rax = .... + // faulting_load_op("movl (%rax), %r10", throw_npe) + // mov(%rcx), %r9 + // + // Check if there are any instructions between the 'test' and conditional + // jump that modify %rax. + unsigned cmpReg = MBP.LHS.getReg(); + + for (auto I = MBB.rbegin(); MBP.ConditionDef != &*I; ++I) + if (I->modifiesRegister(cmpReg, TRI)) + return false; + // We handle the simplest case for now. We can potentially do better by using // the machine dominator tree. if (NotNullSucc->pred_size() != 1) Index: test/CodeGen/X86/implicit-null-chk-reg-rewrite.mir =================================================================== --- /dev/null +++ test/CodeGen/X86/implicit-null-chk-reg-rewrite.mir @@ -0,0 +1,65 @@ +# RUN: llc -mtriple=x86_64 -run-pass=implicit-null-checks %s -o - | FileCheck %s +--- | + + define i32 @reg-rewrite(i32* %x, i32 %val) { + entry: + br i1 undef, label %is_null, label %not_null, !make.implicit !0 + + is_null: + ret i32 42 + + not_null: + br i1 undef, label %ret_100, label %ret_200 + + ret_100: + ret i32 100 + + ret_200: + ret i32 200 + } + + !0 = !{} + +... +--- +# Check that the TEST instruction is replaced with +# FAULTING_OP only if there are no instructions +# between the TEST and conditional jump +# that clobber the register used in TEST. +name: reg-rewrite + +alignment: 4 +tracksRegLiveness: true +liveins: + - { reg: '$rdi' } + - { reg: '$rsi' } +body: | + bb.0.entry: + liveins: $rdi, $rsi + + TEST64rr $rdi, $rdi, implicit-def $eflags + ; CHECK-LABEL: bb.0.entry + ; CHECK-NOT: FAULTING_OP + renamable $rdi = MOV64ri 5000 + JE_1 %bb.2, implicit $eflags + + bb.1.not_null: + liveins: $rdi, $rsi + + $rax = MOV64ri 2200000 + $rax = AND64rm killed $rax, killed $rdi, 1, $noreg, 0, $noreg, implicit-def dead $eflags + CMP64rr killed $rax, killed $rsi, implicit-def $eflags + JE_1 %bb.4, implicit $eflags + + bb.2.ret_200: + $eax = MOV32ri 200 + RETQ $eax + + bb.3.is_null: + $eax = MOV32ri 42 + RETQ $eax + + bb.4.ret_100: + $eax = MOV32ri 100 + RETQ $eax +...