Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc -verify-machineinstrs -disable-fp-elim < %s -mtriple=aarch64-apple-ios -disable-post-ra | FileCheck --check-prefix=CHECK-APPLE %s
      2 ; RUN: llc -verify-machineinstrs -disable-fp-elim -O0 < %s -mtriple=aarch64-apple-ios -disable-post-ra | FileCheck --check-prefix=CHECK-O0 %s
      3 
      4 declare i8* @malloc(i64)
      5 declare void @free(i8*)
      6 %swift_error = type {i64, i8}
      7 
      8 ; This tests the basic usage of a swifterror parameter. "foo" is the function
      9 ; that takes a swifterror parameter and "caller" is the caller of "foo".
     10 define float @foo(%swift_error** swifterror %error_ptr_ref) {
     11 ; CHECK-APPLE-LABEL: foo:
     12 ; CHECK-APPLE: orr w0, wzr, #0x10
     13 ; CHECK-APPLE: malloc
     14 ; CHECK-APPLE: orr [[ID:w[0-9]+]], wzr, #0x1
     15 ; CHECK-APPLE: strb [[ID]], [x0, #8]
     16 ; CHECK-APPLE: mov x19, x0
     17 ; CHECK-APPLE-NOT: x19
     18 
     19 ; CHECK-O0-LABEL: foo:
     20 ; CHECK-O0: orr w{{.*}}, wzr, #0x10
     21 ; CHECK-O0: malloc
     22 ; CHECK-O0: mov [[ID2:x[0-9]+]], x0
     23 ; CHECK-O0: orr [[ID:w[0-9]+]], wzr, #0x1
     24 ; CHECK-O0: strb [[ID]], [x0, #8]
     25 ; CHECK-O0: mov x19, [[ID2]]
     26 ; CHECK-O0-NOT: x19
     27 entry:
     28   %call = call i8* @malloc(i64 16)
     29   %call.0 = bitcast i8* %call to %swift_error*
     30   store %swift_error* %call.0, %swift_error** %error_ptr_ref
     31   %tmp = getelementptr inbounds i8, i8* %call, i64 8
     32   store i8 1, i8* %tmp
     33   ret float 1.0
     34 }
     35 
     36 ; "caller" calls "foo" that takes a swifterror parameter.
     37 define float @caller(i8* %error_ref) {
     38 ; CHECK-APPLE-LABEL: caller:
     39 ; CHECK-APPLE: mov [[ID:x[0-9]+]], x0
     40 ; CHECK-APPLE: mov x19, xzr
     41 ; CHECK-APPLE: bl {{.*}}foo
     42 ; CHECK-APPLE: cbnz x19
     43 ; Access part of the error object and save it to error_ref
     44 ; CHECK-APPLE: ldrb [[CODE:w[0-9]+]], [x19, #8]
     45 ; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
     46 ; CHECK-APPLE: mov x0, x19
     47 ; CHECK_APPLE: bl {{.*}}free
     48 
     49 ; CHECK-O0-LABEL: caller:
     50 ; CHECK-O0: mov x19
     51 ; CHECK-O0: bl {{.*}}foo
     52 ; CHECK-O0: mov [[ID:x[0-9]+]], x19
     53 ; CHECK-O0: cbnz [[ID]]
     54 entry:
     55   %error_ptr_ref = alloca swifterror %swift_error*
     56   store %swift_error* null, %swift_error** %error_ptr_ref
     57   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
     58   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
     59   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
     60   %tmp = bitcast %swift_error* %error_from_foo to i8*
     61   br i1 %had_error_from_foo, label %handler, label %cont
     62 cont:
     63   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
     64   %t = load i8, i8* %v1
     65   store i8 %t, i8* %error_ref
     66   br label %handler
     67 handler:
     68   call void @free(i8* %tmp)
     69   ret float 1.0
     70 }
     71 
     72 ; "caller2" is the caller of "foo", it calls "foo" inside a loop.
     73 define float @caller2(i8* %error_ref) {
     74 ; CHECK-APPLE-LABEL: caller2:
     75 ; CHECK-APPLE: mov [[ID:x[0-9]+]], x0
     76 ; CHECK-APPLE: fmov [[CMP:s[0-9]+]], #1.0
     77 ; CHECK-APPLE: mov x19, xzr
     78 ; CHECK-APPLE: bl {{.*}}foo
     79 ; CHECK-APPLE: cbnz x19
     80 ; CHECK-APPLE: fcmp s0, [[CMP]]
     81 ; CHECK-APPLE: b.le
     82 ; Access part of the error object and save it to error_ref
     83 ; CHECK-APPLE: ldrb [[CODE:w[0-9]+]], [x19, #8]
     84 ; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
     85 ; CHECK-APPLE: mov x0, x19
     86 ; CHECK_APPLE: bl {{.*}}free
     87 
     88 ; CHECK-O0-LABEL: caller2:
     89 ; CHECK-O0: mov x19
     90 ; CHECK-O0: bl {{.*}}foo
     91 ; CHECK-O0: mov [[ID:x[0-9]+]], x19
     92 ; CHECK-O0: cbnz [[ID]]
     93 entry:
     94   %error_ptr_ref = alloca swifterror %swift_error*
     95   br label %bb_loop
     96 bb_loop:
     97   store %swift_error* null, %swift_error** %error_ptr_ref
     98   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
     99   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
    100   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
    101   %tmp = bitcast %swift_error* %error_from_foo to i8*
    102   br i1 %had_error_from_foo, label %handler, label %cont
    103 cont:
    104   %cmp = fcmp ogt float %call, 1.000000e+00
    105   br i1 %cmp, label %bb_end, label %bb_loop
    106 bb_end:
    107   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
    108   %t = load i8, i8* %v1
    109   store i8 %t, i8* %error_ref
    110   br label %handler
    111 handler:
    112   call void @free(i8* %tmp)
    113   ret float 1.0
    114 }
    115 
    116 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
    117 ; under a certain condition.
    118 define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
    119 ; CHECK-APPLE-LABEL: foo_if:
    120 ; CHECK-APPLE: cbz w0
    121 ; CHECK-APPLE: orr w0, wzr, #0x10
    122 ; CHECK-APPLE: malloc
    123 ; CHECK-APPLE: orr [[ID:w[0-9]+]], wzr, #0x1
    124 ; CHECK-APPLE: strb [[ID]], [x0, #8]
    125 ; CHECK-APPLE: mov x19, x0
    126 ; CHECK-APPLE-NOT: x19
    127 ; CHECK-APPLE: ret
    128 
    129 ; CHECK-O0-LABEL: foo_if:
    130 ; spill x19
    131 ; CHECK-O0: str x19
    132 ; CHECK-O0: cbz w0
    133 ; CHECK-O0: orr w{{.*}}, wzr, #0x10
    134 ; CHECK-O0: malloc
    135 ; CHECK-O0: mov [[ID:x[0-9]+]], x0
    136 ; CHECK-O0: orr [[ID2:w[0-9]+]], wzr, #0x1
    137 ; CHECK-O0: strb [[ID2]], [x0, #8]
    138 ; CHECK-O0: mov x19, [[ID]]
    139 ; CHECK-O0: ret
    140 ; reload from stack
    141 ; CHECK-O0: ldr x19
    142 ; CHECK-O0: ret
    143 entry:
    144   %cond = icmp ne i32 %cc, 0
    145   br i1 %cond, label %gen_error, label %normal
    146 
    147 gen_error:
    148   %call = call i8* @malloc(i64 16)
    149   %call.0 = bitcast i8* %call to %swift_error*
    150   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    151   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    152   store i8 1, i8* %tmp
    153   ret float 1.0
    154 
    155 normal:
    156   ret float 0.0
    157 }
    158 
    159 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
    160 ; under a certain condition inside a loop.
    161 define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) {
    162 ; CHECK-APPLE-LABEL: foo_loop:
    163 ; CHECK-APPLE: mov x0, x19
    164 ; CHECK-APPLE: cbz
    165 ; CHECK-APPLE: orr w0, wzr, #0x10
    166 ; CHECK-APPLE: malloc
    167 ; CHECK-APPLE: strb w{{.*}}, [x0, #8]
    168 ; CHECK-APPLE: fcmp
    169 ; CHECK-APPLE: b.le
    170 ; CHECK-APPLE: mov x19, x0
    171 ; CHECK-APPLE: ret
    172 
    173 ; CHECK-O0-LABEL: foo_loop:
    174 ; spill x19
    175 ; CHECK-O0: str x19
    176 ; CHECk-O0: cbz
    177 ; CHECK-O0: orr w{{.*}}, wzr, #0x10
    178 ; CHECK-O0: malloc
    179 ; CHECK-O0: mov [[ID:x[0-9]+]], x0
    180 ; CHECK-O0: strb w{{.*}}, [{{.*}}[[ID]], #8]
    181 ; spill x0
    182 ; CHECK-O0: str x0
    183 ; CHECK-O0: fcmp
    184 ; CHECK-O0: b.le
    185 ; reload from stack
    186 ; CHECK-O0: ldr x19
    187 ; CHECK-O0: ret
    188 entry:
    189   br label %bb_loop
    190 
    191 bb_loop:
    192   %cond = icmp ne i32 %cc, 0
    193   br i1 %cond, label %gen_error, label %bb_cont
    194 
    195 gen_error:
    196   %call = call i8* @malloc(i64 16)
    197   %call.0 = bitcast i8* %call to %swift_error*
    198   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    199   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    200   store i8 1, i8* %tmp
    201   br label %bb_cont
    202 
    203 bb_cont:
    204   %cmp = fcmp ogt float %cc2, 1.000000e+00
    205   br i1 %cmp, label %bb_end, label %bb_loop
    206 bb_end:
    207   ret float 0.0
    208 }
    209 
    210 %struct.S = type { i32, i32, i32, i32, i32, i32 }
    211 
    212 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
    213 ; parameter.
    214 define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
    215 ; CHECK-APPLE-LABEL: foo_sret:
    216 ; CHECK-APPLE: mov [[SRET:x[0-9]+]], x8
    217 ; CHECK-APPLE: orr w0, wzr, #0x10
    218 ; CHECK-APPLE: malloc
    219 ; CHECK-APPLE: orr [[ID:w[0-9]+]], wzr, #0x1
    220 ; CHECK-APPLE: strb [[ID]], [x0, #8]
    221 ; CHECK-APPLE: str w{{.*}}, [{{.*}}[[SRET]], #4]
    222 ; CHECK-APPLE: mov x19, x0
    223 ; CHECK-APPLE-NOT: x19
    224 
    225 ; CHECK-O0-LABEL: foo_sret:
    226 ; CHECK-O0: orr w{{.*}}, wzr, #0x10
    227 ; spill x8
    228 ; CHECK-O0-DAG: str x8
    229 ; spill x19
    230 ; CHECK-O0-DAG: str x19
    231 ; CHECK-O0: malloc
    232 ; CHECK-O0: orr [[ID:w[0-9]+]], wzr, #0x1
    233 ; CHECK-O0: strb [[ID]], [x0, #8]
    234 ; reload from stack
    235 ; CHECK-O0: ldr [[SRET:x[0-9]+]]
    236 ; CHECK-O0: str w{{.*}}, [{{.*}}[[SRET]], #4]
    237 ; CHECK-O0: mov x19
    238 ; CHECK-O0-NOT: x19
    239 entry:
    240   %call = call i8* @malloc(i64 16)
    241   %call.0 = bitcast i8* %call to %swift_error*
    242   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    243   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    244   store i8 1, i8* %tmp
    245   %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
    246   store i32 %val1, i32* %v2
    247   ret void
    248 }
    249 
    250 ; "caller3" calls "foo_sret" that takes a swifterror parameter.
    251 define float @caller3(i8* %error_ref) {
    252 ; CHECK-APPLE-LABEL: caller3:
    253 ; CHECK-APPLE: mov [[ID:x[0-9]+]], x0
    254 ; CHECK-APPLE: mov x19, xzr
    255 ; CHECK-APPLE: bl {{.*}}foo_sret
    256 ; CHECK-APPLE: cbnz x19
    257 ; Access part of the error object and save it to error_ref
    258 ; CHECK-APPLE: ldrb [[CODE:w[0-9]+]], [x19, #8]
    259 ; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
    260 ; CHECK-APPLE: mov x0, x19
    261 ; CHECK_APPLE: bl {{.*}}free
    262 
    263 ; CHECK-O0-LABEL: caller3:
    264 ; spill x0
    265 ; CHECK-O0: str x0
    266 ; CHECK-O0: mov x19
    267 ; CHECK-O0: bl {{.*}}foo_sret
    268 ; CHECK-O0: mov [[ID2:x[0-9]+]], x19
    269 ; CHECK-O0: cbnz [[ID2]]
    270 ; Access part of the error object and save it to error_ref
    271 ; reload from stack
    272 ; CHECK-O0: ldrb [[CODE:w[0-9]+]]
    273 ; CHECK-O0: ldr [[ID:x[0-9]+]]
    274 ; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
    275 ; CHECK_O0: bl {{.*}}free
    276 entry:
    277   %s = alloca %struct.S, align 8
    278   %error_ptr_ref = alloca swifterror %swift_error*
    279   store %swift_error* null, %swift_error** %error_ptr_ref
    280   call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref)
    281   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
    282   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
    283   %tmp = bitcast %swift_error* %error_from_foo to i8*
    284   br i1 %had_error_from_foo, label %handler, label %cont
    285 cont:
    286   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
    287   %t = load i8, i8* %v1
    288   store i8 %t, i8* %error_ref
    289   br label %handler
    290 handler:
    291   call void @free(i8* %tmp)
    292   ret float 1.0
    293 }
    294 
    295 ; "foo_vararg" is a function that takes a swifterror parameter, it also has
    296 ; variable number of arguments.
    297 declare void @llvm.va_start(i8*) nounwind
    298 define float @foo_vararg(%swift_error** swifterror %error_ptr_ref, ...) {
    299 ; CHECK-APPLE-LABEL: foo_vararg:
    300 ; CHECK-APPLE: orr w0, wzr, #0x10
    301 ; CHECK-APPLE: malloc
    302 ; CHECK-APPLE: orr [[ID:w[0-9]+]], wzr, #0x1
    303 ; CHECK-APPLE: add [[ARGS:x[0-9]+]], [[TMP:x[0-9]+]], #16
    304 ; CHECK-APPLE: strb [[ID]], [x0, #8]
    305 
    306 ; First vararg
    307 ; CHECK-APPLE-DAG: orr {{x[0-9]+}}, [[ARGS]], #0x8
    308 ; CHECK-APPLE-DAG: ldr {{w[0-9]+}}, [{{.*}}[[TMP]], #16]
    309 ; CHECK-APPLE: add {{x[0-9]+}}, {{x[0-9]+}}, #8
    310 ; Second vararg
    311 ; CHECK-APPLE: ldr {{w[0-9]+}}, [{{x[0-9]+}}]
    312 ; CHECK-APPLE: add {{x[0-9]+}}, {{x[0-9]+}}, #8
    313 ; Third vararg
    314 ; CHECK-APPLE: ldr {{w[0-9]+}}, [{{x[0-9]+}}]
    315 
    316 ; CHECK-APPLE: mov x19, x0
    317 ; CHECK-APPLE-NOT: x19
    318 entry:
    319   %call = call i8* @malloc(i64 16)
    320   %call.0 = bitcast i8* %call to %swift_error*
    321   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    322   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    323   store i8 1, i8* %tmp
    324 
    325   %args = alloca i8*, align 8
    326   %a10 = alloca i32, align 4
    327   %a11 = alloca i32, align 4
    328   %a12 = alloca i32, align 4
    329   %v10 = bitcast i8** %args to i8*
    330   call void @llvm.va_start(i8* %v10)
    331   %v11 = va_arg i8** %args, i32
    332   store i32 %v11, i32* %a10, align 4
    333   %v12 = va_arg i8** %args, i32
    334   store i32 %v12, i32* %a11, align 4
    335   %v13 = va_arg i8** %args, i32
    336   store i32 %v13, i32* %a12, align 4
    337 
    338   ret float 1.0
    339 }
    340 
    341 ; "caller4" calls "foo_vararg" that takes a swifterror parameter.
    342 define float @caller4(i8* %error_ref) {
    343 ; CHECK-APPLE-LABEL: caller4:
    344 
    345 ; CHECK-APPLE: mov [[ID:x[0-9]+]], x0
    346 ; CHECK-APPLE: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #8]
    347 ; CHECK-APPLE: str {{x[0-9]+}}, [sp]
    348 
    349 ; CHECK-APPLE: mov x19, xzr
    350 ; CHECK-APPLE: bl {{.*}}foo_vararg
    351 ; CHECK-APPLE: cbnz x19
    352 ; Access part of the error object and save it to error_ref
    353 ; CHECK-APPLE: ldrb [[CODE:w[0-9]+]], [x19, #8]
    354 ; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
    355 ; CHECK-APPLE: mov x0, x19
    356 ; CHECK_APPLE: bl {{.*}}free
    357 entry:
    358   %error_ptr_ref = alloca swifterror %swift_error*
    359   store %swift_error* null, %swift_error** %error_ptr_ref
    360 
    361   %a10 = alloca i32, align 4
    362   %a11 = alloca i32, align 4
    363   %a12 = alloca i32, align 4
    364   store i32 10, i32* %a10, align 4
    365   store i32 11, i32* %a11, align 4
    366   store i32 12, i32* %a12, align 4
    367   %v10 = load i32, i32* %a10, align 4
    368   %v11 = load i32, i32* %a11, align 4
    369   %v12 = load i32, i32* %a12, align 4
    370 
    371   %call = call float (%swift_error**, ...) @foo_vararg(%swift_error** swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12)
    372   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
    373   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
    374   %tmp = bitcast %swift_error* %error_from_foo to i8*
    375   br i1 %had_error_from_foo, label %handler, label %cont
    376 
    377 cont:
    378   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
    379   %t = load i8, i8* %v1
    380   store i8 %t, i8* %error_ref
    381   br label %handler
    382 handler:
    383   call void @free(i8* %tmp)
    384   ret float 1.0
    385 }
    386