mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-06 06:33:24 +00:00
[SystemZ] Try to fold shifts into TMxx
E.g. "SRL %r2, 2; TMLL %r2, 1" => "TMLL %r2, 4". git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190672 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9a8392b8ac
commit
856bf59433
@ -1135,17 +1135,37 @@ static bool shouldSwapCmpOperands(SDValue Op0, SDValue Op1,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether the CC value produced by TEST UNDER MASK is descriptive
|
// Return true if shift operation N has an in-range constant shift value.
|
||||||
// enough to handle an AND with Mask followed by a comparison of type Opcode
|
// Store it in ShiftVal if so.
|
||||||
// with CmpVal. CCMask says which comparison result is being tested and
|
static bool isSimpleShift(SDValue N, unsigned &ShiftVal) {
|
||||||
// BitSize is the number of bits in the operands. Return the CC mask that
|
ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N.getOperand(1));
|
||||||
// should be used for the TEST UNDER MASK result, or 0 if the condition is
|
if (!Shift)
|
||||||
// too complex.
|
return false;
|
||||||
|
|
||||||
|
uint64_t Amount = Shift->getZExtValue();
|
||||||
|
if (Amount >= N.getValueType().getSizeInBits())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ShiftVal = Amount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether an AND with Mask is suitable for a TEST UNDER MASK
|
||||||
|
// instruction and whether the CC value is descriptive enough to handle
|
||||||
|
// a comparison of type Opcode between the AND result and CmpVal.
|
||||||
|
// CCMask says which comparison result is being tested and BitSize is
|
||||||
|
// the number of bits in the operands. If TEST UNDER MASK can be used,
|
||||||
|
// return the corresponding CC mask, otherwise return 0.
|
||||||
static unsigned getTestUnderMaskCond(unsigned BitSize, unsigned CCMask,
|
static unsigned getTestUnderMaskCond(unsigned BitSize, unsigned CCMask,
|
||||||
uint64_t Mask, uint64_t CmpVal,
|
uint64_t Mask, uint64_t CmpVal,
|
||||||
unsigned ICmpType) {
|
unsigned ICmpType) {
|
||||||
assert(Mask != 0 && "ANDs with zero should have been removed by now");
|
assert(Mask != 0 && "ANDs with zero should have been removed by now");
|
||||||
|
|
||||||
|
// Check whether the mask is suitable for TMHH, TMHL, TMLH or TMLL.
|
||||||
|
if (!SystemZ::isImmLL(Mask) && !SystemZ::isImmLH(Mask) &&
|
||||||
|
!SystemZ::isImmHL(Mask) && !SystemZ::isImmHH(Mask))
|
||||||
|
return 0;
|
||||||
|
|
||||||
// Work out the masks for the lowest and highest bits.
|
// Work out the masks for the lowest and highest bits.
|
||||||
unsigned HighShift = 63 - countLeadingZeros(Mask);
|
unsigned HighShift = 63 - countLeadingZeros(Mask);
|
||||||
uint64_t High = uint64_t(1) << HighShift;
|
uint64_t High = uint64_t(1) << HighShift;
|
||||||
@ -1230,13 +1250,15 @@ static unsigned getTestUnderMaskCond(unsigned BitSize, unsigned CCMask,
|
|||||||
// implemented as a TEST UNDER MASK instruction when the condition being
|
// implemented as a TEST UNDER MASK instruction when the condition being
|
||||||
// tested is as described by CCValid and CCMask. Update the arguments
|
// tested is as described by CCValid and CCMask. Update the arguments
|
||||||
// with the TM version if so.
|
// with the TM version if so.
|
||||||
static void adjustForTestUnderMask(unsigned &Opcode, SDValue &CmpOp0,
|
static void adjustForTestUnderMask(SelectionDAG &DAG, unsigned &Opcode,
|
||||||
SDValue &CmpOp1, unsigned &CCValid,
|
SDValue &CmpOp0, SDValue &CmpOp1,
|
||||||
unsigned &CCMask, unsigned &ICmpType) {
|
unsigned &CCValid, unsigned &CCMask,
|
||||||
|
unsigned &ICmpType) {
|
||||||
// Check that we have a comparison with a constant.
|
// Check that we have a comparison with a constant.
|
||||||
ConstantSDNode *ConstCmpOp1 = dyn_cast<ConstantSDNode>(CmpOp1);
|
ConstantSDNode *ConstCmpOp1 = dyn_cast<ConstantSDNode>(CmpOp1);
|
||||||
if (!ConstCmpOp1)
|
if (!ConstCmpOp1)
|
||||||
return;
|
return;
|
||||||
|
uint64_t CmpVal = ConstCmpOp1->getZExtValue();
|
||||||
|
|
||||||
// Check whether the nonconstant input is an AND with a constant mask.
|
// Check whether the nonconstant input is an AND with a constant mask.
|
||||||
if (CmpOp0.getOpcode() != ISD::AND)
|
if (CmpOp0.getOpcode() != ISD::AND)
|
||||||
@ -1246,21 +1268,35 @@ static void adjustForTestUnderMask(unsigned &Opcode, SDValue &CmpOp0,
|
|||||||
ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(AndOp1.getNode());
|
ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(AndOp1.getNode());
|
||||||
if (!Mask)
|
if (!Mask)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Check whether the mask is suitable for TMHH, TMHL, TMLH or TMLL.
|
|
||||||
uint64_t MaskVal = Mask->getZExtValue();
|
uint64_t MaskVal = Mask->getZExtValue();
|
||||||
if (!SystemZ::isImmLL(MaskVal) && !SystemZ::isImmLH(MaskVal) &&
|
|
||||||
!SystemZ::isImmHL(MaskVal) && !SystemZ::isImmHH(MaskVal))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Check whether the combination of mask, comparison value and comparison
|
// Check whether the combination of mask, comparison value and comparison
|
||||||
// type are suitable.
|
// type are suitable.
|
||||||
unsigned BitSize = CmpOp0.getValueType().getSizeInBits();
|
unsigned BitSize = CmpOp0.getValueType().getSizeInBits();
|
||||||
unsigned NewCCMask = getTestUnderMaskCond(BitSize, CCMask, MaskVal,
|
unsigned NewCCMask, ShiftVal;
|
||||||
ConstCmpOp1->getZExtValue(),
|
if (ICmpType != SystemZICMP::SignedOnly &&
|
||||||
ICmpType);
|
AndOp0.getOpcode() == ISD::SHL &&
|
||||||
if (!NewCCMask)
|
isSimpleShift(AndOp0, ShiftVal) &&
|
||||||
return;
|
(NewCCMask = getTestUnderMaskCond(BitSize, CCMask, MaskVal >> ShiftVal,
|
||||||
|
CmpVal >> ShiftVal,
|
||||||
|
SystemZICMP::Any))) {
|
||||||
|
AndOp0 = AndOp0.getOperand(0);
|
||||||
|
AndOp1 = DAG.getConstant(MaskVal >> ShiftVal, AndOp0.getValueType());
|
||||||
|
} else if (ICmpType != SystemZICMP::SignedOnly &&
|
||||||
|
AndOp0.getOpcode() == ISD::SRL &&
|
||||||
|
isSimpleShift(AndOp0, ShiftVal) &&
|
||||||
|
(NewCCMask = getTestUnderMaskCond(BitSize, CCMask,
|
||||||
|
MaskVal << ShiftVal,
|
||||||
|
CmpVal << ShiftVal,
|
||||||
|
SystemZICMP::UnsignedOnly))) {
|
||||||
|
AndOp0 = AndOp0.getOperand(0);
|
||||||
|
AndOp1 = DAG.getConstant(MaskVal << ShiftVal, AndOp0.getValueType());
|
||||||
|
} else {
|
||||||
|
NewCCMask = getTestUnderMaskCond(BitSize, CCMask, MaskVal, CmpVal,
|
||||||
|
ICmpType);
|
||||||
|
if (!NewCCMask)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Go ahead and make the change.
|
// Go ahead and make the change.
|
||||||
Opcode = SystemZISD::TM;
|
Opcode = SystemZISD::TM;
|
||||||
@ -1316,7 +1352,8 @@ static SDValue emitCmp(const SystemZTargetMachine &TM, SelectionDAG &DAG,
|
|||||||
(CCMask & SystemZ::CCMASK_CMP_UO));
|
(CCMask & SystemZ::CCMASK_CMP_UO));
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustForTestUnderMask(Opcode, CmpOp0, CmpOp1, CCValid, CCMask, ICmpType);
|
adjustForTestUnderMask(DAG, Opcode, CmpOp0, CmpOp1, CCValid, CCMask,
|
||||||
|
ICmpType);
|
||||||
if (Opcode == SystemZISD::ICMP || Opcode == SystemZISD::TM)
|
if (Opcode == SystemZISD::ICMP || Opcode == SystemZISD::TM)
|
||||||
return DAG.getNode(Opcode, DL, MVT::Glue, CmpOp0, CmpOp1,
|
return DAG.getNode(Opcode, DL, MVT::Glue, CmpOp0, CmpOp1,
|
||||||
DAG.getConstant(ICmpType, MVT::i32));
|
DAG.getConstant(ICmpType, MVT::i32));
|
||||||
|
@ -449,3 +449,43 @@ store:
|
|||||||
exit:
|
exit:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Check that we can fold an SHL into a TMxx mask.
|
||||||
|
define void @f24(i32 %a) {
|
||||||
|
; CHECK-LABEL: f24:
|
||||||
|
; CHECK: tmll %r2, 255
|
||||||
|
; CHECK: jne {{\.L.*}}
|
||||||
|
; CHECK: br %r14
|
||||||
|
entry:
|
||||||
|
%shl = shl i32 %a, 12
|
||||||
|
%and = and i32 %shl, 1044480
|
||||||
|
%cmp = icmp ne i32 %and, 0
|
||||||
|
br i1 %cmp, label %exit, label %store
|
||||||
|
|
||||||
|
store:
|
||||||
|
store i32 1, i32 *@g
|
||||||
|
br label %exit
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Check that we can fold an SHR into a TMxx mask.
|
||||||
|
define void @f25(i32 %a) {
|
||||||
|
; CHECK-LABEL: f25:
|
||||||
|
; CHECK: tmlh %r2, 512
|
||||||
|
; CHECK: jne {{\.L.*}}
|
||||||
|
; CHECK: br %r14
|
||||||
|
entry:
|
||||||
|
%shr = lshr i32 %a, 25
|
||||||
|
%and = and i32 %shr, 1
|
||||||
|
%cmp = icmp ne i32 %and, 0
|
||||||
|
br i1 %cmp, label %exit, label %store
|
||||||
|
|
||||||
|
store:
|
||||||
|
store i32 1, i32 *@g
|
||||||
|
br label %exit
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
@ -191,3 +191,43 @@ store:
|
|||||||
exit:
|
exit:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Check that we can fold an SHL into a TMxx mask.
|
||||||
|
define void @f11(i64 %a) {
|
||||||
|
; CHECK-LABEL: f11:
|
||||||
|
; CHECK: tmhl %r2, 32768
|
||||||
|
; CHECK: jne {{\.L.*}}
|
||||||
|
; CHECK: br %r14
|
||||||
|
entry:
|
||||||
|
%shl = shl i64 %a, 1
|
||||||
|
%and = and i64 %shl, 281474976710656
|
||||||
|
%cmp = icmp ne i64 %and, 0
|
||||||
|
br i1 %cmp, label %exit, label %store
|
||||||
|
|
||||||
|
store:
|
||||||
|
store i32 1, i32 *@g
|
||||||
|
br label %exit
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Check that we can fold an SHR into a TMxx mask.
|
||||||
|
define void @f12(i64 %a) {
|
||||||
|
; CHECK-LABEL: f12:
|
||||||
|
; CHECK: tmhh %r2, 256
|
||||||
|
; CHECK: jne {{\.L.*}}
|
||||||
|
; CHECK: br %r14
|
||||||
|
entry:
|
||||||
|
%shr = lshr i64 %a, 56
|
||||||
|
%and = and i64 %shr, 1
|
||||||
|
%cmp = icmp ne i64 %and, 0
|
||||||
|
br i1 %cmp, label %exit, label %store
|
||||||
|
|
||||||
|
store:
|
||||||
|
store i32 1, i32 *@g
|
||||||
|
br label %exit
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user