summaryrefslogtreecommitdiff
path: root/lib/Target/SystemZ/SystemZISelLowering.cpp
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-08-23 11:27:19 +0000
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-08-23 11:27:19 +0000
commit35c93e4e42d7a35a90e89211fa62f478e25ba0a4 (patch)
tree639fbed77642a320f45ade7a571b37f1fbdf7b3c /lib/Target/SystemZ/SystemZISelLowering.cpp
parent65ddcfa8c1c05aeecd9d4fb062bb121e376aaceb (diff)
downloadllvm-35c93e4e42d7a35a90e89211fa62f478e25ba0a4.tar.gz
llvm-35c93e4e42d7a35a90e89211fa62f478e25ba0a4.tar.bz2
llvm-35c93e4e42d7a35a90e89211fa62f478e25ba0a4.tar.xz
[SystemZ] Try reversing comparisons whose first operand is in memory
This allows us to make more use of the many compare reg,mem instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189099 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/SystemZ/SystemZISelLowering.cpp')
-rw-r--r--lib/Target/SystemZ/SystemZISelLowering.cpp71
1 files changed, 71 insertions, 0 deletions
diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp
index a1eecd736c..65b2ad2164 100644
--- a/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -1110,6 +1110,69 @@ static bool preferUnsignedComparison(SelectionDAG &DAG, SDValue CmpOp0,
return false;
}
+// Return true if Op is either an unextended load, or a load with the
+// extension type given by IsUnsigned.
+static bool isNaturalMemoryOperand(SDValue Op, bool IsUnsigned) {
+ LoadSDNode *Load = dyn_cast<LoadSDNode>(Op.getNode());
+ if (Load)
+ switch (Load->getExtensionType()) {
+ case ISD::NON_EXTLOAD:
+ case ISD::EXTLOAD:
+ return true;
+ case ISD::SEXTLOAD:
+ return !IsUnsigned;
+ case ISD::ZEXTLOAD:
+ return IsUnsigned;
+ default:
+ break;
+ }
+ return false;
+}
+
+// Return true if it is better to swap comparison operands Op0 and Op1.
+// IsUnsigned says whether an integer comparison is signed or unsigned.
+static bool shouldSwapCmpOperands(SDValue Op0, SDValue Op1,
+ bool IsUnsigned) {
+ // Leave f128 comparisons alone, since they have no memory forms.
+ if (Op0.getValueType() == MVT::f128)
+ return false;
+
+ // Always keep a floating-point constant second, since comparisons with
+ // zero can use LOAD TEST and comparisons with other constants make a
+ // natural memory operand.
+ if (isa<ConstantFPSDNode>(Op1))
+ return false;
+
+ // Never swap comparisons with zero since there are many ways to optimize
+ // those later.
+ ConstantSDNode *COp1 = dyn_cast<ConstantSDNode>(Op1);
+ if (COp1 && COp1->getZExtValue() == 0)
+ return false;
+
+ // Look for cases where Cmp0 is a single-use load and Cmp1 isn't.
+ // In that case we generally prefer the memory to be second.
+ if ((isNaturalMemoryOperand(Op0, IsUnsigned) && Op0.hasOneUse()) &&
+ !(isNaturalMemoryOperand(Op1, IsUnsigned) && Op1.hasOneUse())) {
+ // The only exceptions are when the second operand is a constant and
+ // we can use things like CHHSI.
+ if (!COp1)
+ return true;
+ if (IsUnsigned) {
+ // The memory-immediate instructions require 16-bit unsigned integers.
+ if (isUInt<16>(COp1->getZExtValue()))
+ return false;
+ } else {
+ // There are no comparisons between integers and signed memory bytes.
+ // The others require 16-bit signed integers.
+ if (cast<LoadSDNode>(Op0.getNode())->getMemoryVT() == MVT::i8 ||
+ isInt<16>(COp1->getSExtValue()))
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
// 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
@@ -1131,6 +1194,14 @@ static SDValue emitCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1,
IsUnsigned = true;
}
+ if (shouldSwapCmpOperands(CmpOp0, CmpOp1, IsUnsigned)) {
+ std::swap(CmpOp0, CmpOp1);
+ CCMask = ((CCMask & SystemZ::CCMASK_CMP_EQ) |
+ (CCMask & SystemZ::CCMASK_CMP_GT ? SystemZ::CCMASK_CMP_LT : 0) |
+ (CCMask & SystemZ::CCMASK_CMP_LT ? SystemZ::CCMASK_CMP_GT : 0) |
+ (CCMask & SystemZ::CCMASK_CMP_UO));
+ }
+
SDLoc DL(CmpOp0);
return DAG.getNode((IsUnsigned ? SystemZISD::UCMP : SystemZISD::CMP),
DL, MVT::Glue, CmpOp0, CmpOp1);