; 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: f7: ; CHECK-NOT: {{%r[23]}} ; CHECK: l %r2, 0(%r3) ; CHECK: br %r14 %b = load i32, 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-LABEL: f8: ; CHECK-NOT: {{%r[23]}} ; CHECK: lb %r2, 0(%r3) ; CHECK: br %r14 %byte = load i8, 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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 } ; We previously wrongly removed the upper AND as dead. define i64 @f14(i64 %a, i64 %b) { ; CHECK-LABEL: f14: ; CHECK: risbg {{%r[0-5]}}, %r2, 6, 134, 0 ; CHECK: br %r14 %and1 = and i64 %a, 144115188075855872 %and2 = and i64 %b, 15 %or = or i64 %and1, %and2 %res = icmp eq i64 %or, 0 %ext = sext i1 %res to i64 ret i64 %ext } ; Check another representation of f8. define i64 @f15(i64 %a, i8 *%src) { ; CHECK-LABEL: f15: ; CHECK-NOT: {{%r[23]}} ; CHECK: lb %r2, 0(%r3) ; CHECK: br %r14 %byte = load i8, i8 *%src %b = sext i8 %byte to i64 %low = and i64 %b, 4294967295 %high = and i64 %a, -4294967296 %res = or i64 %high, %low ret i64 %res }