270 lines · plain
1; Test 64-bit subtraction in which the second operand is variable.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s4 5declare i64 @foo()6 7; Check SGR.8define zeroext i1 @f1(i64 %dummy, i64 %a, i64 %b, ptr %res) {9; CHECK-LABEL: f1:10; CHECK: sgr %r3, %r411; CHECK-DAG: stg %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 {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)17 %val = extractvalue {i64, i1} %t, 018 %obit = extractvalue {i64, i1} %t, 119 store i64 %val, ptr %res20 ret i1 %obit21}22 23; Check using the overflow result for a branch.24define void @f2(i64 %dummy, i64 %a, i64 %b, ptr %res) {25; CHECK-LABEL: f2:26; CHECK: sgr %r3, %r427; CHECK: stg %r3, 0(%r5)28; CHECK: jgo foo@PLT29; CHECK: br %r1430 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)31 %val = extractvalue {i64, i1} %t, 032 %obit = extractvalue {i64, i1} %t, 133 store i64 %val, ptr %res34 br i1 %obit, label %call, label %exit35 36call:37 tail call i64 @foo()38 br label %exit39 40exit:41 ret void42}43 44; ... and the same with the inverted direction.45define void @f3(i64 %dummy, i64 %a, i64 %b, ptr %res) {46; CHECK-LABEL: f3:47; CHECK: sgr %r3, %r448; CHECK: stg %r3, 0(%r5)49; CHECK: jgno foo@PLT50; CHECK: br %r1451 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)52 %val = extractvalue {i64, i1} %t, 053 %obit = extractvalue {i64, i1} %t, 154 store i64 %val, ptr %res55 br i1 %obit, label %exit, label %call56 57call:58 tail call i64 @foo()59 br label %exit60 61exit:62 ret void63}64 65; Check SG with no displacement.66define zeroext i1 @f4(i64 %dummy, i64 %a, ptr %src, ptr %res) {67; CHECK-LABEL: f4:68; CHECK: sg %r3, 0(%r4)69; CHECK-DAG: stg %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 i64, ptr %src75 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)76 %val = extractvalue {i64, i1} %t, 077 %obit = extractvalue {i64, i1} %t, 178 store i64 %val, ptr %res79 ret i1 %obit80}81 82; Check the high end of the aligned SG range.83define zeroext i1 @f5(i64 %dummy, i64 %a, ptr %src, ptr %res) {84; CHECK-LABEL: f5:85; CHECK: sg %r3, 524280(%r4)86; CHECK-DAG: stg %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 i64, ptr %src, i64 6553592 %b = load i64, ptr %ptr93 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)94 %val = extractvalue {i64, i1} %t, 095 %obit = extractvalue {i64, i1} %t, 196 store i64 %val, ptr %res97 ret i1 %obit98}99 100; Check the next doubleword up, which needs separate address logic.101; Other sequences besides this one would be OK.102define zeroext i1 @f6(i64 %dummy, i64 %a, ptr %src, ptr %res) {103; CHECK-LABEL: f6:104; CHECK: agfi %r4, 524288105; CHECK: sg %r3, 0(%r4)106; CHECK-DAG: stg %r3, 0(%r5)107; CHECK-DAG: ipm [[REG:%r[0-5]]]108; CHECK-DAG: afi [[REG]], 1342177280109; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33110; CHECK: br %r14111 %ptr = getelementptr i64, ptr %src, i64 65536112 %b = load i64, ptr %ptr113 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)114 %val = extractvalue {i64, i1} %t, 0115 %obit = extractvalue {i64, i1} %t, 1116 store i64 %val, ptr %res117 ret i1 %obit118}119 120; Check the high end of the negative aligned SG range.121define zeroext i1 @f7(i64 %dummy, i64 %a, ptr %src, ptr %res) {122; CHECK-LABEL: f7:123; CHECK: sg %r3, -8(%r4)124; CHECK-DAG: stg %r3, 0(%r5)125; CHECK-DAG: ipm [[REG:%r[0-5]]]126; CHECK-DAG: afi [[REG]], 1342177280127; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33128; CHECK: br %r14129 %ptr = getelementptr i64, ptr %src, i64 -1130 %b = load i64, ptr %ptr131 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)132 %val = extractvalue {i64, i1} %t, 0133 %obit = extractvalue {i64, i1} %t, 1134 store i64 %val, ptr %res135 ret i1 %obit136}137 138; Check the low end of the SG range.139define zeroext i1 @f8(i64 %dummy, i64 %a, ptr %src, ptr %res) {140; CHECK-LABEL: f8:141; CHECK: sg %r3, -524288(%r4)142; CHECK-DAG: stg %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 i64, ptr %src, i64 -65536148 %b = load i64, ptr %ptr149 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)150 %val = extractvalue {i64, i1} %t, 0151 %obit = extractvalue {i64, i1} %t, 1152 store i64 %val, ptr %res153 ret i1 %obit154}155 156; Check the next word down, which needs separate address logic.157; Other sequences besides this one would be OK.158define zeroext i1 @f9(i64 %dummy, i64 %a, ptr %src, ptr %res) {159; CHECK-LABEL: f9:160; CHECK: agfi %r4, -524296161; CHECK: sg %r3, 0(%r4)162; CHECK-DAG: stg %r3, 0(%r5)163; CHECK-DAG: ipm [[REG:%r[0-5]]]164; CHECK-DAG: afi [[REG]], 1342177280165; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33166; CHECK: br %r14167 %ptr = getelementptr i64, ptr %src, i64 -65537168 %b = load i64, ptr %ptr169 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)170 %val = extractvalue {i64, i1} %t, 0171 %obit = extractvalue {i64, i1} %t, 1172 store i64 %val, ptr %res173 ret i1 %obit174}175 176; Check that SG allows an index.177define zeroext i1 @f10(i64 %src, i64 %index, i64 %a, ptr %res) {178; CHECK-LABEL: f10:179; CHECK: sg %r4, 524280({{%r3,%r2|%r2,%r3}})180; CHECK-DAG: stg %r4, 0(%r5)181; CHECK-DAG: ipm [[REG:%r[0-5]]]182; CHECK-DAG: afi [[REG]], 1342177280183; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33184; CHECK: br %r14185 %add1 = add i64 %src, %index186 %add2 = add i64 %add1, 524280187 %ptr = inttoptr i64 %add2 to ptr188 %b = load i64, ptr %ptr189 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)190 %val = extractvalue {i64, i1} %t, 0191 %obit = extractvalue {i64, i1} %t, 1192 store i64 %val, ptr %res193 ret i1 %obit194}195 196; Check that subtractions of spilled values can use SG rather than SGR.197define zeroext i1 @f11(ptr %ptr0) {198; CHECK-LABEL: f11:199; CHECK: brasl %r14, foo@PLT200; CHECK: sg %r2, 16{{[04]}}(%r15)201; CHECK: br %r14202 %ptr1 = getelementptr i64, ptr %ptr0, i64 2203 %ptr2 = getelementptr i64, ptr %ptr0, i64 4204 %ptr3 = getelementptr i64, ptr %ptr0, i64 6205 %ptr4 = getelementptr i64, ptr %ptr0, i64 8206 %ptr5 = getelementptr i64, ptr %ptr0, i64 10207 %ptr6 = getelementptr i64, ptr %ptr0, i64 12208 %ptr7 = getelementptr i64, ptr %ptr0, i64 14209 %ptr8 = getelementptr i64, ptr %ptr0, i64 16210 %ptr9 = getelementptr i64, ptr %ptr0, i64 18211 212 %val0 = load i64, ptr %ptr0213 %val1 = load i64, ptr %ptr1214 %val2 = load i64, ptr %ptr2215 %val3 = load i64, ptr %ptr3216 %val4 = load i64, ptr %ptr4217 %val5 = load i64, ptr %ptr5218 %val6 = load i64, ptr %ptr6219 %val7 = load i64, ptr %ptr7220 %val8 = load i64, ptr %ptr8221 %val9 = load i64, ptr %ptr9222 223 %ret = call i64 @foo()224 225 %t0 = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %ret, i64 %val0)226 %add0 = extractvalue {i64, i1} %t0, 0227 %obit0 = extractvalue {i64, i1} %t0, 1228 %t1 = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %add0, i64 %val1)229 %add1 = extractvalue {i64, i1} %t1, 0230 %obit1 = extractvalue {i64, i1} %t1, 1231 %res1 = or i1 %obit0, %obit1232 %t2 = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %add1, i64 %val2)233 %add2 = extractvalue {i64, i1} %t2, 0234 %obit2 = extractvalue {i64, i1} %t2, 1235 %res2 = or i1 %res1, %obit2236 %t3 = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %add2, i64 %val3)237 %add3 = extractvalue {i64, i1} %t3, 0238 %obit3 = extractvalue {i64, i1} %t3, 1239 %res3 = or i1 %res2, %obit3240 %t4 = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %add3, i64 %val4)241 %add4 = extractvalue {i64, i1} %t4, 0242 %obit4 = extractvalue {i64, i1} %t4, 1243 %res4 = or i1 %res3, %obit4244 %t5 = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %add4, i64 %val5)245 %add5 = extractvalue {i64, i1} %t5, 0246 %obit5 = extractvalue {i64, i1} %t5, 1247 %res5 = or i1 %res4, %obit5248 %t6 = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %add5, i64 %val6)249 %add6 = extractvalue {i64, i1} %t6, 0250 %obit6 = extractvalue {i64, i1} %t6, 1251 %res6 = or i1 %res5, %obit6252 %t7 = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %add6, i64 %val7)253 %add7 = extractvalue {i64, i1} %t7, 0254 %obit7 = extractvalue {i64, i1} %t7, 1255 %res7 = or i1 %res6, %obit7256 %t8 = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %add7, i64 %val8)257 %add8 = extractvalue {i64, i1} %t8, 0258 %obit8 = extractvalue {i64, i1} %t8, 1259 %res8 = or i1 %res7, %obit8260 %t9 = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %add8, i64 %val9)261 %add9 = extractvalue {i64, i1} %t9, 0262 %obit9 = extractvalue {i64, i1} %t9, 1263 %res9 = or i1 %res8, %obit9264 265 ret i1 %res9266}267 268declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone269 270