summaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp')
-rw-r--r--contrib/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp134
1 files changed, 108 insertions, 26 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
index c1d44cb0e7de..51480d09d734 100644
--- a/contrib/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
+++ b/contrib/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
@@ -141,49 +141,50 @@ HexagonTargetLowering::getByteShuffle(const SDLoc &dl, SDValue Op0,
opCastElem(Op1, MVT::i8, DAG), ByteMask);
}
+MVT
+HexagonTargetLowering::getVecBoolVT() const {
+ return MVT::getVectorVT(MVT::i1, 8*Subtarget.getVectorLength());
+}
+
SDValue
-HexagonTargetLowering::LowerHvxBuildVector(SDValue Op, SelectionDAG &DAG)
- const {
- const SDLoc &dl(Op);
- BuildVectorSDNode *BN = cast<BuildVectorSDNode>(Op.getNode());
- bool IsConst = BN->isConstant();
+HexagonTargetLowering::buildHvxVectorSingle(ArrayRef<SDValue> Values,
+ const SDLoc &dl, MVT VecTy,
+ SelectionDAG &DAG) const {
+ unsigned VecLen = Values.size();
MachineFunction &MF = DAG.getMachineFunction();
- MVT VecTy = ty(Op);
+ MVT ElemTy = VecTy.getVectorElementType();
+ unsigned ElemWidth = ElemTy.getSizeInBits();
+ unsigned HwLen = Subtarget.getVectorLength();
- if (IsConst) {
- SmallVector<Constant*, 128> Elems;
- for (SDValue V : BN->op_values()) {
- if (auto *C = dyn_cast<ConstantSDNode>(V.getNode()))
- Elems.push_back(const_cast<ConstantInt*>(C->getConstantIntValue()));
- }
- Constant *CV = ConstantVector::get(Elems);
- unsigned Align = VecTy.getSizeInBits() / 8;
+ SmallVector<ConstantInt*, 128> Consts(VecLen);
+ bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
+ if (AllConst) {
+ if (llvm::all_of(Consts, [](ConstantInt *CI) { return CI->isZero(); }))
+ return getZero(dl, VecTy, DAG);
+
+ ArrayRef<Constant*> Tmp((Constant**)Consts.begin(),
+ (Constant**)Consts.end());
+ Constant *CV = ConstantVector::get(Tmp);
+ unsigned Align = HwLen;
SDValue CP = LowerConstantPool(DAG.getConstantPool(CV, VecTy, Align), DAG);
return DAG.getLoad(VecTy, dl, DAG.getEntryNode(), CP,
MachinePointerInfo::getConstantPool(MF), Align);
}
- unsigned NumOps = Op.getNumOperands();
- unsigned HwLen = Subtarget.getVectorLength();
- unsigned ElemSize = VecTy.getVectorElementType().getSizeInBits() / 8;
- assert(ElemSize*NumOps == HwLen);
-
+ unsigned ElemSize = ElemWidth / 8;
+ assert(ElemSize*VecLen == HwLen);
SmallVector<SDValue,32> Words;
- SmallVector<SDValue,32> Ops;
- for (unsigned i = 0; i != NumOps; ++i)
- Ops.push_back(Op.getOperand(i));
if (VecTy.getVectorElementType() != MVT::i32) {
- assert(ElemSize < 4 && "vNi64 should have been promoted to vNi32");
assert((ElemSize == 1 || ElemSize == 2) && "Invalid element size");
unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
MVT PartVT = MVT::getVectorVT(VecTy.getVectorElementType(), OpsPerWord);
- for (unsigned i = 0; i != NumOps; i += OpsPerWord) {
- SDValue W = buildVector32({&Ops[i], OpsPerWord}, dl, PartVT, DAG);
+ for (unsigned i = 0; i != VecLen; i += OpsPerWord) {
+ SDValue W = buildVector32(Values.slice(i, OpsPerWord), dl, PartVT, DAG);
Words.push_back(DAG.getBitcast(MVT::i32, W));
}
} else {
- Words.assign(Ops.begin(), Ops.end());
+ Words.assign(Values.begin(), Values.end());
}
// Construct two halves in parallel, then or them together.
@@ -208,6 +209,83 @@ HexagonTargetLowering::LowerHvxBuildVector(SDValue Op, SelectionDAG &DAG)
}
SDValue
+HexagonTargetLowering::buildHvxVectorPred(ArrayRef<SDValue> Values,
+ const SDLoc &dl, MVT VecTy,
+ SelectionDAG &DAG) const {
+ // Construct a vector V of bytes, such that a comparison V >u 0 would
+ // produce the required vector predicate.
+ unsigned VecLen = Values.size();
+ unsigned HwLen = Subtarget.getVectorLength();
+ assert(VecLen <= HwLen || VecLen == 8*HwLen);
+ SmallVector<SDValue,128> Bytes;
+
+ if (VecLen <= HwLen) {
+ // In the hardware, each bit of a vector predicate corresponds to a byte
+ // of a vector register. Calculate how many bytes does a bit of VecTy
+ // correspond to.
+ assert(HwLen % VecLen == 0);
+ unsigned BitBytes = HwLen / VecLen;
+ for (SDValue V : Values) {
+ SDValue Ext = !V.isUndef() ? DAG.getZExtOrTrunc(V, dl, MVT::i8)
+ : DAG.getConstant(0, dl, MVT::i8);
+ for (unsigned B = 0; B != BitBytes; ++B)
+ Bytes.push_back(Ext);
+ }
+ } else {
+ // There are as many i1 values, as there are bits in a vector register.
+ // Divide the values into groups of 8 and check that each group consists
+ // of the same value (ignoring undefs).
+ for (unsigned I = 0; I != VecLen; I += 8) {
+ unsigned B = 0;
+ // Find the first non-undef value in this group.
+ for (; B != 8; ++B) {
+ if (!Values[I+B].isUndef())
+ break;
+ }
+ SDValue F = Values[I+B];
+ SDValue Ext = (B < 8) ? DAG.getZExtOrTrunc(F, dl, MVT::i8)
+ : DAG.getConstant(0, dl, MVT::i8);
+ Bytes.push_back(Ext);
+ // Verify that the rest of values in the group are the same as the
+ // first.
+ for (; B != 8; ++B)
+ assert(Values[I+B].isUndef() || Values[I+B] == F);
+ }
+ }
+
+ MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
+ SDValue ByteVec = buildHvxVectorSingle(Bytes, dl, ByteTy, DAG);
+ SDValue Cmp = DAG.getSetCC(dl, VecTy, ByteVec, getZero(dl, ByteTy, DAG),
+ ISD::SETUGT);
+ return Cmp;
+}
+
+SDValue
+HexagonTargetLowering::LowerHvxBuildVector(SDValue Op, SelectionDAG &DAG)
+ const {
+ const SDLoc &dl(Op);
+ MVT VecTy = ty(Op);
+
+ unsigned Size = Op.getNumOperands();
+ SmallVector<SDValue,128> Ops;
+ for (unsigned i = 0; i != Size; ++i)
+ Ops.push_back(Op.getOperand(i));
+
+ if (VecTy.getVectorElementType() == MVT::i1)
+ return buildHvxVectorPred(Ops, dl, VecTy, DAG);
+
+ if (VecTy.getSizeInBits() == 16*Subtarget.getVectorLength()) {
+ ArrayRef<SDValue> A(Ops);
+ MVT SingleTy = typeSplit(VecTy).first;
+ SDValue V0 = buildHvxVectorSingle(A.take_front(Size/2), dl, SingleTy, DAG);
+ SDValue V1 = buildHvxVectorSingle(A.drop_front(Size/2), dl, SingleTy, DAG);
+ return DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, V0, V1);
+ }
+
+ return buildHvxVectorSingle(Ops, dl, VecTy, DAG);
+}
+
+SDValue
HexagonTargetLowering::LowerHvxExtractElement(SDValue Op, SelectionDAG &DAG)
const {
// Change the type of the extracted element to i32.
@@ -399,6 +477,10 @@ HexagonTargetLowering::LowerHvxSetCC(SDValue Op, SelectionDAG &DAG) const {
// (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