254 lines · plain
1; Test 32-bit subtraction in which the second operand is a sign-extended2; i16 memory value.3;4; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s5 6declare i32 @foo()7 8; Check the low end of the SH range.9define zeroext i1 @f1(i32 %dummy, i32 %a, ptr %src, ptr %res) {10; CHECK-LABEL: f1:11; CHECK: sh %r3, 0(%r4)12; CHECK-DAG: st %r3, 0(%r5)13; CHECK-DAG: ipm [[REG:%r[0-5]]]14; CHECK-DAG: afi [[REG]], 134217728015; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 3316; CHECK: br %r1417 %half = load i16, ptr %src18 %b = sext i16 %half to i3219 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)20 %val = extractvalue {i32, i1} %t, 021 %obit = extractvalue {i32, i1} %t, 122 store i32 %val, ptr %res23 ret i1 %obit24}25 26; Check the high end of the aligned SH range.27define zeroext i1 @f2(i32 %dummy, i32 %a, ptr %src, ptr %res) {28; CHECK-LABEL: f2:29; CHECK: sh %r3, 4094(%r4)30; CHECK-DAG: st %r3, 0(%r5)31; CHECK-DAG: ipm [[REG:%r[0-5]]]32; CHECK-DAG: afi [[REG]], 134217728033; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 3334; CHECK: br %r1435 %ptr = getelementptr i16, ptr %src, i64 204736 %half = load i16, ptr %ptr37 %b = sext i16 %half to i3238 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)39 %val = extractvalue {i32, i1} %t, 040 %obit = extractvalue {i32, i1} %t, 141 store i32 %val, ptr %res42 ret i1 %obit43}44 45; Check the next halfword up, which should use SHY instead of SH.46define zeroext i1 @f3(i32 %dummy, i32 %a, ptr %src, ptr %res) {47; CHECK-LABEL: f3:48; CHECK: shy %r3, 4096(%r4)49; CHECK-DAG: st %r3, 0(%r5)50; CHECK-DAG: ipm [[REG:%r[0-5]]]51; CHECK-DAG: afi [[REG]], 134217728052; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 3353; CHECK: br %r1454 %ptr = getelementptr i16, ptr %src, i64 204855 %half = load i16, ptr %ptr56 %b = sext i16 %half to i3257 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)58 %val = extractvalue {i32, i1} %t, 059 %obit = extractvalue {i32, i1} %t, 160 store i32 %val, ptr %res61 ret i1 %obit62}63 64; Check the high end of the aligned SHY range.65define zeroext i1 @f4(i32 %dummy, i32 %a, ptr %src, ptr %res) {66; CHECK-LABEL: f4:67; CHECK: shy %r3, 524286(%r4)68; CHECK-DAG: st %r3, 0(%r5)69; CHECK-DAG: ipm [[REG:%r[0-5]]]70; CHECK-DAG: afi [[REG]], 134217728071; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 3372; CHECK: br %r1473 %ptr = getelementptr i16, ptr %src, i64 26214374 %half = load i16, ptr %ptr75 %b = sext i16 %half to i3276 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)77 %val = extractvalue {i32, i1} %t, 078 %obit = extractvalue {i32, i1} %t, 179 store i32 %val, ptr %res80 ret i1 %obit81}82 83; Check the next halfword up, which needs separate address logic.84; Other sequences besides this one would be OK.85define zeroext i1 @f5(i32 %dummy, i32 %a, ptr %src, ptr %res) {86; CHECK-LABEL: f5:87; CHECK: agfi %r4, 52428888; CHECK: sh %r3, 0(%r4)89; CHECK-DAG: st %r3, 0(%r5)90; CHECK-DAG: ipm [[REG:%r[0-5]]]91; CHECK-DAG: afi [[REG]], 134217728092; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 3393; CHECK: br %r1494 %ptr = getelementptr i16, ptr %src, i64 26214495 %half = load i16, ptr %ptr96 %b = sext i16 %half to i3297 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)98 %val = extractvalue {i32, i1} %t, 099 %obit = extractvalue {i32, i1} %t, 1100 store i32 %val, ptr %res101 ret i1 %obit102}103 104; Check the high end of the negative aligned SHY range.105define zeroext i1 @f6(i32 %dummy, i32 %a, ptr %src, ptr %res) {106; CHECK-LABEL: f6:107; CHECK: shy %r3, -2(%r4)108; CHECK-DAG: st %r3, 0(%r5)109; CHECK-DAG: ipm [[REG:%r[0-5]]]110; CHECK-DAG: afi [[REG]], 1342177280111; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33112; CHECK: br %r14113 %ptr = getelementptr i16, ptr %src, i64 -1114 %half = load i16, ptr %ptr115 %b = sext i16 %half to i32116 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)117 %val = extractvalue {i32, i1} %t, 0118 %obit = extractvalue {i32, i1} %t, 1119 store i32 %val, ptr %res120 ret i1 %obit121}122 123; Check the low end of the SHY range.124define zeroext i1 @f7(i32 %dummy, i32 %a, ptr %src, ptr %res) {125; CHECK-LABEL: f7:126; CHECK: shy %r3, -524288(%r4)127; CHECK-DAG: st %r3, 0(%r5)128; CHECK-DAG: ipm [[REG:%r[0-5]]]129; CHECK-DAG: afi [[REG]], 1342177280130; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33131; CHECK: br %r14132 %ptr = getelementptr i16, ptr %src, i64 -262144133 %half = load i16, ptr %ptr134 %b = sext i16 %half to i32135 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)136 %val = extractvalue {i32, i1} %t, 0137 %obit = extractvalue {i32, i1} %t, 1138 store i32 %val, ptr %res139 ret i1 %obit140}141 142; Check the next halfword down, which needs separate address logic.143; Other sequences besides this one would be OK.144define zeroext i1 @f8(i32 %dummy, i32 %a, ptr %src, ptr %res) {145; CHECK-LABEL: f8:146; CHECK: agfi %r4, -524290147; CHECK: sh %r3, 0(%r4)148; CHECK-DAG: st %r3, 0(%r5)149; CHECK-DAG: ipm [[REG:%r[0-5]]]150; CHECK-DAG: afi [[REG]], 1342177280151; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33152; CHECK: br %r14153 %ptr = getelementptr i16, ptr %src, i64 -262145154 %half = load i16, ptr %ptr155 %b = sext i16 %half to i32156 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)157 %val = extractvalue {i32, i1} %t, 0158 %obit = extractvalue {i32, i1} %t, 1159 store i32 %val, ptr %res160 ret i1 %obit161}162 163; Check that SH allows an index.164define zeroext i1 @f9(i64 %src, i64 %index, i32 %a, ptr %res) {165; CHECK-LABEL: f9:166; CHECK: sh %r4, 4094({{%r3,%r2|%r2,%r3}})167; CHECK-DAG: st %r4, 0(%r5)168; CHECK-DAG: ipm [[REG:%r[0-5]]]169; CHECK-DAG: afi [[REG]], 1342177280170; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33171; CHECK: br %r14172 %add1 = add i64 %src, %index173 %add2 = add i64 %add1, 4094174 %ptr = inttoptr i64 %add2 to ptr175 %half = load i16, ptr %ptr176 %b = sext i16 %half to i32177 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)178 %val = extractvalue {i32, i1} %t, 0179 %obit = extractvalue {i32, i1} %t, 1180 store i32 %val, ptr %res181 ret i1 %obit182}183 184; Check that SHY allows an index.185define zeroext i1 @f10(i64 %src, i64 %index, i32 %a, ptr %res) {186; CHECK-LABEL: f10:187; CHECK: shy %r4, 4096({{%r3,%r2|%r2,%r3}})188; CHECK-DAG: st %r4, 0(%r5)189; CHECK-DAG: ipm [[REG:%r[0-5]]]190; CHECK-DAG: afi [[REG]], 1342177280191; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33192; CHECK: br %r14193 %add1 = add i64 %src, %index194 %add2 = add i64 %add1, 4096195 %ptr = inttoptr i64 %add2 to ptr196 %half = load i16, ptr %ptr197 %b = sext i16 %half to i32198 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)199 %val = extractvalue {i32, i1} %t, 0200 %obit = extractvalue {i32, i1} %t, 1201 store i32 %val, ptr %res202 ret i1 %obit203}204 205; Check using the overflow result for a branch.206define void @f11(i32 %dummy, i32 %a, ptr %src, ptr %res) {207; CHECK-LABEL: f11:208; CHECK: sh %r3, 0(%r4)209; CHECK: st %r3, 0(%r5)210; CHECK: jgo foo@PLT211; CHECK: br %r14212 %half = load i16, ptr %src213 %b = sext i16 %half to i32214 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)215 %val = extractvalue {i32, i1} %t, 0216 %obit = extractvalue {i32, i1} %t, 1217 store i32 %val, ptr %res218 br i1 %obit, label %call, label %exit219 220call:221 tail call i32 @foo()222 br label %exit223 224exit:225 ret void226}227 228; ... and the same with the inverted direction.229define void @f12(i32 %dummy, i32 %a, ptr %src, ptr %res) {230; CHECK-LABEL: f12:231; CHECK: sh %r3, 0(%r4)232; CHECK: st %r3, 0(%r5)233; CHECK: jgno foo@PLT234; CHECK: br %r14235 %half = load i16, ptr %src236 %b = sext i16 %half to i32237 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)238 %val = extractvalue {i32, i1} %t, 0239 %obit = extractvalue {i32, i1} %t, 1240 store i32 %val, ptr %res241 br i1 %obit, label %exit, label %call242 243call:244 tail call i32 @foo()245 br label %exit246 247exit:248 ret void249}250 251 252declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone253 254