mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-30 04:35:00 +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;
|
||||
}
|
||||
|
||||
// Check whether the CC value produced by TEST UNDER MASK is descriptive
|
||||
// enough to handle an AND with Mask followed by a comparison of type Opcode
|
||||
// with CmpVal. CCMask says which comparison result is being tested and
|
||||
// BitSize is the number of bits in the operands. Return the CC mask that
|
||||
// should be used for the TEST UNDER MASK result, or 0 if the condition is
|
||||
// too complex.
|
||||
// Return true if shift operation N has an in-range constant shift value.
|
||||
// Store it in ShiftVal if so.
|
||||
static bool isSimpleShift(SDValue N, unsigned &ShiftVal) {
|
||||
ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N.getOperand(1));
|
||||
if (!Shift)
|
||||
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,
|
||||
uint64_t Mask, uint64_t CmpVal,
|
||||
unsigned ICmpType) {
|
||||
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.
|
||||
unsigned HighShift = 63 - countLeadingZeros(Mask);
|
||||
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
|
||||
// tested is as described by CCValid and CCMask. Update the arguments
|
||||
// with the TM version if so.
|
||||
static void adjustForTestUnderMask(unsigned &Opcode, SDValue &CmpOp0,
|
||||
SDValue &CmpOp1, unsigned &CCValid,
|
||||
unsigned &CCMask, unsigned &ICmpType) {
|
||||
static void adjustForTestUnderMask(SelectionDAG &DAG, unsigned &Opcode,
|
||||
SDValue &CmpOp0, SDValue &CmpOp1,
|
||||
unsigned &CCValid, unsigned &CCMask,
|
||||
unsigned &ICmpType) {
|
||||
// Check that we have a comparison with a constant.
|
||||
ConstantSDNode *ConstCmpOp1 = dyn_cast<ConstantSDNode>(CmpOp1);
|
||||
if (!ConstCmpOp1)
|
||||
return;
|
||||
uint64_t CmpVal = ConstCmpOp1->getZExtValue();
|
||||
|
||||
// Check whether the nonconstant input is an AND with a constant mask.
|
||||
if (CmpOp0.getOpcode() != ISD::AND)
|
||||
@ -1246,21 +1268,35 @@ static void adjustForTestUnderMask(unsigned &Opcode, SDValue &CmpOp0,
|
||||
ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(AndOp1.getNode());
|
||||
if (!Mask)
|
||||
return;
|
||||
|
||||
// Check whether the mask is suitable for TMHH, TMHL, TMLH or TMLL.
|
||||
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
|
||||
// type are suitable.
|
||||
unsigned BitSize = CmpOp0.getValueType().getSizeInBits();
|
||||
unsigned NewCCMask = getTestUnderMaskCond(BitSize, CCMask, MaskVal,
|
||||
ConstCmpOp1->getZExtValue(),
|
||||
ICmpType);
|
||||
if (!NewCCMask)
|
||||
return;
|
||||
unsigned NewCCMask, ShiftVal;
|
||||
if (ICmpType != SystemZICMP::SignedOnly &&
|
||||
AndOp0.getOpcode() == ISD::SHL &&
|
||||
isSimpleShift(AndOp0, ShiftVal) &&
|
||||
(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.
|
||||
Opcode = SystemZISD::TM;
|
||||
@ -1316,7 +1352,8 @@ static SDValue emitCmp(const SystemZTargetMachine &TM, SelectionDAG &DAG,
|
||||
(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)
|
||||
return DAG.getNode(Opcode, DL, MVT::Glue, CmpOp0, CmpOp1,
|
||||
DAG.getConstant(ICmpType, MVT::i32));
|
||||
|
@ -449,3 +449,43 @@ store:
|
||||
exit:
|
||||
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:
|
||||
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