Home | History | Annotate | Download | only in SystemZ
      1 ; RUN: llc < %s -mtriple=s390x-linux-gnu| FileCheck %s
      2 ; RUN: llc < %s -O0 -mtriple=s390x-linux-gnu | 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-LABEL: foo:
     12 ; CHECK: lghi %r2, 16
     13 ; CHECK: brasl %r14, malloc
     14 ; CHECK: mvi 8(%r2), 1
     15 ; CHECK: lgr %r9, %r2
     16 ; CHECK-O0-LABEL: foo:
     17 ; CHECK-O0: lghi %r2, 16
     18 ; CHECK-O0: brasl %r14, malloc
     19 ; CHECK-O0: lgr %r[[REG1:[0-9]+]], %r2
     20 ; CHECK-O0: mvi 8(%r2), 1
     21 ; CHECK-O0: lgr %r9, %r[[REG1]]
     22 entry:
     23   %call = call i8* @malloc(i64 16)
     24   %call.0 = bitcast i8* %call to %swift_error*
     25   store %swift_error* %call.0, %swift_error** %error_ptr_ref
     26   %tmp = getelementptr inbounds i8, i8* %call, i64 8
     27   store i8 1, i8* %tmp
     28   ret float 1.0
     29 }
     30 
     31 ; "caller" calls "foo" that takes a swifterror parameter.
     32 define float @caller(i8* %error_ref) {
     33 ; CHECK-LABEL: caller:
     34 ; Make a copy of error_ref because r2 is getting clobbered
     35 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2
     36 ; CHECK: lghi %r9, 0
     37 ; CHECK: brasl %r14, foo
     38 ; CHECK: cgijlh %r9, 0,
     39 ; Access part of the error object and save it to error_ref
     40 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9)
     41 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]])
     42 ; CHECK: lgr %r2, %r9
     43 ; CHECK: brasl %r14, free
     44 ; CHECK-O0-LABEL: caller:
     45 ; CHECK-O0: lghi %r9, 0
     46 ; CHECK-O0: brasl %r14, foo
     47 ; CHECK-O0: cghi %r9, 0
     48 ; CHECK-O0: jlh
     49 entry:
     50   %error_ptr_ref = alloca swifterror %swift_error*
     51   store %swift_error* null, %swift_error** %error_ptr_ref
     52   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
     53   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
     54   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
     55   %tmp = bitcast %swift_error* %error_from_foo to i8*
     56   br i1 %had_error_from_foo, label %handler, label %cont
     57 cont:
     58   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
     59   %t = load i8, i8* %v1
     60   store i8 %t, i8* %error_ref
     61   br label %handler
     62 handler:
     63   call void @free(i8* %tmp)
     64   ret float 1.0
     65 }
     66 
     67 ; "caller2" is the caller of "foo", it calls "foo" inside a loop.
     68 define float @caller2(i8* %error_ref) {
     69 ; CHECK-LABEL: caller2:
     70 ; Make a copy of error_ref because r2 is getting clobbered
     71 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2
     72 ; CHECK: lghi %r9, 0
     73 ; CHECK: brasl %r14, foo
     74 ; CHECK: cgijlh %r9, 0,
     75 ; CHECK: ceb %f0,
     76 ; CHECK: jnh
     77 ; Access part of the error object and save it to error_ref
     78 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9)
     79 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]])
     80 ; CHECK: lgr %r2, %r9
     81 ; CHECK: brasl %r14, free
     82 ; CHECK-O0-LABEL: caller2:
     83 ; CHECK-O0: lghi %r9, 0
     84 ; CHECK-O0: brasl %r14, foo
     85 ; CHECK-O0: cghi %r9, 0
     86 ; CHECK-O0: jlh
     87 entry:
     88   %error_ptr_ref = alloca swifterror %swift_error*
     89   br label %bb_loop
     90 bb_loop:
     91   store %swift_error* null, %swift_error** %error_ptr_ref
     92   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
     93   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
     94   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
     95   %tmp = bitcast %swift_error* %error_from_foo to i8*
     96   br i1 %had_error_from_foo, label %handler, label %cont
     97 cont:
     98   %cmp = fcmp ogt float %call, 1.000000e+00
     99   br i1 %cmp, label %bb_end, label %bb_loop
    100 bb_end:
    101   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
    102   %t = load i8, i8* %v1
    103   store i8 %t, i8* %error_ref
    104   br label %handler
    105 handler:
    106   call void @free(i8* %tmp)
    107   ret float 1.0
    108 }
    109 
    110 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
    111 ; under a certain condition.
    112 define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
    113 ; CHECK-LABEL: foo_if:
    114 ; CHECK: cije %r2, 0
    115 ; CHECK: lghi %r2, 16
    116 ; CHECK: brasl %r14, malloc
    117 ; CHECK: mvi 8(%r2), 1
    118 ; CHECK: lgr %r9, %r2
    119 ; CHECK-NOT: %r9
    120 ; CHECK: br %r14
    121 ; CHECK-O0-LABEL: foo_if:
    122 ; CHECK-O0: chi %r2, 0
    123 ; spill to stack
    124 ; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15)
    125 ; CHECK-O0: je
    126 ; CHECK-O0: lghi %r2, 16
    127 ; CHECK-O0: brasl %r14, malloc
    128 ; CHECK-O0: lgr %r[[REG1:[0-9]+]], %r2
    129 ; CHECK-O0: mvi 8(%r2), 1
    130 ; CHECK-O0: lgr %r9, %r[[REG1]]
    131 ; CHECK-O0: br %r14
    132 ; reload from stack
    133 ; CHECK-O0: lg %r9, [[OFFS]](%r15)
    134 ; CHECK-O0: br %r14
    135 entry:
    136   %cond = icmp ne i32 %cc, 0
    137   br i1 %cond, label %gen_error, label %normal
    138 
    139 gen_error:
    140   %call = call i8* @malloc(i64 16)
    141   %call.0 = bitcast i8* %call to %swift_error*
    142   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    143   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    144   store i8 1, i8* %tmp
    145   ret float 1.0
    146 
    147 normal:
    148   ret float 0.0
    149 }
    150 
    151 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
    152 ; under a certain condition inside a loop.
    153 define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) {
    154 ; CHECK-LABEL: foo_loop:
    155 ; CHECK: lr %r[[REG1:[0-9]+]], %r2
    156 ; CHECK: cije %r[[REG1]], 0
    157 ; CHECK: lghi %r2, 16
    158 ; CHECK: brasl %r14, malloc
    159 ; CHECK: mvi 8(%r2), 1
    160 ; CHECK: ceb %f8,
    161 ; CHECK: jnh
    162 ; CHECK: lgr %r9, %r2
    163 ; CHECK: br %r14
    164 ; CHECK-O0-LABEL: foo_loop:
    165 ; spill to stack
    166 ; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15)
    167 ; CHECK-O0: chi %r{{.*}}, 0
    168 ; CHECK-O0: je
    169 ; CHECK-O0: lghi %r2, 16
    170 ; CHECK-O0: brasl %r14, malloc
    171 ; CHECK-O0: lgr %r[[REG1:[0-9]+]], %r2
    172 ; CHECK-O0: mvi 8(%r2), 1
    173 ; CHECK-O0: jnh
    174 ; reload from stack
    175 ; CHECK-O0: lg %r9, [[OFFS:[0-9]+]](%r15)
    176 ; CHECK-O0: br %r14
    177 entry:
    178   br label %bb_loop
    179 
    180 bb_loop:
    181   %cond = icmp ne i32 %cc, 0
    182   br i1 %cond, label %gen_error, label %bb_cont
    183 
    184 gen_error:
    185   %call = call i8* @malloc(i64 16)
    186   %call.0 = bitcast i8* %call to %swift_error*
    187   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    188   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    189   store i8 1, i8* %tmp
    190   br label %bb_cont
    191 
    192 bb_cont:
    193   %cmp = fcmp ogt float %cc2, 1.000000e+00
    194   br i1 %cmp, label %bb_end, label %bb_loop
    195 bb_end:
    196   ret float 0.0
    197 }
    198 
    199 %struct.S = type { i32, i32, i32, i32, i32, i32 }
    200 
    201 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
    202 ; parameter.
    203 define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
    204 ; CHECK-LABEL: foo_sret:
    205 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2
    206 ; CHECK-DAG: lr %r[[REG2:[0-9]+]], %r3
    207 ; CHECK: lghi %r2, 16
    208 ; CHECK: brasl %r14, malloc
    209 ; CHECK: mvi 8(%r2), 1
    210 ; CHECK: st %r[[REG2]], 4(%r[[REG1]])
    211 ; CHECK: lgr %r9, %r2
    212 ; CHECK-NOT: %r9
    213 ; CHECK: br %r14
    214 
    215 ; CHECK-O0-LABEL: foo_sret:
    216 ; CHECK-O0: lghi %r{{.*}}, 16
    217 ; spill sret to stack
    218 ; CHECK-O0: stg %r2, [[OFFS1:[0-9]+]](%r15)
    219 ; CHECK-O0: lgr %r2, %r{{.*}}
    220 ; CHECK-O0: st %r3, [[OFFS2:[0-9]+]](%r15)
    221 ; CHECK-O0: brasl %r14, malloc
    222 ; CHECK-O0: lgr {{.*}}, %r2
    223 ; CHECK-O0: mvi 8(%r2), 1
    224 ; CHECK-O0-DAG: lg %r[[REG1:[0-9]+]], [[OFFS1]](%r15)
    225 ; CHECK-O0-DAG: l %r[[REG2:[0-9]+]], [[OFFS2]](%r15)
    226 ; CHECK-O0: st %r[[REG2]], 4(%r[[REG1]])
    227 ; CHECK-O0: lgr %r9, {{.*}}
    228 ; CHECK-O0: br %r14
    229 entry:
    230   %call = call i8* @malloc(i64 16)
    231   %call.0 = bitcast i8* %call to %swift_error*
    232   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    233   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    234   store i8 1, i8* %tmp
    235   %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
    236   store i32 %val1, i32* %v2
    237   ret void
    238 }
    239 
    240 ; "caller3" calls "foo_sret" that takes a swifterror parameter.
    241 define float @caller3(i8* %error_ref) {
    242 ; CHECK-LABEL: caller3:
    243 ; Make a copy of error_ref because r2 is getting clobbered
    244 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2
    245 ; CHECK: lhi %r3, 1
    246 ; CHECK: lghi %r9, 0
    247 ; CHECK: brasl %r14, foo_sret
    248 ; CHECK: cgijlh %r9, 0,
    249 ; Access part of the error object and save it to error_ref
    250 ; CHECK: lb %r0, 8(%r9)
    251 ; CHECK: stc %r0, 0(%r[[REG1]])
    252 ; CHECK: lgr %r2, %r9
    253 ; CHECK: brasl %r14, free
    254 
    255 ; CHECK-O0-LABEL: caller3:
    256 ; CHECK-O0: lghi %r9, 0
    257 ; CHECK-O0: lhi %r3, 1
    258 ; CHECK-O0: stg %r2, {{.*}}(%r15)
    259 ; CHECK-O0: lgr %r2, {{.*}}
    260 ; CHECK-O0: brasl %r14, foo_sret
    261 ; CHECK-O0: lgr {{.*}}, %r9
    262 ; CHECK-O0: cghi %r9, 0
    263 ; CHECK-O0: jlh
    264 ; Access part of the error object and save it to error_ref
    265 ; CHECK-O0: lb %r0, 8(%r{{.*}})
    266 ; CHECK-O0: stc %r0, 0(%r{{.*}})
    267 ; reload from stack
    268 ; CHECK-O0: lg %r2, {{.*}}(%r15)
    269 ; CHECK-O0: brasl %r14, free
    270 entry:
    271   %s = alloca %struct.S, align 8
    272   %error_ptr_ref = alloca swifterror %swift_error*
    273   store %swift_error* null, %swift_error** %error_ptr_ref
    274   call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref)
    275   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
    276   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
    277   %tmp = bitcast %swift_error* %error_from_foo to i8*
    278   br i1 %had_error_from_foo, label %handler, label %cont
    279 cont:
    280   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
    281   %t = load i8, i8* %v1
    282   store i8 %t, i8* %error_ref
    283   br label %handler
    284 handler:
    285   call void @free(i8* %tmp)
    286   ret float 1.0
    287 }
    288 
    289 ; This is a caller with multiple swifterror values, it calls "foo" twice, each
    290 ; time with a different swifterror value, from "alloca swifterror".
    291 define float @caller_with_multiple_swifterror_values(i8* %error_ref, i8* %error_ref2) {
    292 ; CHECK-LABEL: caller_with_multiple_swifterror_values:
    293 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2
    294 ; CHECK-DAG: lgr %r[[REG2:[0-9]+]], %r3
    295 ; The first swifterror value:
    296 ; CHECK: lghi %r9, 0
    297 ; CHECK: brasl %r14, foo
    298 ; CHECK: cgijlh %r9, 0,
    299 ; Access part of the error object and save it to error_ref
    300 ; CHECK: lb %r0, 8(%r9)
    301 ; CHECK: stc %r0, 0(%r[[REG1]])
    302 ; CHECK: lgr %r2, %r9
    303 ; CHECK: brasl %r14, free
    304 
    305 ; The second swifterror value:
    306 ; CHECK: lghi %r9, 0
    307 ; CHECK: brasl %r14, foo
    308 ; CHECK: cgijlh %r9, 0,
    309 ; Access part of the error object and save it to error_ref
    310 ; CHECK: lb %r0, 8(%r9)
    311 ; CHECK: stc %r0, 0(%r[[REG2]])
    312 ; CHECK: lgr %r2, %r9
    313 ; CHECK: brasl %r14, free
    314 
    315 ; CHECK-O0-LABEL: caller_with_multiple_swifterror_values:
    316 
    317 ; The first swifterror value:
    318 ; CHECK-O0: lghi %r9, 0
    319 ; CHECK-O0: brasl %r14, foo
    320 ; CHECK-O0: jlh
    321 
    322 ; The second swifterror value:
    323 ; CHECK-O0: lghi %r9, 0
    324 ; CHECK-O0: brasl %r14, foo
    325 ; CHECK-O0: jlh
    326 entry:
    327   %error_ptr_ref = alloca swifterror %swift_error*
    328   store %swift_error* null, %swift_error** %error_ptr_ref
    329   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
    330   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
    331   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
    332   %tmp = bitcast %swift_error* %error_from_foo to i8*
    333   br i1 %had_error_from_foo, label %handler, label %cont
    334 cont:
    335   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
    336   %t = load i8, i8* %v1
    337   store i8 %t, i8* %error_ref
    338   br label %handler
    339 handler:
    340   call void @free(i8* %tmp)
    341 
    342   %error_ptr_ref2 = alloca swifterror %swift_error*
    343   store %swift_error* null, %swift_error** %error_ptr_ref2
    344   %call2 = call float @foo(%swift_error** swifterror %error_ptr_ref2)
    345   %error_from_foo2 = load %swift_error*, %swift_error** %error_ptr_ref2
    346   %had_error_from_foo2 = icmp ne %swift_error* %error_from_foo2, null
    347   %bitcast2 = bitcast %swift_error* %error_from_foo2 to i8*
    348   br i1 %had_error_from_foo2, label %handler2, label %cont2
    349 cont2:
    350   %v2 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo2, i64 0, i32 1
    351   %t2 = load i8, i8* %v2
    352   store i8 %t2, i8* %error_ref2
    353   br label %handler2
    354 handler2:
    355   call void @free(i8* %bitcast2)
    356 
    357   ret float 1.0
    358 }
    359