diff options
| author | Nemanja Ivanovic <nemanja.i.ibm@gmail.com> | 2017-09-22 11:50:25 +0000 |
|---|---|---|
| committer | Nemanja Ivanovic <nemanja.i.ibm@gmail.com> | 2017-09-22 11:50:25 +0000 |
| commit | d6f93f5143b4a91a0b81053e462c38c14810fe4e (patch) | |
| tree | d34a6e5a61afebcf937df8253120ca54c322326c /llvm/lib | |
| parent | a9035a8fec0d52b0854fd79b1cfd2e079d671177 (diff) | |
| download | bcm5719-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.cpp | 201 |
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); |

