#include "X86TargetTransformInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/BasicTTIImpl.h"
#include "llvm/CodeGen/CostTable.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
#define DEBUG_TYPE "x86tti"
TargetTransformInfo::PopcntSupportKind
X86TTIImpl::getPopcntSupport(unsigned TyWidth) {
assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
return ST->hasPOPCNT() ? TTI::PSK_FastHardware : TTI::PSK_Software;
}
llvm::Optional<unsigned> X86TTIImpl::getCacheSize(
TargetTransformInfo::CacheLevel Level) const {
switch (Level) {
case TargetTransformInfo::CacheLevel::L1D:
return 32 * 1024; case TargetTransformInfo::CacheLevel::L2D:
return 256 * 1024; }
llvm_unreachable("Unknown TargetTransformInfo::CacheLevel");
}
llvm::Optional<unsigned> X86TTIImpl::getCacheAssociativity(
TargetTransformInfo::CacheLevel Level) const {
switch (Level) {
case TargetTransformInfo::CacheLevel::L1D:
LLVM_FALLTHROUGH;
case TargetTransformInfo::CacheLevel::L2D:
return 8;
}
llvm_unreachable("Unknown TargetTransformInfo::CacheLevel");
}
unsigned X86TTIImpl::getNumberOfRegisters(unsigned ClassID) const {
bool Vector = (ClassID == 1);
if (Vector && !ST->hasSSE1())
return 0;
if (ST->is64Bit()) {
if (Vector && ST->hasAVX512())
return 32;
return 16;
}
return 8;
}
TypeSize
X86TTIImpl::getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const {
unsigned PreferVectorWidth = ST->getPreferVectorWidth();
switch (K) {
case TargetTransformInfo::RGK_Scalar:
return TypeSize::getFixed(ST->is64Bit() ? 64 : 32);
case TargetTransformInfo::RGK_FixedWidthVector:
if (ST->hasAVX512() && PreferVectorWidth >= 512)
return TypeSize::getFixed(512);
if (ST->hasAVX() && PreferVectorWidth >= 256)
return TypeSize::getFixed(256);
if (ST->hasSSE1() && PreferVectorWidth >= 128)
return TypeSize::getFixed(128);
return TypeSize::getFixed(0);
case TargetTransformInfo::RGK_ScalableVector:
return TypeSize::getScalable(0);
}
llvm_unreachable("Unsupported register kind");
}
unsigned X86TTIImpl::getLoadStoreVecRegBitWidth(unsigned) const {
return getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector)
.getFixedSize();
}
unsigned X86TTIImpl::getMaxInterleaveFactor(unsigned VF) {
if (VF == 1)
return 1;
if (ST->isAtom())
return 1;
if (ST->hasAVX())
return 4;
return 2;
}
InstructionCost X86TTIImpl::getArithmeticInstrCost(
unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
TTI::OperandValueKind Op1Info, TTI::OperandValueKind Op2Info,
TTI::OperandValueProperties Opd1PropInfo,
TTI::OperandValueProperties Opd2PropInfo, ArrayRef<const Value *> Args,
const Instruction *CxtI) {
if (CostKind != TTI::TCK_RecipThroughput)
return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
Op2Info, Opd1PropInfo,
Opd2PropInfo, Args, CxtI);
if (Opcode == Instruction::Mul && Ty->isVectorTy() &&
Ty->getScalarSizeInBits() == 8) {
Type *WideVecTy =
VectorType::getExtendedElementVectorType(cast<VectorType>(Ty));
return getCastInstrCost(Instruction::ZExt, WideVecTy, Ty,
TargetTransformInfo::CastContextHint::None,
CostKind) +
getCastInstrCost(Instruction::Trunc, Ty, WideVecTy,
TargetTransformInfo::CastContextHint::None,
CostKind) +
getArithmeticInstrCost(Opcode, WideVecTy, CostKind, Op1Info, Op2Info,
Opd1PropInfo, Opd2PropInfo);
}
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Ty);
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
if (ISD == ISD::MUL && Args.size() == 2 && LT.second.isVector() &&
LT.second.getScalarType() == MVT::i32) {
bool Op1Signed = false, Op2Signed = false;
unsigned Op1MinSize = BaseT::minRequiredElementSize(Args[0], Op1Signed);
unsigned Op2MinSize = BaseT::minRequiredElementSize(Args[1], Op2Signed);
unsigned OpMinSize = std::max(Op1MinSize, Op2MinSize);
if (OpMinSize <= 15 && !ST->isPMADDWDSlow()) {
bool Op1Constant =
isa<ConstantDataVector>(Args[0]) || isa<ConstantVector>(Args[0]);
bool Op2Constant =
isa<ConstantDataVector>(Args[1]) || isa<ConstantVector>(Args[1]);
bool Op1Sext = isa<SExtInst>(Args[0]) &&
(Op1MinSize == 15 || (Op1MinSize < 15 && !ST->hasSSE41()));
bool Op2Sext = isa<SExtInst>(Args[1]) &&
(Op2MinSize == 15 || (Op2MinSize < 15 && !ST->hasSSE41()));
bool IsZeroExtended = !Op1Signed || !Op2Signed;
bool IsConstant = Op1Constant || Op2Constant;
bool IsSext = Op1Sext || Op2Sext;
if (IsConstant || IsZeroExtended || IsSext)
LT.second =
MVT::getVectorVT(MVT::i16, 2 * LT.second.getVectorNumElements());
}
}
if (ISD == ISD::MUL &&
(Op2Info == TargetTransformInfo::OK_UniformConstantValue ||
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue) &&
Opd2PropInfo == TargetTransformInfo::OP_PowerOf2)
return getArithmeticInstrCost(Instruction::Shl, Ty, CostKind, Op1Info,
Op2Info, TargetTransformInfo::OP_None,
TargetTransformInfo::OP_None);
if ((ISD == ISD::SDIV || ISD == ISD::SREM) &&
(Op2Info == TargetTransformInfo::OK_UniformConstantValue ||
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue) &&
Opd2PropInfo == TargetTransformInfo::OP_PowerOf2) {
InstructionCost Cost =
2 * getArithmeticInstrCost(Instruction::AShr, Ty, CostKind, Op1Info,
Op2Info, TargetTransformInfo::OP_None,
TargetTransformInfo::OP_None);
Cost += getArithmeticInstrCost(Instruction::LShr, Ty, CostKind, Op1Info,
Op2Info, TargetTransformInfo::OP_None,
TargetTransformInfo::OP_None);
Cost += getArithmeticInstrCost(Instruction::Add, Ty, CostKind, Op1Info,
Op2Info, TargetTransformInfo::OP_None,
TargetTransformInfo::OP_None);
if (ISD == ISD::SREM) {
Cost += getArithmeticInstrCost(Instruction::Mul, Ty, CostKind, Op1Info,
Op2Info);
Cost += getArithmeticInstrCost(Instruction::Sub, Ty, CostKind, Op1Info,
Op2Info);
}
return Cost;
}
if ((ISD == ISD::UDIV || ISD == ISD::UREM) &&
(Op2Info == TargetTransformInfo::OK_UniformConstantValue ||
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue) &&
Opd2PropInfo == TargetTransformInfo::OP_PowerOf2) {
if (ISD == ISD::UDIV)
return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind, Op1Info,
Op2Info, TargetTransformInfo::OP_None,
TargetTransformInfo::OP_None);
return getArithmeticInstrCost(Instruction::And, Ty, CostKind, Op1Info,
Op2Info, TargetTransformInfo::OP_None,
TargetTransformInfo::OP_None);
}
static const CostTblEntry GLMCostTable[] = {
{ ISD::FDIV, MVT::f32, 18 }, { ISD::FDIV, MVT::v4f32, 35 }, { ISD::FDIV, MVT::f64, 33 }, { ISD::FDIV, MVT::v2f64, 65 }, };
if (ST->useGLMDivSqrtCosts())
if (const auto *Entry = CostTableLookup(GLMCostTable, ISD,
LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry SLMCostTable[] = {
{ ISD::MUL, MVT::v4i32, 11 }, { ISD::MUL, MVT::v8i16, 2 }, { ISD::FMUL, MVT::f64, 2 }, { ISD::FMUL, MVT::v2f64, 4 }, { ISD::FMUL, MVT::v4f32, 2 }, { ISD::FDIV, MVT::f32, 17 }, { ISD::FDIV, MVT::v4f32, 39 }, { ISD::FDIV, MVT::f64, 32 }, { ISD::FDIV, MVT::v2f64, 69 }, { ISD::FADD, MVT::v2f64, 2 }, { ISD::FSUB, MVT::v2f64, 2 }, { ISD::MUL, MVT::v2i64, 17 },
{ ISD::ADD, MVT::v2i64, 4 },
{ ISD::SUB, MVT::v2i64, 4 },
};
if (ST->useSLMArithCosts()) {
if (Args.size() == 2 && ISD == ISD::MUL && LT.second == MVT::v4i32) {
bool Op1Signed = false;
unsigned Op1MinSize = BaseT::minRequiredElementSize(Args[0], Op1Signed);
bool Op2Signed = false;
unsigned Op2MinSize = BaseT::minRequiredElementSize(Args[1], Op2Signed);
bool SignedMode = Op1Signed || Op2Signed;
unsigned OpMinSize = std::max(Op1MinSize, Op2MinSize);
if (OpMinSize <= 7)
return LT.first * 3; if (!SignedMode && OpMinSize <= 8)
return LT.first * 3; if (OpMinSize <= 15)
return LT.first * 5; if (!SignedMode && OpMinSize <= 16)
return LT.first * 5; }
if (const auto *Entry = CostTableLookup(SLMCostTable, ISD,
LT.second)) {
return LT.first * Entry->Cost;
}
}
static const CostTblEntry AVX512BWUniformConstCostTable[] = {
{ ISD::SHL, MVT::v64i8, 2 }, { ISD::SRL, MVT::v64i8, 2 }, { ISD::SRA, MVT::v64i8, 4 }, };
if (Op2Info == TargetTransformInfo::OK_UniformConstantValue &&
ST->hasBWI()) {
if (const auto *Entry = CostTableLookup(AVX512BWUniformConstCostTable, ISD,
LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry AVX512UniformConstCostTable[] = {
{ ISD::SRA, MVT::v2i64, 1 },
{ ISD::SRA, MVT::v4i64, 1 },
{ ISD::SRA, MVT::v8i64, 1 },
{ ISD::SHL, MVT::v64i8, 4 }, { ISD::SRL, MVT::v64i8, 4 }, { ISD::SRA, MVT::v64i8, 8 },
{ ISD::SDIV, MVT::v16i32, 6 }, { ISD::SREM, MVT::v16i32, 8 }, { ISD::UDIV, MVT::v16i32, 5 }, { ISD::UREM, MVT::v16i32, 7 }, };
if (Op2Info == TargetTransformInfo::OK_UniformConstantValue &&
ST->hasAVX512()) {
if (const auto *Entry = CostTableLookup(AVX512UniformConstCostTable, ISD,
LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry AVX2UniformConstCostTable[] = {
{ ISD::SHL, MVT::v32i8, 2 }, { ISD::SRL, MVT::v32i8, 2 }, { ISD::SRA, MVT::v32i8, 4 },
{ ISD::SRA, MVT::v4i64, 4 },
{ ISD::SDIV, MVT::v8i32, 6 }, { ISD::SREM, MVT::v8i32, 8 }, { ISD::UDIV, MVT::v8i32, 5 }, { ISD::UREM, MVT::v8i32, 7 }, };
if (Op2Info == TargetTransformInfo::OK_UniformConstantValue &&
ST->hasAVX2()) {
if (const auto *Entry = CostTableLookup(AVX2UniformConstCostTable, ISD,
LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry SSE2UniformConstCostTable[] = {
{ ISD::SHL, MVT::v16i8, 2 }, { ISD::SRL, MVT::v16i8, 2 }, { ISD::SRA, MVT::v16i8, 4 },
{ ISD::SHL, MVT::v32i8, 4+2 }, { ISD::SRL, MVT::v32i8, 4+2 }, { ISD::SRA, MVT::v32i8, 8+2 },
{ ISD::SDIV, MVT::v8i32, 12+2 }, { ISD::SREM, MVT::v8i32, 16+2 }, { ISD::SDIV, MVT::v4i32, 6 }, { ISD::SREM, MVT::v4i32, 8 }, { ISD::UDIV, MVT::v8i32, 10+2 }, { ISD::UREM, MVT::v8i32, 14+2 }, { ISD::UDIV, MVT::v4i32, 5 }, { ISD::UREM, MVT::v4i32, 7 }, };
if (Op2Info == TargetTransformInfo::OK_UniformConstantValue &&
ST->hasSSE2() && !ST->hasXOP()) {
if (const auto *Entry =
CostTableLookup(SSE2UniformConstCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry AVX512BWConstCostTable[] = {
{ ISD::SDIV, MVT::v64i8, 14 }, { ISD::SREM, MVT::v64i8, 16 }, { ISD::UDIV, MVT::v64i8, 14 }, { ISD::UREM, MVT::v64i8, 16 }, { ISD::SDIV, MVT::v32i16, 6 }, { ISD::SREM, MVT::v32i16, 8 }, { ISD::UDIV, MVT::v32i16, 6 }, { ISD::UREM, MVT::v32i16, 8 }, };
if ((Op2Info == TargetTransformInfo::OK_UniformConstantValue ||
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue) &&
ST->hasBWI()) {
if (const auto *Entry =
CostTableLookup(AVX512BWConstCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry AVX512ConstCostTable[] = {
{ ISD::SDIV, MVT::v16i32, 15 }, { ISD::SREM, MVT::v16i32, 17 }, { ISD::UDIV, MVT::v16i32, 15 }, { ISD::UREM, MVT::v16i32, 17 }, { ISD::SDIV, MVT::v64i8, 28 }, { ISD::SREM, MVT::v64i8, 32 }, { ISD::UDIV, MVT::v64i8, 28 }, { ISD::UREM, MVT::v64i8, 32 }, { ISD::SDIV, MVT::v32i16, 12 }, { ISD::SREM, MVT::v32i16, 16 }, { ISD::UDIV, MVT::v32i16, 12 }, { ISD::UREM, MVT::v32i16, 16 }, };
if ((Op2Info == TargetTransformInfo::OK_UniformConstantValue ||
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue) &&
ST->hasAVX512()) {
if (const auto *Entry =
CostTableLookup(AVX512ConstCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry AVX2ConstCostTable[] = {
{ ISD::SDIV, MVT::v32i8, 14 }, { ISD::SREM, MVT::v32i8, 16 }, { ISD::UDIV, MVT::v32i8, 14 }, { ISD::UREM, MVT::v32i8, 16 }, { ISD::SDIV, MVT::v16i16, 6 }, { ISD::SREM, MVT::v16i16, 8 }, { ISD::UDIV, MVT::v16i16, 6 }, { ISD::UREM, MVT::v16i16, 8 }, { ISD::SDIV, MVT::v8i32, 15 }, { ISD::SREM, MVT::v8i32, 19 }, { ISD::UDIV, MVT::v8i32, 15 }, { ISD::UREM, MVT::v8i32, 19 }, };
if ((Op2Info == TargetTransformInfo::OK_UniformConstantValue ||
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue) &&
ST->hasAVX2()) {
if (const auto *Entry = CostTableLookup(AVX2ConstCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry SSE2ConstCostTable[] = {
{ ISD::SDIV, MVT::v32i8, 28+2 }, { ISD::SREM, MVT::v32i8, 32+2 }, { ISD::SDIV, MVT::v16i8, 14 }, { ISD::SREM, MVT::v16i8, 16 }, { ISD::UDIV, MVT::v32i8, 28+2 }, { ISD::UREM, MVT::v32i8, 32+2 }, { ISD::UDIV, MVT::v16i8, 14 }, { ISD::UREM, MVT::v16i8, 16 }, { ISD::SDIV, MVT::v16i16, 12+2 }, { ISD::SREM, MVT::v16i16, 16+2 }, { ISD::SDIV, MVT::v8i16, 6 }, { ISD::SREM, MVT::v8i16, 8 }, { ISD::UDIV, MVT::v16i16, 12+2 }, { ISD::UREM, MVT::v16i16, 16+2 }, { ISD::UDIV, MVT::v8i16, 6 }, { ISD::UREM, MVT::v8i16, 8 }, { ISD::SDIV, MVT::v8i32, 38+2 }, { ISD::SREM, MVT::v8i32, 48+2 }, { ISD::SDIV, MVT::v4i32, 19 }, { ISD::SREM, MVT::v4i32, 24 }, { ISD::UDIV, MVT::v8i32, 30+2 }, { ISD::UREM, MVT::v8i32, 40+2 }, { ISD::UDIV, MVT::v4i32, 15 }, { ISD::UREM, MVT::v4i32, 20 }, };
if ((Op2Info == TargetTransformInfo::OK_UniformConstantValue ||
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue) &&
ST->hasSSE2()) {
if (ISD == ISD::SDIV && LT.second == MVT::v8i32 && ST->hasAVX())
return LT.first * 32;
if (ISD == ISD::SREM && LT.second == MVT::v8i32 && ST->hasAVX())
return LT.first * 38;
if (ISD == ISD::SDIV && LT.second == MVT::v4i32 && ST->hasSSE41())
return LT.first * 15;
if (ISD == ISD::SREM && LT.second == MVT::v4i32 && ST->hasSSE41())
return LT.first * 20;
if (const auto *Entry = CostTableLookup(SSE2ConstCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry AVX512BWShiftCostTable[] = {
{ ISD::SHL, MVT::v16i8, 4 }, { ISD::SRL, MVT::v16i8, 4 }, { ISD::SRA, MVT::v16i8, 4 }, { ISD::SHL, MVT::v32i8, 4 }, { ISD::SRL, MVT::v32i8, 4 }, { ISD::SRA, MVT::v32i8, 6 }, { ISD::SHL, MVT::v64i8, 6 }, { ISD::SRL, MVT::v64i8, 7 }, { ISD::SRA, MVT::v64i8, 15 },
{ ISD::SHL, MVT::v8i16, 1 }, { ISD::SRL, MVT::v8i16, 1 }, { ISD::SRA, MVT::v8i16, 1 }, { ISD::SHL, MVT::v16i16, 1 }, { ISD::SRL, MVT::v16i16, 1 }, { ISD::SRA, MVT::v16i16, 1 }, { ISD::SHL, MVT::v32i16, 1 }, { ISD::SRL, MVT::v32i16, 1 }, { ISD::SRA, MVT::v32i16, 1 }, };
if (ST->hasBWI())
if (const auto *Entry = CostTableLookup(AVX512BWShiftCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry AVX2UniformCostTable[] = {
{ ISD::SHL, MVT::v16i16, 1 }, { ISD::SRL, MVT::v16i16, 1 }, { ISD::SRA, MVT::v16i16, 1 }, { ISD::SHL, MVT::v32i16, 2 }, { ISD::SRL, MVT::v32i16, 2 }, { ISD::SRA, MVT::v32i16, 2 },
{ ISD::SHL, MVT::v8i32, 1 }, { ISD::SRL, MVT::v8i32, 1 }, { ISD::SRA, MVT::v8i32, 1 }, { ISD::SHL, MVT::v4i64, 1 }, { ISD::SRL, MVT::v4i64, 1 }, };
if (ST->hasAVX2() &&
((Op2Info == TargetTransformInfo::OK_UniformConstantValue) ||
(Op2Info == TargetTransformInfo::OK_UniformValue))) {
if (const auto *Entry =
CostTableLookup(AVX2UniformCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry SSE2UniformCostTable[] = {
{ ISD::SHL, MVT::v8i16, 1 }, { ISD::SHL, MVT::v4i32, 1 }, { ISD::SHL, MVT::v2i64, 1 },
{ ISD::SRL, MVT::v8i16, 1 }, { ISD::SRL, MVT::v4i32, 1 }, { ISD::SRL, MVT::v2i64, 1 },
{ ISD::SRA, MVT::v8i16, 1 }, { ISD::SRA, MVT::v4i32, 1 }, };
if (ST->hasSSE2() &&
((Op2Info == TargetTransformInfo::OK_UniformConstantValue) ||
(Op2Info == TargetTransformInfo::OK_UniformValue))) {
if (const auto *Entry =
CostTableLookup(SSE2UniformCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry AVX512DQCostTable[] = {
{ ISD::MUL, MVT::v2i64, 2 }, { ISD::MUL, MVT::v4i64, 2 }, { ISD::MUL, MVT::v8i64, 2 } };
if (ST->hasDQI())
if (const auto *Entry = CostTableLookup(AVX512DQCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry AVX512BWCostTable[] = {
{ ISD::SHL, MVT::v64i8, 11 }, { ISD::SRL, MVT::v64i8, 11 }, { ISD::SRA, MVT::v64i8, 24 }, };
if (ST->hasBWI())
if (const auto *Entry = CostTableLookup(AVX512BWCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry AVX512CostTable[] = {
{ ISD::SHL, MVT::v4i32, 1 },
{ ISD::SRL, MVT::v4i32, 1 },
{ ISD::SRA, MVT::v4i32, 1 },
{ ISD::SHL, MVT::v8i32, 1 },
{ ISD::SRL, MVT::v8i32, 1 },
{ ISD::SRA, MVT::v8i32, 1 },
{ ISD::SHL, MVT::v16i32, 1 },
{ ISD::SRL, MVT::v16i32, 1 },
{ ISD::SRA, MVT::v16i32, 1 },
{ ISD::SHL, MVT::v2i64, 1 },
{ ISD::SRL, MVT::v2i64, 1 },
{ ISD::SHL, MVT::v4i64, 1 },
{ ISD::SRL, MVT::v4i64, 1 },
{ ISD::SHL, MVT::v8i64, 1 },
{ ISD::SRL, MVT::v8i64, 1 },
{ ISD::SRA, MVT::v2i64, 1 },
{ ISD::SRA, MVT::v4i64, 1 },
{ ISD::SRA, MVT::v8i64, 1 },
{ ISD::MUL, MVT::v16i32, 1 }, { ISD::MUL, MVT::v8i32, 1 }, { ISD::MUL, MVT::v4i32, 1 }, { ISD::MUL, MVT::v8i64, 6 }, { ISD::MUL, MVT::i64, 1 },
{ ISD::FNEG, MVT::v8f64, 1 }, { ISD::FADD, MVT::v8f64, 1 }, { ISD::FSUB, MVT::v8f64, 1 }, { ISD::FMUL, MVT::v8f64, 1 }, { ISD::FDIV, MVT::f64, 4 }, { ISD::FDIV, MVT::v2f64, 4 }, { ISD::FDIV, MVT::v4f64, 8 }, { ISD::FDIV, MVT::v8f64, 16 },
{ ISD::FNEG, MVT::v16f32, 1 }, { ISD::FADD, MVT::v16f32, 1 }, { ISD::FSUB, MVT::v16f32, 1 }, { ISD::FMUL, MVT::v16f32, 1 }, { ISD::FDIV, MVT::f32, 3 }, { ISD::FDIV, MVT::v4f32, 3 }, { ISD::FDIV, MVT::v8f32, 5 }, { ISD::FDIV, MVT::v16f32, 10 }, };
if (ST->hasAVX512())
if (const auto *Entry = CostTableLookup(AVX512CostTable, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry AVX2ShiftCostTable[] = {
{ ISD::SHL, MVT::v4i32, 2 }, { ISD::SRL, MVT::v4i32, 2 }, { ISD::SRA, MVT::v4i32, 2 }, { ISD::SHL, MVT::v8i32, 2 }, { ISD::SRL, MVT::v8i32, 2 }, { ISD::SRA, MVT::v8i32, 2 }, { ISD::SHL, MVT::v2i64, 1 }, { ISD::SRL, MVT::v2i64, 1 }, { ISD::SHL, MVT::v4i64, 1 }, { ISD::SRL, MVT::v4i64, 1 }, };
if (ST->hasAVX512()) {
if (ISD == ISD::SHL && LT.second == MVT::v32i16 &&
(Op2Info == TargetTransformInfo::OK_UniformConstantValue ||
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue))
return getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
Op1Info, Op2Info,
TargetTransformInfo::OP_None,
TargetTransformInfo::OP_None);
}
if (ST->hasAVX2() && !(ST->hasXOP() && LT.second == MVT::v4i32)) {
if (ISD == ISD::SHL && LT.second == MVT::v16i16 &&
(Op2Info == TargetTransformInfo::OK_UniformConstantValue ||
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue))
return getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
Op1Info, Op2Info,
TargetTransformInfo::OP_None,
TargetTransformInfo::OP_None);
if (const auto *Entry = CostTableLookup(AVX2ShiftCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry XOPShiftCostTable[] = {
{ ISD::SHL, MVT::v16i8, 1 },
{ ISD::SRL, MVT::v16i8, 2 },
{ ISD::SRA, MVT::v16i8, 2 },
{ ISD::SHL, MVT::v8i16, 1 },
{ ISD::SRL, MVT::v8i16, 2 },
{ ISD::SRA, MVT::v8i16, 2 },
{ ISD::SHL, MVT::v4i32, 1 },
{ ISD::SRL, MVT::v4i32, 2 },
{ ISD::SRA, MVT::v4i32, 2 },
{ ISD::SHL, MVT::v2i64, 1 },
{ ISD::SRL, MVT::v2i64, 2 },
{ ISD::SRA, MVT::v2i64, 2 },
{ ISD::SHL, MVT::v32i8, 2+2 },
{ ISD::SRL, MVT::v32i8, 4+2 },
{ ISD::SRA, MVT::v32i8, 4+2 },
{ ISD::SHL, MVT::v16i16, 2+2 },
{ ISD::SRL, MVT::v16i16, 4+2 },
{ ISD::SRA, MVT::v16i16, 4+2 },
{ ISD::SHL, MVT::v8i32, 2+2 },
{ ISD::SRL, MVT::v8i32, 4+2 },
{ ISD::SRA, MVT::v8i32, 4+2 },
{ ISD::SHL, MVT::v4i64, 2+2 },
{ ISD::SRL, MVT::v4i64, 4+2 },
{ ISD::SRA, MVT::v4i64, 4+2 },
};
if (ST->hasXOP()) {
int ShiftISD = ISD;
if ((ShiftISD == ISD::SRL || ShiftISD == ISD::SRA) &&
(Op2Info == TargetTransformInfo::OK_UniformConstantValue ||
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue))
ShiftISD = ISD::SHL;
if (const auto *Entry =
CostTableLookup(XOPShiftCostTable, ShiftISD, LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry SSE2UniformShiftCostTable[] = {
{ ISD::SHL, MVT::v16i16, 2+2 }, { ISD::SHL, MVT::v8i32, 2+2 }, { ISD::SHL, MVT::v4i64, 2+2 },
{ ISD::SRL, MVT::v16i16, 2+2 }, { ISD::SRL, MVT::v8i32, 2+2 }, { ISD::SRL, MVT::v4i64, 2+2 },
{ ISD::SRA, MVT::v16i16, 2+2 }, { ISD::SRA, MVT::v8i32, 2+2 }, { ISD::SRA, MVT::v2i64, 4 }, { ISD::SRA, MVT::v4i64, 8+2 }, };
if (ST->hasSSE2() &&
((Op2Info == TargetTransformInfo::OK_UniformConstantValue) ||
(Op2Info == TargetTransformInfo::OK_UniformValue))) {
if (ISD == ISD::SRA && LT.second == MVT::v4i64 && ST->hasAVX2())
return LT.first * 4;
if (const auto *Entry =
CostTableLookup(SSE2UniformShiftCostTable, ISD, LT.second))
return LT.first * Entry->Cost;
}
if (ISD == ISD::SHL &&
Op2Info == TargetTransformInfo::OK_NonUniformConstantValue) {
MVT VT = LT.second;
if (((VT == MVT::v8i16 || VT == MVT::v4i32) && ST->hasSSE2()) ||
((VT == MVT::v16i16 || VT == MVT::v8i32) && ST->hasAVX()))
ISD = ISD::MUL;
}
static const CostTblEntry AVX2CostTable[] = {
{ ISD::SHL, MVT::v16i8, 6 }, { ISD::SHL, MVT::v32i8, 6 }, { ISD::SHL, MVT::v64i8, 12 }, { ISD::SHL, MVT::v8i16, 5 }, { ISD::SHL, MVT::v16i16, 7 }, { ISD::SHL, MVT::v32i16, 14 },
{ ISD::SRL, MVT::v16i8, 6 }, { ISD::SRL, MVT::v32i8, 6 }, { ISD::SRL, MVT::v64i8, 12 }, { ISD::SRL, MVT::v8i16, 5 }, { ISD::SRL, MVT::v16i16, 7 }, { ISD::SRL, MVT::v32i16, 14 },
{ ISD::SRA, MVT::v16i8, 17 }, { ISD::SRA, MVT::v32i8, 17 }, { ISD::SRA, MVT::v64i8, 34 }, { ISD::SRA, MVT::v8i16, 5 }, { ISD::SRA, MVT::v16i16, 7 }, { ISD::SRA, MVT::v32i16, 14 }, { ISD::SRA, MVT::v2i64, 2 }, { ISD::SRA, MVT::v4i64, 2 },
{ ISD::SUB, MVT::v32i8, 1 }, { ISD::ADD, MVT::v32i8, 1 }, { ISD::SUB, MVT::v16i16, 1 }, { ISD::ADD, MVT::v16i16, 1 }, { ISD::SUB, MVT::v8i32, 1 }, { ISD::ADD, MVT::v8i32, 1 }, { ISD::SUB, MVT::v4i64, 1 }, { ISD::ADD, MVT::v4i64, 1 },
{ ISD::MUL, MVT::v16i16, 1 }, { ISD::MUL, MVT::v8i32, 2 }, { ISD::MUL, MVT::v4i64, 6 },
{ ISD::FNEG, MVT::v4f64, 1 }, { ISD::FNEG, MVT::v8f32, 1 }, { ISD::FADD, MVT::v4f64, 1 }, { ISD::FADD, MVT::v8f32, 1 }, { ISD::FSUB, MVT::v4f64, 1 }, { ISD::FSUB, MVT::v8f32, 1 }, { ISD::FMUL, MVT::f64, 1 }, { ISD::FMUL, MVT::v2f64, 1 }, { ISD::FMUL, MVT::v4f64, 1 }, { ISD::FMUL, MVT::v8f32, 1 },
{ ISD::FDIV, MVT::f32, 7 }, { ISD::FDIV, MVT::v4f32, 7 }, { ISD::FDIV, MVT::v8f32, 14 }, { ISD::FDIV, MVT::f64, 14 }, { ISD::FDIV, MVT::v2f64, 14 }, { ISD::FDIV, MVT::v4f64, 28 }, };
if (ST->hasAVX2())
if (const auto *Entry = CostTableLookup(AVX2CostTable, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry AVX1CostTable[] = {
{ ISD::MUL, MVT::v16i16, 4 },
{ ISD::MUL, MVT::v8i32, 5 }, { ISD::MUL, MVT::v4i64, 12 },
{ ISD::SUB, MVT::v32i8, 4 },
{ ISD::ADD, MVT::v32i8, 4 },
{ ISD::SUB, MVT::v16i16, 4 },
{ ISD::ADD, MVT::v16i16, 4 },
{ ISD::SUB, MVT::v8i32, 4 },
{ ISD::ADD, MVT::v8i32, 4 },
{ ISD::SUB, MVT::v4i64, 4 },
{ ISD::ADD, MVT::v4i64, 4 },
{ ISD::SHL, MVT::v32i8, 22 }, { ISD::SHL, MVT::v8i16, 6 }, { ISD::SHL, MVT::v16i16, 13 }, { ISD::SHL, MVT::v4i32, 3 }, { ISD::SHL, MVT::v8i32, 9 }, { ISD::SHL, MVT::v2i64, 2 }, { ISD::SHL, MVT::v4i64, 6 },
{ ISD::SRL, MVT::v32i8, 23 }, { ISD::SRL, MVT::v16i16, 28 }, { ISD::SRL, MVT::v4i32, 6 }, { ISD::SRL, MVT::v8i32, 14 }, { ISD::SRL, MVT::v2i64, 2 }, { ISD::SRL, MVT::v4i64, 6 },
{ ISD::SRA, MVT::v32i8, 44 }, { ISD::SRA, MVT::v16i16, 28 }, { ISD::SRA, MVT::v4i32, 6 }, { ISD::SRA, MVT::v8i32, 14 }, { ISD::SRA, MVT::v2i64, 5 }, { ISD::SRA, MVT::v4i64, 12 },
{ ISD::FNEG, MVT::v4f64, 2 }, { ISD::FNEG, MVT::v8f32, 2 },
{ ISD::FMUL, MVT::f64, 2 }, { ISD::FMUL, MVT::v2f64, 2 }, { ISD::FMUL, MVT::v4f64, 4 },
{ ISD::FDIV, MVT::f32, 14 }, { ISD::FDIV, MVT::v4f32, 14 }, { ISD::FDIV, MVT::v8f32, 28 }, { ISD::FDIV, MVT::f64, 22 }, { ISD::FDIV, MVT::v2f64, 22 }, { ISD::FDIV, MVT::v4f64, 44 }, };
if (ST->hasAVX())
if (const auto *Entry = CostTableLookup(AVX1CostTable, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry SSE42CostTable[] = {
{ ISD::FADD, MVT::f64, 1 }, { ISD::FADD, MVT::f32, 1 }, { ISD::FADD, MVT::v2f64, 1 }, { ISD::FADD, MVT::v4f32, 1 },
{ ISD::FSUB, MVT::f64, 1 }, { ISD::FSUB, MVT::f32 , 1 }, { ISD::FSUB, MVT::v2f64, 1 }, { ISD::FSUB, MVT::v4f32, 1 },
{ ISD::FMUL, MVT::f64, 1 }, { ISD::FMUL, MVT::f32, 1 }, { ISD::FMUL, MVT::v2f64, 1 }, { ISD::FMUL, MVT::v4f32, 1 },
{ ISD::FDIV, MVT::f32, 14 }, { ISD::FDIV, MVT::v4f32, 14 }, { ISD::FDIV, MVT::f64, 22 }, { ISD::FDIV, MVT::v2f64, 22 },
{ ISD::MUL, MVT::v2i64, 6 } };
if (ST->hasSSE42())
if (const auto *Entry = CostTableLookup(SSE42CostTable, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry SSE41CostTable[] = {
{ ISD::SHL, MVT::v16i8, 10 }, { ISD::SHL, MVT::v8i16, 11 }, { ISD::SHL, MVT::v4i32, 4 },
{ ISD::SRL, MVT::v16i8, 11 }, { ISD::SRL, MVT::v8i16, 13 }, { ISD::SRL, MVT::v4i32, 16 },
{ ISD::SRA, MVT::v16i8, 21 }, { ISD::SRA, MVT::v8i16, 13 },
{ ISD::MUL, MVT::v4i32, 2 } };
if (ST->hasSSE41())
if (const auto *Entry = CostTableLookup(SSE41CostTable, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry SSE2CostTable[] = {
{ ISD::SHL, MVT::v16i8, 13 }, { ISD::SHL, MVT::v8i16, 25 }, { ISD::SHL, MVT::v4i32, 16 }, { ISD::SHL, MVT::v2i64, 4 },
{ ISD::SRL, MVT::v16i8, 14 }, { ISD::SRL, MVT::v8i16, 16 }, { ISD::SRL, MVT::v4i32, 12 }, { ISD::SRL, MVT::v2i64, 4 },
{ ISD::SRA, MVT::v16i8, 27 }, { ISD::SRA, MVT::v8i16, 16 }, { ISD::SRA, MVT::v4i32, 12 }, { ISD::SRA, MVT::v2i64, 8 },
{ ISD::MUL, MVT::v8i16, 1 }, { ISD::MUL, MVT::v4i32, 6 }, { ISD::MUL, MVT::v2i64, 8 },
{ ISD::FDIV, MVT::f32, 23 }, { ISD::FDIV, MVT::v4f32, 39 }, { ISD::FDIV, MVT::f64, 38 }, { ISD::FDIV, MVT::v2f64, 69 },
{ ISD::FNEG, MVT::f32, 1 }, { ISD::FNEG, MVT::f64, 1 }, { ISD::FNEG, MVT::v4f32, 1 }, { ISD::FNEG, MVT::v2f64, 1 },
{ ISD::FADD, MVT::f32, 2 }, { ISD::FADD, MVT::f64, 2 },
{ ISD::FSUB, MVT::f32, 2 }, { ISD::FSUB, MVT::f64, 2 }, };
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2CostTable, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry SSE1CostTable[] = {
{ ISD::FDIV, MVT::f32, 17 }, { ISD::FDIV, MVT::v4f32, 34 },
{ ISD::FNEG, MVT::f32, 2 }, { ISD::FNEG, MVT::v4f32, 2 },
{ ISD::FADD, MVT::f32, 1 }, { ISD::FADD, MVT::v4f32, 2 },
{ ISD::FSUB, MVT::f32, 1 }, { ISD::FSUB, MVT::v4f32, 2 }, };
if (ST->hasSSE1())
if (const auto *Entry = CostTableLookup(SSE1CostTable, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry X64CostTbl[] = { { ISD::ADD, MVT::i64, 1 }, { ISD::SUB, MVT::i64, 1 }, { ISD::MUL, MVT::i64, 2 }, };
if (ST->is64Bit())
if (const auto *Entry = CostTableLookup(X64CostTbl, ISD, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry X86CostTbl[] = { { ISD::ADD, MVT::i8, 1 }, { ISD::ADD, MVT::i16, 1 }, { ISD::ADD, MVT::i32, 1 },
{ ISD::SUB, MVT::i8, 1 }, { ISD::SUB, MVT::i16, 1 }, { ISD::SUB, MVT::i32, 1 }, };
if (const auto *Entry = CostTableLookup(X86CostTbl, ISD, LT.second))
return LT.first * Entry->Cost;
if (LT.second.isVector() && (ISD == ISD::SDIV || ISD == ISD::SREM ||
ISD == ISD::UDIV || ISD == ISD::UREM)) {
InstructionCost ScalarCost = getArithmeticInstrCost(
Opcode, Ty->getScalarType(), CostKind, Op1Info, Op2Info,
TargetTransformInfo::OP_None, TargetTransformInfo::OP_None);
return 20 * LT.first * LT.second.getVectorNumElements() * ScalarCost;
}
return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info);
}
InstructionCost X86TTIImpl::getShuffleCost(TTI::ShuffleKind Kind,
VectorType *BaseTp,
ArrayRef<int> Mask, int Index,
VectorType *SubTp,
ArrayRef<const Value *> Args) {
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, BaseTp);
Kind = improveShuffleKindFromMask(Kind, Mask);
if (Kind == TTI::SK_Transpose)
Kind = TTI::SK_PermuteTwoSrc;
if (Kind == TTI::SK_Broadcast)
LT.first = 1;
if (Kind == TTI::SK_ExtractSubvector && LT.second.isVector()) {
int NumElts = LT.second.getVectorNumElements();
if ((Index % NumElts) == 0)
return 0;
std::pair<InstructionCost, MVT> SubLT =
TLI->getTypeLegalizationCost(DL, SubTp);
if (SubLT.second.isVector()) {
int NumSubElts = SubLT.second.getVectorNumElements();
if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
return SubLT.first;
int OrigSubElts = cast<FixedVectorType>(SubTp)->getNumElements();
if (NumSubElts > OrigSubElts && (Index % OrigSubElts) == 0 &&
(NumSubElts % OrigSubElts) == 0 &&
LT.second.getVectorElementType() ==
SubLT.second.getVectorElementType() &&
LT.second.getVectorElementType().getSizeInBits() ==
BaseTp->getElementType()->getPrimitiveSizeInBits()) {
assert(NumElts >= NumSubElts && NumElts > OrigSubElts &&
"Unexpected number of elements!");
auto *VecTy = FixedVectorType::get(BaseTp->getElementType(),
LT.second.getVectorNumElements());
auto *SubTy = FixedVectorType::get(BaseTp->getElementType(),
SubLT.second.getVectorNumElements());
int ExtractIndex = alignDown((Index % NumElts), NumSubElts);
InstructionCost ExtractCost = getShuffleCost(
TTI::SK_ExtractSubvector, VecTy, None, ExtractIndex, SubTy);
if (SubTp->getPrimitiveSizeInBits() >= 32 || ST->hasSSSE3())
return ExtractCost + 1;
assert(SubTp->getPrimitiveSizeInBits() == 16 &&
"Unexpected vector size");
return ExtractCost + 2; }
}
}
if (Kind == TTI::SK_InsertSubvector && LT.second.isVector()) {
int NumElts = LT.second.getVectorNumElements();
std::pair<InstructionCost, MVT> SubLT =
TLI->getTypeLegalizationCost(DL, SubTp);
if (SubLT.second.isVector()) {
int NumSubElts = SubLT.second.getVectorNumElements();
if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
return SubLT.first;
}
Kind = TTI::SK_PermuteTwoSrc;
}
EVT VT = TLI->getValueType(DL, BaseTp);
if (VT.isSimple() && VT.isVector() && VT.getSizeInBits() < 128 &&
!ST->hasSSSE3()) {
static const CostTblEntry SSE2SubVectorShuffleTbl[] = {
{TTI::SK_Broadcast, MVT::v4i16, 1}, {TTI::SK_Broadcast, MVT::v2i16, 1}, {TTI::SK_Broadcast, MVT::v8i8, 2}, {TTI::SK_Broadcast, MVT::v4i8, 2}, {TTI::SK_Broadcast, MVT::v2i8, 1},
{TTI::SK_Reverse, MVT::v4i16, 1}, {TTI::SK_Reverse, MVT::v2i16, 1}, {TTI::SK_Reverse, MVT::v4i8, 3}, {TTI::SK_Reverse, MVT::v2i8, 1},
{TTI::SK_PermuteTwoSrc, MVT::v4i16, 2}, {TTI::SK_PermuteTwoSrc, MVT::v2i16, 2}, {TTI::SK_PermuteTwoSrc, MVT::v8i8, 7}, {TTI::SK_PermuteTwoSrc, MVT::v4i8, 4}, {TTI::SK_PermuteTwoSrc, MVT::v2i8, 2},
{TTI::SK_PermuteSingleSrc, MVT::v4i16, 1}, {TTI::SK_PermuteSingleSrc, MVT::v2i16, 1}, {TTI::SK_PermuteSingleSrc, MVT::v8i8, 5}, {TTI::SK_PermuteSingleSrc, MVT::v4i8, 3}, {TTI::SK_PermuteSingleSrc, MVT::v2i8, 1}, };
if (ST->hasSSE2())
if (const auto *Entry =
CostTableLookup(SSE2SubVectorShuffleTbl, Kind, VT.getSimpleVT()))
return Entry->Cost;
}
if (Kind == TTI::SK_PermuteSingleSrc && LT.first != 1) {
MVT LegalVT = LT.second;
if (LegalVT.isVector() &&
LegalVT.getVectorElementType().getSizeInBits() ==
BaseTp->getElementType()->getPrimitiveSizeInBits() &&
LegalVT.getVectorNumElements() <
cast<FixedVectorType>(BaseTp)->getNumElements()) {
unsigned VecTySize = DL.getTypeStoreSize(BaseTp);
unsigned LegalVTSize = LegalVT.getStoreSize();
unsigned NumOfSrcs = (VecTySize + LegalVTSize - 1) / LegalVTSize;
InstructionCost NumOfDests = LT.first;
auto *SingleOpTy = FixedVectorType::get(BaseTp->getElementType(),
LegalVT.getVectorNumElements());
if (!Mask.empty() && NumOfDests.isValid()) {
unsigned E = *NumOfDests.getValue();
unsigned NormalizedVF =
LegalVT.getVectorNumElements() * std::max(NumOfSrcs, E);
unsigned NumOfSrcRegs = NormalizedVF / LegalVT.getVectorNumElements();
unsigned NumOfDestRegs = NormalizedVF / LegalVT.getVectorNumElements();
SmallVector<int> NormalizedMask(NormalizedVF, UndefMaskElem);
copy(Mask, NormalizedMask.begin());
unsigned PrevSrcReg = 0;
ArrayRef<int> PrevRegMask;
InstructionCost Cost = 0;
processShuffleMasks(
NormalizedMask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs, []() {},
[this, SingleOpTy, &PrevSrcReg, &PrevRegMask,
&Cost](ArrayRef<int> RegMask, unsigned SrcReg, unsigned DestReg) {
if (!ShuffleVectorInst::isIdentityMask(RegMask)) {
if (PrevRegMask.empty() || PrevSrcReg != SrcReg ||
PrevRegMask != RegMask)
Cost += getShuffleCost(TTI::SK_PermuteSingleSrc, SingleOpTy,
RegMask, 0, nullptr);
else
Cost += TTI::TCC_Basic;
return;
}
if (SrcReg != DestReg &&
any_of(RegMask, [](int I) { return I != UndefMaskElem; })) {
Cost += TTI::TCC_Basic;
}
PrevSrcReg = SrcReg;
PrevRegMask = RegMask;
},
[this, SingleOpTy, &Cost](ArrayRef<int> RegMask,
unsigned ,
unsigned ) {
Cost += getShuffleCost(TTI::SK_PermuteTwoSrc, SingleOpTy, RegMask,
0, nullptr);
});
return Cost;
}
InstructionCost NumOfShuffles = (NumOfSrcs - 1) * NumOfDests;
return NumOfShuffles * getShuffleCost(TTI::SK_PermuteTwoSrc, SingleOpTy,
None, 0, nullptr);
}
return BaseT::getShuffleCost(Kind, BaseTp, Mask, Index, SubTp);
}
if (Kind == TTI::SK_PermuteTwoSrc && LT.first != 1) {
InstructionCost NumOfDests = LT.first;
InstructionCost NumOfShufflesPerDest = LT.first * 2 - 1;
LT.first = NumOfDests * NumOfShufflesPerDest;
}
static const CostTblEntry AVX512VBMIShuffleTbl[] = {
{TTI::SK_Reverse, MVT::v64i8, 1}, {TTI::SK_Reverse, MVT::v32i8, 1},
{TTI::SK_PermuteSingleSrc, MVT::v64i8, 1}, {TTI::SK_PermuteSingleSrc, MVT::v32i8, 1},
{TTI::SK_PermuteTwoSrc, MVT::v64i8, 2}, {TTI::SK_PermuteTwoSrc, MVT::v32i8, 2}, {TTI::SK_PermuteTwoSrc, MVT::v16i8, 2} };
if (ST->hasVBMI())
if (const auto *Entry =
CostTableLookup(AVX512VBMIShuffleTbl, Kind, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry AVX512BWShuffleTbl[] = {
{TTI::SK_Broadcast, MVT::v32i16, 1}, {TTI::SK_Broadcast, MVT::v32f16, 1}, {TTI::SK_Broadcast, MVT::v64i8, 1},
{TTI::SK_Reverse, MVT::v32i16, 2}, {TTI::SK_Reverse, MVT::v32f16, 2}, {TTI::SK_Reverse, MVT::v16i16, 2}, {TTI::SK_Reverse, MVT::v64i8, 2},
{TTI::SK_PermuteSingleSrc, MVT::v32i16, 2}, {TTI::SK_PermuteSingleSrc, MVT::v32f16, 2}, {TTI::SK_PermuteSingleSrc, MVT::v16i16, 2}, {TTI::SK_PermuteSingleSrc, MVT::v16f16, 2}, {TTI::SK_PermuteSingleSrc, MVT::v64i8, 8},
{TTI::SK_PermuteTwoSrc, MVT::v32i16, 2}, {TTI::SK_PermuteTwoSrc, MVT::v32f16, 2}, {TTI::SK_PermuteTwoSrc, MVT::v16i16, 2}, {TTI::SK_PermuteTwoSrc, MVT::v8i16, 2}, {TTI::SK_PermuteTwoSrc, MVT::v64i8, 19},
{TTI::SK_Select, MVT::v32i16, 1}, {TTI::SK_Select, MVT::v64i8, 1}, };
if (ST->hasBWI())
if (const auto *Entry =
CostTableLookup(AVX512BWShuffleTbl, Kind, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry AVX512ShuffleTbl[] = {
{TTI::SK_Broadcast, MVT::v8f64, 1}, {TTI::SK_Broadcast, MVT::v16f32, 1}, {TTI::SK_Broadcast, MVT::v8i64, 1}, {TTI::SK_Broadcast, MVT::v16i32, 1}, {TTI::SK_Broadcast, MVT::v32i16, 1}, {TTI::SK_Broadcast, MVT::v32f16, 1}, {TTI::SK_Broadcast, MVT::v64i8, 1},
{TTI::SK_Reverse, MVT::v8f64, 1}, {TTI::SK_Reverse, MVT::v16f32, 1}, {TTI::SK_Reverse, MVT::v8i64, 1}, {TTI::SK_Reverse, MVT::v16i32, 1}, {TTI::SK_Reverse, MVT::v32i16, 7}, {TTI::SK_Reverse, MVT::v32f16, 7}, {TTI::SK_Reverse, MVT::v64i8, 7},
{TTI::SK_PermuteSingleSrc, MVT::v8f64, 1}, {TTI::SK_PermuteSingleSrc, MVT::v4f64, 1}, {TTI::SK_PermuteSingleSrc, MVT::v2f64, 1}, {TTI::SK_PermuteSingleSrc, MVT::v16f32, 1}, {TTI::SK_PermuteSingleSrc, MVT::v8f32, 1}, {TTI::SK_PermuteSingleSrc, MVT::v4f32, 1}, {TTI::SK_PermuteSingleSrc, MVT::v8i64, 1}, {TTI::SK_PermuteSingleSrc, MVT::v4i64, 1}, {TTI::SK_PermuteSingleSrc, MVT::v2i64, 1}, {TTI::SK_PermuteSingleSrc, MVT::v16i32, 1}, {TTI::SK_PermuteSingleSrc, MVT::v8i32, 1}, {TTI::SK_PermuteSingleSrc, MVT::v4i32, 1}, {TTI::SK_PermuteSingleSrc, MVT::v16i8, 1},
{TTI::SK_PermuteTwoSrc, MVT::v8f64, 1}, {TTI::SK_PermuteTwoSrc, MVT::v16f32, 1}, {TTI::SK_PermuteTwoSrc, MVT::v8i64, 1}, {TTI::SK_PermuteTwoSrc, MVT::v16i32, 1}, {TTI::SK_PermuteTwoSrc, MVT::v4f64, 1}, {TTI::SK_PermuteTwoSrc, MVT::v8f32, 1}, {TTI::SK_PermuteTwoSrc, MVT::v4i64, 1}, {TTI::SK_PermuteTwoSrc, MVT::v8i32, 1}, {TTI::SK_PermuteTwoSrc, MVT::v2f64, 1}, {TTI::SK_PermuteTwoSrc, MVT::v4f32, 1}, {TTI::SK_PermuteTwoSrc, MVT::v2i64, 1}, {TTI::SK_PermuteTwoSrc, MVT::v4i32, 1},
{TTI::SK_PermuteSingleSrc, MVT::v32i16, 14},
{TTI::SK_PermuteSingleSrc, MVT::v32f16, 14},
{TTI::SK_PermuteSingleSrc, MVT::v64i8, 14},
{TTI::SK_PermuteTwoSrc, MVT::v32i16, 42},
{TTI::SK_PermuteTwoSrc, MVT::v32f16, 42},
{TTI::SK_PermuteTwoSrc, MVT::v64i8, 42},
{TTI::SK_Select, MVT::v32i16, 1}, {TTI::SK_Select, MVT::v32f16, 1}, {TTI::SK_Select, MVT::v64i8, 1}, {TTI::SK_Select, MVT::v8f64, 1}, {TTI::SK_Select, MVT::v16f32, 1}, {TTI::SK_Select, MVT::v8i64, 1}, {TTI::SK_Select, MVT::v16i32, 1}, };
if (ST->hasAVX512())
if (const auto *Entry = CostTableLookup(AVX512ShuffleTbl, Kind, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry AVX2ShuffleTbl[] = {
{TTI::SK_Broadcast, MVT::v4f64, 1}, {TTI::SK_Broadcast, MVT::v8f32, 1}, {TTI::SK_Broadcast, MVT::v4i64, 1}, {TTI::SK_Broadcast, MVT::v8i32, 1}, {TTI::SK_Broadcast, MVT::v16i16, 1}, {TTI::SK_Broadcast, MVT::v16f16, 1}, {TTI::SK_Broadcast, MVT::v32i8, 1},
{TTI::SK_Reverse, MVT::v4f64, 1}, {TTI::SK_Reverse, MVT::v8f32, 1}, {TTI::SK_Reverse, MVT::v4i64, 1}, {TTI::SK_Reverse, MVT::v8i32, 1}, {TTI::SK_Reverse, MVT::v16i16, 2}, {TTI::SK_Reverse, MVT::v16f16, 2}, {TTI::SK_Reverse, MVT::v32i8, 2},
{TTI::SK_Select, MVT::v16i16, 1}, {TTI::SK_Select, MVT::v16f16, 1}, {TTI::SK_Select, MVT::v32i8, 1},
{TTI::SK_PermuteSingleSrc, MVT::v4f64, 1}, {TTI::SK_PermuteSingleSrc, MVT::v8f32, 1}, {TTI::SK_PermuteSingleSrc, MVT::v4i64, 1}, {TTI::SK_PermuteSingleSrc, MVT::v8i32, 1}, {TTI::SK_PermuteSingleSrc, MVT::v16i16, 4}, {TTI::SK_PermuteSingleSrc, MVT::v16f16, 4}, {TTI::SK_PermuteSingleSrc, MVT::v32i8, 4},
{TTI::SK_PermuteTwoSrc, MVT::v4f64, 3}, {TTI::SK_PermuteTwoSrc, MVT::v8f32, 3}, {TTI::SK_PermuteTwoSrc, MVT::v4i64, 3}, {TTI::SK_PermuteTwoSrc, MVT::v8i32, 3}, {TTI::SK_PermuteTwoSrc, MVT::v16i16, 7}, {TTI::SK_PermuteTwoSrc, MVT::v16f16, 7}, {TTI::SK_PermuteTwoSrc, MVT::v32i8, 7}, };
if (ST->hasAVX2())
if (const auto *Entry = CostTableLookup(AVX2ShuffleTbl, Kind, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry XOPShuffleTbl[] = {
{TTI::SK_PermuteSingleSrc, MVT::v4f64, 2}, {TTI::SK_PermuteSingleSrc, MVT::v8f32, 2}, {TTI::SK_PermuteSingleSrc, MVT::v4i64, 2}, {TTI::SK_PermuteSingleSrc, MVT::v8i32, 2}, {TTI::SK_PermuteSingleSrc, MVT::v16i16, 4}, {TTI::SK_PermuteSingleSrc, MVT::v32i8, 4},
{TTI::SK_PermuteTwoSrc, MVT::v16i16, 9}, {TTI::SK_PermuteTwoSrc, MVT::v8i16, 1}, {TTI::SK_PermuteTwoSrc, MVT::v32i8, 9}, {TTI::SK_PermuteTwoSrc, MVT::v16i8, 1}, };
if (ST->hasXOP())
if (const auto *Entry = CostTableLookup(XOPShuffleTbl, Kind, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry AVX1ShuffleTbl[] = {
{TTI::SK_Broadcast, MVT::v4f64, 2}, {TTI::SK_Broadcast, MVT::v8f32, 2}, {TTI::SK_Broadcast, MVT::v4i64, 2}, {TTI::SK_Broadcast, MVT::v8i32, 2}, {TTI::SK_Broadcast, MVT::v16i16, 3}, {TTI::SK_Broadcast, MVT::v16f16, 3}, {TTI::SK_Broadcast, MVT::v32i8, 2},
{TTI::SK_Reverse, MVT::v4f64, 2}, {TTI::SK_Reverse, MVT::v8f32, 2}, {TTI::SK_Reverse, MVT::v4i64, 2}, {TTI::SK_Reverse, MVT::v8i32, 2}, {TTI::SK_Reverse, MVT::v16i16, 4}, {TTI::SK_Reverse, MVT::v16f16, 4}, {TTI::SK_Reverse, MVT::v32i8, 4},
{TTI::SK_Select, MVT::v4i64, 1}, {TTI::SK_Select, MVT::v4f64, 1}, {TTI::SK_Select, MVT::v8i32, 1}, {TTI::SK_Select, MVT::v8f32, 1}, {TTI::SK_Select, MVT::v16i16, 3}, {TTI::SK_Select, MVT::v16f16, 3}, {TTI::SK_Select, MVT::v32i8, 3},
{TTI::SK_PermuteSingleSrc, MVT::v4f64, 2}, {TTI::SK_PermuteSingleSrc, MVT::v4i64, 2}, {TTI::SK_PermuteSingleSrc, MVT::v8f32, 4}, {TTI::SK_PermuteSingleSrc, MVT::v8i32, 4}, {TTI::SK_PermuteSingleSrc, MVT::v16i16, 8}, {TTI::SK_PermuteSingleSrc, MVT::v16f16, 8}, {TTI::SK_PermuteSingleSrc, MVT::v32i8, 8},
{TTI::SK_PermuteTwoSrc, MVT::v4f64, 3}, {TTI::SK_PermuteTwoSrc, MVT::v4i64, 3}, {TTI::SK_PermuteTwoSrc, MVT::v8f32, 4}, {TTI::SK_PermuteTwoSrc, MVT::v8i32, 4}, {TTI::SK_PermuteTwoSrc, MVT::v16i16, 15}, {TTI::SK_PermuteTwoSrc, MVT::v16f16, 15}, {TTI::SK_PermuteTwoSrc, MVT::v32i8, 15}, };
if (ST->hasAVX())
if (const auto *Entry = CostTableLookup(AVX1ShuffleTbl, Kind, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry SSE41ShuffleTbl[] = {
{TTI::SK_Select, MVT::v2i64, 1}, {TTI::SK_Select, MVT::v2f64, 1}, {TTI::SK_Select, MVT::v4i32, 1}, {TTI::SK_Select, MVT::v4f32, 1}, {TTI::SK_Select, MVT::v8i16, 1}, {TTI::SK_Select, MVT::v8f16, 1}, {TTI::SK_Select, MVT::v16i8, 1} };
if (ST->hasSSE41())
if (const auto *Entry = CostTableLookup(SSE41ShuffleTbl, Kind, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry SSSE3ShuffleTbl[] = {
{TTI::SK_Broadcast, MVT::v8i16, 1}, {TTI::SK_Broadcast, MVT::v8f16, 1}, {TTI::SK_Broadcast, MVT::v16i8, 1},
{TTI::SK_Reverse, MVT::v8i16, 1}, {TTI::SK_Reverse, MVT::v8f16, 1}, {TTI::SK_Reverse, MVT::v16i8, 1},
{TTI::SK_Select, MVT::v8i16, 3}, {TTI::SK_Select, MVT::v8f16, 3}, {TTI::SK_Select, MVT::v16i8, 3},
{TTI::SK_PermuteSingleSrc, MVT::v8i16, 1}, {TTI::SK_PermuteSingleSrc, MVT::v8f16, 1}, {TTI::SK_PermuteSingleSrc, MVT::v16i8, 1},
{TTI::SK_PermuteTwoSrc, MVT::v8i16, 3}, {TTI::SK_PermuteTwoSrc, MVT::v8f16, 3}, {TTI::SK_PermuteTwoSrc, MVT::v16i8, 3}, };
if (ST->hasSSSE3())
if (const auto *Entry = CostTableLookup(SSSE3ShuffleTbl, Kind, LT.second))
return LT.first * Entry->Cost;
static const CostTblEntry SSE2ShuffleTbl[] = {
{TTI::SK_Broadcast, MVT::v2f64, 1}, {TTI::SK_Broadcast, MVT::v2i64, 1}, {TTI::SK_Broadcast, MVT::v4i32, 1}, {TTI::SK_Broadcast, MVT::v8i16, 2}, {TTI::SK_Broadcast, MVT::v8f16, 2}, {TTI::SK_Broadcast, MVT::v16i8, 3},
{TTI::SK_Reverse, MVT::v2f64, 1}, {TTI::SK_Reverse, MVT::v2i64, 1}, {TTI::SK_Reverse, MVT::v4i32, 1}, {TTI::SK_Reverse, MVT::v8i16, 3}, {TTI::SK_Reverse, MVT::v8f16, 3}, {TTI::SK_Reverse, MVT::v16i8, 9},
{TTI::SK_Select, MVT::v2i64, 1}, {TTI::SK_Select, MVT::v2f64, 1}, {TTI::SK_Select, MVT::v4i32, 2}, {TTI::SK_Select, MVT::v8i16, 3}, {TTI::SK_Select, MVT::v8f16, 3}, {TTI::SK_Select, MVT::v16i8, 3},
{TTI::SK_PermuteSingleSrc, MVT::v2f64, 1}, {TTI::SK_PermuteSingleSrc, MVT::v2i64, 1}, {TTI::SK_PermuteSingleSrc, MVT::v4i32, 1}, {TTI::SK_PermuteSingleSrc, MVT::v8i16, 5}, {TTI::SK_PermuteSingleSrc, MVT::v8f16, 5}, { TTI::SK_PermuteSingleSrc, MVT::v16i8, 10 },
{ TTI::SK_PermuteTwoSrc, MVT::v2f64, 1 }, { TTI::SK_PermuteTwoSrc, MVT::v2i64, 1 }, { TTI::SK_PermuteTwoSrc, MVT::v4i32, 2 }, { TTI::SK_PermuteTwoSrc, MVT::v8i16, 8 }, { TTI::SK_PermuteTwoSrc, MVT::v8f16, 8 }, { TTI::SK_PermuteTwoSrc, MVT::v16i8, 13 }, };
static const CostTblEntry SSE3BroadcastLoadTbl[] = {
{TTI::SK_Broadcast, MVT::v2f64, 0}, };
if (ST->hasSSE2()) {
bool IsLoad =
llvm::any_of(Args, [](const auto &V) { return isa<LoadInst>(V); });
if (ST->hasSSE3() && IsLoad)
if (const auto *Entry =
CostTableLookup(SSE3BroadcastLoadTbl, Kind, LT.second)) {
assert(isLegalBroadcastLoad(BaseTp->getElementType(),
LT.second.getVectorElementCount()) &&
"Table entry missing from isLegalBroadcastLoad()");
return LT.first * Entry->Cost;
}
if (const auto *Entry = CostTableLookup(SSE2ShuffleTbl, Kind, LT.second))
return LT.first * Entry->Cost;
}
static const CostTblEntry SSE1ShuffleTbl[] = {
{ TTI::SK_Broadcast, MVT::v4f32, 1 }, { TTI::SK_Reverse, MVT::v4f32, 1 }, { TTI::SK_Select, MVT::v4f32, 2 }, { TTI::SK_PermuteSingleSrc, MVT::v4f32, 1 }, { TTI::SK_PermuteTwoSrc, MVT::v4f32, 2 }, };
if (ST->hasSSE1())
if (const auto *Entry = CostTableLookup(SSE1ShuffleTbl, Kind, LT.second))
return LT.first * Entry->Cost;
return BaseT::getShuffleCost(Kind, BaseTp, Mask, Index, SubTp);
}
InstructionCost X86TTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst,
Type *Src,
TTI::CastContextHint CCH,
TTI::TargetCostKind CostKind,
const Instruction *I) {
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
auto AdjustCost = [&CostKind](InstructionCost Cost) -> InstructionCost {
if (CostKind != TTI::TCK_RecipThroughput)
return Cost == 0 ? 0 : 1;
return Cost;
};
static const TypeConversionCostTblEntry AVX512BWConversionTbl[] {
{ ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i8, 1 },
{ ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i8, 1 },
{ ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i8, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i16, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i8, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i16, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i8, MVT::v8i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v32i8, MVT::v32i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v64i8, MVT::v64i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v32i16, MVT::v64i1, 1 },
{ ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i8, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i16, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i8, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i16, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i8, MVT::v8i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v32i8, MVT::v32i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v64i8, MVT::v64i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v32i16, MVT::v64i1, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v16i8, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v8i16, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v16i8, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v8i16, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v16i8, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, 2 },
{ ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, 2 },
{ ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, 2 },
{ ISD::TRUNCATE, MVT::v32i1, MVT::v32i8, 2 },
{ ISD::TRUNCATE, MVT::v32i1, MVT::v32i16, 2 },
{ ISD::TRUNCATE, MVT::v64i1, MVT::v64i8, 2 },
{ ISD::TRUNCATE, MVT::v64i1, MVT::v32i16, 2 },
{ ISD::TRUNCATE, MVT::v32i8, MVT::v32i16, 2 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 2 }, { ISD::TRUNCATE, MVT::v2i8, MVT::v2i16, 2 }, { ISD::TRUNCATE, MVT::v4i8, MVT::v4i16, 2 }, { ISD::TRUNCATE, MVT::v8i8, MVT::v8i16, 2 }, };
static const TypeConversionCostTblEntry AVX512DQConversionTbl[] = {
{ ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i32, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i64, MVT::v16i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i1, 1 },
{ ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i32, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i64, MVT::v16i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i1, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v4i32, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, 2 },
{ ISD::TRUNCATE, MVT::v16i1, MVT::v16i32, 2 },
{ ISD::TRUNCATE, MVT::v16i1, MVT::v8i64, 2 },
{ ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i64, 1 },
{ ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i64, 1 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i64, 1 },
{ ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i64, 1 },
{ ISD::FP_TO_SINT, MVT::v8i64, MVT::v8f32, 1 },
{ ISD::FP_TO_SINT, MVT::v8i64, MVT::v8f64, 1 },
{ ISD::FP_TO_UINT, MVT::v8i64, MVT::v8f32, 1 },
{ ISD::FP_TO_UINT, MVT::v8i64, MVT::v8f64, 1 },
};
static const TypeConversionCostTblEntry AVX512FConversionTbl[] = {
{ ISD::FP_EXTEND, MVT::v8f64, MVT::v8f32, 1 },
{ ISD::FP_EXTEND, MVT::v8f64, MVT::v16f32, 3 },
{ ISD::FP_ROUND, MVT::v8f32, MVT::v8f64, 1 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 3 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 3 }, { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, 3 }, { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, 3 }, { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 3 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, 3 }, { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, 3 }, { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, 3 }, { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, 2 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, 2 }, { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 2 }, { ISD::TRUNCATE, MVT::v16i1, MVT::v16i32, 2 }, { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, 2 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, 2 }, { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, 2 }, { ISD::TRUNCATE, MVT::v2i8, MVT::v2i32, 2 }, { ISD::TRUNCATE, MVT::v4i8, MVT::v4i32, 2 }, { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 2 }, { ISD::TRUNCATE, MVT::v32i8, MVT::v16i32, 2 }, { ISD::TRUNCATE, MVT::v64i8, MVT::v16i32, 2 }, { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, 2 }, { ISD::TRUNCATE, MVT::v32i16, MVT::v16i32, 2 }, { ISD::TRUNCATE, MVT::v2i8, MVT::v2i64, 2 }, { ISD::TRUNCATE, MVT::v2i16, MVT::v2i64, 1 }, { ISD::TRUNCATE, MVT::v8i8, MVT::v8i64, 2 }, { ISD::TRUNCATE, MVT::v16i8, MVT::v8i64, 2 }, { ISD::TRUNCATE, MVT::v32i8, MVT::v8i64, 2 }, { ISD::TRUNCATE, MVT::v64i8, MVT::v8i64, 2 }, { ISD::TRUNCATE, MVT::v8i16, MVT::v8i64, 2 }, { ISD::TRUNCATE, MVT::v16i16, MVT::v8i64, 2 }, { ISD::TRUNCATE, MVT::v32i16, MVT::v8i64, 2 }, { ISD::TRUNCATE, MVT::v8i32, MVT::v8i64, 1 }, { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1 }, { ISD::TRUNCATE, MVT::v16i8, MVT::v16i64, 5 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 3 }, { ISD::TRUNCATE, MVT::v32i8, MVT::v32i16, 8 },
{ ISD::TRUNCATE, MVT::v64i8, MVT::v32i16, 8 },
{ ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, 3 },
{ ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, 3 },
{ ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, 3 },
{ ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, 3 },
{ ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, 3 },
{ ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, 3 },
{ ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, 3 },
{ ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 3 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v2i32, MVT::v2i1, 1 }, { ISD::ZERO_EXTEND, MVT::v2i32, MVT::v2i1, 2 }, { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, 1 }, { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, 2 }, { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 1 }, { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 2 }, { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, 1 }, { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, 2 }, { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 1 }, { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 2 },
{ ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i1, 1 }, { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i1, 2 }, { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i1, 1 }, { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i1, 2 },
{ ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i8, 1 },
{ ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i8, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i16, 1 },
{ ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i16, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i8, 1 },
{ ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i8, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i16, 1 },
{ ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i16, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i32, 1 },
{ ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i32, 1 },
{ ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i8, 3 }, { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i8, 3 },
{ ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i1, 4 },
{ ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i1, 3 },
{ ISD::SINT_TO_FP, MVT::v8f64, MVT::v16i8, 2 },
{ ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i8, 1 },
{ ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i16, 2 },
{ ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i16, 1 },
{ ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, 1 },
{ ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i32, 1 },
{ ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i1, 4 },
{ ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i1, 3 },
{ ISD::UINT_TO_FP, MVT::v8f64, MVT::v16i8, 2 },
{ ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i8, 1 },
{ ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i16, 2 },
{ ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i16, 1 },
{ ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, 1 },
{ ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i32, 1 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i64, 26 },
{ ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i64, 5 },
{ ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f32, 2 },
{ ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f64, 7 },
{ ISD::FP_TO_SINT, MVT::v32i8, MVT::v32f64,15 },
{ ISD::FP_TO_SINT, MVT::v64i8, MVT::v64f32,11 },
{ ISD::FP_TO_SINT, MVT::v64i8, MVT::v64f64,31 },
{ ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f64, 3 },
{ ISD::FP_TO_SINT, MVT::v16i16, MVT::v16f64, 7 },
{ ISD::FP_TO_SINT, MVT::v32i16, MVT::v32f32, 5 },
{ ISD::FP_TO_SINT, MVT::v32i16, MVT::v32f64,15 },
{ ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, 1 },
{ ISD::FP_TO_SINT, MVT::v16i32, MVT::v16f64, 3 },
{ ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f64, 1 },
{ ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f64, 3 },
{ ISD::FP_TO_UINT, MVT::v8i8, MVT::v8f64, 3 },
{ ISD::FP_TO_UINT, MVT::v16i32, MVT::v16f32, 1 },
{ ISD::FP_TO_UINT, MVT::v16i16, MVT::v16f32, 3 },
{ ISD::FP_TO_UINT, MVT::v16i8, MVT::v16f32, 3 },
};
static const TypeConversionCostTblEntry AVX512BWVLConversionTbl[] {
{ ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i8, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i16, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i8, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i16, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i8, MVT::v8i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v32i8, MVT::v32i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v32i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v32i8, MVT::v64i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v64i1, 1 },
{ ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i8, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i16, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i8, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i16, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i8, MVT::v8i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v32i8, MVT::v32i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v32i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v32i8, MVT::v64i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v64i1, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v16i8, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v8i16, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v16i8, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v8i16, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v16i8, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, 2 },
{ ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, 2 },
{ ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, 2 },
{ ISD::TRUNCATE, MVT::v32i1, MVT::v32i8, 2 },
{ ISD::TRUNCATE, MVT::v32i1, MVT::v16i16, 2 },
{ ISD::TRUNCATE, MVT::v64i1, MVT::v32i8, 2 },
{ ISD::TRUNCATE, MVT::v64i1, MVT::v16i16, 2 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 2 },
};
static const TypeConversionCostTblEntry AVX512DQVLConversionTbl[] = {
{ ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i32, MVT::v2i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 1 },
{ ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i32, MVT::v2i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i1, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 2 },
{ ISD::TRUNCATE, MVT::v16i1, MVT::v4i64, 2 },
{ ISD::TRUNCATE, MVT::v16i1, MVT::v8i32, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v4i32, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, 2 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v4i64, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 2 },
{ ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i64, 1 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 1 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i64, 1 },
{ ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i64, 1 },
{ ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, 1 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 1 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, 1 },
{ ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, 1 },
{ ISD::FP_TO_SINT, MVT::v2i64, MVT::v4f32, 1 },
{ ISD::FP_TO_SINT, MVT::v4i64, MVT::v4f32, 1 },
{ ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, 1 },
{ ISD::FP_TO_SINT, MVT::v4i64, MVT::v4f64, 1 },
{ ISD::FP_TO_UINT, MVT::v2i64, MVT::v4f32, 1 },
{ ISD::FP_TO_UINT, MVT::v4i64, MVT::v4f32, 1 },
{ ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, 1 },
{ ISD::FP_TO_UINT, MVT::v4i64, MVT::v4f64, 1 },
};
static const TypeConversionCostTblEntry AVX512VLConversionTbl[] = {
{ ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 3 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 3 }, { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, 3 }, { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, 8 }, { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 3 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, 3 }, { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, 3 }, { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, 8 }, { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, 2 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, 2 }, { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 2 }, { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, 2 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, 2 }, { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1 }, { ISD::TRUNCATE, MVT::v4i8, MVT::v4i64, 2 }, { ISD::TRUNCATE, MVT::v4i16, MVT::v4i64, 2 }, { ISD::TRUNCATE, MVT::v8i8, MVT::v8i32, 2 },
{ ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, 5 },
{ ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, 6 },
{ ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, 5 },
{ ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, 6 },
{ ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, 5 },
{ ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, 6 },
{ ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, 10 },
{ ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, 12 },
{ ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, 4 },
{ ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, 5 },
{ ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, 4 },
{ ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, 5 },
{ ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, 4 },
{ ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, 5 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 10 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 12 },
{ ISD::SIGN_EXTEND, MVT::v2i32, MVT::v2i1, 1 }, { ISD::ZERO_EXTEND, MVT::v2i32, MVT::v2i1, 2 }, { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, 1 }, { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, 2 }, { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 1 }, { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 2 }, { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, 1 }, { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, 2 }, { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 1 }, { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 2 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, 1 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, 1 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, 1 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 1 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, 1 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 1 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 1 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 1 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, 1 },
{ ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, 1 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, 1 },
{ ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 1 },
{ ISD::UINT_TO_FP, MVT::f32, MVT::i64, 1 },
{ ISD::UINT_TO_FP, MVT::f64, MVT::i64, 1 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, 1 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, 1 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, 1 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 1 },
{ ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 1 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 1 },
{ ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, 1 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, 1 },
{ ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, 5 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 5 },
{ ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, 5 },
{ ISD::FP_TO_SINT, MVT::v16i8, MVT::v8f32, 2 },
{ ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f32, 2 },
{ ISD::FP_TO_SINT, MVT::v32i8, MVT::v32f32, 5 },
{ ISD::FP_TO_UINT, MVT::i64, MVT::f32, 1 },
{ ISD::FP_TO_UINT, MVT::i64, MVT::f64, 1 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 1 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, 1 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, 1 },
{ ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, 1 },
{ ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f64, 1 },
};
static const TypeConversionCostTblEntry AVX2ConversionTbl[] = {
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 3 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 3 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 3 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 3 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 1 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, 2 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, 2 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 2 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, 2 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 2 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 2 },
{ ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i16, 3 },
{ ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i16, 3 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 2 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 2 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 2 },
{ ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, 4 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 4 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v8i16, 1 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, 1 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, 1 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v8i32, 4 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v4i64, 4 },
{ ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, 1 },
{ ISD::TRUNCATE, MVT::v8i16, MVT::v2i64, 1 },
{ ISD::TRUNCATE, MVT::v8i16, MVT::v4i64, 5 },
{ ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1 },
{ ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 2 },
{ ISD::FP_EXTEND, MVT::v8f64, MVT::v8f32, 3 },
{ ISD::FP_ROUND, MVT::v8f32, MVT::v8f64, 3 },
{ ISD::FP_TO_SINT, MVT::v16i16, MVT::v8f32, 1 },
{ ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f64, 1 },
{ ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f32, 1 },
{ ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, 3 },
{ ISD::FP_TO_UINT, MVT::i64, MVT::f32, 3 },
{ ISD::FP_TO_UINT, MVT::i64, MVT::f64, 3 },
{ ISD::FP_TO_UINT, MVT::v16i16, MVT::v8f32, 1 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 3 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, 4 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, 4 },
{ ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, 3 },
{ ISD::FP_TO_UINT, MVT::v8i32, MVT::v4f64, 4 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, 2 },
{ ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, 2 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, 2 },
{ ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 2 },
{ ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, 1 },
{ ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i32, 1 },
{ ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, 3 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, 2 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, 2 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, 2 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 2 },
{ ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 2 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 1 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 2 },
{ ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, 2 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, 2 },
{ ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, 4 },
};
static const TypeConversionCostTblEntry AVXConversionTbl[] = {
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 6 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 7 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 4 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 4 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, 3 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, 3 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, 3 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, 3 },
{ ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 3 },
{ ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 3 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, 3 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, 3 },
{ ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 3 },
{ ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 3 },
{ ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 3 },
{ ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 3 },
{ ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, 4 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 5 },
{ ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, 4 },
{ ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, 9 },
{ ISD::TRUNCATE, MVT::v16i1, MVT::v16i64, 11 },
{ ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, 6 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 6 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 2 }, { ISD::TRUNCATE, MVT::v16i8, MVT::v8i32, 5 },
{ ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 5 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v4i64, 5 },
{ ISD::TRUNCATE, MVT::v8i16, MVT::v4i64, 3 }, { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 2 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i1, 3 },
{ ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i1, 3 },
{ ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i1, 8 },
{ ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, 4 },
{ ISD::SINT_TO_FP, MVT::v4f64, MVT::v16i8, 2 },
{ ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 4 },
{ ISD::SINT_TO_FP, MVT::v4f64, MVT::v8i16, 2 },
{ ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, 2 },
{ ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i32, 2 },
{ ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, 4 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v2i64, 5 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i64, 8 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i1, 7 },
{ ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i1, 7 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i1, 6 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, 4 },
{ ISD::UINT_TO_FP, MVT::v4f64, MVT::v16i8, 2 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 4 },
{ ISD::UINT_TO_FP, MVT::v4f64, MVT::v8i16, 2 },
{ ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 4 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 4 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 5 },
{ ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, 6 },
{ ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, 8 },
{ ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, 10 },
{ ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, 10 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, 18 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 5 },
{ ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, 10 },
{ ISD::FP_TO_SINT, MVT::v16i8, MVT::v8f32, 2 },
{ ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f64, 2 },
{ ISD::FP_TO_SINT, MVT::v32i8, MVT::v8f32, 2 },
{ ISD::FP_TO_SINT, MVT::v32i8, MVT::v4f64, 2 },
{ ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f32, 2 },
{ ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f64, 2 },
{ ISD::FP_TO_SINT, MVT::v16i16, MVT::v8f32, 2 },
{ ISD::FP_TO_SINT, MVT::v16i16, MVT::v4f64, 2 },
{ ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f64, 2 },
{ ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f32, 2 },
{ ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, 5 },
{ ISD::FP_TO_UINT, MVT::v16i8, MVT::v8f32, 2 },
{ ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f64, 2 },
{ ISD::FP_TO_UINT, MVT::v32i8, MVT::v8f32, 2 },
{ ISD::FP_TO_UINT, MVT::v32i8, MVT::v4f64, 2 },
{ ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f32, 2 },
{ ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f64, 2 },
{ ISD::FP_TO_UINT, MVT::v16i16, MVT::v8f32, 2 },
{ ISD::FP_TO_UINT, MVT::v16i16, MVT::v4f64, 2 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 3 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, 4 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, 6 },
{ ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, 7 },
{ ISD::FP_TO_UINT, MVT::v8i32, MVT::v4f64, 7 },
{ ISD::FP_EXTEND, MVT::v4f64, MVT::v4f32, 1 },
{ ISD::FP_ROUND, MVT::v4f32, MVT::v4f64, 1 },
};
static const TypeConversionCostTblEntry SSE41ConversionTbl[] = {
{ ISD::ZERO_EXTEND, MVT::v2i64, MVT::v16i8, 1 },
{ ISD::SIGN_EXTEND, MVT::v2i64, MVT::v16i8, 1 },
{ ISD::ZERO_EXTEND, MVT::v4i32, MVT::v16i8, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i32, MVT::v16i8, 1 },
{ ISD::ZERO_EXTEND, MVT::v8i16, MVT::v16i8, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i16, MVT::v16i8, 1 },
{ ISD::ZERO_EXTEND, MVT::v2i64, MVT::v8i16, 1 },
{ ISD::SIGN_EXTEND, MVT::v2i64, MVT::v8i16, 1 },
{ ISD::ZERO_EXTEND, MVT::v4i32, MVT::v8i16, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i32, MVT::v8i16, 1 },
{ ISD::ZERO_EXTEND, MVT::v2i64, MVT::v4i32, 1 },
{ ISD::SIGN_EXTEND, MVT::v2i64, MVT::v4i32, 1 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 1 }, { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 1 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 1 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, 2 },
{ ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, 2 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, 2 },
{ ISD::SINT_TO_FP, MVT::f32, MVT::i32, 1 },
{ ISD::SINT_TO_FP, MVT::f64, MVT::i32, 1 },
{ ISD::SINT_TO_FP, MVT::f32, MVT::i64, 1 },
{ ISD::SINT_TO_FP, MVT::f64, MVT::i64, 1 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v16i8, 1 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, 1 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v8i16, 1 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, 1 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, 1 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v4i32, 1 },
{ ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, 2 },
{ ISD::UINT_TO_FP, MVT::f32, MVT::i32, 1 },
{ ISD::UINT_TO_FP, MVT::f64, MVT::i32, 1 },
{ ISD::UINT_TO_FP, MVT::f32, MVT::i64, 4 },
{ ISD::UINT_TO_FP, MVT::f64, MVT::i64, 4 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v16i8, 1 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, 1 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v8i16, 1 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, 1 },
{ ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 3 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 3 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v4i32, 2 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v2i64, 12 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, 22 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 4 },
{ ISD::FP_TO_SINT, MVT::i32, MVT::f32, 1 },
{ ISD::FP_TO_SINT, MVT::i64, MVT::f32, 1 },
{ ISD::FP_TO_SINT, MVT::i32, MVT::f64, 1 },
{ ISD::FP_TO_SINT, MVT::i64, MVT::f64, 1 },
{ ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f32, 2 },
{ ISD::FP_TO_SINT, MVT::v16i8, MVT::v2f64, 2 },
{ ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f32, 1 },
{ ISD::FP_TO_SINT, MVT::v8i16, MVT::v2f64, 1 },
{ ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 1 },
{ ISD::FP_TO_SINT, MVT::v4i32, MVT::v2f64, 1 },
{ ISD::FP_TO_UINT, MVT::i32, MVT::f32, 1 },
{ ISD::FP_TO_UINT, MVT::i64, MVT::f32, 4 },
{ ISD::FP_TO_UINT, MVT::i32, MVT::f64, 1 },
{ ISD::FP_TO_UINT, MVT::i64, MVT::f64, 4 },
{ ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f32, 2 },
{ ISD::FP_TO_UINT, MVT::v16i8, MVT::v2f64, 2 },
{ ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f32, 1 },
{ ISD::FP_TO_UINT, MVT::v8i16, MVT::v2f64, 1 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 4 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, 4 },
};
static const TypeConversionCostTblEntry SSE2ConversionTbl[] = {
{ ISD::SINT_TO_FP, MVT::f32, MVT::i32, 3 },
{ ISD::SINT_TO_FP, MVT::f64, MVT::i32, 3 },
{ ISD::SINT_TO_FP, MVT::f32, MVT::i64, 3 },
{ ISD::SINT_TO_FP, MVT::f64, MVT::i64, 3 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v16i8, 3 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, 4 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v8i16, 3 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, 4 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, 3 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v4i32, 4 },
{ ISD::SINT_TO_FP, MVT::v4f32, MVT::v2i64, 8 },
{ ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 8 },
{ ISD::UINT_TO_FP, MVT::f32, MVT::i32, 3 },
{ ISD::UINT_TO_FP, MVT::f64, MVT::i32, 3 },
{ ISD::UINT_TO_FP, MVT::f32, MVT::i64, 8 },
{ ISD::UINT_TO_FP, MVT::f64, MVT::i64, 9 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, 4 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v16i8, 4 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v8i16, 4 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, 4 },
{ ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 7 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v4i32, 7 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 5 },
{ ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 15 },
{ ISD::UINT_TO_FP, MVT::v4f32, MVT::v2i64, 18 },
{ ISD::FP_TO_SINT, MVT::i32, MVT::f32, 4 },
{ ISD::FP_TO_SINT, MVT::i64, MVT::f32, 4 },
{ ISD::FP_TO_SINT, MVT::i32, MVT::f64, 4 },
{ ISD::FP_TO_SINT, MVT::i64, MVT::f64, 4 },
{ ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f32, 6 },
{ ISD::FP_TO_SINT, MVT::v16i8, MVT::v2f64, 6 },
{ ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f32, 5 },
{ ISD::FP_TO_SINT, MVT::v8i16, MVT::v2f64, 5 },
{ ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 4 },
{ ISD::FP_TO_SINT, MVT::v4i32, MVT::v2f64, 4 },
{ ISD::FP_TO_UINT, MVT::i32, MVT::f32, 4 },
{ ISD::FP_TO_UINT, MVT::i64, MVT::f32, 4 },
{ ISD::FP_TO_UINT, MVT::i32, MVT::f64, 4 },
{ ISD::FP_TO_UINT, MVT::i64, MVT::f64, 15 },
{ ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f32, 6 },
{ ISD::FP_TO_UINT, MVT::v16i8, MVT::v2f64, 6 },
{ ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f32, 5 },
{ ISD::FP_TO_UINT, MVT::v8i16, MVT::v2f64, 5 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 8 },
{ ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, 8 },
{ ISD::ZERO_EXTEND, MVT::v2i64, MVT::v16i8, 4 },
{ ISD::SIGN_EXTEND, MVT::v2i64, MVT::v16i8, 4 },
{ ISD::ZERO_EXTEND, MVT::v4i32, MVT::v16i8, 2 },
{ ISD::SIGN_EXTEND, MVT::v4i32, MVT::v16i8, 3 },
{ ISD::ZERO_EXTEND, MVT::v8i16, MVT::v16i8, 1 },
{ ISD::SIGN_EXTEND, MVT::v8i16, MVT::v16i8, 2 },
{ ISD::ZERO_EXTEND, MVT::v2i64, MVT::v8i16, 2 },
{ ISD::SIGN_EXTEND, MVT::v2i64, MVT::v8i16, 3 },
{ ISD::ZERO_EXTEND, MVT::v4i32, MVT::v8i16, 1 },
{ ISD::SIGN_EXTEND, MVT::v4i32, MVT::v8i16, 2 },
{ ISD::ZERO_EXTEND, MVT::v2i64, MVT::v4i32, 1 },
{ ISD::SIGN_EXTEND, MVT::v2i64, MVT::v4i32, 2 },
{ ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, 1 }, { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 2 }, { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 3 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, 1 }, { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 2 }, { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, 1 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v8i16, 2 }, { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 3 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, 3 }, { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 7 },
{ ISD::TRUNCATE, MVT::v2i16, MVT::v2i32, 1 },
{ ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, 3 },
{ ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 5 },
{ ISD::TRUNCATE, MVT::v16i16, MVT::v16i32,10 },
{ ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, 4 }, { ISD::TRUNCATE, MVT::v8i16, MVT::v2i64, 2 }, { ISD::TRUNCATE, MVT::v4i32, MVT::v2i64, 1 }, };
EVT SrcTy = TLI->getValueType(DL, Src);
EVT DstTy = TLI->getValueType(DL, Dst);
if (SrcTy.isSimple() && DstTy.isSimple()) {
MVT SimpleSrcTy = SrcTy.getSimpleVT();
MVT SimpleDstTy = DstTy.getSimpleVT();
if (ST->useAVX512Regs()) {
if (ST->hasBWI())
if (const auto *Entry = ConvertCostTableLookup(
AVX512BWConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
return AdjustCost(Entry->Cost);
if (ST->hasDQI())
if (const auto *Entry = ConvertCostTableLookup(
AVX512DQConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
return AdjustCost(Entry->Cost);
if (ST->hasAVX512())
if (const auto *Entry = ConvertCostTableLookup(
AVX512FConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
return AdjustCost(Entry->Cost);
}
if (ST->hasBWI())
if (const auto *Entry = ConvertCostTableLookup(
AVX512BWVLConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
return AdjustCost(Entry->Cost);
if (ST->hasDQI())
if (const auto *Entry = ConvertCostTableLookup(
AVX512DQVLConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
return AdjustCost(Entry->Cost);
if (ST->hasAVX512())
if (const auto *Entry = ConvertCostTableLookup(AVX512VLConversionTbl, ISD,
SimpleDstTy, SimpleSrcTy))
return AdjustCost(Entry->Cost);
if (ST->hasAVX2()) {
if (const auto *Entry = ConvertCostTableLookup(AVX2ConversionTbl, ISD,
SimpleDstTy, SimpleSrcTy))
return AdjustCost(Entry->Cost);
}
if (ST->hasAVX()) {
if (const auto *Entry = ConvertCostTableLookup(AVXConversionTbl, ISD,
SimpleDstTy, SimpleSrcTy))
return AdjustCost(Entry->Cost);
}
if (ST->hasSSE41()) {
if (const auto *Entry = ConvertCostTableLookup(SSE41ConversionTbl, ISD,
SimpleDstTy, SimpleSrcTy))
return AdjustCost(Entry->Cost);
}
if (ST->hasSSE2()) {
if (const auto *Entry = ConvertCostTableLookup(SSE2ConversionTbl, ISD,
SimpleDstTy, SimpleSrcTy))
return AdjustCost(Entry->Cost);
}
}
std::pair<InstructionCost, MVT> LTSrc = TLI->getTypeLegalizationCost(DL, Src);
std::pair<InstructionCost, MVT> LTDest =
TLI->getTypeLegalizationCost(DL, Dst);
if (ISD == ISD::TRUNCATE && LTSrc.second == LTDest.second)
return TTI::TCC_Free;
if (ST->useAVX512Regs()) {
if (ST->hasBWI())
if (const auto *Entry = ConvertCostTableLookup(
AVX512BWConversionTbl, ISD, LTDest.second, LTSrc.second))
return AdjustCost(std::max(LTSrc.first, LTDest.first) * Entry->Cost);
if (ST->hasDQI())
if (const auto *Entry = ConvertCostTableLookup(
AVX512DQConversionTbl, ISD, LTDest.second, LTSrc.second))
return AdjustCost(std::max(LTSrc.first, LTDest.first) * Entry->Cost);
if (ST->hasAVX512())
if (const auto *Entry = ConvertCostTableLookup(
AVX512FConversionTbl, ISD, LTDest.second, LTSrc.second))
return AdjustCost(std::max(LTSrc.first, LTDest.first) * Entry->Cost);
}
if (ST->hasBWI())
if (const auto *Entry = ConvertCostTableLookup(AVX512BWVLConversionTbl, ISD,
LTDest.second, LTSrc.second))
return AdjustCost(std::max(LTSrc.first, LTDest.first) * Entry->Cost);
if (ST->hasDQI())
if (const auto *Entry = ConvertCostTableLookup(AVX512DQVLConversionTbl, ISD,
LTDest.second, LTSrc.second))
return AdjustCost(std::max(LTSrc.first, LTDest.first) * Entry->Cost);
if (ST->hasAVX512())
if (const auto *Entry = ConvertCostTableLookup(AVX512VLConversionTbl, ISD,
LTDest.second, LTSrc.second))
return AdjustCost(std::max(LTSrc.first, LTDest.first) * Entry->Cost);
if (ST->hasAVX2())
if (const auto *Entry = ConvertCostTableLookup(AVX2ConversionTbl, ISD,
LTDest.second, LTSrc.second))
return AdjustCost(std::max(LTSrc.first, LTDest.first) * Entry->Cost);
if (ST->hasAVX())
if (const auto *Entry = ConvertCostTableLookup(AVXConversionTbl, ISD,
LTDest.second, LTSrc.second))
return AdjustCost(std::max(LTSrc.first, LTDest.first) * Entry->Cost);
if (ST->hasSSE41())
if (const auto *Entry = ConvertCostTableLookup(SSE41ConversionTbl, ISD,
LTDest.second, LTSrc.second))
return AdjustCost(std::max(LTSrc.first, LTDest.first) * Entry->Cost);
if (ST->hasSSE2())
if (const auto *Entry = ConvertCostTableLookup(SSE2ConversionTbl, ISD,
LTDest.second, LTSrc.second))
return AdjustCost(std::max(LTSrc.first, LTDest.first) * Entry->Cost);
if ((ISD == ISD::SINT_TO_FP || ISD == ISD::UINT_TO_FP) &&
1 < Src->getScalarSizeInBits() && Src->getScalarSizeInBits() < 32) {
Type *ExtSrc = Src->getWithNewBitWidth(32);
unsigned ExtOpc =
(ISD == ISD::SINT_TO_FP) ? Instruction::SExt : Instruction::ZExt;
InstructionCost ExtCost = 0;
if (!(Src->isIntegerTy() && I && isa<LoadInst>(I->getOperand(0))))
ExtCost = getCastInstrCost(ExtOpc, ExtSrc, Src, CCH, CostKind);
return ExtCost + getCastInstrCost(Instruction::SIToFP, Dst, ExtSrc,
TTI::CastContextHint::None, CostKind);
}
if ((ISD == ISD::FP_TO_SINT || ISD == ISD::FP_TO_UINT) &&
1 < Dst->getScalarSizeInBits() && Dst->getScalarSizeInBits() < 32) {
Type *TruncDst = Dst->getWithNewBitWidth(32);
return getCastInstrCost(Instruction::FPToSI, TruncDst, Src, CCH, CostKind) +
getCastInstrCost(Instruction::Trunc, Dst, TruncDst,
TTI::CastContextHint::None, CostKind);
}
return AdjustCost(
BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I));
}
InstructionCost X86TTIImpl::getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
Type *CondTy,
CmpInst::Predicate VecPred,
TTI::TargetCostKind CostKind,
const Instruction *I) {
if (CostKind != TTI::TCK_RecipThroughput)
return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
I);
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, ValTy);
MVT MTy = LT.second;
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
InstructionCost ExtraCost = 0;
if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) {
if (MTy.isVector() &&
!((ST->hasXOP() && (!ST->hasAVX2() || MTy.is128BitVector())) ||
(ST->hasAVX512() && 32 <= MTy.getScalarSizeInBits()) ||
ST->hasBWI())) {
CmpInst::Predicate Pred = VecPred;
if (I && (Pred == CmpInst::BAD_ICMP_PREDICATE ||
Pred == CmpInst::BAD_FCMP_PREDICATE))
Pred = cast<CmpInst>(I)->getPredicate();
switch (Pred) {
case CmpInst::Predicate::ICMP_NE:
ExtraCost = 1;
break;
case CmpInst::Predicate::ICMP_SGE:
case CmpInst::Predicate::ICMP_SLE:
ExtraCost = 1;
break;
case CmpInst::Predicate::ICMP_ULT:
case CmpInst::Predicate::ICMP_UGT:
ExtraCost = 2;
break;
case CmpInst::Predicate::ICMP_ULE:
case CmpInst::Predicate::ICMP_UGE:
if ((ST->hasSSE41() && MTy.getScalarSizeInBits() == 32) ||
(ST->hasSSE2() && MTy.getScalarSizeInBits() < 32)) {
ExtraCost = 1;
} else {
ExtraCost = 3;
}
break;
case CmpInst::Predicate::BAD_ICMP_PREDICATE:
case CmpInst::Predicate::BAD_FCMP_PREDICATE:
ExtraCost = 3;
break;
default:
break;
}
}
}
static const CostTblEntry SLMCostTbl[] = {
{ ISD::SETCC, MVT::v2i64, 2 },
};
static const CostTblEntry AVX512BWCostTbl[] = {
{ ISD::SETCC, MVT::v32i16, 1 },
{ ISD::SETCC, MVT::v64i8, 1 },
{ ISD::SELECT, MVT::v32i16, 1 },
{ ISD::SELECT, MVT::v64i8, 1 },
};
static const CostTblEntry AVX512CostTbl[] = {
{ ISD::SETCC, MVT::v8i64, 1 },
{ ISD::SETCC, MVT::v16i32, 1 },
{ ISD::SETCC, MVT::v8f64, 1 },
{ ISD::SETCC, MVT::v16f32, 1 },
{ ISD::SELECT, MVT::v8i64, 1 },
{ ISD::SELECT, MVT::v4i64, 1 },
{ ISD::SELECT, MVT::v2i64, 1 },
{ ISD::SELECT, MVT::v16i32, 1 },
{ ISD::SELECT, MVT::v8i32, 1 },
{ ISD::SELECT, MVT::v4i32, 1 },
{ ISD::SELECT, MVT::v8f64, 1 },
{ ISD::SELECT, MVT::v4f64, 1 },
{ ISD::SELECT, MVT::v2f64, 1 },
{ ISD::SELECT, MVT::f64, 1 },
{ ISD::SELECT, MVT::v16f32, 1 },
{ ISD::SELECT, MVT::v8f32 , 1 },
{ ISD::SELECT, MVT::v4f32, 1 },
{ ISD::SELECT, MVT::f32 , 1 },
{ ISD::SETCC, MVT::v32i16, 2 }, { ISD::SETCC, MVT::v64i8, 2 },
{ ISD::SELECT, MVT::v32i16, 2 },
{ ISD::SELECT, MVT::v16i16, 1 },
{ ISD::SELECT, MVT::v8i16, 1 },
{ ISD::SELECT, MVT::v64i8, 2 },
{ ISD::SELECT, MVT::v32i8, 1 },
{ ISD::SELECT, MVT::v16i8, 1 },
};
static const CostTblEntry AVX2CostTbl[] = {
{ ISD::SETCC, MVT::v4i64, 1 },
{ ISD::SETCC, MVT::v8i32, 1 },
{ ISD::SETCC, MVT::v16i16, 1 },
{ ISD::SETCC, MVT::v32i8, 1 },
{ ISD::SELECT, MVT::v4f64, 2 }, { ISD::SELECT, MVT::v8f32, 2 }, { ISD::SELECT, MVT::v4i64, 2 }, { ISD::SELECT, MVT::v8i32, 2 }, { ISD::SELECT, MVT::v16i16, 2 }, { ISD::SELECT, MVT::v32i8, 2 }, };
static const CostTblEntry AVX1CostTbl[] = {
{ ISD::SETCC, MVT::v4f64, 1 },
{ ISD::SETCC, MVT::v8f32, 1 },
{ ISD::SETCC, MVT::v4i64, 4 },
{ ISD::SETCC, MVT::v8i32, 4 },
{ ISD::SETCC, MVT::v16i16, 4 },
{ ISD::SETCC, MVT::v32i8, 4 },
{ ISD::SELECT, MVT::v4f64, 3 }, { ISD::SELECT, MVT::v8f32, 3 }, { ISD::SELECT, MVT::v4i64, 3 }, { ISD::SELECT, MVT::v8i32, 3 }, { ISD::SELECT, MVT::v16i16, 3 }, { ISD::SELECT, MVT::v32i8, 3 }, };
static const CostTblEntry SSE42CostTbl[] = {
{ ISD::SETCC, MVT::v2i64, 1 },
};
static const CostTblEntry SSE41CostTbl[] = {
{ ISD::SETCC, MVT::v2f64, 1 },
{ ISD::SETCC, MVT::v4f32, 1 },
{ ISD::SELECT, MVT::v2f64, 2 }, { ISD::SELECT, MVT::f64, 2 }, { ISD::SELECT, MVT::v4f32, 2 }, { ISD::SELECT, MVT::f32 , 2 }, { ISD::SELECT, MVT::v2i64, 2 }, { ISD::SELECT, MVT::v4i32, 2 }, { ISD::SELECT, MVT::v8i16, 2 }, { ISD::SELECT, MVT::v16i8, 2 }, };
static const CostTblEntry SSE2CostTbl[] = {
{ ISD::SETCC, MVT::v2f64, 2 },
{ ISD::SETCC, MVT::f64, 1 },
{ ISD::SETCC, MVT::v2i64, 5 }, { ISD::SETCC, MVT::v4i32, 1 },
{ ISD::SETCC, MVT::v8i16, 1 },
{ ISD::SETCC, MVT::v16i8, 1 },
{ ISD::SELECT, MVT::v2f64, 2 }, { ISD::SELECT, MVT::f64, 2 }, { ISD::SELECT, MVT::v2i64, 2 }, { ISD::SELECT, MVT::v4i32, 2 }, { ISD::SELECT, MVT::v8i16, 2 }, { ISD::SELECT, MVT::v16i8, 2 }, };
static const CostTblEntry SSE1CostTbl[] = {
{ ISD::SETCC, MVT::v4f32, 2 },
{ ISD::SETCC, MVT::f32, 1 },
{ ISD::SELECT, MVT::v4f32, 2 }, { ISD::SELECT, MVT::f32, 2 }, };
if (ST->useSLMArithCosts())
if (const auto *Entry = CostTableLookup(SLMCostTbl, ISD, MTy))
return LT.first * (ExtraCost + Entry->Cost);
if (ST->hasBWI())
if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
return LT.first * (ExtraCost + Entry->Cost);
if (ST->hasAVX512())
if (const auto *Entry = CostTableLookup(AVX512CostTbl, ISD, MTy))
return LT.first * (ExtraCost + Entry->Cost);
if (ST->hasAVX2())
if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
return LT.first * (ExtraCost + Entry->Cost);
if (ST->hasAVX())
if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
return LT.first * (ExtraCost + Entry->Cost);
if (ST->hasSSE42())
if (const auto *Entry = CostTableLookup(SSE42CostTbl, ISD, MTy))
return LT.first * (ExtraCost + Entry->Cost);
if (ST->hasSSE41())
if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
return LT.first * (ExtraCost + Entry->Cost);
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
return LT.first * (ExtraCost + Entry->Cost);
if (ST->hasSSE1())
if (const auto *Entry = CostTableLookup(SSE1CostTbl, ISD, MTy))
return LT.first * (ExtraCost + Entry->Cost);
return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind, I);
}
unsigned X86TTIImpl::getAtomicMemIntrinsicMaxElementSize() const { return 16; }
InstructionCost
X86TTIImpl::getTypeBasedIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,
TTI::TargetCostKind CostKind) {
static const CostTblEntry AVX512BITALGCostTbl[] = {
{ ISD::CTPOP, MVT::v32i16, 1 },
{ ISD::CTPOP, MVT::v64i8, 1 },
{ ISD::CTPOP, MVT::v16i16, 1 },
{ ISD::CTPOP, MVT::v32i8, 1 },
{ ISD::CTPOP, MVT::v8i16, 1 },
{ ISD::CTPOP, MVT::v16i8, 1 },
};
static const CostTblEntry AVX512VPOPCNTDQCostTbl[] = {
{ ISD::CTPOP, MVT::v8i64, 1 },
{ ISD::CTPOP, MVT::v16i32, 1 },
{ ISD::CTPOP, MVT::v4i64, 1 },
{ ISD::CTPOP, MVT::v8i32, 1 },
{ ISD::CTPOP, MVT::v2i64, 1 },
{ ISD::CTPOP, MVT::v4i32, 1 },
};
static const CostTblEntry AVX512CDCostTbl[] = {
{ ISD::CTLZ, MVT::v8i64, 1 },
{ ISD::CTLZ, MVT::v16i32, 1 },
{ ISD::CTLZ, MVT::v32i16, 8 },
{ ISD::CTLZ, MVT::v64i8, 20 },
{ ISD::CTLZ, MVT::v4i64, 1 },
{ ISD::CTLZ, MVT::v8i32, 1 },
{ ISD::CTLZ, MVT::v16i16, 4 },
{ ISD::CTLZ, MVT::v32i8, 10 },
{ ISD::CTLZ, MVT::v2i64, 1 },
{ ISD::CTLZ, MVT::v4i32, 1 },
{ ISD::CTLZ, MVT::v8i16, 4 },
{ ISD::CTLZ, MVT::v16i8, 4 },
};
static const CostTblEntry AVX512BWCostTbl[] = {
{ ISD::ABS, MVT::v32i16, 1 },
{ ISD::ABS, MVT::v64i8, 1 },
{ ISD::BITREVERSE, MVT::v8i64, 3 },
{ ISD::BITREVERSE, MVT::v16i32, 3 },
{ ISD::BITREVERSE, MVT::v32i16, 3 },
{ ISD::BITREVERSE, MVT::v64i8, 2 },
{ ISD::BSWAP, MVT::v8i64, 1 },
{ ISD::BSWAP, MVT::v16i32, 1 },
{ ISD::BSWAP, MVT::v32i16, 1 },
{ ISD::CTLZ, MVT::v8i64, 23 },
{ ISD::CTLZ, MVT::v16i32, 22 },
{ ISD::CTLZ, MVT::v32i16, 18 },
{ ISD::CTLZ, MVT::v64i8, 17 },
{ ISD::CTPOP, MVT::v8i64, 7 },
{ ISD::CTPOP, MVT::v16i32, 11 },
{ ISD::CTPOP, MVT::v32i16, 9 },
{ ISD::CTPOP, MVT::v64i8, 6 },
{ ISD::CTTZ, MVT::v8i64, 10 },
{ ISD::CTTZ, MVT::v16i32, 14 },
{ ISD::CTTZ, MVT::v32i16, 12 },
{ ISD::CTTZ, MVT::v64i8, 9 },
{ ISD::SADDSAT, MVT::v32i16, 1 },
{ ISD::SADDSAT, MVT::v64i8, 1 },
{ ISD::SMAX, MVT::v32i16, 1 },
{ ISD::SMAX, MVT::v64i8, 1 },
{ ISD::SMIN, MVT::v32i16, 1 },
{ ISD::SMIN, MVT::v64i8, 1 },
{ ISD::SSUBSAT, MVT::v32i16, 1 },
{ ISD::SSUBSAT, MVT::v64i8, 1 },
{ ISD::UADDSAT, MVT::v32i16, 1 },
{ ISD::UADDSAT, MVT::v64i8, 1 },
{ ISD::UMAX, MVT::v32i16, 1 },
{ ISD::UMAX, MVT::v64i8, 1 },
{ ISD::UMIN, MVT::v32i16, 1 },
{ ISD::UMIN, MVT::v64i8, 1 },
{ ISD::USUBSAT, MVT::v32i16, 1 },
{ ISD::USUBSAT, MVT::v64i8, 1 },
};
static const CostTblEntry AVX512CostTbl[] = {
{ ISD::ABS, MVT::v8i64, 1 },
{ ISD::ABS, MVT::v16i32, 1 },
{ ISD::ABS, MVT::v32i16, 2 },
{ ISD::ABS, MVT::v64i8, 2 },
{ ISD::ABS, MVT::v4i64, 1 },
{ ISD::ABS, MVT::v2i64, 1 },
{ ISD::BITREVERSE, MVT::v8i64, 36 },
{ ISD::BITREVERSE, MVT::v16i32, 24 },
{ ISD::BITREVERSE, MVT::v32i16, 10 },
{ ISD::BITREVERSE, MVT::v64i8, 10 },
{ ISD::BSWAP, MVT::v8i64, 4 },
{ ISD::BSWAP, MVT::v16i32, 4 },
{ ISD::BSWAP, MVT::v32i16, 4 },
{ ISD::CTLZ, MVT::v8i64, 29 },
{ ISD::CTLZ, MVT::v16i32, 35 },
{ ISD::CTLZ, MVT::v32i16, 28 },
{ ISD::CTLZ, MVT::v64i8, 18 },
{ ISD::CTPOP, MVT::v8i64, 16 },
{ ISD::CTPOP, MVT::v16i32, 24 },
{ ISD::CTPOP, MVT::v32i16, 18 },
{ ISD::CTPOP, MVT::v64i8, 12 },
{ ISD::CTTZ, MVT::v8i64, 20 },
{ ISD::CTTZ, MVT::v16i32, 28 },
{ ISD::CTTZ, MVT::v32i16, 24 },
{ ISD::CTTZ, MVT::v64i8, 18 },
{ ISD::SMAX, MVT::v8i64, 1 },
{ ISD::SMAX, MVT::v16i32, 1 },
{ ISD::SMAX, MVT::v32i16, 2 },
{ ISD::SMAX, MVT::v64i8, 2 },
{ ISD::SMAX, MVT::v4i64, 1 },
{ ISD::SMAX, MVT::v2i64, 1 },
{ ISD::SMIN, MVT::v8i64, 1 },
{ ISD::SMIN, MVT::v16i32, 1 },
{ ISD::SMIN, MVT::v32i16, 2 },
{ ISD::SMIN, MVT::v64i8, 2 },
{ ISD::SMIN, MVT::v4i64, 1 },
{ ISD::SMIN, MVT::v2i64, 1 },
{ ISD::UMAX, MVT::v8i64, 1 },
{ ISD::UMAX, MVT::v16i32, 1 },
{ ISD::UMAX, MVT::v32i16, 2 },
{ ISD::UMAX, MVT::v64i8, 2 },
{ ISD::UMAX, MVT::v4i64, 1 },
{ ISD::UMAX, MVT::v2i64, 1 },
{ ISD::UMIN, MVT::v8i64, 1 },
{ ISD::UMIN, MVT::v16i32, 1 },
{ ISD::UMIN, MVT::v32i16, 2 },
{ ISD::UMIN, MVT::v64i8, 2 },
{ ISD::UMIN, MVT::v4i64, 1 },
{ ISD::UMIN, MVT::v2i64, 1 },
{ ISD::USUBSAT, MVT::v16i32, 2 }, { ISD::USUBSAT, MVT::v2i64, 2 }, { ISD::USUBSAT, MVT::v4i64, 2 }, { ISD::USUBSAT, MVT::v8i64, 2 }, { ISD::UADDSAT, MVT::v16i32, 3 }, { ISD::UADDSAT, MVT::v2i64, 3 }, { ISD::UADDSAT, MVT::v4i64, 3 }, { ISD::UADDSAT, MVT::v8i64, 3 }, { ISD::SADDSAT, MVT::v32i16, 2 },
{ ISD::SADDSAT, MVT::v64i8, 2 },
{ ISD::SSUBSAT, MVT::v32i16, 2 },
{ ISD::SSUBSAT, MVT::v64i8, 2 },
{ ISD::UADDSAT, MVT::v32i16, 2 },
{ ISD::UADDSAT, MVT::v64i8, 2 },
{ ISD::USUBSAT, MVT::v32i16, 2 },
{ ISD::USUBSAT, MVT::v64i8, 2 },
{ ISD::FMAXNUM, MVT::f32, 2 },
{ ISD::FMAXNUM, MVT::v4f32, 2 },
{ ISD::FMAXNUM, MVT::v8f32, 2 },
{ ISD::FMAXNUM, MVT::v16f32, 2 },
{ ISD::FMAXNUM, MVT::f64, 2 },
{ ISD::FMAXNUM, MVT::v2f64, 2 },
{ ISD::FMAXNUM, MVT::v4f64, 2 },
{ ISD::FMAXNUM, MVT::v8f64, 2 },
};
static const CostTblEntry XOPCostTbl[] = {
{ ISD::BITREVERSE, MVT::v4i64, 4 },
{ ISD::BITREVERSE, MVT::v8i32, 4 },
{ ISD::BITREVERSE, MVT::v16i16, 4 },
{ ISD::BITREVERSE, MVT::v32i8, 4 },
{ ISD::BITREVERSE, MVT::v2i64, 1 },
{ ISD::BITREVERSE, MVT::v4i32, 1 },
{ ISD::BITREVERSE, MVT::v8i16, 1 },
{ ISD::BITREVERSE, MVT::v16i8, 1 },
{ ISD::BITREVERSE, MVT::i64, 3 },
{ ISD::BITREVERSE, MVT::i32, 3 },
{ ISD::BITREVERSE, MVT::i16, 3 },
{ ISD::BITREVERSE, MVT::i8, 3 }
};
static const CostTblEntry AVX2CostTbl[] = {
{ ISD::ABS, MVT::v4i64, 2 }, { ISD::ABS, MVT::v8i32, 1 },
{ ISD::ABS, MVT::v16i16, 1 },
{ ISD::ABS, MVT::v32i8, 1 },
{ ISD::BITREVERSE, MVT::v2i64, 3 },
{ ISD::BITREVERSE, MVT::v4i64, 3 },
{ ISD::BITREVERSE, MVT::v4i32, 3 },
{ ISD::BITREVERSE, MVT::v8i32, 3 },
{ ISD::BITREVERSE, MVT::v8i16, 3 },
{ ISD::BITREVERSE, MVT::v16i16, 3 },
{ ISD::BITREVERSE, MVT::v16i8, 3 },
{ ISD::BITREVERSE, MVT::v32i8, 3 },
{ ISD::BSWAP, MVT::v4i64, 1 },
{ ISD::BSWAP, MVT::v8i32, 1 },
{ ISD::BSWAP, MVT::v16i16, 1 },
{ ISD::CTLZ, MVT::v2i64, 7 },
{ ISD::CTLZ, MVT::v4i64, 7 },
{ ISD::CTLZ, MVT::v4i32, 5 },
{ ISD::CTLZ, MVT::v8i32, 5 },
{ ISD::CTLZ, MVT::v8i16, 4 },
{ ISD::CTLZ, MVT::v16i16, 4 },
{ ISD::CTLZ, MVT::v16i8, 3 },
{ ISD::CTLZ, MVT::v32i8, 3 },
{ ISD::CTPOP, MVT::v2i64, 3 },
{ ISD::CTPOP, MVT::v4i64, 3 },
{ ISD::CTPOP, MVT::v4i32, 7 },
{ ISD::CTPOP, MVT::v8i32, 7 },
{ ISD::CTPOP, MVT::v8i16, 3 },
{ ISD::CTPOP, MVT::v16i16, 3 },
{ ISD::CTPOP, MVT::v16i8, 2 },
{ ISD::CTPOP, MVT::v32i8, 2 },
{ ISD::CTTZ, MVT::v2i64, 4 },
{ ISD::CTTZ, MVT::v4i64, 4 },
{ ISD::CTTZ, MVT::v4i32, 7 },
{ ISD::CTTZ, MVT::v8i32, 7 },
{ ISD::CTTZ, MVT::v8i16, 4 },
{ ISD::CTTZ, MVT::v16i16, 4 },
{ ISD::CTTZ, MVT::v16i8, 3 },
{ ISD::CTTZ, MVT::v32i8, 3 },
{ ISD::SADDSAT, MVT::v16i16, 1 },
{ ISD::SADDSAT, MVT::v32i8, 1 },
{ ISD::SMAX, MVT::v8i32, 1 },
{ ISD::SMAX, MVT::v16i16, 1 },
{ ISD::SMAX, MVT::v32i8, 1 },
{ ISD::SMIN, MVT::v8i32, 1 },
{ ISD::SMIN, MVT::v16i16, 1 },
{ ISD::SMIN, MVT::v32i8, 1 },
{ ISD::SSUBSAT, MVT::v16i16, 1 },
{ ISD::SSUBSAT, MVT::v32i8, 1 },
{ ISD::UADDSAT, MVT::v16i16, 1 },
{ ISD::UADDSAT, MVT::v32i8, 1 },
{ ISD::UADDSAT, MVT::v8i32, 3 }, { ISD::UMAX, MVT::v8i32, 1 },
{ ISD::UMAX, MVT::v16i16, 1 },
{ ISD::UMAX, MVT::v32i8, 1 },
{ ISD::UMIN, MVT::v8i32, 1 },
{ ISD::UMIN, MVT::v16i16, 1 },
{ ISD::UMIN, MVT::v32i8, 1 },
{ ISD::USUBSAT, MVT::v16i16, 1 },
{ ISD::USUBSAT, MVT::v32i8, 1 },
{ ISD::USUBSAT, MVT::v8i32, 2 }, { ISD::FMAXNUM, MVT::v8f32, 3 }, { ISD::FMAXNUM, MVT::v4f64, 3 }, { ISD::FSQRT, MVT::f32, 7 }, { ISD::FSQRT, MVT::v4f32, 7 }, { ISD::FSQRT, MVT::v8f32, 14 }, { ISD::FSQRT, MVT::f64, 14 }, { ISD::FSQRT, MVT::v2f64, 14 }, { ISD::FSQRT, MVT::v4f64, 28 }, };
static const CostTblEntry AVX1CostTbl[] = {
{ ISD::ABS, MVT::v4i64, 5 }, { ISD::ABS, MVT::v8i32, 3 },
{ ISD::ABS, MVT::v16i16, 3 },
{ ISD::ABS, MVT::v32i8, 3 },
{ ISD::BITREVERSE, MVT::v4i64, 12 }, { ISD::BITREVERSE, MVT::v8i32, 12 }, { ISD::BITREVERSE, MVT::v16i16, 12 }, { ISD::BITREVERSE, MVT::v32i8, 12 }, { ISD::BSWAP, MVT::v4i64, 4 },
{ ISD::BSWAP, MVT::v8i32, 4 },
{ ISD::BSWAP, MVT::v16i16, 4 },
{ ISD::CTLZ, MVT::v4i64, 48 }, { ISD::CTLZ, MVT::v8i32, 38 }, { ISD::CTLZ, MVT::v16i16, 30 }, { ISD::CTLZ, MVT::v32i8, 20 }, { ISD::CTPOP, MVT::v4i64, 16 }, { ISD::CTPOP, MVT::v8i32, 24 }, { ISD::CTPOP, MVT::v16i16, 20 }, { ISD::CTPOP, MVT::v32i8, 14 }, { ISD::CTTZ, MVT::v4i64, 22 }, { ISD::CTTZ, MVT::v8i32, 30 }, { ISD::CTTZ, MVT::v16i16, 26 }, { ISD::CTTZ, MVT::v32i8, 20 }, { ISD::SADDSAT, MVT::v16i16, 4 }, { ISD::SADDSAT, MVT::v32i8, 4 }, { ISD::SMAX, MVT::v8i32, 4 }, { ISD::SMAX, MVT::v16i16, 4 }, { ISD::SMAX, MVT::v32i8, 4 }, { ISD::SMIN, MVT::v8i32, 4 }, { ISD::SMIN, MVT::v16i16, 4 }, { ISD::SMIN, MVT::v32i8, 4 }, { ISD::SSUBSAT, MVT::v16i16, 4 }, { ISD::SSUBSAT, MVT::v32i8, 4 }, { ISD::UADDSAT, MVT::v16i16, 4 }, { ISD::UADDSAT, MVT::v32i8, 4 }, { ISD::UADDSAT, MVT::v8i32, 8 }, { ISD::UMAX, MVT::v8i32, 4 }, { ISD::UMAX, MVT::v16i16, 4 }, { ISD::UMAX, MVT::v32i8, 4 }, { ISD::UMIN, MVT::v8i32, 4 }, { ISD::UMIN, MVT::v16i16, 4 }, { ISD::UMIN, MVT::v32i8, 4 }, { ISD::USUBSAT, MVT::v16i16, 4 }, { ISD::USUBSAT, MVT::v32i8, 4 }, { ISD::USUBSAT, MVT::v8i32, 6 }, { ISD::FMAXNUM, MVT::f32, 3 }, { ISD::FMAXNUM, MVT::v4f32, 3 }, { ISD::FMAXNUM, MVT::v8f32, 5 }, { ISD::FMAXNUM, MVT::f64, 3 }, { ISD::FMAXNUM, MVT::v2f64, 3 }, { ISD::FMAXNUM, MVT::v4f64, 5 }, { ISD::FSQRT, MVT::f32, 14 }, { ISD::FSQRT, MVT::v4f32, 14 }, { ISD::FSQRT, MVT::v8f32, 28 }, { ISD::FSQRT, MVT::f64, 21 }, { ISD::FSQRT, MVT::v2f64, 21 }, { ISD::FSQRT, MVT::v4f64, 43 }, };
static const CostTblEntry GLMCostTbl[] = {
{ ISD::FSQRT, MVT::f32, 19 }, { ISD::FSQRT, MVT::v4f32, 37 }, { ISD::FSQRT, MVT::f64, 34 }, { ISD::FSQRT, MVT::v2f64, 67 }, };
static const CostTblEntry SLMCostTbl[] = {
{ ISD::FSQRT, MVT::f32, 20 }, { ISD::FSQRT, MVT::v4f32, 40 }, { ISD::FSQRT, MVT::f64, 35 }, { ISD::FSQRT, MVT::v2f64, 70 }, };
static const CostTblEntry SSE42CostTbl[] = {
{ ISD::USUBSAT, MVT::v4i32, 2 }, { ISD::UADDSAT, MVT::v4i32, 3 }, { ISD::FSQRT, MVT::f32, 18 }, { ISD::FSQRT, MVT::v4f32, 18 }, };
static const CostTblEntry SSE41CostTbl[] = {
{ ISD::ABS, MVT::v2i64, 2 }, { ISD::SMAX, MVT::v4i32, 1 },
{ ISD::SMAX, MVT::v16i8, 1 },
{ ISD::SMIN, MVT::v4i32, 1 },
{ ISD::SMIN, MVT::v16i8, 1 },
{ ISD::UMAX, MVT::v4i32, 1 },
{ ISD::UMAX, MVT::v8i16, 1 },
{ ISD::UMIN, MVT::v4i32, 1 },
{ ISD::UMIN, MVT::v8i16, 1 },
};
static const CostTblEntry SSSE3CostTbl[] = {
{ ISD::ABS, MVT::v4i32, 1 },
{ ISD::ABS, MVT::v8i16, 1 },
{ ISD::ABS, MVT::v16i8, 1 },
{ ISD::BITREVERSE, MVT::v2i64, 5 },
{ ISD::BITREVERSE, MVT::v4i32, 5 },
{ ISD::BITREVERSE, MVT::v8i16, 5 },
{ ISD::BITREVERSE, MVT::v16i8, 5 },
{ ISD::BSWAP, MVT::v2i64, 1 },
{ ISD::BSWAP, MVT::v4i32, 1 },
{ ISD::BSWAP, MVT::v8i16, 1 },
{ ISD::CTLZ, MVT::v2i64, 23 },
{ ISD::CTLZ, MVT::v4i32, 18 },
{ ISD::CTLZ, MVT::v8i16, 14 },
{ ISD::CTLZ, MVT::v16i8, 9 },
{ ISD::CTPOP, MVT::v2i64, 7 },
{ ISD::CTPOP, MVT::v4i32, 11 },
{ ISD::CTPOP, MVT::v8i16, 9 },
{ ISD::CTPOP, MVT::v16i8, 6 },
{ ISD::CTTZ, MVT::v2i64, 10 },
{ ISD::CTTZ, MVT::v4i32, 14 },
{ ISD::CTTZ, MVT::v8i16, 12 },
{ ISD::CTTZ, MVT::v16i8, 9 }
};
static const CostTblEntry SSE2CostTbl[] = {
{ ISD::ABS, MVT::v2i64, 4 },
{ ISD::ABS, MVT::v4i32, 3 },
{ ISD::ABS, MVT::v8i16, 2 },
{ ISD::ABS, MVT::v16i8, 2 },
{ ISD::BITREVERSE, MVT::v2i64, 29 },
{ ISD::BITREVERSE, MVT::v4i32, 27 },
{ ISD::BITREVERSE, MVT::v8i16, 27 },
{ ISD::BITREVERSE, MVT::v16i8, 20 },
{ ISD::BSWAP, MVT::v2i64, 7 },
{ ISD::BSWAP, MVT::v4i32, 7 },
{ ISD::BSWAP, MVT::v8i16, 7 },
{ ISD::CTLZ, MVT::v2i64, 25 },
{ ISD::CTLZ, MVT::v4i32, 26 },
{ ISD::CTLZ, MVT::v8i16, 20 },
{ ISD::CTLZ, MVT::v16i8, 17 },
{ ISD::CTPOP, MVT::v2i64, 12 },
{ ISD::CTPOP, MVT::v4i32, 15 },
{ ISD::CTPOP, MVT::v8i16, 13 },
{ ISD::CTPOP, MVT::v16i8, 10 },
{ ISD::CTTZ, MVT::v2i64, 14 },
{ ISD::CTTZ, MVT::v4i32, 18 },
{ ISD::CTTZ, MVT::v8i16, 16 },
{ ISD::CTTZ, MVT::v16i8, 13 },
{ ISD::SADDSAT, MVT::v8i16, 1 },
{ ISD::SADDSAT, MVT::v16i8, 1 },
{ ISD::SMAX, MVT::v8i16, 1 },
{ ISD::SMIN, MVT::v8i16, 1 },
{ ISD::SSUBSAT, MVT::v8i16, 1 },
{ ISD::SSUBSAT, MVT::v16i8, 1 },
{ ISD::UADDSAT, MVT::v8i16, 1 },
{ ISD::UADDSAT, MVT::v16i8, 1 },
{ ISD::UMAX, MVT::v8i16, 2 },
{ ISD::UMAX, MVT::v16i8, 1 },
{ ISD::UMIN, MVT::v8i16, 2 },
{ ISD::UMIN, MVT::v16i8, 1 },
{ ISD::USUBSAT, MVT::v8i16, 1 },
{ ISD::USUBSAT, MVT::v16i8, 1 },
{ ISD::FMAXNUM, MVT::f64, 4 },
{ ISD::FMAXNUM, MVT::v2f64, 4 },
{ ISD::FSQRT, MVT::f64, 32 }, { ISD::FSQRT, MVT::v2f64, 32 }, };
static const CostTblEntry SSE1CostTbl[] = {
{ ISD::FMAXNUM, MVT::f32, 4 },
{ ISD::FMAXNUM, MVT::v4f32, 4 },
{ ISD::FSQRT, MVT::f32, 28 }, { ISD::FSQRT, MVT::v4f32, 56 }, };
static const CostTblEntry BMI64CostTbl[] = { { ISD::CTTZ, MVT::i64, 1 },
};
static const CostTblEntry BMI32CostTbl[] = { { ISD::CTTZ, MVT::i32, 1 },
{ ISD::CTTZ, MVT::i16, 1 },
{ ISD::CTTZ, MVT::i8, 1 },
};
static const CostTblEntry LZCNT64CostTbl[] = { { ISD::CTLZ, MVT::i64, 1 },
};
static const CostTblEntry LZCNT32CostTbl[] = { { ISD::CTLZ, MVT::i32, 1 },
{ ISD::CTLZ, MVT::i16, 1 },
{ ISD::CTLZ, MVT::i8, 1 },
};
static const CostTblEntry POPCNT64CostTbl[] = { { ISD::CTPOP, MVT::i64, 1 },
};
static const CostTblEntry POPCNT32CostTbl[] = { { ISD::CTPOP, MVT::i32, 1 },
{ ISD::CTPOP, MVT::i16, 1 },
{ ISD::CTPOP, MVT::i8, 1 },
};
static const CostTblEntry X64CostTbl[] = { { ISD::ABS, MVT::i64, 2 }, { ISD::BITREVERSE, MVT::i64, 14 },
{ ISD::BSWAP, MVT::i64, 1 },
{ ISD::CTLZ, MVT::i64, 4 }, { ISD::CTTZ, MVT::i64, 3 }, { ISD::CTPOP, MVT::i64, 10 },
{ ISD::SADDO, MVT::i64, 1 },
{ ISD::UADDO, MVT::i64, 1 },
{ ISD::UMULO, MVT::i64, 2 }, };
static const CostTblEntry X86CostTbl[] = { { ISD::ABS, MVT::i32, 2 }, { ISD::ABS, MVT::i16, 2 }, { ISD::BITREVERSE, MVT::i32, 14 },
{ ISD::BITREVERSE, MVT::i16, 14 },
{ ISD::BITREVERSE, MVT::i8, 11 },
{ ISD::BSWAP, MVT::i32, 1 },
{ ISD::BSWAP, MVT::i16, 1 }, { ISD::CTLZ, MVT::i32, 4 }, { ISD::CTLZ, MVT::i16, 4 }, { ISD::CTLZ, MVT::i8, 4 }, { ISD::CTTZ, MVT::i32, 3 }, { ISD::CTTZ, MVT::i16, 3 }, { ISD::CTTZ, MVT::i8, 3 }, { ISD::CTPOP, MVT::i32, 8 },
{ ISD::CTPOP, MVT::i16, 9 },
{ ISD::CTPOP, MVT::i8, 7 },
{ ISD::SADDO, MVT::i32, 1 },
{ ISD::SADDO, MVT::i16, 1 },
{ ISD::SADDO, MVT::i8, 1 },
{ ISD::UADDO, MVT::i32, 1 },
{ ISD::UADDO, MVT::i16, 1 },
{ ISD::UADDO, MVT::i8, 1 },
{ ISD::UMULO, MVT::i32, 2 }, { ISD::UMULO, MVT::i16, 2 },
{ ISD::UMULO, MVT::i8, 2 },
};
Type *RetTy = ICA.getReturnType();
Type *OpTy = RetTy;
Intrinsic::ID IID = ICA.getID();
unsigned ISD = ISD::DELETED_NODE;
switch (IID) {
default:
break;
case Intrinsic::abs:
ISD = ISD::ABS;
break;
case Intrinsic::bitreverse:
ISD = ISD::BITREVERSE;
break;
case Intrinsic::bswap:
ISD = ISD::BSWAP;
break;
case Intrinsic::ctlz:
ISD = ISD::CTLZ;
break;
case Intrinsic::ctpop:
ISD = ISD::CTPOP;
break;
case Intrinsic::cttz:
ISD = ISD::CTTZ;
break;
case Intrinsic::maxnum:
case Intrinsic::minnum:
ISD = ISD::FMAXNUM;
break;
case Intrinsic::sadd_sat:
ISD = ISD::SADDSAT;
break;
case Intrinsic::smax:
ISD = ISD::SMAX;
break;
case Intrinsic::smin:
ISD = ISD::SMIN;
break;
case Intrinsic::ssub_sat:
ISD = ISD::SSUBSAT;
break;
case Intrinsic::uadd_sat:
ISD = ISD::UADDSAT;
break;
case Intrinsic::umax:
ISD = ISD::UMAX;
break;
case Intrinsic::umin:
ISD = ISD::UMIN;
break;
case Intrinsic::usub_sat:
ISD = ISD::USUBSAT;
break;
case Intrinsic::sqrt:
ISD = ISD::FSQRT;
break;
case Intrinsic::sadd_with_overflow:
case Intrinsic::ssub_with_overflow:
ISD = ISD::SADDO;
OpTy = RetTy->getContainedType(0);
break;
case Intrinsic::uadd_with_overflow:
case Intrinsic::usub_with_overflow:
ISD = ISD::UADDO;
OpTy = RetTy->getContainedType(0);
break;
case Intrinsic::umul_with_overflow:
case Intrinsic::smul_with_overflow:
ISD = ISD::UMULO;
OpTy = RetTy->getContainedType(0);
break;
}
if (ISD != ISD::DELETED_NODE) {
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, OpTy);
MVT MTy = LT.second;
if (ISD == ISD::BITREVERSE && ST->hasGFNI() && ST->hasSSSE3() &&
MTy.isVector()) {
unsigned Cost = MTy.getVectorElementType() == MVT::i8 ? 1 : 2;
if (!(MTy.is128BitVector() || (ST->hasAVX2() && MTy.is256BitVector()) ||
(ST->hasBWI() && MTy.is512BitVector())))
Cost = Cost * 2 + 2;
return LT.first * Cost;
}
auto adjustTableCost = [](const CostTblEntry &Entry,
InstructionCost LegalizationCost,
FastMathFlags FMF) {
if (Entry.ISD == ISD::FMAXNUM || Entry.ISD == ISD::FMINNUM) {
if (FMF.noNaNs())
return LegalizationCost * 1;
}
return LegalizationCost * (int)Entry.Cost;
};
if (ST->useGLMDivSqrtCosts())
if (const auto *Entry = CostTableLookup(GLMCostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->useSLMArithCosts())
if (const auto *Entry = CostTableLookup(SLMCostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasBITALG())
if (const auto *Entry = CostTableLookup(AVX512BITALGCostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasVPOPCNTDQ())
if (const auto *Entry = CostTableLookup(AVX512VPOPCNTDQCostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasCDI())
if (const auto *Entry = CostTableLookup(AVX512CDCostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasBWI())
if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasAVX512())
if (const auto *Entry = CostTableLookup(AVX512CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasXOP())
if (const auto *Entry = CostTableLookup(XOPCostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasAVX2())
if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasAVX())
if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasSSE42())
if (const auto *Entry = CostTableLookup(SSE42CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasSSE41())
if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasSSSE3())
if (const auto *Entry = CostTableLookup(SSSE3CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasSSE1())
if (const auto *Entry = CostTableLookup(SSE1CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (ST->hasBMI()) {
if (ST->is64Bit())
if (const auto *Entry = CostTableLookup(BMI64CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (const auto *Entry = CostTableLookup(BMI32CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
}
if (ST->hasLZCNT()) {
if (ST->is64Bit())
if (const auto *Entry = CostTableLookup(LZCNT64CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (const auto *Entry = CostTableLookup(LZCNT32CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
}
if (ST->hasPOPCNT()) {
if (ST->is64Bit())
if (const auto *Entry = CostTableLookup(POPCNT64CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (const auto *Entry = CostTableLookup(POPCNT32CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
}
if (ISD == ISD::BSWAP && ST->hasMOVBE() && ST->hasFastMOVBE()) {
if (const Instruction *II = ICA.getInst()) {
if (II->hasOneUse() && isa<StoreInst>(II->user_back()))
return TTI::TCC_Free;
if (auto *LI = dyn_cast<LoadInst>(II->getOperand(0))) {
if (LI->hasOneUse())
return TTI::TCC_Free;
}
}
}
if (ST->is64Bit())
if (const auto *Entry = CostTableLookup(X64CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
if (const auto *Entry = CostTableLookup(X86CostTbl, ISD, MTy))
return adjustTableCost(*Entry, LT.first, ICA.getFlags());
}
return BaseT::getIntrinsicInstrCost(ICA, CostKind);
}
InstructionCost
X86TTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,
TTI::TargetCostKind CostKind) {
if (ICA.isTypeBasedOnly())
return getTypeBasedIntrinsicInstrCost(ICA, CostKind);
static const CostTblEntry AVX512BWCostTbl[] = {
{ ISD::ROTL, MVT::v32i16, 2 },
{ ISD::ROTL, MVT::v16i16, 2 },
{ ISD::ROTL, MVT::v8i16, 2 },
{ ISD::ROTL, MVT::v64i8, 5 },
{ ISD::ROTL, MVT::v32i8, 5 },
{ ISD::ROTL, MVT::v16i8, 5 },
{ ISD::ROTR, MVT::v32i16, 2 },
{ ISD::ROTR, MVT::v16i16, 2 },
{ ISD::ROTR, MVT::v8i16, 2 },
{ ISD::ROTR, MVT::v64i8, 5 },
{ ISD::ROTR, MVT::v32i8, 5 },
{ ISD::ROTR, MVT::v16i8, 5 }
};
static const CostTblEntry AVX512CostTbl[] = {
{ ISD::ROTL, MVT::v8i64, 1 },
{ ISD::ROTL, MVT::v4i64, 1 },
{ ISD::ROTL, MVT::v2i64, 1 },
{ ISD::ROTL, MVT::v16i32, 1 },
{ ISD::ROTL, MVT::v8i32, 1 },
{ ISD::ROTL, MVT::v4i32, 1 },
{ ISD::ROTR, MVT::v8i64, 1 },
{ ISD::ROTR, MVT::v4i64, 1 },
{ ISD::ROTR, MVT::v2i64, 1 },
{ ISD::ROTR, MVT::v16i32, 1 },
{ ISD::ROTR, MVT::v8i32, 1 },
{ ISD::ROTR, MVT::v4i32, 1 }
};
static const CostTblEntry XOPCostTbl[] = {
{ ISD::ROTL, MVT::v4i64, 4 },
{ ISD::ROTL, MVT::v8i32, 4 },
{ ISD::ROTL, MVT::v16i16, 4 },
{ ISD::ROTL, MVT::v32i8, 4 },
{ ISD::ROTL, MVT::v2i64, 1 },
{ ISD::ROTL, MVT::v4i32, 1 },
{ ISD::ROTL, MVT::v8i16, 1 },
{ ISD::ROTL, MVT::v16i8, 1 },
{ ISD::ROTR, MVT::v4i64, 6 },
{ ISD::ROTR, MVT::v8i32, 6 },
{ ISD::ROTR, MVT::v16i16, 6 },
{ ISD::ROTR, MVT::v32i8, 6 },
{ ISD::ROTR, MVT::v2i64, 2 },
{ ISD::ROTR, MVT::v4i32, 2 },
{ ISD::ROTR, MVT::v8i16, 2 },
{ ISD::ROTR, MVT::v16i8, 2 }
};
static const CostTblEntry X64CostTbl[] = { { ISD::ROTL, MVT::i64, 1 },
{ ISD::ROTR, MVT::i64, 1 },
{ ISD::FSHL, MVT::i64, 4 }
};
static const CostTblEntry X86CostTbl[] = { { ISD::ROTL, MVT::i32, 1 },
{ ISD::ROTL, MVT::i16, 1 },
{ ISD::ROTL, MVT::i8, 1 },
{ ISD::ROTR, MVT::i32, 1 },
{ ISD::ROTR, MVT::i16, 1 },
{ ISD::ROTR, MVT::i8, 1 },
{ ISD::FSHL, MVT::i32, 4 },
{ ISD::FSHL, MVT::i16, 4 },
{ ISD::FSHL, MVT::i8, 4 }
};
Intrinsic::ID IID = ICA.getID();
Type *RetTy = ICA.getReturnType();
const SmallVectorImpl<const Value *> &Args = ICA.getArgs();
unsigned ISD = ISD::DELETED_NODE;
switch (IID) {
default:
break;
case Intrinsic::fshl:
ISD = ISD::FSHL;
if (Args[0] == Args[1])
ISD = ISD::ROTL;
break;
case Intrinsic::fshr:
ISD = ISD::FSHL;
if (Args[0] == Args[1])
ISD = ISD::ROTR;
break;
}
if (ISD != ISD::DELETED_NODE) {
std::pair<InstructionCost, MVT> LT =
TLI->getTypeLegalizationCost(DL, RetTy);
MVT MTy = LT.second;
if (ST->hasBWI())
if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasAVX512())
if (const auto *Entry = CostTableLookup(AVX512CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasXOP())
if (const auto *Entry = CostTableLookup(XOPCostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->is64Bit())
if (const auto *Entry = CostTableLookup(X64CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (const auto *Entry = CostTableLookup(X86CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
}
return BaseT::getIntrinsicInstrCost(ICA, CostKind);
}
InstructionCost X86TTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val,
unsigned Index) {
static const CostTblEntry SLMCostTbl[] = {
{ ISD::EXTRACT_VECTOR_ELT, MVT::i8, 4 },
{ ISD::EXTRACT_VECTOR_ELT, MVT::i16, 4 },
{ ISD::EXTRACT_VECTOR_ELT, MVT::i32, 4 },
{ ISD::EXTRACT_VECTOR_ELT, MVT::i64, 7 }
};
assert(Val->isVectorTy() && "This must be a vector type");
Type *ScalarType = Val->getScalarType();
InstructionCost RegisterFileMoveCost = 0;
if (Index == -1U && (Opcode == Instruction::ExtractElement ||
Opcode == Instruction::InsertElement)) {
assert(isa<FixedVectorType>(Val) && "Fixed vector type expected");
Align VecAlign = DL.getPrefTypeAlign(Val);
Align SclAlign = DL.getPrefTypeAlign(ScalarType);
if (Opcode == Instruction::ExtractElement) {
return getMemoryOpCost(Instruction::Store, Val, VecAlign, 0,
TTI::TargetCostKind::TCK_RecipThroughput) +
getMemoryOpCost(Instruction::Load, ScalarType, SclAlign, 0,
TTI::TargetCostKind::TCK_RecipThroughput);
}
if (Opcode == Instruction::InsertElement) {
return getMemoryOpCost(Instruction::Store, Val, VecAlign, 0,
TTI::TargetCostKind::TCK_RecipThroughput) +
getMemoryOpCost(Instruction::Store, ScalarType, SclAlign, 0,
TTI::TargetCostKind::TCK_RecipThroughput) +
getMemoryOpCost(Instruction::Load, Val, VecAlign, 0,
TTI::TargetCostKind::TCK_RecipThroughput);
}
}
if (Index != -1U && (Opcode == Instruction::ExtractElement ||
Opcode == Instruction::InsertElement)) {
if (Opcode == Instruction::ExtractElement &&
ScalarType->getScalarSizeInBits() == 1 &&
cast<FixedVectorType>(Val)->getNumElements() > 1)
return 1;
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Val);
if (!LT.second.isVector())
return 0;
unsigned SizeInBits = LT.second.getSizeInBits();
unsigned NumElts = LT.second.getVectorNumElements();
unsigned SubNumElts = NumElts;
Index = Index % NumElts;
if (SizeInBits > 128) {
assert((SizeInBits % 128) == 0 && "Illegal vector");
unsigned NumSubVecs = SizeInBits / 128;
SubNumElts = NumElts / NumSubVecs;
if (SubNumElts <= Index) {
RegisterFileMoveCost += (Opcode == Instruction::InsertElement ? 2 : 1);
Index %= SubNumElts;
}
}
if (Index == 0) {
if (ScalarType->isFloatingPointTy())
return RegisterFileMoveCost;
if (ScalarType->isIntegerTy() && Opcode == Instruction::ExtractElement)
return 1 + RegisterFileMoveCost;
}
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Unexpected vector opcode");
MVT MScalarTy = LT.second.getScalarType();
if (ST->useSLMArithCosts())
if (auto *Entry = CostTableLookup(SLMCostTbl, ISD, MScalarTy))
return Entry->Cost + RegisterFileMoveCost;
if ((MScalarTy == MVT::i16 && ST->hasSSE2()) ||
(MScalarTy.isInteger() && ST->hasSSE41()))
return 1 + RegisterFileMoveCost;
if (MScalarTy == MVT::f32 && ST->hasSSE41() &&
Opcode == Instruction::InsertElement)
return 1 + RegisterFileMoveCost;
InstructionCost ShuffleCost = 1;
if (Opcode == Instruction::InsertElement) {
auto *SubTy = cast<VectorType>(Val);
EVT VT = TLI->getValueType(DL, Val);
if (VT.getScalarType() != MScalarTy || VT.getSizeInBits() >= 128)
SubTy = FixedVectorType::get(ScalarType, SubNumElts);
ShuffleCost =
getShuffleCost(TTI::SK_PermuteTwoSrc, SubTy, None, 0, SubTy);
}
int IntOrFpCost = ScalarType->isFloatingPointTy() ? 0 : 1;
return ShuffleCost + IntOrFpCost + RegisterFileMoveCost;
}
if (Opcode == Instruction::ExtractElement && ScalarType->isPointerTy())
RegisterFileMoveCost += 1;
return BaseT::getVectorInstrCost(Opcode, Val, Index) + RegisterFileMoveCost;
}
InstructionCost X86TTIImpl::getScalarizationOverhead(VectorType *Ty,
const APInt &DemandedElts,
bool Insert,
bool Extract) {
assert(DemandedElts.getBitWidth() ==
cast<FixedVectorType>(Ty)->getNumElements() &&
"Vector size mismatch");
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Ty);
MVT MScalarTy = LT.second.getScalarType();
unsigned SizeInBits = LT.second.getSizeInBits();
InstructionCost Cost = 0;
if (Insert) {
if ((MScalarTy == MVT::i16 && ST->hasSSE2()) ||
(MScalarTy.isInteger() && ST->hasSSE41()) ||
(MScalarTy == MVT::f32 && ST->hasSSE41())) {
if (SizeInBits <= 128) {
Cost +=
BaseT::getScalarizationOverhead(Ty, DemandedElts, Insert, false);
} else {
const int CostValue = *LT.first.getValue();
assert(CostValue >= 0 && "Negative cost!");
unsigned Num128Lanes = SizeInBits / 128 * CostValue;
unsigned NumElts = LT.second.getVectorNumElements() * CostValue;
APInt WidenedDemandedElts = DemandedElts.zext(NumElts);
unsigned Scale = NumElts / Num128Lanes;
for (unsigned I = 0; I < NumElts; I += Scale) {
APInt Mask = WidenedDemandedElts.getBitsSet(NumElts, I, I + Scale);
APInt MaskedDE = Mask & WidenedDemandedElts;
unsigned Population = MaskedDE.countPopulation();
Cost += (Population > 0 && Population != Scale &&
I % LT.second.getVectorNumElements() != 0);
Cost += Population > 0;
}
Cost += DemandedElts.countPopulation();
if (MScalarTy == MVT::f32)
for (unsigned i = 0, e = cast<FixedVectorType>(Ty)->getNumElements();
i < e; i += 4)
if (DemandedElts[i])
Cost--;
}
} else if (LT.second.isVector()) {
if (Ty->isIntOrIntVectorTy())
Cost += DemandedElts.countPopulation();
unsigned NumElts = LT.second.getVectorNumElements();
unsigned Pow2Elts =
PowerOf2Ceil(cast<FixedVectorType>(Ty)->getNumElements());
Cost += (std::min<unsigned>(NumElts, Pow2Elts) - 1) * LT.first;
}
}
if (Extract) {
if (!Insert && Ty->getScalarSizeInBits() == 1 && !ST->hasAVX512()) {
unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
unsigned MaxElts = ST->hasAVX2() ? 32 : 16;
unsigned MOVMSKCost = (NumElts + MaxElts - 1) / MaxElts;
return MOVMSKCost;
}
if (LT.second.isVector()) {
int CostValue = *LT.first.getValue();
assert(CostValue >= 0 && "Negative cost!");
unsigned NumElts = LT.second.getVectorNumElements() * CostValue;
assert(NumElts >= DemandedElts.getBitWidth() &&
"Vector has been legalized to smaller element count");
if (SizeInBits > 128) {
assert((SizeInBits % 128) == 0 && "Illegal vector");
unsigned NumLegal128Lanes = SizeInBits / 128;
unsigned Num128Lanes = NumLegal128Lanes * CostValue;
APInt WidenedDemandedElts = DemandedElts.zext(NumElts);
unsigned Scale = NumElts / Num128Lanes;
APInt DemandedUpper128Lanes =
APIntOps::ScaleBitMask(WidenedDemandedElts, Num128Lanes);
auto *Ty128 = FixedVectorType::get(Ty->getElementType(), Scale);
for (unsigned I = 0; I != Num128Lanes; ++I)
if (DemandedUpper128Lanes[I])
Cost += getShuffleCost(TTI::SK_ExtractSubvector, Ty, None,
I * Scale, Ty128);
for (unsigned I = 0; I != NumElts; ++I)
if (WidenedDemandedElts[I]) {
unsigned Idx = I % Scale;
Cost += getVectorInstrCost(Instruction::ExtractElement, Ty, Idx);
}
return Cost;
}
}
Cost += BaseT::getScalarizationOverhead(Ty, DemandedElts, false, Extract);
}
return Cost;
}
InstructionCost
X86TTIImpl::getReplicationShuffleCost(Type *EltTy, int ReplicationFactor,
int VF, const APInt &DemandedDstElts,
TTI::TargetCostKind CostKind) {
const unsigned EltTyBits = DL.getTypeSizeInBits(EltTy);
EltTy = IntegerType::getIntNTy(EltTy->getContext(), EltTyBits);
auto bailout = [&]() {
return BaseT::getReplicationShuffleCost(EltTy, ReplicationFactor, VF,
DemandedDstElts, CostKind);
};
if (!ST->hasAVX512())
return bailout();
unsigned PromEltTyBits = EltTyBits;
switch (EltTyBits) {
case 32:
case 64:
break; case 16:
if (!ST->hasBWI())
PromEltTyBits = 32; break; case 8:
if (!ST->hasVBMI())
PromEltTyBits = 32; break; case 1:
if (ST->hasBWI()) {
if (ST->hasVBMI())
PromEltTyBits = 8; else
PromEltTyBits = 16; break;
}
if (ST->hasDQI()) {
PromEltTyBits = 32; break;
}
return bailout();
default:
return bailout();
}
auto *PromEltTy = IntegerType::getIntNTy(EltTy->getContext(), PromEltTyBits);
auto *SrcVecTy = FixedVectorType::get(EltTy, VF);
auto *PromSrcVecTy = FixedVectorType::get(PromEltTy, VF);
int NumDstElements = VF * ReplicationFactor;
auto *PromDstVecTy = FixedVectorType::get(PromEltTy, NumDstElements);
auto *DstVecTy = FixedVectorType::get(EltTy, NumDstElements);
MVT LegalSrcVecTy = TLI->getTypeLegalizationCost(DL, SrcVecTy).second;
MVT LegalPromSrcVecTy = TLI->getTypeLegalizationCost(DL, PromSrcVecTy).second;
MVT LegalPromDstVecTy = TLI->getTypeLegalizationCost(DL, PromDstVecTy).second;
MVT LegalDstVecTy = TLI->getTypeLegalizationCost(DL, DstVecTy).second;
if (!LegalSrcVecTy.isVector() || !LegalPromSrcVecTy.isVector() ||
!LegalPromDstVecTy.isVector() || !LegalDstVecTy.isVector())
return bailout();
if (PromEltTyBits != EltTyBits) {
InstructionCost PromotionCost;
PromotionCost += getCastInstrCost(
Instruction::SExt, PromSrcVecTy, SrcVecTy,
TargetTransformInfo::CastContextHint::None, CostKind);
PromotionCost +=
getCastInstrCost(Instruction::Trunc, DstVecTy,
PromDstVecTy,
TargetTransformInfo::CastContextHint::None, CostKind);
return PromotionCost + getReplicationShuffleCost(PromEltTy,
ReplicationFactor, VF,
DemandedDstElts, CostKind);
}
assert(LegalSrcVecTy.getScalarSizeInBits() == EltTyBits &&
LegalSrcVecTy.getScalarType() == LegalDstVecTy.getScalarType() &&
"We expect that the legalization doesn't affect the element width, "
"doesn't coalesce/split elements.");
unsigned NumEltsPerDstVec = LegalDstVecTy.getVectorNumElements();
unsigned NumDstVectors =
divideCeil(DstVecTy->getNumElements(), NumEltsPerDstVec);
auto *SingleDstVecTy = FixedVectorType::get(EltTy, NumEltsPerDstVec);
APInt DemandedDstVectors = APIntOps::ScaleBitMask(
DemandedDstElts.zext(NumDstVectors * NumEltsPerDstVec), NumDstVectors);
unsigned NumDstVectorsDemanded = DemandedDstVectors.countPopulation();
InstructionCost SingleShuffleCost =
getShuffleCost(TTI::SK_PermuteSingleSrc, SingleDstVecTy,
None, 0, nullptr);
return NumDstVectorsDemanded * SingleShuffleCost;
}
InstructionCost X86TTIImpl::getMemoryOpCost(unsigned Opcode, Type *Src,
MaybeAlign Alignment,
unsigned AddressSpace,
TTI::TargetCostKind CostKind,
const Instruction *I) {
if (CostKind != TTI::TCK_RecipThroughput) {
if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {
if (auto *GEP = dyn_cast<GetElementPtrInst>(SI->getPointerOperand())) {
if (!all_of(GEP->indices(), [](Value *V) { return isa<Constant>(V); }))
return TTI::TCC_Basic * 2;
}
}
return TTI::TCC_Basic;
}
assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
"Invalid Opcode");
if (TLI->getValueType(DL, Src, true) == MVT::Other)
return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
CostKind);
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Src);
auto *VTy = dyn_cast<FixedVectorType>(Src);
if (!VTy || !LT.second.isVector())
return LT.first * 1;
bool IsLoad = Opcode == Instruction::Load;
Type *EltTy = VTy->getElementType();
const int EltTyBits = DL.getTypeSizeInBits(EltTy);
InstructionCost Cost = 0;
const unsigned SrcNumElt = VTy->getNumElements();
int NumEltRemaining = SrcNumElt;
auto NumEltDone = [&]() { return SrcNumElt - NumEltRemaining; };
const int MaxLegalOpSizeBytes = divideCeil(LT.second.getSizeInBits(), 8);
const unsigned XMMBits = 128;
if (XMMBits % EltTyBits != 0)
return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
CostKind);
const int NumEltPerXMM = XMMBits / EltTyBits;
auto *XMMVecTy = FixedVectorType::get(EltTy, NumEltPerXMM);
for (int CurrOpSizeBytes = MaxLegalOpSizeBytes, SubVecEltsLeft = 0;
NumEltRemaining > 0; CurrOpSizeBytes /= 2) {
if ((8 * CurrOpSizeBytes) % EltTyBits != 0)
return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
CostKind);
int CurrNumEltPerOp = (8 * CurrOpSizeBytes) / EltTyBits;
assert(CurrOpSizeBytes > 0 && CurrNumEltPerOp > 0 && "How'd we get here?");
assert((((NumEltRemaining * EltTyBits) < (2 * 8 * CurrOpSizeBytes)) ||
(CurrOpSizeBytes == MaxLegalOpSizeBytes)) &&
"Unless we haven't halved the op size yet, "
"we have less than two op's sized units of work left.");
auto *CurrVecTy = CurrNumEltPerOp > NumEltPerXMM
? FixedVectorType::get(EltTy, CurrNumEltPerOp)
: XMMVecTy;
assert(CurrVecTy->getNumElements() % CurrNumEltPerOp == 0 &&
"After halving sizes, the vector elt count is no longer a multiple "
"of number of elements per operation?");
auto *CoalescedVecTy =
CurrNumEltPerOp == 1
? CurrVecTy
: FixedVectorType::get(
IntegerType::get(Src->getContext(),
EltTyBits * CurrNumEltPerOp),
CurrVecTy->getNumElements() / CurrNumEltPerOp);
assert(DL.getTypeSizeInBits(CoalescedVecTy) ==
DL.getTypeSizeInBits(CurrVecTy) &&
"coalesciing elements doesn't change vector width.");
while (NumEltRemaining > 0) {
assert(SubVecEltsLeft >= 0 && "Subreg element count overconsumtion?");
if (NumEltRemaining < CurrNumEltPerOp &&
(!IsLoad || Alignment.valueOrOne() < CurrOpSizeBytes) &&
CurrOpSizeBytes != 1)
break;
bool Is0thSubVec = (NumEltDone() % LT.second.getVectorNumElements()) == 0;
if (SubVecEltsLeft == 0) {
SubVecEltsLeft += CurrVecTy->getNumElements();
if (!Is0thSubVec)
Cost += getShuffleCost(IsLoad ? TTI::ShuffleKind::SK_InsertSubvector
: TTI::ShuffleKind::SK_ExtractSubvector,
VTy, None, NumEltDone(), CurrVecTy);
}
if (CurrOpSizeBytes <= 32 / 8 && !Is0thSubVec) {
int NumEltDoneInCurrXMM = NumEltDone() % NumEltPerXMM;
assert(NumEltDoneInCurrXMM % CurrNumEltPerOp == 0 && "");
int CoalescedVecEltIdx = NumEltDoneInCurrXMM / CurrNumEltPerOp;
APInt DemandedElts =
APInt::getBitsSet(CoalescedVecTy->getNumElements(),
CoalescedVecEltIdx, CoalescedVecEltIdx + 1);
assert(DemandedElts.countPopulation() == 1 && "Inserting single value");
Cost += getScalarizationOverhead(CoalescedVecTy, DemandedElts, IsLoad,
!IsLoad);
}
if (CurrOpSizeBytes == 32 && ST->isUnalignedMem32Slow())
Cost += 2;
else
Cost += 1;
SubVecEltsLeft -= CurrNumEltPerOp;
NumEltRemaining -= CurrNumEltPerOp;
Alignment = commonAlignment(Alignment.valueOrOne(), CurrOpSizeBytes);
}
}
assert(NumEltRemaining <= 0 && "Should have processed all the elements.");
return Cost;
}
InstructionCost
X86TTIImpl::getMaskedMemoryOpCost(unsigned Opcode, Type *SrcTy, Align Alignment,
unsigned AddressSpace,
TTI::TargetCostKind CostKind) {
bool IsLoad = (Instruction::Load == Opcode);
bool IsStore = (Instruction::Store == Opcode);
auto *SrcVTy = dyn_cast<FixedVectorType>(SrcTy);
if (!SrcVTy)
return getMemoryOpCost(Opcode, SrcTy, Alignment, AddressSpace, CostKind);
unsigned NumElem = SrcVTy->getNumElements();
auto *MaskTy =
FixedVectorType::get(Type::getInt8Ty(SrcVTy->getContext()), NumElem);
if ((IsLoad && !isLegalMaskedLoad(SrcVTy, Alignment)) ||
(IsStore && !isLegalMaskedStore(SrcVTy, Alignment))) {
APInt DemandedElts = APInt::getAllOnes(NumElem);
InstructionCost MaskSplitCost =
getScalarizationOverhead(MaskTy, DemandedElts, false, true);
InstructionCost ScalarCompareCost = getCmpSelInstrCost(
Instruction::ICmp, Type::getInt8Ty(SrcVTy->getContext()), nullptr,
CmpInst::BAD_ICMP_PREDICATE, CostKind);
InstructionCost BranchCost = getCFInstrCost(Instruction::Br, CostKind);
InstructionCost MaskCmpCost = NumElem * (BranchCost + ScalarCompareCost);
InstructionCost ValueSplitCost =
getScalarizationOverhead(SrcVTy, DemandedElts, IsLoad, IsStore);
InstructionCost MemopCost =
NumElem * BaseT::getMemoryOpCost(Opcode, SrcVTy->getScalarType(),
Alignment, AddressSpace, CostKind);
return MemopCost + ValueSplitCost + MaskSplitCost + MaskCmpCost;
}
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, SrcVTy);
auto VT = TLI->getValueType(DL, SrcVTy);
InstructionCost Cost = 0;
if (VT.isSimple() && LT.second != VT.getSimpleVT() &&
LT.second.getVectorNumElements() == NumElem)
Cost += getShuffleCost(TTI::SK_PermuteTwoSrc, SrcVTy, None, 0, nullptr) +
getShuffleCost(TTI::SK_PermuteTwoSrc, MaskTy, None, 0, nullptr);
else if (LT.first * LT.second.getVectorNumElements() > NumElem) {
auto *NewMaskTy = FixedVectorType::get(MaskTy->getElementType(),
LT.second.getVectorNumElements());
Cost += getShuffleCost(TTI::SK_InsertSubvector, NewMaskTy, None, 0, MaskTy);
}
if (!ST->hasAVX512())
return Cost + LT.first * (IsLoad ? 2 : 8);
return Cost + LT.first;
}
InstructionCost X86TTIImpl::getAddressComputationCost(Type *Ty,
ScalarEvolution *SE,
const SCEV *Ptr) {
const unsigned NumVectorInstToHideOverhead = 10;
if (Ty->isVectorTy() && SE && !ST->hasAVX2()) {
if (!BaseT::isStridedAccess(Ptr))
return NumVectorInstToHideOverhead;
if (!BaseT::getConstantStrideStep(SE, Ptr))
return 1;
}
return BaseT::getAddressComputationCost(Ty, SE, Ptr);
}
InstructionCost
X86TTIImpl::getArithmeticReductionCost(unsigned Opcode, VectorType *ValTy,
Optional<FastMathFlags> FMF,
TTI::TargetCostKind CostKind) {
if (TTI::requiresOrderedReduction(FMF))
return BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);
static const CostTblEntry SLMCostTblNoPairWise[] = {
{ ISD::FADD, MVT::v2f64, 3 },
{ ISD::ADD, MVT::v2i64, 5 },
};
static const CostTblEntry SSE2CostTblNoPairWise[] = {
{ ISD::FADD, MVT::v2f64, 2 },
{ ISD::FADD, MVT::v2f32, 2 },
{ ISD::FADD, MVT::v4f32, 4 },
{ ISD::ADD, MVT::v2i64, 2 }, { ISD::ADD, MVT::v2i32, 2 }, { ISD::ADD, MVT::v4i32, 3 }, { ISD::ADD, MVT::v2i16, 2 }, { ISD::ADD, MVT::v4i16, 3 }, { ISD::ADD, MVT::v8i16, 4 }, { ISD::ADD, MVT::v2i8, 2 },
{ ISD::ADD, MVT::v4i8, 2 },
{ ISD::ADD, MVT::v8i8, 2 },
{ ISD::ADD, MVT::v16i8, 3 },
};
static const CostTblEntry AVX1CostTblNoPairWise[] = {
{ ISD::FADD, MVT::v4f64, 3 },
{ ISD::FADD, MVT::v4f32, 3 },
{ ISD::FADD, MVT::v8f32, 4 },
{ ISD::ADD, MVT::v2i64, 1 }, { ISD::ADD, MVT::v4i64, 3 },
{ ISD::ADD, MVT::v8i32, 5 },
{ ISD::ADD, MVT::v16i16, 5 },
{ ISD::ADD, MVT::v32i8, 4 },
};
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
EVT VT = TLI->getValueType(DL, ValTy);
if (VT.isSimple()) {
MVT MTy = VT.getSimpleVT();
if (ST->useSLMArithCosts())
if (const auto *Entry = CostTableLookup(SLMCostTblNoPairWise, ISD, MTy))
return Entry->Cost;
if (ST->hasAVX())
if (const auto *Entry = CostTableLookup(AVX1CostTblNoPairWise, ISD, MTy))
return Entry->Cost;
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2CostTblNoPairWise, ISD, MTy))
return Entry->Cost;
}
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, ValTy);
MVT MTy = LT.second;
auto *ValVTy = cast<FixedVectorType>(ValTy);
if (ISD == ISD::MUL && MTy.getScalarType() == MVT::i8) {
auto *WideSclTy = IntegerType::get(ValVTy->getContext(), 16);
auto *WideVecTy = FixedVectorType::get(WideSclTy, ValVTy->getNumElements());
return getCastInstrCost(Instruction::ZExt, WideVecTy, ValTy,
TargetTransformInfo::CastContextHint::None,
CostKind) +
getArithmeticReductionCost(Opcode, WideVecTy, FMF, CostKind);
}
InstructionCost ArithmeticCost = 0;
if (LT.first != 1 && MTy.isVector() &&
MTy.getVectorNumElements() < ValVTy->getNumElements()) {
auto *SingleOpTy = FixedVectorType::get(ValVTy->getElementType(),
MTy.getVectorNumElements());
ArithmeticCost = getArithmeticInstrCost(Opcode, SingleOpTy, CostKind);
ArithmeticCost *= LT.first - 1;
}
if (ST->useSLMArithCosts())
if (const auto *Entry = CostTableLookup(SLMCostTblNoPairWise, ISD, MTy))
return ArithmeticCost + Entry->Cost;
if (ST->hasAVX())
if (const auto *Entry = CostTableLookup(AVX1CostTblNoPairWise, ISD, MTy))
return ArithmeticCost + Entry->Cost;
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2CostTblNoPairWise, ISD, MTy))
return ArithmeticCost + Entry->Cost;
static const CostTblEntry AVX512BoolReduction[] = {
{ ISD::AND, MVT::v2i1, 3 },
{ ISD::AND, MVT::v4i1, 5 },
{ ISD::AND, MVT::v8i1, 7 },
{ ISD::AND, MVT::v16i1, 9 },
{ ISD::AND, MVT::v32i1, 11 },
{ ISD::AND, MVT::v64i1, 13 },
{ ISD::OR, MVT::v2i1, 3 },
{ ISD::OR, MVT::v4i1, 5 },
{ ISD::OR, MVT::v8i1, 7 },
{ ISD::OR, MVT::v16i1, 9 },
{ ISD::OR, MVT::v32i1, 11 },
{ ISD::OR, MVT::v64i1, 13 },
};
static const CostTblEntry AVX2BoolReduction[] = {
{ ISD::AND, MVT::v16i16, 2 }, { ISD::AND, MVT::v32i8, 2 }, { ISD::OR, MVT::v16i16, 2 }, { ISD::OR, MVT::v32i8, 2 }, };
static const CostTblEntry AVX1BoolReduction[] = {
{ ISD::AND, MVT::v4i64, 2 }, { ISD::AND, MVT::v8i32, 2 }, { ISD::AND, MVT::v16i16, 4 }, { ISD::AND, MVT::v32i8, 4 }, { ISD::OR, MVT::v4i64, 2 }, { ISD::OR, MVT::v8i32, 2 }, { ISD::OR, MVT::v16i16, 4 }, { ISD::OR, MVT::v32i8, 4 }, };
static const CostTblEntry SSE2BoolReduction[] = {
{ ISD::AND, MVT::v2i64, 2 }, { ISD::AND, MVT::v4i32, 2 }, { ISD::AND, MVT::v8i16, 2 }, { ISD::AND, MVT::v16i8, 2 }, { ISD::OR, MVT::v2i64, 2 }, { ISD::OR, MVT::v4i32, 2 }, { ISD::OR, MVT::v8i16, 2 }, { ISD::OR, MVT::v16i8, 2 }, };
if (ValVTy->getElementType()->isIntegerTy(1)) {
InstructionCost ArithmeticCost = 0;
if (LT.first != 1 && MTy.isVector() &&
MTy.getVectorNumElements() < ValVTy->getNumElements()) {
auto *SingleOpTy = FixedVectorType::get(ValVTy->getElementType(),
MTy.getVectorNumElements());
ArithmeticCost = getArithmeticInstrCost(Opcode, SingleOpTy, CostKind);
ArithmeticCost *= LT.first - 1;
}
if (ST->hasAVX512())
if (const auto *Entry = CostTableLookup(AVX512BoolReduction, ISD, MTy))
return ArithmeticCost + Entry->Cost;
if (ST->hasAVX2())
if (const auto *Entry = CostTableLookup(AVX2BoolReduction, ISD, MTy))
return ArithmeticCost + Entry->Cost;
if (ST->hasAVX())
if (const auto *Entry = CostTableLookup(AVX1BoolReduction, ISD, MTy))
return ArithmeticCost + Entry->Cost;
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2BoolReduction, ISD, MTy))
return ArithmeticCost + Entry->Cost;
return BaseT::getArithmeticReductionCost(Opcode, ValVTy, FMF, CostKind);
}
unsigned NumVecElts = ValVTy->getNumElements();
unsigned ScalarSize = ValVTy->getScalarSizeInBits();
if (!isPowerOf2_32(NumVecElts) || ScalarSize != MTy.getScalarSizeInBits())
return BaseT::getArithmeticReductionCost(Opcode, ValVTy, FMF, CostKind);
InstructionCost ReductionCost = 0;
auto *Ty = ValVTy;
if (LT.first != 1 && MTy.isVector() &&
MTy.getVectorNumElements() < ValVTy->getNumElements()) {
Ty = FixedVectorType::get(ValVTy->getElementType(),
MTy.getVectorNumElements());
ReductionCost = getArithmeticInstrCost(Opcode, Ty, CostKind);
ReductionCost *= LT.first - 1;
NumVecElts = MTy.getVectorNumElements();
}
while (NumVecElts > 1) {
unsigned Size = NumVecElts * ScalarSize;
NumVecElts /= 2;
if (Size > 128) {
auto *SubTy = FixedVectorType::get(ValVTy->getElementType(), NumVecElts);
ReductionCost +=
getShuffleCost(TTI::SK_ExtractSubvector, Ty, None, NumVecElts, SubTy);
Ty = SubTy;
} else if (Size == 128) {
FixedVectorType *ShufTy;
if (ValVTy->isFloatingPointTy())
ShufTy =
FixedVectorType::get(Type::getDoubleTy(ValVTy->getContext()), 2);
else
ShufTy =
FixedVectorType::get(Type::getInt64Ty(ValVTy->getContext()), 2);
ReductionCost +=
getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, None, 0, nullptr);
} else if (Size == 64) {
FixedVectorType *ShufTy;
if (ValVTy->isFloatingPointTy())
ShufTy =
FixedVectorType::get(Type::getFloatTy(ValVTy->getContext()), 4);
else
ShufTy =
FixedVectorType::get(Type::getInt32Ty(ValVTy->getContext()), 4);
ReductionCost +=
getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, None, 0, nullptr);
} else {
auto *ShiftTy = FixedVectorType::get(
Type::getIntNTy(ValVTy->getContext(), Size), 128 / Size);
ReductionCost += getArithmeticInstrCost(
Instruction::LShr, ShiftTy, CostKind,
TargetTransformInfo::OK_AnyValue,
TargetTransformInfo::OK_UniformConstantValue,
TargetTransformInfo::OP_None, TargetTransformInfo::OP_None);
}
ReductionCost += getArithmeticInstrCost(Opcode, Ty, CostKind);
}
return ReductionCost + getVectorInstrCost(Instruction::ExtractElement, Ty, 0);
}
InstructionCost X86TTIImpl::getMinMaxCost(Type *Ty, Type *CondTy,
bool IsUnsigned) {
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Ty);
MVT MTy = LT.second;
int ISD;
if (Ty->isIntOrIntVectorTy()) {
ISD = IsUnsigned ? ISD::UMIN : ISD::SMIN;
} else {
assert(Ty->isFPOrFPVectorTy() &&
"Expected float point or integer vector type.");
ISD = ISD::FMINNUM;
}
static const CostTblEntry SSE1CostTbl[] = {
{ISD::FMINNUM, MVT::v4f32, 1},
};
static const CostTblEntry SSE2CostTbl[] = {
{ISD::FMINNUM, MVT::v2f64, 1},
{ISD::SMIN, MVT::v8i16, 1},
{ISD::UMIN, MVT::v16i8, 1},
};
static const CostTblEntry SSE41CostTbl[] = {
{ISD::SMIN, MVT::v4i32, 1},
{ISD::UMIN, MVT::v4i32, 1},
{ISD::UMIN, MVT::v8i16, 1},
{ISD::SMIN, MVT::v16i8, 1},
};
static const CostTblEntry SSE42CostTbl[] = {
{ISD::UMIN, MVT::v2i64, 3}, };
static const CostTblEntry AVX1CostTbl[] = {
{ISD::FMINNUM, MVT::v8f32, 1},
{ISD::FMINNUM, MVT::v4f64, 1},
{ISD::SMIN, MVT::v8i32, 3},
{ISD::UMIN, MVT::v8i32, 3},
{ISD::SMIN, MVT::v16i16, 3},
{ISD::UMIN, MVT::v16i16, 3},
{ISD::SMIN, MVT::v32i8, 3},
{ISD::UMIN, MVT::v32i8, 3},
};
static const CostTblEntry AVX2CostTbl[] = {
{ISD::SMIN, MVT::v8i32, 1},
{ISD::UMIN, MVT::v8i32, 1},
{ISD::SMIN, MVT::v16i16, 1},
{ISD::UMIN, MVT::v16i16, 1},
{ISD::SMIN, MVT::v32i8, 1},
{ISD::UMIN, MVT::v32i8, 1},
};
static const CostTblEntry AVX512CostTbl[] = {
{ISD::FMINNUM, MVT::v16f32, 1},
{ISD::FMINNUM, MVT::v8f64, 1},
{ISD::SMIN, MVT::v2i64, 1},
{ISD::UMIN, MVT::v2i64, 1},
{ISD::SMIN, MVT::v4i64, 1},
{ISD::UMIN, MVT::v4i64, 1},
{ISD::SMIN, MVT::v8i64, 1},
{ISD::UMIN, MVT::v8i64, 1},
{ISD::SMIN, MVT::v16i32, 1},
{ISD::UMIN, MVT::v16i32, 1},
};
static const CostTblEntry AVX512BWCostTbl[] = {
{ISD::SMIN, MVT::v32i16, 1},
{ISD::UMIN, MVT::v32i16, 1},
{ISD::SMIN, MVT::v64i8, 1},
{ISD::UMIN, MVT::v64i8, 1},
};
if (ST->hasBWI())
if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasAVX512())
if (const auto *Entry = CostTableLookup(AVX512CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasAVX2())
if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasAVX())
if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasSSE42())
if (const auto *Entry = CostTableLookup(SSE42CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasSSE41())
if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasSSE1())
if (const auto *Entry = CostTableLookup(SSE1CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
unsigned CmpOpcode;
if (Ty->isFPOrFPVectorTy()) {
CmpOpcode = Instruction::FCmp;
} else {
assert(Ty->isIntOrIntVectorTy() &&
"expecting floating point or integer type for min/max reduction");
CmpOpcode = Instruction::ICmp;
}
TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
InstructionCost Result =
getCmpSelInstrCost(CmpOpcode, Ty, CondTy, CmpInst::BAD_ICMP_PREDICATE,
CostKind) +
getCmpSelInstrCost(Instruction::Select, Ty, CondTy,
CmpInst::BAD_ICMP_PREDICATE, CostKind);
return Result;
}
InstructionCost
X86TTIImpl::getMinMaxReductionCost(VectorType *ValTy, VectorType *CondTy,
bool IsUnsigned,
TTI::TargetCostKind CostKind) {
std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, ValTy);
MVT MTy = LT.second;
int ISD;
if (ValTy->isIntOrIntVectorTy()) {
ISD = IsUnsigned ? ISD::UMIN : ISD::SMIN;
} else {
assert(ValTy->isFPOrFPVectorTy() &&
"Expected float point or integer vector type.");
ISD = ISD::FMINNUM;
}
static const CostTblEntry SSE2CostTblNoPairWise[] = {
{ISD::UMIN, MVT::v2i16, 5}, {ISD::UMIN, MVT::v4i16, 7}, {ISD::UMIN, MVT::v8i16, 9}, };
static const CostTblEntry SSE41CostTblNoPairWise[] = {
{ISD::SMIN, MVT::v2i16, 3}, {ISD::SMIN, MVT::v4i16, 5}, {ISD::UMIN, MVT::v2i16, 5}, {ISD::UMIN, MVT::v4i16, 7}, {ISD::SMIN, MVT::v8i16, 4}, {ISD::UMIN, MVT::v8i16, 4}, {ISD::SMIN, MVT::v2i8, 3}, {ISD::SMIN, MVT::v4i8, 5}, {ISD::SMIN, MVT::v8i8, 7}, {ISD::SMIN, MVT::v16i8, 6},
{ISD::UMIN, MVT::v2i8, 3}, {ISD::UMIN, MVT::v4i8, 5}, {ISD::UMIN, MVT::v8i8, 7}, {ISD::UMIN, MVT::v16i8, 6}, };
static const CostTblEntry AVX1CostTblNoPairWise[] = {
{ISD::SMIN, MVT::v16i16, 6},
{ISD::UMIN, MVT::v16i16, 6}, {ISD::SMIN, MVT::v32i8, 8},
{ISD::UMIN, MVT::v32i8, 8},
};
static const CostTblEntry AVX512BWCostTblNoPairWise[] = {
{ISD::SMIN, MVT::v32i16, 8},
{ISD::UMIN, MVT::v32i16, 8}, {ISD::SMIN, MVT::v64i8, 10},
{ISD::UMIN, MVT::v64i8, 10},
};
EVT VT = TLI->getValueType(DL, ValTy);
if (VT.isSimple()) {
MVT MTy = VT.getSimpleVT();
if (ST->hasBWI())
if (const auto *Entry = CostTableLookup(AVX512BWCostTblNoPairWise, ISD, MTy))
return Entry->Cost;
if (ST->hasAVX())
if (const auto *Entry = CostTableLookup(AVX1CostTblNoPairWise, ISD, MTy))
return Entry->Cost;
if (ST->hasSSE41())
if (const auto *Entry = CostTableLookup(SSE41CostTblNoPairWise, ISD, MTy))
return Entry->Cost;
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2CostTblNoPairWise, ISD, MTy))
return Entry->Cost;
}
auto *ValVTy = cast<FixedVectorType>(ValTy);
unsigned NumVecElts = ValVTy->getNumElements();
auto *Ty = ValVTy;
InstructionCost MinMaxCost = 0;
if (LT.first != 1 && MTy.isVector() &&
MTy.getVectorNumElements() < ValVTy->getNumElements()) {
Ty = FixedVectorType::get(ValVTy->getElementType(),
MTy.getVectorNumElements());
auto *SubCondTy = FixedVectorType::get(CondTy->getElementType(),
MTy.getVectorNumElements());
MinMaxCost = getMinMaxCost(Ty, SubCondTy, IsUnsigned);
MinMaxCost *= LT.first - 1;
NumVecElts = MTy.getVectorNumElements();
}
if (ST->hasBWI())
if (const auto *Entry = CostTableLookup(AVX512BWCostTblNoPairWise, ISD, MTy))
return MinMaxCost + Entry->Cost;
if (ST->hasAVX())
if (const auto *Entry = CostTableLookup(AVX1CostTblNoPairWise, ISD, MTy))
return MinMaxCost + Entry->Cost;
if (ST->hasSSE41())
if (const auto *Entry = CostTableLookup(SSE41CostTblNoPairWise, ISD, MTy))
return MinMaxCost + Entry->Cost;
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2CostTblNoPairWise, ISD, MTy))
return MinMaxCost + Entry->Cost;
unsigned ScalarSize = ValTy->getScalarSizeInBits();
if (!isPowerOf2_32(ValVTy->getNumElements()) ||
ScalarSize != MTy.getScalarSizeInBits())
return BaseT::getMinMaxReductionCost(ValTy, CondTy, IsUnsigned, CostKind);
while (NumVecElts > 1) {
unsigned Size = NumVecElts * ScalarSize;
NumVecElts /= 2;
if (Size > 128) {
auto *SubTy = FixedVectorType::get(ValVTy->getElementType(), NumVecElts);
MinMaxCost +=
getShuffleCost(TTI::SK_ExtractSubvector, Ty, None, NumVecElts, SubTy);
Ty = SubTy;
} else if (Size == 128) {
VectorType *ShufTy;
if (ValTy->isFloatingPointTy())
ShufTy =
FixedVectorType::get(Type::getDoubleTy(ValTy->getContext()), 2);
else
ShufTy = FixedVectorType::get(Type::getInt64Ty(ValTy->getContext()), 2);
MinMaxCost +=
getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, None, 0, nullptr);
} else if (Size == 64) {
FixedVectorType *ShufTy;
if (ValTy->isFloatingPointTy())
ShufTy = FixedVectorType::get(Type::getFloatTy(ValTy->getContext()), 4);
else
ShufTy = FixedVectorType::get(Type::getInt32Ty(ValTy->getContext()), 4);
MinMaxCost +=
getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, None, 0, nullptr);
} else {
auto *ShiftTy = FixedVectorType::get(
Type::getIntNTy(ValTy->getContext(), Size), 128 / Size);
MinMaxCost += getArithmeticInstrCost(
Instruction::LShr, ShiftTy, TTI::TCK_RecipThroughput,
TargetTransformInfo::OK_AnyValue,
TargetTransformInfo::OK_UniformConstantValue,
TargetTransformInfo::OP_None, TargetTransformInfo::OP_None);
}
auto *SubCondTy =
FixedVectorType::get(CondTy->getElementType(), Ty->getNumElements());
MinMaxCost += getMinMaxCost(Ty, SubCondTy, IsUnsigned);
}
return MinMaxCost + getVectorInstrCost(Instruction::ExtractElement, Ty, 0);
}
InstructionCost X86TTIImpl::getIntImmCost(int64_t Val) {
if (Val == 0)
return TTI::TCC_Free;
if (isInt<32>(Val))
return TTI::TCC_Basic;
return 2 * TTI::TCC_Basic;
}
InstructionCost X86TTIImpl::getIntImmCost(const APInt &Imm, Type *Ty,
TTI::TargetCostKind CostKind) {
assert(Ty->isIntegerTy());
unsigned BitSize = Ty->getPrimitiveSizeInBits();
if (BitSize == 0)
return ~0U;
if (BitSize > 128)
return TTI::TCC_Free;
if (Imm == 0)
return TTI::TCC_Free;
APInt ImmVal = Imm;
if (BitSize % 64 != 0)
ImmVal = Imm.sext(alignTo(BitSize, 64));
InstructionCost Cost = 0;
for (unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
APInt Tmp = ImmVal.ashr(ShiftVal).sextOrTrunc(64);
int64_t Val = Tmp.getSExtValue();
Cost += getIntImmCost(Val);
}
return std::max<InstructionCost>(1, Cost);
}
InstructionCost X86TTIImpl::getIntImmCostInst(unsigned Opcode, unsigned Idx,
const APInt &Imm, Type *Ty,
TTI::TargetCostKind CostKind,
Instruction *Inst) {
assert(Ty->isIntegerTy());
unsigned BitSize = Ty->getPrimitiveSizeInBits();
if (BitSize == 0)
return TTI::TCC_Free;
unsigned ImmIdx = ~0U;
switch (Opcode) {
default:
return TTI::TCC_Free;
case Instruction::GetElementPtr:
if (Idx == 0)
return 2 * TTI::TCC_Basic;
return TTI::TCC_Free;
case Instruction::Store:
ImmIdx = 0;
break;
case Instruction::ICmp:
if (Idx == 1 && Imm.getBitWidth() == 64) {
uint64_t ImmVal = Imm.getZExtValue();
if (ImmVal == 0x100000000ULL || ImmVal == 0xffffffff)
return TTI::TCC_Free;
}
ImmIdx = 1;
break;
case Instruction::And:
if (Idx == 1 && Imm.getBitWidth() == 64 && isUInt<32>(Imm.getZExtValue()))
return TTI::TCC_Free;
ImmIdx = 1;
break;
case Instruction::Add:
case Instruction::Sub:
if (Idx == 1 && Imm.getBitWidth() == 64 && Imm.getZExtValue() == 0x80000000)
return TTI::TCC_Free;
ImmIdx = 1;
break;
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::URem:
case Instruction::SRem:
return TTI::TCC_Free;
case Instruction::Mul:
case Instruction::Or:
case Instruction::Xor:
ImmIdx = 1;
break;
case Instruction::Shl:
case Instruction::LShr:
case Instruction::AShr:
if (Idx == 1)
return TTI::TCC_Free;
break;
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::IntToPtr:
case Instruction::PtrToInt:
case Instruction::BitCast:
case Instruction::PHI:
case Instruction::Call:
case Instruction::Select:
case Instruction::Ret:
case Instruction::Load:
break;
}
if (Idx == ImmIdx) {
int NumConstants = divideCeil(BitSize, 64);
InstructionCost Cost = X86TTIImpl::getIntImmCost(Imm, Ty, CostKind);
return (Cost <= NumConstants * TTI::TCC_Basic)
? static_cast<int>(TTI::TCC_Free)
: Cost;
}
return X86TTIImpl::getIntImmCost(Imm, Ty, CostKind);
}
InstructionCost X86TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
const APInt &Imm, Type *Ty,
TTI::TargetCostKind CostKind) {
assert(Ty->isIntegerTy());
unsigned BitSize = Ty->getPrimitiveSizeInBits();
if (BitSize == 0)
return TTI::TCC_Free;
switch (IID) {
default:
return TTI::TCC_Free;
case Intrinsic::sadd_with_overflow:
case Intrinsic::uadd_with_overflow:
case Intrinsic::ssub_with_overflow:
case Intrinsic::usub_with_overflow:
case Intrinsic::smul_with_overflow:
case Intrinsic::umul_with_overflow:
if ((Idx == 1) && Imm.getBitWidth() <= 64 && isInt<32>(Imm.getSExtValue()))
return TTI::TCC_Free;
break;
case Intrinsic::experimental_stackmap:
if ((Idx < 2) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
return TTI::TCC_Free;
break;
case Intrinsic::experimental_patchpoint_void:
case Intrinsic::experimental_patchpoint_i64:
if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
return TTI::TCC_Free;
break;
}
return X86TTIImpl::getIntImmCost(Imm, Ty, CostKind);
}
InstructionCost X86TTIImpl::getCFInstrCost(unsigned Opcode,
TTI::TargetCostKind CostKind,
const Instruction *I) {
if (CostKind != TTI::TCK_RecipThroughput)
return Opcode == Instruction::PHI ? 0 : 1;
return 0;
}
int X86TTIImpl::getGatherOverhead() const {
if (ST->hasAVX512() || (ST->hasAVX2() && ST->hasFastGather()))
return 2;
return 1024;
}
int X86TTIImpl::getScatterOverhead() const {
if (ST->hasAVX512())
return 2;
return 1024;
}
InstructionCost X86TTIImpl::getGSVectorCost(unsigned Opcode, Type *SrcVTy,
const Value *Ptr, Align Alignment,
unsigned AddressSpace) {
assert(isa<VectorType>(SrcVTy) && "Unexpected type in getGSVectorCost");
unsigned VF = cast<FixedVectorType>(SrcVTy)->getNumElements();
auto getIndexSizeInBits = [](const Value *Ptr, const DataLayout &DL) {
unsigned IndexSize = DL.getPointerSizeInBits();
const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr);
if (IndexSize < 64 || !GEP)
return IndexSize;
unsigned NumOfVarIndices = 0;
const Value *Ptrs = GEP->getPointerOperand();
if (Ptrs->getType()->isVectorTy() && !getSplatValue(Ptrs))
return IndexSize;
for (unsigned i = 1; i < GEP->getNumOperands(); ++i) {
if (isa<Constant>(GEP->getOperand(i)))
continue;
Type *IndxTy = GEP->getOperand(i)->getType();
if (auto *IndexVTy = dyn_cast<VectorType>(IndxTy))
IndxTy = IndexVTy->getElementType();
if ((IndxTy->getPrimitiveSizeInBits() == 64 &&
!isa<SExtInst>(GEP->getOperand(i))) ||
++NumOfVarIndices > 1)
return IndexSize; }
return (unsigned)32;
};
unsigned IndexSize = (ST->hasAVX512() && VF >= 16)
? getIndexSizeInBits(Ptr, DL)
: DL.getPointerSizeInBits();
auto *IndexVTy = FixedVectorType::get(
IntegerType::get(SrcVTy->getContext(), IndexSize), VF);
std::pair<InstructionCost, MVT> IdxsLT =
TLI->getTypeLegalizationCost(DL, IndexVTy);
std::pair<InstructionCost, MVT> SrcLT =
TLI->getTypeLegalizationCost(DL, SrcVTy);
InstructionCost::CostType SplitFactor =
*std::max(IdxsLT.first, SrcLT.first).getValue();
if (SplitFactor > 1) {
auto *SplitSrcTy =
FixedVectorType::get(SrcVTy->getScalarType(), VF / SplitFactor);
return SplitFactor * getGSVectorCost(Opcode, SplitSrcTy, Ptr, Alignment,
AddressSpace);
}
const int GSOverhead = (Opcode == Instruction::Load)
? getGatherOverhead()
: getScatterOverhead();
return GSOverhead + VF * getMemoryOpCost(Opcode, SrcVTy->getScalarType(),
MaybeAlign(Alignment), AddressSpace,
TTI::TCK_RecipThroughput);
}
InstructionCost X86TTIImpl::getGSScalarCost(unsigned Opcode, Type *SrcVTy,
bool VariableMask, Align Alignment,
unsigned AddressSpace) {
Type *ScalarTy = SrcVTy->getScalarType();
unsigned VF = cast<FixedVectorType>(SrcVTy)->getNumElements();
APInt DemandedElts = APInt::getAllOnes(VF);
TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
InstructionCost MaskUnpackCost = 0;
if (VariableMask) {
auto *MaskTy =
FixedVectorType::get(Type::getInt1Ty(SrcVTy->getContext()), VF);
MaskUnpackCost = getScalarizationOverhead(
MaskTy, DemandedElts, false, true);
InstructionCost ScalarCompareCost = getCmpSelInstrCost(
Instruction::ICmp, Type::getInt1Ty(SrcVTy->getContext()), nullptr,
CmpInst::BAD_ICMP_PREDICATE, CostKind);
InstructionCost BranchCost = getCFInstrCost(Instruction::Br, CostKind);
MaskUnpackCost += VF * (BranchCost + ScalarCompareCost);
}
InstructionCost AddressUnpackCost = getScalarizationOverhead(
FixedVectorType::get(ScalarTy->getPointerTo(), VF), DemandedElts,
false, true);
InstructionCost MemoryOpCost =
VF * getMemoryOpCost(Opcode, ScalarTy, MaybeAlign(Alignment),
AddressSpace, CostKind);
InstructionCost InsertExtractCost =
getScalarizationOverhead(cast<FixedVectorType>(SrcVTy), DemandedElts,
Opcode == Instruction::Load,
Opcode == Instruction::Store);
return AddressUnpackCost + MemoryOpCost + MaskUnpackCost + InsertExtractCost;
}
InstructionCost X86TTIImpl::getGatherScatterOpCost(
unsigned Opcode, Type *SrcVTy, const Value *Ptr, bool VariableMask,
Align Alignment, TTI::TargetCostKind CostKind,
const Instruction *I = nullptr) {
if (CostKind != TTI::TCK_RecipThroughput) {
if ((Opcode == Instruction::Load &&
isLegalMaskedGather(SrcVTy, Align(Alignment)) &&
!forceScalarizeMaskedGather(cast<VectorType>(SrcVTy),
Align(Alignment))) ||
(Opcode == Instruction::Store &&
isLegalMaskedScatter(SrcVTy, Align(Alignment)) &&
!forceScalarizeMaskedScatter(cast<VectorType>(SrcVTy),
Align(Alignment))))
return 1;
return BaseT::getGatherScatterOpCost(Opcode, SrcVTy, Ptr, VariableMask,
Alignment, CostKind, I);
}
assert(SrcVTy->isVectorTy() && "Unexpected data type for Gather/Scatter");
PointerType *PtrTy = dyn_cast<PointerType>(Ptr->getType());
if (!PtrTy && Ptr->getType()->isVectorTy())
PtrTy = dyn_cast<PointerType>(
cast<VectorType>(Ptr->getType())->getElementType());
assert(PtrTy && "Unexpected type for Ptr argument");
unsigned AddressSpace = PtrTy->getAddressSpace();
if ((Opcode == Instruction::Load &&
(!isLegalMaskedGather(SrcVTy, Align(Alignment)) ||
forceScalarizeMaskedGather(cast<VectorType>(SrcVTy),
Align(Alignment)))) ||
(Opcode == Instruction::Store &&
(!isLegalMaskedScatter(SrcVTy, Align(Alignment)) ||
forceScalarizeMaskedScatter(cast<VectorType>(SrcVTy),
Align(Alignment)))))
return getGSScalarCost(Opcode, SrcVTy, VariableMask, Alignment,
AddressSpace);
return getGSVectorCost(Opcode, SrcVTy, Ptr, Alignment, AddressSpace);
}
bool X86TTIImpl::isLSRCostLess(const TargetTransformInfo::LSRCost &C1,
const TargetTransformInfo::LSRCost &C2) {
return std::tie(C1.Insns, C1.NumRegs, C1.AddRecCost,
C1.NumIVMuls, C1.NumBaseAdds,
C1.ScaleCost, C1.ImmCost, C1.SetupCost) <
std::tie(C2.Insns, C2.NumRegs, C2.AddRecCost,
C2.NumIVMuls, C2.NumBaseAdds,
C2.ScaleCost, C2.ImmCost, C2.SetupCost);
}
bool X86TTIImpl::canMacroFuseCmp() {
return ST->hasMacroFusion() || ST->hasBranchFusion();
}
bool X86TTIImpl::isLegalMaskedLoad(Type *DataTy, Align Alignment) {
if (!ST->hasAVX())
return false;
if (isa<VectorType>(DataTy) &&
cast<FixedVectorType>(DataTy)->getNumElements() == 1)
return false;
Type *ScalarTy = DataTy->getScalarType();
if (ScalarTy->isPointerTy())
return true;
if (ScalarTy->isFloatTy() || ScalarTy->isDoubleTy())
return true;
if (ScalarTy->isHalfTy() && ST->hasBWI())
return true;
if (!ScalarTy->isIntegerTy())
return false;
unsigned IntWidth = ScalarTy->getIntegerBitWidth();
return IntWidth == 32 || IntWidth == 64 ||
((IntWidth == 8 || IntWidth == 16) && ST->hasBWI());
}
bool X86TTIImpl::isLegalMaskedStore(Type *DataType, Align Alignment) {
return isLegalMaskedLoad(DataType, Alignment);
}
bool X86TTIImpl::isLegalNTLoad(Type *DataType, Align Alignment) {
unsigned DataSize = DL.getTypeStoreSize(DataType);
if (Alignment >= DataSize && (DataSize == 16 || DataSize == 32))
return DataSize == 16 ? ST->hasSSE1() : ST->hasAVX2();
return false;
}
bool X86TTIImpl::isLegalNTStore(Type *DataType, Align Alignment) {
unsigned DataSize = DL.getTypeStoreSize(DataType);
if (ST->hasSSE4A() && (DataType->isFloatTy() || DataType->isDoubleTy()))
return true;
if (Alignment < DataSize || DataSize < 4 || DataSize > 32 ||
!isPowerOf2_32(DataSize))
return false;
if (DataSize == 32)
return ST->hasAVX();
if (DataSize == 16)
return ST->hasSSE1();
return true;
}
bool X86TTIImpl::isLegalBroadcastLoad(Type *ElementTy,
ElementCount NumElements) const {
return ST->hasSSE3() && !NumElements.isScalable() &&
NumElements.getFixedValue() == 2 &&
ElementTy == Type::getDoubleTy(ElementTy->getContext());
}
bool X86TTIImpl::isLegalMaskedExpandLoad(Type *DataTy) {
if (!isa<VectorType>(DataTy))
return false;
if (!ST->hasAVX512())
return false;
if (cast<FixedVectorType>(DataTy)->getNumElements() == 1)
return false;
Type *ScalarTy = cast<VectorType>(DataTy)->getElementType();
if (ScalarTy->isFloatTy() || ScalarTy->isDoubleTy())
return true;
if (!ScalarTy->isIntegerTy())
return false;
unsigned IntWidth = ScalarTy->getIntegerBitWidth();
return IntWidth == 32 || IntWidth == 64 ||
((IntWidth == 8 || IntWidth == 16) && ST->hasVBMI2());
}
bool X86TTIImpl::isLegalMaskedCompressStore(Type *DataTy) {
return isLegalMaskedExpandLoad(DataTy);
}
bool X86TTIImpl::supportsGather() const {
return ST->hasAVX512() || (ST->hasFastGather() && ST->hasAVX2());
}
bool X86TTIImpl::forceScalarizeMaskedGather(VectorType *VTy, Align Alignment) {
unsigned NumElts = cast<FixedVectorType>(VTy)->getNumElements();
return NumElts == 1 ||
(ST->hasAVX512() && (NumElts == 2 || (NumElts == 4 && !ST->hasVLX())));
}
bool X86TTIImpl::isLegalMaskedGather(Type *DataTy, Align Alignment) {
if (!supportsGather())
return false;
Type *ScalarTy = DataTy->getScalarType();
if (ScalarTy->isPointerTy())
return true;
if (ScalarTy->isFloatTy() || ScalarTy->isDoubleTy())
return true;
if (!ScalarTy->isIntegerTy())
return false;
unsigned IntWidth = ScalarTy->getIntegerBitWidth();
return IntWidth == 32 || IntWidth == 64;
}
bool X86TTIImpl::isLegalAltInstr(VectorType *VecTy, unsigned Opcode0,
unsigned Opcode1,
const SmallBitVector &OpcodeMask) const {
unsigned NumElements = cast<FixedVectorType>(VecTy)->getNumElements();
assert(OpcodeMask.size() == NumElements && "Mask and VecTy are incompatible");
if (!isPowerOf2_32(NumElements))
return false;
for (int Lane : seq<int>(0, NumElements)) {
unsigned Opc = OpcodeMask.test(Lane) ? Opcode1 : Opcode0;
if (Lane % 2 == 0 && Opc != Instruction::FSub)
return false;
if (Lane % 2 == 1 && Opc != Instruction::FAdd)
return false;
}
Type *ElemTy = cast<VectorType>(VecTy)->getElementType();
if (ElemTy->isFloatTy())
return ST->hasSSE3() && NumElements % 4 == 0;
if (ElemTy->isDoubleTy())
return ST->hasSSE3() && NumElements % 2 == 0;
return false;
}
bool X86TTIImpl::isLegalMaskedScatter(Type *DataType, Align Alignment) {
if (!ST->hasAVX512())
return false;
return isLegalMaskedGather(DataType, Alignment);
}
bool X86TTIImpl::hasDivRemOp(Type *DataType, bool IsSigned) {
EVT VT = TLI->getValueType(DL, DataType);
return TLI->isOperationLegal(IsSigned ? ISD::SDIVREM : ISD::UDIVREM, VT);
}
bool X86TTIImpl::isFCmpOrdCheaperThanFCmpZero(Type *Ty) {
return false;
}
bool X86TTIImpl::areInlineCompatible(const Function *Caller,
const Function *Callee) const {
const TargetMachine &TM = getTLI()->getTargetMachine();
const FeatureBitset &CallerBits =
TM.getSubtargetImpl(*Caller)->getFeatureBits();
const FeatureBitset &CalleeBits =
TM.getSubtargetImpl(*Callee)->getFeatureBits();
FeatureBitset RealCallerBits = CallerBits & ~InlineFeatureIgnoreList;
FeatureBitset RealCalleeBits = CalleeBits & ~InlineFeatureIgnoreList;
if (RealCallerBits == RealCalleeBits)
return true;
if ((RealCallerBits & RealCalleeBits) != RealCalleeBits)
return false;
for (const Instruction &I : instructions(Callee)) {
if (const auto *CB = dyn_cast<CallBase>(&I)) {
SmallVector<Type *, 8> Types;
for (Value *Arg : CB->args())
Types.push_back(Arg->getType());
if (!CB->getType()->isVoidTy())
Types.push_back(CB->getType());
auto IsSimpleTy = [](Type *Ty) {
return !Ty->isVectorTy() && !Ty->isAggregateType();
};
if (all_of(Types, IsSimpleTy))
continue;
if (Function *NestedCallee = CB->getCalledFunction()) {
if (NestedCallee->isIntrinsic())
continue;
if (!areTypesABICompatible(Caller, NestedCallee, Types))
return false;
} else {
return false;
}
}
}
return true;
}
bool X86TTIImpl::areTypesABICompatible(const Function *Caller,
const Function *Callee,
const ArrayRef<Type *> &Types) const {
if (!BaseT::areTypesABICompatible(Caller, Callee, Types))
return false;
const TargetMachine &TM = getTLI()->getTargetMachine();
if (TM.getSubtarget<X86Subtarget>(*Caller).useAVX512Regs() ==
TM.getSubtarget<X86Subtarget>(*Callee).useAVX512Regs())
return true;
return llvm::none_of(Types,
[](Type *T) { return T->isVectorTy() || T->isAggregateType(); });
}
X86TTIImpl::TTI::MemCmpExpansionOptions
X86TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
TTI::MemCmpExpansionOptions Options;
Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
Options.NumLoadsPerBlock = 2;
Options.AllowOverlappingLoads = true;
if (IsZeroCmp) {
const unsigned PreferredWidth = ST->getPreferVectorWidth();
if (PreferredWidth >= 512 && ST->hasAVX512()) Options.LoadSizes.push_back(64);
if (PreferredWidth >= 256 && ST->hasAVX()) Options.LoadSizes.push_back(32);
if (PreferredWidth >= 128 && ST->hasSSE2()) Options.LoadSizes.push_back(16);
}
if (ST->is64Bit()) {
Options.LoadSizes.push_back(8);
}
Options.LoadSizes.push_back(4);
Options.LoadSizes.push_back(2);
Options.LoadSizes.push_back(1);
return Options;
}
bool X86TTIImpl::prefersVectorizedAddressing() const {
return supportsGather();
}
bool X86TTIImpl::supportsEfficientVectorElementLoadStore() const {
return false;
}
bool X86TTIImpl::enableInterleavedAccessVectorization() {
return !(ST->isAtom());
}
InstructionCost X86TTIImpl::getInterleavedMemoryOpCostAVX512(
unsigned Opcode, FixedVectorType *VecTy, unsigned Factor,
ArrayRef<unsigned> Indices, Align Alignment, unsigned AddressSpace,
TTI::TargetCostKind CostKind, bool UseMaskForCond, bool UseMaskForGaps) {
MVT LegalVT = getTLI()->getTypeLegalizationCost(DL, VecTy).second;
unsigned VecTySize = DL.getTypeStoreSize(VecTy);
unsigned LegalVTSize = LegalVT.getStoreSize();
unsigned NumOfMemOps = (VecTySize + LegalVTSize - 1) / LegalVTSize;
auto *SingleMemOpTy = FixedVectorType::get(VecTy->getElementType(),
LegalVT.getVectorNumElements());
InstructionCost MemOpCost;
bool UseMaskedMemOp = UseMaskForCond || UseMaskForGaps;
if (UseMaskedMemOp)
MemOpCost = getMaskedMemoryOpCost(Opcode, SingleMemOpTy, Alignment,
AddressSpace, CostKind);
else
MemOpCost = getMemoryOpCost(Opcode, SingleMemOpTy, MaybeAlign(Alignment),
AddressSpace, CostKind);
unsigned VF = VecTy->getNumElements() / Factor;
MVT VT = MVT::getVectorVT(MVT::getVT(VecTy->getScalarType()), VF);
InstructionCost MaskCost;
if (UseMaskedMemOp) {
APInt DemandedLoadStoreElts = APInt::getZero(VecTy->getNumElements());
for (unsigned Index : Indices) {
assert(Index < Factor && "Invalid index for interleaved memory op");
for (unsigned Elm = 0; Elm < VF; Elm++)
DemandedLoadStoreElts.setBit(Index + Elm * Factor);
}
Type *I1Type = Type::getInt1Ty(VecTy->getContext());
MaskCost = getReplicationShuffleCost(
I1Type, Factor, VF,
UseMaskForGaps ? DemandedLoadStoreElts
: APInt::getAllOnes(VecTy->getNumElements()),
CostKind);
if (UseMaskForGaps) {
auto *MaskVT = FixedVectorType::get(I1Type, VecTy->getNumElements());
MaskCost += getArithmeticInstrCost(BinaryOperator::And, MaskVT, CostKind);
}
}
if (Opcode == Instruction::Load) {
static const CostTblEntry AVX512InterleavedLoadTbl[] = {
{3, MVT::v16i8, 12}, {3, MVT::v32i8, 14}, {3, MVT::v64i8, 22}, };
if (const auto *Entry =
CostTableLookup(AVX512InterleavedLoadTbl, Factor, VT))
return MaskCost + NumOfMemOps * MemOpCost + Entry->Cost;
TTI::ShuffleKind ShuffleKind =
(NumOfMemOps > 1) ? TTI::SK_PermuteTwoSrc : TTI::SK_PermuteSingleSrc;
InstructionCost ShuffleCost =
getShuffleCost(ShuffleKind, SingleMemOpTy, None, 0, nullptr);
unsigned NumOfLoadsInInterleaveGrp =
Indices.size() ? Indices.size() : Factor;
auto *ResultTy = FixedVectorType::get(VecTy->getElementType(),
VecTy->getNumElements() / Factor);
InstructionCost NumOfResults =
getTLI()->getTypeLegalizationCost(DL, ResultTy).first *
NumOfLoadsInInterleaveGrp;
unsigned NumOfUnfoldedLoads =
UseMaskedMemOp || NumOfResults > 1 ? NumOfMemOps : NumOfMemOps / 2;
unsigned NumOfShufflesPerResult =
std::max((unsigned)1, (unsigned)(NumOfMemOps - 1));
InstructionCost NumOfMoves = 0;
if (NumOfResults > 1 && ShuffleKind == TTI::SK_PermuteTwoSrc)
NumOfMoves = NumOfResults * NumOfShufflesPerResult / 2;
InstructionCost Cost = NumOfResults * NumOfShufflesPerResult * ShuffleCost +
MaskCost + NumOfUnfoldedLoads * MemOpCost +
NumOfMoves;
return Cost;
}
assert(Opcode == Instruction::Store &&
"Expected Store Instruction at this point");
static const CostTblEntry AVX512InterleavedStoreTbl[] = {
{3, MVT::v16i8, 12}, {3, MVT::v32i8, 14}, {3, MVT::v64i8, 26},
{4, MVT::v8i8, 10}, {4, MVT::v16i8, 11}, {4, MVT::v32i8, 14}, {4, MVT::v64i8, 24} };
if (const auto *Entry =
CostTableLookup(AVX512InterleavedStoreTbl, Factor, VT))
return MaskCost + NumOfMemOps * MemOpCost + Entry->Cost;
unsigned NumOfSources = Factor; InstructionCost ShuffleCost =
getShuffleCost(TTI::SK_PermuteTwoSrc, SingleMemOpTy, None, 0, nullptr);
unsigned NumOfShufflesPerStore = NumOfSources - 1;
unsigned NumOfMoves = NumOfMemOps * NumOfShufflesPerStore / 2;
InstructionCost Cost =
MaskCost +
NumOfMemOps * (MemOpCost + NumOfShufflesPerStore * ShuffleCost) +
NumOfMoves;
return Cost;
}
InstructionCost X86TTIImpl::getInterleavedMemoryOpCost(
unsigned Opcode, Type *BaseTy, unsigned Factor, ArrayRef<unsigned> Indices,
Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,
bool UseMaskForCond, bool UseMaskForGaps) {
auto *VecTy = cast<FixedVectorType>(BaseTy);
auto isSupportedOnAVX512 = [&](Type *VecTy, bool HasBW) {
Type *EltTy = cast<VectorType>(VecTy)->getElementType();
if (EltTy->isFloatTy() || EltTy->isDoubleTy() || EltTy->isIntegerTy(64) ||
EltTy->isIntegerTy(32) || EltTy->isPointerTy())
return true;
if (EltTy->isIntegerTy(16) || EltTy->isIntegerTy(8) || EltTy->isHalfTy())
return HasBW;
return false;
};
if (ST->hasAVX512() && isSupportedOnAVX512(VecTy, ST->hasBWI()))
return getInterleavedMemoryOpCostAVX512(
Opcode, VecTy, Factor, Indices, Alignment,
AddressSpace, CostKind, UseMaskForCond, UseMaskForGaps);
if (UseMaskForCond || UseMaskForGaps)
return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
Alignment, AddressSpace, CostKind,
UseMaskForCond, UseMaskForGaps);
MVT LegalVT = getTLI()->getTypeLegalizationCost(DL, VecTy).second;
if (!LegalVT.isVector())
return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
Alignment, AddressSpace, CostKind);
unsigned VF = VecTy->getNumElements() / Factor;
Type *ScalarTy = VecTy->getElementType();
if (!ScalarTy->isIntegerTy())
ScalarTy =
Type::getIntNTy(ScalarTy->getContext(), DL.getTypeSizeInBits(ScalarTy));
InstructionCost MemOpCosts = getMemoryOpCost(
Opcode, VecTy, MaybeAlign(Alignment), AddressSpace, CostKind);
auto *VT = FixedVectorType::get(ScalarTy, VF);
EVT ETy = TLI->getValueType(DL, VT);
if (!ETy.isSimple())
return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
Alignment, AddressSpace, CostKind);
static const CostTblEntry AVX2InterleavedLoadTbl[] = {
{2, MVT::v2i8, 2}, {2, MVT::v4i8, 2}, {2, MVT::v8i8, 2}, {2, MVT::v16i8, 4}, {2, MVT::v32i8, 6},
{2, MVT::v8i16, 6}, {2, MVT::v16i16, 9}, {2, MVT::v32i16, 18},
{2, MVT::v8i32, 4}, {2, MVT::v16i32, 8}, {2, MVT::v32i32, 16},
{2, MVT::v4i64, 4}, {2, MVT::v8i64, 8}, {2, MVT::v16i64, 16}, {2, MVT::v32i64, 32},
{3, MVT::v2i8, 3}, {3, MVT::v4i8, 3}, {3, MVT::v8i8, 6}, {3, MVT::v16i8, 11}, {3, MVT::v32i8, 14},
{3, MVT::v2i16, 5}, {3, MVT::v4i16, 7}, {3, MVT::v8i16, 9}, {3, MVT::v16i16, 28}, {3, MVT::v32i16, 56},
{3, MVT::v2i32, 3}, {3, MVT::v4i32, 3}, {3, MVT::v8i32, 7}, {3, MVT::v16i32, 14}, {3, MVT::v32i32, 32},
{3, MVT::v2i64, 1}, {3, MVT::v4i64, 5}, {3, MVT::v8i64, 10}, {3, MVT::v16i64, 20},
{4, MVT::v2i8, 4}, {4, MVT::v4i8, 4}, {4, MVT::v8i8, 12}, {4, MVT::v16i8, 24}, {4, MVT::v32i8, 56},
{4, MVT::v2i16, 6}, {4, MVT::v4i16, 17}, {4, MVT::v8i16, 33}, {4, MVT::v16i16, 75}, {4, MVT::v32i16, 150},
{4, MVT::v2i32, 4}, {4, MVT::v4i32, 8}, {4, MVT::v8i32, 16}, {4, MVT::v16i32, 32}, {4, MVT::v32i32, 68},
{4, MVT::v2i64, 6}, {4, MVT::v4i64, 8}, {4, MVT::v8i64, 20}, {4, MVT::v16i64, 40},
{6, MVT::v2i8, 6}, {6, MVT::v4i8, 14}, {6, MVT::v8i8, 18}, {6, MVT::v16i8, 43}, {6, MVT::v32i8, 82},
{6, MVT::v2i16, 13}, {6, MVT::v4i16, 9}, {6, MVT::v8i16, 39}, {6, MVT::v16i16, 106}, {6, MVT::v32i16, 212},
{6, MVT::v2i32, 6}, {6, MVT::v4i32, 15}, {6, MVT::v8i32, 31}, {6, MVT::v16i32, 64},
{6, MVT::v2i64, 6}, {6, MVT::v4i64, 18}, {6, MVT::v8i64, 36},
{8, MVT::v8i32, 40} };
static const CostTblEntry SSSE3InterleavedLoadTbl[] = {
{2, MVT::v4i16, 2}, };
static const CostTblEntry SSE2InterleavedLoadTbl[] = {
{2, MVT::v2i16, 2}, {2, MVT::v4i16, 7},
{2, MVT::v2i32, 2}, {2, MVT::v4i32, 2},
{2, MVT::v2i64, 2}, };
static const CostTblEntry AVX2InterleavedStoreTbl[] = {
{2, MVT::v16i8, 3}, {2, MVT::v32i8, 4},
{2, MVT::v8i16, 3}, {2, MVT::v16i16, 4}, {2, MVT::v32i16, 8},
{2, MVT::v4i32, 2}, {2, MVT::v8i32, 4}, {2, MVT::v16i32, 8}, {2, MVT::v32i32, 16},
{2, MVT::v2i64, 2}, {2, MVT::v4i64, 4}, {2, MVT::v8i64, 8}, {2, MVT::v16i64, 16}, {2, MVT::v32i64, 32},
{3, MVT::v2i8, 4}, {3, MVT::v4i8, 4}, {3, MVT::v8i8, 6}, {3, MVT::v16i8, 11}, {3, MVT::v32i8, 13},
{3, MVT::v2i16, 4}, {3, MVT::v4i16, 6}, {3, MVT::v8i16, 12}, {3, MVT::v16i16, 27}, {3, MVT::v32i16, 54},
{3, MVT::v2i32, 4}, {3, MVT::v4i32, 5}, {3, MVT::v8i32, 11}, {3, MVT::v16i32, 22}, {3, MVT::v32i32, 48},
{3, MVT::v2i64, 4}, {3, MVT::v4i64, 6}, {3, MVT::v8i64, 12}, {3, MVT::v16i64, 24},
{4, MVT::v2i8, 4}, {4, MVT::v4i8, 4}, {4, MVT::v8i8, 4}, {4, MVT::v16i8, 8}, {4, MVT::v32i8, 12},
{4, MVT::v2i16, 2}, {4, MVT::v4i16, 6}, {4, MVT::v8i16, 10}, {4, MVT::v16i16, 32}, {4, MVT::v32i16, 64},
{4, MVT::v2i32, 5}, {4, MVT::v4i32, 6}, {4, MVT::v8i32, 16}, {4, MVT::v16i32, 32}, {4, MVT::v32i32, 64},
{4, MVT::v2i64, 6}, {4, MVT::v4i64, 8}, {4, MVT::v8i64, 20}, {4, MVT::v16i64, 40},
{6, MVT::v2i8, 7}, {6, MVT::v4i8, 9}, {6, MVT::v8i8, 16}, {6, MVT::v16i8, 27}, {6, MVT::v32i8, 90},
{6, MVT::v2i16, 10}, {6, MVT::v4i16, 15}, {6, MVT::v8i16, 21}, {6, MVT::v16i16, 58}, {6, MVT::v32i16, 90},
{6, MVT::v2i32, 9}, {6, MVT::v4i32, 12}, {6, MVT::v8i32, 33}, {6, MVT::v16i32, 66},
{6, MVT::v2i64, 8}, {6, MVT::v4i64, 15}, {6, MVT::v8i64, 30}, };
static const CostTblEntry SSE2InterleavedStoreTbl[] = {
{2, MVT::v2i8, 1}, {2, MVT::v4i8, 1}, {2, MVT::v8i8, 1},
{2, MVT::v2i16, 1}, {2, MVT::v4i16, 1},
{2, MVT::v2i32, 1}, };
if (Opcode == Instruction::Load) {
auto GetDiscountedCost = [Factor, NumMembers = Indices.size(),
MemOpCosts](const CostTblEntry *Entry) {
return MemOpCosts + divideCeil(NumMembers * Entry->Cost, Factor);
};
if (ST->hasAVX2())
if (const auto *Entry = CostTableLookup(AVX2InterleavedLoadTbl, Factor,
ETy.getSimpleVT()))
return GetDiscountedCost(Entry);
if (ST->hasSSSE3())
if (const auto *Entry = CostTableLookup(SSSE3InterleavedLoadTbl, Factor,
ETy.getSimpleVT()))
return GetDiscountedCost(Entry);
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2InterleavedLoadTbl, Factor,
ETy.getSimpleVT()))
return GetDiscountedCost(Entry);
} else {
assert(Opcode == Instruction::Store &&
"Expected Store Instruction at this point");
assert((!Indices.size() || Indices.size() == Factor) &&
"Interleaved store only supports fully-interleaved groups.");
if (ST->hasAVX2())
if (const auto *Entry = CostTableLookup(AVX2InterleavedStoreTbl, Factor,
ETy.getSimpleVT()))
return MemOpCosts + Entry->Cost;
if (ST->hasSSE2())
if (const auto *Entry = CostTableLookup(SSE2InterleavedStoreTbl, Factor,
ETy.getSimpleVT()))
return MemOpCosts + Entry->Cost;
}
return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
Alignment, AddressSpace, CostKind,
UseMaskForCond, UseMaskForGaps);
}