344 lines · plain
1; RUN: llc < %s -mtriple=s390x-linux-gnu -disable-block-placement | FileCheck %s2; RUN: llc < %s -O0 -mtriple=s390x-linux-gnu -disable-block-placement | FileCheck --check-prefix=CHECK-O0 %s3 4declare ptr @malloc(i64)5declare void @free(ptr)6%swift_error = type {i64, i8}7 8; This tests the basic usage of a swifterror parameter. "foo" is the function9; that takes a swifterror parameter and "caller" is the caller of "foo".10define float @foo(ptr swifterror %error_ptr_ref) {11; CHECK-LABEL: foo:12; CHECK: lghi %r2, 1613; CHECK: brasl %r14, malloc14; CHECK: mvi 8(%r2), 115; CHECK: lgr %r9, %r216; CHECK-O0-LABEL: foo:17; CHECK-O0: lghi %r2, 1618; CHECK-O0: brasl %r14, malloc19; CHECK-O0: lgr [[T0:%r[0-9]+]], %r220; CHECK-O0: mvi 8(%r2), 121entry:22 %call = call ptr @malloc(i64 16)23 store ptr %call, ptr %error_ptr_ref24 %tmp = getelementptr inbounds i8, ptr %call, i64 825 store i8 1, ptr %tmp26 ret float 1.027}28 29; "caller" calls "foo" that takes a swifterror parameter.30define float @caller(ptr %error_ref) {31; CHECK-LABEL: caller:32; Make a copy of error_ref because r2 is getting clobbered33; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r234; CHECK-DAG: lghi %r9, 035; CHECK: brasl %r14, foo36; CHECK: %r2, %r937; CHECK: jlh38; Access part of the error object and save it to error_ref39; CHECK: lb %r[[REG2:[0-9]+]], 8(%r2)40; CHECK: stc %r[[REG2]], 0(%r[[REG1]])41; CHECK: brasl %r14, free42; CHECK-O0-LABEL: caller:43; CHECK-O0: lghi %r9, 044; CHECK-O0: brasl %r14, foo45; CHECK-O0: cghi %r9, 046; CHECK-O0: jlh47entry:48 %error_ptr_ref = alloca swifterror ptr49 store ptr null, ptr %error_ptr_ref50 %call = call float @foo(ptr swifterror %error_ptr_ref)51 %error_from_foo = load ptr, ptr %error_ptr_ref52 %had_error_from_foo = icmp ne ptr %error_from_foo, null53 br i1 %had_error_from_foo, label %handler, label %cont54cont:55 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 156 %t = load i8, ptr %v157 store i8 %t, ptr %error_ref58 br label %handler59handler:60 call void @free(ptr %error_from_foo)61 ret float 1.062}63 64; "caller2" is the caller of "foo", it calls "foo" inside a loop.65define float @caller2(ptr %error_ref) {66; CHECK-LABEL: caller2:67; Make a copy of error_ref because r2 is getting clobbered68; CHECK: lgr %r[[REG1:[0-9]+]], %r269; CHECK: lghi %r9, 070; CHECK: brasl %r14, foo71; CHECK: cgijlh %r9, 0,72; CHECK: ceb %f0,73; CHECK: jnh74; Access part of the error object and save it to error_ref75; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9)76; CHECK: stc %r[[REG2]], 0(%r[[REG1]])77; CHECK: lgr %r2, %r978; CHECK: brasl %r14, free79; CHECK-O0-LABEL: caller2:80; CHECK-O0: lghi %r9, 081; CHECK-O0: brasl %r14, foo82; CHECK-O0: cghi %r9, 083; CHECK-O0: jlh84entry:85 %error_ptr_ref = alloca swifterror ptr86 br label %bb_loop87bb_loop:88 store ptr null, ptr %error_ptr_ref89 %call = call float @foo(ptr swifterror %error_ptr_ref)90 %error_from_foo = load ptr, ptr %error_ptr_ref91 %had_error_from_foo = icmp ne ptr %error_from_foo, null92 br i1 %had_error_from_foo, label %handler, label %cont93cont:94 %cmp = fcmp ogt float %call, 1.000000e+0095 br i1 %cmp, label %bb_end, label %bb_loop96bb_end:97 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 198 %t = load i8, ptr %v199 store i8 %t, ptr %error_ref100 br label %handler101handler:102 call void @free(ptr %error_from_foo)103 ret float 1.0104}105 106; "foo_if" is a function that takes a swifterror parameter, it sets swifterror107; under a certain condition.108define float @foo_if(ptr swifterror %error_ptr_ref, i32 %cc) {109; CHECK-LABEL: foo_if:110; CHECK: cije %r2, 0111; CHECK: lghi %r2, 16112; CHECK: brasl %r14, malloc113; CHECK: mvi 8(%r2), 1114; CHECK: lgr %r9, %r2115; CHECK-NOT: %r9116; CHECK: br %r14117; CHECK-O0-LABEL: foo_if:118; spill to stack119; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15)120; CHECK-O0: chi %r2, 0121; CHECK-O0: je122; CHECK-O0: lghi %r2, 16123; CHECK-O0: brasl %r14, malloc124; CHECK-O0: lgr %r9, %r2125; CHECK-O0: mvi 8(%r2), 1126; CHECK-O0: br %r14127; reload from stack128; CHECK-O0: lg %r9, [[OFFS]](%r15)129; CHECK-O0: br %r14130entry:131 %cond = icmp ne i32 %cc, 0132 br i1 %cond, label %gen_error, label %normal133 134gen_error:135 %call = call ptr @malloc(i64 16)136 store ptr %call, ptr %error_ptr_ref137 %tmp = getelementptr inbounds i8, ptr %call, i64 8138 store i8 1, ptr %tmp139 ret float 1.0140 141normal:142 ret float 0.0143}144 145; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror146; under a certain condition inside a loop.147define float @foo_loop(ptr swifterror %error_ptr_ref, i32 %cc, float %cc2) {148; CHECK-LABEL: foo_loop:149; CHECK: lr %r[[REG1:[0-9]+]], %r2150; CHECK: cije %r[[REG1]], 0151; CHECK: lghi %r2, 16152; CHECK: brasl %r14, malloc153; CHECK: mvi 8(%r2), 1154; CHECK: ceb %f8,155; CHECK: jnh156; CHECK: lgr %r9, %r2157; CHECK: br %r14158; CHECK-O0-LABEL: foo_loop:159; spill to stack160; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15)161; CHECK-O0: chi %r{{.*}}, 0162; CHECK-O0: je163; CHECK-O0: lghi %r2, 16164; CHECK-O0: brasl %r14, malloc165; CHECK-O0: lgr %r[[REG1:[0-9]+]], %r2166; CHECK-O0: mvi 8(%r[[REG1]]), 1167; CHECK-O0: jnh168; reload from stack169; CHECK-O0: lg %r9, [[OFFS:[0-9]+]](%r15)170; CHECK-O0: br %r14171entry:172 br label %bb_loop173 174bb_loop:175 %cond = icmp ne i32 %cc, 0176 br i1 %cond, label %gen_error, label %bb_cont177 178gen_error:179 %call = call ptr @malloc(i64 16)180 store ptr %call, ptr %error_ptr_ref181 %tmp = getelementptr inbounds i8, ptr %call, i64 8182 store i8 1, ptr %tmp183 br label %bb_cont184 185bb_cont:186 %cmp = fcmp ogt float %cc2, 1.000000e+00187 br i1 %cmp, label %bb_end, label %bb_loop188bb_end:189 ret float 0.0190}191 192%struct.S = type { i32, i32, i32, i32, i32, i32 }193 194; "foo_sret" is a function that takes a swifterror parameter, it also has a sret195; parameter.196define void @foo_sret(ptr sret(%struct.S) %agg.result, i32 %val1, ptr swifterror %error_ptr_ref) {197; CHECK-LABEL: foo_sret:198; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2199; CHECK-DAG: lr %r[[REG2:[0-9]+]], %r3200; CHECK-DAG: lghi %r2, 16201; CHECK: brasl %r14, malloc202; CHECK: mvi 8(%r2), 1203; CHECK: st %r[[REG2]], 4(%r[[REG1]])204; CHECK: lgr %r9, %r2205; CHECK-NOT: %r9206; CHECK: br %r14207 208; CHECK-O0-LABEL: foo_sret:209; spill sret to stack210; CHECK-O0-DAG: stg %r2, [[OFFS1:[0-9]+]](%r15)211; CHECK-O0-DAG: st %r3, [[OFFS2:[0-9]+]](%r15)212; CHECK-O0: lghi %r2, 16213; CHECK-O0: brasl %r14, malloc214; CHECK-O0-DAG: lgr %r[[REG3:[0-9]+]], %r2215; CHECK-O0-DAG: mvi 8(%r[[REG3]]), 1216; CHECK-O0-DAG: lg %r[[REG1:[0-9]+]], [[OFFS1]](%r15)217; CHECK-O0-DAG: lgr %r9, %r[[REG3]]218; CHECK-O0-DAG: l %r[[REG2:[0-9]+]], [[OFFS2]](%r15)219; CHECK-O0: st %r[[REG2]], 4(%r[[REG1]])220; CHECK-O0: br %r14221entry:222 %call = call ptr @malloc(i64 16)223 store ptr %call, ptr %error_ptr_ref224 %tmp = getelementptr inbounds i8, ptr %call, i64 8225 store i8 1, ptr %tmp226 %v2 = getelementptr inbounds %struct.S, ptr %agg.result, i32 0, i32 1227 store i32 %val1, ptr %v2228 ret void229}230 231; "caller3" calls "foo_sret" that takes a swifterror parameter.232define float @caller3(ptr %error_ref) {233; CHECK-LABEL: caller3:234; Make a copy of error_ref because r2 is getting clobbered235; CHECK: lgr %r[[REG1:[0-9]+]], %r2236; CHECK: lhi %r3, 1237; CHECK: lghi %r9, 0238; CHECK: brasl %r14, foo_sret239; CHECK: jlh240; Access part of the error object and save it to error_ref241; CHECK: lb %r0, 8(%r2)242; CHECK: stc %r0, 0(%r[[REG1]])243; CHECK: brasl %r14, free244 245; CHECK-O0-LABEL: caller3:246; CHECK-O0: lghi %r9, 0247; CHECK-O0: lhi %r3, 1248; CHECK-O0: brasl %r14, foo_sret249; CHECK-O0: lgr {{.*}}, %r9250; CHECK-O0: cghi %r9, 0251; CHECK-O0: jlh252; Access part of the error object and save it to error_ref253; CHECK-O0: lb %r0, 8(%r{{.*}})254; CHECK-O0: stc %r0, 0(%r{{.*}})255; reload from stack256; CHECK-O0: lg %r2, {{.*}}(%r15)257; CHECK-O0: brasl %r14, free258entry:259 %s = alloca %struct.S, align 8260 %error_ptr_ref = alloca swifterror ptr261 store ptr null, ptr %error_ptr_ref262 call void @foo_sret(ptr sret(%struct.S) %s, i32 1, ptr swifterror %error_ptr_ref)263 %error_from_foo = load ptr, ptr %error_ptr_ref264 %had_error_from_foo = icmp ne ptr %error_from_foo, null265 br i1 %had_error_from_foo, label %handler, label %cont266cont:267 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1268 %t = load i8, ptr %v1269 store i8 %t, ptr %error_ref270 br label %handler271handler:272 call void @free(ptr %error_from_foo)273 ret float 1.0274}275 276; This is a caller with multiple swifterror values, it calls "foo" twice, each277; time with a different swifterror value, from "alloca swifterror".278define float @caller_with_multiple_swifterror_values(ptr %error_ref, ptr %error_ref2) {279; CHECK-LABEL: caller_with_multiple_swifterror_values:280; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2281; CHECK-DAG: lgr %r[[REG2:[0-9]+]], %r3282; The first swifterror value:283; CHECK-DAG: lghi %r9, 0284; CHECK: brasl %r14, foo285; CHECK: ltgr %r2, %r9286; CHECK: jlh287; Access part of the error object and save it to error_ref288; CHECK: lb %r0, 8(%r2)289; CHECK: stc %r0, 0(%r[[REG1]])290; CHECK: brasl %r14, free291 292; The second swifterror value:293; CHECK: lghi %r9, 0294; CHECK: brasl %r14, foo295; CHECK: ltgr %r2, %r9296; CHECK: jlh297; Access part of the error object and save it to error_ref298; CHECK: lb %r0, 8(%r2)299; CHECK: stc %r0, 0(%r[[REG2]])300; CHECK: brasl %r14, free301 302; CHECK-O0-LABEL: caller_with_multiple_swifterror_values:303 304; The first swifterror value:305; CHECK-O0: lghi %r9, 0306; CHECK-O0: brasl %r14, foo307; CHECK-O0: jlh308 309; The second swifterror value:310; CHECK-O0: lghi %r9, 0311; CHECK-O0: brasl %r14, foo312; CHECK-O0: jlh313entry:314 %error_ptr_ref = alloca swifterror ptr315 store ptr null, ptr %error_ptr_ref316 %call = call float @foo(ptr swifterror %error_ptr_ref)317 %error_from_foo = load ptr, ptr %error_ptr_ref318 %had_error_from_foo = icmp ne ptr %error_from_foo, null319 br i1 %had_error_from_foo, label %handler, label %cont320cont:321 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1322 %t = load i8, ptr %v1323 store i8 %t, ptr %error_ref324 br label %handler325handler:326 call void @free(ptr %error_from_foo)327 328 %error_ptr_ref2 = alloca swifterror ptr329 store ptr null, ptr %error_ptr_ref2330 %call2 = call float @foo(ptr swifterror %error_ptr_ref2)331 %error_from_foo2 = load ptr, ptr %error_ptr_ref2332 %had_error_from_foo2 = icmp ne ptr %error_from_foo2, null333 br i1 %had_error_from_foo2, label %handler2, label %cont2334cont2:335 %v2 = getelementptr inbounds %swift_error, ptr %error_from_foo2, i64 0, i32 1336 %t2 = load i8, ptr %v2337 store i8 %t2, ptr %error_ref2338 br label %handler2339handler2:340 call void @free(ptr %error_from_foo2)341 342 ret float 1.0343}344