269 lines
6.3 KiB
LLVM
269 lines
6.3 KiB
LLVM
; Test sequences that can use RNSBG.
|
|
;
|
|
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
|
|
|
; Test a simple mask, which is a wrap-around case.
|
|
define i32 @f1(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: f1:
|
|
; CHECK: rnsbg %r2, %r3, 59, 56, 0
|
|
; CHECK: br %r14
|
|
%orb = or i32 %b, 96
|
|
%and = and i32 %a, %orb
|
|
ret i32 %and
|
|
}
|
|
|
|
; ...and again with i64.
|
|
define i64 @f2(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: f2:
|
|
; CHECK: rnsbg %r2, %r3, 59, 56, 0
|
|
; CHECK: br %r14
|
|
%orb = or i64 %b, 96
|
|
%and = and i64 %a, %orb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Test a case where no wraparound is needed.
|
|
define i32 @f3(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: f3:
|
|
; CHECK: rnsbg %r2, %r3, 58, 61, 0
|
|
; CHECK: br %r14
|
|
%orb = or i32 %b, -61
|
|
%and = and i32 %a, %orb
|
|
ret i32 %and
|
|
}
|
|
|
|
; ...and again with i64.
|
|
define i64 @f4(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: f4:
|
|
; CHECK: rnsbg %r2, %r3, 58, 61, 0
|
|
; CHECK: br %r14
|
|
%orb = or i64 %b, -61
|
|
%and = and i64 %a, %orb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Test a case with just a left shift. This can't use RNSBG.
|
|
define i32 @f6(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: f6:
|
|
; CHECK: sll {{%r[0-5]}}
|
|
; CHECK: nr {{%r[0-5]}}
|
|
; CHECK: br %r14
|
|
%shrb = shl i32 %b, 20
|
|
%and = and i32 %a, %shrb
|
|
ret i32 %and
|
|
}
|
|
|
|
; ...and again with i64.
|
|
define i64 @f7(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: f7:
|
|
; CHECK: sllg {{%r[0-5]}}
|
|
; CHECK: ngr {{%r[0-5]}}
|
|
; CHECK: br %r14
|
|
%shrb = shl i64 %b, 20
|
|
%and = and i64 %a, %shrb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Test a case with just a rotate. This can't use RNSBG.
|
|
define i32 @f8(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: f8:
|
|
; CHECK: rll {{%r[0-5]}}
|
|
; CHECK: nr {{%r[0-5]}}
|
|
; CHECK: br %r14
|
|
%shlb = shl i32 %b, 22
|
|
%shrb = lshr i32 %b, 10
|
|
%rotlb = or i32 %shlb, %shrb
|
|
%and = and i32 %a, %rotlb
|
|
ret i32 %and
|
|
}
|
|
|
|
; ...and again with i64, which can.
|
|
define i64 @f9(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: f9:
|
|
; CHECK: rnsbg %r2, %r3, 0, 63, 44
|
|
; CHECK: br %r14
|
|
%shlb = shl i64 %b, 44
|
|
%shrb = lshr i64 %b, 20
|
|
%rotlb = or i64 %shlb, %shrb
|
|
%and = and i64 %a, %rotlb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Test a case with a left shift and OR, where the OR covers all shifted bits.
|
|
; We can do the whole thing using RNSBG.
|
|
define i32 @f10(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: f10:
|
|
; CHECK: rnsbg %r2, %r3, 32, 56, 7
|
|
; CHECK: br %r14
|
|
%shlb = shl i32 %b, 7
|
|
%orb = or i32 %shlb, 127
|
|
%and = and i32 %a, %orb
|
|
ret i32 %and
|
|
}
|
|
|
|
; ...and again with i64.
|
|
define i64 @f11(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: f11:
|
|
; CHECK: rnsbg %r2, %r3, 0, 56, 7
|
|
; CHECK: br %r14
|
|
%shlb = shl i64 %b, 7
|
|
%orb = or i64 %shlb, 127
|
|
%and = and i64 %a, %orb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Test a case with a left shift and OR, where the OR doesn't cover all
|
|
; shifted bits. We can't use RNSBG for the shift, but we can for the OR
|
|
; and AND.
|
|
define i32 @f12(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: f12:
|
|
; CHECK: sll %r3, 7
|
|
; CHECK: rnsbg %r2, %r3, 32, 57, 0
|
|
; CHECK: br %r14
|
|
%shlb = shl i32 %b, 7
|
|
%orb = or i32 %shlb, 63
|
|
%and = and i32 %a, %orb
|
|
ret i32 %and
|
|
}
|
|
|
|
; ...and again with i64.
|
|
define i64 @f13(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: f13:
|
|
; CHECK: sllg [[REG:%r[01345]]], %r3, 7
|
|
; CHECK: rnsbg %r2, [[REG]], 0, 57, 0
|
|
; CHECK: br %r14
|
|
%shlb = shl i64 %b, 7
|
|
%orb = or i64 %shlb, 63
|
|
%and = and i64 %a, %orb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Test a case with a right shift and OR, where the OR covers all the shifted
|
|
; bits. The whole thing can be done using RNSBG.
|
|
define i32 @f14(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: f14:
|
|
; CHECK: rnsbg %r2, %r3, 60, 63, 37
|
|
; CHECK: br %r14
|
|
%shrb = lshr i32 %b, 27
|
|
%orb = or i32 %shrb, -16
|
|
%and = and i32 %a, %orb
|
|
ret i32 %and
|
|
}
|
|
|
|
; ...and again with i64.
|
|
define i64 @f15(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: f15:
|
|
; CHECK: rnsbg %r2, %r3, 60, 63, 5
|
|
; CHECK: br %r14
|
|
%shrb = lshr i64 %b, 59
|
|
%orb = or i64 %shrb, -16
|
|
%and = and i64 %a, %orb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Test a case with a right shift and OR, where the OR doesn't cover all the
|
|
; shifted bits. The shift needs to be done separately, but the OR and AND
|
|
; can use RNSBG.
|
|
define i32 @f16(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: f16:
|
|
; CHECK: srl %r3, 29
|
|
; CHECK: rnsbg %r2, %r3, 60, 63, 0
|
|
; CHECK: br %r14
|
|
%shrb = lshr i32 %b, 29
|
|
%orb = or i32 %shrb, -16
|
|
%and = and i32 %a, %orb
|
|
ret i32 %and
|
|
}
|
|
|
|
; ...and again with i64.
|
|
define i64 @f17(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: f17:
|
|
; CHECK: srlg [[REG:%r[01345]]], %r3, 61
|
|
; CHECK: rnsbg %r2, [[REG]], 60, 63, 0
|
|
; CHECK: br %r14
|
|
%shrb = lshr i64 %b, 61
|
|
%orb = or i64 %shrb, -16
|
|
%and = and i64 %a, %orb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Test a combination involving an ASHR in which the sign bits matter.
|
|
; We can't use RNSBG for the ASHR in that case, but we can for the rest.
|
|
define i32 @f18(i32 %a, i32 %b, i32 *%dest) {
|
|
; CHECK-LABEL: f18:
|
|
; CHECK: sra %r3, 4
|
|
; CHECK: rnsbg %r2, %r3, 32, 62, 1
|
|
; CHECK: br %r14
|
|
%ashrb = ashr i32 %b, 4
|
|
store i32 %ashrb, i32 *%dest
|
|
%shlb = shl i32 %ashrb, 1
|
|
%orb = or i32 %shlb, 1
|
|
%and = and i32 %a, %orb
|
|
ret i32 %and
|
|
}
|
|
|
|
; ...and again with i64.
|
|
define i64 @f19(i64 %a, i64 %b, i64 *%dest) {
|
|
; CHECK-LABEL: f19:
|
|
; CHECK: srag [[REG:%r[0145]]], %r3, 34
|
|
; CHECK: rnsbg %r2, [[REG]], 0, 62, 1
|
|
; CHECK: br %r14
|
|
%ashrb = ashr i64 %b, 34
|
|
store i64 %ashrb, i64 *%dest
|
|
%shlb = shl i64 %ashrb, 1
|
|
%orb = or i64 %shlb, 1
|
|
%and = and i64 %a, %orb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Test a combination involving an ASHR in which the sign bits don't matter.
|
|
define i32 @f20(i32 %a, i32 %b, i32 *%dest) {
|
|
; CHECK-LABEL: f20:
|
|
; CHECK: rnsbg %r2, %r3, 48, 62, 48
|
|
; CHECK: br %r14
|
|
%ashrb = ashr i32 %b, 17
|
|
store i32 %ashrb, i32 *%dest
|
|
%shlb = shl i32 %ashrb, 1
|
|
%orb = or i32 %shlb, -65535
|
|
%and = and i32 %a, %orb
|
|
ret i32 %and
|
|
}
|
|
|
|
; ...and again with i64.
|
|
define i64 @f21(i64 %a, i64 %b, i64 *%dest) {
|
|
; CHECK-LABEL: f21:
|
|
; CHECK: rnsbg %r2, %r3, 48, 62, 16
|
|
; CHECK: br %r14
|
|
%ashrb = ashr i64 %b, 49
|
|
store i64 %ashrb, i64 *%dest
|
|
%shlb = shl i64 %ashrb, 1
|
|
%orb = or i64 %shlb, -65535
|
|
%and = and i64 %a, %orb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Test a case with a shift, OR, and rotate where the OR covers all shifted bits.
|
|
define i64 @f22(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: f22:
|
|
; CHECK: rnsbg %r2, %r3, 60, 54, 9
|
|
; CHECK: br %r14
|
|
%shlb = shl i64 %b, 5
|
|
%orb = or i64 %shlb, 31
|
|
%shlorb = shl i64 %orb, 4
|
|
%shrorb = lshr i64 %orb, 60
|
|
%rotlorb = or i64 %shlorb, %shrorb
|
|
%and = and i64 %a, %rotlorb
|
|
ret i64 %and
|
|
}
|
|
|
|
; Check the handling of zext and AND, which isn't suitable for RNSBG.
|
|
define i64 @f23(i64 %a, i32 %b) {
|
|
; CHECK-LABEL: f23:
|
|
; CHECK-NOT: rnsbg
|
|
; CHECK: br %r14
|
|
%add = add i32 %b, 1
|
|
%ext = zext i32 %add to i64
|
|
%and = and i64 %a, %ext
|
|
ret i64 %and
|
|
}
|