summaryrefslogtreecommitdiffstats
path: root/test/CodeGen/SystemZ/insert-06.ll
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGen/SystemZ/insert-06.ll')
-rw-r--r--test/CodeGen/SystemZ/insert-06.ll167
1 files changed, 167 insertions, 0 deletions
diff --git a/test/CodeGen/SystemZ/insert-06.ll b/test/CodeGen/SystemZ/insert-06.ll
new file mode 100644
index 0000000..4a13ef4
--- /dev/null
+++ b/test/CodeGen/SystemZ/insert-06.ll
@@ -0,0 +1,167 @@
+; Test insertions of i32s into the low half of an i64.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+; Insertion of an i32 can be done using LR.
+define i64 @f1(i64 %a, i32 %b) {
+; CHECK: f1:
+; CHECK-NOT: {{%r[23]}}
+; CHECK: lr %r2, %r3
+; CHECK: br %r14
+ %low = zext i32 %b to i64
+ %high = and i64 %a, -4294967296
+ %res = or i64 %high, %low
+ ret i64 %res
+}
+
+; ... and again with the operands reversed.
+define i64 @f2(i64 %a, i32 %b) {
+; CHECK: f2:
+; CHECK-NOT: {{%r[23]}}
+; CHECK: lr %r2, %r3
+; CHECK: br %r14
+ %low = zext i32 %b to i64
+ %high = and i64 %a, -4294967296
+ %res = or i64 %low, %high
+ ret i64 %res
+}
+
+; Like f1, but with "in register" zero extension.
+define i64 @f3(i64 %a, i64 %b) {
+; CHECK: f3:
+; CHECK-NOT: {{%r[23]}}
+; CHECK: lr %r2, %r3
+; CHECK: br %r14
+ %low = and i64 %b, 4294967295
+ %high = and i64 %a, -4294967296
+ %res = or i64 %high, %low
+ ret i64 %res
+}
+
+; ... and again with the operands reversed.
+define i64 @f4(i64 %a, i64 %b) {
+; CHECK: f4:
+; CHECK-NOT: {{%r[23]}}
+; CHECK: lr %r2, %r3
+; CHECK: br %r14
+ %low = and i64 %b, 4294967295
+ %high = and i64 %a, -4294967296
+ %res = or i64 %low, %high
+ ret i64 %res
+}
+
+; Unary operations can be done directly into the low half.
+define i64 @f5(i64 %a, i32 %b) {
+; CHECK: f5:
+; CHECK-NOT: {{%r[23]}}
+; CHECK: lcr %r2, %r3
+; CHECK: br %r14
+ %neg = sub i32 0, %b
+ %low = zext i32 %neg to i64
+ %high = and i64 %a, -4294967296
+ %res = or i64 %high, %low
+ ret i64 %res
+}
+
+; ...likewise three-operand binary operations like RLL.
+define i64 @f6(i64 %a, i32 %b) {
+; CHECK: f6:
+; CHECK-NOT: {{%r[23]}}
+; CHECK: rll %r2, %r3, 1
+; CHECK: br %r14
+ %parta = shl i32 %b, 1
+ %partb = lshr i32 %b, 31
+ %rot = or i32 %parta, %partb
+ %low = zext i32 %rot to i64
+ %high = and i64 %a, -4294967296
+ %res = or i64 %low, %high
+ ret i64 %res
+}
+
+; Loads can be done directly into the low half. The range of L is checked
+; in the move tests.
+define i64 @f7(i64 %a, i32 *%src) {
+; CHECK: f7:
+; CHECK-NOT: {{%r[23]}}
+; CHECK: l %r2, 0(%r3)
+; CHECK: br %r14
+ %b = load i32 *%src
+ %low = zext i32 %b to i64
+ %high = and i64 %a, -4294967296
+ %res = or i64 %high, %low
+ ret i64 %res
+}
+
+; ...likewise extending loads.
+define i64 @f8(i64 %a, i8 *%src) {
+; CHECK: f8:
+; CHECK-NOT: {{%r[23]}}
+; CHECK: lb %r2, 0(%r3)
+; CHECK: br %r14
+ %byte = load i8 *%src
+ %b = sext i8 %byte to i32
+ %low = zext i32 %b to i64
+ %high = and i64 %a, -4294967296
+ %res = or i64 %high, %low
+ ret i64 %res
+}
+
+; Check a case like f1 in which there is no AND. We simply know from context
+; that the upper half of one OR operand and the lower half of the other are
+; both clear.
+define i64 @f9(i64 %a, i32 %b) {
+; CHECK: f9:
+; CHECK: sllg %r2, %r2, 32
+; CHECK: lr %r2, %r3
+; CHECK: br %r14
+ %shift = shl i64 %a, 32
+ %low = zext i32 %b to i64
+ %or = or i64 %shift, %low
+ ret i64 %or
+}
+
+; ...and again with the operands reversed.
+define i64 @f10(i64 %a, i32 %b) {
+; CHECK: f10:
+; CHECK: sllg %r2, %r2, 32
+; CHECK: lr %r2, %r3
+; CHECK: br %r14
+ %shift = shl i64 %a, 32
+ %low = zext i32 %b to i64
+ %or = or i64 %low, %shift
+ ret i64 %or
+}
+
+; Like f9, but with "in register" zero extension.
+define i64 @f11(i64 %a, i64 %b) {
+; CHECK: f11:
+; CHECK: lr %r2, %r3
+; CHECK: br %r14
+ %shift = shl i64 %a, 32
+ %low = and i64 %b, 4294967295
+ %or = or i64 %shift, %low
+ ret i64 %or
+}
+
+; ...and again with the operands reversed.
+define i64 @f12(i64 %a, i64 %b) {
+; CHECK: f12:
+; CHECK: lr %r2, %r3
+; CHECK: br %r14
+ %shift = shl i64 %a, 32
+ %low = and i64 %b, 4294967295
+ %or = or i64 %low, %shift
+ ret i64 %or
+}
+
+; Like f9, but for larger shifts than 32.
+define i64 @f13(i64 %a, i32 %b) {
+; CHECK: f13:
+; CHECK: sllg %r2, %r2, 60
+; CHECK: lr %r2, %r3
+; CHECK: br %r14
+ %shift = shl i64 %a, 60
+ %low = zext i32 %b to i64
+ %or = or i64 %shift, %low
+ ret i64 %or
+}
OpenPOWER on IntegriCloud