1; Test insertions of i32s into the low half of an i64.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5; Insertion of an i32 can be done using LR.
6define i64 @f1(i64 %a, i32 %b) {
7; CHECK-LABEL: f1:
8; CHECK-NOT: {{%r[23]}}
9; CHECK: lr %r2, %r3
10; CHECK: br %r14
11  %low = zext i32 %b to i64
12  %high = and i64 %a, -4294967296
13  %res = or i64 %high, %low
14  ret i64 %res
15}
16
17; ... and again with the operands reversed.
18define i64 @f2(i64 %a, i32 %b) {
19; CHECK-LABEL: f2:
20; CHECK-NOT: {{%r[23]}}
21; CHECK: lr %r2, %r3
22; CHECK: br %r14
23  %low = zext i32 %b to i64
24  %high = and i64 %a, -4294967296
25  %res = or i64 %low, %high
26  ret i64 %res
27}
28
29; Like f1, but with "in register" zero extension.
30define i64 @f3(i64 %a, i64 %b) {
31; CHECK-LABEL: f3:
32; CHECK-NOT: {{%r[23]}}
33; CHECK: lr %r2, %r3
34; CHECK: br %r14
35  %low = and i64 %b, 4294967295
36  %high = and i64 %a, -4294967296
37  %res = or i64 %high, %low
38  ret i64 %res
39}
40
41; ... and again with the operands reversed.
42define i64 @f4(i64 %a, i64 %b) {
43; CHECK-LABEL: f4:
44; CHECK-NOT: {{%r[23]}}
45; CHECK: lr %r2, %r3
46; CHECK: br %r14
47  %low = and i64 %b, 4294967295
48  %high = and i64 %a, -4294967296
49  %res = or i64 %low, %high
50  ret i64 %res
51}
52
53; Unary operations can be done directly into the low half.
54define i64 @f5(i64 %a, i32 %b) {
55; CHECK-LABEL: f5:
56; CHECK-NOT: {{%r[23]}}
57; CHECK: lcr %r2, %r3
58; CHECK: br %r14
59  %neg = sub i32 0, %b
60  %low = zext i32 %neg to i64
61  %high = and i64 %a, -4294967296
62  %res = or i64 %high, %low
63  ret i64 %res
64}
65
66; ...likewise three-operand binary operations like RLL.
67define i64 @f6(i64 %a, i32 %b) {
68; CHECK-LABEL: f6:
69; CHECK-NOT: {{%r[23]}}
70; CHECK: rll %r2, %r3, 1
71; CHECK: br %r14
72  %parta = shl i32 %b, 1
73  %partb = lshr i32 %b, 31
74  %rot = or i32 %parta, %partb
75  %low = zext i32 %rot to i64
76  %high = and i64 %a, -4294967296
77  %res = or i64 %low, %high
78  ret i64 %res
79}
80
81; Loads can be done directly into the low half.  The range of L is checked
82; in the move tests.
83define i64 @f7(i64 %a, i32 *%src) {
84; CHECK-LABEL: f7:
85; CHECK-NOT: {{%r[23]}}
86; CHECK: l %r2, 0(%r3)
87; CHECK: br %r14
88  %b = load i32 *%src
89  %low = zext i32 %b to i64
90  %high = and i64 %a, -4294967296
91  %res = or i64 %high, %low
92  ret i64 %res
93}
94
95; ...likewise extending loads.
96define i64 @f8(i64 %a, i8 *%src) {
97; CHECK-LABEL: f8:
98; CHECK-NOT: {{%r[23]}}
99; CHECK: lb %r2, 0(%r3)
100; CHECK: br %r14
101  %byte = load i8 *%src
102  %b = sext i8 %byte to i32
103  %low = zext i32 %b to i64
104  %high = and i64 %a, -4294967296
105  %res = or i64 %high, %low
106  ret i64 %res
107}
108
109; Check a case like f1 in which there is no AND.  We simply know from context
110; that the upper half of one OR operand and the lower half of the other are
111; both clear.
112define i64 @f9(i64 %a, i32 %b) {
113; CHECK-LABEL: f9:
114; CHECK: sllg %r2, %r2, 32
115; CHECK: lr %r2, %r3
116; CHECK: br %r14
117  %shift = shl i64 %a, 32
118  %low = zext i32 %b to i64
119  %or = or i64 %shift, %low
120  ret i64 %or
121}
122
123; ...and again with the operands reversed.
124define i64 @f10(i64 %a, i32 %b) {
125; CHECK-LABEL: f10:
126; CHECK: sllg %r2, %r2, 32
127; CHECK: lr %r2, %r3
128; CHECK: br %r14
129  %shift = shl i64 %a, 32
130  %low = zext i32 %b to i64
131  %or = or i64 %low, %shift
132  ret i64 %or
133}
134
135; Like f9, but with "in register" zero extension.
136define i64 @f11(i64 %a, i64 %b) {
137; CHECK-LABEL: f11:
138; CHECK: lr %r2, %r3
139; CHECK: br %r14
140  %shift = shl i64 %a, 32
141  %low = and i64 %b, 4294967295
142  %or = or i64 %shift, %low
143  ret i64 %or
144}
145
146; ...and again with the operands reversed.
147define i64 @f12(i64 %a, i64 %b) {
148; CHECK-LABEL: f12:
149; CHECK: lr %r2, %r3
150; CHECK: br %r14
151  %shift = shl i64 %a, 32
152  %low = and i64 %b, 4294967295
153  %or = or i64 %low, %shift
154  ret i64 %or
155}
156
157; Like f9, but for larger shifts than 32.
158define i64 @f13(i64 %a, i32 %b) {
159; CHECK-LABEL: f13:
160; CHECK: sllg %r2, %r2, 60
161; CHECK: lr %r2, %r3
162; CHECK: br %r14
163  %shift = shl i64 %a, 60
164  %low = zext i32 %b to i64
165  %or = or i64 %shift, %low
166  ret i64 %or
167}
168
169; We previously wrongly removed the upper AND as dead.
170define i64 @f14(i64 %a, i64 %b) {
171; CHECK-LABEL: f14:
172; CHECK: risbg {{%r[0-5]}}, %r2, 6, 134, 0
173; CHECK: br %r14
174  %and1 = and i64 %a, 144115188075855872
175  %and2 = and i64 %b, 15
176  %or = or i64 %and1, %and2
177  %res = icmp eq i64 %or, 0
178  %ext = sext i1 %res to i64
179  ret i64 %ext
180}
181
182; Check another representation of f8.
183define i64 @f15(i64 %a, i8 *%src) {
184; CHECK-LABEL: f15:
185; CHECK-NOT: {{%r[23]}}
186; CHECK: lb %r2, 0(%r3)
187; CHECK: br %r14
188  %byte = load i8 *%src
189  %b = sext i8 %byte to i64
190  %low = and i64 %b, 4294967295
191  %high = and i64 %a, -4294967296
192  %res = or i64 %high, %low
193  ret i64 %res
194}
195