19e3577ffSUlrich Weigand; Test insertions of i32s into the low half of an i64.
29e3577ffSUlrich Weigand;
39e3577ffSUlrich Weigand; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
49e3577ffSUlrich Weigand
59e3577ffSUlrich Weigand; Insertion of an i32 can be done using LR.
69e3577ffSUlrich Weiganddefine i64 @f1(i64 %a, i32 %b) {
7d24ab20eSStephen Lin; CHECK-LABEL: f1:
89e3577ffSUlrich Weigand; CHECK-NOT: {{%r[23]}}
99e3577ffSUlrich Weigand; CHECK: lr %r2, %r3
109e3577ffSUlrich Weigand; CHECK: br %r14
119e3577ffSUlrich Weigand  %low = zext i32 %b to i64
129e3577ffSUlrich Weigand  %high = and i64 %a, -4294967296
139e3577ffSUlrich Weigand  %res = or i64 %high, %low
149e3577ffSUlrich Weigand  ret i64 %res
159e3577ffSUlrich Weigand}
169e3577ffSUlrich Weigand
179e3577ffSUlrich Weigand; ... and again with the operands reversed.
189e3577ffSUlrich Weiganddefine i64 @f2(i64 %a, i32 %b) {
19d24ab20eSStephen Lin; CHECK-LABEL: f2:
209e3577ffSUlrich Weigand; CHECK-NOT: {{%r[23]}}
219e3577ffSUlrich Weigand; CHECK: lr %r2, %r3
229e3577ffSUlrich Weigand; CHECK: br %r14
239e3577ffSUlrich Weigand  %low = zext i32 %b to i64
249e3577ffSUlrich Weigand  %high = and i64 %a, -4294967296
259e3577ffSUlrich Weigand  %res = or i64 %low, %high
269e3577ffSUlrich Weigand  ret i64 %res
279e3577ffSUlrich Weigand}
289e3577ffSUlrich Weigand
299e3577ffSUlrich Weigand; Like f1, but with "in register" zero extension.
309e3577ffSUlrich Weiganddefine i64 @f3(i64 %a, i64 %b) {
31d24ab20eSStephen Lin; CHECK-LABEL: f3:
329e3577ffSUlrich Weigand; CHECK-NOT: {{%r[23]}}
339e3577ffSUlrich Weigand; CHECK: lr %r2, %r3
349e3577ffSUlrich Weigand; CHECK: br %r14
359e3577ffSUlrich Weigand  %low = and i64 %b, 4294967295
369e3577ffSUlrich Weigand  %high = and i64 %a, -4294967296
379e3577ffSUlrich Weigand  %res = or i64 %high, %low
389e3577ffSUlrich Weigand  ret i64 %res
399e3577ffSUlrich Weigand}
409e3577ffSUlrich Weigand
419e3577ffSUlrich Weigand; ... and again with the operands reversed.
429e3577ffSUlrich Weiganddefine i64 @f4(i64 %a, i64 %b) {
43d24ab20eSStephen Lin; CHECK-LABEL: f4:
449e3577ffSUlrich Weigand; CHECK-NOT: {{%r[23]}}
459e3577ffSUlrich Weigand; CHECK: lr %r2, %r3
469e3577ffSUlrich Weigand; CHECK: br %r14
479e3577ffSUlrich Weigand  %low = and i64 %b, 4294967295
489e3577ffSUlrich Weigand  %high = and i64 %a, -4294967296
499e3577ffSUlrich Weigand  %res = or i64 %low, %high
509e3577ffSUlrich Weigand  ret i64 %res
519e3577ffSUlrich Weigand}
529e3577ffSUlrich Weigand
539e3577ffSUlrich Weigand; Unary operations can be done directly into the low half.
549e3577ffSUlrich Weiganddefine i64 @f5(i64 %a, i32 %b) {
55d24ab20eSStephen Lin; CHECK-LABEL: f5:
569e3577ffSUlrich Weigand; CHECK-NOT: {{%r[23]}}
579e3577ffSUlrich Weigand; CHECK: lcr %r2, %r3
589e3577ffSUlrich Weigand; CHECK: br %r14
599e3577ffSUlrich Weigand  %neg = sub i32 0, %b
609e3577ffSUlrich Weigand  %low = zext i32 %neg to i64
619e3577ffSUlrich Weigand  %high = and i64 %a, -4294967296
629e3577ffSUlrich Weigand  %res = or i64 %high, %low
639e3577ffSUlrich Weigand  ret i64 %res
649e3577ffSUlrich Weigand}
659e3577ffSUlrich Weigand
669e3577ffSUlrich Weigand; ...likewise three-operand binary operations like RLL.
679e3577ffSUlrich Weiganddefine i64 @f6(i64 %a, i32 %b) {
68d24ab20eSStephen Lin; CHECK-LABEL: f6:
699e3577ffSUlrich Weigand; CHECK-NOT: {{%r[23]}}
709e3577ffSUlrich Weigand; CHECK: rll %r2, %r3, 1
719e3577ffSUlrich Weigand; CHECK: br %r14
729e3577ffSUlrich Weigand  %parta = shl i32 %b, 1
739e3577ffSUlrich Weigand  %partb = lshr i32 %b, 31
749e3577ffSUlrich Weigand  %rot = or i32 %parta, %partb
759e3577ffSUlrich Weigand  %low = zext i32 %rot to i64
769e3577ffSUlrich Weigand  %high = and i64 %a, -4294967296
779e3577ffSUlrich Weigand  %res = or i64 %low, %high
789e3577ffSUlrich Weigand  ret i64 %res
799e3577ffSUlrich Weigand}
809e3577ffSUlrich Weigand
819e3577ffSUlrich Weigand; Loads can be done directly into the low half.  The range of L is checked
829e3577ffSUlrich Weigand; in the move tests.
839e3577ffSUlrich Weiganddefine i64 @f7(i64 %a, i32 *%src) {
84d24ab20eSStephen Lin; CHECK-LABEL: f7:
859e3577ffSUlrich Weigand; CHECK-NOT: {{%r[23]}}
869e3577ffSUlrich Weigand; CHECK: l %r2, 0(%r3)
879e3577ffSUlrich Weigand; CHECK: br %r14
88*a79ac14fSDavid Blaikie  %b = load i32, i32 *%src
899e3577ffSUlrich Weigand  %low = zext i32 %b to i64
909e3577ffSUlrich Weigand  %high = and i64 %a, -4294967296
919e3577ffSUlrich Weigand  %res = or i64 %high, %low
929e3577ffSUlrich Weigand  ret i64 %res
939e3577ffSUlrich Weigand}
949e3577ffSUlrich Weigand
959e3577ffSUlrich Weigand; ...likewise extending loads.
969e3577ffSUlrich Weiganddefine i64 @f8(i64 %a, i8 *%src) {
97d24ab20eSStephen Lin; CHECK-LABEL: f8:
989e3577ffSUlrich Weigand; CHECK-NOT: {{%r[23]}}
999e3577ffSUlrich Weigand; CHECK: lb %r2, 0(%r3)
1009e3577ffSUlrich Weigand; CHECK: br %r14
101*a79ac14fSDavid Blaikie  %byte = load i8, i8 *%src
1029e3577ffSUlrich Weigand  %b = sext i8 %byte to i32
1039e3577ffSUlrich Weigand  %low = zext i32 %b to i64
1049e3577ffSUlrich Weigand  %high = and i64 %a, -4294967296
1059e3577ffSUlrich Weigand  %res = or i64 %high, %low
1069e3577ffSUlrich Weigand  ret i64 %res
1079e3577ffSUlrich Weigand}
1089e3577ffSUlrich Weigand
1099e3577ffSUlrich Weigand; Check a case like f1 in which there is no AND.  We simply know from context
1109e3577ffSUlrich Weigand; that the upper half of one OR operand and the lower half of the other are
1119e3577ffSUlrich Weigand; both clear.
1129e3577ffSUlrich Weiganddefine i64 @f9(i64 %a, i32 %b) {
113d24ab20eSStephen Lin; CHECK-LABEL: f9:
1149e3577ffSUlrich Weigand; CHECK: sllg %r2, %r2, 32
1159e3577ffSUlrich Weigand; CHECK: lr %r2, %r3
1169e3577ffSUlrich Weigand; CHECK: br %r14
1179e3577ffSUlrich Weigand  %shift = shl i64 %a, 32
1189e3577ffSUlrich Weigand  %low = zext i32 %b to i64
1199e3577ffSUlrich Weigand  %or = or i64 %shift, %low
1209e3577ffSUlrich Weigand  ret i64 %or
1219e3577ffSUlrich Weigand}
1229e3577ffSUlrich Weigand
1239e3577ffSUlrich Weigand; ...and again with the operands reversed.
1249e3577ffSUlrich Weiganddefine i64 @f10(i64 %a, i32 %b) {
125d24ab20eSStephen Lin; CHECK-LABEL: f10:
1269e3577ffSUlrich Weigand; CHECK: sllg %r2, %r2, 32
1279e3577ffSUlrich Weigand; CHECK: lr %r2, %r3
1289e3577ffSUlrich Weigand; CHECK: br %r14
1299e3577ffSUlrich Weigand  %shift = shl i64 %a, 32
1309e3577ffSUlrich Weigand  %low = zext i32 %b to i64
1319e3577ffSUlrich Weigand  %or = or i64 %low, %shift
1329e3577ffSUlrich Weigand  ret i64 %or
1339e3577ffSUlrich Weigand}
1349e3577ffSUlrich Weigand
1359e3577ffSUlrich Weigand; Like f9, but with "in register" zero extension.
1369e3577ffSUlrich Weiganddefine i64 @f11(i64 %a, i64 %b) {
137d24ab20eSStephen Lin; CHECK-LABEL: f11:
1389e3577ffSUlrich Weigand; CHECK: lr %r2, %r3
1399e3577ffSUlrich Weigand; CHECK: br %r14
1409e3577ffSUlrich Weigand  %shift = shl i64 %a, 32
1419e3577ffSUlrich Weigand  %low = and i64 %b, 4294967295
1429e3577ffSUlrich Weigand  %or = or i64 %shift, %low
1439e3577ffSUlrich Weigand  ret i64 %or
1449e3577ffSUlrich Weigand}
1459e3577ffSUlrich Weigand
1469e3577ffSUlrich Weigand; ...and again with the operands reversed.
1479e3577ffSUlrich Weiganddefine i64 @f12(i64 %a, i64 %b) {
148d24ab20eSStephen Lin; CHECK-LABEL: f12:
1499e3577ffSUlrich Weigand; CHECK: lr %r2, %r3
1509e3577ffSUlrich Weigand; CHECK: br %r14
1519e3577ffSUlrich Weigand  %shift = shl i64 %a, 32
1529e3577ffSUlrich Weigand  %low = and i64 %b, 4294967295
1539e3577ffSUlrich Weigand  %or = or i64 %low, %shift
1549e3577ffSUlrich Weigand  ret i64 %or
1559e3577ffSUlrich Weigand}
1569e3577ffSUlrich Weigand
1579e3577ffSUlrich Weigand; Like f9, but for larger shifts than 32.
1589e3577ffSUlrich Weiganddefine i64 @f13(i64 %a, i32 %b) {
159d24ab20eSStephen Lin; CHECK-LABEL: f13:
1609e3577ffSUlrich Weigand; CHECK: sllg %r2, %r2, 60
1619e3577ffSUlrich Weigand; CHECK: lr %r2, %r3
1629e3577ffSUlrich Weigand; CHECK: br %r14
1639e3577ffSUlrich Weigand  %shift = shl i64 %a, 60
1649e3577ffSUlrich Weigand  %low = zext i32 %b to i64
1659e3577ffSUlrich Weigand  %or = or i64 %shift, %low
1669e3577ffSUlrich Weigand  ret i64 %or
1679e3577ffSUlrich Weigand}
168ccc2a7c1SRichard Sandiford
169ccc2a7c1SRichard Sandiford; We previously wrongly removed the upper AND as dead.
170ccc2a7c1SRichard Sandiforddefine i64 @f14(i64 %a, i64 %b) {
171ccc2a7c1SRichard Sandiford; CHECK-LABEL: f14:
172ccc2a7c1SRichard Sandiford; CHECK: risbg {{%r[0-5]}}, %r2, 6, 134, 0
173ccc2a7c1SRichard Sandiford; CHECK: br %r14
174ccc2a7c1SRichard Sandiford  %and1 = and i64 %a, 144115188075855872
175ccc2a7c1SRichard Sandiford  %and2 = and i64 %b, 15
176ccc2a7c1SRichard Sandiford  %or = or i64 %and1, %and2
177ccc2a7c1SRichard Sandiford  %res = icmp eq i64 %or, 0
178ccc2a7c1SRichard Sandiford  %ext = sext i1 %res to i64
179ccc2a7c1SRichard Sandiford  ret i64 %ext
180ccc2a7c1SRichard Sandiford}
181d1093636SRichard Sandiford
182d1093636SRichard Sandiford; Check another representation of f8.
183d1093636SRichard Sandiforddefine i64 @f15(i64 %a, i8 *%src) {
184d1093636SRichard Sandiford; CHECK-LABEL: f15:
185d1093636SRichard Sandiford; CHECK-NOT: {{%r[23]}}
186d1093636SRichard Sandiford; CHECK: lb %r2, 0(%r3)
187d1093636SRichard Sandiford; CHECK: br %r14
188*a79ac14fSDavid Blaikie  %byte = load i8, i8 *%src
189d1093636SRichard Sandiford  %b = sext i8 %byte to i64
190d1093636SRichard Sandiford  %low = and i64 %b, 4294967295
191d1093636SRichard Sandiford  %high = and i64 %a, -4294967296
192d1093636SRichard Sandiford  %res = or i64 %high, %low
193d1093636SRichard Sandiford  ret i64 %res
194d1093636SRichard Sandiford}
195