summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/PowerPC
diff options
context:
space:
mode:
authorNemanja Ivanovic <nemanja.i.ibm@gmail.com>2017-08-08 11:20:44 +0000
committerNemanja Ivanovic <nemanja.i.ibm@gmail.com>2017-08-08 11:20:44 +0000
commit809fbfa6a16e3d3cf5df46c068e6f72dfe6f46ba (patch)
tree40d05c631ce45641242c2b926c8900235d24fbcc /llvm/lib/Target/PowerPC
parent7e9c478cda26a71dc4efbf96183738171eb9b721 (diff)
downloadbcm5719-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.cpp126
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);
+ }
}
}
OpenPOWER on IntegriCloud