[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:
Richard Sandiford 2013-09-13 09:09:50 +00:00
parent 9a8392b8ac
commit 856bf59433
3 changed files with 137 additions and 20 deletions

View File

@ -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));

View File

@ -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
}

View File

@ -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
}