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 %r9, %r2
     20 ; CHECK-O0: mvi 8(%r2), 1
     21 entry:
     22   %call = call i8* @malloc(i64 16)
     23   %call.0 = bitcast i8* %call to %swift_error*
     24   store %swift_error* %call.0, %swift_error** %error_ptr_ref
     25   %tmp = getelementptr inbounds i8, i8* %call, i64 8
     26   store i8 1, i8* %tmp
     27   ret float 1.0
     28 }
     29 
     30 ; "caller" calls "foo" that takes a swifterror parameter.
     31 define float @caller(i8* %error_ref) {
     32 ; CHECK-LABEL: caller:
     33 ; Make a copy of error_ref because r2 is getting clobbered
     34 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2
     35 ; CHECK: lghi %r9, 0
     36 ; CHECK: brasl %r14, foo
     37 ; CHECK: %r2, %r9
     38 ; CHECK: jlh
     39 ; Access part of the error object and save it to error_ref
     40 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r2)
     41 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]])
     42 ; CHECK: brasl %r14, free
     43 ; CHECK-O0-LABEL: caller:
     44 ; CHECK-O0: lghi %r9, 0
     45 ; CHECK-O0: brasl %r14, foo
     46 ; CHECK-O0: cghi %r9, 0
     47 ; CHECK-O0: jlh
     48 entry:
     49   %error_ptr_ref = alloca swifterror %swift_error*
     50   store %swift_error* null, %swift_error** %error_ptr_ref
     51   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
     52   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
     53   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
     54   %tmp = bitcast %swift_error* %error_from_foo to i8*
     55   br i1 %had_error_from_foo, label %handler, label %cont
     56 cont:
     57   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
     58   %t = load i8, i8* %v1
     59   store i8 %t, i8* %error_ref
     60   br label %handler
     61 handler:
     62   call void @free(i8* %tmp)
     63   ret float 1.0
     64 }
     65 
     66 ; "caller2" is the caller of "foo", it calls "foo" inside a loop.
     67 define float @caller2(i8* %error_ref) {
     68 ; CHECK-LABEL: caller2:
     69 ; Make a copy of error_ref because r2 is getting clobbered
     70 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2
     71 ; CHECK: lghi %r9, 0
     72 ; CHECK: brasl %r14, foo
     73 ; CHECK: cgijlh %r9, 0,
     74 ; CHECK: ceb %f0,
     75 ; CHECK: jnh
     76 ; Access part of the error object and save it to error_ref
     77 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9)
     78 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]])
     79 ; CHECK: lgr %r2, %r9
     80 ; CHECK: brasl %r14, free
     81 ; CHECK-O0-LABEL: caller2:
     82 ; CHECK-O0: lghi %r9, 0
     83 ; CHECK-O0: brasl %r14, foo
     84 ; CHECK-O0: cghi %r9, 0
     85 ; CHECK-O0: jlh
     86 entry:
     87   %error_ptr_ref = alloca swifterror %swift_error*
     88   br label %bb_loop
     89 bb_loop:
     90   store %swift_error* null, %swift_error** %error_ptr_ref
     91   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
     92   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
     93   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
     94   %tmp = bitcast %swift_error* %error_from_foo to i8*
     95   br i1 %had_error_from_foo, label %handler, label %cont
     96 cont:
     97   %cmp = fcmp ogt float %call, 1.000000e+00
     98   br i1 %cmp, label %bb_end, label %bb_loop
     99 bb_end:
    100   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
    101   %t = load i8, i8* %v1
    102   store i8 %t, i8* %error_ref
    103   br label %handler
    104 handler:
    105   call void @free(i8* %tmp)
    106   ret float 1.0
    107 }
    108 
    109 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
    110 ; under a certain condition.
    111 define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
    112 ; CHECK-LABEL: foo_if:
    113 ; CHECK: cije %r2, 0
    114 ; CHECK: lghi %r2, 16
    115 ; CHECK: brasl %r14, malloc
    116 ; CHECK: mvi 8(%r2), 1
    117 ; CHECK: lgr %r9, %r2
    118 ; CHECK-NOT: %r9
    119 ; CHECK: br %r14
    120 ; CHECK-O0-LABEL: foo_if:
    121 ; CHECK-O0: chi %r2, 0
    122 ; spill to stack
    123 ; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15)
    124 ; CHECK-O0: je
    125 ; CHECK-O0: lghi %r2, 16
    126 ; CHECK-O0: brasl %r14, malloc
    127 ; CHECK-O0: lgr %r[[REG1:[0-9]+]], %r2
    128 ; CHECK-O0: mvi 8(%r2), 1
    129 ; CHECK-O0: lgr %r9, %r[[REG1]]
    130 ; CHECK-O0: br %r14
    131 ; reload from stack
    132 ; CHECK-O0: lg %r[[REG2:[0-9]+]], [[OFFS]](%r15)
    133 ; CHECK-O0: lgr %r9, %r[[REG2]]
    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 %r[[REG2:[0-9]+]], [[OFFS:[0-9]+]](%r15)
    176 ; CHECK-O0: lgr %r9, %r[[REG2]]
    177 ; CHECK-O0: br %r14
    178 entry:
    179   br label %bb_loop
    180 
    181 bb_loop:
    182   %cond = icmp ne i32 %cc, 0
    183   br i1 %cond, label %gen_error, label %bb_cont
    184 
    185 gen_error:
    186   %call = call i8* @malloc(i64 16)
    187   %call.0 = bitcast i8* %call to %swift_error*
    188   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    189   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    190   store i8 1, i8* %tmp
    191   br label %bb_cont
    192 
    193 bb_cont:
    194   %cmp = fcmp ogt float %cc2, 1.000000e+00
    195   br i1 %cmp, label %bb_end, label %bb_loop
    196 bb_end:
    197   ret float 0.0
    198 }
    199 
    200 %struct.S = type { i32, i32, i32, i32, i32, i32 }
    201 
    202 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
    203 ; parameter.
    204 define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
    205 ; CHECK-LABEL: foo_sret:
    206 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2
    207 ; CHECK-DAG: lr %r[[REG2:[0-9]+]], %r3
    208 ; CHECK: lghi %r2, 16
    209 ; CHECK: brasl %r14, malloc
    210 ; CHECK: mvi 8(%r2), 1
    211 ; CHECK: st %r[[REG2]], 4(%r[[REG1]])
    212 ; CHECK: lgr %r9, %r2
    213 ; CHECK-NOT: %r9
    214 ; CHECK: br %r14
    215 
    216 ; CHECK-O0-LABEL: foo_sret:
    217 ; CHECK-O0: lghi %r{{.*}}, 16
    218 ; spill sret to stack
    219 ; CHECK-O0: stg %r2, [[OFFS1:[0-9]+]](%r15)
    220 ; CHECK-O0: lgr %r2, %r{{.*}}
    221 ; CHECK-O0: st %r3, [[OFFS2:[0-9]+]](%r15)
    222 ; CHECK-O0: brasl %r14, malloc
    223 ; CHECK-O0: lgr {{.*}}, %r2
    224 ; CHECK-O0: mvi 8(%r2), 1
    225 ; CHECK-O0-DAG: lg %r[[REG1:[0-9]+]], [[OFFS1]](%r15)
    226 ; CHECK-O0-DAG: l %r[[REG2:[0-9]+]], [[OFFS2]](%r15)
    227 ; CHECK-O0: st %r[[REG2]], 4(%r[[REG1]])
    228 ; CHECK-O0: lgr %r9, {{.*}}
    229 ; CHECK-O0: br %r14
    230 entry:
    231   %call = call i8* @malloc(i64 16)
    232   %call.0 = bitcast i8* %call to %swift_error*
    233   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    234   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    235   store i8 1, i8* %tmp
    236   %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
    237   store i32 %val1, i32* %v2
    238   ret void
    239 }
    240 
    241 ; "caller3" calls "foo_sret" that takes a swifterror parameter.
    242 define float @caller3(i8* %error_ref) {
    243 ; CHECK-LABEL: caller3:
    244 ; Make a copy of error_ref because r2 is getting clobbered
    245 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2
    246 ; CHECK: lhi %r3, 1
    247 ; CHECK: lghi %r9, 0
    248 ; CHECK: brasl %r14, foo_sret
    249 ; CHECK: jlh
    250 ; Access part of the error object and save it to error_ref
    251 ; CHECK: lb %r0, 8(%r2)
    252 ; CHECK: stc %r0, 0(%r[[REG1]])
    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: ltgr %r2, %r9
    299 ; CHECK: jlh
    300 ; Access part of the error object and save it to error_ref
    301 ; CHECK: lb %r0, 8(%r2)
    302 ; CHECK: stc %r0, 0(%r[[REG1]])
    303 ; CHECK: brasl %r14, free
    304 
    305 ; The second swifterror value:
    306 ; CHECK: lghi %r9, 0
    307 ; CHECK: brasl %r14, foo
    308 ; CHECK: ltgr %r2, %r9
    309 ; CHECK: jlh
    310 ; Access part of the error object and save it to error_ref
    311 ; CHECK: lb %r0, 8(%r2)
    312 ; CHECK: stc %r0, 0(%r[[REG2]])
    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