mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-31 09:32:11 +00:00
[SystemZ] Use zeroing form of RISBG for shift-and-AND sequences
Extend r186072 to handle shifts and ANDs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186073 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b3cabb44c3
commit
261e2877eb
@ -613,20 +613,81 @@ SDNode *SystemZDAGToDAGISel::tryRISBGForAND(SDNode *N) {
|
||||
unsigned Start, End;
|
||||
ConstantSDNode *MaskNode =
|
||||
dyn_cast<ConstantSDNode>(N->getOperand(1).getNode());
|
||||
if (!MaskNode
|
||||
|| !isRISBGMask(MaskNode->getZExtValue(), BitSize, Start, End))
|
||||
if (!MaskNode)
|
||||
return 0;
|
||||
|
||||
SDValue Input = N->getOperand(0);
|
||||
uint64_t Mask = MaskNode->getZExtValue();
|
||||
if (!isRISBGMask(Mask, BitSize, Start, End)) {
|
||||
APInt KnownZero, KnownOne;
|
||||
CurDAG->ComputeMaskedBits(Input, KnownZero, KnownOne);
|
||||
Mask |= KnownZero.getZExtValue();
|
||||
if (!isRISBGMask(Mask, BitSize, Start, End))
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned Rotate = 0;
|
||||
if (Input->getOpcode() == ISD::ROTL && BitSize == 64) {
|
||||
// Any 64-bit rotate left can be merged into the RISBG.
|
||||
if (ConstantSDNode *CountNode =
|
||||
dyn_cast<ConstantSDNode>(Input.getOperand(1).getNode())) {
|
||||
Rotate = CountNode->getZExtValue() & (BitSize - 1);
|
||||
Input = Input->getOperand(0);
|
||||
}
|
||||
} else if (Input->getOpcode() == ISD::SHL) {
|
||||
// Try to convert (and (shl X, count), mask) into
|
||||
// (and (rotl X, count), mask&(~0<<count)), where the new mask
|
||||
// removes bits from the original mask that are zeroed by the shl
|
||||
// but that are not necessarily zero in X.
|
||||
if (ConstantSDNode *CountNode =
|
||||
dyn_cast<ConstantSDNode>(Input.getOperand(1).getNode())) {
|
||||
uint64_t Count = CountNode->getZExtValue();
|
||||
if (Count > 0 &&
|
||||
Count < BitSize &&
|
||||
isRISBGMask(Mask & (allOnes(BitSize - Count) << Count),
|
||||
BitSize, Start, End)) {
|
||||
Rotate = Count;
|
||||
Input = Input->getOperand(0);
|
||||
}
|
||||
}
|
||||
} else if (Input->getOpcode() == ISD::SRL) {
|
||||
// Try to convert (and (srl X, count), mask) into
|
||||
// (and (rotl X, size-count), mask&(~0>>count)), which is similar
|
||||
// to SLL above.
|
||||
if (ConstantSDNode *CountNode =
|
||||
dyn_cast<ConstantSDNode>(Input.getOperand(1).getNode())) {
|
||||
uint64_t Count = CountNode->getZExtValue();
|
||||
if (Count > 0 &&
|
||||
Count < BitSize &&
|
||||
isRISBGMask(Mask & allOnes(BitSize - Count), BitSize, Start, End)) {
|
||||
Rotate = 64 - Count;
|
||||
Input = Input->getOperand(0);
|
||||
}
|
||||
}
|
||||
} else if (Start <= End && Input->getOpcode() == ISD::SRA) {
|
||||
// Try to convert (and (sra X, count), mask) into
|
||||
// (and (rotl X, size-count), mask). The mask must not include
|
||||
// any sign bits.
|
||||
if (ConstantSDNode *CountNode =
|
||||
dyn_cast<ConstantSDNode>(Input.getOperand(1).getNode())) {
|
||||
uint64_t Count = CountNode->getZExtValue();
|
||||
if (Count > 0 && Count < BitSize && Start >= 64 - (BitSize - Count)) {
|
||||
Rotate = 64 - Count;
|
||||
Input = Input->getOperand(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prefer register extensions like LLC over RSIBG.
|
||||
if ((Start == 32 || Start == 48 || Start == 56) && End == 63)
|
||||
if (Rotate == 0 && (Start == 32 || Start == 48 || Start == 56) && End == 63)
|
||||
return 0;
|
||||
|
||||
SDValue Ops[5] = {
|
||||
getUNDEF64(SDLoc(N)),
|
||||
convertTo(SDLoc(N), MVT::i64, N->getOperand(0)),
|
||||
convertTo(SDLoc(N), MVT::i64, Input),
|
||||
CurDAG->getTargetConstant(Start, MVT::i32),
|
||||
CurDAG->getTargetConstant(End | 128, MVT::i32),
|
||||
CurDAG->getTargetConstant(0, MVT::i32)
|
||||
CurDAG->getTargetConstant(Rotate, MVT::i32)
|
||||
};
|
||||
N = CurDAG->getMachineNode(SystemZ::RISBG, SDLoc(N), MVT::i64, Ops);
|
||||
return convertTo(SDLoc(N), VT, SDValue(N, 0)).getNode();
|
||||
|
@ -16,7 +16,7 @@ define float @f1(i32 %a) {
|
||||
; surrounding code.
|
||||
define float @f2(i64 %big) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[REGISTER:%r[0-5]]], %r2, 31
|
||||
; CHECK: risbg [[REGISTER:%r[0-5]]], %r2, 0, 159, 31
|
||||
; CHECK: ldgr %f0, [[REGISTER]]
|
||||
%shift = lshr i64 %big, 1
|
||||
%a = trunc i64 %shift to i32
|
||||
@ -27,7 +27,7 @@ define float @f2(i64 %big) {
|
||||
; Another example of the same thing.
|
||||
define float @f3(i64 %big) {
|
||||
; CHECK: f3:
|
||||
; CHECK: sllg [[REGISTER:%r[0-5]]], %r2, 2
|
||||
; CHECK: risbg [[REGISTER:%r[0-5]]], %r2, 0, 159, 2
|
||||
; CHECK: ldgr %f0, [[REGISTER]]
|
||||
%shift = ashr i64 %big, 30
|
||||
%a = trunc i64 %shift to i32
|
||||
|
Loading…
Reference in New Issue
Block a user