[SystemZ] Try reversing comparisons whose first operand is in memory
[oota-llvm.git] / lib / Target / SystemZ / SystemZISelLowering.cpp
index a1eecd736ce94b680b7907434c314493c49a3f0a..65b2ad2164f8ed328d140c4dd160b445427e3bd3 100644 (file)
@@ -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);