1 # RUN: llc -run-pass implicit-null-checks -mtriple=x86_64-apple-macosx -o - %s | FileCheck %s
4 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
5 target triple = "x86_64-apple-macosx"
8 define i32 @imp_null_check_with_bitwise_op_0(i32* %x, i32 %val) {
10 br i1 undef, label %is_null, label %not_null, !make.implicit !0
16 br i1 undef, label %ret_100, label %ret_200
25 ;; Negative test. The regalloc is such that we cannot hoist the
26 ;; instruction materializing 2200000 into %eax
27 define i32 @imp_null_check_with_bitwise_op_1(i32* %x, i32 %val, i32* %ptr) {
29 br i1 undef, label %is_null, label %not_null, !make.implicit !0
35 br i1 undef, label %ret_100, label %ret_200
44 ;; Negative test: IR is identical to
45 ;; @imp_null_check_with_bitwise_op_0 but MIR differs.
46 define i32 @imp_null_check_with_bitwise_op_2(i32* %x, i32 %val) {
48 br i1 undef, label %is_null, label %not_null, !make.implicit !0
54 br i1 undef, label %ret_100, label %ret_200
63 ;; Negative test: IR is identical to
64 ;; @imp_null_check_with_bitwise_op_0 but MIR differs.
65 define i32 @imp_null_check_with_bitwise_op_3(i32* %x, i32 %val) {
67 br i1 undef, label %is_null, label %not_null, !make.implicit !0
73 br i1 undef, label %ret_100, label %ret_200
83 define i32 @imp_null_check_with_bitwise_op_4(i32* %x, i32 %val) {
85 br i1 undef, label %is_null, label %not_null, !make.implicit !0
91 br i1 undef, label %ret_100, label %ret_200
100 declare void @f() readonly
102 define i32 @no_hoist_across_call(i32* %ptr) {
104 %is_null = icmp eq i32* %ptr, null
105 br i1 %is_null, label %leave, label %stay, !make.implicit !0
109 %val = load i32, i32* %ptr
116 define i32 @dependency_live_in_hazard(i32* %ptr, i32** %ptr2, i32* %ptr3) #0 {
118 %val = load i32*, i32** %ptr2
119 %ptr_is_null = icmp eq i32* %ptr, null
120 br i1 %ptr_is_null, label %is_null, label %not_null, !make.implicit !0
122 not_null: ; preds = %entry
123 %addend = load i32, i32* %val
124 %result = load i32, i32* %ptr
125 %result.shr = lshr i32 %result, 4
126 %result.and = and i32 %result.shr, 4095
127 %result.add = add i32 %addend, %result.and
130 is_null: ; preds = %entry
134 attributes #0 = { "target-features"="+bmi,+bmi2" }
139 name: imp_null_check_with_bitwise_op_0
140 # CHECK-LABEL: name: imp_null_check_with_bitwise_op_0
142 tracksRegLiveness: true
147 # CHECK: %eax = MOV32ri 2200000
148 # CHECK-NEXT: %eax = FAULTING_LOAD_OP %bb.3.is_null, {{[0-9]+}}, killed %eax, killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (load 4 from %ir.x)
149 # CHECK-NEXT: JMP_1 %bb.1.not_null
153 successors: %bb.3.is_null, %bb.1.not_null
156 TEST64rr %rdi, %rdi, implicit-def %eflags
157 JE_1 %bb.3.is_null, implicit %eflags
160 successors: %bb.4.ret_100, %bb.2.ret_200
163 %eax = MOV32ri 2200000
164 %eax = AND32rm killed %eax, killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (load 4 from %ir.x)
165 CMP32rr killed %eax, killed %esi, implicit-def %eflags
166 JE_1 %bb.4.ret_100, implicit %eflags
182 name: imp_null_check_with_bitwise_op_1
184 tracksRegLiveness: true
190 # CHECK: %eax = MOV32rm killed %rdx, 1, _, 0, _ :: (volatile load 4 from %ir.ptr)
191 # CHECK-NEXT: TEST64rr %rdi, %rdi, implicit-def %eflags
192 # CHECK-NEXT: JE_1 %bb.3.is_null, implicit %eflags
196 successors: %bb.3.is_null, %bb.1.not_null
197 liveins: %esi, %rdi, %rdx
199 %eax = MOV32rm killed %rdx, 1, _, 0, _ :: (volatile load 4 from %ir.ptr)
200 TEST64rr %rdi, %rdi, implicit-def %eflags
201 JE_1 %bb.3.is_null, implicit %eflags
204 successors: %bb.4.ret_100, %bb.2.ret_200
207 %eax = MOV32ri 2200000
208 %eax = AND32rm killed %eax, killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (load 4 from %ir.x)
209 CMP32rr killed %eax, killed %esi, implicit-def %eflags
210 JE_1 %bb.4.ret_100, implicit %eflags
213 successors: %bb.3.is_null
218 liveins: %eax, %ah, %al, %ax, %bh, %bl, %bp, %bpl, %bx, %eax, %ebp, %ebx, %rax, %rbp, %rbx, %r12, %r13, %r14, %r15, %r12b, %r13b, %r14b, %r15b, %r12d, %r13d, %r14d, %r15d, %r12w, %r13w, %r14w, %r15w
228 name: imp_null_check_with_bitwise_op_2
229 # CHECK-LABEL: name: imp_null_check_with_bitwise_op_2
231 tracksRegLiveness: true
236 # CHECK: TEST64rr %rdi, %rdi, implicit-def %eflags
237 # CHECK-NEXT: JE_1 %bb.3.is_null, implicit %eflags
241 successors: %bb.3.is_null, %bb.1.not_null
244 TEST64rr %rdi, %rdi, implicit-def %eflags
245 JE_1 %bb.3.is_null, implicit %eflags
248 successors: %bb.4.ret_100, %bb.2.ret_200
251 %eax = MOV32ri 2200000
252 %eax = ADD32ri killed %eax, 100, implicit-def dead %eflags
253 %eax = AND32rm killed %eax, killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (load 4 from %ir.x)
254 CMP32rr killed %eax, killed %esi, implicit-def %eflags
255 JE_1 %bb.4.ret_100, implicit %eflags
271 name: imp_null_check_with_bitwise_op_3
272 # CHECK-LABEL: name: imp_null_check_with_bitwise_op_3
274 tracksRegLiveness: true
279 # CHECK: TEST64rr %rdi, %rdi, implicit-def %eflags
280 # CHECK-NEXT: JE_1 %bb.3.is_null, implicit %eflags
284 successors: %bb.3.is_null, %bb.1.not_null
287 TEST64rr %rdi, %rdi, implicit-def %eflags
288 JE_1 %bb.3.is_null, implicit %eflags
291 successors: %bb.4.ret_100, %bb.2.ret_200
295 %rdi = AND64rm killed %rdi, killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (load 4 from %ir.x)
296 CMP64rr killed %rdi, killed %rsi, implicit-def %eflags
297 JE_1 %bb.4.ret_100, implicit %eflags
313 name: imp_null_check_with_bitwise_op_4
314 # CHECK-LABEL: name: imp_null_check_with_bitwise_op_4
316 tracksRegLiveness: true
321 # CHECK: %rbx = MOV64rr %rdx
322 # CHECK-NEXT: %rdi = FAULTING_LOAD_OP %bb.3.is_null, {{[0-9]+}}, killed %rbx, killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (load 4 from %ir.x)
326 successors: %bb.3.is_null, %bb.1.not_null
327 liveins: %rsi, %rdi, %rdx
329 TEST64rr %rdi, %rdi, implicit-def %eflags
330 JE_1 %bb.3.is_null, implicit %eflags
333 successors: %bb.4.ret_100, %bb.2.ret_200
334 liveins: %rsi, %rdi, %rdx
337 %rdi = AND64rm killed %rbx, killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (load 4 from %ir.x)
339 CMP64rr killed %rdi, killed %rsi, implicit-def %eflags
340 JE_1 %bb.4.ret_100, implicit %eflags
356 name: no_hoist_across_call
357 # CHECK-LABEL: name: no_hoist_across_call
359 tracksRegLiveness: true
362 calleeSavedRegisters: [ '%bh', '%bl', '%bp', '%bpl', '%bx', '%ebp', '%ebx',
363 '%rbp', '%rbx', '%r12', '%r13', '%r14', '%r15',
364 '%r12b', '%r13b', '%r14b', '%r15b', '%r12d', '%r13d',
365 '%r14d', '%r15d', '%r12w', '%r13w', '%r14w', '%r15w' ]
367 # CHECK-NOT: FAULTING_LOAD_OP
369 # CHECK: CALL64pcrel32
372 successors: %bb.2.leave, %bb.1.stay
375 frame-setup PUSH64r killed %rbx, implicit-def %rsp, implicit %rsp
376 CFI_INSTRUCTION def_cfa_offset 16
377 CFI_INSTRUCTION offset %rbx, -16
379 TEST64rr %rbx, %rbx, implicit-def %eflags
380 JE_1 %bb.2.leave, implicit killed %eflags
385 CALL64pcrel32 @f, csr_64, implicit %rsp, implicit-def %rsp
386 %eax = MOV32rm killed %rbx, 1, _, 0, _ :: (load 4 from %ir.ptr)
387 %rbx = POP64r implicit-def %rsp, implicit %rsp
391 %eax = XOR32rr undef %eax, undef %eax, implicit-def dead %eflags
392 %rbx = POP64r implicit-def %rsp, implicit %rsp
397 name: dependency_live_in_hazard
398 # CHECK-LABEL: name: dependency_live_in_hazard
400 # CHECK-NOT: FAULTING_LOAD_OP
401 # CHECK: bb.1.not_null:
403 # Make sure that the BEXTR32rm instruction below is not used to emit
404 # an implicit null check -- hoisting it will require hosting the move
405 # to %esi and we cannot do that without clobbering the use of %rsi in
406 # the first instruction in bb.1.not_null.
408 tracksRegLiveness: true
414 successors: %bb.2.is_null, %bb.1.not_null
417 TEST64rr %rdi, %rdi, implicit-def %eflags
418 JE_1 %bb.2.is_null, implicit killed %eflags
423 %rcx = MOV64rm killed %rsi, 1, _, 0, _ :: (load 8 from %ir.ptr2)
425 %eax = BEXTR32rm killed %rdi, 1, _, 0, _, killed %esi, implicit-def dead %eflags :: (load 4 from %ir.ptr)
426 %eax = ADD32rm killed %eax, killed %rcx, 1, _, 0, _, implicit-def dead %eflags :: (load 4 from %ir.val)
430 %eax = XOR32rr undef %eax, undef %eax, implicit-def dead %eflags