mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
[SystemZ] Recognize RISBG opportunities involving a truncate
Summary: Recognize RISBG opportunities where the end result is narrower than the original input - where a truncate separates the shift/and operations. The motivating case is some code in postgres which looks like: srlg %r2, %r0, 11 nilh %r2, 255 Reviewers: uweigand Author: RolandF Differential Revision: http://reviews.llvm.org/D21452 llvm-svn: 273433
This commit is contained in:
parent
3eed4ddaa1
commit
6cc38f3a79
@ -113,7 +113,8 @@ static uint64_t allOnes(unsigned int Count) {
|
|||||||
// (and (rotl Input, Rotate), Mask)
|
// (and (rotl Input, Rotate), Mask)
|
||||||
//
|
//
|
||||||
// otherwise. The output value has BitSize bits, although Input may be
|
// otherwise. The output value has BitSize bits, although Input may be
|
||||||
// narrower (in which case the upper bits are don't care).
|
// narrower (in which case the upper bits are don't care), or wider (in which
|
||||||
|
// case the result will be truncated as part of the operation).
|
||||||
struct RxSBGOperands {
|
struct RxSBGOperands {
|
||||||
RxSBGOperands(unsigned Op, SDValue N)
|
RxSBGOperands(unsigned Op, SDValue N)
|
||||||
: Opcode(Op), BitSize(N.getValueType().getSizeInBits()),
|
: Opcode(Op), BitSize(N.getValueType().getSizeInBits()),
|
||||||
@ -745,6 +746,16 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) const {
|
|||||||
SDValue N = RxSBG.Input;
|
SDValue N = RxSBG.Input;
|
||||||
unsigned Opcode = N.getOpcode();
|
unsigned Opcode = N.getOpcode();
|
||||||
switch (Opcode) {
|
switch (Opcode) {
|
||||||
|
case ISD::TRUNCATE: {
|
||||||
|
if (RxSBG.Opcode == SystemZ::RNSBG)
|
||||||
|
return false;
|
||||||
|
uint64_t BitSize = N.getValueType().getSizeInBits();
|
||||||
|
uint64_t Mask = allOnes(BitSize);
|
||||||
|
if (!refineRxSBGMask(RxSBG, Mask))
|
||||||
|
return false;
|
||||||
|
RxSBG.Input = N.getOperand(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
case ISD::AND: {
|
case ISD::AND: {
|
||||||
if (RxSBG.Opcode == SystemZ::RNSBG)
|
if (RxSBG.Opcode == SystemZ::RNSBG)
|
||||||
return false;
|
return false;
|
||||||
@ -916,7 +927,11 @@ bool SystemZDAGToDAGISel::tryRISBGZero(SDNode *N) {
|
|||||||
RxSBGOperands RISBG(SystemZ::RISBG, SDValue(N, 0));
|
RxSBGOperands RISBG(SystemZ::RISBG, SDValue(N, 0));
|
||||||
unsigned Count = 0;
|
unsigned Count = 0;
|
||||||
while (expandRxSBG(RISBG))
|
while (expandRxSBG(RISBG))
|
||||||
if (RISBG.Input.getOpcode() != ISD::ANY_EXTEND)
|
// The widening or narrowing is expected to be free.
|
||||||
|
// Counting widening or narrowing as a saved operation will result in
|
||||||
|
// preferring an R*SBG over a simple shift/logical instruction.
|
||||||
|
if (RISBG.Input.getOpcode() != ISD::ANY_EXTEND &&
|
||||||
|
RISBG.Input.getOpcode() != ISD::TRUNCATE)
|
||||||
Count += 1;
|
Count += 1;
|
||||||
if (Count == 0)
|
if (Count == 0)
|
||||||
return false;
|
return false;
|
||||||
@ -1004,7 +1019,11 @@ bool SystemZDAGToDAGISel::tryRxSBG(SDNode *N, unsigned Opcode) {
|
|||||||
unsigned Count[] = { 0, 0 };
|
unsigned Count[] = { 0, 0 };
|
||||||
for (unsigned I = 0; I < 2; ++I)
|
for (unsigned I = 0; I < 2; ++I)
|
||||||
while (expandRxSBG(RxSBG[I]))
|
while (expandRxSBG(RxSBG[I]))
|
||||||
if (RxSBG[I].Input.getOpcode() != ISD::ANY_EXTEND)
|
// The widening or narrowing is expected to be free.
|
||||||
|
// Counting widening or narrowing as a saved operation will result in
|
||||||
|
// preferring an R*SBG over a simple shift/logical instruction.
|
||||||
|
if (RxSBG[I].Input.getOpcode() != ISD::ANY_EXTEND &&
|
||||||
|
RxSBG[I].Input.getOpcode() != ISD::TRUNCATE)
|
||||||
Count[I] += 1;
|
Count[I] += 1;
|
||||||
|
|
||||||
// Do nothing if neither operand is suitable.
|
// Do nothing if neither operand is suitable.
|
||||||
|
@ -480,3 +480,24 @@ define i64 @f42(i1 %x) {
|
|||||||
%ext2 = zext i8 %ext to i64
|
%ext2 = zext i8 %ext to i64
|
||||||
ret i64 %ext2
|
ret i64 %ext2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Check that we get the case where a 64-bit shift is used by a 32-bit and.
|
||||||
|
define signext i32 @f43(i64 %x) {
|
||||||
|
; CHECK-LABEL: f43:
|
||||||
|
; CHECK: risbg [[REG:%r[0-5]]], %r2, 32, 189, 52
|
||||||
|
; CHECK: lgfr %r2, [[REG]]
|
||||||
|
%shr3 = lshr i64 %x, 12
|
||||||
|
%shr3.tr = trunc i64 %shr3 to i32
|
||||||
|
%conv = and i32 %shr3.tr, -4
|
||||||
|
ret i32 %conv
|
||||||
|
}
|
||||||
|
|
||||||
|
; Check that we don't get the case where the 32-bit and mask is not contiguous
|
||||||
|
define signext i32 @f44(i64 %x) {
|
||||||
|
; CHECK-LABEL: f44:
|
||||||
|
; CHECK: srlg [[REG:%r[0-5]]], %r2, 12
|
||||||
|
%shr4 = lshr i64 %x, 12
|
||||||
|
%conv = trunc i64 %shr4 to i32
|
||||||
|
%and = and i32 %conv, 10
|
||||||
|
ret i32 %and
|
||||||
|
}
|
||||||
|
@ -91,3 +91,28 @@ define i64 @f8(i64 %a, i64 %b) {
|
|||||||
%or = or i64 %anda, %shrb
|
%or = or i64 %anda, %shrb
|
||||||
ret i64 %or
|
ret i64 %or
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Check that we can get the case where a 64-bit shift feeds a 32-bit or of
|
||||||
|
; ands with complement masks.
|
||||||
|
define signext i32 @f9(i64 %x, i32 signext %y) {
|
||||||
|
; CHECK-LABEL: f9:
|
||||||
|
; CHECK: risbg [[REG:%r[0-5]]], %r2, 48, 63, 16
|
||||||
|
; CHECK: lgfr %r2, [[REG]]
|
||||||
|
%shr6 = lshr i64 %x, 48
|
||||||
|
%conv = trunc i64 %shr6 to i32
|
||||||
|
%and1 = and i32 %y, -65536
|
||||||
|
%or = or i32 %conv, %and1
|
||||||
|
ret i32 %or
|
||||||
|
}
|
||||||
|
|
||||||
|
; Check that we don't get the case where a 64-bit shift feeds a 32-bit or of
|
||||||
|
; ands with incompatible masks.
|
||||||
|
define signext i32 @f10(i64 %x, i32 signext %y) {
|
||||||
|
; CHECK-LABEL: f10:
|
||||||
|
; CHECK: nilf %r3, 4278190080
|
||||||
|
%shr6 = lshr i64 %x, 48
|
||||||
|
%conv = trunc i64 %shr6 to i32
|
||||||
|
%and1 = and i32 %y, -16777216
|
||||||
|
%or = or i32 %conv, %and1
|
||||||
|
ret i32 %or
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user