diff options
author | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-08-23 11:27:19 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-08-23 11:27:19 +0000 |
commit | 24e597b8c5986f4cc2d23e8145c0f04c57fae0bd (patch) | |
tree | 7afe4da420482b37cf87fc0a6b23c8f4e14148f2 /llvm/lib | |
parent | a481f5854203e81cde5bba83e3f4c9a7c321fd29 (diff) | |
download | bcm5719-llvm-24e597b8c5986f4cc2d23e8145c0f04c57fae0bd.tar.gz bcm5719-llvm-24e597b8c5986f4cc2d23e8145c0f04c57fae0bd.zip |
[SystemZ] Try reversing comparisons whose first operand is in memory
This allows us to make more use of the many compare reg,mem instructions.
llvm-svn: 189099
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index a1eecd736ce..65b2ad2164f 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/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); |