summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorNemanja Ivanovic <nemanja.i.ibm@gmail.com>2017-09-22 11:50:25 +0000
committerNemanja Ivanovic <nemanja.i.ibm@gmail.com>2017-09-22 11:50:25 +0000
commitd6f93f5143b4a91a0b81053e462c38c14810fe4e (patch)
treed34a6e5a61afebcf937df8253120ca54c322326c /llvm/lib
parenta9035a8fec0d52b0854fd79b1cfd2e079d671177 (diff)
downloadbcm5719-llvm-d6f93f5143b4a91a0b81053e462c38c14810fe4e.tar.gz
bcm5719-llvm-d6f93f5143b4a91a0b81053e462c38c14810fe4e.zip
Recommit r310809 with a fix for the spill problem
This patch re-commits the patch that was pulled out due to a problem it caused, but with a fix for the problem. The fix was reviewed separately by Eric Christopher and Hal Finkel. Differential Revision: https://reviews.llvm.org/D38054 llvm-svn: 313978
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp201
1 files changed, 150 insertions, 51 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index c9a5faa86f6..f794312e39b 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -75,8 +75,6 @@ STATISTIC(NumZextSetcc,
"Number of (zext(setcc)) nodes expanded into GPR sequence.");
STATISTIC(SignExtensionsAdded,
"Number of sign extensions for compare inputs added.");
-STATISTIC(ZeroExtensionsAdded,
- "Number of zero extensions for compare inputs added.");
STATISTIC(NumLogicOpsOnComparison,
"Number of logical ops on i1 values calculated in GPR.");
STATISTIC(OmittedForNonExtendUses,
@@ -288,13 +286,24 @@ private:
// SExtInvert - invert the condition code, sign-extend value
enum SetccInGPROpts { ZExtOrig, ZExtInvert, SExtOrig, SExtInvert };
+ // Comparisons against zero to emit GPR code sequences for. Each of these
+ // sequences may need to be emitted for two or more equivalent patterns.
+ // For example (a >= 0) == (a > -1). The direction of the comparison (</>)
+ // matters as well as the extension type: sext (-1/0), zext (1/0).
+ // GEZExt - (zext (LHS >= 0))
+ // GESExt - (sext (LHS >= 0))
+ // LEZExt - (zext (LHS <= 0))
+ // LESExt - (sext (LHS <= 0))
+ enum ZeroCompare { GEZExt, GESExt, LEZExt, LESExt };
+
bool trySETCC(SDNode *N);
bool tryEXTEND(SDNode *N);
bool tryLogicOpOfCompares(SDNode *N);
SDValue computeLogicOpInGPR(SDValue LogicOp);
SDValue signExtendInputIfNeeded(SDValue Input);
- SDValue zeroExtendInputIfNeeded(SDValue Input);
SDValue addExtOrTrunc(SDValue NatWidthRes, ExtOrTruncConversion Conv);
+ SDValue getCompoundZeroComparisonInGPR(SDValue LHS, SDLoc dl,
+ ZeroCompare CmpTy);
SDValue get32BitZExtCompare(SDValue LHS, SDValue RHS, ISD::CondCode CC,
int64_t RHSValue, SDLoc dl);
SDValue get32BitSExtCompare(SDValue LHS, SDValue RHS, ISD::CondCode CC,
@@ -2553,15 +2562,15 @@ bool PPCDAGToDAGISel::tryEXTEND(SDNode *N) {
return false;
SDLoc dl(N);
- bool Inputs32Bit = N->getOperand(0).getOperand(0).getValueType() == MVT::i32;
+ bool Input32Bit = WideRes.getValueType() == MVT::i32;
bool Output32Bit = N->getValueType(0) == MVT::i32;
NumSextSetcc += N->getOpcode() == ISD::SIGN_EXTEND ? 1 : 0;
NumZextSetcc += N->getOpcode() == ISD::SIGN_EXTEND ? 0 : 1;
SDValue ConvOp = WideRes;
- if (Inputs32Bit != Output32Bit)
- ConvOp = addExtOrTrunc(WideRes, Inputs32Bit ? ExtOrTruncConversion::Ext :
+ if (Input32Bit != Output32Bit)
+ ConvOp = addExtOrTrunc(WideRes, Input32Bit ? ExtOrTruncConversion::Ext :
ExtOrTruncConversion::Trunc);
ReplaceNode(N, ConvOp.getNode());
@@ -2722,6 +2731,7 @@ bool PPCDAGToDAGISel::tryLogicOpOfCompares(SDNode *N) {
}
/// If the value isn't guaranteed to be sign-extended to 64-bits, extend it.
+/// Otherwise just reinterpret it as a 64-bit value.
/// Useful when emitting comparison code for 32-bit values without using
/// the compare instruction (which only considers the lower 32-bits).
SDValue PPCDAGToDAGISel::signExtendInputIfNeeded(SDValue Input) {
@@ -2734,51 +2744,23 @@ SDValue PPCDAGToDAGISel::signExtendInputIfNeeded(SDValue Input) {
if (Opc == ISD::TRUNCATE &&
(Input.getOperand(0).getOpcode() == ISD::AssertSext ||
Input.getOperand(0).getOpcode() == ISD::SIGN_EXTEND))
- return Input;
+ return addExtOrTrunc(Input, ExtOrTruncConversion::Ext);
LoadSDNode *InputLoad = dyn_cast<LoadSDNode>(Input);
// The input is a sign-extending load. No reason to sign-extend.
if (InputLoad && InputLoad->getExtensionType() == ISD::SEXTLOAD)
- return Input;
+ return addExtOrTrunc(Input, ExtOrTruncConversion::Ext);
ConstantSDNode *InputConst = dyn_cast<ConstantSDNode>(Input);
// We don't sign-extend constants and already sign-extended values.
if (InputConst || Opc == ISD::AssertSext || Opc == ISD::SIGN_EXTEND_INREG ||
Opc == ISD::SIGN_EXTEND)
- return Input;
+ return addExtOrTrunc(Input, ExtOrTruncConversion::Ext);
SDLoc dl(Input);
SignExtensionsAdded++;
- return SDValue(CurDAG->getMachineNode(PPC::EXTSW_32, dl, MVT::i32, Input), 0);
-}
-
-/// If the value isn't guaranteed to be zero-extended to 64-bits, extend it.
-/// Useful when emitting comparison code for 32-bit values without using
-/// the compare instruction (which only considers the lower 32-bits).
-SDValue PPCDAGToDAGISel::zeroExtendInputIfNeeded(SDValue Input) {
- assert(Input.getValueType() == MVT::i32 &&
- "Can only zero-extend 32-bit values here.");
- LoadSDNode *InputLoad = dyn_cast<LoadSDNode>(Input);
- unsigned Opc = Input.getOpcode();
-
- // No need to zero-extend loaded values (unless they're loaded with
- // a sign-extending load).
- if (InputLoad && InputLoad->getExtensionType() != ISD::SEXTLOAD)
- return Input;
-
- ConstantSDNode *InputConst = dyn_cast<ConstantSDNode>(Input);
- bool InputZExtConst = InputConst && InputConst->getSExtValue() >= 0;
- // An ISD::TRUNCATE will be lowered to an EXTRACT_SUBREG so we have
- // to conservatively actually clear the high bits. We also don't need to
- // zero-extend constants or values that are already zero-extended.
- if (InputZExtConst || Opc == ISD::AssertZext || Opc == ISD::ZERO_EXTEND)
- return Input;
-
- SDLoc dl(Input);
- ZeroExtensionsAdded++;
- return SDValue(CurDAG->getMachineNode(PPC::RLDICL_32, dl, MVT::i32, Input,
- getI64Imm(0, dl), getI64Imm(32, dl)),
- 0);
+ return SDValue(CurDAG->getMachineNode(PPC::EXTSW_32_64, dl,
+ MVT::i64, Input), 0);
}
// Handle a 32-bit value in a 64-bit register and vice-versa. These are of
@@ -2809,6 +2791,73 @@ SDValue PPCDAGToDAGISel::addExtOrTrunc(SDValue NatWidthRes,
NatWidthRes, SubRegIdx), 0);
}
+// Produce a GPR sequence for compound comparisons (<=, >=) against zero.
+// Handle both zero-extensions and sign-extensions.
+SDValue PPCDAGToDAGISel::getCompoundZeroComparisonInGPR(SDValue LHS, SDLoc dl,
+ ZeroCompare CmpTy) {
+ EVT InVT = LHS.getValueType();
+ bool Is32Bit = InVT == MVT::i32;
+ SDValue ToExtend;
+
+ // Produce the value that needs to be either zero or sign extended.
+ switch (CmpTy) {
+ default: llvm_unreachable("Unknown Zero-comparison type.");
+ case ZeroCompare::GEZExt:
+ case ZeroCompare::GESExt:
+ ToExtend = SDValue(CurDAG->getMachineNode(Is32Bit ? PPC::NOR : PPC::NOR8,
+ dl, InVT, LHS, LHS), 0);
+ case ZeroCompare::LEZExt:
+ case ZeroCompare::LESExt: {
+ if (Is32Bit) {
+ // Upper 32 bits cannot be undefined for this sequence.
+ LHS = signExtendInputIfNeeded(LHS);
+ SDValue Neg =
+ SDValue(CurDAG->getMachineNode(PPC::NEG8, dl, MVT::i64, LHS), 0);
+ ToExtend =
+ SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
+ Neg, getI64Imm(1, dl),
+ getI64Imm(63, dl)), 0);
+ } else {
+ SDValue Addi =
+ SDValue(CurDAG->getMachineNode(PPC::ADDI8, dl, MVT::i64, LHS,
+ getI64Imm(~0ULL, dl)), 0);
+ ToExtend = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
+ Addi, LHS), 0);
+ }
+ }
+ }
+
+ // For 64-bit sequences, the extensions are the same for the GE/LE cases.
+ if (!Is32Bit && (CmpTy == ZeroCompare::GEZExt || ZeroCompare::LEZExt))
+ return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
+ ToExtend, getI64Imm(1, dl),
+ getI64Imm(63, dl)), 0);
+ if (!Is32Bit && (CmpTy == ZeroCompare::GESExt || ZeroCompare::LESExt))
+ return SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64, ToExtend,
+ getI64Imm(63, dl)), 0);
+
+ assert(Is32Bit && "Should have handled the 32-bit sequences above.");
+ // For 32-bit sequences, the extensions differ between GE/LE cases.
+ switch (CmpTy) {
+ default: llvm_unreachable("Unknown Zero-comparison type.");
+ case ZeroCompare::GEZExt: {
+ SDValue ShiftOps[] =
+ { ToExtend, getI32Imm(1, dl), getI32Imm(31, dl), getI32Imm(31, dl) };
+ return SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32,
+ ShiftOps), 0);
+ }
+ case ZeroCompare::GESExt:
+ return SDValue(CurDAG->getMachineNode(PPC::SRAWI, dl, MVT::i32, ToExtend,
+ getI32Imm(31, dl)), 0);
+ case ZeroCompare::LEZExt:
+ return SDValue(CurDAG->getMachineNode(PPC::XORI8, dl, MVT::i64, ToExtend,
+ getI32Imm(1, dl)), 0);
+ case ZeroCompare::LESExt:
+ return SDValue(CurDAG->getMachineNode(PPC::ADDI8, dl, MVT::i64, ToExtend,
+ getI32Imm(-1, dl)), 0);
+ }
+}
+
/// Produces a zero-extended result of comparing two 32-bit values according to
/// the passed condition code.
SDValue PPCDAGToDAGISel::get32BitZExtCompare(SDValue LHS, SDValue RHS,
@@ -2843,6 +2892,34 @@ SDValue PPCDAGToDAGISel::get32BitZExtCompare(SDValue LHS, SDValue RHS,
return SDValue(CurDAG->getMachineNode(PPC::XORI, dl, MVT::i32, Shift,
getI32Imm(1, dl)), 0);
}
+ case ISD::SETGE: {
+ // (zext (setcc %a, %b, setge)) -> (xor (lshr (sub %a, %b), 63), 1)
+ // (zext (setcc %a, 0, setge)) -> (lshr (~ %a), 31)
+ if(IsRHSZero)
+ return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GEZExt);
+ std::swap(LHS, RHS);
+ ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
+ IsRHSZero = RHSConst && RHSConst->isNullValue();
+ LLVM_FALLTHROUGH;
+ }
+ case ISD::SETLE: {
+ // (zext (setcc %a, %b, setle)) -> (xor (lshr (sub %b, %a), 63), 1)
+ // (zext (setcc %a, 0, setle)) -> (xor (lshr (- %a), 63), 1)
+ if(IsRHSZero)
+ return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::LEZExt);
+
+ // The upper 32-bits of the register can't be undefined for this sequence.
+ LHS = signExtendInputIfNeeded(LHS);
+ RHS = signExtendInputIfNeeded(RHS);
+ SDValue Sub =
+ SDValue(CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, LHS, RHS), 0);
+ SDValue Shift =
+ SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Sub,
+ getI64Imm(1, dl), getI64Imm(63, dl)), 0);
+ return
+ SDValue(CurDAG->getMachineNode(PPC::XORI8, dl,
+ MVT::i64, Shift, getI32Imm(1, dl)), 0);
+ }
}
}
@@ -2863,11 +2940,11 @@ SDValue PPCDAGToDAGISel::get32BitSExtCompare(SDValue LHS, SDValue RHS,
SDValue(CurDAG->getMachineNode(PPC::XOR, dl, MVT::i32, LHS, RHS), 0);
SDValue Cntlzw =
SDValue(CurDAG->getMachineNode(PPC::CNTLZW, dl, MVT::i32, CountInput), 0);
- SDValue SHLOps[] = { Cntlzw, getI32Imm(58, dl), getI32Imm(0, dl) };
- SDValue Sldi =
- SDValue(CurDAG->getMachineNode(PPC::RLDICR_32, dl, MVT::i32, SHLOps), 0);
- return SDValue(CurDAG->getMachineNode(PPC::SRADI_32, dl, MVT::i32, Sldi,
- getI32Imm(63, dl)), 0);
+ SDValue SHLOps[] = { Cntlzw, getI32Imm(27, dl),
+ getI32Imm(5, dl), getI32Imm(31, dl) };
+ SDValue Slwi =
+ SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, SHLOps), 0);
+ return SDValue(CurDAG->getMachineNode(PPC::NEG, dl, MVT::i32, Slwi), 0);
}
case ISD::SETNE: {
// Bitwise xor the operands, count leading zeros, shift right by 5 bits and
@@ -2890,6 +2967,35 @@ SDValue PPCDAGToDAGISel::get32BitSExtCompare(SDValue LHS, SDValue RHS,
getI32Imm(1, dl)), 0);
return SDValue(CurDAG->getMachineNode(PPC::NEG, dl, MVT::i32, Xori), 0);
}
+ case ISD::SETGE: {
+ // (sext (setcc %a, %b, setge)) -> (add (lshr (sub %a, %b), 63), -1)
+ // (sext (setcc %a, 0, setge)) -> (ashr (~ %a), 31)
+ if (IsRHSZero)
+ return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GESExt);
+ std::swap(LHS, RHS);
+ ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
+ IsRHSZero = RHSConst && RHSConst->isNullValue();
+ LLVM_FALLTHROUGH;
+ }
+ case ISD::SETLE: {
+ // (sext (setcc %a, %b, setge)) -> (add (lshr (sub %b, %a), 63), -1)
+ // (sext (setcc %a, 0, setle)) -> (add (lshr (- %a), 63), -1)
+ if (IsRHSZero)
+ return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::LESExt);
+
+ // The upper 32-bits of the register can't be undefined for this sequence.
+ LHS = signExtendInputIfNeeded(LHS);
+ RHS = signExtendInputIfNeeded(RHS);
+ SDValue SUBFNode =
+ SDValue(CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, MVT::Glue,
+ LHS, RHS), 0);
+ SDValue Srdi =
+ SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
+ SUBFNode, getI64Imm(1, dl),
+ getI64Imm(63, dl)), 0);
+ return SDValue(CurDAG->getMachineNode(PPC::ADDI8, dl, MVT::i64, Srdi,
+ getI32Imm(-1, dl)), 0);
+ }
}
}
@@ -3020,13 +3126,6 @@ SDValue PPCDAGToDAGISel::getSETCCInGPR(SDValue Compare,
CC = ISD::getSetCCInverse(CC, true);
bool Inputs32Bit = InputVT == MVT::i32;
- if (ISD::isSignedIntSetCC(CC) && Inputs32Bit) {
- LHS = signExtendInputIfNeeded(LHS);
- RHS = signExtendInputIfNeeded(RHS);
- } else if (ISD::isUnsignedIntSetCC(CC) && Inputs32Bit) {
- LHS = zeroExtendInputIfNeeded(LHS);
- RHS = zeroExtendInputIfNeeded(RHS);
- }
SDLoc dl(Compare);
ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
OpenPOWER on IntegriCloud