aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/SystemZ/SystemZ.h7
-rw-r--r--lib/Target/SystemZ/SystemZISelLowering.cpp61
-rw-r--r--lib/Target/SystemZ/SystemZISelLowering.h4
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.td13
-rw-r--r--lib/Target/SystemZ/SystemZOperators.td1
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,