Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 776 Lines • ▼ Show 20 Lines | AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM, | ||||
setTargetDAGCombine(ISD::SIGN_EXTEND); | setTargetDAGCombine(ISD::SIGN_EXTEND); | ||||
setTargetDAGCombine(ISD::SIGN_EXTEND_INREG); | setTargetDAGCombine(ISD::SIGN_EXTEND_INREG); | ||||
setTargetDAGCombine(ISD::TRUNCATE); | setTargetDAGCombine(ISD::TRUNCATE); | ||||
setTargetDAGCombine(ISD::CONCAT_VECTORS); | setTargetDAGCombine(ISD::CONCAT_VECTORS); | ||||
setTargetDAGCombine(ISD::STORE); | setTargetDAGCombine(ISD::STORE); | ||||
if (Subtarget->supportsAddressTopByteIgnored()) | if (Subtarget->supportsAddressTopByteIgnored()) | ||||
setTargetDAGCombine(ISD::LOAD); | setTargetDAGCombine(ISD::LOAD); | ||||
setTargetDAGCombine(ISD::MSCATTER); | |||||
setTargetDAGCombine(ISD::MUL); | setTargetDAGCombine(ISD::MUL); | ||||
setTargetDAGCombine(ISD::SELECT); | setTargetDAGCombine(ISD::SELECT); | ||||
setTargetDAGCombine(ISD::VSELECT); | setTargetDAGCombine(ISD::VSELECT); | ||||
setTargetDAGCombine(ISD::INTRINSIC_VOID); | setTargetDAGCombine(ISD::INTRINSIC_VOID); | ||||
setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN); | setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN); | ||||
setTargetDAGCombine(ISD::INSERT_VECTOR_ELT); | setTargetDAGCombine(ISD::INSERT_VECTOR_ELT); | ||||
▲ Show 20 Lines • Show All 203 Lines • ▼ Show 20 Lines | if (Subtarget->hasSVE()) { | ||||
// splat of 0 or undef) once vector selects supported in SVE codegen. See | // splat of 0 or undef) once vector selects supported in SVE codegen. See | ||||
// D68877 for more details. | // D68877 for more details. | ||||
for (auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64}) { | for (auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64}) { | ||||
setOperationAction(ISD::INSERT_SUBVECTOR, VT, Custom); | setOperationAction(ISD::INSERT_SUBVECTOR, VT, Custom); | ||||
setOperationAction(ISD::UINT_TO_FP, VT, Custom); | setOperationAction(ISD::UINT_TO_FP, VT, Custom); | ||||
setOperationAction(ISD::SINT_TO_FP, VT, Custom); | setOperationAction(ISD::SINT_TO_FP, VT, Custom); | ||||
setOperationAction(ISD::FP_TO_UINT, VT, Custom); | setOperationAction(ISD::FP_TO_UINT, VT, Custom); | ||||
setOperationAction(ISD::FP_TO_SINT, VT, Custom); | setOperationAction(ISD::FP_TO_SINT, VT, Custom); | ||||
setOperationAction(ISD::MSCATTER, VT, Custom); | |||||
setOperationAction(ISD::MUL, VT, Custom); | setOperationAction(ISD::MUL, VT, Custom); | ||||
setOperationAction(ISD::SPLAT_VECTOR, VT, Custom); | setOperationAction(ISD::SPLAT_VECTOR, VT, Custom); | ||||
setOperationAction(ISD::SELECT, VT, Custom); | setOperationAction(ISD::SELECT, VT, Custom); | ||||
setOperationAction(ISD::SDIV, VT, Custom); | setOperationAction(ISD::SDIV, VT, Custom); | ||||
setOperationAction(ISD::UDIV, VT, Custom); | setOperationAction(ISD::UDIV, VT, Custom); | ||||
setOperationAction(ISD::SMIN, VT, Custom); | setOperationAction(ISD::SMIN, VT, Custom); | ||||
setOperationAction(ISD::UMIN, VT, Custom); | setOperationAction(ISD::UMIN, VT, Custom); | ||||
setOperationAction(ISD::SMAX, VT, Custom); | setOperationAction(ISD::SMAX, VT, Custom); | ||||
Show All 24 Lines | for (auto VT : {MVT::nxv16i1, MVT::nxv8i1, MVT::nxv4i1, MVT::nxv2i1}) { | ||||
AddPromotedToType(ISD::UINT_TO_FP, VT, getPromotedVTForPredicate(VT)); | AddPromotedToType(ISD::UINT_TO_FP, VT, getPromotedVTForPredicate(VT)); | ||||
} | } | ||||
} | } | ||||
for (auto VT : {MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32, | for (auto VT : {MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32, | ||||
MVT::nxv4f32, MVT::nxv2f64}) { | MVT::nxv4f32, MVT::nxv2f64}) { | ||||
setOperationAction(ISD::CONCAT_VECTORS, VT, Custom); | setOperationAction(ISD::CONCAT_VECTORS, VT, Custom); | ||||
setOperationAction(ISD::INSERT_SUBVECTOR, VT, Custom); | setOperationAction(ISD::INSERT_SUBVECTOR, VT, Custom); | ||||
setOperationAction(ISD::MSCATTER, VT, Custom); | |||||
setOperationAction(ISD::SPLAT_VECTOR, VT, Custom); | setOperationAction(ISD::SPLAT_VECTOR, VT, Custom); | ||||
setOperationAction(ISD::SELECT, VT, Custom); | setOperationAction(ISD::SELECT, VT, Custom); | ||||
setOperationAction(ISD::FADD, VT, Custom); | setOperationAction(ISD::FADD, VT, Custom); | ||||
setOperationAction(ISD::FDIV, VT, Custom); | setOperationAction(ISD::FDIV, VT, Custom); | ||||
setOperationAction(ISD::FMA, VT, Custom); | setOperationAction(ISD::FMA, VT, Custom); | ||||
setOperationAction(ISD::FMUL, VT, Custom); | setOperationAction(ISD::FMUL, VT, Custom); | ||||
setOperationAction(ISD::FNEG, VT, Custom); | setOperationAction(ISD::FNEG, VT, Custom); | ||||
setOperationAction(ISD::FSUB, VT, Custom); | setOperationAction(ISD::FSUB, VT, Custom); | ||||
setOperationAction(ISD::FCEIL, VT, Custom); | setOperationAction(ISD::FCEIL, VT, Custom); | ||||
setOperationAction(ISD::FFLOOR, VT, Custom); | setOperationAction(ISD::FFLOOR, VT, Custom); | ||||
setOperationAction(ISD::FNEARBYINT, VT, Custom); | setOperationAction(ISD::FNEARBYINT, VT, Custom); | ||||
setOperationAction(ISD::FRINT, VT, Custom); | setOperationAction(ISD::FRINT, VT, Custom); | ||||
setOperationAction(ISD::FROUND, VT, Custom); | setOperationAction(ISD::FROUND, VT, Custom); | ||||
setOperationAction(ISD::FROUNDEVEN, VT, Custom); | setOperationAction(ISD::FROUNDEVEN, VT, Custom); | ||||
setOperationAction(ISD::FTRUNC, VT, Custom); | setOperationAction(ISD::FTRUNC, VT, Custom); | ||||
setOperationAction(ISD::FSQRT, VT, Custom); | setOperationAction(ISD::FSQRT, VT, Custom); | ||||
setOperationAction(ISD::FABS, VT, Custom); | setOperationAction(ISD::FABS, VT, Custom); | ||||
setOperationAction(ISD::FP_EXTEND, VT, Custom); | setOperationAction(ISD::FP_EXTEND, VT, Custom); | ||||
setOperationAction(ISD::FP_ROUND, VT, Custom); | setOperationAction(ISD::FP_ROUND, VT, Custom); | ||||
} | } | ||||
setOperationAction(ISD::SPLAT_VECTOR, MVT::nxv8bf16, Custom); | setOperationAction(ISD::SPLAT_VECTOR, MVT::nxv8bf16, Custom); | ||||
for (auto VT : {MVT::nxv2bf16, MVT::nxv4bf16, MVT::nxv8bf16}) | |||||
setOperationAction(ISD::MSCATTER, VT, Custom); | |||||
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i8, Custom); | setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i8, Custom); | ||||
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i16, Custom); | setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i16, Custom); | ||||
// NOTE: Currently this has to happen after computeRegisterProperties rather | // NOTE: Currently this has to happen after computeRegisterProperties rather | ||||
// than the preferred option of combining it with the addRegisterClass call. | // than the preferred option of combining it with the addRegisterClass call. | ||||
if (useSVEForFixedLengthVectors()) { | if (useSVEForFixedLengthVectors()) { | ||||
for (MVT VT : MVT::integer_fixedlen_vector_valuetypes()) | for (MVT VT : MVT::integer_fixedlen_vector_valuetypes()) | ||||
if (useSVEForFixedLengthVectorVT(VT)) | if (useSVEForFixedLengthVectorVT(VT)) | ||||
▲ Show 20 Lines • Show All 2,610 Lines • ▼ Show 20 Lines | SDValue AArch64TargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, | ||||
} | } | ||||
case Intrinsic::aarch64_neon_sabd: { | case Intrinsic::aarch64_neon_sabd: { | ||||
return DAG.getNode(AArch64ISD::SABD, dl, Op.getValueType(), | return DAG.getNode(AArch64ISD::SABD, dl, Op.getValueType(), | ||||
Op.getOperand(1), Op.getOperand(2)); | Op.getOperand(1), Op.getOperand(2)); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
bool AArch64TargetLowering::isLegalMaskedGSIndexType(EVT VT) const { | |||||
if (VT.getVectorElementType() == MVT::i32 && | |||||
sdesmalen: Is that right though? nxv2i32 is not a legal type.
I feel like the interface is actually… | |||||
Changed isLegalMaskedGSIndexType to instead return true only if the index is extended from i32 & the number of elements is >=4. The test above has been added to sve-masked-scatter-legalise.ll, along with some other tests where the offset vector type is illegal. kmclaughlin: Changed `isLegalMaskedGSIndexType` to instead return true only if the index is extended from… | |||||
After this change, I think isLegalMaskedGSIndexType is a misnomer, because nxv8i32 is not a legal type for SVE. sdesmalen: After this change, I think `isLegalMaskedGSIndexType` is a misnomer, because `nxv8i32` is not a… | |||||
VT.getVectorElementCount().getKnownMinValue() >= 4) | |||||
return true; | |||||
return false; | |||||
} | |||||
bool AArch64TargetLowering::isVectorLoadExtDesirable(SDValue ExtVal) const { | bool AArch64TargetLowering::isVectorLoadExtDesirable(SDValue ExtVal) const { | ||||
return ExtVal.getValueType().isScalableVector(); | return ExtVal.getValueType().isScalableVector(); | ||||
} | } | ||||
// Custom lower trunc store for v4i8 vectors, since it is promoted to v4i16. | // Custom lower trunc store for v4i8 vectors, since it is promoted to v4i16. | ||||
static SDValue LowerTruncateVectorStore(SDLoc DL, StoreSDNode *ST, | static SDValue LowerTruncateVectorStore(SDLoc DL, StoreSDNode *ST, | ||||
EVT VT, EVT MemVT, | EVT VT, EVT MemVT, | ||||
SelectionDAG &DAG) { | SelectionDAG &DAG) { | ||||
Show All 20 Lines | static SDValue LowerTruncateVectorStore(SDLoc DL, StoreSDNode *ST, | ||||
Trunc = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Trunc); | Trunc = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Trunc); | ||||
SDValue ExtractTrunc = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, | SDValue ExtractTrunc = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, | ||||
Trunc, DAG.getConstant(0, DL, MVT::i64)); | Trunc, DAG.getConstant(0, DL, MVT::i64)); | ||||
return DAG.getStore(ST->getChain(), DL, ExtractTrunc, | return DAG.getStore(ST->getChain(), DL, ExtractTrunc, | ||||
ST->getBasePtr(), ST->getMemOperand()); | ST->getBasePtr(), ST->getMemOperand()); | ||||
} | } | ||||
unsigned getScatterVecOpcode(bool IsScaled, bool IsSigned, bool NeedsExtend) { | |||||
std::map<std::tuple<bool, bool, bool>, unsigned> AddrModes = { | |||||
{std::make_tuple(/*Scaled*/ false, /*Signed*/ false, /*Extend*/ false), | |||||
AArch64ISD::SST1_PRED}, | |||||
{std::make_tuple(/*Scaled*/ false, /*Signed*/ false, /*Extend*/ true), | |||||
AArch64ISD::SST1_UXTW_PRED}, | |||||
{std::make_tuple(/*Scaled*/ false, /*Signed*/ true, /*Extend*/ false), | |||||
AArch64ISD::SST1_PRED}, | |||||
{std::make_tuple(/*Scaled*/ false, /*Signed*/ true, /*Extend*/ true), | |||||
AArch64ISD::SST1_SXTW_PRED}, | |||||
{std::make_tuple(/*Scaled*/ true, /*Signed*/ false, /*Extend*/ false), | |||||
AArch64ISD::SST1_SCALED_PRED}, | |||||
{std::make_tuple(/*Scaled*/ true, /*Signed*/ false, /*Extend*/ true), | |||||
AArch64ISD::SST1_UXTW_SCALED_PRED}, | |||||
{std::make_tuple(/*Scaled*/ true, /*Signed*/ true, /*Extend*/ false), | |||||
AArch64ISD::SST1_SCALED_PRED}, | |||||
{std::make_tuple(/*Scaled*/ true, /*Signed*/ true, /*Extend*/ true), | |||||
AArch64ISD::SST1_SXTW_SCALED_PRED}, | |||||
}; | |||||
auto Key = std::make_tuple(IsScaled, IsSigned, NeedsExtend); | |||||
return AddrModes.find(Key)->second; | |||||
} | |||||
bool getScatterIndexIsExtended(SDValue Index) { | |||||
unsigned Opcode = Index.getOpcode(); | |||||
if (Opcode == ISD::SIGN_EXTEND_INREG) | |||||
return true; | |||||
if (Opcode == ISD::AND) { | |||||
SDValue Splat = Index.getOperand(1); | |||||
if (Splat.getOpcode() != ISD::SPLAT_VECTOR) | |||||
return false; | |||||
ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(Splat.getOperand(0)); | |||||
if (!Mask || Mask->getZExtValue() != 0xFFFFFFFF) | |||||
return false; | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
SDValue AArch64TargetLowering::LowerMSCATTER(SDValue Op, | |||||
SelectionDAG &DAG) const { | |||||
SDLoc DL(Op); | |||||
MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(Op); | |||||
assert(MSC && "Can only custom lower scatter store nodes"); | |||||
SDValue Index = MSC->getIndex(); | |||||
SDValue Chain = MSC->getChain(); | |||||
SDValue StoreVal = MSC->getValue(); | |||||
SDValue Mask = MSC->getMask(); | |||||
SDValue BasePtr = MSC->getBasePtr(); | |||||
ISD::MemIndexType IndexType = MSC->getIndexType(); | |||||
bool IsScaled = | |||||
IndexType == ISD::SIGNED_SCALED || IndexType == ISD::UNSIGNED_SCALED; | |||||
bool IsSigned = | |||||
IndexType == ISD::SIGNED_SCALED || IndexType == ISD::SIGNED_UNSCALED; | |||||
bool NeedsExtend = getScatterIndexIsExtended(Index) || | |||||
Index.getSimpleValueType().getVectorElementType() == MVT::i32; | |||||
EVT VT = StoreVal.getSimpleValueType(); | |||||
SDVTList VTs = DAG.getVTList(MVT::Other); | |||||
EVT MemVT = MSC->getMemoryVT(); | |||||
SDValue InputVT = DAG.getValueType(MemVT); | |||||
if (VT.getVectorElementType() == MVT::bf16 && | |||||
!static_cast<const AArch64Subtarget &>(DAG.getSubtarget()).hasBF16()) | |||||
return SDValue(); | |||||
// Handle FP data | |||||
if (VT.isFloatingPoint()) { | |||||
VT = VT.changeVectorElementTypeToInteger(); | |||||
ElementCount EC = VT.getVectorElementCount(); | |||||
auto ScalarIntVT = | |||||
MVT::getIntegerVT(AArch64::SVEBitsPerBlock / EC.getKnownMinValue()); | |||||
StoreVal = DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, | |||||
MVT::getVectorVT(ScalarIntVT, EC), StoreVal); | |||||
InputVT = DAG.getValueType(MemVT.changeVectorElementTypeToInteger()); | |||||
} | |||||
if (getScatterIndexIsExtended(Index)) | |||||
Index = Index.getOperand(0); | |||||
SDValue Ops[] = {Chain, StoreVal, Mask, BasePtr, Index, InputVT}; | |||||
return DAG.getNode(getScatterVecOpcode(IsScaled, IsSigned, NeedsExtend), DL, | |||||
VTs, Ops); | |||||
} | |||||
// Custom lowering for any store, vector or scalar and/or default or with | // Custom lowering for any store, vector or scalar and/or default or with | ||||
// a truncate operations. Currently only custom lower truncate operation | // a truncate operations. Currently only custom lower truncate operation | ||||
// from vector v4i16 to v4i8 or volatile stores of i128. | // from vector v4i16 to v4i8 or volatile stores of i128. | ||||
SDValue AArch64TargetLowering::LowerSTORE(SDValue Op, | SDValue AArch64TargetLowering::LowerSTORE(SDValue Op, | ||||
SelectionDAG &DAG) const { | SelectionDAG &DAG) const { | ||||
SDLoc Dl(Op); | SDLoc Dl(Op); | ||||
StoreSDNode *StoreNode = cast<StoreSDNode>(Op); | StoreSDNode *StoreNode = cast<StoreSDNode>(Op); | ||||
assert (StoreNode && "Can only custom lower store nodes"); | assert (StoreNode && "Can only custom lower store nodes"); | ||||
▲ Show 20 Lines • Show All 231 Lines • ▼ Show 20 Lines | SDValue AArch64TargetLowering::LowerOperation(SDValue Op, | ||||
case ISD::MUL: | case ISD::MUL: | ||||
return LowerMUL(Op, DAG); | return LowerMUL(Op, DAG); | ||||
case ISD::INTRINSIC_WO_CHAIN: | case ISD::INTRINSIC_WO_CHAIN: | ||||
return LowerINTRINSIC_WO_CHAIN(Op, DAG); | return LowerINTRINSIC_WO_CHAIN(Op, DAG); | ||||
case ISD::STORE: | case ISD::STORE: | ||||
return LowerSTORE(Op, DAG); | return LowerSTORE(Op, DAG); | ||||
case ISD::VECREDUCE_SEQ_FADD: | case ISD::VECREDUCE_SEQ_FADD: | ||||
return LowerVECREDUCE_SEQ_FADD(Op, DAG); | return LowerVECREDUCE_SEQ_FADD(Op, DAG); | ||||
case ISD::MSCATTER: | |||||
return LowerMSCATTER(Op, DAG); | |||||
case ISD::VECREDUCE_ADD: | case ISD::VECREDUCE_ADD: | ||||
case ISD::VECREDUCE_AND: | case ISD::VECREDUCE_AND: | ||||
case ISD::VECREDUCE_OR: | case ISD::VECREDUCE_OR: | ||||
case ISD::VECREDUCE_XOR: | case ISD::VECREDUCE_XOR: | ||||
case ISD::VECREDUCE_SMAX: | case ISD::VECREDUCE_SMAX: | ||||
case ISD::VECREDUCE_SMIN: | case ISD::VECREDUCE_SMIN: | ||||
case ISD::VECREDUCE_UMAX: | case ISD::VECREDUCE_UMAX: | ||||
case ISD::VECREDUCE_UMIN: | case ISD::VECREDUCE_UMIN: | ||||
▲ Show 20 Lines • Show All 9,775 Lines • ▼ Show 20 Lines | static SDValue performSTORECombine(SDNode *N, | ||||
if (Subtarget->supportsAddressTopByteIgnored() && | if (Subtarget->supportsAddressTopByteIgnored() && | ||||
performTBISimplification(N->getOperand(2), DCI, DAG)) | performTBISimplification(N->getOperand(2), DCI, DAG)) | ||||
return SDValue(N, 0); | return SDValue(N, 0); | ||||
return SDValue(); | return SDValue(); | ||||
} | } | ||||
static SDValue performMSCATTERCombine(SDNode *N, | |||||
TargetLowering::DAGCombinerInfo &DCI, | |||||
SelectionDAG &DAG) { | |||||
MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N); | |||||
assert(MSC && "Can only combine scatter store nodes"); | |||||
SDLoc DL(MSC); | |||||
SDValue Chain = MSC->getChain(); | |||||
SDValue Scale = MSC->getScale(); | |||||
SDValue Index = MSC->getIndex(); | |||||
SDValue Data = MSC->getValue(); | |||||
SDValue Mask = MSC->getMask(); | |||||
SDValue BasePtr = MSC->getBasePtr(); | |||||
ISD::MemIndexType IndexType = MSC->getIndexType(); | |||||
EVT IdxVT = Index.getValueType(); | |||||
if (DCI.isBeforeLegalize()) { | |||||
// SVE gather/scatter requires indices of i32/i64. Promote anything smaller | |||||
// prior to legalisation so the result can be split if required. | |||||
if ((IdxVT.getVectorElementType() == MVT::i8) || | |||||
(IdxVT.getVectorElementType() == MVT::i16)) { | |||||
EVT NewIdxVT = IdxVT.changeVectorElementType(MVT::i32); | |||||
if (MSC->isIndexSigned()) | |||||
Index = DAG.getNode(ISD::SIGN_EXTEND, DL, NewIdxVT, Index); | |||||
else | |||||
Index = DAG.getNode(ISD::ZERO_EXTEND, DL, NewIdxVT, Index); | |||||
SDValue Ops[] = { Chain, Data, Mask, BasePtr, Index, Scale }; | |||||
return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), | |||||
MSC->getMemoryVT(), DL, Ops, | |||||
MSC->getMemOperand(), IndexType, | |||||
MSC->isTruncatingStore()); | |||||
} | |||||
} | |||||
return SDValue(); | |||||
} | |||||
/// Target-specific DAG combine function for NEON load/store intrinsics | /// Target-specific DAG combine function for NEON load/store intrinsics | ||||
/// to merge base address updates. | /// to merge base address updates. | ||||
static SDValue performNEONPostLDSTCombine(SDNode *N, | static SDValue performNEONPostLDSTCombine(SDNode *N, | ||||
TargetLowering::DAGCombinerInfo &DCI, | TargetLowering::DAGCombinerInfo &DCI, | ||||
SelectionDAG &DAG) { | SelectionDAG &DAG) { | ||||
if (DCI.isBeforeLegalize() || DCI.isCalledByLegalizer()) | if (DCI.isBeforeLegalize() || DCI.isCalledByLegalizer()) | ||||
return SDValue(); | return SDValue(); | ||||
▲ Show 20 Lines • Show All 1,176 Lines • ▼ Show 20 Lines | SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N, | ||||
case ISD::VSELECT: | case ISD::VSELECT: | ||||
return performVSelectCombine(N, DCI.DAG); | return performVSelectCombine(N, DCI.DAG); | ||||
case ISD::LOAD: | case ISD::LOAD: | ||||
if (performTBISimplification(N->getOperand(1), DCI, DAG)) | if (performTBISimplification(N->getOperand(1), DCI, DAG)) | ||||
return SDValue(N, 0); | return SDValue(N, 0); | ||||
break; | break; | ||||
case ISD::STORE: | case ISD::STORE: | ||||
return performSTORECombine(N, DCI, DAG, Subtarget); | return performSTORECombine(N, DCI, DAG, Subtarget); | ||||
case ISD::MSCATTER: | |||||
return performMSCATTERCombine(N, DCI, DAG); | |||||
case AArch64ISD::BRCOND: | case AArch64ISD::BRCOND: | ||||
return performBRCONDCombine(N, DCI, DAG); | return performBRCONDCombine(N, DCI, DAG); | ||||
case AArch64ISD::TBNZ: | case AArch64ISD::TBNZ: | ||||
case AArch64ISD::TBZ: | case AArch64ISD::TBZ: | ||||
return performTBZCombine(N, DCI, DAG); | return performTBZCombine(N, DCI, DAG); | ||||
case AArch64ISD::CSEL: | case AArch64ISD::CSEL: | ||||
return performCONDCombine(N, DCI, DAG, 2, 3); | return performCONDCombine(N, DCI, DAG, 2, 3); | ||||
case AArch64ISD::DUP: | case AArch64ISD::DUP: | ||||
▲ Show 20 Lines • Show All 1,027 Lines • ▼ Show 20 Lines | bool AArch64TargetLowering::fallBackToDAGISel(const Instruction &Inst) const { | ||||
if (const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) { | if (const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) { | ||||
if (isa<ScalableVectorType>(AI->getAllocatedType())) | if (isa<ScalableVectorType>(AI->getAllocatedType())) | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
ISD::MemIndexType | |||||
AArch64TargetLowering::getCanonicalIndexType(ISD::MemIndexType IndexType, | |||||
EVT MemVT, SDValue Offsets) const { | |||||
bool ScaledIndex = (IndexType == ISD::SIGNED_SCALED) || | |||||
sdesmalenUnsubmitted nit: s/ScaledIndex/IsScaledIndex/ sdesmalen: nit: s/ScaledIndex/IsScaledIndex/
nit: s/SignedIndex/IsSignedIndex/ | |||||
(IndexType == ISD::UNSIGNED_SCALED); | |||||
bool SignedIndex = (IndexType == ISD::SIGNED_SCALED) || | |||||
(IndexType == ISD::SIGNED_UNSCALED); | |||||
// Scaling is unimportant for bytes, canonicalize to unscaled. | |||||
if (ScaledIndex && MemVT.getScalarType() == MVT::i8) { | |||||
ScaledIndex = false; | |||||
IndexType = SignedIndex ? ISD::SIGNED_UNSCALED : ISD::UNSIGNED_UNSCALED; | |||||
} | |||||
return IndexType; | |||||
} | |||||
// Return the largest legal scalable vector type that matches VT's element type. | // Return the largest legal scalable vector type that matches VT's element type. | ||||
static EVT getContainerForFixedLengthVector(SelectionDAG &DAG, EVT VT) { | static EVT getContainerForFixedLengthVector(SelectionDAG &DAG, EVT VT) { | ||||
assert(VT.isFixedLengthVector() && | assert(VT.isFixedLengthVector() && | ||||
DAG.getTargetLoweringInfo().isTypeLegal(VT) && | DAG.getTargetLoweringInfo().isTypeLegal(VT) && | ||||
"Expected legal fixed length vector!"); | "Expected legal fixed length vector!"); | ||||
switch (VT.getVectorElementType().getSimpleVT().SimpleTy) { | switch (VT.getVectorElementType().getSimpleVT().SimpleTy) { | ||||
default: | default: | ||||
llvm_unreachable("unexpected element type for SVE container"); | llvm_unreachable("unexpected element type for SVE container"); | ||||
▲ Show 20 Lines • Show All 475 Lines • Show Last 20 Lines |
Is that right though? nxv2i32 is not a legal type.
I feel like the interface is actually asking the wrong question. I think the question the DAGCombiner wants to ask is: "should I remove the sign/zero-extend for the gather/scatter index". For SVE, that is true for indices that are extended like:
because the instruction can do this. It adds little value to add this for:
because the type itself needs to be promoted to nxv2i64 anyway.
If it asks the right question and you make it work for nxv8i32, then codegen for the following test would much improve:
(for which tests are currently missing in the patch)