forked from OSchip/llvm-project
[Hexagon] Extract HVX lowering and selection into HVX-specific files, NFC
llvm-svn: 324392
This commit is contained in:
parent
97a5095db6
commit
8abaf8954a
|
@ -302,6 +302,7 @@ include "HexagonDepInstrFormats.td"
|
|||
include "HexagonDepInstrInfo.td"
|
||||
include "HexagonPseudo.td"
|
||||
include "HexagonPatterns.td"
|
||||
include "HexagonPatternsHVX.td"
|
||||
include "HexagonPatternsV65.td"
|
||||
include "HexagonDepMappings.td"
|
||||
include "HexagonIntrinsics.td"
|
||||
|
|
|
@ -129,11 +129,6 @@ namespace {
|
|||
|
||||
// Implement calling convention for Hexagon.
|
||||
|
||||
static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
|
||||
static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
|
||||
static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
|
||||
static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };
|
||||
|
||||
static bool
|
||||
CC_Hexagon(unsigned ValNo, MVT ValVT,
|
||||
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||
|
@ -1732,40 +1727,6 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
|
|||
addRegisterClass(MVT::f64, &Hexagon::DoubleRegsRegClass);
|
||||
}
|
||||
|
||||
if (Subtarget.hasV60TOps()) {
|
||||
if (Subtarget.useHVX64BOps()) {
|
||||
addRegisterClass(MVT::v64i8, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v32i16, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v16i32, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v128i8, &Hexagon::HvxWRRegClass);
|
||||
addRegisterClass(MVT::v64i16, &Hexagon::HvxWRRegClass);
|
||||
addRegisterClass(MVT::v32i32, &Hexagon::HvxWRRegClass);
|
||||
// These "short" boolean vector types should be legal because
|
||||
// they will appear as results of vector compares. If they were
|
||||
// not legal, type legalization would try to make them legal
|
||||
// and that would require using operations that do not use or
|
||||
// produce such types. That, in turn, would imply using custom
|
||||
// nodes, which would be unoptimizable by the DAG combiner.
|
||||
// The idea is to rely on target-independent operations as much
|
||||
// as possible.
|
||||
addRegisterClass(MVT::v16i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v512i1, &Hexagon::HvxQRRegClass);
|
||||
} else if (Subtarget.useHVX128BOps()) {
|
||||
addRegisterClass(MVT::v128i8, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v64i16, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v32i32, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v256i8, &Hexagon::HvxWRRegClass);
|
||||
addRegisterClass(MVT::v128i16, &Hexagon::HvxWRRegClass);
|
||||
addRegisterClass(MVT::v64i32, &Hexagon::HvxWRRegClass);
|
||||
addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v128i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v1024i1, &Hexagon::HvxQRRegClass);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Handling of scalar operations.
|
||||
//
|
||||
|
@ -2002,11 +1963,6 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
|
|||
setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v4i16, Custom);
|
||||
setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v8i8, Custom);
|
||||
|
||||
auto setPromoteTo = [this] (unsigned Opc, MVT FromTy, MVT ToTy) {
|
||||
setOperationAction(Opc, FromTy, Promote);
|
||||
AddPromotedToType(Opc, FromTy, ToTy);
|
||||
};
|
||||
|
||||
// Subtarget-specific operation actions.
|
||||
//
|
||||
if (Subtarget.hasV5TOps()) {
|
||||
|
@ -2068,121 +2024,8 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
|
|||
setIndexedStoreAction(ISD::POST_INC, VT, Legal);
|
||||
}
|
||||
|
||||
if (Subtarget.useHVXOps()) {
|
||||
bool Use64b = Subtarget.useHVX64BOps();
|
||||
ArrayRef<MVT> LegalV = Use64b ? LegalV64 : LegalV128;
|
||||
ArrayRef<MVT> LegalW = Use64b ? LegalW64 : LegalW128;
|
||||
MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
|
||||
MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
|
||||
|
||||
setOperationAction(ISD::VECTOR_SHUFFLE, ByteV, Legal);
|
||||
setOperationAction(ISD::VECTOR_SHUFFLE, ByteW, Legal);
|
||||
setOperationAction(ISD::AND, ByteV, Legal);
|
||||
setOperationAction(ISD::OR, ByteV, Legal);
|
||||
setOperationAction(ISD::XOR, ByteV, Legal);
|
||||
|
||||
for (MVT T : LegalV) {
|
||||
setIndexedLoadAction(ISD::POST_INC, T, Legal);
|
||||
setIndexedStoreAction(ISD::POST_INC, T, Legal);
|
||||
|
||||
setOperationAction(ISD::ADD, T, Legal);
|
||||
setOperationAction(ISD::SUB, T, Legal);
|
||||
if (T != ByteV) {
|
||||
setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal);
|
||||
setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal);
|
||||
}
|
||||
|
||||
setOperationAction(ISD::MUL, T, Custom);
|
||||
setOperationAction(ISD::MULHS, T, Custom);
|
||||
setOperationAction(ISD::MULHU, T, Custom);
|
||||
setOperationAction(ISD::BUILD_VECTOR, T, Custom);
|
||||
// Make concat-vectors custom to handle concats of more than 2 vectors.
|
||||
setOperationAction(ISD::CONCAT_VECTORS, T, Custom);
|
||||
setOperationAction(ISD::INSERT_SUBVECTOR, T, Custom);
|
||||
setOperationAction(ISD::INSERT_VECTOR_ELT, T, Custom);
|
||||
setOperationAction(ISD::EXTRACT_SUBVECTOR, T, Custom);
|
||||
setOperationAction(ISD::EXTRACT_VECTOR_ELT, T, Custom);
|
||||
setOperationAction(ISD::ANY_EXTEND, T, Custom);
|
||||
setOperationAction(ISD::SIGN_EXTEND, T, Custom);
|
||||
setOperationAction(ISD::ZERO_EXTEND, T, Custom);
|
||||
if (T != ByteV) {
|
||||
setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom);
|
||||
// HVX only has shifts of words and halfwords.
|
||||
setOperationAction(ISD::SRA, T, Custom);
|
||||
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) {
|
||||
MVT BoolV = MVT::getVectorVT(MVT::i1, T.getVectorNumElements());
|
||||
setOperationAction(ISD::BUILD_VECTOR, BoolV, Custom);
|
||||
setOperationAction(ISD::CONCAT_VECTORS, BoolV, Custom);
|
||||
setOperationAction(ISD::INSERT_SUBVECTOR, BoolV, Custom);
|
||||
setOperationAction(ISD::INSERT_VECTOR_ELT, BoolV, Custom);
|
||||
setOperationAction(ISD::EXTRACT_SUBVECTOR, BoolV, Custom);
|
||||
setOperationAction(ISD::EXTRACT_VECTOR_ELT, BoolV, Custom);
|
||||
}
|
||||
|
||||
for (MVT T : LegalV) {
|
||||
if (T == ByteV)
|
||||
continue;
|
||||
// Promote all shuffles to operate on vectors of bytes.
|
||||
setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteV);
|
||||
setPromoteTo(ISD::AND, T, ByteV);
|
||||
setPromoteTo(ISD::OR, T, ByteV);
|
||||
setPromoteTo(ISD::XOR, T, ByteV);
|
||||
}
|
||||
|
||||
for (MVT T : LegalW) {
|
||||
// Custom-lower BUILD_VECTOR for vector pairs. The standard (target-
|
||||
// independent) handling of it would convert it to a load, which is
|
||||
// not always the optimal choice.
|
||||
setOperationAction(ISD::BUILD_VECTOR, T, Custom);
|
||||
// Make concat-vectors custom to handle concats of more than 2 vectors.
|
||||
setOperationAction(ISD::CONCAT_VECTORS, T, Custom);
|
||||
|
||||
// Custom-lower these operations for pairs. Expand them into a concat
|
||||
// of the corresponding operations on individual vectors.
|
||||
setOperationAction(ISD::ANY_EXTEND, T, Custom);
|
||||
setOperationAction(ISD::SIGN_EXTEND, T, Custom);
|
||||
setOperationAction(ISD::ZERO_EXTEND, T, Custom);
|
||||
setOperationAction(ISD::SIGN_EXTEND_INREG, T, Custom);
|
||||
setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom);
|
||||
setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal);
|
||||
setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal);
|
||||
|
||||
setOperationAction(ISD::ADD, T, Legal);
|
||||
setOperationAction(ISD::SUB, T, Legal);
|
||||
setOperationAction(ISD::MUL, T, Custom);
|
||||
setOperationAction(ISD::MULHS, T, Custom);
|
||||
setOperationAction(ISD::MULHU, T, Custom);
|
||||
setOperationAction(ISD::AND, T, Custom);
|
||||
setOperationAction(ISD::OR, T, Custom);
|
||||
setOperationAction(ISD::XOR, T, Custom);
|
||||
setOperationAction(ISD::SETCC, T, Custom);
|
||||
setOperationAction(ISD::VSELECT, T, Custom);
|
||||
if (T != ByteW) {
|
||||
setOperationAction(ISD::SRA, T, Custom);
|
||||
setOperationAction(ISD::SHL, T, Custom);
|
||||
setOperationAction(ISD::SRL, T, Custom);
|
||||
|
||||
// Promote all shuffles to operate on vectors of bytes.
|
||||
setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteW);
|
||||
}
|
||||
|
||||
MVT BoolV = MVT::getVectorVT(MVT::i1, T.getVectorNumElements());
|
||||
setOperationAction(ISD::SETCC, BoolV, Custom);
|
||||
}
|
||||
}
|
||||
if (Subtarget.useHVXOps())
|
||||
initializeHVXLowering();
|
||||
|
||||
computeRegisterProperties(&HRI);
|
||||
|
||||
|
@ -2444,6 +2287,8 @@ HexagonTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
|
|||
unsigned VecLen = AM.size();
|
||||
|
||||
MVT VecTy = ty(Op);
|
||||
assert(!Subtarget.isHVXVectorType(VecTy, true) &&
|
||||
"HVX shuffles should be legal");
|
||||
assert(VecTy.getSizeInBits() <= 64 && "Unexpected vector length");
|
||||
|
||||
SDValue Op0 = Op.getOperand(0);
|
||||
|
@ -2559,13 +2404,10 @@ HexagonTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
|
|||
return SDValue();
|
||||
}
|
||||
|
||||
// Lower a vector shift. Try to convert
|
||||
// <VT> = SHL/SRA/SRL <VT> by <VT> to Hexagon specific
|
||||
// <VT> = SHL/SRA/SRL <VT> by <IT/i32>.
|
||||
// Create a Hexagon-specific node for shifting a vector by an integer.
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerVECTOR_SHIFT(SDValue Op, SelectionDAG &DAG) const {
|
||||
const SDLoc dl(Op);
|
||||
|
||||
HexagonTargetLowering::getVectorShiftByInt(SDValue Op, SelectionDAG &DAG)
|
||||
const {
|
||||
if (auto *BVN = dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode())) {
|
||||
if (SDValue S = BVN->getSplatValue()) {
|
||||
unsigned NewOpc;
|
||||
|
@ -2582,16 +2424,18 @@ HexagonTargetLowering::LowerVECTOR_SHIFT(SDValue Op, SelectionDAG &DAG) const {
|
|||
default:
|
||||
llvm_unreachable("Unexpected shift opcode");
|
||||
}
|
||||
return DAG.getNode(NewOpc, dl, ty(Op), Op.getOperand(0), S);
|
||||
return DAG.getNode(NewOpc, SDLoc(Op), ty(Op), Op.getOperand(0), S);
|
||||
}
|
||||
}
|
||||
|
||||
if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(ty(Op)))
|
||||
return LowerHvxShift(Op, DAG);
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerVECTOR_SHIFT(SDValue Op, SelectionDAG &DAG) const {
|
||||
return getVectorShiftByInt(Op, DAG);
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerBITCAST(SDValue Op, SelectionDAG &DAG) const {
|
||||
MVT ResTy = ty(Op);
|
||||
|
@ -2610,43 +2454,6 @@ HexagonTargetLowering::LowerBITCAST(SDValue Op, SelectionDAG &DAG) const {
|
|||
return SDValue();
|
||||
}
|
||||
|
||||
// Any-, sign-, and zero-extends of boolean vectors to integer types are
|
||||
// all the same.
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerANY_EXTEND(SDValue Op, SelectionDAG &DAG) const {
|
||||
// Lower any-extends of boolean vectors to sign-extends, since they
|
||||
// translate directly to Q2V. Zero-extending could also be done equally
|
||||
// fast, but Q2V is used/recognized in more places.
|
||||
// For all other vectors, use zero-extend.
|
||||
MVT ResTy = ty(Op);
|
||||
SDValue InpV = Op.getOperand(0);
|
||||
MVT ElemTy = ty(InpV).getVectorElementType();
|
||||
if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
|
||||
return LowerSIGN_EXTEND(Op, DAG);
|
||||
return DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Op), ResTy, InpV);
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG) const {
|
||||
MVT ResTy = ty(Op);
|
||||
SDValue InpV = Op.getOperand(0);
|
||||
MVT ElemTy = ty(InpV).getVectorElementType();
|
||||
if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
|
||||
return extendHvxVectorPred(InpV, SDLoc(Op), ty(Op), false, DAG);
|
||||
return Op;
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerZERO_EXTEND(SDValue Op, SelectionDAG &DAG) const {
|
||||
MVT ResTy = ty(Op);
|
||||
SDValue InpV = Op.getOperand(0);
|
||||
MVT ElemTy = ty(InpV).getVectorElementType();
|
||||
if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
|
||||
return extendHvxVectorPred(InpV, SDLoc(Op), ty(Op), true, DAG);
|
||||
return Op;
|
||||
}
|
||||
|
||||
bool
|
||||
HexagonTargetLowering::getBuildVectorConstInts(ArrayRef<SDValue> Values,
|
||||
MVT VecTy, SelectionDAG &DAG,
|
||||
|
@ -3022,9 +2829,6 @@ HexagonTargetLowering::getZero(const SDLoc &dl, MVT Ty, SelectionDAG &DAG)
|
|||
SDValue
|
||||
HexagonTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
|
||||
MVT VecTy = ty(Op);
|
||||
if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy, true))
|
||||
return LowerHvxBuildVector(Op, DAG);
|
||||
|
||||
unsigned BW = VecTy.getSizeInBits();
|
||||
const SDLoc &dl(Op);
|
||||
SmallVector<SDValue,8> Ops;
|
||||
|
@ -3064,9 +2868,6 @@ HexagonTargetLowering::LowerCONCAT_VECTORS(SDValue Op,
|
|||
SelectionDAG &DAG) const {
|
||||
MVT VecTy = ty(Op);
|
||||
const SDLoc &dl(Op);
|
||||
if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy, true))
|
||||
return LowerHvxConcatVectors(Op, DAG);
|
||||
|
||||
if (VecTy.getSizeInBits() == 64) {
|
||||
assert(Op.getNumOperands() == 2);
|
||||
return DAG.getNode(HexagonISD::COMBINE, dl, VecTy, Op.getOperand(1),
|
||||
|
@ -3131,10 +2932,6 @@ SDValue
|
|||
HexagonTargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
SDValue Vec = Op.getOperand(0);
|
||||
MVT VecTy = ty(Vec);
|
||||
if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy, true))
|
||||
return LowerHvxExtractElement(Op, DAG);
|
||||
|
||||
MVT ElemTy = ty(Vec).getVectorElementType();
|
||||
return extractVector(Vec, Op.getOperand(1), SDLoc(Op), ElemTy, ty(Op), DAG);
|
||||
}
|
||||
|
@ -3142,31 +2939,20 @@ HexagonTargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op,
|
|||
SDValue
|
||||
HexagonTargetLowering::LowerEXTRACT_SUBVECTOR(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
SDValue Vec = Op.getOperand(0);
|
||||
MVT VecTy = ty(Vec);
|
||||
if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy, true))
|
||||
return LowerHvxExtractSubvector(Op, DAG);
|
||||
|
||||
return extractVector(Vec, Op.getOperand(1), SDLoc(Op), ty(Op), ty(Op), DAG);
|
||||
return extractVector(Op.getOperand(0), Op.getOperand(1), SDLoc(Op),
|
||||
ty(Op), ty(Op), DAG);
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
MVT VecTy = ty(Op);
|
||||
if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy, true))
|
||||
return LowerHvxInsertElement(Op, DAG);
|
||||
|
||||
return insertVector(Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
|
||||
SDLoc(Op), VecTy.getVectorElementType(), DAG);
|
||||
SDLoc(Op), ty(Op).getVectorElementType(), DAG);
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerINSERT_SUBVECTOR(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(ty(Op), true))
|
||||
return LowerHvxInsertSubvector(Op, DAG);
|
||||
|
||||
SDValue ValV = Op.getOperand(1);
|
||||
return insertVector(Op.getOperand(0), ValV, Op.getOperand(2),
|
||||
SDLoc(Op), ty(ValV), DAG);
|
||||
|
|
|
@ -298,6 +298,8 @@ namespace HexagonISD {
|
|||
}
|
||||
|
||||
private:
|
||||
void initializeHVXLowering();
|
||||
|
||||
bool getBuildVectorConstInts(ArrayRef<SDValue> Values, MVT VecTy,
|
||||
SelectionDAG &DAG,
|
||||
MutableArrayRef<ConstantInt*> Consts) const;
|
||||
|
@ -313,6 +315,7 @@ namespace HexagonISD {
|
|||
SelectionDAG &DAG) const;
|
||||
SDValue contractPredicate(SDValue Vec64, const SDLoc &dl,
|
||||
SelectionDAG &DAG) const;
|
||||
SDValue getVectorShiftByInt(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
bool isUndef(SDValue Op) const {
|
||||
if (Op.isMachineOpcode())
|
||||
|
@ -403,6 +406,10 @@ namespace HexagonISD {
|
|||
SDValue LowerHvxInsertElement(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerHvxExtractSubvector(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerHvxInsertSubvector(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
SDValue LowerHvxAnyExt(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerHvxSignExt(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerHvxZeroExt(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerHvxMul(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerHvxMulh(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerHvxSetCC(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
|
|
@ -13,6 +13,168 @@
|
|||
|
||||
using namespace llvm;
|
||||
|
||||
static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
|
||||
static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
|
||||
static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
|
||||
static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };
|
||||
|
||||
|
||||
void
|
||||
HexagonTargetLowering::initializeHVXLowering() {
|
||||
if (Subtarget.useHVX64BOps()) {
|
||||
addRegisterClass(MVT::v64i8, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v32i16, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v16i32, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v128i8, &Hexagon::HvxWRRegClass);
|
||||
addRegisterClass(MVT::v64i16, &Hexagon::HvxWRRegClass);
|
||||
addRegisterClass(MVT::v32i32, &Hexagon::HvxWRRegClass);
|
||||
// These "short" boolean vector types should be legal because
|
||||
// they will appear as results of vector compares. If they were
|
||||
// not legal, type legalization would try to make them legal
|
||||
// and that would require using operations that do not use or
|
||||
// produce such types. That, in turn, would imply using custom
|
||||
// nodes, which would be unoptimizable by the DAG combiner.
|
||||
// The idea is to rely on target-independent operations as much
|
||||
// as possible.
|
||||
addRegisterClass(MVT::v16i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v512i1, &Hexagon::HvxQRRegClass);
|
||||
} else if (Subtarget.useHVX128BOps()) {
|
||||
addRegisterClass(MVT::v128i8, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v64i16, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v32i32, &Hexagon::HvxVRRegClass);
|
||||
addRegisterClass(MVT::v256i8, &Hexagon::HvxWRRegClass);
|
||||
addRegisterClass(MVT::v128i16, &Hexagon::HvxWRRegClass);
|
||||
addRegisterClass(MVT::v64i32, &Hexagon::HvxWRRegClass);
|
||||
addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v128i1, &Hexagon::HvxQRRegClass);
|
||||
addRegisterClass(MVT::v1024i1, &Hexagon::HvxQRRegClass);
|
||||
}
|
||||
|
||||
// Set up operation actions.
|
||||
|
||||
bool Use64b = Subtarget.useHVX64BOps();
|
||||
ArrayRef<MVT> LegalV = Use64b ? LegalV64 : LegalV128;
|
||||
ArrayRef<MVT> LegalW = Use64b ? LegalW64 : LegalW128;
|
||||
MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
|
||||
MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
|
||||
|
||||
auto setPromoteTo = [this] (unsigned Opc, MVT FromTy, MVT ToTy) {
|
||||
setOperationAction(Opc, FromTy, Promote);
|
||||
AddPromotedToType(Opc, FromTy, ToTy);
|
||||
};
|
||||
|
||||
setOperationAction(ISD::VECTOR_SHUFFLE, ByteV, Legal);
|
||||
setOperationAction(ISD::VECTOR_SHUFFLE, ByteW, Legal);
|
||||
setOperationAction(ISD::AND, ByteV, Legal);
|
||||
setOperationAction(ISD::OR, ByteV, Legal);
|
||||
setOperationAction(ISD::XOR, ByteV, Legal);
|
||||
|
||||
for (MVT T : LegalV) {
|
||||
setIndexedLoadAction(ISD::POST_INC, T, Legal);
|
||||
setIndexedStoreAction(ISD::POST_INC, T, Legal);
|
||||
|
||||
setOperationAction(ISD::ADD, T, Legal);
|
||||
setOperationAction(ISD::SUB, T, Legal);
|
||||
if (T != ByteV) {
|
||||
setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal);
|
||||
setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal);
|
||||
}
|
||||
|
||||
setOperationAction(ISD::MUL, T, Custom);
|
||||
setOperationAction(ISD::MULHS, T, Custom);
|
||||
setOperationAction(ISD::MULHU, T, Custom);
|
||||
setOperationAction(ISD::BUILD_VECTOR, T, Custom);
|
||||
// Make concat-vectors custom to handle concats of more than 2 vectors.
|
||||
setOperationAction(ISD::CONCAT_VECTORS, T, Custom);
|
||||
setOperationAction(ISD::INSERT_SUBVECTOR, T, Custom);
|
||||
setOperationAction(ISD::INSERT_VECTOR_ELT, T, Custom);
|
||||
setOperationAction(ISD::EXTRACT_SUBVECTOR, T, Custom);
|
||||
setOperationAction(ISD::EXTRACT_VECTOR_ELT, T, Custom);
|
||||
setOperationAction(ISD::ANY_EXTEND, T, Custom);
|
||||
setOperationAction(ISD::SIGN_EXTEND, T, Custom);
|
||||
setOperationAction(ISD::ZERO_EXTEND, T, Custom);
|
||||
if (T != ByteV) {
|
||||
setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom);
|
||||
// HVX only has shifts of words and halfwords.
|
||||
setOperationAction(ISD::SRA, T, Custom);
|
||||
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) {
|
||||
MVT BoolV = MVT::getVectorVT(MVT::i1, T.getVectorNumElements());
|
||||
setOperationAction(ISD::BUILD_VECTOR, BoolV, Custom);
|
||||
setOperationAction(ISD::CONCAT_VECTORS, BoolV, Custom);
|
||||
setOperationAction(ISD::INSERT_SUBVECTOR, BoolV, Custom);
|
||||
setOperationAction(ISD::INSERT_VECTOR_ELT, BoolV, Custom);
|
||||
setOperationAction(ISD::EXTRACT_SUBVECTOR, BoolV, Custom);
|
||||
setOperationAction(ISD::EXTRACT_VECTOR_ELT, BoolV, Custom);
|
||||
}
|
||||
|
||||
for (MVT T : LegalV) {
|
||||
if (T == ByteV)
|
||||
continue;
|
||||
// Promote all shuffles to operate on vectors of bytes.
|
||||
setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteV);
|
||||
setPromoteTo(ISD::AND, T, ByteV);
|
||||
setPromoteTo(ISD::OR, T, ByteV);
|
||||
setPromoteTo(ISD::XOR, T, ByteV);
|
||||
}
|
||||
|
||||
for (MVT T : LegalW) {
|
||||
// Custom-lower BUILD_VECTOR for vector pairs. The standard (target-
|
||||
// independent) handling of it would convert it to a load, which is
|
||||
// not always the optimal choice.
|
||||
setOperationAction(ISD::BUILD_VECTOR, T, Custom);
|
||||
// Make concat-vectors custom to handle concats of more than 2 vectors.
|
||||
setOperationAction(ISD::CONCAT_VECTORS, T, Custom);
|
||||
|
||||
// Custom-lower these operations for pairs. Expand them into a concat
|
||||
// of the corresponding operations on individual vectors.
|
||||
setOperationAction(ISD::ANY_EXTEND, T, Custom);
|
||||
setOperationAction(ISD::SIGN_EXTEND, T, Custom);
|
||||
setOperationAction(ISD::ZERO_EXTEND, T, Custom);
|
||||
setOperationAction(ISD::SIGN_EXTEND_INREG, T, Custom);
|
||||
setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom);
|
||||
setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal);
|
||||
setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal);
|
||||
|
||||
setOperationAction(ISD::ADD, T, Legal);
|
||||
setOperationAction(ISD::SUB, T, Legal);
|
||||
setOperationAction(ISD::MUL, T, Custom);
|
||||
setOperationAction(ISD::MULHS, T, Custom);
|
||||
setOperationAction(ISD::MULHU, T, Custom);
|
||||
setOperationAction(ISD::AND, T, Custom);
|
||||
setOperationAction(ISD::OR, T, Custom);
|
||||
setOperationAction(ISD::XOR, T, Custom);
|
||||
setOperationAction(ISD::SETCC, T, Custom);
|
||||
setOperationAction(ISD::VSELECT, T, Custom);
|
||||
if (T != ByteW) {
|
||||
setOperationAction(ISD::SRA, T, Custom);
|
||||
setOperationAction(ISD::SHL, T, Custom);
|
||||
setOperationAction(ISD::SRL, T, Custom);
|
||||
|
||||
// Promote all shuffles to operate on vectors of bytes.
|
||||
setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteW);
|
||||
}
|
||||
|
||||
MVT BoolV = MVT::getVectorVT(MVT::i1, T.getVectorNumElements());
|
||||
setOperationAction(ISD::SETCC, BoolV, Custom);
|
||||
}
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::getInt(unsigned IntId, MVT ResTy, ArrayRef<SDValue> Ops,
|
||||
const SDLoc &dl, SelectionDAG &DAG) const {
|
||||
|
@ -916,6 +1078,40 @@ HexagonTargetLowering::LowerHvxInsertSubvector(SDValue Op, SelectionDAG &DAG)
|
|||
return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerHvxAnyExt(SDValue Op, SelectionDAG &DAG) const {
|
||||
// Lower any-extends of boolean vectors to sign-extends, since they
|
||||
// translate directly to Q2V. Zero-extending could also be done equally
|
||||
// fast, but Q2V is used/recognized in more places.
|
||||
// For all other vectors, use zero-extend.
|
||||
MVT ResTy = ty(Op);
|
||||
SDValue InpV = Op.getOperand(0);
|
||||
MVT ElemTy = ty(InpV).getVectorElementType();
|
||||
if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
|
||||
return LowerHvxSignExt(Op, DAG);
|
||||
return DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Op), ResTy, InpV);
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerHvxSignExt(SDValue Op, SelectionDAG &DAG) const {
|
||||
MVT ResTy = ty(Op);
|
||||
SDValue InpV = Op.getOperand(0);
|
||||
MVT ElemTy = ty(InpV).getVectorElementType();
|
||||
if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
|
||||
return extendHvxVectorPred(InpV, SDLoc(Op), ty(Op), false, DAG);
|
||||
return Op;
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerHvxZeroExt(SDValue Op, SelectionDAG &DAG) const {
|
||||
MVT ResTy = ty(Op);
|
||||
SDValue InpV = Op.getOperand(0);
|
||||
MVT ElemTy = ty(InpV).getVectorElementType();
|
||||
if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
|
||||
return extendHvxVectorPred(InpV, SDLoc(Op), ty(Op), true, DAG);
|
||||
return Op;
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerHvxMul(SDValue Op, SelectionDAG &DAG) const {
|
||||
MVT ResTy = ty(Op);
|
||||
|
@ -1085,6 +1281,8 @@ HexagonTargetLowering::LowerHvxExtend(SDValue Op, SelectionDAG &DAG) const {
|
|||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerHvxShift(SDValue Op, SelectionDAG &DAG) const {
|
||||
if (SDValue S = getVectorShiftByInt(Op, DAG))
|
||||
return S;
|
||||
return Op;
|
||||
}
|
||||
|
||||
|
@ -1152,19 +1350,19 @@ HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const {
|
|||
switch (Opc) {
|
||||
default:
|
||||
break;
|
||||
case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);
|
||||
case ISD::INSERT_SUBVECTOR: return LowerINSERT_SUBVECTOR(Op, DAG);
|
||||
case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR_ELT(Op, DAG);
|
||||
case ISD::EXTRACT_SUBVECTOR: return LowerEXTRACT_SUBVECTOR(Op, DAG);
|
||||
case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG);
|
||||
case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
|
||||
case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
|
||||
case ISD::ANY_EXTEND: return LowerANY_EXTEND(Op, DAG);
|
||||
case ISD::SIGN_EXTEND: return LowerSIGN_EXTEND(Op, DAG);
|
||||
case ISD::ZERO_EXTEND: return LowerZERO_EXTEND(Op, DAG);
|
||||
case ISD::BUILD_VECTOR: return LowerHvxBuildVector(Op, DAG);
|
||||
case ISD::CONCAT_VECTORS: return LowerHvxConcatVectors(Op, DAG);
|
||||
case ISD::INSERT_SUBVECTOR: return LowerHvxInsertSubvector(Op, DAG);
|
||||
case ISD::INSERT_VECTOR_ELT: return LowerHvxInsertElement(Op, DAG);
|
||||
case ISD::EXTRACT_SUBVECTOR: return LowerHvxExtractSubvector(Op, DAG);
|
||||
case ISD::EXTRACT_VECTOR_ELT: return LowerHvxExtractElement(Op, DAG);
|
||||
|
||||
case ISD::ANY_EXTEND: return LowerHvxAnyExt(Op, DAG);
|
||||
case ISD::SIGN_EXTEND: return LowerHvxSignExt(Op, DAG);
|
||||
case ISD::ZERO_EXTEND: return LowerHvxZeroExt(Op, DAG);
|
||||
case ISD::SRA:
|
||||
case ISD::SHL:
|
||||
case ISD::SRL: return LowerVECTOR_SHIFT(Op, DAG);
|
||||
case ISD::SRL: return LowerHvxShift(Op, DAG);
|
||||
case ISD::MUL: return LowerHvxMul(Op, DAG);
|
||||
case ISD::MULHS:
|
||||
case ISD::MULHU: return LowerHvxMulh(Op, DAG);
|
||||
|
@ -1182,7 +1380,7 @@ bool
|
|||
HexagonTargetLowering::isHvxOperation(SDValue Op) const {
|
||||
// If the type of the result, or any operand type are HVX vector types,
|
||||
// this is an HVX operation.
|
||||
return Subtarget.isHVXVectorType(ty(Op)) ||
|
||||
return Subtarget.isHVXVectorType(ty(Op), true) ||
|
||||
llvm::any_of(Op.getNode()->ops(),
|
||||
[this] (SDValue V) {
|
||||
return Subtarget.isHVXVectorType(ty(V), true);
|
||||
|
|
|
@ -839,20 +839,6 @@ def: Pat<(vselect V4I1:$Pu, V4I16:$Rs, V4I16:$Rt),
|
|||
def: Pat<(vselect V2I1:$Pu, V2I32:$Rs, V2I32:$Rt),
|
||||
(C2_vmux V2I1:$Pu, V2I32:$Rs, V2I32:$Rt)>;
|
||||
|
||||
|
||||
class HvxSel_pat<InstHexagon MI, PatFrag RegPred>
|
||||
: Pat<(select I1:$Pu, RegPred:$Vs, RegPred:$Vt),
|
||||
(MI I1:$Pu, RegPred:$Vs, RegPred:$Vt)>;
|
||||
|
||||
let Predicates = [HasV60T,UseHVX] in {
|
||||
def: HvxSel_pat<PS_vselect, HVI8>;
|
||||
def: HvxSel_pat<PS_vselect, HVI16>;
|
||||
def: HvxSel_pat<PS_vselect, HVI32>;
|
||||
def: HvxSel_pat<PS_wselect, HWI8>;
|
||||
def: HvxSel_pat<PS_wselect, HWI16>;
|
||||
def: HvxSel_pat<PS_wselect, HWI32>;
|
||||
}
|
||||
|
||||
// From LegalizeDAG.cpp: (Pu ? Pv : Pw) <=> (Pu & Pv) | (!Pu & Pw).
|
||||
def: Pat<(select I1:$Pu, I1:$Pv, I1:$Pw),
|
||||
(C2_or (C2_and I1:$Pu, I1:$Pv),
|
||||
|
@ -2061,46 +2047,10 @@ def: Pat<(i1 (load (add I32:$Rs, anyimm0:$Off))),
|
|||
def: Pat<(i1 (load I32:$Rs)),
|
||||
(C2_tfrrp (L2_loadrub_io IntRegs:$Rs, 0))>;
|
||||
|
||||
// HVX loads
|
||||
|
||||
multiclass HvxLd_pat<InstHexagon MI, PatFrag Load, ValueType VT,
|
||||
PatFrag ImmPred> {
|
||||
def: Pat<(VT (Load I32:$Rt)), (MI I32:$Rt, 0)>;
|
||||
def: Pat<(VT (Load (add I32:$Rt, ImmPred:$s))), (MI I32:$Rt, imm:$s)>;
|
||||
// The HVX selection code for shuffles can generate vector constants.
|
||||
// Calling "Select" on the resulting loads from CP fails without these
|
||||
// patterns.
|
||||
def: Pat<(VT (Load (HexagonCP tconstpool:$A))), (MI (A2_tfrsi imm:$A), 0)>;
|
||||
def: Pat<(VT (Load (HexagonAtPcrel tconstpool:$A))),
|
||||
(MI (C4_addipc imm:$A), 0)>;
|
||||
}
|
||||
|
||||
|
||||
let Predicates = [UseHVX] in {
|
||||
multiclass HvxLdVs_pat<InstHexagon MI, PatFrag Load> {
|
||||
defm: HvxLd_pat<MI, Load, VecI8, IsVecOff>;
|
||||
defm: HvxLd_pat<MI, Load, VecI16, IsVecOff>;
|
||||
defm: HvxLd_pat<MI, Load, VecI32, IsVecOff>;
|
||||
}
|
||||
defm: HvxLdVs_pat<V6_vL32b_nt_ai, alignednontemporalload>;
|
||||
defm: HvxLdVs_pat<V6_vL32b_ai, alignedload>;
|
||||
defm: HvxLdVs_pat<V6_vL32Ub_ai, unalignedload>;
|
||||
|
||||
multiclass HvxLdWs_pat<InstHexagon MI, PatFrag Load> {
|
||||
defm: HvxLd_pat<MI, Load, VecPI8, IsVecOff>;
|
||||
defm: HvxLd_pat<MI, Load, VecPI16, IsVecOff>;
|
||||
defm: HvxLd_pat<MI, Load, VecPI32, IsVecOff>;
|
||||
}
|
||||
defm: HvxLdWs_pat<PS_vloadrw_nt_ai, alignednontemporalload>;
|
||||
defm: HvxLdWs_pat<PS_vloadrw_ai, alignedload>;
|
||||
defm: HvxLdWs_pat<PS_vloadrwu_ai, unalignedload>;
|
||||
}
|
||||
|
||||
|
||||
// --(13) Store ----------------------------------------------------------
|
||||
//
|
||||
|
||||
|
||||
class Storepi_pat<PatFrag Store, PatFrag Value, PatFrag Offset, InstHexagon MI>
|
||||
: Pat<(Store Value:$Rt, I32:$Rx, Offset:$s4),
|
||||
(MI I32:$Rx, imm:$s4, Value:$Rt)>;
|
||||
|
@ -2537,36 +2487,6 @@ let AddedComplexity = 10 in {
|
|||
def: Storexi_base_pat<AtomSt<atomic_store_64>, I64, S2_storerd_io>;
|
||||
}
|
||||
|
||||
// HVX stores
|
||||
|
||||
multiclass HvxSt_pat<InstHexagon MI, PatFrag Store, PatFrag ImmPred,
|
||||
PatFrag Value> {
|
||||
def: Pat<(Store Value:$Vs, I32:$Rt),
|
||||
(MI I32:$Rt, 0, Value:$Vs)>;
|
||||
def: Pat<(Store Value:$Vs, (add I32:$Rt, ImmPred:$s)),
|
||||
(MI I32:$Rt, imm:$s, Value:$Vs)>;
|
||||
}
|
||||
|
||||
let Predicates = [UseHVX] in {
|
||||
multiclass HvxStVs_pat<InstHexagon MI, PatFrag Store> {
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HVI8>;
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HVI16>;
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HVI32>;
|
||||
}
|
||||
defm: HvxStVs_pat<V6_vS32b_nt_ai, alignednontemporalstore>;
|
||||
defm: HvxStVs_pat<V6_vS32b_ai, alignedstore>;
|
||||
defm: HvxStVs_pat<V6_vS32Ub_ai, unalignedstore>;
|
||||
|
||||
multiclass HvxStWs_pat<InstHexagon MI, PatFrag Store> {
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HWI8>;
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HWI16>;
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HWI32>;
|
||||
}
|
||||
defm: HvxStWs_pat<PS_vstorerw_nt_ai, alignednontemporalstore>;
|
||||
defm: HvxStWs_pat<PS_vstorerw_ai, alignedstore>;
|
||||
defm: HvxStWs_pat<PS_vstorerwu_ai, unalignedstore>;
|
||||
}
|
||||
|
||||
|
||||
// --(14) Memop ----------------------------------------------------------
|
||||
//
|
||||
|
@ -2975,262 +2895,3 @@ def HexagonREADCYCLE: SDNode<"HexagonISD::READCYCLE", SDTInt64Leaf,
|
|||
[SDNPHasChain]>;
|
||||
|
||||
def: Pat<(HexagonREADCYCLE), (A4_tfrcpp UPCYCLE)>;
|
||||
|
||||
|
||||
def SDTVecLeaf:
|
||||
SDTypeProfile<1, 0, [SDTCisVec<0>]>;
|
||||
def SDTVecBinOp:
|
||||
SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<1,2>]>;
|
||||
|
||||
def SDTHexagonVEXTRACTW: SDTypeProfile<1, 2,
|
||||
[SDTCisVT<0, i32>, SDTCisVec<1>, SDTCisVT<2, i32>]>;
|
||||
def HexagonVEXTRACTW : SDNode<"HexagonISD::VEXTRACTW", SDTHexagonVEXTRACTW>;
|
||||
|
||||
def SDTHexagonVINSERTW0: SDTypeProfile<1, 2,
|
||||
[SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisVT<2, i32>]>;
|
||||
def HexagonVINSERTW0 : SDNode<"HexagonISD::VINSERTW0", SDTHexagonVINSERTW0>;
|
||||
|
||||
def HwLen2: SDNodeXForm<imm, [{
|
||||
const auto &ST = static_cast<const HexagonSubtarget&>(CurDAG->getSubtarget());
|
||||
return CurDAG->getTargetConstant(ST.getVectorLength()/2, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def Q2V: OutPatFrag<(ops node:$Qs), (V6_vandqrt $Qs, (A2_tfrsi -1))>;
|
||||
|
||||
def Combinev: OutPatFrag<(ops node:$Vs, node:$Vt),
|
||||
(REG_SEQUENCE HvxWR, $Vs, vsub_hi, $Vt, vsub_lo)>;
|
||||
|
||||
def Combineq: OutPatFrag<(ops node:$Qs, node:$Qt),
|
||||
(V6_vandvrt
|
||||
(V6_vor
|
||||
(V6_vror (V6_vpackeb (V6_vd0), (Q2V $Qs)),
|
||||
(A2_tfrsi (HwLen2 (i32 0)))), // Half the vector length
|
||||
(V6_vpackeb (V6_vd0), (Q2V $Qt))),
|
||||
(A2_tfrsi -1))>;
|
||||
|
||||
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 HexagonQCAT: SDNode<"HexagonISD::QCAT", SDTVecBinOp>;
|
||||
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 qcat: PatFrag<(ops node:$Qs, node:$Qt),
|
||||
(HexagonQCAT node:$Qs, node:$Qt)>;
|
||||
|
||||
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)>;
|
||||
def VZxtb: OutPatFrag<(ops node:$Vs), (V6_vunpackub $Vs)>;
|
||||
def VZxth: OutPatFrag<(ops node:$Vs), (V6_vunpackuh $Vs)>;
|
||||
|
||||
def SplatB: SDNodeXForm<imm, [{
|
||||
uint32_t V = N->getZExtValue();
|
||||
assert(isUInt<8>(V));
|
||||
uint32_t S = V << 24 | V << 16 | V << 8 | V;
|
||||
return CurDAG->getTargetConstant(S, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def SplatH: SDNodeXForm<imm, [{
|
||||
uint32_t V = N->getZExtValue();
|
||||
assert(isUInt<16>(V));
|
||||
return CurDAG->getTargetConstant(V << 16 | V, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
let Predicates = [UseHVX] in {
|
||||
def: Pat<(VecI8 vzero), (V6_vd0)>;
|
||||
def: Pat<(VecI16 vzero), (V6_vd0)>;
|
||||
def: Pat<(VecI32 vzero), (V6_vd0)>;
|
||||
// Use V6_vsubw_dv instead.
|
||||
def: Pat<(VecPI8 vzero), (Combinev (V6_vd0), (V6_vd0))>;
|
||||
def: Pat<(VecPI16 vzero), (Combinev (V6_vd0), (V6_vd0))>;
|
||||
def: Pat<(VecPI32 vzero), (Combinev (V6_vd0), (V6_vd0))>;
|
||||
|
||||
def: Pat<(VecPI8 (concat_vectors HVI8:$Vs, HVI8:$Vt)),
|
||||
(Combinev HvxVR:$Vt, HvxVR:$Vs)>;
|
||||
def: Pat<(VecPI16 (concat_vectors HVI16:$Vs, HVI16:$Vt)),
|
||||
(Combinev HvxVR:$Vt, HvxVR:$Vs)>;
|
||||
def: Pat<(VecPI32 (concat_vectors HVI32:$Vs, HVI32:$Vt)),
|
||||
(Combinev HvxVR:$Vt, HvxVR:$Vs)>;
|
||||
|
||||
def: Pat<(VecQ8 (qcat HQ16:$Qs, HQ16:$Qt)), (Combineq $Qs, $Qt)>;
|
||||
def: Pat<(VecQ16 (qcat HQ32:$Qs, HQ32:$Qt)), (Combineq $Qs, $Qt)>;
|
||||
|
||||
def: Pat<(HexagonVEXTRACTW HVI8:$Vu, I32:$Rs),
|
||||
(V6_extractw HvxVR:$Vu, I32:$Rs)>;
|
||||
def: Pat<(HexagonVEXTRACTW HVI16:$Vu, I32:$Rs),
|
||||
(V6_extractw HvxVR:$Vu, I32:$Rs)>;
|
||||
def: Pat<(HexagonVEXTRACTW HVI32:$Vu, I32:$Rs),
|
||||
(V6_extractw HvxVR:$Vu, I32:$Rs)>;
|
||||
|
||||
def: Pat<(HexagonVINSERTW0 HVI8:$Vu, I32:$Rt),
|
||||
(V6_vinsertwr HvxVR:$Vu, I32:$Rt)>;
|
||||
def: Pat<(HexagonVINSERTW0 HVI16:$Vu, I32:$Rt),
|
||||
(V6_vinsertwr HvxVR:$Vu, I32:$Rt)>;
|
||||
def: Pat<(HexagonVINSERTW0 HVI32:$Vu, I32:$Rt),
|
||||
(V6_vinsertwr HvxVR:$Vu, I32:$Rt)>;
|
||||
|
||||
let AddedComplexity = 10 in {
|
||||
def: Pat<(VecI8 (HexagonVSPLAT u8_0ImmPred:$V)),
|
||||
(V6_lvsplatw (ToI32 (SplatB $V)))>;
|
||||
def: Pat<(VecI16 (HexagonVSPLAT u16_0ImmPred:$V)),
|
||||
(V6_lvsplatw (ToI32 (SplatH $V)))>;
|
||||
def: Pat<(VecI32 (HexagonVSPLAT anyimm:$V)),
|
||||
(V6_lvsplatw (ToI32 $V))>;
|
||||
def: Pat<(VecPI8 (HexagonVSPLAT u8_0ImmPred:$V)),
|
||||
(Combinev (V6_lvsplatw (ToI32 (SplatB $V))),
|
||||
(V6_lvsplatw (ToI32 (SplatB $V))))>;
|
||||
def: Pat<(VecPI16 (HexagonVSPLAT u16_0ImmPred:$V)),
|
||||
(Combinev (V6_lvsplatw (ToI32 (SplatH $V))),
|
||||
(V6_lvsplatw (ToI32 (SplatH $V))))>;
|
||||
def: Pat<(VecPI32 (HexagonVSPLAT anyimm:$V)),
|
||||
(Combinev (V6_lvsplatw (ToI32 $V)), (V6_lvsplatw (ToI32 $V)))>;
|
||||
}
|
||||
def: Pat<(VecI8 (HexagonVSPLAT I32:$Rs)),
|
||||
(V6_lvsplatw (S2_vsplatrb I32:$Rs))>;
|
||||
def: Pat<(VecI16 (HexagonVSPLAT I32:$Rs)),
|
||||
(V6_lvsplatw (A2_combine_ll I32:$Rs, I32:$Rs))>;
|
||||
def: Pat<(VecI32 (HexagonVSPLAT I32:$Rs)),
|
||||
(V6_lvsplatw I32:$Rs)>;
|
||||
def: Pat<(VecPI8 (HexagonVSPLAT I32:$Rs)),
|
||||
(Combinev (V6_lvsplatw (S2_vsplatrb I32:$Rs)),
|
||||
(V6_lvsplatw (S2_vsplatrb I32:$Rs)))>;
|
||||
def: Pat<(VecPI16 (HexagonVSPLAT I32:$Rs)),
|
||||
(Combinev (V6_lvsplatw (A2_combine_ll I32:$Rs, I32:$Rs)),
|
||||
(V6_lvsplatw (A2_combine_ll I32:$Rs, I32:$Rs)))>;
|
||||
def: Pat<(VecPI32 (HexagonVSPLAT I32:$Rs)),
|
||||
(Combinev (V6_lvsplatw I32:$Rs), (V6_lvsplatw I32:$Rs))>;
|
||||
|
||||
def: Pat<(add HVI8:$Vs, HVI8:$Vt), (V6_vaddb HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(add HVI16:$Vs, HVI16:$Vt), (V6_vaddh HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(add HVI32:$Vs, HVI32:$Vt), (V6_vaddw HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(add HWI8:$Vs, HWI8:$Vt), (V6_vaddb_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
def: Pat<(add HWI16:$Vs, HWI16:$Vt), (V6_vaddh_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
def: Pat<(add HWI32:$Vs, HWI32:$Vt), (V6_vaddw_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
|
||||
def: Pat<(sub HVI8:$Vs, HVI8:$Vt), (V6_vsubb HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(sub HVI16:$Vs, HVI16:$Vt), (V6_vsubh HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(sub HVI32:$Vs, HVI32:$Vt), (V6_vsubw HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(sub HWI8:$Vs, HWI8:$Vt), (V6_vsubb_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
def: Pat<(sub HWI16:$Vs, HWI16:$Vt), (V6_vsubh_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
def: Pat<(sub HWI32:$Vs, HWI32:$Vt), (V6_vsubw_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
|
||||
def: Pat<(and HVI8:$Vs, HVI8:$Vt), (V6_vand HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(or HVI8:$Vs, HVI8:$Vt), (V6_vor HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(xor HVI8:$Vs, HVI8:$Vt), (V6_vxor HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
|
||||
def: Pat<(vselect HQ8:$Qu, HVI8:$Vs, HVI8:$Vt),
|
||||
(V6_vmux HvxQR:$Qu, HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(vselect HQ16:$Qu, HVI16:$Vs, HVI16:$Vt),
|
||||
(V6_vmux HvxQR:$Qu, HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
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)>;
|
||||
def: Pat<(VecPI32 (zext HVI16:$Vs)), (VZxth $Vs)>;
|
||||
|
||||
def: Pat<(VecI16 (sext_invec HVI8:$Vs)), (LoVec (VSxtb $Vs))>;
|
||||
def: Pat<(VecI32 (sext_invec HVI16:$Vs)), (LoVec (VSxth $Vs))>;
|
||||
def: Pat<(VecI32 (sext_invec HVI8:$Vs)),
|
||||
(LoVec (VSxth (LoVec (VSxtb $Vs))))>;
|
||||
def: Pat<(VecPI16 (sext_invec HWI8:$Vss)), (VSxtb (LoVec $Vss))>;
|
||||
def: Pat<(VecPI32 (sext_invec HWI16:$Vss)), (VSxth (LoVec $Vss))>;
|
||||
def: Pat<(VecPI32 (sext_invec HWI8:$Vss)),
|
||||
(VSxth (LoVec (VSxtb (LoVec $Vss))))>;
|
||||
|
||||
def: Pat<(VecI16 (zext_invec HVI8:$Vs)), (LoVec (VZxtb $Vs))>;
|
||||
def: Pat<(VecI32 (zext_invec HVI16:$Vs)), (LoVec (VZxth $Vs))>;
|
||||
def: Pat<(VecI32 (zext_invec HVI8:$Vs)),
|
||||
(LoVec (VZxth (LoVec (VZxtb $Vs))))>;
|
||||
def: Pat<(VecPI16 (zext_invec HWI8:$Vss)), (VZxtb (LoVec $Vss))>;
|
||||
def: Pat<(VecPI32 (zext_invec HWI16:$Vss)), (VZxth (LoVec $Vss))>;
|
||||
def: Pat<(VecPI32 (zext_invec HWI8:$Vss)),
|
||||
(VZxth (LoVec (VZxtb (LoVec $Vss))))>;
|
||||
|
||||
// The "source" types are not legal, and there are no parameterized
|
||||
// definitions for them, but they are length-specific.
|
||||
let Predicates = [UseHVX,UseHVX64B] in {
|
||||
def: Pat<(VecI16 (sext_inreg HVI16:$Vs, v32i8)),
|
||||
(V6_vasrh (V6_vaslh HVI16:$Vs, (A2_tfrsi 8)), (A2_tfrsi 8))>;
|
||||
def: Pat<(VecI32 (sext_inreg HVI32:$Vs, v16i8)),
|
||||
(V6_vasrw (V6_vaslw HVI32:$Vs, (A2_tfrsi 24)), (A2_tfrsi 24))>;
|
||||
def: Pat<(VecI32 (sext_inreg HVI32:$Vs, v16i16)),
|
||||
(V6_vasrw (V6_vaslw HVI32:$Vs, (A2_tfrsi 16)), (A2_tfrsi 16))>;
|
||||
}
|
||||
let Predicates = [UseHVX,UseHVX128B] in {
|
||||
def: Pat<(VecI16 (sext_inreg HVI16:$Vs, v64i8)),
|
||||
(V6_vasrh (V6_vaslh HVI16:$Vs, (A2_tfrsi 8)), (A2_tfrsi 8))>;
|
||||
def: Pat<(VecI32 (sext_inreg HVI32:$Vs, v32i8)),
|
||||
(V6_vasrw (V6_vaslw HVI32:$Vs, (A2_tfrsi 24)), (A2_tfrsi 24))>;
|
||||
def: Pat<(VecI32 (sext_inreg HVI32:$Vs, v32i16)),
|
||||
(V6_vasrw (V6_vaslw HVI32:$Vs, (A2_tfrsi 16)), (A2_tfrsi 16))>;
|
||||
}
|
||||
|
||||
def: Pat<(HexagonVASL HVI8:$Vs, I32:$Rt),
|
||||
(V6_vpackeb (V6_vaslh (HiVec (VZxtb HvxVR:$Vs)), I32:$Rt),
|
||||
(V6_vaslh (LoVec (VZxtb HvxVR:$Vs)), I32:$Rt))>;
|
||||
def: Pat<(HexagonVASR HVI8:$Vs, I32:$Rt),
|
||||
(V6_vpackeb (V6_vasrh (HiVec (VSxtb HvxVR:$Vs)), I32:$Rt),
|
||||
(V6_vasrh (LoVec (VSxtb HvxVR:$Vs)), I32:$Rt))>;
|
||||
def: Pat<(HexagonVLSR HVI8:$Vs, I32:$Rt),
|
||||
(V6_vpackeb (V6_vlsrh (HiVec (VZxtb HvxVR:$Vs)), I32:$Rt),
|
||||
(V6_vlsrh (LoVec (VZxtb HvxVR:$Vs)), I32:$Rt))>;
|
||||
|
||||
def: Pat<(HexagonVASL HVI16:$Vs, I32:$Rt), (V6_vaslh HvxVR:$Vs, I32:$Rt)>;
|
||||
def: Pat<(HexagonVASL HVI32:$Vs, I32:$Rt), (V6_vaslw HvxVR:$Vs, I32:$Rt)>;
|
||||
def: Pat<(HexagonVASR HVI16:$Vs, I32:$Rt), (V6_vasrh HvxVR:$Vs, I32:$Rt)>;
|
||||
def: Pat<(HexagonVASR HVI32:$Vs, I32:$Rt), (V6_vasrw HvxVR:$Vs, I32:$Rt)>;
|
||||
def: Pat<(HexagonVLSR HVI16:$Vs, I32:$Rt), (V6_vlsrh HvxVR:$Vs, I32:$Rt)>;
|
||||
def: Pat<(HexagonVLSR HVI32:$Vs, I32:$Rt), (V6_vlsrw HvxVR:$Vs, I32:$Rt)>;
|
||||
|
||||
def: Pat<(shl HVI16:$Vs, HVI16:$Vt), (V6_vaslhv HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(shl HVI32:$Vs, HVI32:$Vt), (V6_vaslwv HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(sra HVI16:$Vs, HVI16:$Vt), (V6_vasrhv HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(sra HVI32:$Vs, HVI32:$Vt), (V6_vasrwv HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
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)),
|
||||
(V6_vpackeh (HiVec $Vss), (LoVec $Vss))>;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,338 @@
|
|||
def SDTVecLeaf:
|
||||
SDTypeProfile<1, 0, [SDTCisVec<0>]>;
|
||||
def SDTVecBinOp:
|
||||
SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<1,2>]>;
|
||||
|
||||
def SDTHexagonVEXTRACTW: SDTypeProfile<1, 2,
|
||||
[SDTCisVT<0, i32>, SDTCisVec<1>, SDTCisVT<2, i32>]>;
|
||||
def HexagonVEXTRACTW : SDNode<"HexagonISD::VEXTRACTW", SDTHexagonVEXTRACTW>;
|
||||
|
||||
def SDTHexagonVINSERTW0: SDTypeProfile<1, 2,
|
||||
[SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisVT<2, i32>]>;
|
||||
def HexagonVINSERTW0 : SDNode<"HexagonISD::VINSERTW0", SDTHexagonVINSERTW0>;
|
||||
|
||||
def HwLen2: SDNodeXForm<imm, [{
|
||||
const auto &ST = static_cast<const HexagonSubtarget&>(CurDAG->getSubtarget());
|
||||
return CurDAG->getTargetConstant(ST.getVectorLength()/2, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def Q2V: OutPatFrag<(ops node:$Qs), (V6_vandqrt $Qs, (A2_tfrsi -1))>;
|
||||
|
||||
def Combinev: OutPatFrag<(ops node:$Vs, node:$Vt),
|
||||
(REG_SEQUENCE HvxWR, $Vs, vsub_hi, $Vt, vsub_lo)>;
|
||||
|
||||
def Combineq: OutPatFrag<(ops node:$Qs, node:$Qt),
|
||||
(V6_vandvrt
|
||||
(V6_vor
|
||||
(V6_vror (V6_vpackeb (V6_vd0), (Q2V $Qs)),
|
||||
(A2_tfrsi (HwLen2 (i32 0)))), // Half the vector length
|
||||
(V6_vpackeb (V6_vd0), (Q2V $Qt))),
|
||||
(A2_tfrsi -1))>;
|
||||
|
||||
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 HexagonQCAT: SDNode<"HexagonISD::QCAT", SDTVecBinOp>;
|
||||
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 qcat: PatFrag<(ops node:$Qs, node:$Qt),
|
||||
(HexagonQCAT node:$Qs, node:$Qt)>;
|
||||
|
||||
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)>;
|
||||
def VZxtb: OutPatFrag<(ops node:$Vs), (V6_vunpackub $Vs)>;
|
||||
def VZxth: OutPatFrag<(ops node:$Vs), (V6_vunpackuh $Vs)>;
|
||||
|
||||
def SplatB: SDNodeXForm<imm, [{
|
||||
uint32_t V = N->getZExtValue();
|
||||
assert(isUInt<8>(V));
|
||||
uint32_t S = V << 24 | V << 16 | V << 8 | V;
|
||||
return CurDAG->getTargetConstant(S, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def SplatH: SDNodeXForm<imm, [{
|
||||
uint32_t V = N->getZExtValue();
|
||||
assert(isUInt<16>(V));
|
||||
return CurDAG->getTargetConstant(V << 16 | V, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
|
||||
// HVX loads
|
||||
|
||||
multiclass HvxLd_pat<InstHexagon MI, PatFrag Load, ValueType VT,
|
||||
PatFrag ImmPred> {
|
||||
def: Pat<(VT (Load I32:$Rt)), (MI I32:$Rt, 0)>;
|
||||
def: Pat<(VT (Load (add I32:$Rt, ImmPred:$s))), (MI I32:$Rt, imm:$s)>;
|
||||
// The HVX selection code for shuffles can generate vector constants.
|
||||
// Calling "Select" on the resulting loads from CP fails without these
|
||||
// patterns.
|
||||
def: Pat<(VT (Load (HexagonCP tconstpool:$A))), (MI (A2_tfrsi imm:$A), 0)>;
|
||||
def: Pat<(VT (Load (HexagonAtPcrel tconstpool:$A))),
|
||||
(MI (C4_addipc imm:$A), 0)>;
|
||||
}
|
||||
|
||||
let Predicates = [UseHVX] in {
|
||||
multiclass HvxLdVs_pat<InstHexagon MI, PatFrag Load> {
|
||||
defm: HvxLd_pat<MI, Load, VecI8, IsVecOff>;
|
||||
defm: HvxLd_pat<MI, Load, VecI16, IsVecOff>;
|
||||
defm: HvxLd_pat<MI, Load, VecI32, IsVecOff>;
|
||||
}
|
||||
defm: HvxLdVs_pat<V6_vL32b_nt_ai, alignednontemporalload>;
|
||||
defm: HvxLdVs_pat<V6_vL32b_ai, alignedload>;
|
||||
defm: HvxLdVs_pat<V6_vL32Ub_ai, unalignedload>;
|
||||
|
||||
multiclass HvxLdWs_pat<InstHexagon MI, PatFrag Load> {
|
||||
defm: HvxLd_pat<MI, Load, VecPI8, IsVecOff>;
|
||||
defm: HvxLd_pat<MI, Load, VecPI16, IsVecOff>;
|
||||
defm: HvxLd_pat<MI, Load, VecPI32, IsVecOff>;
|
||||
}
|
||||
defm: HvxLdWs_pat<PS_vloadrw_nt_ai, alignednontemporalload>;
|
||||
defm: HvxLdWs_pat<PS_vloadrw_ai, alignedload>;
|
||||
defm: HvxLdWs_pat<PS_vloadrwu_ai, unalignedload>;
|
||||
}
|
||||
|
||||
|
||||
// HVX stores
|
||||
|
||||
multiclass HvxSt_pat<InstHexagon MI, PatFrag Store, PatFrag ImmPred,
|
||||
PatFrag Value> {
|
||||
def: Pat<(Store Value:$Vs, I32:$Rt),
|
||||
(MI I32:$Rt, 0, Value:$Vs)>;
|
||||
def: Pat<(Store Value:$Vs, (add I32:$Rt, ImmPred:$s)),
|
||||
(MI I32:$Rt, imm:$s, Value:$Vs)>;
|
||||
}
|
||||
|
||||
let Predicates = [UseHVX] in {
|
||||
multiclass HvxStVs_pat<InstHexagon MI, PatFrag Store> {
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HVI8>;
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HVI16>;
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HVI32>;
|
||||
}
|
||||
defm: HvxStVs_pat<V6_vS32b_nt_ai, alignednontemporalstore>;
|
||||
defm: HvxStVs_pat<V6_vS32b_ai, alignedstore>;
|
||||
defm: HvxStVs_pat<V6_vS32Ub_ai, unalignedstore>;
|
||||
|
||||
multiclass HvxStWs_pat<InstHexagon MI, PatFrag Store> {
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HWI8>;
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HWI16>;
|
||||
defm: HvxSt_pat<MI, Store, IsVecOff, HWI32>;
|
||||
}
|
||||
defm: HvxStWs_pat<PS_vstorerw_nt_ai, alignednontemporalstore>;
|
||||
defm: HvxStWs_pat<PS_vstorerw_ai, alignedstore>;
|
||||
defm: HvxStWs_pat<PS_vstorerwu_ai, unalignedstore>;
|
||||
}
|
||||
|
||||
|
||||
let Predicates = [UseHVX] in {
|
||||
def: Pat<(VecI8 vzero), (V6_vd0)>;
|
||||
def: Pat<(VecI16 vzero), (V6_vd0)>;
|
||||
def: Pat<(VecI32 vzero), (V6_vd0)>;
|
||||
// Use V6_vsubw_dv instead.
|
||||
def: Pat<(VecPI8 vzero), (Combinev (V6_vd0), (V6_vd0))>;
|
||||
def: Pat<(VecPI16 vzero), (Combinev (V6_vd0), (V6_vd0))>;
|
||||
def: Pat<(VecPI32 vzero), (Combinev (V6_vd0), (V6_vd0))>;
|
||||
|
||||
def: Pat<(VecPI8 (concat_vectors HVI8:$Vs, HVI8:$Vt)),
|
||||
(Combinev HvxVR:$Vt, HvxVR:$Vs)>;
|
||||
def: Pat<(VecPI16 (concat_vectors HVI16:$Vs, HVI16:$Vt)),
|
||||
(Combinev HvxVR:$Vt, HvxVR:$Vs)>;
|
||||
def: Pat<(VecPI32 (concat_vectors HVI32:$Vs, HVI32:$Vt)),
|
||||
(Combinev HvxVR:$Vt, HvxVR:$Vs)>;
|
||||
|
||||
def: Pat<(VecQ8 (qcat HQ16:$Qs, HQ16:$Qt)), (Combineq $Qs, $Qt)>;
|
||||
def: Pat<(VecQ16 (qcat HQ32:$Qs, HQ32:$Qt)), (Combineq $Qs, $Qt)>;
|
||||
|
||||
def: Pat<(HexagonVEXTRACTW HVI8:$Vu, I32:$Rs),
|
||||
(V6_extractw HvxVR:$Vu, I32:$Rs)>;
|
||||
def: Pat<(HexagonVEXTRACTW HVI16:$Vu, I32:$Rs),
|
||||
(V6_extractw HvxVR:$Vu, I32:$Rs)>;
|
||||
def: Pat<(HexagonVEXTRACTW HVI32:$Vu, I32:$Rs),
|
||||
(V6_extractw HvxVR:$Vu, I32:$Rs)>;
|
||||
|
||||
def: Pat<(HexagonVINSERTW0 HVI8:$Vu, I32:$Rt),
|
||||
(V6_vinsertwr HvxVR:$Vu, I32:$Rt)>;
|
||||
def: Pat<(HexagonVINSERTW0 HVI16:$Vu, I32:$Rt),
|
||||
(V6_vinsertwr HvxVR:$Vu, I32:$Rt)>;
|
||||
def: Pat<(HexagonVINSERTW0 HVI32:$Vu, I32:$Rt),
|
||||
(V6_vinsertwr HvxVR:$Vu, I32:$Rt)>;
|
||||
|
||||
let AddedComplexity = 10 in {
|
||||
def: Pat<(VecI8 (HexagonVSPLAT u8_0ImmPred:$V)),
|
||||
(V6_lvsplatw (ToI32 (SplatB $V)))>;
|
||||
def: Pat<(VecI16 (HexagonVSPLAT u16_0ImmPred:$V)),
|
||||
(V6_lvsplatw (ToI32 (SplatH $V)))>;
|
||||
def: Pat<(VecI32 (HexagonVSPLAT anyimm:$V)),
|
||||
(V6_lvsplatw (ToI32 $V))>;
|
||||
def: Pat<(VecPI8 (HexagonVSPLAT u8_0ImmPred:$V)),
|
||||
(Combinev (V6_lvsplatw (ToI32 (SplatB $V))),
|
||||
(V6_lvsplatw (ToI32 (SplatB $V))))>;
|
||||
def: Pat<(VecPI16 (HexagonVSPLAT u16_0ImmPred:$V)),
|
||||
(Combinev (V6_lvsplatw (ToI32 (SplatH $V))),
|
||||
(V6_lvsplatw (ToI32 (SplatH $V))))>;
|
||||
def: Pat<(VecPI32 (HexagonVSPLAT anyimm:$V)),
|
||||
(Combinev (V6_lvsplatw (ToI32 $V)), (V6_lvsplatw (ToI32 $V)))>;
|
||||
}
|
||||
def: Pat<(VecI8 (HexagonVSPLAT I32:$Rs)),
|
||||
(V6_lvsplatw (S2_vsplatrb I32:$Rs))>;
|
||||
def: Pat<(VecI16 (HexagonVSPLAT I32:$Rs)),
|
||||
(V6_lvsplatw (A2_combine_ll I32:$Rs, I32:$Rs))>;
|
||||
def: Pat<(VecI32 (HexagonVSPLAT I32:$Rs)),
|
||||
(V6_lvsplatw I32:$Rs)>;
|
||||
def: Pat<(VecPI8 (HexagonVSPLAT I32:$Rs)),
|
||||
(Combinev (V6_lvsplatw (S2_vsplatrb I32:$Rs)),
|
||||
(V6_lvsplatw (S2_vsplatrb I32:$Rs)))>;
|
||||
def: Pat<(VecPI16 (HexagonVSPLAT I32:$Rs)),
|
||||
(Combinev (V6_lvsplatw (A2_combine_ll I32:$Rs, I32:$Rs)),
|
||||
(V6_lvsplatw (A2_combine_ll I32:$Rs, I32:$Rs)))>;
|
||||
def: Pat<(VecPI32 (HexagonVSPLAT I32:$Rs)),
|
||||
(Combinev (V6_lvsplatw I32:$Rs), (V6_lvsplatw I32:$Rs))>;
|
||||
|
||||
def: Pat<(add HVI8:$Vs, HVI8:$Vt), (V6_vaddb HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(add HVI16:$Vs, HVI16:$Vt), (V6_vaddh HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(add HVI32:$Vs, HVI32:$Vt), (V6_vaddw HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(add HWI8:$Vs, HWI8:$Vt), (V6_vaddb_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
def: Pat<(add HWI16:$Vs, HWI16:$Vt), (V6_vaddh_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
def: Pat<(add HWI32:$Vs, HWI32:$Vt), (V6_vaddw_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
|
||||
def: Pat<(sub HVI8:$Vs, HVI8:$Vt), (V6_vsubb HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(sub HVI16:$Vs, HVI16:$Vt), (V6_vsubh HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(sub HVI32:$Vs, HVI32:$Vt), (V6_vsubw HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(sub HWI8:$Vs, HWI8:$Vt), (V6_vsubb_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
def: Pat<(sub HWI16:$Vs, HWI16:$Vt), (V6_vsubh_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
def: Pat<(sub HWI32:$Vs, HWI32:$Vt), (V6_vsubw_dv HvxWR:$Vs, HvxWR:$Vt)>;
|
||||
|
||||
def: Pat<(and HVI8:$Vs, HVI8:$Vt), (V6_vand HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(or HVI8:$Vs, HVI8:$Vt), (V6_vor HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(xor HVI8:$Vs, HVI8:$Vt), (V6_vxor HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
|
||||
def: Pat<(vselect HQ8:$Qu, HVI8:$Vs, HVI8:$Vt),
|
||||
(V6_vmux HvxQR:$Qu, HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(vselect HQ16:$Qu, HVI16:$Vs, HVI16:$Vt),
|
||||
(V6_vmux HvxQR:$Qu, HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
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)>;
|
||||
def: Pat<(VecPI32 (zext HVI16:$Vs)), (VZxth $Vs)>;
|
||||
|
||||
def: Pat<(VecI16 (sext_invec HVI8:$Vs)), (LoVec (VSxtb $Vs))>;
|
||||
def: Pat<(VecI32 (sext_invec HVI16:$Vs)), (LoVec (VSxth $Vs))>;
|
||||
def: Pat<(VecI32 (sext_invec HVI8:$Vs)),
|
||||
(LoVec (VSxth (LoVec (VSxtb $Vs))))>;
|
||||
def: Pat<(VecPI16 (sext_invec HWI8:$Vss)), (VSxtb (LoVec $Vss))>;
|
||||
def: Pat<(VecPI32 (sext_invec HWI16:$Vss)), (VSxth (LoVec $Vss))>;
|
||||
def: Pat<(VecPI32 (sext_invec HWI8:$Vss)),
|
||||
(VSxth (LoVec (VSxtb (LoVec $Vss))))>;
|
||||
|
||||
def: Pat<(VecI16 (zext_invec HVI8:$Vs)), (LoVec (VZxtb $Vs))>;
|
||||
def: Pat<(VecI32 (zext_invec HVI16:$Vs)), (LoVec (VZxth $Vs))>;
|
||||
def: Pat<(VecI32 (zext_invec HVI8:$Vs)),
|
||||
(LoVec (VZxth (LoVec (VZxtb $Vs))))>;
|
||||
def: Pat<(VecPI16 (zext_invec HWI8:$Vss)), (VZxtb (LoVec $Vss))>;
|
||||
def: Pat<(VecPI32 (zext_invec HWI16:$Vss)), (VZxth (LoVec $Vss))>;
|
||||
def: Pat<(VecPI32 (zext_invec HWI8:$Vss)),
|
||||
(VZxth (LoVec (VZxtb (LoVec $Vss))))>;
|
||||
|
||||
// The "source" types are not legal, and there are no parameterized
|
||||
// definitions for them, but they are length-specific.
|
||||
let Predicates = [UseHVX,UseHVX64B] in {
|
||||
def: Pat<(VecI16 (sext_inreg HVI16:$Vs, v32i8)),
|
||||
(V6_vasrh (V6_vaslh HVI16:$Vs, (A2_tfrsi 8)), (A2_tfrsi 8))>;
|
||||
def: Pat<(VecI32 (sext_inreg HVI32:$Vs, v16i8)),
|
||||
(V6_vasrw (V6_vaslw HVI32:$Vs, (A2_tfrsi 24)), (A2_tfrsi 24))>;
|
||||
def: Pat<(VecI32 (sext_inreg HVI32:$Vs, v16i16)),
|
||||
(V6_vasrw (V6_vaslw HVI32:$Vs, (A2_tfrsi 16)), (A2_tfrsi 16))>;
|
||||
}
|
||||
let Predicates = [UseHVX,UseHVX128B] in {
|
||||
def: Pat<(VecI16 (sext_inreg HVI16:$Vs, v64i8)),
|
||||
(V6_vasrh (V6_vaslh HVI16:$Vs, (A2_tfrsi 8)), (A2_tfrsi 8))>;
|
||||
def: Pat<(VecI32 (sext_inreg HVI32:$Vs, v32i8)),
|
||||
(V6_vasrw (V6_vaslw HVI32:$Vs, (A2_tfrsi 24)), (A2_tfrsi 24))>;
|
||||
def: Pat<(VecI32 (sext_inreg HVI32:$Vs, v32i16)),
|
||||
(V6_vasrw (V6_vaslw HVI32:$Vs, (A2_tfrsi 16)), (A2_tfrsi 16))>;
|
||||
}
|
||||
|
||||
def: Pat<(HexagonVASL HVI8:$Vs, I32:$Rt),
|
||||
(V6_vpackeb (V6_vaslh (HiVec (VZxtb HvxVR:$Vs)), I32:$Rt),
|
||||
(V6_vaslh (LoVec (VZxtb HvxVR:$Vs)), I32:$Rt))>;
|
||||
def: Pat<(HexagonVASR HVI8:$Vs, I32:$Rt),
|
||||
(V6_vpackeb (V6_vasrh (HiVec (VSxtb HvxVR:$Vs)), I32:$Rt),
|
||||
(V6_vasrh (LoVec (VSxtb HvxVR:$Vs)), I32:$Rt))>;
|
||||
def: Pat<(HexagonVLSR HVI8:$Vs, I32:$Rt),
|
||||
(V6_vpackeb (V6_vlsrh (HiVec (VZxtb HvxVR:$Vs)), I32:$Rt),
|
||||
(V6_vlsrh (LoVec (VZxtb HvxVR:$Vs)), I32:$Rt))>;
|
||||
|
||||
def: Pat<(HexagonVASL HVI16:$Vs, I32:$Rt), (V6_vaslh HvxVR:$Vs, I32:$Rt)>;
|
||||
def: Pat<(HexagonVASL HVI32:$Vs, I32:$Rt), (V6_vaslw HvxVR:$Vs, I32:$Rt)>;
|
||||
def: Pat<(HexagonVASR HVI16:$Vs, I32:$Rt), (V6_vasrh HvxVR:$Vs, I32:$Rt)>;
|
||||
def: Pat<(HexagonVASR HVI32:$Vs, I32:$Rt), (V6_vasrw HvxVR:$Vs, I32:$Rt)>;
|
||||
def: Pat<(HexagonVLSR HVI16:$Vs, I32:$Rt), (V6_vlsrh HvxVR:$Vs, I32:$Rt)>;
|
||||
def: Pat<(HexagonVLSR HVI32:$Vs, I32:$Rt), (V6_vlsrw HvxVR:$Vs, I32:$Rt)>;
|
||||
|
||||
def: Pat<(shl HVI16:$Vs, HVI16:$Vt), (V6_vaslhv HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(shl HVI32:$Vs, HVI32:$Vt), (V6_vaslwv HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(sra HVI16:$Vs, HVI16:$Vt), (V6_vasrhv HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
def: Pat<(sra HVI32:$Vs, HVI32:$Vt), (V6_vasrwv HvxVR:$Vs, HvxVR:$Vt)>;
|
||||
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)),
|
||||
(V6_vpackeh (HiVec $Vss), (LoVec $Vss))>;
|
||||
}
|
||||
|
||||
class HvxSel_pat<InstHexagon MI, PatFrag RegPred>
|
||||
: Pat<(select I1:$Pu, RegPred:$Vs, RegPred:$Vt),
|
||||
(MI I1:$Pu, RegPred:$Vs, RegPred:$Vt)>;
|
||||
|
||||
let Predicates = [HasV60T,UseHVX] in {
|
||||
def: HvxSel_pat<PS_vselect, HVI8>;
|
||||
def: HvxSel_pat<PS_vselect, HVI16>;
|
||||
def: HvxSel_pat<PS_vselect, HVI32>;
|
||||
def: HvxSel_pat<PS_wselect, HWI8>;
|
||||
def: HvxSel_pat<PS_wselect, HWI16>;
|
||||
def: HvxSel_pat<PS_wselect, HWI32>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue