1; Test 32-bit addition in which the second operand is a sign-extended
2; i16 memory value.
3;
4; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
5
6; Check the low end of the AH range.
7define i32 @f1(i32 %lhs, i16 *%src) {
8; CHECK-LABEL: f1:
9; CHECK: ah %r2, 0(%r3)
10; CHECK: br %r14
11  %half = load i16, i16 *%src
12  %rhs = sext i16 %half to i32
13  %res = add i32 %lhs, %rhs
14  ret i32 %res
15}
16
17; Check the high end of the aligned AH range.
18define i32 @f2(i32 %lhs, i16 *%src) {
19; CHECK-LABEL: f2:
20; CHECK: ah %r2, 4094(%r3)
21; CHECK: br %r14
22  %ptr = getelementptr i16, i16 *%src, i64 2047
23  %half = load i16, i16 *%ptr
24  %rhs = sext i16 %half to i32
25  %res = add i32 %lhs, %rhs
26  ret i32 %res
27}
28
29; Check the next halfword up, which should use AHY instead of AH.
30define i32 @f3(i32 %lhs, i16 *%src) {
31; CHECK-LABEL: f3:
32; CHECK: ahy %r2, 4096(%r3)
33; CHECK: br %r14
34  %ptr = getelementptr i16, i16 *%src, i64 2048
35  %half = load i16, i16 *%ptr
36  %rhs = sext i16 %half to i32
37  %res = add i32 %lhs, %rhs
38  ret i32 %res
39}
40
41; Check the high end of the aligned AHY range.
42define i32 @f4(i32 %lhs, i16 *%src) {
43; CHECK-LABEL: f4:
44; CHECK: ahy %r2, 524286(%r3)
45; CHECK: br %r14
46  %ptr = getelementptr i16, i16 *%src, i64 262143
47  %half = load i16, i16 *%ptr
48  %rhs = sext i16 %half to i32
49  %res = add i32 %lhs, %rhs
50  ret i32 %res
51}
52
53; Check the next halfword up, which needs separate address logic.
54; Other sequences besides this one would be OK.
55define i32 @f5(i32 %lhs, i16 *%src) {
56; CHECK-LABEL: f5:
57; CHECK: agfi %r3, 524288
58; CHECK: ah %r2, 0(%r3)
59; CHECK: br %r14
60  %ptr = getelementptr i16, i16 *%src, i64 262144
61  %half = load i16, i16 *%ptr
62  %rhs = sext i16 %half to i32
63  %res = add i32 %lhs, %rhs
64  ret i32 %res
65}
66
67; Check the high end of the negative aligned AHY range.
68define i32 @f6(i32 %lhs, i16 *%src) {
69; CHECK-LABEL: f6:
70; CHECK: ahy %r2, -2(%r3)
71; CHECK: br %r14
72  %ptr = getelementptr i16, i16 *%src, i64 -1
73  %half = load i16, i16 *%ptr
74  %rhs = sext i16 %half to i32
75  %res = add i32 %lhs, %rhs
76  ret i32 %res
77}
78
79; Check the low end of the AHY range.
80define i32 @f7(i32 %lhs, i16 *%src) {
81; CHECK-LABEL: f7:
82; CHECK: ahy %r2, -524288(%r3)
83; CHECK: br %r14
84  %ptr = getelementptr i16, i16 *%src, i64 -262144
85  %half = load i16, i16 *%ptr
86  %rhs = sext i16 %half to i32
87  %res = add i32 %lhs, %rhs
88  ret i32 %res
89}
90
91; Check the next halfword down, which needs separate address logic.
92; Other sequences besides this one would be OK.
93define i32 @f8(i32 %lhs, i16 *%src) {
94; CHECK-LABEL: f8:
95; CHECK: agfi %r3, -524290
96; CHECK: ah %r2, 0(%r3)
97; CHECK: br %r14
98  %ptr = getelementptr i16, i16 *%src, i64 -262145
99  %half = load i16, i16 *%ptr
100  %rhs = sext i16 %half to i32
101  %res = add i32 %lhs, %rhs
102  ret i32 %res
103}
104
105; Check that AH allows an index.
106define i32 @f9(i32 %lhs, i64 %src, i64 %index) {
107; CHECK-LABEL: f9:
108; CHECK: ah %r2, 4094({{%r4,%r3|%r3,%r4}})
109; CHECK: br %r14
110  %add1 = add i64 %src, %index
111  %add2 = add i64 %add1, 4094
112  %ptr = inttoptr i64 %add2 to i16 *
113  %half = load i16, i16 *%ptr
114  %rhs = sext i16 %half to i32
115  %res = add i32 %lhs, %rhs
116  ret i32 %res
117}
118
119; Check that AHY allows an index.
120define i32 @f10(i32 %lhs, i64 %src, i64 %index) {
121; CHECK-LABEL: f10:
122; CHECK: ahy %r2, 4096({{%r4,%r3|%r3,%r4}})
123; CHECK: br %r14
124  %add1 = add i64 %src, %index
125  %add2 = add i64 %add1, 4096
126  %ptr = inttoptr i64 %add2 to i16 *
127  %half = load i16, i16 *%ptr
128  %rhs = sext i16 %half to i32
129  %res = add i32 %lhs, %rhs
130  ret i32 %res
131}
132