diff options
| author | Nemanja Ivanovic <nemanja.i.ibm@gmail.com> | 2017-08-08 11:20:44 +0000 |
|---|---|---|
| committer | Nemanja Ivanovic <nemanja.i.ibm@gmail.com> | 2017-08-08 11:20:44 +0000 |
| commit | 809fbfa6a16e3d3cf5df46c068e6f72dfe6f46ba (patch) | |
| tree | 40d05c631ce45641242c2b926c8900235d24fbcc /llvm/lib/Target/PowerPC | |
| parent | 7e9c478cda26a71dc4efbf96183738171eb9b721 (diff) | |
| download | bcm5719-llvm-809fbfa6a16e3d3cf5df46c068e6f72dfe6f46ba.tar.gz bcm5719-llvm-809fbfa6a16e3d3cf5df46c068e6f72dfe6f46ba.zip | |
[PowerPC] Eliminate compares - add i32 sext/zext handling for SETLE/SETGE
Adds handling for SETLE/SETGE comparisons on i32 values. Furthermore, it adds
the handling for the special case where RHS == 0.
Differential Revision: https://reviews.llvm.org/D34048
llvm-svn: 310346
Diffstat (limited to 'llvm/lib/Target/PowerPC')
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 4867f77bdc5..16325e76098 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -282,6 +282,11 @@ 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). + enum ZeroCompare { GEZExt, GESExt, LEZExt, LESExt }; + bool trySETCC(SDNode *N); bool tryEXTEND(SDNode *N); bool tryLogicOpOfCompares(SDNode *N); @@ -289,6 +294,8 @@ private: 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, @@ -2797,6 +2804,71 @@ 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) { + SDValue Neg = + SDValue(CurDAG->getMachineNode(PPC::NEG, dl, MVT::i32, LHS), 0); + ToExtend = + SDValue(CurDAG->getMachineNode(PPC::RLDICL_32, dl, MVT::i32, + 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::XORI, dl, MVT::i32, ToExtend, + getI32Imm(1, dl)), 0); + case ZeroCompare::LESExt: + return SDValue(CurDAG->getMachineNode(PPC::ADDI, dl, MVT::i32, 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, @@ -2831,6 +2903,32 @@ 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); + + // Not a special case (i.e. RHS == 0). Handle (%a >= %b) as (%b <= %a) + // by swapping inputs and falling through. + 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); + SDValue Sub = + SDValue(CurDAG->getMachineNode(PPC::SUBF, dl, MVT::i32, LHS, RHS), 0); + SDValue Shift = + SDValue(CurDAG->getMachineNode(PPC::RLDICL_32, dl, MVT::i32, Sub, + getI64Imm(1, dl), getI64Imm(63, dl)), 0); + return SDValue(CurDAG->getMachineNode(PPC::XORI, dl, + MVT::i32, Shift, getI32Imm(1, dl)), 0); + } } } @@ -2878,6 +2976,34 @@ 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); + + // Not a special case (i.e. RHS == 0). Handle (%a >= %b) as (%b <= %a) + // by swapping inputs and falling through. + 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); + SDValue SUBFNode = + SDValue(CurDAG->getMachineNode(PPC::SUBF, dl, MVT::i32, MVT::Glue, + LHS, RHS), 0); + SDValue Srdi = + SDValue(CurDAG->getMachineNode(PPC::RLDICL_32, dl, MVT::i32, + SUBFNode, getI64Imm(1, dl), + getI64Imm(63, dl)), 0); + return SDValue(CurDAG->getMachineNode(PPC::ADDI, dl, MVT::i32, Srdi, + getI32Imm(-1, dl)), 0); + } } } |

