326 lines · plain
1; Test 32-bit subtraction in which the second operand is variable.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s4 5declare i32 @foo()6 7; Check SR.8define zeroext i1 @f1(i32 %dummy, i32 %a, i32 %b, ptr %res) {9; CHECK-LABEL: f1:10; CHECK: sr %r3, %r411; CHECK-DAG: st %r3, 0(%r5)12; CHECK-DAG: ipm [[REG:%r[0-5]]]13; CHECK-DAG: afi [[REG]], 134217728014; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 3315; CHECK: br %r1416 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)17 %val = extractvalue {i32, i1} %t, 018 %obit = extractvalue {i32, i1} %t, 119 store i32 %val, ptr %res20 ret i1 %obit21}22 23; Check using the overflow result for a branch.24define void @f2(i32 %dummy, i32 %a, i32 %b, ptr %res) {25; CHECK-LABEL: f2:26; CHECK: sr %r3, %r427; CHECK: st %r3, 0(%r5)28; CHECK: jgo foo@PLT29; CHECK: br %r1430 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)31 %val = extractvalue {i32, i1} %t, 032 %obit = extractvalue {i32, i1} %t, 133 store i32 %val, ptr %res34 br i1 %obit, label %call, label %exit35 36call:37 tail call i32 @foo()38 br label %exit39 40exit:41 ret void42}43 44; ... and the same with the inverted direction.45define void @f3(i32 %dummy, i32 %a, i32 %b, ptr %res) {46; CHECK-LABEL: f3:47; CHECK: sr %r3, %r448; CHECK: st %r3, 0(%r5)49; CHECK: jgno foo@PLT50; CHECK: br %r1451 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)52 %val = extractvalue {i32, i1} %t, 053 %obit = extractvalue {i32, i1} %t, 154 store i32 %val, ptr %res55 br i1 %obit, label %exit, label %call56 57call:58 tail call i32 @foo()59 br label %exit60 61exit:62 ret void63}64 65; Check the low end of the S range.66define zeroext i1 @f4(i32 %dummy, i32 %a, ptr %src, ptr %res) {67; CHECK-LABEL: f4:68; CHECK: s %r3, 0(%r4)69; CHECK-DAG: st %r3, 0(%r5)70; CHECK-DAG: ipm [[REG:%r[0-5]]]71; CHECK-DAG: afi [[REG]], 134217728072; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 3373; CHECK: br %r1474 %b = load i32, ptr %src75 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)76 %val = extractvalue {i32, i1} %t, 077 %obit = extractvalue {i32, i1} %t, 178 store i32 %val, ptr %res79 ret i1 %obit80}81 82; Check the high end of the aligned S range.83define zeroext i1 @f5(i32 %dummy, i32 %a, ptr %src, ptr %res) {84; CHECK-LABEL: f5:85; CHECK: s %r3, 4092(%r4)86; CHECK-DAG: st %r3, 0(%r5)87; CHECK-DAG: ipm [[REG:%r[0-5]]]88; CHECK-DAG: afi [[REG]], 134217728089; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 3390; CHECK: br %r1491 %ptr = getelementptr i32, ptr %src, i64 102392 %b = load i32, ptr %ptr93 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)94 %val = extractvalue {i32, i1} %t, 095 %obit = extractvalue {i32, i1} %t, 196 store i32 %val, ptr %res97 ret i1 %obit98}99 100; Check the next word up, which should use SY instead of S.101define zeroext i1 @f6(i32 %dummy, i32 %a, ptr %src, ptr %res) {102; CHECK-LABEL: f6:103; CHECK: sy %r3, 4096(%r4)104; CHECK-DAG: st %r3, 0(%r5)105; CHECK-DAG: ipm [[REG:%r[0-5]]]106; CHECK-DAG: afi [[REG]], 1342177280107; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33108; CHECK: br %r14109 %ptr = getelementptr i32, ptr %src, i64 1024110 %b = load i32, ptr %ptr111 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)112 %val = extractvalue {i32, i1} %t, 0113 %obit = extractvalue {i32, i1} %t, 1114 store i32 %val, ptr %res115 ret i1 %obit116}117 118; Check the high end of the aligned SY range.119define zeroext i1 @f7(i32 %dummy, i32 %a, ptr %src, ptr %res) {120; CHECK-LABEL: f7:121; CHECK: sy %r3, 524284(%r4)122; CHECK-DAG: st %r3, 0(%r5)123; CHECK-DAG: ipm [[REG:%r[0-5]]]124; CHECK-DAG: afi [[REG]], 1342177280125; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33126; CHECK: br %r14127 %ptr = getelementptr i32, ptr %src, i64 131071128 %b = load i32, ptr %ptr129 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)130 %val = extractvalue {i32, i1} %t, 0131 %obit = extractvalue {i32, i1} %t, 1132 store i32 %val, ptr %res133 ret i1 %obit134}135 136; Check the next word up, which needs separate address logic.137; Other sequences besides this one would be OK.138define zeroext i1 @f8(i32 %dummy, i32 %a, ptr %src, ptr %res) {139; CHECK-LABEL: f8:140; CHECK: agfi %r4, 524288141; CHECK: s %r3, 0(%r4)142; CHECK-DAG: st %r3, 0(%r5)143; CHECK-DAG: ipm [[REG:%r[0-5]]]144; CHECK-DAG: afi [[REG]], 1342177280145; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33146; CHECK: br %r14147 %ptr = getelementptr i32, ptr %src, i64 131072148 %b = load i32, ptr %ptr149 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)150 %val = extractvalue {i32, i1} %t, 0151 %obit = extractvalue {i32, i1} %t, 1152 store i32 %val, ptr %res153 ret i1 %obit154}155 156; Check the high end of the negative aligned SY range.157define zeroext i1 @f9(i32 %dummy, i32 %a, ptr %src, ptr %res) {158; CHECK-LABEL: f9:159; CHECK: sy %r3, -4(%r4)160; CHECK-DAG: st %r3, 0(%r5)161; CHECK-DAG: ipm [[REG:%r[0-5]]]162; CHECK-DAG: afi [[REG]], 1342177280163; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33164; CHECK: br %r14165 %ptr = getelementptr i32, ptr %src, i64 -1166 %b = load i32, ptr %ptr167 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)168 %val = extractvalue {i32, i1} %t, 0169 %obit = extractvalue {i32, i1} %t, 1170 store i32 %val, ptr %res171 ret i1 %obit172}173 174; Check the low end of the SY range.175define zeroext i1 @f10(i32 %dummy, i32 %a, ptr %src, ptr %res) {176; CHECK-LABEL: f10:177; CHECK: sy %r3, -524288(%r4)178; CHECK-DAG: st %r3, 0(%r5)179; CHECK-DAG: ipm [[REG:%r[0-5]]]180; CHECK-DAG: afi [[REG]], 1342177280181; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33182; CHECK: br %r14183 %ptr = getelementptr i32, ptr %src, i64 -131072184 %b = load i32, ptr %ptr185 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)186 %val = extractvalue {i32, i1} %t, 0187 %obit = extractvalue {i32, i1} %t, 1188 store i32 %val, ptr %res189 ret i1 %obit190}191 192; Check the next word down, which needs separate address logic.193; Other sequences besides this one would be OK.194define zeroext i1 @f11(i32 %dummy, i32 %a, ptr %src, ptr %res) {195; CHECK-LABEL: f11:196; CHECK: agfi %r4, -524292197; CHECK: s %r3, 0(%r4)198; CHECK-DAG: st %r3, 0(%r5)199; CHECK-DAG: ipm [[REG:%r[0-5]]]200; CHECK-DAG: afi [[REG]], 1342177280201; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33202; CHECK: br %r14203 %ptr = getelementptr i32, ptr %src, i64 -131073204 %b = load i32, ptr %ptr205 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)206 %val = extractvalue {i32, i1} %t, 0207 %obit = extractvalue {i32, i1} %t, 1208 store i32 %val, ptr %res209 ret i1 %obit210}211 212; Check that S allows an index.213define zeroext i1 @f12(i64 %src, i64 %index, i32 %a, ptr %res) {214; CHECK-LABEL: f12:215; CHECK: s %r4, 4092({{%r3,%r2|%r2,%r3}})216; CHECK-DAG: st %r4, 0(%r5)217; CHECK-DAG: ipm [[REG:%r[0-5]]]218; CHECK-DAG: afi [[REG]], 1342177280219; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33220; CHECK: br %r14221 %add1 = add i64 %src, %index222 %add2 = add i64 %add1, 4092223 %ptr = inttoptr i64 %add2 to ptr224 %b = load i32, ptr %ptr225 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)226 %val = extractvalue {i32, i1} %t, 0227 %obit = extractvalue {i32, i1} %t, 1228 store i32 %val, ptr %res229 ret i1 %obit230}231 232; Check that SY allows an index.233define zeroext i1 @f13(i64 %src, i64 %index, i32 %a, ptr %res) {234; CHECK-LABEL: f13:235; CHECK: sy %r4, 4096({{%r3,%r2|%r2,%r3}})236; CHECK-DAG: st %r4, 0(%r5)237; CHECK-DAG: ipm [[REG:%r[0-5]]]238; CHECK-DAG: afi [[REG]], 1342177280239; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33240; CHECK: br %r14241 %add1 = add i64 %src, %index242 %add2 = add i64 %add1, 4096243 %ptr = inttoptr i64 %add2 to ptr244 %b = load i32, ptr %ptr245 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)246 %val = extractvalue {i32, i1} %t, 0247 %obit = extractvalue {i32, i1} %t, 1248 store i32 %val, ptr %res249 ret i1 %obit250}251 252; Check that subtractions of spilled values can use S rather than SR.253define zeroext i1 @f14(ptr %ptr0) {254; CHECK-LABEL: f14:255; CHECK: brasl %r14, foo@PLT256; CHECK: s %r2, 16{{[04]}}(%r15)257; CHECK: br %r14258 %ptr1 = getelementptr i32, ptr %ptr0, i64 2259 %ptr2 = getelementptr i32, ptr %ptr0, i64 4260 %ptr3 = getelementptr i32, ptr %ptr0, i64 6261 %ptr4 = getelementptr i32, ptr %ptr0, i64 8262 %ptr5 = getelementptr i32, ptr %ptr0, i64 10263 %ptr6 = getelementptr i32, ptr %ptr0, i64 12264 %ptr7 = getelementptr i32, ptr %ptr0, i64 14265 %ptr8 = getelementptr i32, ptr %ptr0, i64 16266 %ptr9 = getelementptr i32, ptr %ptr0, i64 18267 268 %val0 = load i32, ptr %ptr0269 %val1 = load i32, ptr %ptr1270 %val2 = load i32, ptr %ptr2271 %val3 = load i32, ptr %ptr3272 %val4 = load i32, ptr %ptr4273 %val5 = load i32, ptr %ptr5274 %val6 = load i32, ptr %ptr6275 %val7 = load i32, ptr %ptr7276 %val8 = load i32, ptr %ptr8277 %val9 = load i32, ptr %ptr9278 279 %ret = call i32 @foo()280 281 %t0 = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %ret, i32 %val0)282 %add0 = extractvalue {i32, i1} %t0, 0283 %obit0 = extractvalue {i32, i1} %t0, 1284 %t1 = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %add0, i32 %val1)285 %add1 = extractvalue {i32, i1} %t1, 0286 %obit1 = extractvalue {i32, i1} %t1, 1287 %res1 = or i1 %obit0, %obit1288 %t2 = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %add1, i32 %val2)289 %add2 = extractvalue {i32, i1} %t2, 0290 %obit2 = extractvalue {i32, i1} %t2, 1291 %res2 = or i1 %res1, %obit2292 %t3 = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %add2, i32 %val3)293 %add3 = extractvalue {i32, i1} %t3, 0294 %obit3 = extractvalue {i32, i1} %t3, 1295 %res3 = or i1 %res2, %obit3296 %t4 = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %add3, i32 %val4)297 %add4 = extractvalue {i32, i1} %t4, 0298 %obit4 = extractvalue {i32, i1} %t4, 1299 %res4 = or i1 %res3, %obit4300 %t5 = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %add4, i32 %val5)301 %add5 = extractvalue {i32, i1} %t5, 0302 %obit5 = extractvalue {i32, i1} %t5, 1303 %res5 = or i1 %res4, %obit5304 %t6 = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %add5, i32 %val6)305 %add6 = extractvalue {i32, i1} %t6, 0306 %obit6 = extractvalue {i32, i1} %t6, 1307 %res6 = or i1 %res5, %obit6308 %t7 = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %add6, i32 %val7)309 %add7 = extractvalue {i32, i1} %t7, 0310 %obit7 = extractvalue {i32, i1} %t7, 1311 %res7 = or i1 %res6, %obit7312 %t8 = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %add7, i32 %val8)313 %add8 = extractvalue {i32, i1} %t8, 0314 %obit8 = extractvalue {i32, i1} %t8, 1315 %res8 = or i1 %res7, %obit8316 %t9 = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %add8, i32 %val9)317 %add9 = extractvalue {i32, i1} %t9, 0318 %obit9 = extractvalue {i32, i1} %t9, 1319 %res9 = or i1 %res8, %obit9320 321 ret i1 %res9322}323 324declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone325 326