Home | History | Annotate | Download | only in X86
      1 ; RUN: llc -verify-machineinstrs -O3 -mtriple=x86_64-apple-macosx -enable-implicit-null-checks < %s | FileCheck %s
      2 
      3 ; RUN: llc < %s -mtriple=x86_64-apple-macosx -enable-implicit-null-checks \
      4 ; RUN:    | llvm-mc -triple x86_64-apple-macosx -filetype=obj -o - \
      5 ; RUN:    | llvm-objdump -triple x86_64-apple-macosx -fault-map-section - \
      6 ; RUN:    | FileCheck %s -check-prefix OBJDUMP
      7 
      8 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -enable-implicit-null-checks \
      9 ; RUN:    | llvm-mc -triple x86_64-unknown-linux-gnu -filetype=obj -o - \
     10 ; RUN:    | llvm-objdump -triple x86_64-unknown-linux-gnu -fault-map-section - \
     11 ; RUN:    | FileCheck %s -check-prefix OBJDUMP
     12 
     13 define i32 @imp_null_check_load(i32* %x) {
     14 ; CHECK-LABEL: _imp_null_check_load:
     15 ; CHECK: [[BB0_imp_null_check_load:L[^:]+]]:
     16 ; CHECK: movl (%rdi), %eax
     17 ; CHECK: retq
     18 ; CHECK: [[BB1_imp_null_check_load:LBB0_[0-9]+]]:
     19 ; CHECK: movl $42, %eax
     20 ; CHECK: retq
     21 
     22  entry:
     23   %c = icmp eq i32* %x, null
     24   br i1 %c, label %is_null, label %not_null, !make.implicit !0
     25 
     26  is_null:
     27   ret i32 42
     28 
     29  not_null:
     30   %t = load i32, i32* %x
     31   ret i32 %t
     32 }
     33 
     34 define i32 @imp_null_check_gep_load(i32* %x) {
     35 ; CHECK-LABEL: _imp_null_check_gep_load:
     36 ; CHECK: [[BB0_imp_null_check_gep_load:L[^:]+]]:
     37 ; CHECK: movl 128(%rdi), %eax
     38 ; CHECK: retq
     39 ; CHECK: [[BB1_imp_null_check_gep_load:LBB1_[0-9]+]]:
     40 ; CHECK: movl $42, %eax
     41 ; CHECK: retq
     42 
     43  entry:
     44   %c = icmp eq i32* %x, null
     45   br i1 %c, label %is_null, label %not_null, !make.implicit !0
     46 
     47  is_null:
     48   ret i32 42
     49 
     50  not_null:
     51   %x.gep = getelementptr i32, i32* %x, i32 32
     52   %t = load i32, i32* %x.gep
     53   ret i32 %t
     54 }
     55 
     56 define i32 @imp_null_check_add_result(i32* %x, i32 %p) {
     57 ; CHECK-LABEL: _imp_null_check_add_result:
     58 ; CHECK: [[BB0_imp_null_check_add_result:L[^:]+]]:
     59 ; CHECK: addl (%rdi), %esi
     60 ; CHECK: movl %esi, %eax
     61 ; CHECK: retq
     62 ; CHECK: [[BB1_imp_null_check_add_result:LBB2_[0-9]+]]:
     63 ; CHECK: movl $42, %eax
     64 ; CHECK: retq
     65 
     66  entry:
     67   %c = icmp eq i32* %x, null
     68   br i1 %c, label %is_null, label %not_null, !make.implicit !0
     69 
     70  is_null:
     71   ret i32 42
     72 
     73  not_null:
     74   %t = load i32, i32* %x
     75   %p1 = add i32 %t, %p
     76   ret i32 %p1
     77 }
     78 
     79 define i32 @imp_null_check_hoist_over_unrelated_load(i32* %x, i32* %y, i32* %z) {
     80 ; CHECK-LABEL: _imp_null_check_hoist_over_unrelated_load:
     81 ; CHECK: [[BB0_imp_null_check_hoist_over_unrelated_load:L[^:]+]]:
     82 ; CHECK: movl (%rdi), %eax
     83 ; CHECK: movl (%rsi), %ecx
     84 ; CHECK: movl %ecx, (%rdx)
     85 ; CHECK: retq
     86 ; CHECK: [[BB1_imp_null_check_hoist_over_unrelated_load:LBB3_[0-9]+]]:
     87 ; CHECK: movl	$42, %eax
     88 ; CHECK: retq
     89 
     90  entry:
     91   %c = icmp eq i32* %x, null
     92   br i1 %c, label %is_null, label %not_null, !make.implicit !0
     93 
     94  is_null:
     95   ret i32 42
     96 
     97  not_null:
     98   %t0 = load i32, i32* %y
     99   %t1 = load i32, i32* %x
    100   store i32 %t0, i32* %z
    101   ret i32 %t1
    102 }
    103 
    104 define i32 @imp_null_check_via_mem_comparision(i32* %x, i32 %val) {
    105 ; CHECK-LABEL: _imp_null_check_via_mem_comparision
    106 ; CHECK: [[BB0_imp_null_check_via_mem_comparision:L[^:]+]]:
    107 ; CHECK: cmpl   %esi, 4(%rdi)
    108 ; CHECK: jge    LBB4_2
    109 ; CHECK: movl   $100, %eax
    110 ; CHECK: retq
    111 ; CHECK: [[BB1_imp_null_check_via_mem_comparision:LBB4_[0-9]+]]:
    112 ; CHECK: movl   $42, %eax
    113 ; CHECK: retq
    114 ; CHECK: LBB4_2:
    115 ; CHECK: movl   $200, %eax
    116 ; CHECK: retq
    117 
    118  entry:
    119   %c = icmp eq i32* %x, null
    120   br i1 %c, label %is_null, label %not_null, !make.implicit !0
    121 
    122  is_null:
    123   ret i32 42
    124 
    125  not_null:
    126   %x.loc = getelementptr i32, i32* %x, i32 1
    127   %t = load i32, i32* %x.loc
    128   %m = icmp slt i32 %t, %val
    129   br i1 %m, label %ret_100, label %ret_200
    130 
    131  ret_100:
    132   ret i32 100
    133 
    134  ret_200:
    135   ret i32 200
    136 }
    137 
    138 define i32 @imp_null_check_gep_load_with_use_dep(i32* %x, i32 %a) {
    139 ; CHECK-LABEL: imp_null_check_gep_load_with_use_dep:
    140 ; CHECK: [[BB0_imp_null_check_gep_load_with_use_dep:L[^:]+]]:
    141 ; CHECK: movl (%rdi), %eax
    142 ; CHECK: addl %edi, %esi
    143 ; CHECK: leal 4(%rax,%rsi), %eax
    144 ; CHECK: retq
    145 ; CHECK: [[BB1_imp_null_check_gep_load_with_use_dep:LBB5_[0-9]+]]:
    146 ; CHECK: movl $42, %eax
    147 ; CHECK: retq
    148 
    149  entry:
    150   %c = icmp eq i32* %x, null
    151   br i1 %c, label %is_null, label %not_null, !make.implicit !0
    152 
    153  is_null:
    154   ret i32 42
    155 
    156  not_null:
    157   %x.loc = getelementptr i32, i32* %x, i32 1
    158   %y = ptrtoint i32* %x.loc to i32
    159   %b = add i32 %a, %y
    160   %t = load i32, i32* %x
    161   %z = add i32 %t, %b
    162   ret i32 %z
    163 }
    164 
    165 define void @imp_null_check_store(i32* %x) {
    166 ; CHECK-LABEL: _imp_null_check_store:
    167 ; CHECK: [[BB0_imp_null_check_store:L[^:]+]]:
    168 ; CHECK: movl $1, (%rdi)
    169 ; CHECK: retq
    170 ; CHECK: [[BB1_imp_null_check_store:LBB6_[0-9]+]]:
    171 ; CHECK: retq
    172 
    173  entry:
    174   %c = icmp eq i32* %x, null
    175   br i1 %c, label %is_null, label %not_null, !make.implicit !0
    176 
    177  is_null:
    178   ret void
    179 
    180  not_null:
    181   store i32 1, i32* %x
    182   ret void
    183 }
    184 
    185 define i32 @imp_null_check_neg_gep_load(i32* %x) {
    186 ; CHECK-LABEL: _imp_null_check_neg_gep_load:
    187 ; CHECK: [[BB0_imp_null_check_neg_gep_load:L[^:]+]]:
    188 ; CHECK: movl -128(%rdi), %eax
    189 ; CHECK: retq
    190 ; CHECK: [[BB1_imp_null_check_neg_gep_load:LBB7_[0-9]+]]:
    191 ; CHECK: movl $42, %eax
    192 ; CHECK: retq
    193 
    194  entry:
    195   %c = icmp eq i32* %x, null
    196   br i1 %c, label %is_null, label %not_null, !make.implicit !0
    197 
    198  is_null:
    199   ret i32 42
    200 
    201  not_null:
    202   %x.gep = getelementptr i32, i32* %x, i32 -32
    203   %t = load i32, i32* %x.gep
    204   ret i32 %t
    205 }
    206 
    207 !0 = !{}
    208 
    209 ; CHECK-LABEL: __LLVM_FaultMaps:
    210 
    211 ; Version:
    212 ; CHECK-NEXT: .byte 1
    213 
    214 ; Reserved x2
    215 ; CHECK-NEXT: .byte 0
    216 ; CHECK-NEXT: .short 0
    217 
    218 ; # functions:
    219 ; CHECK-NEXT: .long 8
    220 
    221 ; FunctionAddr:
    222 ; CHECK-NEXT: .quad _imp_null_check_add_result
    223 ; NumFaultingPCs
    224 ; CHECK-NEXT: .long 1
    225 ; Reserved:
    226 ; CHECK-NEXT: .long 0
    227 ; Fault[0].Type:
    228 ; CHECK-NEXT: .long 1
    229 ; Fault[0].FaultOffset:
    230 ; CHECK-NEXT: .long [[BB0_imp_null_check_add_result]]-_imp_null_check_add_result
    231 ; Fault[0].HandlerOffset:
    232 ; CHECK-NEXT: .long [[BB1_imp_null_check_add_result]]-_imp_null_check_add_result
    233 
    234 ; FunctionAddr:
    235 ; CHECK-NEXT: .quad _imp_null_check_gep_load
    236 ; NumFaultingPCs
    237 ; CHECK-NEXT: .long 1
    238 ; Reserved:
    239 ; CHECK-NEXT: .long 0
    240 ; Fault[0].Type:
    241 ; CHECK-NEXT: .long 1
    242 ; Fault[0].FaultOffset:
    243 ; CHECK-NEXT: .long [[BB0_imp_null_check_gep_load]]-_imp_null_check_gep_load
    244 ; Fault[0].HandlerOffset:
    245 ; CHECK-NEXT: .long [[BB1_imp_null_check_gep_load]]-_imp_null_check_gep_load
    246 
    247 ; FunctionAddr:
    248 ; CHECK-NEXT: .quad _imp_null_check_gep_load_with_use_dep
    249 ; NumFaultingPCs
    250 ; CHECK-NEXT: .long 1
    251 ; Reserved:
    252 ; CHECK-NEXT: .long 0
    253 ; Fault[0].Type:
    254 ; CHECK-NEXT: .long 1
    255 ; Fault[0].FaultOffset:
    256 ; CHECK-NEXT: .long [[BB0_imp_null_check_gep_load_with_use_dep]]-_imp_null_check_gep_load_with_use_dep
    257 ; Fault[0].HandlerOffset:
    258 ; CHECK-NEXT: .long [[BB1_imp_null_check_gep_load_with_use_dep]]-_imp_null_check_gep_load_with_use_dep
    259 
    260 ; FunctionAddr:
    261 ; CHECK-NEXT: .quad _imp_null_check_hoist_over_unrelated_load
    262 ; NumFaultingPCs
    263 ; CHECK-NEXT: .long 1
    264 ; Reserved:
    265 ; CHECK-NEXT: .long 0
    266 ; Fault[0].Type:
    267 ; CHECK-NEXT: .long 1
    268 ; Fault[0].FaultOffset:
    269 ; CHECK-NEXT: .long [[BB0_imp_null_check_hoist_over_unrelated_load]]-_imp_null_check_hoist_over_unrelated_load
    270 ; Fault[0].HandlerOffset:
    271 ; CHECK-NEXT: .long [[BB1_imp_null_check_hoist_over_unrelated_load]]-_imp_null_check_hoist_over_unrelated_load
    272 
    273 ; FunctionAddr:
    274 ; CHECK-NEXT: .quad _imp_null_check_load
    275 ; NumFaultingPCs
    276 ; CHECK-NEXT: .long 1
    277 ; Reserved:
    278 ; CHECK-NEXT: .long 0
    279 ; Fault[0].Type:
    280 ; CHECK-NEXT: .long 1
    281 ; Fault[0].FaultOffset:
    282 ; CHECK-NEXT: .long [[BB0_imp_null_check_load]]-_imp_null_check_load
    283 ; Fault[0].HandlerOffset:
    284 ; CHECK-NEXT: .long [[BB1_imp_null_check_load]]-_imp_null_check_load
    285 
    286 ; FunctionAddr:
    287 ; CHECK-NEXT: .quad _imp_null_check_neg_gep_load
    288 ; NumFaultingPCs
    289 ; CHECK-NEXT: .long 1
    290 ; Reserved:
    291 ; CHECK-NEXT: .long 0
    292 ; Fault[0].Type:
    293 ; CHECK-NEXT: .long 1
    294 ; Fault[0].FaultOffset:
    295 ; CHECK-NEXT: .long [[BB0_imp_null_check_neg_gep_load]]-_imp_null_check_neg_gep_load
    296 ; Fault[0].HandlerOffset:
    297 ; CHECK-NEXT: .long [[BB1_imp_null_check_neg_gep_load]]-_imp_null_check_neg_gep_load
    298 
    299 ; FunctionAddr:
    300 ; CHECK-NEXT: .quad _imp_null_check_store
    301 ; NumFaultingPCs
    302 ; CHECK-NEXT: .long 1
    303 ; Reserved:
    304 ; CHECK-NEXT: .long 0
    305 ; Fault[0].Type:
    306 ; CHECK-NEXT: .long 3
    307 ; Fault[0].FaultOffset:
    308 ; CHECK-NEXT: .long [[BB0_imp_null_check_store]]-_imp_null_check_store
    309 ; Fault[0].HandlerOffset:
    310 ; CHECK-NEXT: .long [[BB1_imp_null_check_store]]-_imp_null_check_store
    311 
    312 ; FunctionAddr:
    313 ; CHECK-NEXT: .quad     _imp_null_check_via_mem_comparision
    314 ; NumFaultingPCs
    315 ; CHECK-NEXT: .long   1
    316 ; Reserved:
    317 ; CHECK-NEXT: .long   0
    318 ; Fault[0].Type:
    319 ; CHECK-NEXT: .long   1
    320 ; Fault[0].FaultOffset:
    321 ; CHECK-NEXT: .long   [[BB0_imp_null_check_via_mem_comparision]]-_imp_null_check_via_mem_comparision
    322 ; Fault[0].HandlerOffset:
    323 ; CHECK-NEXT: .long   [[BB1_imp_null_check_via_mem_comparision]]-_imp_null_check_via_mem_comparision
    324 
    325 ; OBJDUMP: FaultMap table:
    326 ; OBJDUMP-NEXT: Version: 0x1
    327 ; OBJDUMP-NEXT: NumFunctions: 8
    328 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
    329 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 5
    330 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
    331 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 7
    332 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
    333 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 9
    334 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
    335 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 7
    336 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
    337 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 3
    338 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
    339 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 4
    340 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
    341 ; OBJDUMP-NEXT: Fault kind: FaultingStore, faulting PC offset: 0, handling PC offset: 7
    342 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
    343 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 11
    344