diff options
author | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-08-28 10:31:43 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-08-28 10:31:43 +0000 |
commit | 477168192c98e1f75a5bc6db3d34a177f327bd34 (patch) | |
tree | 29024a631a02e26dd2d4634abed8612c5469ca0c /lib/Target | |
parent | a6c3a4ee76ef8464d3c83472e15af521ade7eeb4 (diff) | |
download | external_llvm-477168192c98e1f75a5bc6db3d34a177f327bd34.zip external_llvm-477168192c98e1f75a5bc6db3d34a177f327bd34.tar.gz external_llvm-477168192c98e1f75a5bc6db3d34a177f327bd34.tar.bz2 |
[SystemZ] Add support for TMHH, TMHL, TMLH and TMLL
For now just handles simple comparisons of an ANDed value with zero.
The CC value provides enough information to do any comparison for a
2-bit mask, and some nonzero comparisons with more populated masks,
but that's all future work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189469 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/SystemZ/SystemZ.h | 7 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZISelLowering.cpp | 61 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZISelLowering.h | 4 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZInstrInfo.td | 13 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZOperators.td | 1 |
5 files changed, 76 insertions, 10 deletions
diff --git a/lib/Target/SystemZ/SystemZ.h b/lib/Target/SystemZ/SystemZ.h index ea6c7d1..051ba1d 100644 --- a/lib/Target/SystemZ/SystemZ.h +++ b/lib/Target/SystemZ/SystemZ.h @@ -57,6 +57,13 @@ namespace llvm { const unsigned CCMASK_SRST_NOTFOUND = CCMASK_2; const unsigned CCMASK_SRST = CCMASK_1 | CCMASK_2; + // Condition-code mask assignments for TEST UNDER MASK. + const unsigned CCMASK_TM_ALL_0 = CCMASK_0; + const unsigned CCMASK_TM_MIXED_MSB_0 = CCMASK_1; + const unsigned CCMASK_TM_MIXED_MSB_1 = CCMASK_2; + const unsigned CCMASK_TM_ALL_1 = CCMASK_3; + const unsigned CCMASK_TM = CCMASK_ANY; + // Mask assignments for PFD. const unsigned PFD_READ = 1; const unsigned PFD_WRITE = 2; diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index dd230c6..1ab1ef4 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1072,8 +1072,8 @@ static void adjustSubwordCmp(SelectionDAG &DAG, bool &IsUnsigned, // Return true if a comparison described by CCMask, CmpOp0 and CmpOp1 // is an equality comparison that is better implemented using unsigned // rather than signed comparison instructions. -static bool preferUnsignedComparison(SelectionDAG &DAG, SDValue CmpOp0, - SDValue CmpOp1, unsigned CCMask) { +static bool preferUnsignedComparison(SDValue CmpOp0, SDValue CmpOp1, + unsigned CCMask) { // The test must be for equality or inequality. if (CCMask != SystemZ::CCMASK_CMP_EQ && CCMask != SystemZ::CCMASK_CMP_NE) return false; @@ -1176,12 +1176,52 @@ static bool shouldSwapCmpOperands(SDValue Op0, SDValue Op1, return false; } +// See whether the comparison (Opcode CmpOp0, CmpOp1) can be 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) { + // For now we just handle equality and inequality with zero. + if (CCMask != SystemZ::CCMASK_CMP_EQ && + (CCMask ^ CCValid) != SystemZ::CCMASK_CMP_EQ) + return; + ConstantSDNode *ConstCmpOp1 = dyn_cast<ConstantSDNode>(CmpOp1); + if (!ConstCmpOp1 || ConstCmpOp1->getZExtValue() != 0) + return; + + // Check whether the nonconstant input is an AND with a constant mask. + if (CmpOp0.getOpcode() != ISD::AND) + return; + SDValue AndOp0 = CmpOp0.getOperand(0); + SDValue AndOp1 = CmpOp0.getOperand(1); + 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; + + // Go ahead and make the change. + Opcode = SystemZISD::TM; + CmpOp0 = AndOp0; + CmpOp1 = AndOp1; + CCValid = SystemZ::CCMASK_TM; + CCMask = (CCMask == SystemZ::CCMASK_CMP_EQ ? + SystemZ::CCMASK_TM_ALL_0 : + SystemZ::CCMASK_TM_ALL_0 ^ CCValid); +} + // Return a target node that compares CmpOp0 with CmpOp1 and stores a // 2-bit result in CC. Set CCValid to the CCMASK_* of all possible // 2-bit results and CCMask to the subset of those results that are // associated with Cond. -static SDValue emitCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, - ISD::CondCode Cond, unsigned &CCValid, +static SDValue emitCmp(SelectionDAG &DAG, SDLoc DL, SDValue CmpOp0, + SDValue CmpOp1, ISD::CondCode Cond, unsigned &CCValid, unsigned &CCMask) { bool IsUnsigned = false; CCMask = CCMaskForCondCode(Cond); @@ -1193,7 +1233,7 @@ static SDValue emitCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, CCMask &= CCValid; adjustZeroCmp(DAG, IsUnsigned, CmpOp0, CmpOp1, CCMask); adjustSubwordCmp(DAG, IsUnsigned, CmpOp0, CmpOp1, CCMask); - if (preferUnsignedComparison(DAG, CmpOp0, CmpOp1, CCMask)) + if (preferUnsignedComparison(CmpOp0, CmpOp1, CCMask)) IsUnsigned = true; } @@ -1205,9 +1245,9 @@ static SDValue emitCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, (CCMask & SystemZ::CCMASK_CMP_UO)); } - SDLoc DL(CmpOp0); - return DAG.getNode((IsUnsigned ? SystemZISD::UCMP : SystemZISD::CMP), - DL, MVT::Glue, CmpOp0, CmpOp1); + unsigned Opcode = (IsUnsigned ? SystemZISD::UCMP : SystemZISD::CMP); + adjustForTestUnderMask(Opcode, CmpOp0, CmpOp1, CCValid, CCMask); + return DAG.getNode(Opcode, DL, MVT::Glue, CmpOp0, CmpOp1); } // Implement a 32-bit *MUL_LOHI operation by extending both operands to @@ -1256,7 +1296,7 @@ SDValue SystemZTargetLowering::lowerBR_CC(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); unsigned CCValid, CCMask; - SDValue Flags = emitCmp(DAG, CmpOp0, CmpOp1, CC, CCValid, CCMask); + SDValue Flags = emitCmp(DAG, DL, CmpOp0, CmpOp1, CC, CCValid, CCMask); return DAG.getNode(SystemZISD::BR_CCMASK, DL, Op.getValueType(), Chain, DAG.getConstant(CCValid, MVT::i32), DAG.getConstant(CCMask, MVT::i32), Dest, Flags); @@ -1272,7 +1312,7 @@ SDValue SystemZTargetLowering::lowerSELECT_CC(SDValue Op, SDLoc DL(Op); unsigned CCValid, CCMask; - SDValue Flags = emitCmp(DAG, CmpOp0, CmpOp1, CC, CCValid, CCMask); + SDValue Flags = emitCmp(DAG, DL, CmpOp0, CmpOp1, CC, CCValid, CCMask); SmallVector<SDValue, 5> Ops; Ops.push_back(TrueOp); @@ -1908,6 +1948,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { OPCODE(PCREL_WRAPPER); OPCODE(CMP); OPCODE(UCMP); + OPCODE(TM); OPCODE(BR_CCMASK); OPCODE(SELECT_CCMASK); OPCODE(ADJDYNALLOC); diff --git a/lib/Target/SystemZ/SystemZISelLowering.h b/lib/Target/SystemZ/SystemZISelLowering.h index 9831777..ec5051f 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.h +++ b/lib/Target/SystemZ/SystemZISelLowering.h @@ -45,6 +45,10 @@ namespace SystemZISD { // Likewise unsigned integer comparison. UCMP, + // Test under mask. The first operand is ANDed with the second operand + // and the condition codes are set on the result. + TM, + // Branches if a condition is true. Operand 0 is the chain operand; // operand 1 is the 4-bit condition-code mask, with bit N in // big-endian order meaning "branch if CC=N"; operand 2 is the diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index 399b48a..7793818 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -1034,6 +1034,19 @@ let mayLoad = 1, Defs = [CC] in let mayLoad = 1, Defs = [CC], Uses = [R0W] in defm CLST : StringRRE<"clst", 0xB25D, z_strcmp>; +// Test under mask. +let Defs = [CC] in { + let isCodeGenOnly = 1 in { + def TMLL32 : CompareRI<"tmll", 0xA71, z_tm, GR32, imm32ll16>; + def TMLH32 : CompareRI<"tmlh", 0xA70, z_tm, GR32, imm32lh16>; + } + + def TMLL : CompareRI<"tmll", 0xA71, z_tm, GR64, imm64ll16>; + def TMLH : CompareRI<"tmlh", 0xA70, z_tm, GR64, imm64lh16>; + def TMHL : CompareRI<"tmhl", 0xA73, z_tm, GR64, imm64hl16>; + def TMHH : CompareRI<"tmhh", 0xA72, z_tm, GR64, imm64hh16>; +} + //===----------------------------------------------------------------------===// // Prefetch //===----------------------------------------------------------------------===// diff --git a/lib/Target/SystemZ/SystemZOperators.td b/lib/Target/SystemZ/SystemZOperators.td index ff64ea8..822195c 100644 --- a/lib/Target/SystemZ/SystemZOperators.td +++ b/lib/Target/SystemZ/SystemZOperators.td @@ -96,6 +96,7 @@ def z_sibcall : SDNode<"SystemZISD::SIBCALL", SDT_ZCall, def z_pcrel_wrapper : SDNode<"SystemZISD::PCREL_WRAPPER", SDT_ZWrapPtr, []>; def z_cmp : SDNode<"SystemZISD::CMP", SDT_ZCmp, [SDNPOutGlue]>; def z_ucmp : SDNode<"SystemZISD::UCMP", SDT_ZCmp, [SDNPOutGlue]>; +def z_tm : SDNode<"SystemZISD::TM", SDT_ZCmp, [SDNPOutGlue]>; def z_br_ccmask : SDNode<"SystemZISD::BR_CCMASK", SDT_ZBRCCMask, [SDNPHasChain, SDNPInGlue]>; def z_select_ccmask : SDNode<"SystemZISD::SELECT_CCMASK", SDT_ZSelectCCMask, |