17#include "llvm/IR/IntrinsicsWebAssembly.h"
23#define DEBUG_TYPE "wasmtti"
35 bool Vector = (ClassID == 1);
37 Result = std::max(Result, 16u);
61 if (ST->hasSIMD128()) {
72 EVT DstVT = TLI->getValueType(
DL, Ty);
74 int ISD = TLI->InstructionOpcodeToISD(Opcode);
75 if (
const auto *Entry =
83 Opcode, Ty,
CostKind, Op1Info, Op2Info);
87 case Instruction::LShr:
88 case Instruction::AShr:
89 case Instruction::Shl:
108 int ISD = TLI->InstructionOpcodeToISD(Opcode);
109 auto SrcTy = TLI->getValueType(
DL, Src);
110 auto DstTy = TLI->getValueType(
DL, Dst);
112 if (!SrcTy.isSimple() || !DstTy.isSimple()) {
116 if (!ST->hasSIMD128()) {
120 auto DstVT = DstTy.getSimpleVT();
121 auto SrcVT = SrcTy.getSimpleVT();
123 if (
I &&
I->hasOneUser()) {
125 int UserISD = TLI->InstructionOpcodeToISD(SingleUser->getOpcode());
131 if ((SrcVT == MVT::v8i8 && DstVT == MVT::v8i16) ||
132 (SrcVT == MVT::v4i16 && DstVT == MVT::v4i32) ||
133 (SrcVT == MVT::v2i32 && DstVT == MVT::v2i64)) {
138 if ((SrcVT == MVT::v4i8 && DstVT == MVT::v4i32) ||
139 (SrcVT == MVT::v2i16 && DstVT == MVT::v2i64)) {
223 if (
const auto *Entry =
235 Options.AllowOverlappingLoads =
true;
237 if (ST->hasSIMD128())
238 Options.LoadSizes.push_back(16);
240 Options.LoadSizes.append({8, 4, 2, 1});
241 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
256 EVT VT = TLI->getValueType(
DL, Ty,
true);
258 if (VT == MVT::Other)
263 if (!LT.first.isValid())
266 int ISD = TLI->InstructionOpcodeToISD(Opcode);
300 bool UseMaskForCond,
bool UseMaskForGaps)
const {
301 assert(Factor >= 2 &&
"Invalid interleave factor");
308 if (UseMaskForCond || UseMaskForGaps)
311 UseMaskForCond, UseMaskForGaps);
315 unsigned MinElts = VecTy->getElementCount().getKnownMinValue();
317 if (MinElts < 2 || MinElts % Factor != 0)
320 unsigned ElSize =
DL.getTypeSizeInBits(VecTy->getElementType());
322 if (ElSize != 8 && ElSize != 16 && ElSize != 32 && ElSize != 64)
325 if (Factor != 2 && Factor != 4)
330 VecTy->getElementCount().divideCoefficientBy(Factor));
334 unsigned VecSize =
DL.getTypeSizeInBits(SubVecTy);
336 unsigned NumAccesses =
337 std::max<unsigned>(1, (MinElts * ElSize +
MaxVecSize - 1) / VecSize);
373 EVT ETy = TLI->getValueType(
DL, SubVecTy);
374 if (
const auto *Entry =
376 return Entry->Cost + (NumAccesses * MemCost);
381 UseMaskForCond, UseMaskForGaps);
388 Opcode, Val,
CostKind, Index, Op0, Op1);
398 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
403 if (!VF.
isFixed() || !ST->hasSIMD128())
409 if (Opcode != Instruction::Add)
414 if (AccumEVT != MVT::i32)
436 if (OpAExtend != OpBExtend)
439 if (*BinOp != Instruction::Mul)
442 if (InputTypeA != InputTypeB)
459 switch (
II->getIntrinsicID()) {
462 case Intrinsic::vector_reduce_fadd:
496 return getST()->hasTailCall();
503 if (!
I->getType()->isVectorTy() || !
I->isShift())
506 Value *V =
I->getOperand(1);
516 Ops.push_back(&
I->getOperandUse(1));
533 unsigned NumElts = VecTy->getNumElements();
538 bool AnyOutOfBounds =
false;
540 for (
unsigned I = 0;
I < NumElts; ++
I) {
571 if (Index >= NumElts) {
572 AnyOutOfBounds =
true;
576 Indexes[
I] = NumElts;
583 auto *V1 =
II.getArgOperand(0);
587 return Builder.CreateShuffleVector(V1, V2,
ArrayRef(Indexes, NumElts));
590std::optional<Instruction *>
595 case Intrinsic::wasm_swizzle:
596 case Intrinsic::wasm_relaxed_swizzle:
598 II, IC.
Builder, IID == Intrinsic::wasm_relaxed_swizzle)) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
Cost tables and simple lookup functions.
static const int MaxVecSize
This file provides the interface for the instcombine pass implementation.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static const unsigned MaxInterleaveFactor
Maximum vectorization interleave count.
static const Function * getCalledFunction(const Value *V)
uint64_t IntrinsicInst * II
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1) const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Opd1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Opd2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
std::pair< InstructionCost, MVT > getTypeLegalizationCost(Type *Ty) const
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
This is an important base class in LLVM.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
The core instruction combiner logic.
IRBuilder< TargetFolder, IRBuilderCallbackInserter > BuilderTy
An IRBuilder that automatically inserts new instructions into the worklist.
Instruction * replaceInstUsesWith(Instruction &I, Value *V)
A combiner-aware RAUW-like routine.
static InstructionCost getInvalid(CostType Val=0)
A wrapper class for inspecting calls to intrinsic functions.
Represents a single loop in the control flow graph.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
The main scalar evolution driver.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *Ty, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond, bool UseMaskForGaps) const override
bool supportsTailCalls() const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override
std::optional< Instruction * > instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) const override
bool isProfitableToSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops) const override
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1) const override
TTI::ReductionShuffle getPreferredExpandedReductionShuffle(const IntrinsicInst *II) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
unsigned getNumberOfRegisters(unsigned ClassID) const override
constexpr ScalarTy getFixedValue() const
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ISD namespace - This namespace contains an enum which represents all of the SelectionDAG node types a...
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ SIGN_EXTEND
Conversion operators.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
bool match(Val *V, const Pattern &P)
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
This is an optimization pass for GlobalISel generic memory operations.
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
TypeConversionCostTblEntryT< unsigned > TypeConversionCostTblEntry
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
CostTblEntryT< unsigned > CostTblEntry
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
const TypeConversionCostTblEntryT< CostType > * ConvertCostTableLookup(ArrayRef< TypeConversionCostTblEntryT< CostType > > Tbl, int ISD, MVT Dst, MVT Src)
Find in type conversion cost table.
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.