summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>2018-02-06 14:16:52 +0000
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>2018-02-06 14:16:52 +0000
commit69f1d7e37007cdbff7ef8eb67bba392bf335a606 (patch)
tree0019cfb753123dd16862fcd204181ef396cc88fc /llvm/lib
parentae00a71f55ca7cfcefc43f5da738efed6f7c057b (diff)
downloadbcm5719-llvm-69f1d7e37007cdbff7ef8eb67bba392bf335a606.tar.gz
bcm5719-llvm-69f1d7e37007cdbff7ef8eb67bba392bf335a606.zip
[Hexagon] Handle lowering of SETCC via setCondCodeAction
It was expanded directly into instructions earlier. That was to avoid loads from a constant pool for a vector negation: "xor x, splat(i1 -1)". Implement ISD opcodes QTRUE and QFALSE to denote logical vectors of all true and all false values, and handle setcc with negations through selection patterns. llvm-svn: 324348
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLowering.cpp11
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLowering.h2
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp98
-rw-r--r--llvm/lib/Target/Hexagon/HexagonPatterns.td43
4 files changed, 82 insertions, 72 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index f026d58383d..5cee2070f18 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -2100,7 +2100,6 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::MUL, T, Custom);
setOperationAction(ISD::MULHS, T, Custom);
setOperationAction(ISD::MULHU, T, Custom);
- setOperationAction(ISD::SETCC, T, Custom);
setOperationAction(ISD::BUILD_VECTOR, T, Custom);
setOperationAction(ISD::INSERT_SUBVECTOR, T, Custom);
setOperationAction(ISD::INSERT_VECTOR_ELT, T, Custom);
@@ -2116,6 +2115,14 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SHL, T, Custom);
setOperationAction(ISD::SRL, T, Custom);
}
+
+ setCondCodeAction(ISD::SETNE, T, Expand);
+ setCondCodeAction(ISD::SETLE, T, Expand);
+ setCondCodeAction(ISD::SETGE, T, Expand);
+ setCondCodeAction(ISD::SETLT, T, Expand);
+ setCondCodeAction(ISD::SETULE, T, Expand);
+ setCondCodeAction(ISD::SETUGE, T, Expand);
+ setCondCodeAction(ISD::SETULT, T, Expand);
}
for (MVT T : LegalV) {
@@ -2303,6 +2310,8 @@ const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
case HexagonISD::P2D: return "HexagonISD::P2D";
case HexagonISD::V2Q: return "HexagonISD::V2Q";
case HexagonISD::Q2V: return "HexagonISD::Q2V";
+ case HexagonISD::QTRUE: return "HexagonISD::QTRUE";
+ case HexagonISD::QFALSE: return "HexagonISD::QFALSE";
case HexagonISD::TYPECAST: return "HexagonISD::TYPECAST";
case HexagonISD::OP_END: break;
}
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
index 59b39b7544b..200f7253f81 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
@@ -73,6 +73,8 @@ namespace HexagonISD {
// [*] The equivalence is defined as "Q <=> (V != 0)",
// where the != operation compares bytes.
// Note: V != 0 is implemented as V >u 0.
+ QTRUE,
+ QFALSE,
VZERO,
TYPECAST, // No-op that's used to convert between different legal
// types in a register.
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
index 9c0c3e0e2de..571b78ee94e 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
@@ -324,6 +324,18 @@ HexagonTargetLowering::buildHvxVectorPred(ArrayRef<SDValue> Values,
unsigned HwLen = Subtarget.getVectorLength();
assert(VecLen <= HwLen || VecLen == 8*HwLen);
SmallVector<SDValue,128> Bytes;
+ bool AllT = true, AllF = true;
+
+ auto IsTrue = [] (SDValue V) {
+ if (const auto *N = dyn_cast<ConstantSDNode>(V.getNode()))
+ return !N->isNullValue();
+ return false;
+ };
+ auto IsFalse = [] (SDValue V) {
+ if (const auto *N = dyn_cast<ConstantSDNode>(V.getNode()))
+ return N->isNullValue();
+ return false;
+ };
if (VecLen <= HwLen) {
// In the hardware, each bit of a vector predicate corresponds to a byte
@@ -332,8 +344,11 @@ HexagonTargetLowering::buildHvxVectorPred(ArrayRef<SDValue> Values,
assert(HwLen % VecLen == 0);
unsigned BitBytes = HwLen / VecLen;
for (SDValue V : Values) {
+ AllT &= IsTrue(V);
+ AllF &= IsFalse(V);
+
SDValue Ext = !V.isUndef() ? DAG.getZExtOrTrunc(V, dl, MVT::i8)
- : DAG.getConstant(0, dl, MVT::i8);
+ : DAG.getUNDEF(MVT::i8);
for (unsigned B = 0; B != BitBytes; ++B)
Bytes.push_back(Ext);
}
@@ -349,8 +364,11 @@ HexagonTargetLowering::buildHvxVectorPred(ArrayRef<SDValue> Values,
break;
}
SDValue F = Values[I+B];
+ AllT &= IsTrue(F);
+ AllF &= IsFalse(F);
+
SDValue Ext = (B < 8) ? DAG.getZExtOrTrunc(F, dl, MVT::i8)
- : DAG.getConstant(0, dl, MVT::i8);
+ : DAG.getUNDEF(MVT::i8);
Bytes.push_back(Ext);
// Verify that the rest of values in the group are the same as the
// first.
@@ -359,6 +377,11 @@ HexagonTargetLowering::buildHvxVectorPred(ArrayRef<SDValue> Values,
}
}
+ if (AllT)
+ return DAG.getNode(HexagonISD::QTRUE, dl, VecTy);
+ if (AllF)
+ return DAG.getNode(HexagonISD::QFALSE, dl, VecTy);
+
MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
return DAG.getNode(HexagonISD::V2Q, dl, VecTy, ByteVec);
@@ -1013,6 +1036,7 @@ HexagonTargetLowering::LowerHvxMulh(SDValue Op, SelectionDAG &DAG) const {
SDValue
HexagonTargetLowering::LowerHvxSetCC(SDValue Op, SelectionDAG &DAG) const {
+ MVT ResTy = ty(Op);
MVT VecTy = ty(Op.getOperand(0));
assert(VecTy == ty(Op.getOperand(1)));
unsigned HwLen = Subtarget.getVectorLength();
@@ -1024,78 +1048,14 @@ HexagonTargetLowering::LowerHvxSetCC(SDValue Op, SelectionDAG &DAG) const {
if (VecTy.getSizeInBits() == 16*HwLen) {
VectorPair P0 = opSplit(Op.getOperand(0), dl, DAG);
VectorPair P1 = opSplit(Op.getOperand(1), dl, DAG);
- MVT HalfTy = typeSplit(VecTy).first;
+ MVT HalfTy = typeSplit(ResTy).first;
SDValue V0 = DAG.getSetCC(dl, HalfTy, P0.first, P1.first, CC);
SDValue V1 = DAG.getSetCC(dl, HalfTy, P0.second, P1.second, CC);
- return DAG.getNode(ISD::CONCAT_VECTORS, dl, ty(Op), V1, V0);
+ return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResTy, V1, V0);
}
- bool Negate = false, Swap = false;
-
- // HVX has instructions for SETEQ, SETGT, SETUGT. The other comparisons
- // can be arranged as operand-swapped/negated versions of these. Since
- // the generated code will have the original CC expressed as
- // (negate (swap-op NewCmp)),
- // the condition code for the NewCmp should be calculated from the original
- // CC by applying these operations in the reverse order.
- //
- // This could also be done through setCondCodeAction, but for negation it
- // uses a xor with a vector of -1s, which it obtains from BUILD_VECTOR.
- // That is far too expensive for what can be done with a single instruction.
-
- switch (CC) {
- case ISD::SETNE: // !eq
- case ISD::SETLE: // !gt
- case ISD::SETGE: // !lt
- case ISD::SETULE: // !ugt
- case ISD::SETUGE: // !ult
- CC = ISD::getSetCCInverse(CC, true);
- Negate = true;
- break;
- default:
- break;
- }
-
- switch (CC) {
- case ISD::SETLT: // swap gt
- case ISD::SETULT: // swap ugt
- CC = ISD::getSetCCSwappedOperands(CC);
- Swap = true;
- break;
- default:
- break;
- }
-
- assert(CC == ISD::SETEQ || CC == ISD::SETGT || CC == ISD::SETUGT);
-
- MVT ElemTy = VecTy.getVectorElementType();
- unsigned ElemWidth = ElemTy.getSizeInBits();
- assert(isPowerOf2_32(ElemWidth));
-
- auto getIdx = [] (unsigned Code) {
- static const unsigned Idx[] = { ISD::SETEQ, ISD::SETGT, ISD::SETUGT };
- for (unsigned I = 0, E = array_lengthof(Idx); I != E; ++I)
- if (Code == Idx[I])
- return I;
- llvm_unreachable("Unhandled CondCode");
- };
-
- static unsigned OpcTable[3][3] = {
- // SETEQ SETGT, SETUGT
- /* Byte */ { Hexagon::V6_veqb, Hexagon::V6_vgtb, Hexagon::V6_vgtub },
- /* Half */ { Hexagon::V6_veqh, Hexagon::V6_vgth, Hexagon::V6_vgtuh },
- /* Word */ { Hexagon::V6_veqw, Hexagon::V6_vgtw, Hexagon::V6_vgtuw }
- };
-
- unsigned CmpOpc = OpcTable[Log2_32(ElemWidth)-3][getIdx(CC)];
-
- MVT ResTy = ty(Op);
- SDValue OpL = Swap ? Op.getOperand(1) : Op.getOperand(0);
- SDValue OpR = Swap ? Op.getOperand(0) : Op.getOperand(1);
- SDValue CmpV = getInstr(CmpOpc, dl, ResTy, {OpL, OpR}, DAG);
- return Negate ? getInstr(Hexagon::V6_pred_not, dl, ResTy, {CmpV}, DAG)
- : CmpV;
+ return SDValue();
}
SDValue
diff --git a/llvm/lib/Target/Hexagon/HexagonPatterns.td b/llvm/lib/Target/Hexagon/HexagonPatterns.td
index 06e23e24991..31aac6c1e23 100644
--- a/llvm/lib/Target/Hexagon/HexagonPatterns.td
+++ b/llvm/lib/Target/Hexagon/HexagonPatterns.td
@@ -2993,8 +2993,14 @@ def Combinev: OutPatFrag<(ops node:$Rs, node:$Rt),
def LoVec: OutPatFrag<(ops node:$Vs), (EXTRACT_SUBREG $Vs, vsub_lo)>;
def HiVec: OutPatFrag<(ops node:$Vs), (EXTRACT_SUBREG $Vs, vsub_hi)>;
-def HexagonVZERO: SDNode<"HexagonISD::VZERO", SDTVecLeaf>;
-def vzero: PatFrag<(ops), (HexagonVZERO)>;
+def HexagonVZERO: SDNode<"HexagonISD::VZERO", SDTVecLeaf>;
+def HexagonQTRUE: SDNode<"HexagonISD::QTRUE", SDTVecLeaf>;
+def HexagonQFALSE: SDNode<"HexagonISD::QFALSE", SDTVecLeaf>;
+def vzero: PatFrag<(ops), (HexagonVZERO)>;
+def qtrue: PatFrag<(ops), (HexagonQTRUE)>;
+def qfalse: PatFrag<(ops), (HexagonQFALSE)>;
+
+def qnot: PatFrag<(ops node:$Qs), (xor node:$Qs, qtrue)>;
def VSxtb: OutPatFrag<(ops node:$Vs), (V6_vunpackb $Vs)>;
def VSxth: OutPatFrag<(ops node:$Vs), (V6_vunpackh $Vs)>;
@@ -3074,6 +3080,13 @@ let Predicates = [UseHVX] in {
def: Pat<(vselect HQ32:$Qu, HVI32:$Vs, HVI32:$Vt),
(V6_vmux HvxQR:$Qu, HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(vselect (qnot HQ8:$Qu), HVI8:$Vs, HVI8:$Vt),
+ (V6_vmux HvxQR:$Qu, HvxVR:$Vt, HvxVR:$Vs)>;
+ def: Pat<(vselect (qnot HQ16:$Qu), HVI16:$Vs, HVI16:$Vt),
+ (V6_vmux HvxQR:$Qu, HvxVR:$Vt, HvxVR:$Vs)>;
+ def: Pat<(vselect (qnot HQ32:$Qu), HVI32:$Vs, HVI32:$Vt),
+ (V6_vmux HvxQR:$Qu, HvxVR:$Vt, HvxVR:$Vs)>;
+
def: Pat<(VecPI16 (sext HVI8:$Vs)), (VSxtb $Vs)>;
def: Pat<(VecPI32 (sext HVI16:$Vs)), (VSxth $Vs)>;
def: Pat<(VecPI16 (zext HVI8:$Vs)), (VZxtb $Vs)>;
@@ -3122,6 +3135,32 @@ let Predicates = [UseHVX] in {
def: Pat<(srl HVI16:$Vs, HVI16:$Vt), (V6_vlsrhv HvxVR:$Vs, HvxVR:$Vt)>;
def: Pat<(srl HVI32:$Vs, HVI32:$Vt), (V6_vlsrwv HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(vnot HQ8:$Qs), (V6_pred_not HvxQR:$Qs)>;
+ def: Pat<(vnot HQ16:$Qs), (V6_pred_not HvxQR:$Qs)>;
+ def: Pat<(vnot HQ32:$Qs), (V6_pred_not HvxQR:$Qs)>;
+ def: Pat<(qnot HQ8:$Qs), (V6_pred_not HvxQR:$Qs)>;
+ def: Pat<(qnot HQ16:$Qs), (V6_pred_not HvxQR:$Qs)>;
+ def: Pat<(qnot HQ32:$Qs), (V6_pred_not HvxQR:$Qs)>;
+
+ def: Pat<(VecQ8 (seteq HVI8:$Vs, HVI8:$Vt)),
+ (V6_veqb HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(VecQ8 (setgt HVI8:$Vs, HVI8:$Vt)),
+ (V6_vgtb HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(VecQ8 (setugt HVI8:$Vs, HVI8:$Vt)),
+ (V6_vgtub HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(VecQ16 (seteq HVI16:$Vs, HVI16:$Vt)),
+ (V6_veqh HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(VecQ16 (setgt HVI16:$Vs, HVI16:$Vt)),
+ (V6_vgth HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(VecQ16 (setugt HVI16:$Vs, HVI16:$Vt)),
+ (V6_vgtuh HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(VecQ32 (seteq HVI32:$Vs, HVI32:$Vt)),
+ (V6_veqw HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(VecQ32 (setgt HVI32:$Vs, HVI32:$Vt)),
+ (V6_vgtw HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(VecQ32 (setugt HVI32:$Vs, HVI32:$Vt)),
+ (V6_vgtuw HvxVR:$Vs, HvxVR:$Vt)>;
+
def: Pat<(VecI8 (trunc HWI16:$Vss)),
(V6_vpackeb (HiVec $Vss), (LoVec $Vss))>;
def: Pat<(VecI16 (trunc HWI32:$Vss)),
OpenPOWER on IntegriCloud