187 lines · plain
1; Test additions between an i64 and a sign-extended i16 on z14.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s4 5declare i64 @foo()6 7; Check AGH with no displacement.8define zeroext i1 @f1(i64 %dummy, i64 %a, ptr %src, ptr %res) {9; CHECK-LABEL: f1:10; CHECK: agh %r3, 0(%r4)11; CHECK-DAG: stg %r3, 0(%r5)12; CHECK-DAG: lghi %r2, 013; CHECK-DAG: locghio %r2, 114; CHECK: br %r1415 %half = load i16, ptr %src16 %b = sext i16 %half to i6417 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)18 %val = extractvalue {i64, i1} %t, 019 %obit = extractvalue {i64, i1} %t, 120 store i64 %val, ptr %res21 ret i1 %obit22}23 24; Check the high end of the aligned AGH range.25define zeroext i1 @f4(i64 %dummy, i64 %a, ptr %src, ptr %res) {26; CHECK-LABEL: f4:27; CHECK: agh %r3, 524286(%r4)28; CHECK-DAG: stg %r3, 0(%r5)29; CHECK-DAG: lghi %r2, 030; CHECK-DAG: locghio %r2, 131; CHECK: br %r1432 %ptr = getelementptr i16, ptr %src, i64 26214333 %half = load i16, ptr %ptr34 %b = sext i16 %half to i6435 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)36 %val = extractvalue {i64, i1} %t, 037 %obit = extractvalue {i64, i1} %t, 138 store i64 %val, ptr %res39 ret i1 %obit40}41 42; Check the next halfword up, which needs separate address logic.43; Other sequences besides this one would be OK.44define zeroext i1 @f5(i64 %dummy, i64 %a, ptr %src, ptr %res) {45; CHECK-LABEL: f5:46; CHECK: agfi %r4, 52428847; CHECK: agh %r3, 0(%r4)48; CHECK-DAG: stg %r3, 0(%r5)49; CHECK-DAG: lghi %r2, 050; CHECK-DAG: locghio %r2, 151; CHECK: br %r1452 %ptr = getelementptr i16, ptr %src, i64 26214453 %half = load i16, ptr %ptr54 %b = sext i16 %half to i6455 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)56 %val = extractvalue {i64, i1} %t, 057 %obit = extractvalue {i64, i1} %t, 158 store i64 %val, ptr %res59 ret i1 %obit60}61 62; Check the high end of the negative aligned AGH range.63define zeroext i1 @f6(i64 %dummy, i64 %a, ptr %src, ptr %res) {64; CHECK-LABEL: f6:65; CHECK: agh %r3, -2(%r4)66; CHECK-DAG: stg %r3, 0(%r5)67; CHECK-DAG: lghi %r2, 068; CHECK-DAG: locghio %r2, 169; CHECK: br %r1470 %ptr = getelementptr i16, ptr %src, i64 -171 %half = load i16, ptr %ptr72 %b = sext i16 %half to i6473 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)74 %val = extractvalue {i64, i1} %t, 075 %obit = extractvalue {i64, i1} %t, 176 store i64 %val, ptr %res77 ret i1 %obit78}79 80; Check the low end of the AGH range.81define zeroext i1 @f7(i64 %dummy, i64 %a, ptr %src, ptr %res) {82; CHECK-LABEL: f7:83; CHECK: agh %r3, -524288(%r4)84; CHECK-DAG: stg %r3, 0(%r5)85; CHECK-DAG: lghi %r2, 086; CHECK-DAG: locghio %r2, 187; CHECK: br %r1488 %ptr = getelementptr i16, ptr %src, i64 -26214489 %half = load i16, ptr %ptr90 %b = sext i16 %half to i6491 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)92 %val = extractvalue {i64, i1} %t, 093 %obit = extractvalue {i64, i1} %t, 194 store i64 %val, ptr %res95 ret i1 %obit96}97 98; Check the next halfword down, which needs separate address logic.99; Other sequences besides this one would be OK.100define zeroext i1 @f8(i64 %dummy, i64 %a, ptr %src, ptr %res) {101; CHECK-LABEL: f8:102; CHECK: agfi %r4, -524290103; CHECK: agh %r3, 0(%r4)104; CHECK-DAG: stg %r3, 0(%r5)105; CHECK-DAG: lghi %r2, 0106; CHECK-DAG: locghio %r2, 1107; CHECK: br %r14108 %ptr = getelementptr i16, ptr %src, i64 -262145109 %half = load i16, ptr %ptr110 %b = sext i16 %half to i64111 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)112 %val = extractvalue {i64, i1} %t, 0113 %obit = extractvalue {i64, i1} %t, 1114 store i64 %val, ptr %res115 ret i1 %obit116}117 118; Check that AGH allows an index.119define zeroext i1 @f9(i64 %src, i64 %index, i64 %a, ptr %res) {120; CHECK-LABEL: f9:121; CHECK: agh %r4, 524284({{%r3,%r2|%r2,%r3}})122; CHECK-DAG: stg %r4, 0(%r5)123; CHECK-DAG: lghi %r2, 0124; CHECK-DAG: locghio %r2, 1125; CHECK: br %r14126 %add1 = add i64 %src, %index127 %add2 = add i64 %add1, 524284128 %ptr = inttoptr i64 %add2 to ptr129 %half = load i16, ptr %ptr130 %b = sext i16 %half to i64131 %t = call {i64, i1} @llvm.sadd.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 using the overflow result for a branch.139define void @f11(i64 %dummy, i64 %a, ptr %src, ptr %res) {140; CHECK-LABEL: f11:141; CHECK: agh %r3, 0(%r4)142; CHECK: stg %r3, 0(%r5)143; CHECK: jgo foo@PLT144; CHECK: br %r14145 %half = load i16, ptr %src146 %b = sext i16 %half to i64147 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)148 %val = extractvalue {i64, i1} %t, 0149 %obit = extractvalue {i64, i1} %t, 1150 store i64 %val, ptr %res151 br i1 %obit, label %call, label %exit152 153call:154 tail call i64 @foo()155 br label %exit156 157exit:158 ret void159}160 161; ... and the same with the inverted direction.162define void @f12(i64 %dummy, i64 %a, ptr %src, ptr %res) {163; CHECK-LABEL: f12:164; CHECK: agh %r3, 0(%r4)165; CHECK: stg %r3, 0(%r5)166; CHECK: jgno foo@PLT167; CHECK: br %r14168 %half = load i16, ptr %src169 %b = sext i16 %half to i64170 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)171 %val = extractvalue {i64, i1} %t, 0172 %obit = extractvalue {i64, i1} %t, 1173 store i64 %val, ptr %res174 br i1 %obit, label %exit, label %call175 176call:177 tail call i64 @foo()178 br label %exit179 180exit:181 ret void182}183 184 185declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone186 187