LLVM 24.0.0git
X86TargetTransformInfo.cpp
Go to the documentation of this file.
1//===-- X86TargetTransformInfo.cpp - X86 specific TTI pass ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements a TargetTransformInfo analysis pass specific to the
10/// X86 target machine. It uses the target's detailed information to provide
11/// more precise answers to certain TTI queries, while letting the target
12/// independent and default TTI implementations handle the rest.
13///
14//===----------------------------------------------------------------------===//
15/// About Cost Model numbers used below it's necessary to say the following:
16/// the numbers correspond to some "generic" X86 CPU instead of usage of a
17/// specific CPU model. Usually the numbers correspond to the CPU where the
18/// feature first appeared. For example, if we do Subtarget.hasSSE42() in
19/// the lookups below the cost is based on Nehalem as that was the first CPU
20/// to support that feature level and thus has most likely the worst case cost,
21/// although we may discard an outlying worst cost from one CPU (e.g. Atom).
22///
23/// Some examples of other technologies/CPUs:
24/// SSE 3 - Pentium4 / Athlon64
25/// SSE 4.1 - Penryn
26/// SSE 4.2 - Nehalem / Silvermont
27/// AVX - Sandy Bridge / Jaguar / Bulldozer
28/// AVX2 - Haswell / Ryzen
29/// AVX-512 - Xeon Phi / Skylake
30///
31/// And some examples of instruction target dependent costs (latency)
32/// divss sqrtss rsqrtss
33/// AMD K7 11-16 19 3
34/// Piledriver 9-24 13-15 5
35/// Jaguar 14 16 2
36/// Pentium II,III 18 30 2
37/// Nehalem 7-14 7-18 3
38/// Haswell 10-13 11 5
39///
40/// Interpreting the 4 TargetCostKind types:
41/// TCK_RecipThroughput and TCK_Latency should try to match the worst case
42/// values reported by the CPU scheduler models (and llvm-mca).
43/// TCK_CodeSize should match the instruction count (e.g. divss = 1), NOT the
44/// actual encoding size of the instruction.
45/// TCK_SizeAndLatency should match the worst case micro-op counts reported by
46/// by the CPU scheduler models (and llvm-mca), to ensure that they are
47/// compatible with the MicroOpBufferSize and LoopMicroOpBufferSize values which are
48/// often used as the cost thresholds where TCK_SizeAndLatency is requested.
49//===----------------------------------------------------------------------===//
50
60#include <optional>
61
62using namespace llvm;
63
64#define DEBUG_TYPE "x86tti"
65
66//===----------------------------------------------------------------------===//
67//
68// X86 cost model.
69//
70//===----------------------------------------------------------------------===//
71
72// Helper struct to store/access costs for each cost kind.
73// TODO: Move this to allow other targets to use it?
74namespace {
75struct CostKindCosts {
76 unsigned RecipThroughputCost = ~0U;
77 unsigned LatencyCost = ~0U;
78 unsigned CodeSizeCost = ~0U;
79 unsigned SizeAndLatencyCost = ~0U;
80
81 std::optional<unsigned>
82 operator[](TargetTransformInfo::TargetCostKind Kind) const {
83 unsigned Cost = ~0U;
84 switch (Kind) {
86 Cost = RecipThroughputCost;
87 break;
89 Cost = LatencyCost;
90 break;
92 Cost = CodeSizeCost;
93 break;
95 Cost = SizeAndLatencyCost;
96 break;
97 }
98 if (Cost == ~0U)
99 return std::nullopt;
100 return Cost;
101 }
102};
103} // namespace
106
108X86TTIImpl::getPopcntSupport(unsigned TyWidth) const {
109 assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
110 // TODO: Currently the __builtin_popcount() implementation using SSE3
111 // instructions is inefficient. Once the problem is fixed, we should
112 // call ST->hasSSE3() instead of ST->hasPOPCNT().
113 return ST->hasPOPCNT() ? TTI::PSK_FastHardware : TTI::PSK_Software;
114}
115
116std::optional<unsigned> X86TTIImpl::getCacheSize(
118 switch (Level) {
120 // - Penryn
121 // - Nehalem
122 // - Westmere
123 // - Sandy Bridge
124 // - Ivy Bridge
125 // - Haswell
126 // - Broadwell
127 // - Skylake
128 // - Kabylake
129 return 32 * 1024; // 32 KiB
131 // - Penryn
132 // - Nehalem
133 // - Westmere
134 // - Sandy Bridge
135 // - Ivy Bridge
136 // - Haswell
137 // - Broadwell
138 // - Skylake
139 // - Kabylake
140 return 256 * 1024; // 256 KiB
141 }
142
143 llvm_unreachable("Unknown TargetTransformInfo::CacheLevel");
144}
145
146std::optional<unsigned> X86TTIImpl::getCacheAssociativity(
148 // - Penryn
149 // - Nehalem
150 // - Westmere
151 // - Sandy Bridge
152 // - Ivy Bridge
153 // - Haswell
154 // - Broadwell
155 // - Skylake
156 // - Kabylake
157 switch (Level) {
159 [[fallthrough]];
161 return 8;
162 }
163
164 llvm_unreachable("Unknown TargetTransformInfo::CacheLevel");
165}
166
168
170 return Vector ? VectorClass
171 : Ty && Ty->isFloatingPointTy() ? ScalarFPClass
172 : GPRClass;
173}
174
175unsigned X86TTIImpl::getNumberOfRegisters(unsigned ClassID) const {
176 if (ClassID == VectorClass && !ST->hasSSE1())
177 return 0;
178
179 if (!ST->is64Bit())
180 return 8;
181
182 if ((ClassID == GPRClass && ST->hasEGPR()) ||
183 (ClassID != GPRClass && ST->hasAVX512()))
184 return 32;
185
186 return 16;
187}
188
190 if (!ST->hasCF())
191 return false;
192 if (!Ty)
193 return true;
194 // Conditional faulting is supported by CFCMOV, which only accepts
195 // 16/32/64-bit operands.
196 // TODO: Support f32/f64 with VMOVSS/VMOVSD with zero mask when it's
197 // profitable.
198 auto *VTy = dyn_cast<FixedVectorType>(Ty);
199 if (!Ty->isIntegerTy() && (!VTy || VTy->getNumElements() != 1))
200 return false;
201 auto *ScalarTy = Ty->getScalarType();
202 switch (cast<IntegerType>(ScalarTy)->getBitWidth()) {
203 default:
204 return false;
205 case 16:
206 case 32:
207 case 64:
208 return true;
209 }
210}
211
214 unsigned PreferVectorWidth = ST->getPreferVectorWidth();
215 switch (K) {
217 return TypeSize::getFixed(ST->is64Bit() ? 64 : 32);
219 if (ST->hasAVX512() && PreferVectorWidth >= 512)
220 return TypeSize::getFixed(512);
221 if (ST->hasAVX() && PreferVectorWidth >= 256)
222 return TypeSize::getFixed(256);
223 if (ST->hasSSE1() && PreferVectorWidth >= 128)
224 return TypeSize::getFixed(128);
225 return TypeSize::getFixed(0);
227 return TypeSize::getScalable(0);
228 }
229
230 llvm_unreachable("Unsupported register kind");
231}
232
237
239 bool HasUnorderedReductions) const {
240 // If the loop will not be vectorized, don't interleave the loop.
241 // Let regular unroll to unroll the loop, which saves the overflow
242 // check and memory check cost.
243 if (VF.isScalar())
244 return 1;
245
246 if (ST->isAtom())
247 return 1;
248
249 // Sandybridge and Haswell have multiple execution ports and pipelined
250 // vector units.
251 if (ST->hasAVX())
252 return 4;
253
254 return 2;
255}
256
258 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
260 ArrayRef<const Value *> Args, const Instruction *CtxI) const {
261
262 // vXi8 multiplications are always promoted to vXi16.
263 // Sub-128-bit types can be extended/packed more efficiently.
264 if (Opcode == Instruction::Mul && Ty->isVectorTy() &&
265 Ty->getPrimitiveSizeInBits() <= 64 && Ty->getScalarSizeInBits() == 8) {
266 Type *WideVecTy =
268 return getCastInstrCost(Instruction::ZExt, WideVecTy, Ty,
270 CostKind) +
271 getCastInstrCost(Instruction::Trunc, Ty, WideVecTy,
273 CostKind) +
274 getArithmeticInstrCost(Opcode, WideVecTy, CostKind, Op1Info, Op2Info);
275 }
276
277 // Legalize the type.
278 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
279
280 int ISD = TLI->InstructionOpcodeToISD(Opcode);
281 assert(ISD && "Invalid opcode");
282
283 if (ISD == ISD::MUL && Args.size() == 2 && LT.second.isVector() &&
284 (LT.second.getScalarType() == MVT::i32 ||
285 LT.second.getScalarType() == MVT::i64)) {
286 // Check if the operands can be represented as a smaller datatype.
287 bool Op1Signed = false, Op2Signed = false;
288 unsigned Op1MinSize = BaseT::minRequiredElementSize(Args[0], Op1Signed);
289 unsigned Op2MinSize = BaseT::minRequiredElementSize(Args[1], Op2Signed);
290 unsigned OpMinSize = std::max(Op1MinSize, Op2MinSize);
291 bool SignedMode = Op1Signed || Op2Signed;
292
293 // If both vXi32 are representable as i15 and at least one is constant,
294 // zero-extended, or sign-extended from vXi16 (or less pre-SSE41) then we
295 // can treat this as PMADDWD which has the same costs as a vXi16 multiply.
296 if (OpMinSize <= 15 && !ST->isPMADDWDSlow() &&
297 LT.second.getScalarType() == MVT::i32) {
298 bool Op1Constant =
299 isa<ConstantDataVector>(Args[0]) || isa<ConstantVector>(Args[0]);
300 bool Op2Constant =
301 isa<ConstantDataVector>(Args[1]) || isa<ConstantVector>(Args[1]);
302 bool Op1Sext = isa<SExtInst>(Args[0]) &&
303 (Op1MinSize == 15 || (Op1MinSize < 15 && !ST->hasSSE41()));
304 bool Op2Sext = isa<SExtInst>(Args[1]) &&
305 (Op2MinSize == 15 || (Op2MinSize < 15 && !ST->hasSSE41()));
306
307 bool IsZeroExtended = !Op1Signed || !Op2Signed;
308 bool IsConstant = Op1Constant || Op2Constant;
309 bool IsSext = Op1Sext || Op2Sext;
310 if (IsConstant || IsZeroExtended || IsSext)
311 LT.second =
312 MVT::getVectorVT(MVT::i16, 2 * LT.second.getVectorNumElements());
313 }
314
315 // Check if the vXi32 operands can be shrunk into a smaller datatype.
316 // This should match the codegen from reduceVMULWidth.
317 // TODO: Make this generic (!ST->SSE41 || ST->isPMULLDSlow()).
318 if (ST->useSLMArithCosts() && LT.second == MVT::v4i32) {
319 if (OpMinSize <= 7)
320 return LT.first * 3; // pmullw/sext
321 if (!SignedMode && OpMinSize <= 8)
322 return LT.first * 3; // pmullw/zext
323 if (OpMinSize <= 15)
324 return LT.first * 5; // pmullw/pmulhw/pshuf
325 if (!SignedMode && OpMinSize <= 16)
326 return LT.first * 5; // pmullw/pmulhw/pshuf
327 }
328
329 // If both vXi64 are representable as (unsigned) i32, then we can perform
330 // the multiple with a single PMULUDQ instruction.
331 // TODO: Add (SSE41+) PMULDQ handling for signed extensions.
332 if (!SignedMode && OpMinSize <= 32 && LT.second.getScalarType() == MVT::i64)
333 ISD = X86ISD::PMULUDQ;
334 }
335
336 // Vector multiply by pow2 will be simplified to shifts.
337 // Vector multiply by -pow2 will be simplified to shifts/negates.
338 if (ISD == ISD::MUL && Op2Info.isConstant() &&
339 (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2())) {
341 getArithmeticInstrCost(Instruction::Shl, Ty, CostKind,
342 Op1Info.getNoProps(), Op2Info.getNoProps());
343 if (Op2Info.isNegatedPowerOf2())
344 Cost += getArithmeticInstrCost(Instruction::Sub, Ty, CostKind);
345 return Cost;
346 }
347
348 // On X86, vector signed division by constants power-of-two are
349 // normally expanded to the sequence SRA + SRL + ADD + SRA.
350 // The OperandValue properties may not be the same as that of the previous
351 // operation; conservatively assume OP_None.
352 if ((ISD == ISD::SDIV || ISD == ISD::SREM) &&
353 Op2Info.isConstant() && Op2Info.isPowerOf2()) {
355 2 * getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
356 Op1Info.getNoProps(), Op2Info.getNoProps());
357 Cost += getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
358 Op1Info.getNoProps(), Op2Info.getNoProps());
359 Cost += getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
360 Op1Info.getNoProps(), Op2Info.getNoProps());
361
362 if (ISD == ISD::SREM) {
363 // For SREM: (X % C) is the equivalent of (X - (X/C)*C)
364 Cost += getArithmeticInstrCost(Instruction::Mul, Ty, CostKind, Op1Info.getNoProps(),
365 Op2Info.getNoProps());
366 Cost += getArithmeticInstrCost(Instruction::Sub, Ty, CostKind, Op1Info.getNoProps(),
367 Op2Info.getNoProps());
368 }
369
370 return Cost;
371 }
372
373 // Vector unsigned division/remainder will be simplified to shifts/masks.
374 if ((ISD == ISD::UDIV || ISD == ISD::UREM) &&
375 Op2Info.isConstant() && Op2Info.isPowerOf2()) {
376 if (ISD == ISD::UDIV)
377 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
378 Op1Info.getNoProps(), Op2Info.getNoProps());
379 // UREM
380 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
381 Op1Info.getNoProps(), Op2Info.getNoProps());
382 }
383
384 // A rem paired with a div on the same operands in the same block is free:
385 // the pair costs the div alone. Power-of-two divisors are handled above.
386 if ((ISD == ISD::UREM || ISD == ISD::SREM) && CostKind != TTI::TCK_Latency &&
387 CtxI && CtxI->getOpcode() == Opcode) {
388 using namespace PatternMatch;
389 // Same use limit as SLP, bounds the walk over the operand users.
390 constexpr unsigned MaxUses = 64;
391 unsigned DivOpcode =
392 ISD == ISD::SREM ? Instruction::SDiv : Instruction::UDiv;
393 const Value *X = CtxI->getOperand(0);
394 const Value *Y = CtxI->getOperand(1);
395 // Constants have context-wide use lists, walk the variable operand.
396 const Value *V = isa<Constant>(Y) ? X : Y;
397 if (!isa<Constant>(V) && !V->hasNUsesOrMore(MaxUses) &&
398 any_of(V->users(), [&](const User *U) {
399 return match(U, m_BinOp(DivOpcode, m_Specific(X), m_Specific(Y))) &&
400 cast<Instruction>(U)->getParent() == CtxI->getParent();
401 }))
402 return TTI::TCC_Free;
403 }
404
405 // A scalar integer divide/remainder by a constant is not a hardware divide;
406 // it lowers to a magic-number multiply-high plus a few fixup ops. Cost it as
407 // that sequence rather than the generic single-instruction divide, so the
408 // vectorizers do not compare against an artificially cheap scalar lane. The
409 // power-of-two cases are handled above; negated powers of two are left to the
410 // generic handling.
411 if (!Ty->isVectorTy() && Op2Info.isConstant() && !Op2Info.isNegatedPowerOf2() &&
412 (ISD == ISD::UDIV || ISD == ISD::SDIV || ISD == ISD::UREM ||
413 ISD == ISD::SREM)) {
414 unsigned Cost = ISD == ISD::UREM || ISD == ISD::SREM ? 6 : 5;
415 if (CostKind == TTI::TCK_CodeSize || CostKind == TTI::TCK_SizeAndLatency)
416 Cost += 2;
417 return LT.first * Cost;
418 }
419
420 static const CostKindTblEntry GFNIUniformConstCostTable[] = {
421 { ISD::SHL, MVT::v16i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
422 { ISD::SRL, MVT::v16i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
423 { ISD::SRA, MVT::v16i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
424 { ISD::SHL, MVT::v32i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
425 { ISD::SRL, MVT::v32i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
426 { ISD::SRA, MVT::v32i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
427 { ISD::SHL, MVT::v64i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
428 { ISD::SRL, MVT::v64i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
429 { ISD::SRA, MVT::v64i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
430 };
431
432 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasGFNI())
433 if (const auto *Entry =
434 CostTableLookup(GFNIUniformConstCostTable, ISD, LT.second))
435 if (auto KindCost = Entry->Cost[CostKind])
436 return LT.first * *KindCost;
437
438 static const CostKindTblEntry AVX512BWUniformConstCostTable[] = {
439 { ISD::SHL, MVT::v16i8, { 1, 7, 2, 3 } }, // psllw + pand.
440 { ISD::SRL, MVT::v16i8, { 1, 7, 2, 3 } }, // psrlw + pand.
441 { ISD::SRA, MVT::v16i8, { 1, 8, 4, 5 } }, // psrlw, pand, pxor, psubb.
442 { ISD::SHL, MVT::v32i8, { 1, 8, 2, 3 } }, // psllw + pand.
443 { ISD::SRL, MVT::v32i8, { 1, 8, 2, 3 } }, // psrlw + pand.
444 { ISD::SRA, MVT::v32i8, { 1, 9, 4, 5 } }, // psrlw, pand, pxor, psubb.
445 { ISD::SHL, MVT::v64i8, { 1, 8, 2, 3 } }, // psllw + pand.
446 { ISD::SRL, MVT::v64i8, { 1, 8, 2, 3 } }, // psrlw + pand.
447 { ISD::SRA, MVT::v64i8, { 1, 9, 4, 6 } }, // psrlw, pand, pxor, psubb.
448
449 { ISD::SHL, MVT::v16i16, { 1, 1, 1, 1 } }, // psllw
450 { ISD::SRL, MVT::v16i16, { 1, 1, 1, 1 } }, // psrlw
451 { ISD::SRA, MVT::v16i16, { 1, 1, 1, 1 } }, // psrlw
452 { ISD::SHL, MVT::v32i16, { 1, 1, 1, 1 } }, // psllw
453 { ISD::SRL, MVT::v32i16, { 1, 1, 1, 1 } }, // psrlw
454 { ISD::SRA, MVT::v32i16, { 1, 1, 1, 1 } }, // psrlw
455 };
456
457 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasBWI())
458 if (const auto *Entry =
459 CostTableLookup(AVX512BWUniformConstCostTable, ISD, LT.second))
460 if (auto KindCost = Entry->Cost[CostKind])
461 return LT.first * *KindCost;
462
463 static const CostKindTblEntry AVX512DQUniformConstCostTable[] = {
464 { ISD::SDIV, MVT::v4i64, { 15 } }, // vpmullq-based MULHS sequence
465 { ISD::SREM, MVT::v4i64, { 17 } }, // vpmullq-based MULHS+mul+sub sequence
466 { ISD::SDIV, MVT::v8i64, { 15 } }, // vpmullq-based MULHS sequence
467 { ISD::SREM, MVT::v8i64, { 17 } }, // vpmullq-based MULHS+mul+sub sequence
468 // The remainder's multiply-back is a single vpmullq with DQ, just like the
469 // pmulld the vXi32 entries above rely on. Without DQ it is another
470 // vpmuludq schoolbook, so the AVX512/AVX2 tables charge more.
471 { ISD::UREM, MVT::v4i64, { 17 } }, // MULHU + vpmullq + sub sequence
472 { ISD::UREM, MVT::v8i64, { 17 } }, // MULHU + vpmullq + sub sequence
473 };
474
475 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasDQI())
476 if (const auto *Entry =
477 CostTableLookup(AVX512DQUniformConstCostTable, ISD, LT.second))
478 if (auto KindCost = Entry->Cost[CostKind])
479 return LT.first * *KindCost;
480
481 static const CostKindTblEntry AVX512UniformConstCostTable[] = {
482 { ISD::SHL, MVT::v64i8, { 2, 12, 5, 6 } }, // psllw + pand.
483 { ISD::SRL, MVT::v64i8, { 2, 12, 5, 6 } }, // psrlw + pand.
484 { ISD::SRA, MVT::v64i8, { 3, 10, 12, 12 } }, // psrlw, pand, pxor, psubb.
485
486 { ISD::SHL, MVT::v16i16, { 2, 7, 4, 4 } }, // psllw + split.
487 { ISD::SRL, MVT::v16i16, { 2, 7, 4, 4 } }, // psrlw + split.
488 { ISD::SRA, MVT::v16i16, { 2, 7, 4, 4 } }, // psraw + split.
489
490 { ISD::SHL, MVT::v8i32, { 1, 1, 1, 1 } }, // pslld
491 { ISD::SRL, MVT::v8i32, { 1, 1, 1, 1 } }, // psrld
492 { ISD::SRA, MVT::v8i32, { 1, 1, 1, 1 } }, // psrad
493 { ISD::SHL, MVT::v16i32, { 1, 1, 1, 1 } }, // pslld
494 { ISD::SRL, MVT::v16i32, { 1, 1, 1, 1 } }, // psrld
495 { ISD::SRA, MVT::v16i32, { 1, 1, 1, 1 } }, // psrad
496
497 { ISD::SRA, MVT::v2i64, { 1, 1, 1, 1 } }, // psraq
498 { ISD::SHL, MVT::v4i64, { 1, 1, 1, 1 } }, // psllq
499 { ISD::SRL, MVT::v4i64, { 1, 1, 1, 1 } }, // psrlq
500 { ISD::SRA, MVT::v4i64, { 1, 1, 1, 1 } }, // psraq
501 { ISD::SHL, MVT::v8i64, { 1, 1, 1, 1 } }, // psllq
502 { ISD::SRL, MVT::v8i64, { 1, 1, 1, 1 } }, // psrlq
503 { ISD::SRA, MVT::v8i64, { 1, 1, 1, 1 } }, // psraq
504
505 { ISD::SDIV, MVT::v16i32, { 6 } }, // pmuludq sequence
506 { ISD::SREM, MVT::v16i32, { 8 } }, // pmuludq+mul+sub sequence
507 { ISD::UDIV, MVT::v16i32, { 5 } }, // pmuludq sequence
508 { ISD::UREM, MVT::v16i32, { 7 } }, // pmuludq+mul+sub sequence
509
510 { ISD::UDIV, MVT::v8i64, { 15 } }, // pmuludq-based MULHU sequence
511 { ISD::UREM, MVT::v8i64, { 21 } }, // pmuludq-based MULHU+mul+sub sequence
512 };
513
514 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasAVX512())
515 if (const auto *Entry =
516 CostTableLookup(AVX512UniformConstCostTable, ISD, LT.second))
517 if (auto KindCost = Entry->Cost[CostKind])
518 return LT.first * *KindCost;
519
520 static const CostKindTblEntry AVX2UniformConstCostTable[] = {
521 { ISD::SHL, MVT::v16i8, { 1, 8, 2, 3 } }, // psllw + pand.
522 { ISD::SRL, MVT::v16i8, { 1, 8, 2, 3 } }, // psrlw + pand.
523 { ISD::SRA, MVT::v16i8, { 2, 10, 5, 6 } }, // psrlw, pand, pxor, psubb.
524 { ISD::SHL, MVT::v32i8, { 2, 8, 2, 4 } }, // psllw + pand.
525 { ISD::SRL, MVT::v32i8, { 2, 8, 2, 4 } }, // psrlw + pand.
526 { ISD::SRA, MVT::v32i8, { 3, 10, 5, 9 } }, // psrlw, pand, pxor, psubb.
527
528 { ISD::SHL, MVT::v8i16, { 1, 1, 1, 1 } }, // psllw
529 { ISD::SRL, MVT::v8i16, { 1, 1, 1, 1 } }, // psrlw
530 { ISD::SRA, MVT::v8i16, { 1, 1, 1, 1 } }, // psraw
531 { ISD::SHL, MVT::v16i16,{ 2, 2, 1, 2 } }, // psllw
532 { ISD::SRL, MVT::v16i16,{ 2, 2, 1, 2 } }, // psrlw
533 { ISD::SRA, MVT::v16i16,{ 2, 2, 1, 2 } }, // psraw
534
535 { ISD::SHL, MVT::v4i32, { 1, 1, 1, 1 } }, // pslld
536 { ISD::SRL, MVT::v4i32, { 1, 1, 1, 1 } }, // psrld
537 { ISD::SRA, MVT::v4i32, { 1, 1, 1, 1 } }, // psrad
538 { ISD::SHL, MVT::v8i32, { 2, 2, 1, 2 } }, // pslld
539 { ISD::SRL, MVT::v8i32, { 2, 2, 1, 2 } }, // psrld
540 { ISD::SRA, MVT::v8i32, { 2, 2, 1, 2 } }, // psrad
541
542 { ISD::SHL, MVT::v2i64, { 1, 1, 1, 1 } }, // psllq
543 { ISD::SRL, MVT::v2i64, { 1, 1, 1, 1 } }, // psrlq
544 { ISD::SRA, MVT::v2i64, { 2, 3, 3, 3 } }, // psrad + shuffle.
545 { ISD::SHL, MVT::v4i64, { 2, 2, 1, 2 } }, // psllq
546 { ISD::SRL, MVT::v4i64, { 2, 2, 1, 2 } }, // psrlq
547 { ISD::SRA, MVT::v4i64, { 4, 4, 3, 6 } }, // psrad + shuffle + split.
548
549 { ISD::SDIV, MVT::v8i32, { 6 } }, // pmuludq sequence
550 { ISD::SREM, MVT::v8i32, { 8 } }, // pmuludq+mul+sub sequence
551 { ISD::UDIV, MVT::v8i32, { 5 } }, // pmuludq sequence
552 { ISD::UREM, MVT::v8i32, { 7 } }, // pmuludq+mul+sub sequence
553
554 { ISD::UDIV, MVT::v4i64, { 15 } }, // pmuludq-based MULHU sequence
555 { ISD::UREM, MVT::v4i64, { 21 } }, // pmuludq-based MULHU+mul+sub sequence
556 };
557
558 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasAVX2())
559 if (const auto *Entry =
560 CostTableLookup(AVX2UniformConstCostTable, ISD, LT.second))
561 if (auto KindCost = Entry->Cost[CostKind])
562 return LT.first * *KindCost;
563
564 static const CostKindTblEntry AVXUniformConstCostTable[] = {
565 { ISD::SHL, MVT::v16i8, { 2, 7, 2, 3 } }, // psllw + pand.
566 { ISD::SRL, MVT::v16i8, { 2, 7, 2, 3 } }, // psrlw + pand.
567 { ISD::SRA, MVT::v16i8, { 3, 9, 5, 6 } }, // psrlw, pand, pxor, psubb.
568 { ISD::SHL, MVT::v32i8, { 4, 7, 7, 8 } }, // 2*(psllw + pand) + split.
569 { ISD::SRL, MVT::v32i8, { 4, 7, 7, 8 } }, // 2*(psrlw + pand) + split.
570 { ISD::SRA, MVT::v32i8, { 7, 7, 12, 13 } }, // 2*(psrlw, pand, pxor, psubb) + split.
571
572 { ISD::SHL, MVT::v8i16, { 1, 2, 1, 1 } }, // psllw.
573 { ISD::SRL, MVT::v8i16, { 1, 2, 1, 1 } }, // psrlw.
574 { ISD::SRA, MVT::v8i16, { 1, 2, 1, 1 } }, // psraw.
575 { ISD::SHL, MVT::v16i16,{ 3, 6, 4, 5 } }, // psllw + split.
576 { ISD::SRL, MVT::v16i16,{ 3, 6, 4, 5 } }, // psrlw + split.
577 { ISD::SRA, MVT::v16i16,{ 3, 6, 4, 5 } }, // psraw + split.
578
579 { ISD::SHL, MVT::v4i32, { 1, 2, 1, 1 } }, // pslld.
580 { ISD::SRL, MVT::v4i32, { 1, 2, 1, 1 } }, // psrld.
581 { ISD::SRA, MVT::v4i32, { 1, 2, 1, 1 } }, // psrad.
582 { ISD::SHL, MVT::v8i32, { 3, 6, 4, 5 } }, // pslld + split.
583 { ISD::SRL, MVT::v8i32, { 3, 6, 4, 5 } }, // psrld + split.
584 { ISD::SRA, MVT::v8i32, { 3, 6, 4, 5 } }, // psrad + split.
585
586 { ISD::SHL, MVT::v2i64, { 1, 2, 1, 1 } }, // psllq.
587 { ISD::SRL, MVT::v2i64, { 1, 2, 1, 1 } }, // psrlq.
588 { ISD::SRA, MVT::v2i64, { 2, 3, 3, 3 } }, // psrad + shuffle.
589 { ISD::SHL, MVT::v4i64, { 3, 6, 4, 5 } }, // 2 x psllq + split.
590 { ISD::SRL, MVT::v4i64, { 3, 6, 4, 5 } }, // 2 x psllq + split.
591 { ISD::SRA, MVT::v4i64, { 5, 7, 8, 9 } }, // 2 x psrad + shuffle + split.
592
593 { ISD::SDIV, MVT::v8i32, { 14 } }, // 2*pmuludq sequence + split.
594 { ISD::SREM, MVT::v8i32, { 18 } }, // 2*pmuludq+mul+sub sequence + split.
595 { ISD::UDIV, MVT::v8i32, { 12 } }, // 2*pmuludq sequence + split.
596 { ISD::UREM, MVT::v8i32, { 16 } }, // 2*pmuludq+mul+sub sequence + split.
597 };
598
599 // XOP has faster vXi8 shifts.
600 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasAVX() &&
601 (!ST->hasXOP() || LT.second.getScalarSizeInBits() != 8))
602 if (const auto *Entry =
603 CostTableLookup(AVXUniformConstCostTable, ISD, LT.second))
604 if (auto KindCost = Entry->Cost[CostKind])
605 return LT.first * *KindCost;
606
607 static const CostKindTblEntry SSE2UniformConstCostTable[] = {
608 { ISD::SHL, MVT::v16i8, { 1, 7, 2, 3 } }, // psllw + pand.
609 { ISD::SRL, MVT::v16i8, { 1, 7, 2, 3 } }, // psrlw + pand.
610 { ISD::SRA, MVT::v16i8, { 3, 9, 5, 6 } }, // psrlw, pand, pxor, psubb.
611
612 { ISD::SHL, MVT::v8i16, { 1, 1, 1, 1 } }, // psllw.
613 { ISD::SRL, MVT::v8i16, { 1, 1, 1, 1 } }, // psrlw.
614 { ISD::SRA, MVT::v8i16, { 1, 1, 1, 1 } }, // psraw.
615
616 { ISD::SHL, MVT::v4i32, { 1, 1, 1, 1 } }, // pslld
617 { ISD::SRL, MVT::v4i32, { 1, 1, 1, 1 } }, // psrld.
618 { ISD::SRA, MVT::v4i32, { 1, 1, 1, 1 } }, // psrad.
619
620 { ISD::SHL, MVT::v2i64, { 1, 1, 1, 1 } }, // psllq.
621 { ISD::SRL, MVT::v2i64, { 1, 1, 1, 1 } }, // psrlq.
622 { ISD::SRA, MVT::v2i64, { 3, 5, 6, 6 } }, // 2 x psrad + shuffle.
623
624 { ISD::SDIV, MVT::v4i32, { 6 } }, // pmuludq sequence
625 { ISD::SREM, MVT::v4i32, { 8 } }, // pmuludq+mul+sub sequence
626 { ISD::UDIV, MVT::v4i32, { 5 } }, // pmuludq sequence
627 { ISD::UREM, MVT::v4i32, { 7 } }, // pmuludq+mul+sub sequence
628 };
629
630 // XOP has faster vXi8 shifts.
631 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasSSE2() &&
632 (!ST->hasXOP() || LT.second.getScalarSizeInBits() != 8))
633 if (const auto *Entry =
634 CostTableLookup(SSE2UniformConstCostTable, ISD, LT.second))
635 if (auto KindCost = Entry->Cost[CostKind])
636 return LT.first * *KindCost;
637
638 static const CostKindTblEntry AVX512BWConstCostTable[] = {
639 { ISD::SDIV, MVT::v64i8, { 14 } }, // 2*ext+2*pmulhw sequence
640 { ISD::SREM, MVT::v64i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
641 { ISD::UDIV, MVT::v64i8, { 14 } }, // 2*ext+2*pmulhw sequence
642 { ISD::UREM, MVT::v64i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
643
644 { ISD::SDIV, MVT::v32i16, { 6 } }, // vpmulhw sequence
645 { ISD::SREM, MVT::v32i16, { 8 } }, // vpmulhw+mul+sub sequence
646 { ISD::UDIV, MVT::v32i16, { 6 } }, // vpmulhuw sequence
647 { ISD::UREM, MVT::v32i16, { 8 } }, // vpmulhuw+mul+sub sequence
648 };
649
650 if (Op2Info.isConstant() && ST->hasBWI())
651 if (const auto *Entry =
652 CostTableLookup(AVX512BWConstCostTable, ISD, LT.second))
653 if (auto KindCost = Entry->Cost[CostKind])
654 return LT.first * *KindCost;
655
656 static const CostKindTblEntry AVX512DQConstCostTable[] = {
657 { ISD::SDIV, MVT::v4i64, { 19 } }, // vpmullq-based MULHS sequence
658 { ISD::SREM, MVT::v4i64, { 21 } }, // vpmullq-based MULHS+mul+sub sequence
659 { ISD::SDIV, MVT::v8i64, { 19 } }, // vpmullq-based MULHS sequence
660 { ISD::SREM, MVT::v8i64, { 21 } }, // vpmullq-based MULHS+mul+sub sequence
661 // The remainder's multiply-back is a single vpmullq with DQ, whereas the
662 // AVX512/AVX2 tables have to charge for another vpmuludq schoolbook.
663 { ISD::UREM, MVT::v4i64, { 24 } }, // MULHU + vpmullq + sub sequence
664 { ISD::UREM, MVT::v8i64, { 24 } }, // MULHU + vpmullq + sub sequence
665 };
666
667 if (Op2Info.isConstant() && ST->hasDQI())
668 if (const auto *Entry =
669 CostTableLookup(AVX512DQConstCostTable, ISD, LT.second))
670 if (auto KindCost = Entry->Cost[CostKind])
671 return LT.first * *KindCost;
672
673 static const CostKindTblEntry AVX512ConstCostTable[] = {
674 { ISD::SDIV, MVT::v64i8, { 28 } }, // 4*ext+4*pmulhw sequence
675 { ISD::SREM, MVT::v64i8, { 32 } }, // 4*ext+4*pmulhw+mul+sub sequence
676 { ISD::UDIV, MVT::v64i8, { 28 } }, // 4*ext+4*pmulhw sequence
677 { ISD::UREM, MVT::v64i8, { 32 } }, // 4*ext+4*pmulhw+mul+sub sequence
678
679 { ISD::SDIV, MVT::v32i16, { 12 } }, // 2*vpmulhw sequence
680 { ISD::SREM, MVT::v32i16, { 16 } }, // 2*vpmulhw+mul+sub sequence
681 { ISD::UDIV, MVT::v32i16, { 12 } }, // 2*vpmulhuw sequence
682 { ISD::UREM, MVT::v32i16, { 16 } }, // 2*vpmulhuw+mul+sub sequence
683
684 { ISD::SDIV, MVT::v16i32, { 15 } }, // vpmuldq sequence
685 { ISD::SREM, MVT::v16i32, { 17 } }, // vpmuldq+mul+sub sequence
686 { ISD::UDIV, MVT::v16i32, { 15 } }, // vpmuludq sequence
687 { ISD::UREM, MVT::v16i32, { 17 } }, // vpmuludq+mul+sub sequence
688
689 { ISD::UDIV, MVT::v8i64, { 22 } }, // vpmuludq-based MULHU sequence
690 { ISD::UREM, MVT::v8i64, { 28 } }, // vpmuludq-based MULHU+mul+sub sequence
691 };
692
693 if (Op2Info.isConstant() && ST->hasAVX512())
694 if (const auto *Entry =
695 CostTableLookup(AVX512ConstCostTable, ISD, LT.second))
696 if (auto KindCost = Entry->Cost[CostKind])
697 return LT.first * *KindCost;
698
699 static const CostKindTblEntry AVX2ConstCostTable[] = {
700 { ISD::SDIV, MVT::v32i8, { 14 } }, // 2*ext+2*pmulhw sequence
701 { ISD::SREM, MVT::v32i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
702 { ISD::UDIV, MVT::v32i8, { 14 } }, // 2*ext+2*pmulhw sequence
703 { ISD::UREM, MVT::v32i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
704
705 { ISD::SDIV, MVT::v16i16, { 6 } }, // vpmulhw sequence
706 { ISD::SREM, MVT::v16i16, { 8 } }, // vpmulhw+mul+sub sequence
707 { ISD::UDIV, MVT::v16i16, { 6 } }, // vpmulhuw sequence
708 { ISD::UREM, MVT::v16i16, { 8 } }, // vpmulhuw+mul+sub sequence
709
710 { ISD::SDIV, MVT::v8i32, { 15 } }, // vpmuldq sequence
711 { ISD::SREM, MVT::v8i32, { 19 } }, // vpmuldq+mul+sub sequence
712 { ISD::UDIV, MVT::v8i32, { 15 } }, // vpmuludq sequence
713 { ISD::UREM, MVT::v8i32, { 19 } }, // vpmuludq+mul+sub sequence
714
715 { ISD::UDIV, MVT::v4i64, { 22 } }, // vpmuludq-based MULHU sequence
716 { ISD::UREM, MVT::v4i64, { 28 } }, // vpmuludq-based MULHU+mul+sub sequence
717 };
718
719 if (Op2Info.isConstant() && ST->hasAVX2())
720 if (const auto *Entry = CostTableLookup(AVX2ConstCostTable, ISD, LT.second))
721 if (auto KindCost = Entry->Cost[CostKind])
722 return LT.first * *KindCost;
723
724 static const CostKindTblEntry AVXConstCostTable[] = {
725 { ISD::SDIV, MVT::v32i8, { 30 } }, // 4*ext+4*pmulhw sequence + split.
726 { ISD::SREM, MVT::v32i8, { 34 } }, // 4*ext+4*pmulhw+mul+sub sequence + split.
727 { ISD::UDIV, MVT::v32i8, { 30 } }, // 4*ext+4*pmulhw sequence + split.
728 { ISD::UREM, MVT::v32i8, { 34 } }, // 4*ext+4*pmulhw+mul+sub sequence + split.
729
730 { ISD::SDIV, MVT::v16i16, { 14 } }, // 2*pmulhw sequence + split.
731 { ISD::SREM, MVT::v16i16, { 18 } }, // 2*pmulhw+mul+sub sequence + split.
732 { ISD::UDIV, MVT::v16i16, { 14 } }, // 2*pmulhuw sequence + split.
733 { ISD::UREM, MVT::v16i16, { 18 } }, // 2*pmulhuw+mul+sub sequence + split.
734
735 { ISD::SDIV, MVT::v8i32, { 32 } }, // vpmuludq sequence
736 { ISD::SREM, MVT::v8i32, { 38 } }, // vpmuludq+mul+sub sequence
737 { ISD::UDIV, MVT::v8i32, { 32 } }, // 2*pmuludq sequence + split.
738 { ISD::UREM, MVT::v8i32, { 42 } }, // 2*pmuludq+mul+sub sequence + split.
739 };
740
741 if (Op2Info.isConstant() && ST->hasAVX())
742 if (const auto *Entry = CostTableLookup(AVXConstCostTable, ISD, LT.second))
743 if (auto KindCost = Entry->Cost[CostKind])
744 return LT.first * *KindCost;
745
746 static const CostKindTblEntry SSE41ConstCostTable[] = {
747 { ISD::SDIV, MVT::v4i32, { 15 } }, // vpmuludq sequence
748 { ISD::SREM, MVT::v4i32, { 20 } }, // vpmuludq+mul+sub sequence
749 };
750
751 if (Op2Info.isConstant() && ST->hasSSE41())
752 if (const auto *Entry =
753 CostTableLookup(SSE41ConstCostTable, ISD, LT.second))
754 if (auto KindCost = Entry->Cost[CostKind])
755 return LT.first * *KindCost;
756
757 static const CostKindTblEntry SSE2ConstCostTable[] = {
758 { ISD::SDIV, MVT::v16i8, { 14 } }, // 2*ext+2*pmulhw sequence
759 { ISD::SREM, MVT::v16i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
760 { ISD::UDIV, MVT::v16i8, { 14 } }, // 2*ext+2*pmulhw sequence
761 { ISD::UREM, MVT::v16i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
762
763 { ISD::SDIV, MVT::v8i16, { 6 } }, // pmulhw sequence
764 { ISD::SREM, MVT::v8i16, { 8 } }, // pmulhw+mul+sub sequence
765 { ISD::UDIV, MVT::v8i16, { 6 } }, // pmulhuw sequence
766 { ISD::UREM, MVT::v8i16, { 8 } }, // pmulhuw+mul+sub sequence
767
768 { ISD::SDIV, MVT::v4i32, { 19 } }, // pmuludq sequence
769 { ISD::SREM, MVT::v4i32, { 24 } }, // pmuludq+mul+sub sequence
770 { ISD::UDIV, MVT::v4i32, { 15 } }, // pmuludq sequence
771 { ISD::UREM, MVT::v4i32, { 20 } }, // pmuludq+mul+sub sequence
772 };
773
774 if (Op2Info.isConstant() && ST->hasSSE2())
775 if (const auto *Entry = CostTableLookup(SSE2ConstCostTable, ISD, LT.second))
776 if (auto KindCost = Entry->Cost[CostKind])
777 return LT.first * *KindCost;
778
779 // rem matches div because the divider returns the remainder for free.
780 static const CostKindTblEntry ScalarVarDivCostTable[] = {
781 { ISD::SDIV, MVT::i8, { 15, 20, 2, 4 } },
782 { ISD::UDIV, MVT::i8, { 15, 20, 2, 4 } },
783 { ISD::SREM, MVT::i8, { 15, 20, 2, 4 } },
784 { ISD::UREM, MVT::i8, { 15, 20, 2, 4 } },
785 { ISD::SDIV, MVT::i16, { 17, 20, 2, 4 } },
786 { ISD::UDIV, MVT::i16, { 17, 20, 2, 4 } },
787 { ISD::SREM, MVT::i16, { 17, 20, 2, 4 } },
788 { ISD::UREM, MVT::i16, { 17, 20, 2, 4 } },
789 { ISD::SDIV, MVT::i32, { 25, 22, 2, 4 } },
790 { ISD::UDIV, MVT::i32, { 25, 22, 2, 4 } },
791 { ISD::SREM, MVT::i32, { 25, 22, 2, 4 } },
792 { ISD::UREM, MVT::i32, { 25, 22, 2, 4 } },
793 { ISD::SDIV, MVT::i64, { 41, 24, 2, 4 } },
794 { ISD::UDIV, MVT::i64, { 41, 24, 2, 4 } },
795 { ISD::SREM, MVT::i64, { 41, 24, 2, 4 } },
796 { ISD::UREM, MVT::i64, { 41, 24, 2, 4 } },
797 };
798
799 if (!LT.second.isVector() && !Op2Info.isConstant())
800 if (const auto *Entry =
801 CostTableLookup(ScalarVarDivCostTable, ISD, LT.second))
802 if (auto KindCost = Entry->Cost[CostKind])
803 return LT.first * *KindCost;
804
805 // Variable divisors lower through a float divide. strictfp needs SAE
806 // rounding which is 512-bit only.
807 bool IsStrictFP =
808 CtxI && CtxI->getFunction()->hasFnAttribute(Attribute::StrictFP);
809 bool IsDivRem = ISD == ISD::UDIV || ISD == ISD::SDIV || ISD == ISD::UREM ||
810 ISD == ISD::SREM;
811 bool VarDivToFP = IsDivRem && !Op2Info.isConstant() &&
812 (!IsStrictFP || ST->useAVX512Regs());
813
814 // i64 needs the qq converts, which are AVX512DQ only. Two tables because the
815 // lowering picks by operand value and not by type.
816 static const CostKindTblEntry AVX512DQExactVarDivCostTable[] = {
817 { ISD::UDIV, MVT::v2i64, { 5 } }, // cvt+divpd sequence
818 { ISD::SDIV, MVT::v2i64, { 5 } },
819 { ISD::UREM, MVT::v2i64, { 5 } },
820 { ISD::SREM, MVT::v2i64, { 5 } },
821 { ISD::UDIV, MVT::v4i64, { 8 } },
822 { ISD::SDIV, MVT::v4i64, { 8 } },
823 { ISD::UREM, MVT::v4i64, { 8 } },
824 { ISD::SREM, MVT::v4i64, { 8 } },
825 { ISD::UDIV, MVT::v8i64, { 16 } },
826 { ISD::SDIV, MVT::v8i64, { 16 } },
827 { ISD::UREM, MVT::v8i64, { 16 } },
828 { ISD::SREM, MVT::v8i64, { 16 } },
829 };
830
831 static const CostKindTblEntry AVX512DQVarDivCostTable[] = {
832 { ISD::UDIV, MVT::v2i64, { 16 } },
833 { ISD::SDIV, MVT::v2i64, { 16 } },
834 { ISD::UREM, MVT::v2i64, { 16 } },
835 { ISD::SREM, MVT::v2i64, { 16 } },
836 { ISD::UDIV, MVT::v4i64, { 16 } },
837 { ISD::SDIV, MVT::v4i64, { 16 } },
838 { ISD::UREM, MVT::v4i64, { 16 } },
839 { ISD::SREM, MVT::v4i64, { 16 } },
840 { ISD::UDIV, MVT::v8i64, { 16 } },
841 { ISD::SDIV, MVT::v8i64, { 18 } },
842 { ISD::UREM, MVT::v8i64, { 16 } },
843 { ISD::SREM, MVT::v8i64, { 18 } },
844 };
845
846 // The DAG combine picks between the two sequences with these same two
847 // queries, so the cost cannot disagree with what codegen emits.
848 bool IsSignedDiv = ISD == ISD::SDIV || ISD == ISD::SREM;
849 auto OperandsFit = [&](unsigned Mantissa) {
850 if (Args.size() != 2 || !CtxI)
851 return false;
852 unsigned EltBits = LT.second.getScalarSizeInBits();
853 const DataLayout &DL = CtxI->getDataLayout();
854 auto Fits = [&](const Value *V) {
855 if (IsSignedDiv)
856 return ComputeNumSignBits(V, DL, /*AC=*/nullptr, CtxI) + Mantissa >
857 EltBits;
858 return computeKnownBits(V, DL, /*AC=*/nullptr, CtxI)
859 .countMaxActiveBits() <= Mantissa;
860 };
861 return Fits(Args[0]) && Fits(Args[1]);
862 };
863
864 // An i32 divide goes through f32 when both operands fit in 24 bits, and
865 // through f64 at twice the vector width when they do not.
866 bool ExactI32 =
867 VarDivToFP && LT.second.getScalarType() == MVT::i32 &&
869
870 if (VarDivToFP && ST->hasDQI() && ST->useAVX512Regs() &&
871 LT.second.getScalarType() == MVT::i64) {
872 bool ExactFPDiv =
874
875 // Only the reciprocal chain multiplies, so only it is vpmullq gated.
876 bool SlowMultiply =
877 !ExactFPDiv && LT.second == MVT::v2i64 && ST->isPMULLQSlow();
878
879 if (!SlowMultiply) {
881 ExactFPDiv ? AVX512DQExactVarDivCostTable : AVX512DQVarDivCostTable;
882 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
883 if (auto KindCost = Entry->Cost[CostKind])
884 return LT.first * *KindCost;
885 }
886 }
887
888 static const CostKindTblEntry AVX512BWVarDivCostTable[] = {
889 { ISD::UDIV, MVT::v16i8, { 10 } }, // unpack+cvt+divps sequence
890 { ISD::SDIV, MVT::v16i8, { 10 } },
891 { ISD::UREM, MVT::v16i8, { 10 } },
892 { ISD::SREM, MVT::v16i8, { 10 } },
893 { ISD::UDIV, MVT::v32i8, { 20 } },
894 { ISD::SDIV, MVT::v32i8, { 20 } },
895 { ISD::UREM, MVT::v32i8, { 20 } },
896 { ISD::SREM, MVT::v32i8, { 20 } },
897 { ISD::UDIV, MVT::v64i8, { 40 } },
898 { ISD::SDIV, MVT::v64i8, { 40 } },
899 { ISD::UREM, MVT::v64i8, { 40 } },
900 { ISD::SREM, MVT::v64i8, { 40 } },
901 { ISD::UDIV, MVT::v8i16, { 5 } },
902 { ISD::SDIV, MVT::v8i16, { 5 } },
903 { ISD::UREM, MVT::v8i16, { 5 } },
904 { ISD::SREM, MVT::v8i16, { 5 } },
905 { ISD::UDIV, MVT::v16i16, { 10 } },
906 { ISD::SDIV, MVT::v16i16, { 10 } },
907 { ISD::UREM, MVT::v16i16, { 10 } },
908 { ISD::SREM, MVT::v16i16, { 10 } },
909 { ISD::UDIV, MVT::v32i16, { 20 } },
910 { ISD::SDIV, MVT::v32i16, { 20 } },
911 { ISD::UREM, MVT::v32i16, { 20 } },
912 { ISD::SREM, MVT::v32i16, { 20 } },
913 { ISD::UDIV, MVT::v4i32, { 8 } }, // cvt+divpd sequence
914 { ISD::SDIV, MVT::v4i32, { 8 } },
915 { ISD::UREM, MVT::v4i32, { 8 } },
916 { ISD::SREM, MVT::v4i32, { 8 } },
917 { ISD::UDIV, MVT::v8i32, { 16 } },
918 { ISD::SDIV, MVT::v8i32, { 16 } },
919 { ISD::UREM, MVT::v8i32, { 16 } },
920 { ISD::SREM, MVT::v8i32, { 16 } },
921 { ISD::UDIV, MVT::v16i32, { 32 } },
922 { ISD::SDIV, MVT::v16i32, { 32 } },
923 { ISD::UREM, MVT::v16i32, { 32 } },
924 { ISD::SREM, MVT::v16i32, { 32 } },
925 };
926
927 static const CostKindTblEntry AVX512BWExactVarDivCostTable[] = {
928 { ISD::UDIV, MVT::v4i32, { 3 } }, // cvt+divps sequence
929 { ISD::SDIV, MVT::v4i32, { 3 } },
930 { ISD::UREM, MVT::v4i32, { 3 } },
931 { ISD::SREM, MVT::v4i32, { 3 } },
932 { ISD::UDIV, MVT::v8i32, { 5 } },
933 { ISD::SDIV, MVT::v8i32, { 5 } },
934 { ISD::UREM, MVT::v8i32, { 5 } },
935 { ISD::SREM, MVT::v8i32, { 5 } },
936 { ISD::UDIV, MVT::v16i32, { 10 } },
937 { ISD::SDIV, MVT::v16i32, { 10 } },
938 { ISD::UREM, MVT::v16i32, { 10 } },
939 { ISD::SREM, MVT::v16i32, { 10 } },
940 };
941
942 if (VarDivToFP && ST->hasBWI()) {
943 ArrayRef<CostKindTblEntry> Tbl = AVX512BWVarDivCostTable;
944 if (ExactI32)
945 Tbl = AVX512BWExactVarDivCostTable;
946 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
947 if (auto KindCost = Entry->Cost[CostKind])
948 return LT.first * *KindCost;
949 }
950
951 static const CostKindTblEntry AVX512VarDivCostTable[] = {
952 { ISD::UDIV, MVT::v16i8, { 14 } }, // unpack+cvt+divps sequence
953 { ISD::SDIV, MVT::v16i8, { 14 } },
954 { ISD::UREM, MVT::v16i8, { 14 } },
955 { ISD::SREM, MVT::v16i8, { 14 } },
956 { ISD::UDIV, MVT::v32i8, { 28 } },
957 { ISD::SDIV, MVT::v32i8, { 28 } },
958 { ISD::UREM, MVT::v32i8, { 28 } },
959 { ISD::SREM, MVT::v32i8, { 28 } },
960 { ISD::UDIV, MVT::v64i8, { 56 } },
961 { ISD::SDIV, MVT::v64i8, { 56 } },
962 { ISD::UREM, MVT::v64i8, { 56 } },
963 { ISD::SREM, MVT::v64i8, { 56 } },
964 { ISD::UDIV, MVT::v8i16, { 14 } },
965 { ISD::SDIV, MVT::v8i16, { 14 } },
966 { ISD::UREM, MVT::v8i16, { 14 } },
967 { ISD::SREM, MVT::v8i16, { 14 } },
968 { ISD::UDIV, MVT::v16i16, { 14 } },
969 { ISD::SDIV, MVT::v16i16, { 14 } },
970 { ISD::UREM, MVT::v16i16, { 14 } },
971 { ISD::SREM, MVT::v16i16, { 14 } },
972 { ISD::UDIV, MVT::v32i16, { 28 } },
973 { ISD::SDIV, MVT::v32i16, { 28 } },
974 { ISD::UREM, MVT::v32i16, { 28 } },
975 { ISD::SREM, MVT::v32i16, { 28 } },
976 { ISD::UDIV, MVT::v4i32, { 28 } }, // cvt+divpd sequence
977 { ISD::SDIV, MVT::v4i32, { 28 } },
978 { ISD::UREM, MVT::v4i32, { 28 } },
979 { ISD::SREM, MVT::v4i32, { 28 } },
980 { ISD::UDIV, MVT::v8i32, { 28 } },
981 { ISD::SDIV, MVT::v8i32, { 28 } },
982 { ISD::UREM, MVT::v8i32, { 28 } },
983 { ISD::SREM, MVT::v8i32, { 28 } },
984 { ISD::UDIV, MVT::v16i32, { 56 } },
985 { ISD::SDIV, MVT::v16i32, { 56 } },
986 { ISD::UREM, MVT::v16i32, { 56 } },
987 { ISD::SREM, MVT::v16i32, { 56 } },
988 };
989
990 static const CostKindTblEntry AVX512ExactVarDivCostTable[] = {
991 { ISD::UDIV, MVT::v4i32, { 7 } }, // cvt+divps sequence
992 { ISD::SDIV, MVT::v4i32, { 7 } },
993 { ISD::UREM, MVT::v4i32, { 7 } },
994 { ISD::SREM, MVT::v4i32, { 7 } },
995 { ISD::UDIV, MVT::v8i32, { 14 } },
996 { ISD::SDIV, MVT::v8i32, { 14 } },
997 { ISD::UREM, MVT::v8i32, { 14 } },
998 { ISD::SREM, MVT::v8i32, { 14 } },
999 { ISD::UDIV, MVT::v16i32, { 14 } },
1000 { ISD::SDIV, MVT::v16i32, { 14 } },
1001 { ISD::UREM, MVT::v16i32, { 14 } },
1002 { ISD::SREM, MVT::v16i32, { 14 } },
1003 };
1004
1005 if (VarDivToFP && ST->hasAVX512()) {
1006 ArrayRef<CostKindTblEntry> Tbl = AVX512VarDivCostTable;
1007 if (ExactI32)
1008 Tbl = AVX512ExactVarDivCostTable;
1009 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
1010 if (auto KindCost = Entry->Cost[CostKind])
1011 return LT.first * *KindCost;
1012 }
1013
1014 static const CostKindTblEntry AVX2VarDivCostTable[] = {
1015 { ISD::UDIV, MVT::v16i8, { 28 } }, // unpack+cvt+divps sequence
1016 { ISD::SDIV, MVT::v16i8, { 28 } },
1017 { ISD::UREM, MVT::v16i8, { 28 } },
1018 { ISD::SREM, MVT::v16i8, { 28 } },
1019 { ISD::UDIV, MVT::v32i8, { 56 } },
1020 { ISD::SDIV, MVT::v32i8, { 56 } },
1021 { ISD::UREM, MVT::v32i8, { 56 } },
1022 { ISD::SREM, MVT::v32i8, { 56 } },
1023 { ISD::UDIV, MVT::v8i16, { 14 } },
1024 { ISD::SDIV, MVT::v8i16, { 14 } },
1025 { ISD::UREM, MVT::v8i16, { 14 } },
1026 { ISD::SREM, MVT::v8i16, { 14 } },
1027 { ISD::UDIV, MVT::v16i16, { 28 } },
1028 { ISD::SDIV, MVT::v16i16, { 28 } },
1029 { ISD::UREM, MVT::v16i16, { 28 } },
1030 { ISD::SREM, MVT::v16i16, { 28 } },
1031 { ISD::UDIV, MVT::v4i32, { 28 } }, // cvt+divpd sequence
1032 { ISD::SDIV, MVT::v4i32, { 28 } },
1033 { ISD::UREM, MVT::v4i32, { 28 } },
1034 { ISD::SREM, MVT::v4i32, { 28 } },
1035 { ISD::UDIV, MVT::v8i32, { 56 } },
1036 { ISD::SDIV, MVT::v8i32, { 56 } },
1037 { ISD::UREM, MVT::v8i32, { 56 } },
1038 { ISD::SREM, MVT::v8i32, { 56 } },
1039 };
1040
1041 static const CostKindTblEntry AVX2ExactVarDivCostTable[] = {
1042 { ISD::UDIV, MVT::v4i32, { 9 } }, // cvt+divps sequence
1043 { ISD::SDIV, MVT::v4i32, { 8 } },
1044 { ISD::UREM, MVT::v4i32, { 9 } },
1045 { ISD::SREM, MVT::v4i32, { 8 } },
1046 { ISD::UDIV, MVT::v8i32, { 14 } },
1047 { ISD::SDIV, MVT::v8i32, { 14 } },
1048 { ISD::UREM, MVT::v8i32, { 14 } },
1049 { ISD::SREM, MVT::v8i32, { 14 } },
1050 };
1051
1052 if (VarDivToFP && ST->hasAVX2()) {
1053 ArrayRef<CostKindTblEntry> Tbl = AVX2VarDivCostTable;
1054 if (ExactI32)
1055 Tbl = AVX2ExactVarDivCostTable;
1056 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
1057 if (auto KindCost = Entry->Cost[CostKind])
1058 return LT.first * *KindCost;
1059 }
1060
1061 // No unsigned i32 entries below AVX2, where the u32 to f64 converts are
1062 // emulated and the fold stays off.
1063 static const CostKindTblEntry AVX1VarDivCostTable[] = {
1064 { ISD::UDIV, MVT::v16i8, { 56 } }, // unpack+cvt+divps sequence
1065 { ISD::SDIV, MVT::v16i8, { 56 } },
1066 { ISD::UREM, MVT::v16i8, { 56 } },
1067 { ISD::SREM, MVT::v16i8, { 56 } },
1068 { ISD::UDIV, MVT::v32i8, { 112 } },
1069 { ISD::SDIV, MVT::v32i8, { 112 } },
1070 { ISD::UREM, MVT::v32i8, { 112 } },
1071 { ISD::SREM, MVT::v32i8, { 112 } },
1072 { ISD::UDIV, MVT::v8i16, { 28 } },
1073 { ISD::SDIV, MVT::v8i16, { 28 } },
1074 { ISD::UREM, MVT::v8i16, { 28 } },
1075 { ISD::SREM, MVT::v8i16, { 28 } },
1076 { ISD::UDIV, MVT::v16i16, { 56 } },
1077 { ISD::SDIV, MVT::v16i16, { 56 } },
1078 { ISD::UREM, MVT::v16i16, { 56 } },
1079 { ISD::SREM, MVT::v16i16, { 56 } },
1080 { ISD::SDIV, MVT::v4i32, { 44 } }, // cvt+divpd sequence
1081 { ISD::SREM, MVT::v4i32, { 44 } },
1082 { ISD::SDIV, MVT::v8i32, { 88 } },
1083 { ISD::SREM, MVT::v8i32, { 88 } },
1084 };
1085
1086 static const CostKindTblEntry AVX1ExactVarDivCostTable[] = {
1087 { ISD::SDIV, MVT::v4i32, { 14 } }, // cvt+divps sequence
1088 { ISD::SREM, MVT::v4i32, { 14 } },
1089 { ISD::SDIV, MVT::v8i32, { 28 } },
1090 { ISD::SREM, MVT::v8i32, { 28 } },
1091 };
1092
1093 if (VarDivToFP && ST->hasAVX()) {
1094 ArrayRef<CostKindTblEntry> Tbl = AVX1VarDivCostTable;
1095 if (ExactI32)
1096 Tbl = AVX1ExactVarDivCostTable;
1097 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
1098 if (auto KindCost = Entry->Cost[CostKind])
1099 return LT.first * *KindCost;
1100 }
1101
1102 static const CostKindTblEntry SSE2VarDivCostTable[] = {
1103 { ISD::UDIV, MVT::v16i8, { 56 } }, // unpack+cvt+divps sequence
1104 { ISD::SDIV, MVT::v16i8, { 56 } },
1105 { ISD::UREM, MVT::v16i8, { 56 } },
1106 { ISD::SREM, MVT::v16i8, { 56 } },
1107 { ISD::UDIV, MVT::v8i16, { 28 } },
1108 { ISD::SDIV, MVT::v8i16, { 28 } },
1109 { ISD::UREM, MVT::v8i16, { 28 } },
1110 { ISD::SREM, MVT::v8i16, { 28 } },
1111 { ISD::SDIV, MVT::v4i32, { 44 } }, // cvt+divpd sequence
1112 { ISD::SREM, MVT::v4i32, { 44 } },
1113 };
1114
1115 static const CostKindTblEntry SSE2ExactVarDivCostTable[] = {
1116 { ISD::SDIV, MVT::v4i32, { 14 } }, // cvt+divps sequence
1117 { ISD::SREM, MVT::v4i32, { 14 } },
1118 };
1119
1120 if (VarDivToFP && ST->hasSSE2()) {
1121 ArrayRef<CostKindTblEntry> Tbl = SSE2VarDivCostTable;
1122 if (ExactI32)
1123 Tbl = SSE2ExactVarDivCostTable;
1124 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
1125 if (auto KindCost = Entry->Cost[CostKind])
1126 return LT.first * *KindCost;
1127 }
1128
1129 static const CostKindTblEntry AVX512BWUniformCostTable[] = {
1130 { ISD::SHL, MVT::v16i8, { 3, 5, 5, 7 } }, // psllw + pand.
1131 { ISD::SRL, MVT::v16i8, { 3,10, 5, 8 } }, // psrlw + pand.
1132 { ISD::SRA, MVT::v16i8, { 4,12, 8,12 } }, // psrlw, pand, pxor, psubb.
1133 { ISD::SHL, MVT::v32i8, { 4, 7, 6, 8 } }, // psllw + pand.
1134 { ISD::SRL, MVT::v32i8, { 4, 8, 7, 9 } }, // psrlw + pand.
1135 { ISD::SRA, MVT::v32i8, { 5,10,10,13 } }, // psrlw, pand, pxor, psubb.
1136 { ISD::SHL, MVT::v64i8, { 4, 7, 6, 8 } }, // psllw + pand.
1137 { ISD::SRL, MVT::v64i8, { 4, 8, 7,10 } }, // psrlw + pand.
1138 { ISD::SRA, MVT::v64i8, { 5,10,10,15 } }, // psrlw, pand, pxor, psubb.
1139
1140 { ISD::SHL, MVT::v32i16, { 2, 4, 2, 3 } }, // psllw
1141 { ISD::SRL, MVT::v32i16, { 2, 4, 2, 3 } }, // psrlw
1142 { ISD::SRA, MVT::v32i16, { 2, 4, 2, 3 } }, // psrqw
1143 };
1144
1145 if (ST->hasBWI() && Op2Info.isUniform())
1146 if (const auto *Entry =
1147 CostTableLookup(AVX512BWUniformCostTable, ISD, LT.second))
1148 if (auto KindCost = Entry->Cost[CostKind])
1149 return LT.first * *KindCost;
1150
1151 static const CostKindTblEntry AVX512UniformCostTable[] = {
1152 { ISD::SHL, MVT::v32i16, { 5,10, 5, 7 } }, // psllw + split.
1153 { ISD::SRL, MVT::v32i16, { 5,10, 5, 7 } }, // psrlw + split.
1154 { ISD::SRA, MVT::v32i16, { 5,10, 5, 7 } }, // psraw + split.
1155
1156 { ISD::SHL, MVT::v16i32, { 2, 4, 2, 3 } }, // pslld
1157 { ISD::SRL, MVT::v16i32, { 2, 4, 2, 3 } }, // psrld
1158 { ISD::SRA, MVT::v16i32, { 2, 4, 2, 3 } }, // psrad
1159
1160 { ISD::SRA, MVT::v2i64, { 1, 2, 1, 2 } }, // psraq
1161 { ISD::SHL, MVT::v4i64, { 1, 4, 1, 2 } }, // psllq
1162 { ISD::SRL, MVT::v4i64, { 1, 4, 1, 2 } }, // psrlq
1163 { ISD::SRA, MVT::v4i64, { 1, 4, 1, 2 } }, // psraq
1164 { ISD::SHL, MVT::v8i64, { 1, 4, 1, 2 } }, // psllq
1165 { ISD::SRL, MVT::v8i64, { 1, 4, 1, 2 } }, // psrlq
1166 { ISD::SRA, MVT::v8i64, { 1, 4, 1, 2 } }, // psraq
1167 };
1168
1169 if (ST->hasAVX512() && Op2Info.isUniform())
1170 if (const auto *Entry =
1171 CostTableLookup(AVX512UniformCostTable, ISD, LT.second))
1172 if (auto KindCost = Entry->Cost[CostKind])
1173 return LT.first * *KindCost;
1174
1175 static const CostKindTblEntry AVX2UniformCostTable[] = {
1176 // Uniform splats are cheaper for the following instructions.
1177 { ISD::SHL, MVT::v16i8, { 3, 5, 5, 7 } }, // psllw + pand.
1178 { ISD::SRL, MVT::v16i8, { 3, 9, 5, 8 } }, // psrlw + pand.
1179 { ISD::SRA, MVT::v16i8, { 4, 5, 9,13 } }, // psrlw, pand, pxor, psubb.
1180 { ISD::SHL, MVT::v32i8, { 4, 7, 6, 8 } }, // psllw + pand.
1181 { ISD::SRL, MVT::v32i8, { 4, 8, 7, 9 } }, // psrlw + pand.
1182 { ISD::SRA, MVT::v32i8, { 6, 9,11,16 } }, // psrlw, pand, pxor, psubb.
1183
1184 { ISD::SHL, MVT::v8i16, { 1, 2, 1, 2 } }, // psllw.
1185 { ISD::SRL, MVT::v8i16, { 1, 2, 1, 2 } }, // psrlw.
1186 { ISD::SRA, MVT::v8i16, { 1, 2, 1, 2 } }, // psraw.
1187 { ISD::SHL, MVT::v16i16, { 2, 4, 2, 3 } }, // psllw.
1188 { ISD::SRL, MVT::v16i16, { 2, 4, 2, 3 } }, // psrlw.
1189 { ISD::SRA, MVT::v16i16, { 2, 4, 2, 3 } }, // psraw.
1190
1191 { ISD::SHL, MVT::v4i32, { 1, 2, 1, 2 } }, // pslld
1192 { ISD::SRL, MVT::v4i32, { 1, 2, 1, 2 } }, // psrld
1193 { ISD::SRA, MVT::v4i32, { 1, 2, 1, 2 } }, // psrad
1194 { ISD::SHL, MVT::v8i32, { 2, 4, 2, 3 } }, // pslld
1195 { ISD::SRL, MVT::v8i32, { 2, 4, 2, 3 } }, // psrld
1196 { ISD::SRA, MVT::v8i32, { 2, 4, 2, 3 } }, // psrad
1197
1198 { ISD::SHL, MVT::v2i64, { 1, 2, 1, 2 } }, // psllq
1199 { ISD::SRL, MVT::v2i64, { 1, 2, 1, 2 } }, // psrlq
1200 { ISD::SRA, MVT::v2i64, { 2, 4, 5, 7 } }, // 2 x psrad + shuffle.
1201 { ISD::SHL, MVT::v4i64, { 2, 4, 1, 2 } }, // psllq
1202 { ISD::SRL, MVT::v4i64, { 2, 4, 1, 2 } }, // psrlq
1203 { ISD::SRA, MVT::v4i64, { 4, 6, 5, 9 } }, // 2 x psrad + shuffle.
1204 };
1205
1206 if (ST->hasAVX2() && Op2Info.isUniform())
1207 if (const auto *Entry =
1208 CostTableLookup(AVX2UniformCostTable, ISD, LT.second))
1209 if (auto KindCost = Entry->Cost[CostKind])
1210 return LT.first * *KindCost;
1211
1212 static const CostKindTblEntry AVXUniformCostTable[] = {
1213 { ISD::SHL, MVT::v16i8, { 4, 4, 6, 8 } }, // psllw + pand.
1214 { ISD::SRL, MVT::v16i8, { 4, 8, 5, 8 } }, // psrlw + pand.
1215 { ISD::SRA, MVT::v16i8, { 6, 6, 9,13 } }, // psrlw, pand, pxor, psubb.
1216 { ISD::SHL, MVT::v32i8, { 7, 8,11,14 } }, // psllw + pand + split.
1217 { ISD::SRL, MVT::v32i8, { 7, 9,10,14 } }, // psrlw + pand + split.
1218 { ISD::SRA, MVT::v32i8, { 10,11,16,21 } }, // psrlw, pand, pxor, psubb + split.
1219
1220 { ISD::SHL, MVT::v8i16, { 1, 3, 1, 2 } }, // psllw.
1221 { ISD::SRL, MVT::v8i16, { 1, 3, 1, 2 } }, // psrlw.
1222 { ISD::SRA, MVT::v8i16, { 1, 3, 1, 2 } }, // psraw.
1223 { ISD::SHL, MVT::v16i16, { 3, 7, 5, 7 } }, // psllw + split.
1224 { ISD::SRL, MVT::v16i16, { 3, 7, 5, 7 } }, // psrlw + split.
1225 { ISD::SRA, MVT::v16i16, { 3, 7, 5, 7 } }, // psraw + split.
1226
1227 { ISD::SHL, MVT::v4i32, { 1, 3, 1, 2 } }, // pslld.
1228 { ISD::SRL, MVT::v4i32, { 1, 3, 1, 2 } }, // psrld.
1229 { ISD::SRA, MVT::v4i32, { 1, 3, 1, 2 } }, // psrad.
1230 { ISD::SHL, MVT::v8i32, { 3, 7, 5, 7 } }, // pslld + split.
1231 { ISD::SRL, MVT::v8i32, { 3, 7, 5, 7 } }, // psrld + split.
1232 { ISD::SRA, MVT::v8i32, { 3, 7, 5, 7 } }, // psrad + split.
1233
1234 { ISD::SHL, MVT::v2i64, { 1, 3, 1, 2 } }, // psllq.
1235 { ISD::SRL, MVT::v2i64, { 1, 3, 1, 2 } }, // psrlq.
1236 { ISD::SRA, MVT::v2i64, { 3, 4, 5, 7 } }, // 2 x psrad + shuffle.
1237 { ISD::SHL, MVT::v4i64, { 3, 7, 4, 6 } }, // psllq + split.
1238 { ISD::SRL, MVT::v4i64, { 3, 7, 4, 6 } }, // psrlq + split.
1239 { ISD::SRA, MVT::v4i64, { 6, 7,10,13 } }, // 2 x (2 x psrad + shuffle) + split.
1240 };
1241
1242 // XOP has faster vXi8 shifts.
1243 if (ST->hasAVX() && Op2Info.isUniform() &&
1244 (!ST->hasXOP() || LT.second.getScalarSizeInBits() != 8))
1245 if (const auto *Entry =
1246 CostTableLookup(AVXUniformCostTable, ISD, LT.second))
1247 if (auto KindCost = Entry->Cost[CostKind])
1248 return LT.first * *KindCost;
1249
1250 static const CostKindTblEntry SSE2UniformCostTable[] = {
1251 // Uniform splats are cheaper for the following instructions.
1252 { ISD::SHL, MVT::v16i8, { 9, 10, 6, 9 } }, // psllw + pand.
1253 { ISD::SRL, MVT::v16i8, { 9, 13, 5, 9 } }, // psrlw + pand.
1254 { ISD::SRA, MVT::v16i8, { 11, 15, 9,13 } }, // pcmpgtb sequence.
1255
1256 { ISD::SHL, MVT::v8i16, { 2, 2, 1, 2 } }, // psllw.
1257 { ISD::SRL, MVT::v8i16, { 2, 2, 1, 2 } }, // psrlw.
1258 { ISD::SRA, MVT::v8i16, { 2, 2, 1, 2 } }, // psraw.
1259
1260 { ISD::SHL, MVT::v4i32, { 2, 2, 1, 2 } }, // pslld
1261 { ISD::SRL, MVT::v4i32, { 2, 2, 1, 2 } }, // psrld.
1262 { ISD::SRA, MVT::v4i32, { 2, 2, 1, 2 } }, // psrad.
1263
1264 { ISD::SHL, MVT::v2i64, { 2, 2, 1, 2 } }, // psllq.
1265 { ISD::SRL, MVT::v2i64, { 2, 2, 1, 2 } }, // psrlq.
1266 { ISD::SRA, MVT::v2i64, { 5, 9, 5, 7 } }, // 2*psrlq + xor + sub.
1267 };
1268
1269 if (ST->hasSSE2() && Op2Info.isUniform() &&
1270 (!ST->hasXOP() || LT.second.getScalarSizeInBits() != 8))
1271 if (const auto *Entry =
1272 CostTableLookup(SSE2UniformCostTable, ISD, LT.second))
1273 if (auto KindCost = Entry->Cost[CostKind])
1274 return LT.first * *KindCost;
1275
1276 static const CostKindTblEntry AVX512DQCostTable[] = {
1277 { ISD::MUL, MVT::v2i64, { 2, 15, 1, 3 } }, // pmullq
1278 { ISD::MUL, MVT::v4i64, { 2, 15, 1, 3 } }, // pmullq
1279 { ISD::MUL, MVT::v8i64, { 3, 15, 1, 3 } } // pmullq
1280 };
1281
1282 // Look for AVX512DQ lowering tricks for custom cases.
1283 if (ST->hasDQI())
1284 if (const auto *Entry = CostTableLookup(AVX512DQCostTable, ISD, LT.second))
1285 if (auto KindCost = Entry->Cost[CostKind])
1286 return LT.first * *KindCost;
1287
1288 static const CostKindTblEntry AVX512BWCostTable[] = {
1289 { ISD::SHL, MVT::v16i8, { 4, 8, 4, 5 } }, // extend/vpsllvw/pack sequence.
1290 { ISD::SRL, MVT::v16i8, { 4, 8, 4, 5 } }, // extend/vpsrlvw/pack sequence.
1291 { ISD::SRA, MVT::v16i8, { 4, 8, 4, 5 } }, // extend/vpsravw/pack sequence.
1292 { ISD::SHL, MVT::v32i8, { 4, 23,11,16 } }, // extend/vpsllvw/pack sequence.
1293 { ISD::SRL, MVT::v32i8, { 4, 30,12,18 } }, // extend/vpsrlvw/pack sequence.
1294 { ISD::SRA, MVT::v32i8, { 6, 13,24,30 } }, // extend/vpsravw/pack sequence.
1295 { ISD::SHL, MVT::v64i8, { 6, 19,13,15 } }, // extend/vpsllvw/pack sequence.
1296 { ISD::SRL, MVT::v64i8, { 7, 27,15,18 } }, // extend/vpsrlvw/pack sequence.
1297 { ISD::SRA, MVT::v64i8, { 15, 15,30,30 } }, // extend/vpsravw/pack sequence.
1298
1299 { ISD::SHL, MVT::v8i16, { 1, 1, 1, 1 } }, // vpsllvw
1300 { ISD::SRL, MVT::v8i16, { 1, 1, 1, 1 } }, // vpsrlvw
1301 { ISD::SRA, MVT::v8i16, { 1, 1, 1, 1 } }, // vpsravw
1302 { ISD::SHL, MVT::v16i16, { 1, 1, 1, 1 } }, // vpsllvw
1303 { ISD::SRL, MVT::v16i16, { 1, 1, 1, 1 } }, // vpsrlvw
1304 { ISD::SRA, MVT::v16i16, { 1, 1, 1, 1 } }, // vpsravw
1305 { ISD::SHL, MVT::v32i16, { 1, 1, 1, 1 } }, // vpsllvw
1306 { ISD::SRL, MVT::v32i16, { 1, 1, 1, 1 } }, // vpsrlvw
1307 { ISD::SRA, MVT::v32i16, { 1, 1, 1, 1 } }, // vpsravw
1308
1309 { ISD::ADD, MVT::v64i8, { 1, 1, 1, 1 } }, // paddb
1310 { ISD::ADD, MVT::v32i16, { 1, 1, 1, 1 } }, // paddw
1311
1312 { ISD::ADD, MVT::v32i8, { 1, 1, 1, 1 } }, // paddb
1313 { ISD::ADD, MVT::v16i16, { 1, 1, 1, 1 } }, // paddw
1314 { ISD::ADD, MVT::v8i32, { 1, 1, 1, 1 } }, // paddd
1315 { ISD::ADD, MVT::v4i64, { 1, 1, 1, 1 } }, // paddq
1316
1317 { ISD::SUB, MVT::v64i8, { 1, 1, 1, 1 } }, // psubb
1318 { ISD::SUB, MVT::v32i16, { 1, 1, 1, 1 } }, // psubw
1319
1320 { ISD::MUL, MVT::v16i8, { 4, 12, 4, 5 } }, // extend/pmullw/trunc
1321 { ISD::MUL, MVT::v32i8, { 3, 10, 7,10 } }, // pmaddubsw
1322 { ISD::MUL, MVT::v64i8, { 3, 11, 7,10 } }, // pmaddubsw
1323 { ISD::MUL, MVT::v32i16, { 1, 5, 1, 1 } }, // pmullw
1324
1325 { ISD::SUB, MVT::v32i8, { 1, 1, 1, 1 } }, // psubb
1326 { ISD::SUB, MVT::v16i16, { 1, 1, 1, 1 } }, // psubw
1327 { ISD::SUB, MVT::v8i32, { 1, 1, 1, 1 } }, // psubd
1328 { ISD::SUB, MVT::v4i64, { 1, 1, 1, 1 } }, // psubq
1329 };
1330
1331 // Look for AVX512BW lowering tricks for custom cases.
1332 if (ST->hasBWI())
1333 if (const auto *Entry = CostTableLookup(AVX512BWCostTable, ISD, LT.second))
1334 if (auto KindCost = Entry->Cost[CostKind])
1335 return LT.first * *KindCost;
1336
1337 static const CostKindTblEntry AVX512CostTable[] = {
1338 { ISD::SHL, MVT::v64i8, { 15, 19,27,33 } }, // vpblendv+split sequence.
1339 { ISD::SRL, MVT::v64i8, { 15, 19,30,36 } }, // vpblendv+split sequence.
1340 { ISD::SRA, MVT::v64i8, { 37, 37,51,63 } }, // vpblendv+split sequence.
1341
1342 { ISD::SHL, MVT::v32i16, { 11, 16,11,15 } }, // 2*extend/vpsrlvd/pack sequence.
1343 { ISD::SRL, MVT::v32i16, { 11, 16,11,15 } }, // 2*extend/vpsrlvd/pack sequence.
1344 { ISD::SRA, MVT::v32i16, { 11, 16,11,15 } }, // 2*extend/vpsravd/pack sequence.
1345
1346 { ISD::SHL, MVT::v4i32, { 1, 1, 1, 1 } },
1347 { ISD::SRL, MVT::v4i32, { 1, 1, 1, 1 } },
1348 { ISD::SRA, MVT::v4i32, { 1, 1, 1, 1 } },
1349 { ISD::SHL, MVT::v8i32, { 1, 1, 1, 1 } },
1350 { ISD::SRL, MVT::v8i32, { 1, 1, 1, 1 } },
1351 { ISD::SRA, MVT::v8i32, { 1, 1, 1, 1 } },
1352 { ISD::SHL, MVT::v16i32, { 1, 1, 1, 1 } },
1353 { ISD::SRL, MVT::v16i32, { 1, 1, 1, 1 } },
1354 { ISD::SRA, MVT::v16i32, { 1, 1, 1, 1 } },
1355
1356 { ISD::SHL, MVT::v2i64, { 1, 1, 1, 1 } },
1357 { ISD::SRL, MVT::v2i64, { 1, 1, 1, 1 } },
1358 { ISD::SRA, MVT::v2i64, { 1, 1, 1, 1 } },
1359 { ISD::SHL, MVT::v4i64, { 1, 1, 1, 1 } },
1360 { ISD::SRL, MVT::v4i64, { 1, 1, 1, 1 } },
1361 { ISD::SRA, MVT::v4i64, { 1, 1, 1, 1 } },
1362 { ISD::SHL, MVT::v8i64, { 1, 1, 1, 1 } },
1363 { ISD::SRL, MVT::v8i64, { 1, 1, 1, 1 } },
1364 { ISD::SRA, MVT::v8i64, { 1, 1, 1, 1 } },
1365
1366 { ISD::ADD, MVT::v64i8, { 3, 7, 5, 5 } }, // 2*paddb + split
1367 { ISD::ADD, MVT::v32i16, { 3, 7, 5, 5 } }, // 2*paddw + split
1368
1369 { ISD::SUB, MVT::v64i8, { 3, 7, 5, 5 } }, // 2*psubb + split
1370 { ISD::SUB, MVT::v32i16, { 3, 7, 5, 5 } }, // 2*psubw + split
1371
1372 { ISD::AND, MVT::v32i8, { 1, 1, 1, 1 } },
1373 { ISD::AND, MVT::v16i16, { 1, 1, 1, 1 } },
1374 { ISD::AND, MVT::v8i32, { 1, 1, 1, 1 } },
1375 { ISD::AND, MVT::v4i64, { 1, 1, 1, 1 } },
1376
1377 { ISD::OR, MVT::v32i8, { 1, 1, 1, 1 } },
1378 { ISD::OR, MVT::v16i16, { 1, 1, 1, 1 } },
1379 { ISD::OR, MVT::v8i32, { 1, 1, 1, 1 } },
1380 { ISD::OR, MVT::v4i64, { 1, 1, 1, 1 } },
1381
1382 { ISD::XOR, MVT::v32i8, { 1, 1, 1, 1 } },
1383 { ISD::XOR, MVT::v16i16, { 1, 1, 1, 1 } },
1384 { ISD::XOR, MVT::v8i32, { 1, 1, 1, 1 } },
1385 { ISD::XOR, MVT::v4i64, { 1, 1, 1, 1 } },
1386
1387 { ISD::MUL, MVT::v16i32, { 1, 10, 1, 2 } }, // pmulld (Skylake from agner.org)
1388 { ISD::MUL, MVT::v8i32, { 1, 10, 1, 2 } }, // pmulld (Skylake from agner.org)
1389 { ISD::MUL, MVT::v4i32, { 1, 10, 1, 2 } }, // pmulld (Skylake from agner.org)
1390 { ISD::MUL, MVT::v8i64, { 6, 9, 8, 8 } }, // 3*pmuludq/3*shift/2*add
1391 { ISD::MUL, MVT::i64, { 1 } }, // Skylake from http://www.agner.org/
1392
1393 { X86ISD::PMULUDQ, MVT::v8i64, { 1, 5, 1, 1 } },
1394
1395 { ISD::FNEG, MVT::v8f64, { 1, 1, 1, 2 } }, // Skylake from http://www.agner.org/
1396 { ISD::FADD, MVT::v8f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1397 { ISD::FADD, MVT::v4f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1398 { ISD::FSUB, MVT::v8f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1399 { ISD::FSUB, MVT::v4f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1400 { ISD::FMUL, MVT::v8f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1401 { ISD::FMUL, MVT::v4f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1402 { ISD::FMUL, MVT::v2f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1403 { ISD::FMUL, MVT::f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1404
1405 { ISD::FDIV, MVT::f64, { 4, 14, 1, 1 } }, // Skylake from http://www.agner.org/
1406 { ISD::FDIV, MVT::v2f64, { 4, 14, 1, 1 } }, // Skylake from http://www.agner.org/
1407 { ISD::FDIV, MVT::v4f64, { 8, 14, 1, 1 } }, // Skylake from http://www.agner.org/
1408 { ISD::FDIV, MVT::v8f64, { 16, 23, 1, 3 } }, // Skylake from http://www.agner.org/
1409
1410 { ISD::FNEG, MVT::v16f32, { 1, 1, 1, 2 } }, // Skylake from http://www.agner.org/
1411 { ISD::FADD, MVT::v16f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1412 { ISD::FADD, MVT::v8f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1413 { ISD::FSUB, MVT::v16f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1414 { ISD::FSUB, MVT::v8f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1415 { ISD::FMUL, MVT::v16f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1416 { ISD::FMUL, MVT::v8f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1417 { ISD::FMUL, MVT::v4f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1418 { ISD::FMUL, MVT::f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1419
1420 { ISD::FDIV, MVT::f32, { 3, 11, 1, 1 } }, // Skylake from http://www.agner.org/
1421 { ISD::FDIV, MVT::v4f32, { 3, 11, 1, 1 } }, // Skylake from http://www.agner.org/
1422 { ISD::FDIV, MVT::v8f32, { 5, 11, 1, 1 } }, // Skylake from http://www.agner.org/
1423 { ISD::FDIV, MVT::v16f32, { 10, 18, 1, 3 } }, // Skylake from http://www.agner.org/
1424 };
1425
1426 if (ST->hasAVX512())
1427 if (const auto *Entry = CostTableLookup(AVX512CostTable, ISD, LT.second))
1428 if (auto KindCost = Entry->Cost[CostKind])
1429 return LT.first * *KindCost;
1430
1431 static const CostKindTblEntry AVX2ShiftCostTable[] = {
1432 // Shifts on vXi64/vXi32 on AVX2 is legal even though we declare to
1433 // customize them to detect the cases where shift amount is a scalar one.
1434 { ISD::SHL, MVT::v4i32, { 2, 3, 1, 3 } }, // vpsllvd (Haswell from agner.org)
1435 { ISD::SRL, MVT::v4i32, { 2, 3, 1, 3 } }, // vpsrlvd (Haswell from agner.org)
1436 { ISD::SRA, MVT::v4i32, { 2, 3, 1, 3 } }, // vpsravd (Haswell from agner.org)
1437 { ISD::SHL, MVT::v8i32, { 4, 4, 1, 3 } }, // vpsllvd (Haswell from agner.org)
1438 { ISD::SRL, MVT::v8i32, { 4, 4, 1, 3 } }, // vpsrlvd (Haswell from agner.org)
1439 { ISD::SRA, MVT::v8i32, { 4, 4, 1, 3 } }, // vpsravd (Haswell from agner.org)
1440 { ISD::SHL, MVT::v2i64, { 2, 3, 1, 1 } }, // vpsllvq (Haswell from agner.org)
1441 { ISD::SRL, MVT::v2i64, { 2, 3, 1, 1 } }, // vpsrlvq (Haswell from agner.org)
1442 { ISD::SHL, MVT::v4i64, { 4, 4, 1, 2 } }, // vpsllvq (Haswell from agner.org)
1443 { ISD::SRL, MVT::v4i64, { 4, 4, 1, 2 } }, // vpsrlvq (Haswell from agner.org)
1444 };
1445
1446 if (ST->hasAVX512()) {
1447 if (ISD == ISD::SHL && LT.second == MVT::v32i16 && Op2Info.isConstant())
1448 // On AVX512, a packed v32i16 shift left by a constant build_vector
1449 // is lowered into a vector multiply (vpmullw).
1450 return getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
1451 Op1Info.getNoProps(), Op2Info.getNoProps());
1452 }
1453
1454 // Look for AVX2 lowering tricks (XOP is always better at v4i32 shifts).
1455 if (ST->hasAVX2() && !(ST->hasXOP() && LT.second == MVT::v4i32)) {
1456 if (ISD == ISD::SHL && LT.second == MVT::v16i16 &&
1457 Op2Info.isConstant())
1458 // On AVX2, a packed v16i16 shift left by a constant build_vector
1459 // is lowered into a vector multiply (vpmullw).
1460 return getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
1461 Op1Info.getNoProps(), Op2Info.getNoProps());
1462
1463 if (const auto *Entry = CostTableLookup(AVX2ShiftCostTable, ISD, LT.second))
1464 if (auto KindCost = Entry->Cost[CostKind])
1465 return LT.first * *KindCost;
1466 }
1467
1468 static const CostKindTblEntry XOPShiftCostTable[] = {
1469 // 128bit shifts take 1cy, but right shifts require negation beforehand.
1470 { ISD::SHL, MVT::v16i8, { 1, 3, 1, 1 } },
1471 { ISD::SRL, MVT::v16i8, { 2, 3, 1, 1 } },
1472 { ISD::SRA, MVT::v16i8, { 2, 3, 1, 1 } },
1473 { ISD::SHL, MVT::v8i16, { 1, 3, 1, 1 } },
1474 { ISD::SRL, MVT::v8i16, { 2, 3, 1, 1 } },
1475 { ISD::SRA, MVT::v8i16, { 2, 3, 1, 1 } },
1476 { ISD::SHL, MVT::v4i32, { 1, 3, 1, 1 } },
1477 { ISD::SRL, MVT::v4i32, { 2, 3, 1, 1 } },
1478 { ISD::SRA, MVT::v4i32, { 2, 3, 1, 1 } },
1479 { ISD::SHL, MVT::v2i64, { 1, 3, 1, 1 } },
1480 { ISD::SRL, MVT::v2i64, { 2, 3, 1, 1 } },
1481 { ISD::SRA, MVT::v2i64, { 2, 3, 1, 1 } },
1482 // 256bit shifts require splitting if AVX2 didn't catch them above.
1483 { ISD::SHL, MVT::v32i8, { 4, 7, 5, 6 } },
1484 { ISD::SRL, MVT::v32i8, { 6, 7, 5, 6 } },
1485 { ISD::SRA, MVT::v32i8, { 6, 7, 5, 6 } },
1486 { ISD::SHL, MVT::v16i16, { 4, 7, 5, 6 } },
1487 { ISD::SRL, MVT::v16i16, { 6, 7, 5, 6 } },
1488 { ISD::SRA, MVT::v16i16, { 6, 7, 5, 6 } },
1489 { ISD::SHL, MVT::v8i32, { 4, 7, 5, 6 } },
1490 { ISD::SRL, MVT::v8i32, { 6, 7, 5, 6 } },
1491 { ISD::SRA, MVT::v8i32, { 6, 7, 5, 6 } },
1492 { ISD::SHL, MVT::v4i64, { 4, 7, 5, 6 } },
1493 { ISD::SRL, MVT::v4i64, { 6, 7, 5, 6 } },
1494 { ISD::SRA, MVT::v4i64, { 6, 7, 5, 6 } },
1495 };
1496
1497 // Look for XOP lowering tricks.
1498 if (ST->hasXOP()) {
1499 // If the right shift is constant then we'll fold the negation so
1500 // it's as cheap as a left shift.
1501 int ShiftISD = ISD;
1502 if ((ShiftISD == ISD::SRL || ShiftISD == ISD::SRA) && Op2Info.isConstant())
1503 ShiftISD = ISD::SHL;
1504 if (const auto *Entry =
1505 CostTableLookup(XOPShiftCostTable, ShiftISD, LT.second))
1506 if (auto KindCost = Entry->Cost[CostKind])
1507 return LT.first * *KindCost;
1508 }
1509
1510 if (ISD == ISD::SHL && !Op2Info.isUniform() && Op2Info.isConstant()) {
1511 MVT VT = LT.second;
1512 // Vector shift left by non uniform constant can be lowered
1513 // into vector multiply.
1514 if (((VT == MVT::v8i16 || VT == MVT::v4i32) && ST->hasSSE2()) ||
1515 ((VT == MVT::v16i16 || VT == MVT::v8i32) && ST->hasAVX()))
1516 ISD = ISD::MUL;
1517 }
1518
1519 static const CostKindTblEntry GLMCostTable[] = {
1520 { ISD::FDIV, MVT::f32, { 18, 19, 1, 1 } }, // divss
1521 { ISD::FDIV, MVT::v4f32, { 35, 36, 1, 1 } }, // divps
1522 { ISD::FDIV, MVT::f64, { 33, 34, 1, 1 } }, // divsd
1523 { ISD::FDIV, MVT::v2f64, { 65, 66, 1, 1 } }, // divpd
1524 };
1525
1526 if (ST->useGLMDivSqrtCosts())
1527 if (const auto *Entry = CostTableLookup(GLMCostTable, ISD, LT.second))
1528 if (auto KindCost = Entry->Cost[CostKind])
1529 return LT.first * *KindCost;
1530
1531 static const CostKindTblEntry SLMCostTable[] = {
1532 { ISD::MUL, MVT::v4i32, { 11, 11, 1, 7 } }, // pmulld
1533 { ISD::MUL, MVT::v8i16, { 2, 5, 1, 1 } }, // pmullw
1534 { ISD::FMUL, MVT::f64, { 2, 5, 1, 1 } }, // mulsd
1535 { ISD::FMUL, MVT::f32, { 1, 4, 1, 1 } }, // mulss
1536 { ISD::FMUL, MVT::v2f64, { 4, 7, 1, 1 } }, // mulpd
1537 { ISD::FMUL, MVT::v4f32, { 2, 5, 1, 1 } }, // mulps
1538 { ISD::FDIV, MVT::f32, { 17, 19, 1, 1 } }, // divss
1539 { ISD::FDIV, MVT::v4f32, { 39, 39, 1, 6 } }, // divps
1540 { ISD::FDIV, MVT::f64, { 32, 34, 1, 1 } }, // divsd
1541 { ISD::FDIV, MVT::v2f64, { 69, 69, 1, 6 } }, // divpd
1542 { ISD::FADD, MVT::v2f64, { 2, 4, 1, 1 } }, // addpd
1543 { ISD::FSUB, MVT::v2f64, { 2, 4, 1, 1 } }, // subpd
1544 // v2i64/v4i64 mul is custom lowered as a series of long:
1545 // multiplies(3), shifts(3) and adds(2)
1546 // slm muldq version throughput is 2 and addq throughput 4
1547 // thus: 3X2 (muldq throughput) + 3X1 (shift throughput) +
1548 // 3X4 (addq throughput) = 17
1549 { ISD::MUL, MVT::v2i64, { 17, 22, 9, 9 } },
1550 // slm addq\subq throughput is 4
1551 { ISD::ADD, MVT::v2i64, { 4, 2, 1, 2 } },
1552 { ISD::SUB, MVT::v2i64, { 4, 2, 1, 2 } },
1553 };
1554
1555 if (ST->useSLMArithCosts())
1556 if (const auto *Entry = CostTableLookup(SLMCostTable, ISD, LT.second))
1557 if (auto KindCost = Entry->Cost[CostKind])
1558 return LT.first * *KindCost;
1559
1560 static const CostKindTblEntry AVX2CostTable[] = {
1561 { ISD::SHL, MVT::v16i8, { 6, 21,11,16 } }, // vpblendvb sequence.
1562 { ISD::SHL, MVT::v32i8, { 6, 23,11,22 } }, // vpblendvb sequence.
1563 { ISD::SHL, MVT::v8i16, { 5, 18, 5,10 } }, // extend/vpsrlvd/pack sequence.
1564 { ISD::SHL, MVT::v16i16, { 8, 10,10,14 } }, // extend/vpsrlvd/pack sequence.
1565
1566 { ISD::SRL, MVT::v16i8, { 6, 27,12,18 } }, // vpblendvb sequence.
1567 { ISD::SRL, MVT::v32i8, { 8, 30,12,24 } }, // vpblendvb sequence.
1568 { ISD::SRL, MVT::v8i16, { 5, 11, 5,10 } }, // extend/vpsrlvd/pack sequence.
1569 { ISD::SRL, MVT::v16i16, { 8, 10,10,14 } }, // extend/vpsrlvd/pack sequence.
1570
1571 { ISD::SRA, MVT::v16i8, { 17, 17,24,30 } }, // vpblendvb sequence.
1572 { ISD::SRA, MVT::v32i8, { 18, 20,24,43 } }, // vpblendvb sequence.
1573 { ISD::SRA, MVT::v8i16, { 5, 11, 5,10 } }, // extend/vpsravd/pack sequence.
1574 { ISD::SRA, MVT::v16i16, { 8, 10,10,14 } }, // extend/vpsravd/pack sequence.
1575 { ISD::SRA, MVT::v2i64, { 4, 5, 5, 5 } }, // srl/xor/sub sequence.
1576 { ISD::SRA, MVT::v4i64, { 8, 8, 5, 9 } }, // srl/xor/sub sequence.
1577
1578 { ISD::SUB, MVT::v32i8, { 1, 1, 1, 2 } }, // psubb
1579 { ISD::ADD, MVT::v32i8, { 1, 1, 1, 2 } }, // paddb
1580 { ISD::SUB, MVT::v16i16, { 1, 1, 1, 2 } }, // psubw
1581 { ISD::ADD, MVT::v16i16, { 1, 1, 1, 2 } }, // paddw
1582 { ISD::SUB, MVT::v8i32, { 1, 1, 1, 2 } }, // psubd
1583 { ISD::ADD, MVT::v8i32, { 1, 1, 1, 2 } }, // paddd
1584 { ISD::SUB, MVT::v4i64, { 1, 1, 1, 2 } }, // psubq
1585 { ISD::ADD, MVT::v4i64, { 1, 1, 1, 2 } }, // paddq
1586
1587 { ISD::MUL, MVT::v16i8, { 5, 18, 6,12 } }, // extend/pmullw/pack
1588 { ISD::MUL, MVT::v32i8, { 4, 8, 8,16 } }, // pmaddubsw
1589 { ISD::MUL, MVT::v16i16, { 2, 5, 1, 2 } }, // pmullw
1590 { ISD::MUL, MVT::v8i32, { 4, 10, 1, 2 } }, // pmulld
1591 { ISD::MUL, MVT::v4i32, { 2, 10, 1, 2 } }, // pmulld
1592 { ISD::MUL, MVT::v4i64, { 6, 10, 8,13 } }, // 3*pmuludq/3*shift/2*add
1593 { ISD::MUL, MVT::v2i64, { 6, 10, 8, 8 } }, // 3*pmuludq/3*shift/2*add
1594
1595 { X86ISD::PMULUDQ, MVT::v4i64, { 1, 5, 1, 1 } },
1596
1597 { ISD::FNEG, MVT::v4f64, { 1, 1, 1, 2 } }, // vxorpd
1598 { ISD::FNEG, MVT::v8f32, { 1, 1, 1, 2 } }, // vxorps
1599
1600 { ISD::FADD, MVT::f64, { 1, 4, 1, 1 } }, // vaddsd
1601 { ISD::FADD, MVT::f32, { 1, 4, 1, 1 } }, // vaddss
1602 { ISD::FADD, MVT::v2f64, { 1, 4, 1, 1 } }, // vaddpd
1603 { ISD::FADD, MVT::v4f32, { 1, 4, 1, 1 } }, // vaddps
1604 { ISD::FADD, MVT::v4f64, { 1, 4, 1, 2 } }, // vaddpd
1605 { ISD::FADD, MVT::v8f32, { 1, 4, 1, 2 } }, // vaddps
1606
1607 { ISD::FSUB, MVT::f64, { 1, 4, 1, 1 } }, // vsubsd
1608 { ISD::FSUB, MVT::f32, { 1, 4, 1, 1 } }, // vsubss
1609 { ISD::FSUB, MVT::v2f64, { 1, 4, 1, 1 } }, // vsubpd
1610 { ISD::FSUB, MVT::v4f32, { 1, 4, 1, 1 } }, // vsubps
1611 { ISD::FSUB, MVT::v4f64, { 1, 4, 1, 2 } }, // vsubpd
1612 { ISD::FSUB, MVT::v8f32, { 1, 4, 1, 2 } }, // vsubps
1613
1614 { ISD::FMUL, MVT::f64, { 1, 5, 1, 1 } }, // vmulsd
1615 { ISD::FMUL, MVT::f32, { 1, 5, 1, 1 } }, // vmulss
1616 { ISD::FMUL, MVT::v2f64, { 1, 5, 1, 1 } }, // vmulpd
1617 { ISD::FMUL, MVT::v4f32, { 1, 5, 1, 1 } }, // vmulps
1618 { ISD::FMUL, MVT::v4f64, { 1, 5, 1, 2 } }, // vmulpd
1619 { ISD::FMUL, MVT::v8f32, { 1, 5, 1, 2 } }, // vmulps
1620
1621 { ISD::FDIV, MVT::f32, { 7, 13, 1, 1 } }, // vdivss
1622 { ISD::FDIV, MVT::v4f32, { 7, 13, 1, 1 } }, // vdivps
1623 { ISD::FDIV, MVT::v8f32, { 14, 21, 1, 3 } }, // vdivps
1624 { ISD::FDIV, MVT::f64, { 14, 20, 1, 1 } }, // vdivsd
1625 { ISD::FDIV, MVT::v2f64, { 14, 20, 1, 1 } }, // vdivpd
1626 { ISD::FDIV, MVT::v4f64, { 28, 35, 1, 3 } }, // vdivpd
1627 };
1628
1629 // Look for AVX2 lowering tricks for custom cases.
1630 if (ST->hasAVX2())
1631 if (const auto *Entry = CostTableLookup(AVX2CostTable, ISD, LT.second))
1632 if (auto KindCost = Entry->Cost[CostKind])
1633 return LT.first * *KindCost;
1634
1635 static const CostKindTblEntry AVX1CostTable[] = {
1636 // We don't have to scalarize unsupported ops. We can issue two half-sized
1637 // operations and we only need to extract the upper YMM half.
1638 // Two ops + 1 extract + 1 insert = 4.
1639 { ISD::MUL, MVT::v32i8, { 10, 11, 18, 19 } }, // pmaddubsw + split
1640 { ISD::MUL, MVT::v16i8, { 5, 6, 8, 12 } }, // 2*pmaddubsw/3*and/psllw/or
1641 { ISD::MUL, MVT::v16i16, { 4, 8, 5, 6 } }, // pmullw + split
1642 { ISD::MUL, MVT::v8i32, { 5, 8, 5, 10 } }, // pmulld + split
1643 { ISD::MUL, MVT::v4i32, { 2, 5, 1, 3 } }, // pmulld
1644 { ISD::MUL, MVT::v4i64, { 12, 15, 19, 20 } },
1645
1646 { X86ISD::PMULUDQ, MVT::v4i64, { 3, 5, 5, 6 } }, // pmuludq + split
1647
1648 { ISD::AND, MVT::v32i8, { 1, 1, 1, 2 } }, // vandps
1649 { ISD::AND, MVT::v16i16, { 1, 1, 1, 2 } }, // vandps
1650 { ISD::AND, MVT::v8i32, { 1, 1, 1, 2 } }, // vandps
1651 { ISD::AND, MVT::v4i64, { 1, 1, 1, 2 } }, // vandps
1652
1653 { ISD::OR, MVT::v32i8, { 1, 1, 1, 2 } }, // vorps
1654 { ISD::OR, MVT::v16i16, { 1, 1, 1, 2 } }, // vorps
1655 { ISD::OR, MVT::v8i32, { 1, 1, 1, 2 } }, // vorps
1656 { ISD::OR, MVT::v4i64, { 1, 1, 1, 2 } }, // vorps
1657
1658 { ISD::XOR, MVT::v32i8, { 1, 1, 1, 2 } }, // vxorps
1659 { ISD::XOR, MVT::v16i16, { 1, 1, 1, 2 } }, // vxorps
1660 { ISD::XOR, MVT::v8i32, { 1, 1, 1, 2 } }, // vxorps
1661 { ISD::XOR, MVT::v4i64, { 1, 1, 1, 2 } }, // vxorps
1662
1663 { ISD::SUB, MVT::v32i8, { 4, 2, 5, 6 } }, // psubb + split
1664 { ISD::ADD, MVT::v32i8, { 4, 2, 5, 6 } }, // paddb + split
1665 { ISD::SUB, MVT::v16i16, { 4, 2, 5, 6 } }, // psubw + split
1666 { ISD::ADD, MVT::v16i16, { 4, 2, 5, 6 } }, // paddw + split
1667 { ISD::SUB, MVT::v8i32, { 4, 2, 5, 6 } }, // psubd + split
1668 { ISD::ADD, MVT::v8i32, { 4, 2, 5, 6 } }, // paddd + split
1669 { ISD::SUB, MVT::v4i64, { 4, 2, 5, 6 } }, // psubq + split
1670 { ISD::ADD, MVT::v4i64, { 4, 2, 5, 6 } }, // paddq + split
1671 { ISD::SUB, MVT::v2i64, { 1, 1, 1, 1 } }, // psubq
1672 { ISD::ADD, MVT::v2i64, { 1, 1, 1, 1 } }, // paddq
1673
1674 { ISD::SHL, MVT::v16i8, { 10, 21,11,17 } }, // pblendvb sequence.
1675 { ISD::SHL, MVT::v32i8, { 22, 22,27,40 } }, // pblendvb sequence + split.
1676 { ISD::SHL, MVT::v8i16, { 6, 9,11,11 } }, // pblendvb sequence.
1677 { ISD::SHL, MVT::v16i16, { 13, 16,24,25 } }, // pblendvb sequence + split.
1678 { ISD::SHL, MVT::v4i32, { 3, 11, 4, 6 } }, // pslld/paddd/cvttps2dq/pmulld
1679 { ISD::SHL, MVT::v8i32, { 9, 11,12,17 } }, // pslld/paddd/cvttps2dq/pmulld + split
1680 { ISD::SHL, MVT::v2i64, { 2, 4, 4, 6 } }, // Shift each lane + blend.
1681 { ISD::SHL, MVT::v4i64, { 6, 7,11,15 } }, // Shift each lane + blend + split.
1682
1683 { ISD::SRL, MVT::v16i8, { 11, 27,12,18 } }, // pblendvb sequence.
1684 { ISD::SRL, MVT::v32i8, { 23, 23,30,43 } }, // pblendvb sequence + split.
1685 { ISD::SRL, MVT::v8i16, { 13, 16,14,22 } }, // pblendvb sequence.
1686 { ISD::SRL, MVT::v16i16, { 28, 30,31,48 } }, // pblendvb sequence + split.
1687 { ISD::SRL, MVT::v4i32, { 6, 7,12,16 } }, // Shift each lane + blend.
1688 { ISD::SRL, MVT::v8i32, { 14, 14,26,34 } }, // Shift each lane + blend + split.
1689 { ISD::SRL, MVT::v2i64, { 2, 4, 4, 6 } }, // Shift each lane + blend.
1690 { ISD::SRL, MVT::v4i64, { 6, 7,11,15 } }, // Shift each lane + blend + split.
1691
1692 { ISD::SRA, MVT::v16i8, { 21, 22,24,36 } }, // pblendvb sequence.
1693 { ISD::SRA, MVT::v32i8, { 44, 45,51,76 } }, // pblendvb sequence + split.
1694 { ISD::SRA, MVT::v8i16, { 13, 16,14,22 } }, // pblendvb sequence.
1695 { ISD::SRA, MVT::v16i16, { 28, 30,31,48 } }, // pblendvb sequence + split.
1696 { ISD::SRA, MVT::v4i32, { 6, 7,12,16 } }, // Shift each lane + blend.
1697 { ISD::SRA, MVT::v8i32, { 14, 14,26,34 } }, // Shift each lane + blend + split.
1698 { ISD::SRA, MVT::v2i64, { 5, 6,10,14 } }, // Shift each lane + blend.
1699 { ISD::SRA, MVT::v4i64, { 12, 12,22,30 } }, // Shift each lane + blend + split.
1700
1701 { ISD::FNEG, MVT::v4f64, { 2, 2, 1, 2 } }, // BTVER2 from http://www.agner.org/
1702 { ISD::FNEG, MVT::v8f32, { 2, 2, 1, 2 } }, // BTVER2 from http://www.agner.org/
1703
1704 { ISD::FADD, MVT::f64, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1705 { ISD::FADD, MVT::f32, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1706 { ISD::FADD, MVT::v2f64, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1707 { ISD::FADD, MVT::v4f32, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1708 { ISD::FADD, MVT::v4f64, { 2, 5, 1, 2 } }, // BDVER2 from http://www.agner.org/
1709 { ISD::FADD, MVT::v8f32, { 2, 5, 1, 2 } }, // BDVER2 from http://www.agner.org/
1710
1711 { ISD::FSUB, MVT::f64, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1712 { ISD::FSUB, MVT::f32, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1713 { ISD::FSUB, MVT::v2f64, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1714 { ISD::FSUB, MVT::v4f32, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1715 { ISD::FSUB, MVT::v4f64, { 2, 5, 1, 2 } }, // BDVER2 from http://www.agner.org/
1716 { ISD::FSUB, MVT::v8f32, { 2, 5, 1, 2 } }, // BDVER2 from http://www.agner.org/
1717
1718 { ISD::FMUL, MVT::f64, { 2, 5, 1, 1 } }, // BTVER2 from http://www.agner.org/
1719 { ISD::FMUL, MVT::f32, { 1, 5, 1, 1 } }, // BTVER2 from http://www.agner.org/
1720 { ISD::FMUL, MVT::v2f64, { 2, 5, 1, 1 } }, // BTVER2 from http://www.agner.org/
1721 { ISD::FMUL, MVT::v4f32, { 1, 5, 1, 1 } }, // BTVER2 from http://www.agner.org/
1722 { ISD::FMUL, MVT::v4f64, { 4, 5, 1, 2 } }, // BTVER2 from http://www.agner.org/
1723 { ISD::FMUL, MVT::v8f32, { 2, 5, 1, 2 } }, // BTVER2 from http://www.agner.org/
1724
1725 { ISD::FDIV, MVT::f32, { 14, 14, 1, 1 } }, // SNB from http://www.agner.org/
1726 { ISD::FDIV, MVT::v4f32, { 14, 14, 1, 1 } }, // SNB from http://www.agner.org/
1727 { ISD::FDIV, MVT::v8f32, { 28, 29, 1, 3 } }, // SNB from http://www.agner.org/
1728 { ISD::FDIV, MVT::f64, { 22, 22, 1, 1 } }, // SNB from http://www.agner.org/
1729 { ISD::FDIV, MVT::v2f64, { 22, 22, 1, 1 } }, // SNB from http://www.agner.org/
1730 { ISD::FDIV, MVT::v4f64, { 44, 45, 1, 3 } }, // SNB from http://www.agner.org/
1731 };
1732
1733 if (ST->hasAVX())
1734 if (const auto *Entry = CostTableLookup(AVX1CostTable, ISD, LT.second))
1735 if (auto KindCost = Entry->Cost[CostKind])
1736 return LT.first * *KindCost;
1737
1738 static const CostKindTblEntry SSE42CostTable[] = {
1739 { ISD::FADD, MVT::f64, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1740 { ISD::FADD, MVT::f32, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1741 { ISD::FADD, MVT::v2f64, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1742 { ISD::FADD, MVT::v4f32, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1743
1744 { ISD::FSUB, MVT::f64, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1745 { ISD::FSUB, MVT::f32 , { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1746 { ISD::FSUB, MVT::v2f64, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1747 { ISD::FSUB, MVT::v4f32, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1748
1749 { ISD::FMUL, MVT::f64, { 1, 5, 1, 1 } }, // Nehalem from http://www.agner.org/
1750 { ISD::FMUL, MVT::f32, { 1, 5, 1, 1 } }, // Nehalem from http://www.agner.org/
1751 { ISD::FMUL, MVT::v2f64, { 1, 5, 1, 1 } }, // Nehalem from http://www.agner.org/
1752 { ISD::FMUL, MVT::v4f32, { 1, 5, 1, 1 } }, // Nehalem from http://www.agner.org/
1753
1754 { ISD::FDIV, MVT::f32, { 14, 14, 1, 1 } }, // Nehalem from http://www.agner.org/
1755 { ISD::FDIV, MVT::v4f32, { 14, 14, 1, 1 } }, // Nehalem from http://www.agner.org/
1756 { ISD::FDIV, MVT::f64, { 22, 22, 1, 1 } }, // Nehalem from http://www.agner.org/
1757 { ISD::FDIV, MVT::v2f64, { 22, 22, 1, 1 } }, // Nehalem from http://www.agner.org/
1758
1759 { ISD::MUL, MVT::v2i64, { 6, 10,10,10 } } // 3*pmuludq/3*shift/2*add
1760 };
1761
1762 if (ST->hasSSE42())
1763 if (const auto *Entry = CostTableLookup(SSE42CostTable, ISD, LT.second))
1764 if (auto KindCost = Entry->Cost[CostKind])
1765 return LT.first * *KindCost;
1766
1767 static const CostKindTblEntry SSE41CostTable[] = {
1768 { ISD::SHL, MVT::v16i8, { 15, 24,17,22 } }, // pblendvb sequence.
1769 { ISD::SHL, MVT::v8i16, { 11, 14,11,11 } }, // pblendvb sequence.
1770 { ISD::SHL, MVT::v4i32, { 14, 20, 4,10 } }, // pslld/paddd/cvttps2dq/pmulld
1771
1772 { ISD::SRL, MVT::v16i8, { 16, 27,18,24 } }, // pblendvb sequence.
1773 { ISD::SRL, MVT::v8i16, { 22, 26,23,27 } }, // pblendvb sequence.
1774 { ISD::SRL, MVT::v4i32, { 16, 17,15,19 } }, // Shift each lane + blend.
1775 { ISD::SRL, MVT::v2i64, { 4, 6, 5, 7 } }, // splat+shuffle sequence.
1776
1777 { ISD::SRA, MVT::v16i8, { 38, 41,30,36 } }, // pblendvb sequence.
1778 { ISD::SRA, MVT::v8i16, { 22, 26,23,27 } }, // pblendvb sequence.
1779 { ISD::SRA, MVT::v4i32, { 16, 17,15,19 } }, // Shift each lane + blend.
1780 { ISD::SRA, MVT::v2i64, { 8, 17, 5, 7 } }, // splat+shuffle sequence.
1781
1782 { ISD::MUL, MVT::v4i32, { 2, 11, 1, 1 } } // pmulld (Nehalem from agner.org)
1783 };
1784
1785 if (ST->hasSSE41())
1786 if (const auto *Entry = CostTableLookup(SSE41CostTable, ISD, LT.second))
1787 if (auto KindCost = Entry->Cost[CostKind])
1788 return LT.first * *KindCost;
1789
1790 static const CostKindTblEntry SSSE3CostTable[] = {
1791 { ISD::MUL, MVT::v16i8, { 5, 18,10,12 } }, // 2*pmaddubsw/3*and/psllw/or
1792 };
1793
1794 if (ST->hasSSSE3())
1795 if (const auto *Entry = CostTableLookup(SSSE3CostTable, ISD, LT.second))
1796 if (auto KindCost = Entry->Cost[CostKind])
1797 return LT.first * *KindCost;
1798
1799 static const CostKindTblEntry SSE2CostTable[] = {
1800 // We don't correctly identify costs of casts because they are marked as
1801 // custom.
1802 { ISD::SHL, MVT::v16i8, { 13, 21,26,28 } }, // cmpgtb sequence.
1803 { ISD::SHL, MVT::v8i16, { 24, 27,16,20 } }, // cmpgtw sequence.
1804 { ISD::SHL, MVT::v4i32, { 17, 19,10,12 } }, // pslld/paddd/cvttps2dq/pmuludq.
1805 { ISD::SHL, MVT::v2i64, { 4, 6, 5, 7 } }, // splat+shuffle sequence.
1806
1807 { ISD::SRL, MVT::v16i8, { 14, 28,27,30 } }, // cmpgtb sequence.
1808 { ISD::SRL, MVT::v8i16, { 16, 19,31,31 } }, // cmpgtw sequence.
1809 { ISD::SRL, MVT::v4i32, { 12, 12,15,19 } }, // Shift each lane + blend.
1810 { ISD::SRL, MVT::v2i64, { 4, 6, 5, 7 } }, // splat+shuffle sequence.
1811
1812 { ISD::SRA, MVT::v16i8, { 27, 30,54,54 } }, // unpacked cmpgtb sequence.
1813 { ISD::SRA, MVT::v8i16, { 16, 19,31,31 } }, // cmpgtw sequence.
1814 { ISD::SRA, MVT::v4i32, { 12, 12,15,19 } }, // Shift each lane + blend.
1815 { ISD::SRA, MVT::v2i64, { 8, 11,12,16 } }, // srl/xor/sub splat+shuffle sequence.
1816
1817 { ISD::AND, MVT::v16i8, { 1, 1, 1, 1 } }, // pand
1818 { ISD::AND, MVT::v8i16, { 1, 1, 1, 1 } }, // pand
1819 { ISD::AND, MVT::v4i32, { 1, 1, 1, 1 } }, // pand
1820 { ISD::AND, MVT::v2i64, { 1, 1, 1, 1 } }, // pand
1821
1822 { ISD::OR, MVT::v16i8, { 1, 1, 1, 1 } }, // por
1823 { ISD::OR, MVT::v8i16, { 1, 1, 1, 1 } }, // por
1824 { ISD::OR, MVT::v4i32, { 1, 1, 1, 1 } }, // por
1825 { ISD::OR, MVT::v2i64, { 1, 1, 1, 1 } }, // por
1826
1827 { ISD::XOR, MVT::v16i8, { 1, 1, 1, 1 } }, // pxor
1828 { ISD::XOR, MVT::v8i16, { 1, 1, 1, 1 } }, // pxor
1829 { ISD::XOR, MVT::v4i32, { 1, 1, 1, 1 } }, // pxor
1830 { ISD::XOR, MVT::v2i64, { 1, 1, 1, 1 } }, // pxor
1831
1832 { ISD::ADD, MVT::v2i64, { 1, 2, 1, 2 } }, // paddq
1833 { ISD::SUB, MVT::v2i64, { 1, 2, 1, 2 } }, // psubq
1834
1835 { ISD::MUL, MVT::v16i8, { 6, 18,12,12 } }, // 2*unpack/2*pmullw/2*and/pack
1836 { ISD::MUL, MVT::v8i16, { 1, 5, 1, 1 } }, // pmullw
1837 { ISD::MUL, MVT::v4i32, { 6, 8, 7, 7 } }, // 3*pmuludq/4*shuffle
1838 { ISD::MUL, MVT::v2i64, { 7, 10,10,10 } }, // 3*pmuludq/3*shift/2*add
1839
1840 { X86ISD::PMULUDQ, MVT::v2i64, { 1, 5, 1, 1 } },
1841
1842 { ISD::FDIV, MVT::f32, { 23, 23, 1, 1 } }, // Pentium IV from http://www.agner.org/
1843 { ISD::FDIV, MVT::v4f32, { 39, 39, 1, 1 } }, // Pentium IV from http://www.agner.org/
1844 { ISD::FDIV, MVT::f64, { 38, 38, 1, 1 } }, // Pentium IV from http://www.agner.org/
1845 { ISD::FDIV, MVT::v2f64, { 69, 69, 1, 1 } }, // Pentium IV from http://www.agner.org/
1846
1847 { ISD::FNEG, MVT::f32, { 1, 1, 1, 1 } }, // Pentium IV from http://www.agner.org/
1848 { ISD::FNEG, MVT::f64, { 1, 1, 1, 1 } }, // Pentium IV from http://www.agner.org/
1849 { ISD::FNEG, MVT::v4f32, { 1, 1, 1, 1 } }, // Pentium IV from http://www.agner.org/
1850 { ISD::FNEG, MVT::v2f64, { 1, 1, 1, 1 } }, // Pentium IV from http://www.agner.org/
1851
1852 { ISD::FADD, MVT::f32, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1853 { ISD::FADD, MVT::f64, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1854 { ISD::FADD, MVT::v2f64, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1855
1856 { ISD::FSUB, MVT::f32, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1857 { ISD::FSUB, MVT::f64, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1858 { ISD::FSUB, MVT::v2f64, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1859
1860 { ISD::FMUL, MVT::f64, { 2, 5, 1, 1 } }, // Pentium IV from http://www.agner.org/
1861 { ISD::FMUL, MVT::v2f64, { 2, 5, 1, 1 } }, // Pentium IV from http://www.agner.org/
1862 };
1863
1864 if (ST->hasSSE2())
1865 if (const auto *Entry = CostTableLookup(SSE2CostTable, ISD, LT.second))
1866 if (auto KindCost = Entry->Cost[CostKind])
1867 return LT.first * *KindCost;
1868
1869 static const CostKindTblEntry SSE1CostTable[] = {
1870 { ISD::FDIV, MVT::f32, { 17, 18, 1, 1 } }, // Pentium III from http://www.agner.org/
1871 { ISD::FDIV, MVT::v4f32, { 34, 48, 1, 1 } }, // Pentium III from http://www.agner.org/
1872
1873 { ISD::FNEG, MVT::f32, { 2, 2, 1, 2 } }, // Pentium III from http://www.agner.org/
1874 { ISD::FNEG, MVT::v4f32, { 2, 2, 1, 2 } }, // Pentium III from http://www.agner.org/
1875
1876 { ISD::FADD, MVT::f32, { 1, 3, 1, 1 } }, // Pentium III from http://www.agner.org/
1877 { ISD::FADD, MVT::v4f32, { 2, 3, 1, 1 } }, // Pentium III from http://www.agner.org/
1878
1879 { ISD::FSUB, MVT::f32, { 1, 3, 1, 1 } }, // Pentium III from http://www.agner.org/
1880 { ISD::FSUB, MVT::v4f32, { 2, 3, 1, 1 } }, // Pentium III from http://www.agner.org/
1881
1882 { ISD::FMUL, MVT::f32, { 2, 5, 1, 1 } }, // Pentium III from http://www.agner.org/
1883 { ISD::FMUL, MVT::v4f32, { 2, 5, 1, 1 } }, // Pentium III from http://www.agner.org/
1884 };
1885
1886 if (ST->hasSSE1())
1887 if (const auto *Entry = CostTableLookup(SSE1CostTable, ISD, LT.second))
1888 if (auto KindCost = Entry->Cost[CostKind])
1889 return LT.first * *KindCost;
1890
1891 static const CostKindTblEntry X64CostTbl[] = { // 64-bit targets
1892 { ISD::ADD, MVT::i64, { 1 } }, // Core (Merom) from http://www.agner.org/
1893 { ISD::SUB, MVT::i64, { 1 } }, // Core (Merom) from http://www.agner.org/
1894 { ISD::MUL, MVT::i64, { 2, 6, 1, 2 } },
1895 };
1896
1897 if (ST->is64Bit())
1898 if (const auto *Entry = CostTableLookup(X64CostTbl, ISD, LT.second))
1899 if (auto KindCost = Entry->Cost[CostKind])
1900 return LT.first * *KindCost;
1901
1902 static const CostKindTblEntry X86CostTbl[] = { // 32 or 64-bit targets
1903 { ISD::ADD, MVT::i8, { 1 } }, // Pentium III from http://www.agner.org/
1904 { ISD::ADD, MVT::i16, { 1 } }, // Pentium III from http://www.agner.org/
1905 { ISD::ADD, MVT::i32, { 1 } }, // Pentium III from http://www.agner.org/
1906
1907 { ISD::SUB, MVT::i8, { 1 } }, // Pentium III from http://www.agner.org/
1908 { ISD::SUB, MVT::i16, { 1 } }, // Pentium III from http://www.agner.org/
1909 { ISD::SUB, MVT::i32, { 1 } }, // Pentium III from http://www.agner.org/
1910
1911 { ISD::MUL, MVT::i8, { 3, 4, 1, 1 } },
1912 { ISD::MUL, MVT::i16, { 2, 4, 1, 1 } },
1913 { ISD::MUL, MVT::i32, { 1, 4, 1, 1 } },
1914
1915 { ISD::FNEG, MVT::f64, { 2, 2, 1, 3 } }, // (x87)
1916 { ISD::FADD, MVT::f64, { 2, 3, 1, 1 } }, // (x87)
1917 { ISD::FSUB, MVT::f64, { 2, 3, 1, 1 } }, // (x87)
1918 { ISD::FMUL, MVT::f64, { 2, 5, 1, 1 } }, // (x87)
1919 { ISD::FDIV, MVT::f64, { 38, 38, 1, 1 } }, // (x87)
1920 };
1921
1922 if (const auto *Entry = CostTableLookup(X86CostTbl, ISD, LT.second))
1923 if (auto KindCost = Entry->Cost[CostKind])
1924 return LT.first * *KindCost;
1925
1926 // It is not a good idea to vectorize division. We have to scalarize it and
1927 // in the process we will often end up having to spilling regular
1928 // registers. The overhead of division is going to dominate most kernels
1929 // anyways so try hard to prevent vectorization of division - it is
1930 // generally a bad idea. Assume somewhat arbitrarily that we have to be able
1931 // to hide "20 cycles" for each lane.
1932 if (CostKind == TTI::TCK_RecipThroughput && LT.second.isVector() &&
1933 (ISD == ISD::SDIV || ISD == ISD::SREM || ISD == ISD::UDIV ||
1934 ISD == ISD::UREM)) {
1935 InstructionCost ScalarCost =
1936 getArithmeticInstrCost(Opcode, Ty->getScalarType(), CostKind,
1937 Op1Info.getNoProps(), Op2Info.getNoProps());
1938 return 20 * LT.first * LT.second.getVectorNumElements() * ScalarCost;
1939 }
1940
1941 // Handle some basic single instruction code size cases.
1942 if (CostKind == TTI::TCK_CodeSize) {
1943 switch (ISD) {
1944 case ISD::FADD:
1945 case ISD::FSUB:
1946 case ISD::FMUL:
1947 case ISD::FDIV:
1948 case ISD::FNEG:
1949 case ISD::AND:
1950 case ISD::OR:
1951 case ISD::XOR:
1952 return LT.first;
1953 break;
1954 }
1955 }
1956
1957 // Fallback to the default implementation.
1958 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info,
1959 Args, CtxI);
1960}
1961
1964 unsigned Opcode1, const SmallBitVector &OpcodeMask,
1965 TTI::TargetCostKind CostKind,
1966 ArrayRef<const Value *> Scalars) const {
1967 if (isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask, Scalars))
1968 return TTI::TCC_Basic;
1970}
1971
1973 TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy,
1974 TTI::TargetCostKind CostKind, ArrayRef<int> Mask, int Index,
1975 VectorType *SubTp, ArrayRef<const Value *> Args, const Instruction *CtxI,
1976 TTI::VectorInstrContext VIC) const {
1977 assert((Mask.empty() || DstTy->isScalableTy() ||
1978 Mask.size() == DstTy->getElementCount().getKnownMinValue()) &&
1979 "Expected the Mask to match the return size if given");
1980 assert(SrcTy->getScalarType() == DstTy->getScalarType() &&
1981 "Expected the same scalar types");
1982
1983 // 64-bit packed float vectors (v2f32) are widened to type v4f32.
1984 // 64-bit packed integer vectors (v2i32) are widened to type v4i32.
1985 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(SrcTy);
1986
1987 Kind = improveShuffleKindFromMask(Kind, Mask, SrcTy, Index, SubTp);
1988
1989 // If all args are constant than this will be constant folded away.
1990 if (!Args.empty() &&
1991 all_of(Args, [](const Value *Arg) { return isa<Constant>(Arg); }))
1992 return TTI::TCC_Free;
1993
1994 // Recognize a basic concat_vector shuffle.
1995 if (Kind == TTI::SK_PermuteTwoSrc &&
1996 Mask.size() == (2 * SrcTy->getElementCount().getKnownMinValue()) &&
1997 ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
2001 CostKind, Mask, Mask.size() / 2, SrcTy);
2002
2003 // Treat Transpose as 2-op shuffles - there's no difference in lowering.
2004 if (Kind == TTI::SK_Transpose)
2005 if (LT.second != MVT::v4f64 && LT.second != MVT::v4i64)
2006 Kind = TTI::SK_PermuteTwoSrc;
2007
2008 if (Kind == TTI::SK_Broadcast) {
2009 // For Broadcasts we are splatting the first element from the first input
2010 // register, so only need to reference that input and all the output
2011 // registers are the same.
2012 LT.first = 1;
2013
2014 // If we're broadcasting a load then AVX/AVX2 can do this for free.
2015 // If many-used-load whose every use is one of a small set of operations
2016 // that SLP can rewrite into a single vector lane, codegen can fold it into
2017 // the free broadcast.
2018 using namespace PatternMatch;
2019 auto IsBroadcastLoadFoldUser = [&](const User *U) {
2020 if (isa<InsertElementInst>(U) && U->getOperand(1) == Args[0])
2021 return true;
2022 if (U->getType()->isVectorTy())
2023 return false;
2024 // Terminators (return/branch/switch/indirectbr/resume/invoke EH)
2025 // and phis carry the value across control flow.
2026 if (const auto *I = dyn_cast<Instruction>(U))
2027 if (I->isTerminator() ||
2029 return false;
2030 // Only pure calls can be folded.
2031 if (const auto *CB = dyn_cast<CallBase>(U))
2032 return CB->doesNotAccessMemory() && !CB->mayHaveSideEffects();
2033 return true;
2034 };
2035 auto IsFoldableSLPBroadcastLoad = [&]() {
2036 if (!match(Args[0], m_Load(m_Value())))
2037 return false;
2038 auto *FVT = dyn_cast<FixedVectorType>(DstTy);
2039 if (!FVT)
2040 return false;
2041 // getNumUses() counts each Use, matching the per-lane broadcast
2042 // accounting (a use like `op %x, %x` consumes two broadcast lanes).
2043 if (Args[0]->getNumUses() != FVT->getNumElements())
2044 return false;
2045 return all_of(Args[0]->users(), IsBroadcastLoadFoldUser);
2046 };
2047 if (!Args.empty() &&
2048 (match(Args[0], m_OneUse(m_Load(m_Value()))) ||
2049 IsFoldableSLPBroadcastLoad()) &&
2050 (ST->hasAVX2() ||
2051 (ST->hasAVX() && LT.second.getScalarSizeInBits() >= 32)))
2052 return TTI::TCC_Free;
2053 }
2054
2055 // Attempt to detect a cheaper inlane shuffle, avoiding 128-bit subvector
2056 // permutation.
2057 // Attempt to detect a shuffle mask with a single defined element.
2058 bool IsInLaneShuffle = false;
2059 bool IsSingleElementMask = false;
2060 if (SrcTy->getPrimitiveSizeInBits() > 0 &&
2061 (SrcTy->getPrimitiveSizeInBits() % 128) == 0 &&
2062 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
2063 Mask.size() == SrcTy->getElementCount().getKnownMinValue()) {
2064 unsigned NumLanes = SrcTy->getPrimitiveSizeInBits() / 128;
2065 unsigned NumEltsPerLane = Mask.size() / NumLanes;
2066 if ((Mask.size() % NumLanes) == 0) {
2067 IsInLaneShuffle = all_of(enumerate(Mask), [&](const auto &P) {
2068 return P.value() == PoisonMaskElem ||
2069 ((P.value() % Mask.size()) / NumEltsPerLane) ==
2070 (P.index() / NumEltsPerLane);
2071 });
2072 IsSingleElementMask =
2073 (Mask.size() - 1) == static_cast<unsigned>(count_if(Mask, [](int M) {
2074 return M == PoisonMaskElem;
2075 }));
2076 }
2077 }
2078
2079 // Treat <X x bfloat> shuffles as <X x half>.
2080 if (LT.second.isVectorOf(MVT::bf16))
2081 LT.second = LT.second.changeVectorElementType(MVT::f16);
2082
2083 // Subvector extractions are free if they start at the beginning of a
2084 // vector and cheap if the subvectors are aligned.
2085 if (Kind == TTI::SK_ExtractSubvector && LT.second.isVector()) {
2086 int NumElts = LT.second.getVectorNumElements();
2087 if ((Index % NumElts) == 0)
2088 return TTI::TCC_Free;
2089 std::pair<InstructionCost, MVT> SubLT = getTypeLegalizationCost(SubTp);
2090 if (SubLT.second.isVector()) {
2091 int NumSubElts = SubLT.second.getVectorNumElements();
2092 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
2093 return SubLT.first;
2094 // Handle some cases for widening legalization. For now we only handle
2095 // cases where the original subvector was naturally aligned and evenly
2096 // fit in its legalized subvector type.
2097 // FIXME: Remove some of the alignment restrictions.
2098 // FIXME: We can use permq for 64-bit or larger extracts from 256-bit
2099 // vectors.
2100 int OrigSubElts = cast<FixedVectorType>(SubTp)->getNumElements();
2101 if (NumSubElts > OrigSubElts && (Index % OrigSubElts) == 0 &&
2102 (NumSubElts % OrigSubElts) == 0 &&
2103 LT.second.getVectorElementType() ==
2104 SubLT.second.getVectorElementType() &&
2105 LT.second.getVectorElementType().getSizeInBits() ==
2106 SrcTy->getElementType()->getPrimitiveSizeInBits()) {
2107 assert(NumElts >= NumSubElts && NumElts > OrigSubElts &&
2108 "Unexpected number of elements!");
2109 auto *VecTy = FixedVectorType::get(SrcTy->getElementType(),
2110 LT.second.getVectorNumElements());
2111 auto *SubTy = FixedVectorType::get(SrcTy->getElementType(),
2112 SubLT.second.getVectorNumElements());
2113 int ExtractIndex = alignDown((Index % NumElts), NumSubElts);
2114 InstructionCost ExtractCost =
2115 getShuffleCost(TTI::SK_ExtractSubvector, VecTy, VecTy, CostKind, {},
2116 ExtractIndex, SubTy);
2117
2118 // If the original size is 32-bits or more, we can use pshufd. Otherwise
2119 // if we have SSSE3 we can use pshufb.
2120 if (SubTp->getPrimitiveSizeInBits() >= 32 || ST->hasSSSE3())
2121 return ExtractCost + 1; // pshufd or pshufb
2122
2123 assert(SubTp->getPrimitiveSizeInBits() == 16 &&
2124 "Unexpected vector size");
2125
2126 return ExtractCost + 2; // worst case pshufhw + pshufd
2127 }
2128 }
2129 // If the extract subvector is not optimal, treat it as single op shuffle.
2131 }
2132
2133 // Subvector insertions are cheap if the subvectors are aligned.
2134 // Note that in general, the insertion starting at the beginning of a vector
2135 // isn't free, because we need to preserve the rest of the wide vector,
2136 // but if the destination vector legalizes to the same width as the subvector
2137 // then the insertion will simplify to a (free) register copy.
2138 if (Kind == TTI::SK_InsertSubvector && LT.second.isVector()) {
2139 std::pair<InstructionCost, MVT> DstLT = getTypeLegalizationCost(DstTy);
2140 int NumElts = DstLT.second.getVectorNumElements();
2141 std::pair<InstructionCost, MVT> SubLT = getTypeLegalizationCost(SubTp);
2142 if (SubLT.second.isVector()) {
2143 int NumSubElts = SubLT.second.getVectorNumElements();
2144 bool MatchingTypes =
2145 NumElts == NumSubElts &&
2146 (SubTp->getElementCount().getKnownMinValue() % NumSubElts) == 0;
2147 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
2148 return MatchingTypes ? TTI::TCC_Free : SubLT.first;
2149 }
2150
2151 // Attempt to match MOVSS (Idx == 0) or INSERTPS pattern. This will have
2152 // been matched by improveShuffleKindFromMask as a SK_InsertSubvector of
2153 // v1f32 (legalised to f32) into a v4f32.
2154 if (LT.first == 1 && LT.second == MVT::v4f32 && SubLT.first == 1 &&
2155 SubLT.second == MVT::f32 && (Index == 0 || ST->hasSSE41()))
2156 return 1;
2157
2158 // If the insertion is the lowest subvector then it will be blended
2159 // otherwise treat it like a 2-op shuffle.
2160 Kind =
2161 (Index == 0 && LT.first == 1) ? TTI::SK_Select : TTI::SK_PermuteTwoSrc;
2162 }
2163
2164 // Handle some common (illegal) sub-vector types as they are often very cheap
2165 // to shuffle even on targets without PSHUFB.
2166 EVT VT = TLI->getValueType(DL, SrcTy);
2167 if (VT.isSimple() && VT.isVector() && VT.getSizeInBits() < 128 &&
2168 !ST->hasSSSE3()) {
2169 static const CostKindTblEntry SSE2SubVectorShuffleTbl[] = {
2170 {TTI::SK_Broadcast, MVT::v4i16, {1,1,1,1}}, // pshuflw
2171 {TTI::SK_Broadcast, MVT::v2i16, {1,1,1,1}}, // pshuflw
2172 {TTI::SK_Broadcast, MVT::v8i8, {2,2,2,2}}, // punpck/pshuflw
2173 {TTI::SK_Broadcast, MVT::v4i8, {2,2,2,2}}, // punpck/pshuflw
2174 {TTI::SK_Broadcast, MVT::v2i8, {1,1,1,1}}, // punpck
2175
2176 {TTI::SK_Reverse, MVT::v4i16, {1,1,1,1}}, // pshuflw
2177 {TTI::SK_Reverse, MVT::v2i16, {1,1,1,1}}, // pshuflw
2178 {TTI::SK_Reverse, MVT::v4i8, {3,3,3,3}}, // punpck/pshuflw/packus
2179 {TTI::SK_Reverse, MVT::v2i8, {1,1,1,1}}, // punpck
2180
2181 {TTI::SK_Splice, MVT::v4i16, {2,2,2,2}}, // punpck+psrldq
2182 {TTI::SK_Splice, MVT::v2i16, {2,2,2,2}}, // punpck+psrldq
2183 {TTI::SK_Splice, MVT::v4i8, {2,2,2,2}}, // punpck+psrldq
2184 {TTI::SK_Splice, MVT::v2i8, {2,2,2,2}}, // punpck+psrldq
2185
2186 {TTI::SK_PermuteTwoSrc, MVT::v4i16, {2,2,2,2}}, // punpck/pshuflw
2187 {TTI::SK_PermuteTwoSrc, MVT::v2i16, {2,2,2,2}}, // punpck/pshuflw
2188 {TTI::SK_PermuteTwoSrc, MVT::v8i8, {7,7,7,7}}, // punpck/pshuflw
2189 {TTI::SK_PermuteTwoSrc, MVT::v4i8, {4,4,4,4}}, // punpck/pshuflw
2190 {TTI::SK_PermuteTwoSrc, MVT::v2i8, {2,2,2,2}}, // punpck
2191
2192 {TTI::SK_PermuteSingleSrc, MVT::v4i16, {1,1,1,1}}, // pshuflw
2193 {TTI::SK_PermuteSingleSrc, MVT::v2i16, {1,1,1,1}}, // pshuflw
2194 {TTI::SK_PermuteSingleSrc, MVT::v8i8, {5,5,5,5}}, // punpck/pshuflw
2195 {TTI::SK_PermuteSingleSrc, MVT::v4i8, {3,3,3,3}}, // punpck/pshuflw
2196 {TTI::SK_PermuteSingleSrc, MVT::v2i8, {1,1,1,1}}, // punpck
2197 };
2198
2199 if (ST->hasSSE2())
2200 if (const auto *Entry =
2201 CostTableLookup(SSE2SubVectorShuffleTbl, Kind, VT.getSimpleVT()))
2202 if (auto KindCost = Entry->Cost[CostKind])
2203 return LT.first * *KindCost;
2204 }
2205
2206 // We are going to permute multiple sources and the result will be in multiple
2207 // destinations. Providing an accurate cost only for splits where the element
2208 // type remains the same.
2209 if (LT.first != 1) {
2210 MVT LegalVT = LT.second;
2211 if (LegalVT.isVector() &&
2212 LegalVT.getVectorElementType().getSizeInBits() ==
2213 SrcTy->getElementType()->getPrimitiveSizeInBits() &&
2214 LegalVT.getVectorNumElements() <
2215 cast<FixedVectorType>(SrcTy)->getNumElements()) {
2216 unsigned VecTySize = DL.getTypeStoreSize(SrcTy);
2217 unsigned LegalVTSize = LegalVT.getStoreSize();
2218 // Number of source vectors after legalization:
2219 unsigned NumOfSrcs = (VecTySize + LegalVTSize - 1) / LegalVTSize;
2220 // Number of destination vectors after legalization:
2221 InstructionCost NumOfDests = LT.first;
2222
2223 auto *SingleOpTy = FixedVectorType::get(SrcTy->getElementType(),
2224 LegalVT.getVectorNumElements());
2225
2226 if (!Mask.empty() && NumOfDests.isValid()) {
2227 // Try to perform better estimation of the permutation.
2228 // 1. Split the source/destination vectors into real registers.
2229 // 2. Do the mask analysis to identify which real registers are
2230 // permuted. If more than 1 source registers are used for the
2231 // destination register building, the cost for this destination register
2232 // is (Number_of_source_register - 1) * Cost_PermuteTwoSrc. If only one
2233 // source register is used, build mask and calculate the cost as a cost
2234 // of PermuteSingleSrc.
2235 // Also, for the single register permute we try to identify if the
2236 // destination register is just a copy of the source register or the
2237 // copy of the previous destination register (the cost is
2238 // TTI::TCC_Basic). If the source register is just reused, the cost for
2239 // this operation is TTI::TCC_Free.
2240 NumOfDests =
2242 FixedVectorType::get(SrcTy->getElementType(), Mask.size()))
2243 .first;
2244 unsigned E = NumOfDests.getValue();
2245 unsigned NormalizedVF =
2246 LegalVT.getVectorNumElements() * std::max(NumOfSrcs, E);
2247 unsigned NumOfSrcRegs = NormalizedVF / LegalVT.getVectorNumElements();
2248 unsigned NumOfDestRegs = NormalizedVF / LegalVT.getVectorNumElements();
2249 SmallVector<int> NormalizedMask(NormalizedVF, PoisonMaskElem);
2250 copy(Mask, NormalizedMask.begin());
2251 unsigned PrevSrcReg = 0;
2252 ArrayRef<int> PrevRegMask;
2255 NormalizedMask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs, []() {},
2256 [this, SingleOpTy, CostKind, &PrevSrcReg, &PrevRegMask,
2257 &Cost](ArrayRef<int> RegMask, unsigned SrcReg, unsigned DestReg) {
2258 if (!ShuffleVectorInst::isIdentityMask(RegMask, RegMask.size())) {
2259 // Check if the previous register can be just copied to the next
2260 // one.
2261 if (PrevRegMask.empty() || PrevSrcReg != SrcReg ||
2262 PrevRegMask != RegMask)
2263 Cost +=
2265 SingleOpTy, CostKind, RegMask, 0, nullptr);
2266 else
2267 // Just a copy of previous destination register.
2269 return;
2270 }
2271 if (SrcReg != DestReg &&
2272 any_of(RegMask, not_equal_to(PoisonMaskElem))) {
2273 // Just a copy of the source register.
2275 }
2276 PrevSrcReg = SrcReg;
2277 PrevRegMask = RegMask;
2278 },
2279 [this, SingleOpTy, CostKind,
2280 &Cost](ArrayRef<int> RegMask, unsigned /*Unused*/,
2281 unsigned /*Unused*/, bool /*Unused*/) {
2283 SingleOpTy, CostKind, RegMask, 0, nullptr);
2284 });
2285 return Cost;
2286 }
2287
2288 InstructionCost NumOfShuffles = (NumOfSrcs - 1) * NumOfDests;
2289 return NumOfShuffles * getShuffleCost(TTI::SK_PermuteTwoSrc, SingleOpTy,
2290 SingleOpTy, CostKind, {}, 0,
2291 nullptr);
2292 }
2293
2294 return BaseT::getShuffleCost(Kind, DstTy, SrcTy, CostKind, Mask, Index,
2295 SubTp);
2296 }
2297
2298 // If we're just moving a single element around (probably as an alternative to
2299 // extracting it), we can assume this is cheap.
2300 if (LT.first == 1 && IsInLaneShuffle && IsSingleElementMask)
2301 return TTI::TCC_Basic;
2302
2303 static const CostKindTblEntry AVX512VBMIShuffleTbl[] = {
2304 { TTI::SK_Reverse, MVT::v64i8, { 1, 1, 1, 1 } }, // vpermb
2305 { TTI::SK_Reverse, MVT::v32i8, { 1, 1, 1, 1 } }, // vpermb
2306 { TTI::SK_PermuteSingleSrc, MVT::v64i8, { 1, 1, 1, 1 } }, // vpermb
2307 { TTI::SK_PermuteSingleSrc, MVT::v32i8, { 1, 1, 1, 1 } }, // vpermb
2308 { TTI::SK_PermuteTwoSrc, MVT::v64i8, { 2, 2, 2, 2 } }, // vpermt2b
2309 { TTI::SK_PermuteTwoSrc, MVT::v32i8, { 2, 2, 2, 2 } }, // vpermt2b
2310 { TTI::SK_PermuteTwoSrc, MVT::v16i8, { 2, 2, 2, 2 } } // vpermt2b
2311 };
2312
2313 if (ST->hasVBMI())
2314 if (const auto *Entry =
2315 CostTableLookup(AVX512VBMIShuffleTbl, Kind, LT.second))
2316 if (auto KindCost = Entry->Cost[CostKind])
2317 return LT.first * *KindCost;
2318
2319 static const CostKindTblEntry AVX512BWInLaneShuffleTbl[] = {
2320 {TTI::SK_PermuteTwoSrc, MVT::v64i8, {2, 2, 2, 2}}, // 2*vpshufb + vpor
2321 };
2322
2323 if (IsInLaneShuffle && ST->hasBWI())
2324 if (const auto *Entry =
2325 CostTableLookup(AVX512BWInLaneShuffleTbl, Kind, LT.second))
2326 if (auto KindCost = Entry->Cost[CostKind])
2327 return LT.first * *KindCost;
2328
2329 static const CostKindTblEntry AVX512BWShuffleTbl[] = {
2330 { TTI::SK_Broadcast, MVT::v32i16, { 1, 3, 1, 1 } }, // vpbroadcastw
2331 { TTI::SK_Broadcast, MVT::v32f16, { 1, 3, 1, 1 } }, // vpbroadcastw
2332 { TTI::SK_Broadcast, MVT::v64i8, { 1, 3, 1, 1 } }, // vpbroadcastb
2333
2334 { TTI::SK_Reverse, MVT::v32i16, { 2, 6, 2, 4 } }, // vpermw
2335 { TTI::SK_Reverse, MVT::v32f16, { 2, 6, 2, 4 } }, // vpermw
2336 { TTI::SK_Reverse, MVT::v16i16, { 2, 2, 2, 2 } }, // vpermw
2337 { TTI::SK_Reverse, MVT::v16f16, { 2, 2, 2, 2 } }, // vpermw
2338 { TTI::SK_Reverse, MVT::v64i8, { 2, 9, 2, 3 } }, // pshufb + vshufi64x2
2339
2340 { TTI::SK_PermuteSingleSrc, MVT::v32i16, { 2, 2, 2, 2 } }, // vpermw
2341 { TTI::SK_PermuteSingleSrc, MVT::v32f16, { 2, 2, 2, 2 } }, // vpermw
2342 { TTI::SK_PermuteSingleSrc, MVT::v16i16, { 2, 2, 2, 2 } }, // vpermw
2343 { TTI::SK_PermuteSingleSrc, MVT::v16f16, { 2, 2, 2, 2 } }, // vpermw
2344 { TTI::SK_PermuteSingleSrc, MVT::v64i8, { 8, 8, 8, 8 } }, // extend to v32i16
2345
2346 { TTI::SK_PermuteTwoSrc, MVT::v32i16,{ 2, 2, 2, 2 } }, // vpermt2w
2347 { TTI::SK_PermuteTwoSrc, MVT::v32f16,{ 2, 2, 2, 2 } }, // vpermt2w
2348 { TTI::SK_PermuteTwoSrc, MVT::v16i16,{ 2, 2, 2, 2 } }, // vpermt2w
2349 { TTI::SK_PermuteTwoSrc, MVT::v8i16, { 2, 2, 2, 2 } }, // vpermt2w
2350 { TTI::SK_PermuteTwoSrc, MVT::v64i8, { 19, 19, 19, 19 } }, // 6 * v32i8 + 1
2351
2352 { TTI::SK_Select, MVT::v32i16, { 1, 1, 1, 1 } }, // vblendmw
2353 { TTI::SK_Select, MVT::v64i8, { 1, 1, 1, 1 } }, // vblendmb
2354
2355 { TTI::SK_Splice, MVT::v32i16, { 2, 2, 2, 2 } }, // vshufi64x2 + palignr
2356 { TTI::SK_Splice, MVT::v32f16, { 2, 2, 2, 2 } }, // vshufi64x2 + palignr
2357 { TTI::SK_Splice, MVT::v64i8, { 2, 2, 2, 2 } }, // vshufi64x2 + palignr
2358 };
2359
2360 if (ST->hasBWI())
2361 if (const auto *Entry =
2362 CostTableLookup(AVX512BWShuffleTbl, Kind, LT.second))
2363 if (auto KindCost = Entry->Cost[CostKind])
2364 return LT.first * *KindCost;
2365
2366 static const CostKindTblEntry AVX512InLaneShuffleTbl[] = {
2367 {TTI::SK_PermuteTwoSrc, MVT::v8f64, { 1, 3, 1, 1 } },
2368 {TTI::SK_PermuteTwoSrc, MVT::v16f32, { 1, 3, 1, 1 } },
2369 {TTI::SK_PermuteTwoSrc, MVT::v8i64, { 1, 3, 1, 1 } },
2370 {TTI::SK_PermuteTwoSrc, MVT::v16i32, { 1, 3, 1, 1 } },
2371 {TTI::SK_PermuteTwoSrc, MVT::v4f64, { 1, 3, 1, 1 } },
2372 {TTI::SK_PermuteTwoSrc, MVT::v8f32, { 1, 3, 1, 1 } },
2373 {TTI::SK_PermuteTwoSrc, MVT::v4i64, { 1, 3, 1, 1 } },
2374 {TTI::SK_PermuteTwoSrc, MVT::v8i32, { 1, 3, 1, 1 } },
2375 };
2376
2377 if (IsInLaneShuffle && ST->hasAVX512())
2378 if (const auto *Entry =
2379 CostTableLookup(AVX512InLaneShuffleTbl, Kind, LT.second))
2380 if (auto KindCost = Entry->Cost[CostKind])
2381 return LT.first * *KindCost;
2382
2383 static const CostKindTblEntry AVX512ShuffleTbl[] = {
2384 {TTI::SK_Broadcast, MVT::v8f64, { 1, 3, 1, 1 } }, // vbroadcastsd
2385 {TTI::SK_Broadcast, MVT::v4f64, { 1, 3, 1, 1 } }, // vbroadcastsd
2386 {TTI::SK_Broadcast, MVT::v16f32, { 1, 3, 1, 1 } }, // vbroadcastss
2387 {TTI::SK_Broadcast, MVT::v8f32, { 1, 3, 1, 1 } }, // vbroadcastss
2388 {TTI::SK_Broadcast, MVT::v8i64, { 1, 3, 1, 1 } }, // vpbroadcastq
2389 {TTI::SK_Broadcast, MVT::v4i64, { 1, 3, 1, 1 } }, // vpbroadcastq
2390 {TTI::SK_Broadcast, MVT::v16i32, { 1, 3, 1, 1 } }, // vpbroadcastd
2391 {TTI::SK_Broadcast, MVT::v8i32, { 1, 3, 1, 1 } }, // vpbroadcastd
2392 {TTI::SK_Broadcast, MVT::v32i16, { 1, 3, 1, 1 } }, // vpbroadcastw
2393 {TTI::SK_Broadcast, MVT::v16i16, { 1, 3, 1, 1 } }, // vpbroadcastw
2394 {TTI::SK_Broadcast, MVT::v32f16, { 1, 3, 1, 1 } }, // vpbroadcastw
2395 {TTI::SK_Broadcast, MVT::v16f16, { 1, 3, 1, 1 } }, // vpbroadcastw
2396 {TTI::SK_Broadcast, MVT::v64i8, { 1, 3, 1, 1 } }, // vpbroadcastb
2397 {TTI::SK_Broadcast, MVT::v32i8, { 1, 3, 1, 1 }}, // vpbroadcastb
2398
2399 {TTI::SK_Reverse, MVT::v8f64, { 1, 5, 2, 3 } }, // vpermpd
2400 {TTI::SK_Reverse, MVT::v16f32, { 1, 3, 2, 3 } }, // vpermps
2401 {TTI::SK_Reverse, MVT::v8i64, { 1, 5, 2, 3 } }, // vpermq
2402 {TTI::SK_Reverse, MVT::v16i32, { 1, 3, 2, 3 } }, // vpermd
2403 {TTI::SK_Reverse, MVT::v32i16, { 7, 7, 7, 7 } }, // per mca
2404 {TTI::SK_Reverse, MVT::v32f16, { 7, 7, 7, 7 } }, // per mca
2405 {TTI::SK_Reverse, MVT::v64i8, { 7, 7, 7, 7 } }, // per mca
2406
2407 {TTI::SK_Splice, MVT::v8f64, { 1, 1, 1, 1 } }, // vpalignd
2408 {TTI::SK_Splice, MVT::v4f64, { 1, 1, 1, 1 } }, // vpalignd
2409 {TTI::SK_Splice, MVT::v16f32, { 1, 1, 1, 1 } }, // vpalignd
2410 {TTI::SK_Splice, MVT::v8f32, { 1, 1, 1, 1 } }, // vpalignd
2411 {TTI::SK_Splice, MVT::v8i64, { 1, 1, 1, 1 } }, // vpalignd
2412 {TTI::SK_Splice, MVT::v4i64, { 1, 1, 1, 1 } }, // vpalignd
2413 {TTI::SK_Splice, MVT::v16i32, { 1, 1, 1, 1 } }, // vpalignd
2414 {TTI::SK_Splice, MVT::v8i32, { 1, 1, 1, 1 } }, // vpalignd
2415 {TTI::SK_Splice, MVT::v32i16, { 4, 4, 4, 4 } }, // split + palignr
2416 {TTI::SK_Splice, MVT::v32f16, { 4, 4, 4, 4 } }, // split + palignr
2417 {TTI::SK_Splice, MVT::v64i8, { 4, 4, 4, 4 } }, // split + palignr
2418
2419 {TTI::SK_PermuteSingleSrc, MVT::v8f64, { 1, 3, 1, 1 } }, // vpermpd
2420 {TTI::SK_PermuteSingleSrc, MVT::v4f64, { 1, 3, 1, 1 } }, // vpermpd
2421 {TTI::SK_PermuteSingleSrc, MVT::v2f64, { 1, 3, 1, 1 } }, // vpermpd
2422 {TTI::SK_PermuteSingleSrc, MVT::v16f32, { 1, 3, 1, 1 } }, // vpermps
2423 {TTI::SK_PermuteSingleSrc, MVT::v8f32, { 1, 3, 1, 1 } }, // vpermps
2424 {TTI::SK_PermuteSingleSrc, MVT::v4f32, { 1, 3, 1, 1 } }, // vpermps
2425 {TTI::SK_PermuteSingleSrc, MVT::v8i64, { 1, 3, 1, 1 } }, // vpermq
2426 {TTI::SK_PermuteSingleSrc, MVT::v4i64, { 1, 3, 1, 1 } }, // vpermq
2427 {TTI::SK_PermuteSingleSrc, MVT::v2i64, { 1, 3, 1, 1 } }, // vpermq
2428 {TTI::SK_PermuteSingleSrc, MVT::v16i32, { 1, 3, 1, 1 } }, // vpermd
2429 {TTI::SK_PermuteSingleSrc, MVT::v8i32, { 1, 3, 1, 1 } }, // vpermd
2430 {TTI::SK_PermuteSingleSrc, MVT::v4i32, { 1, 3, 1, 1 } }, // vpermd
2431 {TTI::SK_PermuteSingleSrc, MVT::v16i8, { 1, 3, 1, 1 } }, // pshufb
2432
2433 {TTI::SK_PermuteTwoSrc, MVT::v8f64, { 2, 3, 1, 1 } }, // vpermt2pd
2434 {TTI::SK_PermuteTwoSrc, MVT::v16f32, { 2, 3, 1, 1 } }, // vpermt2ps
2435 {TTI::SK_PermuteTwoSrc, MVT::v8i64, { 2, 3, 1, 1 } }, // vpermt2q
2436 {TTI::SK_PermuteTwoSrc, MVT::v16i32, { 2, 3, 1, 1 } }, // vpermt2d
2437 {TTI::SK_PermuteTwoSrc, MVT::v4f64, { 2, 3, 1, 1 } }, // vpermt2pd
2438 {TTI::SK_PermuteTwoSrc, MVT::v8f32, { 2, 3, 1, 1 } }, // vpermt2ps
2439 {TTI::SK_PermuteTwoSrc, MVT::v4i64, { 2, 3, 1, 1 } }, // vpermt2q
2440 {TTI::SK_PermuteTwoSrc, MVT::v8i32, { 2, 3, 1, 1 } }, // vpermt2d
2441 {TTI::SK_PermuteTwoSrc, MVT::v2f64, { 1, 3, 1, 1 } },
2442 {TTI::SK_PermuteTwoSrc, MVT::v4f32, { 1, 3, 1, 1 } },
2443 {TTI::SK_PermuteTwoSrc, MVT::v2i64, { 1, 3, 1, 1 } },
2444 {TTI::SK_PermuteTwoSrc, MVT::v4i32, { 1, 3, 1, 1 } },
2445
2446 // FIXME: This just applies the type legalization cost rules above
2447 // assuming these completely split.
2448 {TTI::SK_PermuteSingleSrc, MVT::v32i16, { 14, 14, 14, 14 } },
2449 {TTI::SK_PermuteSingleSrc, MVT::v32f16, { 14, 14, 14, 14 } },
2450 {TTI::SK_PermuteSingleSrc, MVT::v64i8, { 14, 14, 14, 14 } },
2451 {TTI::SK_PermuteTwoSrc, MVT::v32i16, { 42, 42, 42, 42 } },
2452 {TTI::SK_PermuteTwoSrc, MVT::v32f16, { 42, 42, 42, 42 } },
2453 {TTI::SK_PermuteTwoSrc, MVT::v64i8, { 42, 42, 42, 42 } },
2454
2455 {TTI::SK_Select, MVT::v32i16, { 1, 1, 1, 1 } }, // vpternlogq
2456 {TTI::SK_Select, MVT::v32f16, { 1, 1, 1, 1 } }, // vpternlogq
2457 {TTI::SK_Select, MVT::v64i8, { 1, 1, 1, 1 } }, // vpternlogq
2458 {TTI::SK_Select, MVT::v8f64, { 1, 1, 1, 1 } }, // vblendmpd
2459 {TTI::SK_Select, MVT::v16f32, { 1, 1, 1, 1 } }, // vblendmps
2460 {TTI::SK_Select, MVT::v8i64, { 1, 1, 1, 1 } }, // vblendmq
2461 {TTI::SK_Select, MVT::v16i32, { 1, 1, 1, 1 } }, // vblendmd
2462 };
2463
2464 if (ST->hasAVX512())
2465 if (const auto *Entry = CostTableLookup(AVX512ShuffleTbl, Kind, LT.second))
2466 if (auto KindCost = Entry->Cost[CostKind])
2467 return LT.first * *KindCost;
2468
2469 static const CostKindTblEntry AVX2InLaneShuffleTbl[] = {
2470 { TTI::SK_PermuteSingleSrc, MVT::v16i16, { 1, 1, 1, 1 } }, // vpshufb
2471 { TTI::SK_PermuteSingleSrc, MVT::v16f16, { 1, 1, 1, 1 } }, // vpshufb
2472 { TTI::SK_PermuteSingleSrc, MVT::v32i8, { 1, 1, 1, 1 } }, // vpshufb
2473
2474 { TTI::SK_Transpose, MVT::v4f64, { 1, 1, 1, 1 } }, // vshufpd/vunpck
2475 { TTI::SK_Transpose, MVT::v4i64, { 1, 1, 1, 1 } }, // vshufpd/vunpck
2476
2477 { TTI::SK_PermuteTwoSrc, MVT::v4f64, { 2, 2, 2, 2 } }, // 2*vshufpd + vblendpd
2478 { TTI::SK_PermuteTwoSrc, MVT::v8f32, { 2, 2, 2, 2 } }, // 2*vshufps + vblendps
2479 { TTI::SK_PermuteTwoSrc, MVT::v4i64, { 2, 2, 2, 2 } }, // 2*vpshufd + vpblendd
2480 { TTI::SK_PermuteTwoSrc, MVT::v8i32, { 2, 2, 2, 2 } }, // 2*vpshufd + vpblendd
2481 { TTI::SK_PermuteTwoSrc, MVT::v16i16, { 2, 2, 2, 2 } }, // 2*vpshufb + vpor
2482 { TTI::SK_PermuteTwoSrc, MVT::v16f16, { 2, 2, 2, 2 } }, // 2*vpshufb + vpor
2483 { TTI::SK_PermuteTwoSrc, MVT::v32i8, { 2, 2, 2, 2 } }, // 2*vpshufb + vpor
2484 };
2485
2486 if (IsInLaneShuffle && ST->hasAVX2())
2487 if (const auto *Entry =
2488 CostTableLookup(AVX2InLaneShuffleTbl, Kind, LT.second))
2489 if (auto KindCost = Entry->Cost[CostKind])
2490 return LT.first * *KindCost;
2491
2492 static const CostKindTblEntry AVX2ShuffleTbl[] = {
2493 { TTI::SK_Broadcast, MVT::v4f64, { 1, 3, 1, 2 } }, // vbroadcastpd
2494 { TTI::SK_Broadcast, MVT::v8f32, { 1, 3, 1, 2 } }, // vbroadcastps
2495 { TTI::SK_Broadcast, MVT::v4i64, { 1, 3, 1, 2 } }, // vpbroadcastq
2496 { TTI::SK_Broadcast, MVT::v8i32, { 1, 3, 1, 2 } }, // vpbroadcastd
2497 { TTI::SK_Broadcast, MVT::v16i16, { 1, 3, 1, 2 } }, // vpbroadcastw
2498 { TTI::SK_Broadcast, MVT::v8i16, { 1, 3, 1, 1 } }, // vpbroadcastw
2499 { TTI::SK_Broadcast, MVT::v16f16, { 1, 3, 1, 2 } }, // vpbroadcastw
2500 { TTI::SK_Broadcast, MVT::v8f16, { 1, 3, 1, 1 } }, // vpbroadcastw
2501 { TTI::SK_Broadcast, MVT::v32i8, { 1, 3, 1, 2 } }, // vpbroadcastb
2502 { TTI::SK_Broadcast, MVT::v16i8, { 1, 3, 1, 1 } }, // vpbroadcastb
2503
2504 { TTI::SK_Reverse, MVT::v4f64, { 1, 6, 1, 2 } }, // vpermpd
2505 { TTI::SK_Reverse, MVT::v8f32, { 2, 7, 2, 4 } }, // vpermps
2506 { TTI::SK_Reverse, MVT::v4i64, { 1, 6, 1, 2 } }, // vpermq
2507 { TTI::SK_Reverse, MVT::v8i32, { 2, 7, 2, 4 } }, // vpermd
2508 { TTI::SK_Reverse, MVT::v16i16, { 2, 9, 2, 4 } }, // vperm2i128 + pshufb
2509 { TTI::SK_Reverse, MVT::v16f16, { 2, 9, 2, 4 } }, // vperm2i128 + pshufb
2510 { TTI::SK_Reverse, MVT::v32i8, { 2, 9, 2, 4 } }, // vperm2i128 + pshufb
2511
2512 { TTI::SK_Select, MVT::v16i16, { 1, 1, 1, 1 } }, // vpblendvb
2513 { TTI::SK_Select, MVT::v16f16, { 1, 1, 1, 1 } }, // vpblendvb
2514 { TTI::SK_Select, MVT::v32i8, { 1, 1, 1, 1 } }, // vpblendvb
2515
2516 { TTI::SK_Splice, MVT::v8i32, { 2, 2, 2, 2 } }, // vperm2i128 + vpalignr
2517 { TTI::SK_Splice, MVT::v8f32, { 2, 2, 2, 2 } }, // vperm2i128 + vpalignr
2518 { TTI::SK_Splice, MVT::v16i16, { 2, 2, 2, 2 } }, // vperm2i128 + vpalignr
2519 { TTI::SK_Splice, MVT::v16f16, { 2, 2, 2, 2 } }, // vperm2i128 + vpalignr
2520 { TTI::SK_Splice, MVT::v32i8, { 2, 2, 2, 2 } }, // vperm2i128 + vpalignr
2521
2522 { TTI::SK_PermuteSingleSrc, MVT::v4f64, { 1, 1, 1, 1 } }, // vpermpd
2523 { TTI::SK_PermuteSingleSrc, MVT::v8f32, { 1, 1, 1, 1 } }, // vpermps
2524 { TTI::SK_PermuteSingleSrc, MVT::v4i64, { 1, 1, 1, 1 } }, // vpermq
2525 { TTI::SK_PermuteSingleSrc, MVT::v8i32, { 1, 1, 1, 1 } }, // vpermd
2526 { TTI::SK_PermuteSingleSrc, MVT::v16i16, { 4, 4, 4, 4 } },
2527 { TTI::SK_PermuteSingleSrc, MVT::v16f16, { 4, 4, 4, 4 } },
2528 { TTI::SK_PermuteSingleSrc, MVT::v32i8, { 4, 4, 4, 4 } },
2529
2530 { TTI::SK_PermuteTwoSrc, MVT::v4f64, { 3, 3, 3, 3 } }, // 2*vpermpd + vblendpd
2531 { TTI::SK_PermuteTwoSrc, MVT::v8f32, { 3, 3, 3, 3 } }, // 2*vpermps + vblendps
2532 { TTI::SK_PermuteTwoSrc, MVT::v4i64, { 3, 3, 3, 3 } }, // 2*vpermq + vpblendd
2533 { TTI::SK_PermuteTwoSrc, MVT::v8i32, { 3, 3, 3, 3 } }, // 2*vpermd + vpblendd
2534 { TTI::SK_PermuteTwoSrc, MVT::v16i16, { 7, 7, 7, 7 } },
2535 { TTI::SK_PermuteTwoSrc, MVT::v16f16, { 7, 7, 7, 7 } },
2536 { TTI::SK_PermuteTwoSrc, MVT::v32i8, { 7, 7, 7, 7 } },
2537 };
2538
2539 if (ST->hasAVX2())
2540 if (const auto *Entry = CostTableLookup(AVX2ShuffleTbl, Kind, LT.second))
2541 if (auto KindCost = Entry->Cost[CostKind])
2542 return LT.first * *KindCost;
2543
2544 static const CostKindTblEntry XOPShuffleTbl[] = {
2545 { TTI::SK_PermuteSingleSrc, MVT::v4f64, { 2, 2, 2, 2 } }, // vperm2f128 + vpermil2pd
2546 { TTI::SK_PermuteSingleSrc, MVT::v8f32, { 2, 2, 2, 2 } }, // vperm2f128 + vpermil2ps
2547 { TTI::SK_PermuteSingleSrc, MVT::v4i64, { 2, 2, 2, 2 } }, // vperm2f128 + vpermil2pd
2548 { TTI::SK_PermuteSingleSrc, MVT::v8i32, { 2, 2, 2, 2 } }, // vperm2f128 + vpermil2ps
2549 { TTI::SK_PermuteSingleSrc, MVT::v16i16,{ 4, 4, 4, 4 } }, // vextractf128 + 2*vpperm
2550 // + vinsertf128
2551 { TTI::SK_PermuteSingleSrc, MVT::v32i8, { 4, 4, 4, 4 } }, // vextractf128 + 2*vpperm
2552 // + vinsertf128
2553
2554 { TTI::SK_PermuteTwoSrc, MVT::v16i16, { 9, 9, 9, 9 } }, // 2*vextractf128 + 6*vpperm
2555 // + vinsertf128
2556
2557 { TTI::SK_PermuteTwoSrc, MVT::v8i16, { 1, 1, 1, 1 } }, // vpperm
2558 { TTI::SK_PermuteTwoSrc, MVT::v32i8, { 9, 9, 9, 9 } }, // 2*vextractf128 + 6*vpperm
2559 // + vinsertf128
2560 { TTI::SK_PermuteTwoSrc, MVT::v16i8, { 1, 1, 1, 1 } }, // vpperm
2561 };
2562
2563 if (ST->hasXOP())
2564 if (const auto *Entry = CostTableLookup(XOPShuffleTbl, Kind, LT.second))
2565 if (auto KindCost = Entry->Cost[CostKind])
2566 return LT.first * *KindCost;
2567
2568 static const CostKindTblEntry AVX1InLaneShuffleTbl[] = {
2569 { TTI::SK_PermuteSingleSrc, MVT::v4f64, { 1, 1, 1, 1 } }, // vpermilpd
2570 { TTI::SK_PermuteSingleSrc, MVT::v4i64, { 1, 1, 1, 1 } }, // vpermilpd
2571 { TTI::SK_PermuteSingleSrc, MVT::v8f32, { 1, 1, 1, 1 } }, // vpermilps
2572 { TTI::SK_PermuteSingleSrc, MVT::v8i32, { 1, 1, 1, 1 } }, // vpermilps
2573
2574 { TTI::SK_PermuteSingleSrc, MVT::v16i16, { 4, 4, 4, 4 } }, // vextractf128 + 2*pshufb
2575 // + vpor + vinsertf128
2576 { TTI::SK_PermuteSingleSrc, MVT::v16f16, { 4, 4, 4, 4 } }, // vextractf128 + 2*pshufb
2577 // + vpor + vinsertf128
2578 { TTI::SK_PermuteSingleSrc, MVT::v32i8, { 4, 4, 4, 4 } }, // vextractf128 + 2*pshufb
2579 // + vpor + vinsertf128
2580
2581 { TTI::SK_Transpose, MVT::v4f64, { 1, 1, 1, 1 } }, // vshufpd/vunpck
2582 { TTI::SK_Transpose, MVT::v4i64, { 1, 1, 1, 1 } }, // vshufpd/vunpck
2583
2584 { TTI::SK_PermuteTwoSrc, MVT::v4f64, { 2, 2, 2, 2 } }, // 2*vshufpd + vblendpd
2585 { TTI::SK_PermuteTwoSrc, MVT::v8f32, { 2, 2, 2, 2 } }, // 2*vshufps + vblendps
2586 { TTI::SK_PermuteTwoSrc, MVT::v4i64, { 2, 2, 2, 2 } }, // 2*vpermilpd + vblendpd
2587 { TTI::SK_PermuteTwoSrc, MVT::v8i32, { 2, 2, 2, 2 } }, // 2*vpermilps + vblendps
2588 { TTI::SK_PermuteTwoSrc, MVT::v16i16, { 9, 9, 9, 9 } }, // 2*vextractf128 + 4*pshufb
2589 // + 2*vpor + vinsertf128
2590 { TTI::SK_PermuteTwoSrc, MVT::v16f16, { 9, 9, 9, 9 } }, // 2*vextractf128 + 4*pshufb
2591 // + 2*vpor + vinsertf128
2592 { TTI::SK_PermuteTwoSrc, MVT::v32i8, { 9, 9, 9, 9 } }, // 2*vextractf128 + 4*pshufb
2593 // + 2*vpor + vinsertf128
2594 };
2595
2596 if (IsInLaneShuffle && ST->hasAVX())
2597 if (const auto *Entry =
2598 CostTableLookup(AVX1InLaneShuffleTbl, Kind, LT.second))
2599 if (auto KindCost = Entry->Cost[CostKind])
2600 return LT.first * *KindCost;
2601
2602 static const CostKindTblEntry AVX1ShuffleTbl[] = {
2603 {TTI::SK_Broadcast, MVT::v4f64, {2,3,2,3}}, // vperm2f128 + vpermilpd
2604 {TTI::SK_Broadcast, MVT::v8f32, {2,3,2,3}}, // vperm2f128 + vpermilps
2605 {TTI::SK_Broadcast, MVT::v4i64, {2,3,2,3}}, // vperm2f128 + vpermilpd
2606 {TTI::SK_Broadcast, MVT::v8i32, {2,3,2,3}}, // vperm2f128 + vpermilps
2607 {TTI::SK_Broadcast, MVT::v16i16, {2,3,3,4}}, // vpshuflw + vpshufd + vinsertf128
2608 {TTI::SK_Broadcast, MVT::v16f16, {2,3,3,4}}, // vpshuflw + vpshufd + vinsertf128
2609 {TTI::SK_Broadcast, MVT::v32i8, {3,4,3,6}}, // vpshufb + vinsertf128
2610
2611 {TTI::SK_Reverse, MVT::v4f64, {2,6,2,2}}, // vperm2f128 + vpermilpd
2612 {TTI::SK_Reverse, MVT::v8f32, {2,7,2,4}}, // vperm2f128 + vpermilps
2613 {TTI::SK_Reverse, MVT::v4i64, {2,6,2,2}}, // vperm2f128 + vpermilpd
2614 {TTI::SK_Reverse, MVT::v8i32, {2,7,2,4}}, // vperm2f128 + vpermilps
2615 {TTI::SK_Reverse, MVT::v16i16, {2,9,5,5}}, // vextractf128 + 2*pshufb
2616 // + vinsertf128
2617 {TTI::SK_Reverse, MVT::v16f16, {2,9,5,5}}, // vextractf128 + 2*pshufb
2618 // + vinsertf128
2619 {TTI::SK_Reverse, MVT::v32i8, {2,9,5,5}}, // vextractf128 + 2*pshufb
2620 // + vinsertf128
2621
2622 {TTI::SK_Select, MVT::v4i64, {1,1,1,1}}, // vblendpd
2623 {TTI::SK_Select, MVT::v4f64, {1,1,1,1}}, // vblendpd
2624 {TTI::SK_Select, MVT::v8i32, {1,1,1,1}}, // vblendps
2625 {TTI::SK_Select, MVT::v8f32, {1,1,1,1}}, // vblendps
2626 {TTI::SK_Select, MVT::v16i16, {3,3,3,3}}, // vpand + vpandn + vpor
2627 {TTI::SK_Select, MVT::v16f16, {3,3,3,3}}, // vpand + vpandn + vpor
2628 {TTI::SK_Select, MVT::v32i8, {3,3,3,3}}, // vpand + vpandn + vpor
2629
2630 {TTI::SK_Splice, MVT::v4i64, {2,2,2,2}}, // vperm2f128 + shufpd
2631 {TTI::SK_Splice, MVT::v4f64, {2,2,2,2}}, // vperm2f128 + shufpd
2632 {TTI::SK_Splice, MVT::v8i32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2633 {TTI::SK_Splice, MVT::v8f32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2634 {TTI::SK_Splice, MVT::v16i16, {5,5,5,5}}, // 2*vperm2f128 + 2*vpalignr + vinsertf128
2635 {TTI::SK_Splice, MVT::v16f16, {5,5,5,5}}, // 2*vperm2f128 + 2*vpalignr + vinsertf128
2636 {TTI::SK_Splice, MVT::v32i8, {5,5,5,5}}, // 2*vperm2f128 + 2*vpalignr + vinsertf128
2637
2638 {TTI::SK_PermuteSingleSrc, MVT::v4f64, {2,2,2,2}}, // vperm2f128 + vshufpd
2639 {TTI::SK_PermuteSingleSrc, MVT::v4i64, {2,2,2,2}}, // vperm2f128 + vshufpd
2640 {TTI::SK_PermuteSingleSrc, MVT::v8f32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2641 {TTI::SK_PermuteSingleSrc, MVT::v8i32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2642 {TTI::SK_PermuteSingleSrc, MVT::v16i16,{8,8,8,8}}, // vextractf128 + 4*pshufb
2643 // + 2*por + vinsertf128
2644 {TTI::SK_PermuteSingleSrc, MVT::v16f16,{8,8,8,8}}, // vextractf128 + 4*pshufb
2645 // + 2*por + vinsertf128
2646 {TTI::SK_PermuteSingleSrc, MVT::v32i8, {8,8,8,8}}, // vextractf128 + 4*pshufb
2647 // + 2*por + vinsertf128
2648
2649 {TTI::SK_PermuteTwoSrc, MVT::v4f64, {3,3,3,3}}, // 2*vperm2f128 + vshufpd
2650 {TTI::SK_PermuteTwoSrc, MVT::v4i64, {3,3,3,3}}, // 2*vperm2f128 + vshufpd
2651 {TTI::SK_PermuteTwoSrc, MVT::v8f32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2652 {TTI::SK_PermuteTwoSrc, MVT::v8i32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2653 {TTI::SK_PermuteTwoSrc, MVT::v16i16,{15,15,15,15}}, // 2*vextractf128 + 8*pshufb
2654 // + 4*por + vinsertf128
2655 {TTI::SK_PermuteTwoSrc, MVT::v16f16,{15,15,15,15}}, // 2*vextractf128 + 8*pshufb
2656 // + 4*por + vinsertf128
2657 {TTI::SK_PermuteTwoSrc, MVT::v32i8, {15,15,15,15}}, // 2*vextractf128 + 8*pshufb
2658 // + 4*por + vinsertf128
2659 };
2660
2661 if (ST->hasAVX())
2662 if (const auto *Entry = CostTableLookup(AVX1ShuffleTbl, Kind, LT.second))
2663 if (auto KindCost = Entry->Cost[CostKind])
2664 return LT.first * *KindCost;
2665
2666 static const CostKindTblEntry SSE41ShuffleTbl[] = {
2667 {TTI::SK_Select, MVT::v2i64, {1,1,1,1}}, // pblendw
2668 {TTI::SK_Select, MVT::v2f64, {1,1,1,1}}, // movsd
2669 {TTI::SK_Select, MVT::v4i32, {1,1,1,1}}, // pblendw
2670 {TTI::SK_Select, MVT::v4f32, {1,1,1,1}}, // blendps
2671 {TTI::SK_Select, MVT::v8i16, {1,1,1,1}}, // pblendw
2672 {TTI::SK_Select, MVT::v8f16, {1,1,1,1}}, // pblendw
2673 {TTI::SK_Select, MVT::v16i8, {1,1,1,1}} // pblendvb
2674 };
2675
2676 if (ST->hasSSE41())
2677 if (const auto *Entry = CostTableLookup(SSE41ShuffleTbl, Kind, LT.second))
2678 if (auto KindCost = Entry->Cost[CostKind])
2679 return LT.first * *KindCost;
2680
2681 static const CostKindTblEntry SSSE3ShuffleTbl[] = {
2682 {TTI::SK_Broadcast, MVT::v8i16, {1, 3, 2, 2}}, // pshufb
2683 {TTI::SK_Broadcast, MVT::v8f16, {1, 3, 2, 2}}, // pshufb
2684 {TTI::SK_Broadcast, MVT::v16i8, {1, 3, 2, 2}}, // pshufb
2685
2686 {TTI::SK_Reverse, MVT::v8i16, {1, 2, 1, 2}}, // pshufb
2687 {TTI::SK_Reverse, MVT::v8f16, {1, 2, 1, 2}}, // pshufb
2688 {TTI::SK_Reverse, MVT::v16i8, {1, 2, 1, 2}}, // pshufb
2689
2690 {TTI::SK_Splice, MVT::v4i32, {1, 1, 1, 1}}, // palignr
2691 {TTI::SK_Splice, MVT::v4f32, {1, 1, 1, 1}}, // palignr
2692 {TTI::SK_Splice, MVT::v8i16, {1, 1, 1, 1}}, // palignr
2693 {TTI::SK_Splice, MVT::v8f16, {1, 1, 1, 1}}, // palignr
2694 {TTI::SK_Splice, MVT::v16i8, {1, 1, 1, 1}}, // palignr
2695
2696 {TTI::SK_PermuteSingleSrc, MVT::v8i16, {1, 1, 1, 1}}, // pshufb
2697 {TTI::SK_PermuteSingleSrc, MVT::v8f16, {1, 1, 1, 1}}, // pshufb
2698 {TTI::SK_PermuteSingleSrc, MVT::v16i8, {1, 1, 1, 1}}, // pshufb
2699
2700 {TTI::SK_PermuteTwoSrc, MVT::v8i16, {3, 3, 3, 3}}, // 2*pshufb + por
2701 {TTI::SK_PermuteTwoSrc, MVT::v8f16, {3, 3, 3, 3}}, // 2*pshufb + por
2702 {TTI::SK_PermuteTwoSrc, MVT::v16i8, {3, 3, 3, 3}}, // 2*pshufb + por
2703 };
2704
2705 if (ST->hasSSSE3())
2706 if (const auto *Entry = CostTableLookup(SSSE3ShuffleTbl, Kind, LT.second))
2707 if (auto KindCost = Entry->Cost[CostKind])
2708 return LT.first * *KindCost;
2709
2710 static const CostKindTblEntry SSE2ShuffleTbl[] = {
2711 {TTI::SK_Broadcast, MVT::v2f64, {1, 1, 1, 1}}, // shufpd
2712 {TTI::SK_Broadcast, MVT::v2i64, {1, 1, 1, 1}}, // pshufd
2713 {TTI::SK_Broadcast, MVT::v4i32, {1, 1, 1, 1}}, // pshufd
2714 {TTI::SK_Broadcast, MVT::v8i16, {1, 2, 2, 2}}, // pshuflw + pshufd
2715 {TTI::SK_Broadcast, MVT::v8f16, {1, 2, 2, 2}}, // pshuflw + pshufd
2716 {TTI::SK_Broadcast, MVT::v16i8, {2, 3, 3, 4}}, // unpck + pshuflw + pshufd
2717
2718 {TTI::SK_Reverse, MVT::v2f64, {1, 1, 1, 1}}, // shufpd
2719 {TTI::SK_Reverse, MVT::v2i64, {1, 1, 1, 1}}, // pshufd
2720 {TTI::SK_Reverse, MVT::v4i32, {1, 1, 1, 1}}, // pshufd
2721 {TTI::SK_Reverse, MVT::v8i16, {2, 3, 3, 3}}, // pshuflw + pshufhw + pshufd
2722 {TTI::SK_Reverse, MVT::v8f16, {2, 3, 3, 3}}, // pshuflw + pshufhw + pshufd
2723 {TTI::SK_Reverse, MVT::v16i8, {5, 6,11,11}}, // 2*pshuflw + 2*pshufhw
2724 // + 2*pshufd + 2*unpck + packus
2725
2726 {TTI::SK_Select, MVT::v2i64, {1, 1, 1, 1}}, // movsd
2727 {TTI::SK_Select, MVT::v2f64, {1, 1, 1, 1}}, // movsd
2728 {TTI::SK_Select, MVT::v4i32, {2, 2, 2, 2}}, // 2*shufps
2729 {TTI::SK_Select, MVT::v8i16, {2, 2, 3, 3}}, // pand + pandn + por
2730 {TTI::SK_Select, MVT::v8f16, {2, 2, 3, 3}}, // pand + pandn + por
2731 {TTI::SK_Select, MVT::v16i8, {2, 2, 3, 3}}, // pand + pandn + por
2732
2733 {TTI::SK_Splice, MVT::v2i64, {1, 1, 1, 1}}, // shufpd
2734 {TTI::SK_Splice, MVT::v2f64, {1, 1, 1, 1}}, // shufpd
2735 {TTI::SK_Splice, MVT::v4i32, {2, 2, 2, 2}}, // 2*{unpck,movsd,pshufd}
2736 {TTI::SK_Splice, MVT::v8i16, {3, 3, 3, 3}}, // psrldq + psrlldq + por
2737 {TTI::SK_Splice, MVT::v8f16, {3, 3, 3, 3}}, // psrldq + psrlldq + por
2738 {TTI::SK_Splice, MVT::v16i8, {3, 3, 3, 3}}, // psrldq + psrlldq + por
2739
2740 {TTI::SK_PermuteSingleSrc, MVT::v2f64, {1, 1, 1, 1}}, // shufpd
2741 {TTI::SK_PermuteSingleSrc, MVT::v2i64, {1, 1, 1, 1}}, // pshufd
2742 {TTI::SK_PermuteSingleSrc, MVT::v4i32, {1, 1, 1, 1}}, // pshufd
2743 {TTI::SK_PermuteSingleSrc, MVT::v8i16, {3, 5, 5, 5}}, // 2*pshuflw + 2*pshufhw
2744 // + pshufd/unpck
2745 {TTI::SK_PermuteSingleSrc, MVT::v8f16, {3, 5, 5, 5}}, // 2*pshuflw + 2*pshufhw
2746 // + pshufd/unpck
2747 {TTI::SK_PermuteSingleSrc, MVT::v16i8, {8, 10, 10, 10}}, // 2*pshuflw + 2*pshufhw
2748 // + 2*pshufd + 2*unpck + 2*packus
2749
2750 {TTI::SK_PermuteTwoSrc, MVT::v2f64, {1, 1, 1, 1}}, // shufpd
2751 {TTI::SK_PermuteTwoSrc, MVT::v2i64, {1, 1, 1, 1}}, // shufpd
2752 {TTI::SK_PermuteTwoSrc, MVT::v4i32, {2, 2, 2, 2}}, // 2*{unpck,movsd,pshufd}
2753 {TTI::SK_PermuteTwoSrc, MVT::v8i16, {6, 8, 8, 8}}, // blend+permute
2754 {TTI::SK_PermuteTwoSrc, MVT::v8f16, {6, 8, 8, 8}}, // blend+permute
2755 {TTI::SK_PermuteTwoSrc, MVT::v16i8, {11, 13, 13, 13}}, // blend+permute
2756 };
2757
2758 static const CostTblEntry SSE3BroadcastLoadTbl[] = {
2759 {TTI::SK_Broadcast, MVT::v2f64, 0}, // broadcast handled by movddup
2760 };
2761
2762 if (ST->hasSSE2()) {
2763 bool IsLoad =
2764 llvm::any_of(Args, [](const auto &V) { return isa<LoadInst>(V); });
2765 if (ST->hasSSE3() && IsLoad)
2766 if (const auto *Entry =
2767 CostTableLookup(SSE3BroadcastLoadTbl, Kind, LT.second)) {
2768 assert(isLegalBroadcastLoad(SrcTy->getElementType(),
2769 LT.second.getVectorElementCount()) &&
2770 "Table entry missing from isLegalBroadcastLoad()");
2771 return LT.first * Entry->Cost;
2772 }
2773
2774 if (const auto *Entry = CostTableLookup(SSE2ShuffleTbl, Kind, LT.second))
2775 if (auto KindCost = Entry->Cost[CostKind])
2776 return LT.first * *KindCost;
2777 }
2778
2779 static const CostKindTblEntry SSE1ShuffleTbl[] = {
2780 { TTI::SK_Broadcast, MVT::v4f32, {1,1,1,1} }, // shufps
2781 { TTI::SK_Reverse, MVT::v4f32, {1,1,1,1} }, // shufps
2782 { TTI::SK_Select, MVT::v4f32, {2,2,2,2} }, // 2*shufps
2783 { TTI::SK_Splice, MVT::v4f32, {2,2,2,2} }, // 2*shufps
2784 { TTI::SK_PermuteSingleSrc, MVT::v4f32, {1,1,1,1} }, // shufps
2785 { TTI::SK_PermuteTwoSrc, MVT::v4f32, {2,2,2,2} }, // 2*shufps
2786 };
2787
2788 if (ST->hasSSE1()) {
2789 if (LT.first == 1 && LT.second == MVT::v4f32 && Mask.size() == 4) {
2790 // SHUFPS: both pairs must come from the same source register.
2791 auto MatchSHUFPS = [](int X, int Y) {
2792 return X < 0 || Y < 0 || ((X & 4) == (Y & 4));
2793 };
2794 if (MatchSHUFPS(Mask[0], Mask[1]) && MatchSHUFPS(Mask[2], Mask[3]))
2795 return 1;
2796 }
2797 if (const auto *Entry = CostTableLookup(SSE1ShuffleTbl, Kind, LT.second))
2798 if (auto KindCost = Entry->Cost[CostKind])
2799 return LT.first * *KindCost;
2800 }
2801
2802 return BaseT::getShuffleCost(Kind, DstTy, SrcTy, CostKind, Mask, Index,
2803 SubTp);
2804}
2805
2807 Type *Src,
2809 TTI::TargetCostKind CostKind,
2810 const Instruction *I) const {
2811 int ISD = TLI->InstructionOpcodeToISD(Opcode);
2812 assert(ISD && "Invalid opcode");
2813
2814 // A narrow (i8/i16) zero-extension used as a GEP *index* can be folded into
2815 // the addressing mode of the consuming memory op, but only if the source is
2816 // already materialised zero-extended in a full register. X86's SIB form
2817 // [base + index*scale + disp] reads the index at full width and does NOT
2818 // zero-extend a narrow index (unlike AArch64's uxtw-extended addressing), so
2819 // a "dirty" narrow source (e.g. an i16 add result used only as an index)
2820 // still needs a dedicated movzx and is not free. Price it as free only with
2821 // positive evidence that no movzx is required.
2822 if (ISD == ISD::ZERO_EXTEND && I && I->hasOneUse() && Src->isIntegerTy() &&
2823 Src->getScalarSizeInBits() < 32) {
2824 const Use &U = *I->use_begin();
2825 if (isa<GetElementPtrInst>(U.getUser()) &&
2826 U.getOperandNo() != GetElementPtrInst::getPointerOperandIndex()) {
2827 const Value *Op = I->getOperand(0);
2828 // Clean sources: an extending load, a zeroext argument, or a value whose
2829 // high bits are provably zero (e.g. from a shift/mask). These mirror the
2830 // proof-based reasoning the middle end uses elsewhere (ValueTracking and
2831 // InstCombine's canEvaluateZExtd); we intentionally do NOT treat a merely
2832 // multiply-used operand as clean, since that is a guess rather than
2833 // proof.
2834 if (isa<LoadInst>(Op))
2835 return TTI::TCC_Free;
2836 if (const auto *A = dyn_cast<Argument>(Op))
2837 if (A->hasAttribute(Attribute::ZExt))
2838 return TTI::TCC_Free;
2839 if (computeKnownBits(Op, I->getDataLayout(), /*AC=*/nullptr, I)
2840 .countMinLeadingZeros() > 0)
2841 return TTI::TCC_Free;
2842 }
2843 }
2844
2845 // The cost tables include both specific, custom (non-legal) src/dst type
2846 // conversions and generic, legalized types. We test for customs first, before
2847 // falling back to legalization.
2848 // FIXME: Need a better design of the cost table to handle non-simple types of
2849 // potential massive combinations (elem_num x src_type x dst_type).
2850 static const TypeConversionCostKindTblEntry AVX512BWConversionTbl[]{
2851 { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i8, { 1, 1, 1, 1 } },
2852 { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i8, { 1, 1, 1, 1 } },
2853
2854 // Mask sign extend has an instruction.
2855 { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 1, 1, 1, 1 } },
2856 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v2i1, { 1, 1, 1, 1 } },
2857 { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 1, 1, 1, 1 } },
2858 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v2i1, { 1, 1, 1, 1 } },
2859 { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 1, 1, 1, 1 } },
2860 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v4i1, { 1, 1, 1, 1 } },
2861 { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 1, 1, 1, 1 } },
2862 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v4i1, { 1, 1, 1, 1 } },
2863 { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 1, 1, 1, 1 } },
2864 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v8i1, { 1, 1, 1, 1 } },
2865 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 1, 1, 1, 1 } },
2866 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, { 1, 1, 1, 1 } },
2867 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } },
2868 { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v32i1, { 1, 1, 1, 1 } },
2869 { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i1, { 1, 1, 1, 1 } },
2870 { ISD::SIGN_EXTEND, MVT::v64i8, MVT::v64i1, { 1, 1, 1, 1 } },
2871 { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v64i1, { 1, 1, 1, 1 } },
2872
2873 // Mask zero extend is a sext + shift.
2874 { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 2, 1, 1, 1 } },
2875 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v2i1, { 2, 1, 1, 1 } },
2876 { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 2, 1, 1, 1 } },
2877 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v2i1, { 2, 1, 1, 1 } },
2878 { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 2, 1, 1, 1 } },
2879 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v4i1, { 2, 1, 1, 1 } },
2880 { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 2, 1, 1, 1 } },
2881 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v4i1, { 2, 1, 1, 1 } },
2882 { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 2, 1, 1, 1 } },
2883 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v8i1, { 2, 1, 1, 1 } },
2884 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 2, 1, 1, 1 } },
2885 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, { 2, 1, 1, 1 } },
2886 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 2, 1, 1, 1 } },
2887 { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v32i1, { 2, 1, 1, 1 } },
2888 { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i1, { 2, 1, 1, 1 } },
2889 { ISD::ZERO_EXTEND, MVT::v64i8, MVT::v64i1, { 2, 1, 1, 1 } },
2890 { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v64i1, { 2, 1, 1, 1 } },
2891
2892 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 2, 1, 1, 1 } },
2893 { ISD::TRUNCATE, MVT::v2i1, MVT::v16i8, { 2, 1, 1, 1 } },
2894 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 2, 1, 1, 1 } },
2895 { ISD::TRUNCATE, MVT::v2i1, MVT::v8i16, { 2, 1, 1, 1 } },
2896 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 2, 1, 1, 1 } },
2897 { ISD::TRUNCATE, MVT::v4i1, MVT::v16i8, { 2, 1, 1, 1 } },
2898 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 2, 1, 1, 1 } },
2899 { ISD::TRUNCATE, MVT::v4i1, MVT::v8i16, { 2, 1, 1, 1 } },
2900 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 2, 1, 1, 1 } },
2901 { ISD::TRUNCATE, MVT::v8i1, MVT::v16i8, { 2, 1, 1, 1 } },
2902 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 2, 1, 1, 1 } },
2903 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 2, 1, 1, 1 } },
2904 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 2, 1, 1, 1 } },
2905 { ISD::TRUNCATE, MVT::v32i1, MVT::v32i8, { 2, 1, 1, 1 } },
2906 { ISD::TRUNCATE, MVT::v32i1, MVT::v32i16, { 2, 1, 1, 1 } },
2907 { ISD::TRUNCATE, MVT::v64i1, MVT::v64i8, { 2, 1, 1, 1 } },
2908 { ISD::TRUNCATE, MVT::v64i1, MVT::v32i16, { 2, 1, 1, 1 } },
2909
2910 { ISD::TRUNCATE, MVT::v32i8, MVT::v32i16, { 2, 1, 1, 1 } },
2911 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 2, 1, 1, 1 } }, // widen to zmm
2912 { ISD::TRUNCATE, MVT::v2i8, MVT::v2i16, { 2, 1, 1, 1 } }, // vpmovwb
2913 { ISD::TRUNCATE, MVT::v4i8, MVT::v4i16, { 2, 1, 1, 1 } }, // vpmovwb
2914 { ISD::TRUNCATE, MVT::v8i8, MVT::v8i16, { 2, 1, 1, 1 } }, // vpmovwb
2915 };
2916
2917 static const TypeConversionCostKindTblEntry AVX512DQConversionTbl[] = {
2918 // Mask sign extend has an instruction.
2919 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } },
2920 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v2i1, { 1, 1, 1, 1 } },
2921 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } },
2922 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } },
2923 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } },
2924 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v16i1, { 1, 1, 1, 1 } },
2925 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i1, { 1, 1, 1, 1 } },
2926 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i1, { 1, 1, 1, 1 } },
2927
2928 // Mask zero extend is a sext + shift.
2929 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1, } },
2930 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v2i1, { 2, 1, 1, 1, } },
2931 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1, } },
2932 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1, } },
2933 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1, } },
2934 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v16i1, { 2, 1, 1, 1, } },
2935 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i1, { 2, 1, 1, 1, } },
2936 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i1, { 2, 1, 1, 1, } },
2937
2938 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } },
2939 { ISD::TRUNCATE, MVT::v2i1, MVT::v4i32, { 2, 1, 1, 1 } },
2940 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } },
2941 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } },
2942 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } },
2943 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, { 2, 1, 1, 1 } },
2944 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i32, { 2, 1, 1, 1 } },
2945 { ISD::TRUNCATE, MVT::v16i1, MVT::v8i64, { 2, 1, 1, 1 } },
2946
2947 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i64, { 1, 1, 1, 1 } },
2948 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i64, { 1, 1, 1, 1 } },
2949
2950 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i64, { 1, 1, 1, 1 } },
2951 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i64, { 1, 1, 1, 1 } },
2952
2953 { ISD::FP_TO_SINT, MVT::v8i64, MVT::v8f32, { 1, 1, 1, 1 } },
2954 { ISD::FP_TO_SINT, MVT::v8i64, MVT::v8f64, { 1, 1, 1, 1 } },
2955
2956 { ISD::FP_TO_UINT, MVT::v8i64, MVT::v8f32, { 1, 1, 1, 1 } },
2957 { ISD::FP_TO_UINT, MVT::v8i64, MVT::v8f64, { 1, 1, 1, 1 } },
2958 };
2959
2960 // TODO: For AVX512DQ + AVX512VL, we also have cheap casts for 128-bit and
2961 // 256-bit wide vectors.
2962
2963 static const TypeConversionCostKindTblEntry AVX512FConversionTbl[] = {
2964 { ISD::FP_EXTEND, MVT::v8f64, MVT::v8f32, { 1, 1, 1, 1 } },
2965 { ISD::FP_EXTEND, MVT::v8f64, MVT::v16f32, { 3, 1, 1, 1 } },
2966 { ISD::FP_EXTEND, MVT::v16f64, MVT::v16f32, { 4, 1, 1, 1 } }, // 2*vcvtps2pd+vextractf64x4
2967 { ISD::FP_EXTEND, MVT::v16f32, MVT::v16f16, { 1, 1, 1, 1 } }, // vcvtph2ps
2968 { ISD::FP_EXTEND, MVT::v8f64, MVT::v8f16, { 2, 1, 1, 1 } }, // vcvtph2ps+vcvtps2pd
2969 { ISD::FP_ROUND, MVT::v8f32, MVT::v8f64, { 1, 1, 1, 1 } },
2970 { ISD::FP_ROUND, MVT::v16f16, MVT::v16f32, { 1, 1, 1, 1 } }, // vcvtps2ph
2971
2972 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
2973 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
2974 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
2975 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
2976 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
2977 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
2978 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
2979 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
2980 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, { 2, 1, 1, 1 } }, // zmm vpslld+vptestmd
2981 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } }, // zmm vpslld+vptestmd
2982 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } }, // zmm vpslld+vptestmd
2983 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd
2984 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } }, // zmm vpsllq+vptestmq
2985 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } }, // zmm vpsllq+vptestmq
2986 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, { 2, 1, 1, 1 } }, // vpsllq+vptestmq
2987 { ISD::TRUNCATE, MVT::v2i8, MVT::v2i32, { 2, 1, 1, 1 } }, // vpmovdb
2988 { ISD::TRUNCATE, MVT::v4i8, MVT::v4i32, { 2, 1, 1, 1 } }, // vpmovdb
2989 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdb
2990 { ISD::TRUNCATE, MVT::v32i8, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdb
2991 { ISD::TRUNCATE, MVT::v64i8, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdb
2992 { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdw
2993 { ISD::TRUNCATE, MVT::v32i16, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdw
2994 { ISD::TRUNCATE, MVT::v2i8, MVT::v2i64, { 2, 1, 1, 1 } }, // vpmovqb
2995 { ISD::TRUNCATE, MVT::v2i16, MVT::v2i64, { 1, 1, 1, 1 } }, // vpshufb
2996 { ISD::TRUNCATE, MVT::v8i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb
2997 { ISD::TRUNCATE, MVT::v16i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb
2998 { ISD::TRUNCATE, MVT::v32i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb
2999 { ISD::TRUNCATE, MVT::v64i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb
3000 { ISD::TRUNCATE, MVT::v8i16, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqw
3001 { ISD::TRUNCATE, MVT::v16i16, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqw
3002 { ISD::TRUNCATE, MVT::v32i16, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqw
3003 { ISD::TRUNCATE, MVT::v8i32, MVT::v8i64, { 1, 1, 1, 1 } }, // vpmovqd
3004 { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 1, 1, 1, 1 } }, // zmm vpmovqd
3005 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i64, { 5, 1, 1, 1 } },// 2*vpmovqd+concat+vpmovdb
3006
3007 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 3, 1, 1, 1 } }, // extend to v16i32
3008 { ISD::TRUNCATE, MVT::v32i8, MVT::v32i16, { 8, 1, 1, 1 } },
3009 { ISD::TRUNCATE, MVT::v64i8, MVT::v32i16, { 8, 1, 1, 1 } },
3010
3011 // Sign extend is zmm vpternlogd+vptruncdb.
3012 // Zero extend is zmm broadcast load+vptruncdw.
3013 { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 3, 1, 1, 1 } },
3014 { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 4, 1, 1, 1 } },
3015 { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 3, 1, 1, 1 } },
3016 { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 4, 1, 1, 1 } },
3017 { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 3, 1, 1, 1 } },
3018 { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 4, 1, 1, 1 } },
3019 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, { 3, 1, 1, 1 } },
3020 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, { 4, 1, 1, 1 } },
3021
3022 // Sign extend is zmm vpternlogd+vptruncdw.
3023 // Zero extend is zmm vpternlogd+vptruncdw+vpsrlw.
3024 { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 3, 1, 1, 1 } },
3025 { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 4, 1, 1, 1 } },
3026 { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 3, 1, 1, 1 } },
3027 { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 4, 1, 1, 1 } },
3028 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 3, 1, 1, 1 } },
3029 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 4, 1, 1, 1 } },
3030 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 3, 1, 1, 1 } },
3031 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 4, 1, 1, 1 } },
3032
3033 { ISD::SIGN_EXTEND, MVT::v2i32, MVT::v2i1, { 1, 1, 1, 1 } }, // zmm vpternlogd
3034 { ISD::ZERO_EXTEND, MVT::v2i32, MVT::v2i1, { 2, 1, 1, 1 } }, // zmm vpternlogd+psrld
3035 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } }, // zmm vpternlogd
3036 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1 } }, // zmm vpternlogd+psrld
3037 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } }, // zmm vpternlogd
3038 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1 } }, // zmm vpternlogd+psrld
3039 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } }, // zmm vpternlogq
3040 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1 } }, // zmm vpternlogq+psrlq
3041 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } }, // zmm vpternlogq
3042 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1 } }, // zmm vpternlogq+psrlq
3043
3044 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i1, { 1, 1, 1, 1 } }, // vpternlogd
3045 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld
3046 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i1, { 1, 1, 1, 1 } }, // vpternlogq
3047 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i1, { 2, 1, 1, 1 } }, // vpternlogq+psrlq
3048
3049 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i8, { 1, 1, 1, 1 } },
3050 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i8, { 1, 1, 1, 1 } },
3051 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i16, { 1, 1, 1, 1 } },
3052 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i16, { 1, 1, 1, 1 } },
3053 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i8, { 1, 1, 1, 1 } },
3054 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i8, { 1, 1, 1, 1 } },
3055 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i16, { 1, 1, 1, 1 } },
3056 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i16, { 1, 1, 1, 1 } },
3057 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i32, { 1, 1, 1, 1 } },
3058 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i32, { 1, 1, 1, 1 } },
3059
3060 { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i8, { 3, 1, 1, 1 } }, // FIXME: May not be right
3061 { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i8, { 3, 1, 1, 1 } }, // FIXME: May not be right
3062
3063 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i1, { 4, 1, 1, 1 } },
3064 { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i1, { 3, 1, 1, 1 } },
3065 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v16i8, { 2, 1, 1, 1 } },
3066 { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i8, { 1, 1, 1, 1 } },
3067 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i16, { 2, 1, 1, 1 } },
3068 { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i16, { 1, 1, 1, 1 } },
3069 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, { 1, 1, 1, 1 } },
3070 { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i32, { 1, 1, 1, 1 } },
3071
3072 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i1, { 4, 1, 1, 1 } },
3073 { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i1, { 3, 1, 1, 1 } },
3074 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v16i8, { 2, 1, 1, 1 } },
3075 { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i8, { 1, 1, 1, 1 } },
3076 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i16, { 2, 1, 1, 1 } },
3077 { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i16, { 1, 1, 1, 1 } },
3078 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, { 1, 1, 1, 1 } },
3079 { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i32, { 1, 1, 1, 1 } },
3080 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i64, {26, 1, 1, 1 } },
3081 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i64, { 5, 1, 1, 1 } },
3082
3083 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f32, { 2, 1, 1, 1 } },
3084 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f64, { 7, 1, 1, 1 } },
3085 { ISD::FP_TO_SINT, MVT::v32i8, MVT::v32f64, {15, 1, 1, 1 } },
3086 { ISD::FP_TO_SINT, MVT::v64i8, MVT::v64f32, {11, 1, 1, 1 } },
3087 { ISD::FP_TO_SINT, MVT::v64i8, MVT::v64f64, {31, 1, 1, 1 } },
3088 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f64, { 3, 1, 1, 1 } },
3089 { ISD::FP_TO_SINT, MVT::v16i16, MVT::v16f64, { 7, 1, 1, 1 } },
3090 { ISD::FP_TO_SINT, MVT::v32i16, MVT::v32f32, { 5, 1, 1, 1 } },
3091 { ISD::FP_TO_SINT, MVT::v32i16, MVT::v32f64, {15, 1, 1, 1 } },
3092 { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, { 1, 1, 1, 1 } },
3093 { ISD::FP_TO_SINT, MVT::v16i32, MVT::v16f64, { 3, 1, 1, 1 } },
3094
3095 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f64, { 1, 1, 1, 1 } },
3096 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f64, { 3, 1, 1, 1 } },
3097 { ISD::FP_TO_UINT, MVT::v8i8, MVT::v8f64, { 3, 1, 1, 1 } },
3098 { ISD::FP_TO_UINT, MVT::v16i32, MVT::v16f32, { 1, 1, 1, 1 } },
3099 { ISD::FP_TO_UINT, MVT::v16i16, MVT::v16f32, { 3, 1, 1, 1 } },
3100 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v16f32, { 3, 1, 1, 1 } },
3101 };
3102
3103 static const TypeConversionCostKindTblEntry AVX512BWVLConversionTbl[] {
3104 // Mask sign extend has an instruction.
3105 { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 1, 1, 1, 1 } },
3106 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v2i1, { 1, 1, 1, 1 } },
3107 { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 1, 1, 1, 1 } },
3108 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v2i1, { 1, 1, 1, 1 } },
3109 { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 1, 1, 1, 1 } },
3110 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v4i1, { 1, 1, 1, 1 } },
3111 { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 1, 1, 1, 1 } },
3112 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v4i1, { 1, 1, 1, 1 } },
3113 { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 1, 1, 1, 1 } },
3114 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v8i1, { 1, 1, 1, 1 } },
3115 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 1, 1, 1, 1 } },
3116 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, { 1, 1, 1, 1 } },
3117 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } },
3118 { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v32i1, { 1, 1, 1, 1 } },
3119 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v32i1, { 1, 1, 1, 1 } },
3120 { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v64i1, { 1, 1, 1, 1 } },
3121 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v64i1, { 1, 1, 1, 1 } },
3122
3123 // Mask zero extend is a sext + shift.
3124 { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 2, 1, 1, 1 } },
3125 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v2i1, { 2, 1, 1, 1 } },
3126 { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 2, 1, 1, 1 } },
3127 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v2i1, { 2, 1, 1, 1 } },
3128 { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 2, 1, 1, 1 } },
3129 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v4i1, { 2, 1, 1, 1 } },
3130 { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 2, 1, 1, 1 } },
3131 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v4i1, { 2, 1, 1, 1 } },
3132 { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 2, 1, 1, 1 } },
3133 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v8i1, { 2, 1, 1, 1 } },
3134 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 2, 1, 1, 1 } },
3135 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, { 2, 1, 1, 1 } },
3136 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 2, 1, 1, 1 } },
3137 { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v32i1, { 2, 1, 1, 1 } },
3138 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v32i1, { 2, 1, 1, 1 } },
3139 { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v64i1, { 2, 1, 1, 1 } },
3140 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v64i1, { 2, 1, 1, 1 } },
3141
3142 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 2, 1, 1, 1 } },
3143 { ISD::TRUNCATE, MVT::v2i1, MVT::v16i8, { 2, 1, 1, 1 } },
3144 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 2, 1, 1, 1 } },
3145 { ISD::TRUNCATE, MVT::v2i1, MVT::v8i16, { 2, 1, 1, 1 } },
3146 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 2, 1, 1, 1 } },
3147 { ISD::TRUNCATE, MVT::v4i1, MVT::v16i8, { 2, 1, 1, 1 } },
3148 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 2, 1, 1, 1 } },
3149 { ISD::TRUNCATE, MVT::v4i1, MVT::v8i16, { 2, 1, 1, 1 } },
3150 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 2, 1, 1, 1 } },
3151 { ISD::TRUNCATE, MVT::v8i1, MVT::v16i8, { 2, 1, 1, 1 } },
3152 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 2, 1, 1, 1 } },
3153 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 2, 1, 1, 1 } },
3154 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 2, 1, 1, 1 } },
3155 { ISD::TRUNCATE, MVT::v32i1, MVT::v32i8, { 2, 1, 1, 1 } },
3156 { ISD::TRUNCATE, MVT::v32i1, MVT::v16i16, { 2, 1, 1, 1 } },
3157 { ISD::TRUNCATE, MVT::v64i1, MVT::v32i8, { 2, 1, 1, 1 } },
3158 { ISD::TRUNCATE, MVT::v64i1, MVT::v16i16, { 2, 1, 1, 1 } },
3159
3160 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 2, 1, 1, 1 } },
3161 };
3162
3163 static const TypeConversionCostKindTblEntry AVX512DQVLConversionTbl[] = {
3164 // Mask sign extend has an instruction.
3165 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } },
3166 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v2i1, { 1, 1, 1, 1 } },
3167 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } },
3168 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i1, { 1, 1, 1, 1 } },
3169 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } },
3170 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i1, { 1, 1, 1, 1 } },
3171 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i1, { 1, 1, 1, 1 } },
3172 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } },
3173
3174 // Mask zero extend is a sext + shift.
3175 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1 } },
3176 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v2i1, { 2, 1, 1, 1 } },
3177 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1 } },
3178 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i1, { 2, 1, 1, 1 } },
3179 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1 } },
3180 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i1, { 2, 1, 1, 1 } },
3181 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i1, { 2, 1, 1, 1 } },
3182 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1 } },
3183
3184 { ISD::TRUNCATE, MVT::v16i1, MVT::v4i64, { 2, 1, 1, 1 } },
3185 { ISD::TRUNCATE, MVT::v16i1, MVT::v8i32, { 2, 1, 1, 1 } },
3186 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } },
3187 { ISD::TRUNCATE, MVT::v2i1, MVT::v4i32, { 2, 1, 1, 1 } },
3188 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } },
3189 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } },
3190 { ISD::TRUNCATE, MVT::v8i1, MVT::v4i64, { 2, 1, 1, 1 } },
3191 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } },
3192
3193 { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i64, { 1, 1, 1, 1 } },
3194 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, { 1, 1, 1, 1 } },
3195 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i64, { 1, 1, 1, 1 } },
3196 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i64, { 1, 1, 1, 1 } },
3197
3198 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, { 1, 1, 1, 1 } },
3199 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 1, 1, 1, 1 } },
3200 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, { 1, 1, 1, 1 } },
3201 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, { 1, 1, 1, 1 } },
3202
3203 { ISD::FP_TO_SINT, MVT::v2i64, MVT::v4f32, { 1, 1, 1, 1 } },
3204 { ISD::FP_TO_SINT, MVT::v4i64, MVT::v4f32, { 1, 1, 1, 1 } },
3205 { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, { 1, 1, 1, 1 } },
3206 { ISD::FP_TO_SINT, MVT::v4i64, MVT::v4f64, { 1, 1, 1, 1 } },
3207
3208 { ISD::FP_TO_UINT, MVT::v2i64, MVT::v4f32, { 1, 1, 1, 1 } },
3209 { ISD::FP_TO_UINT, MVT::v4i64, MVT::v4f32, { 1, 1, 1, 1 } },
3210 { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, { 1, 1, 1, 1 } },
3211 { ISD::FP_TO_UINT, MVT::v4i64, MVT::v4f64, { 1, 1, 1, 1 } },
3212 };
3213
3214 static const TypeConversionCostKindTblEntry AVX512VLConversionTbl[] = {
3215 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
3216 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
3217 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
3218 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 8, 1, 1, 1 } }, // split+2*v8i8
3219 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
3220 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
3221 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
3222 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 8, 1, 1, 1 } }, // split+2*v8i16
3223 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd
3224 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd
3225 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd
3226 { ISD::TRUNCATE, MVT::v16i1, MVT::v8i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd
3227 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } }, // vpsllq+vptestmq
3228 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } }, // vpsllq+vptestmq
3229 { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 1, 1, 1, 1 } }, // vpmovqd
3230 { ISD::TRUNCATE, MVT::v4i8, MVT::v4i64, { 2, 1, 1, 1 } }, // vpmovqb
3231 { ISD::TRUNCATE, MVT::v4i16, MVT::v4i64, { 2, 1, 1, 1 } }, // vpmovqw
3232 { ISD::TRUNCATE, MVT::v8i8, MVT::v8i32, { 2, 1, 1, 1 } }, // vpmovwb
3233
3234 // sign extend is vpcmpeq+maskedmove+vpmovdw+vpacksswb
3235 // zero extend is vpcmpeq+maskedmove+vpmovdw+vpsrlw+vpackuswb
3236 { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 5, 1, 1, 1 } },
3237 { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 6, 1, 1, 1 } },
3238 { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 5, 1, 1, 1 } },
3239 { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 6, 1, 1, 1 } },
3240 { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 5, 1, 1, 1 } },
3241 { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 6, 1, 1, 1 } },
3242 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, {10, 1, 1, 1 } },
3243 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, {12, 1, 1, 1 } },
3244
3245 // sign extend is vpcmpeq+maskedmove+vpmovdw
3246 // zero extend is vpcmpeq+maskedmove+vpmovdw+vpsrlw
3247 { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 4, 1, 1, 1 } },
3248 { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 5, 1, 1, 1 } },
3249 { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 4, 1, 1, 1 } },
3250 { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 5, 1, 1, 1 } },
3251 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 4, 1, 1, 1 } },
3252 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 5, 1, 1, 1 } },
3253 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, {10, 1, 1, 1 } },
3254 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, {12, 1, 1, 1 } },
3255
3256 { ISD::SIGN_EXTEND, MVT::v2i32, MVT::v2i1, { 1, 1, 1, 1 } }, // vpternlogd
3257 { ISD::ZERO_EXTEND, MVT::v2i32, MVT::v2i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld
3258 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } }, // vpternlogd
3259 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld
3260 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } }, // vpternlogd
3261 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld
3262 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i1, { 1, 1, 1, 1 } }, // vpternlogd
3263 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld
3264
3265 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } }, // vpternlogq
3266 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1 } }, // vpternlogq+psrlq
3267 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } }, // vpternlogq
3268 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1 } }, // vpternlogq+psrlq
3269
3270 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, { 1, 1, 1, 1 } },
3271 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, { 1, 1, 1, 1 } },
3272 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, { 1, 1, 1, 1 } },
3273 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, { 1, 1, 1, 1 } },
3274 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, { 1, 1, 1, 1 } },
3275 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, { 1, 1, 1, 1 } },
3276 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, { 1, 1, 1, 1 } },
3277 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, { 1, 1, 1, 1 } },
3278 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, { 1, 1, 1, 1 } },
3279 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, { 1, 1, 1, 1 } },
3280 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, { 1, 1, 1, 1 } },
3281 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, { 1, 1, 1, 1 } },
3282
3283 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } },
3284 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, { 1, 1, 1, 1 } },
3285 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } },
3286 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, { 1, 1, 1, 1 } },
3287
3288 { ISD::UINT_TO_FP, MVT::f32, MVT::i64, { 1, 1, 1, 1 } },
3289 { ISD::UINT_TO_FP, MVT::f64, MVT::i64, { 1, 1, 1, 1 } },
3290 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } },
3291 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, { 1, 1, 1, 1 } },
3292 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } },
3293 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, { 1, 1, 1, 1 } },
3294 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 1, 1, 1, 1 } },
3295 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 1, 1, 1, 1 } },
3296 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, { 1, 1, 1, 1 } },
3297 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, { 1, 1, 1, 1 } },
3298 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, { 5, 1, 1, 1 } },
3299 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 5, 1, 1, 1 } },
3300 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, { 5, 1, 1, 1 } },
3301
3302 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v8f32, { 2, 1, 1, 1 } },
3303 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f32, { 2, 1, 1, 1 } },
3304 { ISD::FP_TO_SINT, MVT::v32i8, MVT::v32f32, { 5, 1, 1, 1 } },
3305
3306 { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 1, 1, 1, 1 } },
3307 { ISD::FP_TO_UINT, MVT::i64, MVT::f64, { 1, 1, 1, 1 } },
3308 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 1, 1, 1, 1 } },
3309 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 1, 1, 1, 1 } },
3310 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, { 1, 1, 1, 1 } },
3311 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, { 1, 1, 1, 1 } },
3312 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f64, { 1, 1, 1, 1 } },
3313 };
3314
3315 static const TypeConversionCostKindTblEntry AVX2ConversionTbl[] = {
3316 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 3, 1, 1, 1 } },
3317 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 3, 1, 1, 1 } },
3318 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 3, 1, 1, 1 } },
3319 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 3, 1, 1, 1 } },
3320 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } },
3321 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } },
3322
3323 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, { 2, 1, 1, 1 } },
3324 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, { 2, 1, 1, 1 } },
3325 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, { 2, 1, 1, 1 } },
3326 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, { 2, 1, 1, 1 } },
3327 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, { 2, 1, 1, 1 } },
3328 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, { 2, 1, 1, 1 } },
3329 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, { 2, 1, 1, 1 } },
3330 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, { 2, 1, 1, 1 } },
3331 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, { 2, 1, 1, 1 } },
3332 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, { 2, 1, 1, 1 } },
3333 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i16, { 3, 1, 1, 1 } },
3334 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i16, { 3, 1, 1, 1 } },
3335 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, { 2, 1, 1, 1 } },
3336 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, { 2, 1, 1, 1 } },
3337
3338 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } },
3339
3340 { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, { 4, 1, 1, 1 } },
3341 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 4, 1, 1, 1 } },
3342 { ISD::TRUNCATE, MVT::v16i8, MVT::v8i16, { 1, 1, 1, 1 } },
3343 { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, { 1, 1, 1, 1 } },
3344 { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, { 1, 1, 1, 1 } },
3345 { ISD::TRUNCATE, MVT::v16i8, MVT::v8i32, { 4, 1, 1, 1 } },
3346 { ISD::TRUNCATE, MVT::v16i8, MVT::v4i64, { 4, 1, 1, 1 } },
3347 { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, { 1, 1, 1, 1 } },
3348 { ISD::TRUNCATE, MVT::v8i16, MVT::v2i64, { 1, 1, 1, 1 } },
3349 { ISD::TRUNCATE, MVT::v8i16, MVT::v4i64, { 5, 1, 1, 1 } },
3350 { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 1, 1, 1, 1 } },
3351 { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, { 2, 1, 1, 1 } },
3352
3353 { ISD::FP_EXTEND, MVT::v8f64, MVT::v8f32, { 3, 1, 1, 1 } },
3354 { ISD::FP_ROUND, MVT::v8f32, MVT::v8f64, { 3, 1, 1, 1 } },
3355
3356 { ISD::FP_TO_SINT, MVT::v16i16, MVT::v8f32, { 1, 1, 1, 1 } },
3357 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f64, { 1, 1, 1, 1 } },
3358 { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f32, { 1, 1, 1, 1 } },
3359 { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, { 3, 1, 1, 1 } },
3360
3361 { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 3, 1, 1, 1 } },
3362 { ISD::FP_TO_UINT, MVT::i64, MVT::f64, { 3, 1, 1, 1 } },
3363 { ISD::FP_TO_UINT, MVT::v16i16, MVT::v8f32, { 1, 1, 1, 1 } },
3364 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 3, 1, 1, 1 } },
3365 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } },
3366 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, { 4, 1, 1, 1 } },
3367 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, { 3, 1, 1, 1 } },
3368 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v4f64, { 4, 1, 1, 1 } },
3369
3370 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 2, 1, 1, 1 } },
3371 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, { 2, 1, 1, 1 } },
3372 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 2, 1, 1, 1 } },
3373 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, { 2, 1, 1, 1 } },
3374 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, { 1, 1, 1, 1 } },
3375 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i32, { 1, 1, 1, 1 } },
3376 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, { 3, 1, 1, 1 } },
3377
3378 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 2, 1, 1, 1 } },
3379 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, { 2, 1, 1, 1 } },
3380 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 2, 1, 1, 1 } },
3381 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, { 2, 1, 1, 1 } },
3382 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 2, 1, 1, 1 } },
3383 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, { 1, 1, 1, 1 } },
3384 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 2, 1, 1, 1 } },
3385 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, { 2, 1, 1, 1 } },
3386 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, { 2, 1, 1, 1 } },
3387 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, { 4, 1, 1, 1 } },
3388 };
3389
3390 static const TypeConversionCostKindTblEntry AVXConversionTbl[] = {
3391 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 4, 1, 1, 1 } },
3392 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 4, 1, 1, 1 } },
3393 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 4, 1, 1, 1 } },
3394 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 4, 1, 1, 1 } },
3395 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 4, 1, 1, 1 } },
3396 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 4, 1, 1, 1 } },
3397
3398 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, { 3, 1, 1, 1 } },
3399 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, { 3, 1, 1, 1 } },
3400 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, { 3, 1, 1, 1 } },
3401 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, { 3, 1, 1, 1 } },
3402 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, { 3, 1, 1, 1 } },
3403 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, { 3, 1, 1, 1 } },
3404 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, { 3, 1, 1, 1 } },
3405 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, { 3, 1, 1, 1 } },
3406 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, { 3, 1, 1, 1 } },
3407 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, { 3, 1, 1, 1 } },
3408 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, { 3, 1, 1, 1 } },
3409 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, { 3, 1, 1, 1 } },
3410
3411 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 4, 1, 1, 1 } },
3412 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 5, 1, 1, 1 } },
3413 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 4, 1, 1, 1 } },
3414 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, { 9, 1, 1, 1 } },
3415 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i64, {11, 1, 1, 1 } },
3416
3417 { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, { 6, 1, 1, 1 } },
3418 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 6, 1, 1, 1 } },
3419 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 2, 1, 1, 1 } }, // and+extract+packuswb
3420 { ISD::TRUNCATE, MVT::v16i8, MVT::v8i32, { 5, 1, 1, 1 } },
3421 { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, { 5, 1, 1, 1 } },
3422 { ISD::TRUNCATE, MVT::v16i8, MVT::v4i64, { 5, 1, 1, 1 } },
3423 { ISD::TRUNCATE, MVT::v8i16, MVT::v4i64, { 3, 1, 1, 1 } }, // and+extract+2*packusdw
3424 { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 2, 1, 1, 1 } },
3425
3426 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i1, { 3, 1, 1, 1 } },
3427 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i1, { 3, 1, 1, 1 } },
3428 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i1, { 8, 1, 1, 1 } },
3429 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, { 4, 1, 1, 1 } },
3430 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v16i8, { 2, 1, 1, 1 } },
3431 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, { 4, 1, 1, 1 } },
3432 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v8i16, { 2, 1, 1, 1 } },
3433 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, { 2, 1, 1, 1 } },
3434 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i32, { 2, 1, 1, 1 } },
3435 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, { 4, 1, 1, 1 } },
3436 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v2i64, { 5, 1, 1, 1 } },
3437 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i64, { 8, 1, 1, 1 } },
3438
3439 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i1, { 7, 1, 1, 1 } },
3440 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i1, { 7, 1, 1, 1 } },
3441 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i1, { 6, 1, 1, 1 } },
3442 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, { 4, 1, 1, 1 } },
3443 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v16i8, { 2, 1, 1, 1 } },
3444 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, { 4, 1, 1, 1 } },
3445 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v8i16, { 2, 1, 1, 1 } },
3446 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 4, 1, 1, 1 } },
3447 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, { 4, 1, 1, 1 } },
3448 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 5, 1, 1, 1 } },
3449 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, { 6, 1, 1, 1 } },
3450 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, { 8, 1, 1, 1 } },
3451 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, {10, 1, 1, 1 } },
3452 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, {11, 1, 1, 1 } },
3453 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, {18, 1, 1, 1 } },
3454 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 5, 1, 1, 1 } },
3455 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, {10, 1, 1, 1 } },
3456
3457 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v8f32, { 2, 1, 1, 1 } },
3458 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f64, { 2, 1, 1, 1 } },
3459 { ISD::FP_TO_SINT, MVT::v32i8, MVT::v8f32, { 2, 1, 1, 1 } },
3460 { ISD::FP_TO_SINT, MVT::v32i8, MVT::v4f64, { 2, 1, 1, 1 } },
3461 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f32, { 2, 1, 1, 1 } },
3462 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f64, { 2, 1, 1, 1 } },
3463 { ISD::FP_TO_SINT, MVT::v16i16, MVT::v8f32, { 2, 1, 1, 1 } },
3464 { ISD::FP_TO_SINT, MVT::v16i16, MVT::v4f64, { 2, 1, 1, 1 } },
3465 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f64, { 2, 1, 1, 1 } },
3466 { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f32, { 2, 1, 1, 1 } },
3467 { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, { 5, 1, 1, 1 } },
3468
3469 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v8f32, { 2, 1, 1, 1 } },
3470 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f64, { 2, 1, 1, 1 } },
3471 { ISD::FP_TO_UINT, MVT::v32i8, MVT::v8f32, { 2, 1, 1, 1 } },
3472 { ISD::FP_TO_UINT, MVT::v32i8, MVT::v4f64, { 2, 1, 1, 1 } },
3473 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f32, { 2, 1, 1, 1 } },
3474 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f64, { 2, 1, 1, 1 } },
3475 { ISD::FP_TO_UINT, MVT::v16i16, MVT::v8f32, { 2, 1, 1, 1 } },
3476 { ISD::FP_TO_UINT, MVT::v16i16, MVT::v4f64, { 2, 1, 1, 1 } },
3477 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 3, 1, 1, 1 } },
3478 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } },
3479 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, { 6, 1, 1, 1 } },
3480 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, { 7, 1, 1, 1 } },
3481 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v4f64, { 7, 1, 1, 1 } },
3482
3483 { ISD::FP_EXTEND, MVT::v4f64, MVT::v4f32, { 1, 1, 1, 1 } },
3484 { ISD::FP_ROUND, MVT::v4f32, MVT::v4f64, { 1, 1, 1, 1 } },
3485 };
3486
3487 static const TypeConversionCostKindTblEntry SSE41ConversionTbl[] = {
3488 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v16i8, { 1, 1, 1, 1 } },
3489 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v16i8, { 1, 1, 1, 1 } },
3490 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v16i8, { 1, 1, 1, 1 } },
3491 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v16i8, { 1, 1, 1, 1 } },
3492 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v16i8, { 1, 1, 1, 1 } },
3493 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v16i8, { 1, 1, 1, 1 } },
3494 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v8i16, { 1, 1, 1, 1 } },
3495 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v8i16, { 1, 1, 1, 1 } },
3496 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v8i16, { 1, 1, 1, 1 } },
3497 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v8i16, { 1, 1, 1, 1 } },
3498 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v4i32, { 1, 1, 1, 1 } },
3499 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v4i32, { 1, 1, 1, 1 } },
3500
3501 // These truncates end up widening elements.
3502 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 1, 1, 1, 1 } }, // PMOVXZBQ
3503 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 1, 1, 1, 1 } }, // PMOVXZWQ
3504 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 1, 1, 1, 1 } }, // PMOVXZBD
3505
3506 { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, { 2, 1, 1, 1 } },
3507 { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, { 2, 1, 1, 1 } },
3508 { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, { 2, 1, 1, 1 } },
3509
3510 { ISD::SINT_TO_FP, MVT::f32, MVT::i32, { 1, 1, 1, 1 } },
3511 { ISD::SINT_TO_FP, MVT::f64, MVT::i32, { 1, 1, 1, 1 } },
3512 { ISD::SINT_TO_FP, MVT::f32, MVT::i64, { 1, 1, 1, 1 } },
3513 { ISD::SINT_TO_FP, MVT::f64, MVT::i64, { 1, 1, 1, 1 } },
3514 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v16i8, { 1, 1, 1, 1 } },
3515 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } },
3516 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v8i16, { 1, 1, 1, 1 } },
3517 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } },
3518 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, { 1, 1, 1, 1 } },
3519 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v4i32, { 1, 1, 1, 1 } },
3520 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, { 2, 1, 1, 1 } },
3521
3522 { ISD::UINT_TO_FP, MVT::f32, MVT::i32, { 1, 1, 1, 1 } },
3523 { ISD::UINT_TO_FP, MVT::f64, MVT::i32, { 1, 1, 1, 1 } },
3524 { ISD::UINT_TO_FP, MVT::f32, MVT::i64, { 4, 1, 1, 1 } },
3525 { ISD::UINT_TO_FP, MVT::f64, MVT::i64, { 4, 1, 1, 1 } },
3526 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v16i8, { 1, 1, 1, 1 } },
3527 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } },
3528 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v8i16, { 1, 1, 1, 1 } },
3529 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } },
3530 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 3, 1, 1, 1 } },
3531 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 3, 1, 1, 1 } },
3532 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v4i32, { 2, 1, 1, 1 } },
3533 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v2i64, {12, 1, 1, 1 } },
3534 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, {22, 1, 1, 1 } },
3535 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 4, 1, 1, 1 } },
3536
3537 { ISD::FP_TO_SINT, MVT::i32, MVT::f32, { 1, 1, 1, 1 } },
3538 { ISD::FP_TO_SINT, MVT::i64, MVT::f32, { 1, 1, 1, 1 } },
3539 { ISD::FP_TO_SINT, MVT::i32, MVT::f64, { 1, 1, 1, 1 } },
3540 { ISD::FP_TO_SINT, MVT::i64, MVT::f64, { 1, 1, 1, 1 } },
3541 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f32, { 2, 1, 1, 1 } },
3542 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v2f64, { 2, 1, 1, 1 } },
3543 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f32, { 1, 1, 1, 1 } },
3544 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v2f64, { 1, 1, 1, 1 } },
3545 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, { 1, 1, 1, 1 } },
3546 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v2f64, { 1, 1, 1, 1 } },
3547
3548 { ISD::FP_TO_UINT, MVT::i32, MVT::f32, { 1, 1, 1, 1 } },
3549 { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 4, 1, 1, 1 } },
3550 { ISD::FP_TO_UINT, MVT::i32, MVT::f64, { 1, 1, 1, 1 } },
3551 { ISD::FP_TO_UINT, MVT::i64, MVT::f64, { 4, 1, 1, 1 } },
3552 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f32, { 2, 1, 1, 1 } },
3553 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v2f64, { 2, 1, 1, 1 } },
3554 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f32, { 1, 1, 1, 1 } },
3555 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v2f64, { 1, 1, 1, 1 } },
3556 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 4, 1, 1, 1 } },
3557 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } },
3558 };
3559
3560 static const TypeConversionCostKindTblEntry SSE2ConversionTbl[] = {
3561 // These are somewhat magic numbers justified by comparing the
3562 // output of llvm-mca for our various supported scheduler models
3563 // and basing it off the worst case scenario.
3564 { ISD::SINT_TO_FP, MVT::f32, MVT::i32, { 3, 1, 1, 1 } },
3565 { ISD::SINT_TO_FP, MVT::f64, MVT::i32, { 3, 1, 1, 1 } },
3566 { ISD::SINT_TO_FP, MVT::f32, MVT::i64, { 3, 1, 1, 1 } },
3567 { ISD::SINT_TO_FP, MVT::f64, MVT::i64, { 3, 1, 1, 1 } },
3568 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v16i8, { 3, 1, 1, 1 } },
3569 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 4, 1, 1, 1 } },
3570 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v8i16, { 3, 1, 1, 1 } },
3571 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 4, 1, 1, 1 } },
3572 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, { 3, 1, 1, 1 } },
3573 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v4i32, { 4, 1, 1, 1 } },
3574 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v2i64, { 8, 1, 1, 1 } },
3575 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, { 8, 1, 1, 1 } },
3576
3577 { ISD::UINT_TO_FP, MVT::f32, MVT::i32, { 3, 1, 1, 1 } },
3578 { ISD::UINT_TO_FP, MVT::f64, MVT::i32, { 3, 1, 1, 1 } },
3579 { ISD::UINT_TO_FP, MVT::f32, MVT::i64, { 8, 1, 1, 1 } },
3580 { ISD::UINT_TO_FP, MVT::f64, MVT::i64, { 9, 1, 1, 1 } },
3581 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 4, 1, 1, 1 } },
3582 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v16i8, { 4, 1, 1, 1 } },
3583 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v8i16, { 4, 1, 1, 1 } },
3584 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 4, 1, 1, 1 } },
3585 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 7, 1, 1, 1 } },
3586 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v4i32, { 7, 1, 1, 1 } },
3587 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 5, 1, 1, 1 } },
3588 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, {15, 1, 1, 1 } },
3589 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v2i64, {18, 1, 1, 1 } },
3590
3591 { ISD::FP_TO_SINT, MVT::i32, MVT::f32, { 4, 1, 1, 1 } },
3592 { ISD::FP_TO_SINT, MVT::i64, MVT::f32, { 4, 1, 1, 1 } },
3593 { ISD::FP_TO_SINT, MVT::i32, MVT::f64, { 4, 1, 1, 1 } },
3594 { ISD::FP_TO_SINT, MVT::i64, MVT::f64, { 4, 1, 1, 1 } },
3595 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f32, { 6, 1, 1, 1 } },
3596 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v2f64, { 6, 1, 1, 1 } },
3597 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f32, { 5, 1, 1, 1 } },
3598 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v2f64, { 5, 1, 1, 1 } },
3599 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, { 4, 1, 1, 1 } },
3600 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } },
3601
3602 { ISD::FP_TO_UINT, MVT::i32, MVT::f32, { 4, 1, 1, 1 } },
3603 { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 4, 1, 1, 1 } },
3604 { ISD::FP_TO_UINT, MVT::i32, MVT::f64, { 4, 1, 1, 1 } },
3605 { ISD::FP_TO_UINT, MVT::i64, MVT::f64, {15, 1, 1, 1 } },
3606 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f32, { 6, 1, 1, 1 } },
3607 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v2f64, { 6, 1, 1, 1 } },
3608 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f32, { 5, 1, 1, 1 } },
3609 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v2f64, { 5, 1, 1, 1 } },
3610 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 8, 1, 1, 1 } },
3611 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 8, 1, 1, 1 } },
3612
3613 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v16i8, { 4, 1, 1, 1 } },
3614 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v16i8, { 4, 1, 1, 1 } },
3615 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v16i8, { 2, 1, 1, 1 } },
3616 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v16i8, { 3, 1, 1, 1 } },
3617 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v16i8, { 1, 1, 1, 1 } },
3618 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v16i8, { 2, 1, 1, 1 } },
3619 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v8i16, { 2, 1, 1, 1 } },
3620 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v8i16, { 3, 1, 1, 1 } },
3621 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v8i16, { 1, 1, 1, 1 } },
3622 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v8i16, { 2, 1, 1, 1 } },
3623 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v4i32, { 1, 1, 1, 1 } },
3624 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v4i32, { 2, 1, 1, 1 } },
3625
3626 // These truncates are really widening elements.
3627 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, { 1, 1, 1, 1 } }, // PSHUFD
3628 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 2, 1, 1, 1 } }, // PUNPCKLWD+DQ
3629 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 3, 1, 1, 1 } }, // PUNPCKLBW+WD+PSHUFD
3630 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 1, 1, 1, 1 } }, // PUNPCKLWD
3631 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 2, 1, 1, 1 } }, // PUNPCKLBW+WD
3632 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 1, 1, 1, 1 } }, // PUNPCKLBW
3633
3634 { ISD::TRUNCATE, MVT::v16i8, MVT::v8i16, { 2, 1, 1, 1 } }, // PAND+PACKUSWB
3635 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 3, 1, 1, 1 } },
3636 { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, { 3, 1, 1, 1 } }, // PAND+2*PACKUSWB
3637 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 7, 1, 1, 1 } },
3638 { ISD::TRUNCATE, MVT::v2i16, MVT::v2i32, { 1, 1, 1, 1 } },
3639 { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, { 3, 1, 1, 1 } },
3640 { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, { 5, 1, 1, 1 } },
3641 { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, {10, 1, 1, 1 } },
3642 { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, { 4, 1, 1, 1 } }, // PAND+3*PACKUSWB
3643 { ISD::TRUNCATE, MVT::v8i16, MVT::v2i64, { 2, 1, 1, 1 } }, // PSHUFD+PSHUFLW
3644 { ISD::TRUNCATE, MVT::v4i32, MVT::v2i64, { 1, 1, 1, 1 } }, // PSHUFD
3645 };
3646
3647 static const TypeConversionCostKindTblEntry F16ConversionTbl[] = {
3648 { ISD::FP_ROUND, MVT::f16, MVT::f32, { 1, 1, 1, 1 } },
3649 { ISD::FP_ROUND, MVT::v8f16, MVT::v8f32, { 1, 1, 1, 1 } },
3650 { ISD::FP_ROUND, MVT::v4f16, MVT::v4f32, { 1, 1, 1, 1 } },
3651 { ISD::FP_EXTEND, MVT::f32, MVT::f16, { 1, 1, 1, 1 } },
3652 { ISD::FP_EXTEND, MVT::f64, MVT::f16, { 2, 1, 1, 1 } }, // vcvtph2ps+vcvtps2pd
3653 { ISD::FP_EXTEND, MVT::v8f32, MVT::v8f16, { 1, 1, 1, 1 } },
3654 { ISD::FP_EXTEND, MVT::v4f32, MVT::v4f16, { 1, 1, 1, 1 } },
3655 { ISD::FP_EXTEND, MVT::v4f64, MVT::v4f16, { 2, 1, 1, 1 } }, // vcvtph2ps+vcvtps2pd
3656 };
3657
3658 // Attempt to map directly to (simple) MVT types to let us match custom entries.
3659 EVT SrcTy = TLI->getValueType(DL, Src);
3660 EVT DstTy = TLI->getValueType(DL, Dst);
3661
3662 // If we're sign-extending a vector comparison result back to the comparison
3663 // width, this will be free without AVX512 (or for 8/16-bit types without
3664 // BWI).
3665 if (!ST->hasAVX512() || (!ST->hasBWI() && DstTy.getScalarSizeInBits() < 32)) {
3666 if (I && Opcode == Instruction::CastOps::SExt &&
3667 SrcTy.isFixedLengthVectorOf(MVT::i1)) {
3668 if (auto *CmpI = dyn_cast<CmpInst>(I->getOperand(0))) {
3669 Type *CmpTy = CmpI->getOperand(0)->getType();
3670 if (CmpTy->getScalarSizeInBits() == DstTy.getScalarSizeInBits())
3671 return TTI::TCC_Free;
3672 }
3673 }
3674 }
3675
3676 // The function getSimpleVT only handles simple value types.
3677 if (SrcTy.isSimple() && DstTy.isSimple()) {
3678 MVT SimpleSrcTy = SrcTy.getSimpleVT();
3679 MVT SimpleDstTy = DstTy.getSimpleVT();
3680
3681 if (ST->useAVX512Regs()) {
3682 if (ST->hasBWI())
3683 if (const auto *Entry = ConvertCostTableLookup(
3684 AVX512BWConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
3685 if (auto KindCost = Entry->Cost[CostKind])
3686 return *KindCost;
3687
3688 if (ST->hasDQI())
3689 if (const auto *Entry = ConvertCostTableLookup(
3690 AVX512DQConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
3691 if (auto KindCost = Entry->Cost[CostKind])
3692 return *KindCost;
3693
3694 if (ST->hasAVX512())
3695 if (const auto *Entry = ConvertCostTableLookup(
3696 AVX512FConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
3697 if (auto KindCost = Entry->Cost[CostKind])
3698 return *KindCost;
3699 }
3700
3701 if (ST->hasBWI())
3702 if (const auto *Entry = ConvertCostTableLookup(
3703 AVX512BWVLConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
3704 if (auto KindCost = Entry->Cost[CostKind])
3705 return *KindCost;
3706
3707 if (ST->hasDQI())
3708 if (const auto *Entry = ConvertCostTableLookup(
3709 AVX512DQVLConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
3710 if (auto KindCost = Entry->Cost[CostKind])
3711 return *KindCost;
3712
3713 if (ST->hasAVX512())
3714 if (const auto *Entry = ConvertCostTableLookup(AVX512VLConversionTbl, ISD,
3715 SimpleDstTy, SimpleSrcTy))
3716 if (auto KindCost = Entry->Cost[CostKind])
3717 return *KindCost;
3718
3719 if (ST->hasAVX2()) {
3720 if (const auto *Entry = ConvertCostTableLookup(AVX2ConversionTbl, ISD,
3721 SimpleDstTy, SimpleSrcTy))
3722 if (auto KindCost = Entry->Cost[CostKind])
3723 return *KindCost;
3724 }
3725
3726 if (ST->hasAVX()) {
3727 if (const auto *Entry = ConvertCostTableLookup(AVXConversionTbl, ISD,
3728 SimpleDstTy, SimpleSrcTy))
3729 if (auto KindCost = Entry->Cost[CostKind])
3730 return *KindCost;
3731 }
3732
3733 if (ST->hasF16C()) {
3734 if (const auto *Entry = ConvertCostTableLookup(F16ConversionTbl, ISD,
3735 SimpleDstTy, SimpleSrcTy))
3736 if (auto KindCost = Entry->Cost[CostKind])
3737 return *KindCost;
3738 }
3739
3740 if (ST->hasSSE41()) {
3741 if (const auto *Entry = ConvertCostTableLookup(SSE41ConversionTbl, ISD,
3742 SimpleDstTy, SimpleSrcTy))
3743 if (auto KindCost = Entry->Cost[CostKind])
3744 return *KindCost;
3745 }
3746
3747 if (ST->hasSSE2()) {
3748 if (const auto *Entry = ConvertCostTableLookup(SSE2ConversionTbl, ISD,
3749 SimpleDstTy, SimpleSrcTy))
3750 if (auto KindCost = Entry->Cost[CostKind])
3751 return *KindCost;
3752 }
3753
3754 if ((ISD == ISD::FP_ROUND && SimpleDstTy == MVT::f16) ||
3755 (ISD == ISD::FP_EXTEND && SimpleSrcTy == MVT::f16)) {
3756 // fp16 conversions not covered by any table entries require a libcall.
3757 // Return a large (arbitrary) number to model this.
3758 return InstructionCost(64);
3759 }
3760 }
3761
3762 // Fall back to legalized types.
3763 std::pair<InstructionCost, MVT> LTSrc = getTypeLegalizationCost(Src);
3764 std::pair<InstructionCost, MVT> LTDest = getTypeLegalizationCost(Dst);
3765
3766 // If we're truncating to the same legalized type - just assume its free.
3767 if (ISD == ISD::TRUNCATE && LTSrc.second == LTDest.second)
3768 return TTI::TCC_Free;
3769
3770 if (ST->useAVX512Regs()) {
3771 if (ST->hasBWI())
3772 if (const auto *Entry = ConvertCostTableLookup(
3773 AVX512BWConversionTbl, ISD, LTDest.second, LTSrc.second))
3774 if (auto KindCost = Entry->Cost[CostKind])
3775 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3776
3777 if (ST->hasDQI())
3778 if (const auto *Entry = ConvertCostTableLookup(
3779 AVX512DQConversionTbl, ISD, LTDest.second, LTSrc.second))
3780 if (auto KindCost = Entry->Cost[CostKind])
3781 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3782
3783 if (ST->hasAVX512())
3784 if (const auto *Entry = ConvertCostTableLookup(
3785 AVX512FConversionTbl, ISD, LTDest.second, LTSrc.second))
3786 if (auto KindCost = Entry->Cost[CostKind])
3787 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3788 }
3789
3790 if (ST->hasBWI())
3791 if (const auto *Entry = ConvertCostTableLookup(AVX512BWVLConversionTbl, ISD,
3792 LTDest.second, LTSrc.second))
3793 if (auto KindCost = Entry->Cost[CostKind])
3794 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3795
3796 if (ST->hasDQI())
3797 if (const auto *Entry = ConvertCostTableLookup(AVX512DQVLConversionTbl, ISD,
3798 LTDest.second, LTSrc.second))
3799 if (auto KindCost = Entry->Cost[CostKind])
3800 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3801
3802 if (ST->hasAVX512())
3803 if (const auto *Entry = ConvertCostTableLookup(AVX512VLConversionTbl, ISD,
3804 LTDest.second, LTSrc.second))
3805 if (auto KindCost = Entry->Cost[CostKind])
3806 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3807
3808 if (ST->hasAVX2())
3809 if (const auto *Entry = ConvertCostTableLookup(AVX2ConversionTbl, ISD,
3810 LTDest.second, LTSrc.second))
3811 if (auto KindCost = Entry->Cost[CostKind])
3812 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3813
3814 if (ST->hasAVX())
3815 if (const auto *Entry = ConvertCostTableLookup(AVXConversionTbl, ISD,
3816 LTDest.second, LTSrc.second))
3817 if (auto KindCost = Entry->Cost[CostKind])
3818 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3819
3820 if (ST->hasF16C()) {
3821 if (const auto *Entry = ConvertCostTableLookup(F16ConversionTbl, ISD,
3822 LTDest.second, LTSrc.second))
3823 if (auto KindCost = Entry->Cost[CostKind])
3824 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3825 }
3826
3827 if (ST->hasSSE41())
3828 if (const auto *Entry = ConvertCostTableLookup(SSE41ConversionTbl, ISD,
3829 LTDest.second, LTSrc.second))
3830 if (auto KindCost = Entry->Cost[CostKind])
3831 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3832
3833 if (ST->hasSSE2())
3834 if (const auto *Entry = ConvertCostTableLookup(SSE2ConversionTbl, ISD,
3835 LTDest.second, LTSrc.second))
3836 if (auto KindCost = Entry->Cost[CostKind])
3837 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3838
3839 // Fallback, for i8/i16 sitofp/uitofp cases we need to extend to i32 for
3840 // sitofp.
3841 if ((ISD == ISD::SINT_TO_FP || ISD == ISD::UINT_TO_FP) &&
3842 1 < Src->getScalarSizeInBits() && Src->getScalarSizeInBits() < 32) {
3843 Type *ExtSrc = Src->getWithNewBitWidth(32);
3844 unsigned ExtOpc =
3845 (ISD == ISD::SINT_TO_FP) ? Instruction::SExt : Instruction::ZExt;
3846
3847 // For scalar loads the extend would be free.
3848 InstructionCost ExtCost = 0;
3849 if (!(Src->isIntegerTy() && I && isa<LoadInst>(I->getOperand(0))))
3850 ExtCost = getCastInstrCost(ExtOpc, ExtSrc, Src, CCH, CostKind);
3851
3852 return ExtCost + getCastInstrCost(Instruction::SIToFP, Dst, ExtSrc,
3853 TTI::CastContextHint::None, CostKind);
3854 }
3855
3856 // Fallback for fptosi/fptoui i8/i16 cases we need to truncate from fptosi
3857 // i32.
3858 if ((ISD == ISD::FP_TO_SINT || ISD == ISD::FP_TO_UINT) &&
3859 1 < Dst->getScalarSizeInBits() && Dst->getScalarSizeInBits() < 32) {
3860 Type *TruncDst = Dst->getWithNewBitWidth(32);
3861 return getCastInstrCost(Instruction::FPToSI, TruncDst, Src, CCH, CostKind) +
3862 getCastInstrCost(Instruction::Trunc, Dst, TruncDst,
3863 TTI::CastContextHint::None, CostKind);
3864 }
3865
3866 // TODO: Allow non-throughput costs that aren't binary.
3867 auto AdjustCost = [&CostKind](InstructionCost Cost,
3869 if (CostKind != TTI::TCK_RecipThroughput)
3870 return Cost == 0 ? 0 : N;
3871 return Cost * N;
3872 };
3873 return AdjustCost(
3874 BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I));
3875}
3876
3877// Additive cost for a predicated op's "predicate fanout": a select, masked
3878// load/store or gather/scatter keeps a compact <N x i1> mask, but if its data
3879// legalizes into more parts than the mask, codegen builds a sub-mask per extra
3880// part (kshiftr on AVX-512, unpack/extend on SSE/AVX) the per-part tables miss.
3881// FanoutCostPerPart is a tie-break: it beats the vectorizer's widest-VF bias.
3883 Type *DataVTy, Type *MaskVTy) {
3884 constexpr unsigned FanoutCostPerPart = 4;
3885 unsigned DataParts = TTI.getNumberOfParts(DataVTy);
3886 unsigned MaskParts = TTI.getNumberOfParts(MaskVTy);
3887 if (DataParts > MaskParts && MaskParts > 0)
3888 return InstructionCost((DataParts - MaskParts) * FanoutCostPerPart);
3889 return InstructionCost(0);
3890}
3891
3893 unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,
3895 TTI::OperandValueInfo Op2Info, const Instruction *I) const {
3896 // Early out if this type isn't scalar/vector integer/float.
3897 if (!(ValTy->isIntOrIntVectorTy() || ValTy->isFPOrFPVectorTy()))
3898 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
3899 Op1Info, Op2Info, I);
3900
3901 // Legalize the type.
3902 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
3903
3904 MVT MTy = LT.second;
3905
3906 int ISD = TLI->InstructionOpcodeToISD(Opcode);
3907 assert(ISD && "Invalid opcode");
3908
3909 // Predicate fanout (see getPredicateFanoutCost), AVX-512 only: on SSE/AVX a
3910 // select blend is already priced per part, so charging it there shrinks VF.
3911 InstructionCost MaskExpCost = 0;
3912 if (Opcode == Instruction::Select && ST->hasAVX512() &&
3914 MaskExpCost = getPredicateFanoutCost(*this, ValTy, CondTy);
3915
3916 InstructionCost ExtraCost = 0;
3917 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) {
3918 // Some vector comparison predicates cost extra instructions.
3919 // TODO: Adjust ExtraCost based on CostKind?
3920 // TODO: Should we invert this and assume worst case cmp costs
3921 // and reduce for particular predicates?
3922 if (MTy.isVector() &&
3923 !((ST->hasXOP() && (!ST->hasAVX2() || MTy.is128BitVector())) ||
3924 (ST->hasAVX512() && 32 <= MTy.getScalarSizeInBits()) ||
3925 ST->hasBWI())) {
3926 // Fallback to I if a specific predicate wasn't specified.
3927 CmpInst::Predicate Pred = VecPred;
3928 if (I && (Pred == CmpInst::BAD_ICMP_PREDICATE ||
3930 Pred = cast<CmpInst>(I)->getPredicate();
3931
3932 bool CmpWithConstant = false;
3933 if (auto *CmpInstr = dyn_cast_or_null<CmpInst>(I))
3934 CmpWithConstant = isa<Constant>(CmpInstr->getOperand(1));
3935
3936 switch (Pred) {
3938 // xor(cmpeq(x,y),-1)
3939 ExtraCost = CmpWithConstant ? 0 : 1;
3940 break;
3943 // xor(cmpgt(x,y),-1)
3944 ExtraCost = CmpWithConstant ? 0 : 1;
3945 break;
3948 // cmpgt(xor(x,signbit),xor(y,signbit))
3949 // xor(cmpeq(pmaxu(x,y),x),-1)
3950 ExtraCost = CmpWithConstant ? 1 : 2;
3951 break;
3954 if ((ST->hasSSE41() && MTy.getScalarSizeInBits() == 32) ||
3955 (ST->hasSSE2() && MTy.getScalarSizeInBits() < 32)) {
3956 // cmpeq(psubus(x,y),0)
3957 // cmpeq(pminu(x,y),x)
3958 ExtraCost = 1;
3959 } else {
3960 // xor(cmpgt(xor(x,signbit),xor(y,signbit)),-1)
3961 ExtraCost = CmpWithConstant ? 2 : 3;
3962 }
3963 break;
3966 // Without AVX we need to expand FCMP_ONE/FCMP_UEQ cases.
3967 // Use FCMP_UEQ expansion - FCMP_ONE should be the same.
3968 if (CondTy && !ST->hasAVX())
3969 return getCmpSelInstrCost(Opcode, ValTy, CondTy,
3971 Op1Info, Op2Info) +
3972 getCmpSelInstrCost(Opcode, ValTy, CondTy,
3974 Op1Info, Op2Info) +
3975 getArithmeticInstrCost(Instruction::Or, CondTy, CostKind);
3976
3977 break;
3980 // Assume worst case scenario and add the maximum extra cost.
3981 ExtraCost = 3;
3982 break;
3983 default:
3984 break;
3985 }
3986 }
3987 }
3988
3989 static const CostKindTblEntry SLMCostTbl[] = {
3990 // slm pcmpeq/pcmpgt throughput is 2
3991 { ISD::SETCC, MVT::v2i64, { 2, 5, 1, 2 } },
3992 // slm pblendvb/blendvpd/blendvps throughput is 4
3993 { ISD::SELECT, MVT::v2f64, { 4, 4, 1, 3 } }, // vblendvpd
3994 { ISD::SELECT, MVT::v4f32, { 4, 4, 1, 3 } }, // vblendvps
3995 { ISD::SELECT, MVT::v2i64, { 4, 4, 1, 3 } }, // pblendvb
3996 { ISD::SELECT, MVT::v8i32, { 4, 4, 1, 3 } }, // pblendvb
3997 { ISD::SELECT, MVT::v8i16, { 4, 4, 1, 3 } }, // pblendvb
3998 { ISD::SELECT, MVT::v16i8, { 4, 4, 1, 3 } }, // pblendvb
3999 };
4000
4001 static const CostKindTblEntry AVX512BWCostTbl[] = {
4002 { ISD::SETCC, MVT::v32i16, { 1, 1, 1, 1 } },
4003 { ISD::SETCC, MVT::v16i16, { 1, 1, 1, 1 } },
4004 { ISD::SETCC, MVT::v64i8, { 1, 1, 1, 1 } },
4005 { ISD::SETCC, MVT::v32i8, { 1, 1, 1, 1 } },
4006
4007 { ISD::SELECT, MVT::v32i16, { 1, 1, 1, 1 } },
4008 { ISD::SELECT, MVT::v64i8, { 1, 1, 1, 1 } },
4009 };
4010
4011 static const CostKindTblEntry AVX512CostTbl[] = {
4012 { ISD::SETCC, MVT::v8f64, { 1, 4, 1, 1 } },
4013 { ISD::SETCC, MVT::v4f64, { 1, 4, 1, 1 } },
4014 { ISD::SETCC, MVT::v16f32, { 1, 4, 1, 1 } },
4015 { ISD::SETCC, MVT::v8f32, { 1, 4, 1, 1 } },
4016
4017 { ISD::SETCC, MVT::v8i64, { 1, 1, 1, 1 } },
4018 { ISD::SETCC, MVT::v4i64, { 1, 1, 1, 1 } },
4019 { ISD::SETCC, MVT::v2i64, { 1, 1, 1, 1 } },
4020 { ISD::SETCC, MVT::v16i32, { 1, 1, 1, 1 } },
4021 { ISD::SETCC, MVT::v8i32, { 1, 1, 1, 1 } },
4022 { ISD::SETCC, MVT::v32i16, { 3, 7, 5, 5 } },
4023 { ISD::SETCC, MVT::v64i8, { 3, 7, 5, 5 } },
4024
4025 { ISD::SELECT, MVT::v8i64, { 1, 1, 1, 1 } },
4026 { ISD::SELECT, MVT::v4i64, { 1, 1, 1, 1 } },
4027 { ISD::SELECT, MVT::v2i64, { 1, 1, 1, 1 } },
4028 { ISD::SELECT, MVT::v16i32, { 1, 1, 1, 1 } },
4029 { ISD::SELECT, MVT::v8i32, { 1, 1, 1, 1 } },
4030 { ISD::SELECT, MVT::v4i32, { 1, 1, 1, 1 } },
4031 { ISD::SELECT, MVT::v8f64, { 1, 1, 1, 1 } },
4032 { ISD::SELECT, MVT::v4f64, { 1, 1, 1, 1 } },
4033 { ISD::SELECT, MVT::v2f64, { 1, 1, 1, 1 } },
4034 { ISD::SELECT, MVT::f64, { 1, 1, 1, 1 } },
4035 { ISD::SELECT, MVT::v16f32, { 1, 1, 1, 1 } },
4036 { ISD::SELECT, MVT::v8f32 , { 1, 1, 1, 1 } },
4037 { ISD::SELECT, MVT::v4f32, { 1, 1, 1, 1 } },
4038 { ISD::SELECT, MVT::f32 , { 1, 1, 1, 1 } },
4039
4040 { ISD::SELECT, MVT::v32i16, { 2, 2, 4, 4 } },
4041 { ISD::SELECT, MVT::v16i16, { 1, 1, 1, 1 } },
4042 { ISD::SELECT, MVT::v8i16, { 1, 1, 1, 1 } },
4043 { ISD::SELECT, MVT::v64i8, { 2, 2, 4, 4 } },
4044 { ISD::SELECT, MVT::v32i8, { 1, 1, 1, 1 } },
4045 { ISD::SELECT, MVT::v16i8, { 1, 1, 1, 1 } },
4046 };
4047
4048 static const CostKindTblEntry AVX2CostTbl[] = {
4049 { ISD::SETCC, MVT::v4f64, { 1, 4, 1, 2 } },
4050 { ISD::SETCC, MVT::v2f64, { 1, 4, 1, 1 } },
4051 { ISD::SETCC, MVT::f64, { 1, 4, 1, 1 } },
4052 { ISD::SETCC, MVT::v8f32, { 1, 4, 1, 2 } },
4053 { ISD::SETCC, MVT::v4f32, { 1, 4, 1, 1 } },
4054 { ISD::SETCC, MVT::f32, { 1, 4, 1, 1 } },
4055
4056 { ISD::SETCC, MVT::v4i64, { 1, 1, 1, 2 } },
4057 { ISD::SETCC, MVT::v8i32, { 1, 1, 1, 2 } },
4058 { ISD::SETCC, MVT::v16i16, { 1, 1, 1, 2 } },
4059 { ISD::SETCC, MVT::v32i8, { 1, 1, 1, 2 } },
4060
4061 { ISD::SELECT, MVT::v4f64, { 2, 2, 1, 2 } }, // vblendvpd
4062 { ISD::SELECT, MVT::v8f32, { 2, 2, 1, 2 } }, // vblendvps
4063 { ISD::SELECT, MVT::v4i64, { 2, 2, 1, 2 } }, // pblendvb
4064 { ISD::SELECT, MVT::v8i32, { 2, 2, 1, 2 } }, // pblendvb
4065 { ISD::SELECT, MVT::v16i16, { 2, 2, 1, 2 } }, // pblendvb
4066 { ISD::SELECT, MVT::v32i8, { 2, 2, 1, 2 } }, // pblendvb
4067 };
4068
4069 static const CostKindTblEntry XOPCostTbl[] = {
4070 { ISD::SETCC, MVT::v4i64, { 4, 2, 5, 6 } },
4071 { ISD::SETCC, MVT::v2i64, { 1, 1, 1, 1 } },
4072 };
4073
4074 static const CostKindTblEntry AVX1CostTbl[] = {
4075 { ISD::SETCC, MVT::v4f64, { 2, 3, 1, 2 } },
4076 { ISD::SETCC, MVT::v2f64, { 1, 3, 1, 1 } },
4077 { ISD::SETCC, MVT::f64, { 1, 3, 1, 1 } },
4078 { ISD::SETCC, MVT::v8f32, { 2, 3, 1, 2 } },
4079 { ISD::SETCC, MVT::v4f32, { 1, 3, 1, 1 } },
4080 { ISD::SETCC, MVT::f32, { 1, 3, 1, 1 } },
4081
4082 // AVX1 does not support 8-wide integer compare.
4083 { ISD::SETCC, MVT::v4i64, { 4, 2, 5, 6 } },
4084 { ISD::SETCC, MVT::v8i32, { 4, 2, 5, 6 } },
4085 { ISD::SETCC, MVT::v16i16, { 4, 2, 5, 6 } },
4086 { ISD::SETCC, MVT::v32i8, { 4, 2, 5, 6 } },
4087
4088 { ISD::SELECT, MVT::v4f64, { 3, 3, 1, 2 } }, // vblendvpd
4089 { ISD::SELECT, MVT::v8f32, { 3, 3, 1, 2 } }, // vblendvps
4090 { ISD::SELECT, MVT::v4i64, { 3, 3, 1, 2 } }, // vblendvpd
4091 { ISD::SELECT, MVT::v8i32, { 3, 3, 1, 2 } }, // vblendvps
4092 { ISD::SELECT, MVT::v16i16, { 3, 3, 3, 3 } }, // vandps + vandnps + vorps
4093 { ISD::SELECT, MVT::v32i8, { 3, 3, 3, 3 } }, // vandps + vandnps + vorps
4094 };
4095
4096 static const CostKindTblEntry SSE42CostTbl[] = {
4097 { ISD::SETCC, MVT::v2i64, { 1, 2, 1, 2 } },
4098 };
4099
4100 static const CostKindTblEntry SSE41CostTbl[] = {
4101 { ISD::SETCC, MVT::v2f64, { 1, 5, 1, 1 } },
4102 { ISD::SETCC, MVT::v4f32, { 1, 5, 1, 1 } },
4103
4104 { ISD::SELECT, MVT::v2f64, { 2, 2, 1, 2 } }, // blendvpd
4105 { ISD::SELECT, MVT::f64, { 2, 2, 1, 2 } }, // blendvpd
4106 { ISD::SELECT, MVT::v4f32, { 2, 2, 1, 2 } }, // blendvps
4107 { ISD::SELECT, MVT::f32 , { 2, 2, 1, 2 } }, // blendvps
4108 { ISD::SELECT, MVT::v2i64, { 2, 2, 1, 2 } }, // pblendvb
4109 { ISD::SELECT, MVT::v4i32, { 2, 2, 1, 2 } }, // pblendvb
4110 { ISD::SELECT, MVT::v8i16, { 2, 2, 1, 2 } }, // pblendvb
4111 { ISD::SELECT, MVT::v16i8, { 2, 2, 1, 2 } }, // pblendvb
4112 };
4113
4114 static const CostKindTblEntry SSE2CostTbl[] = {
4115 { ISD::SETCC, MVT::v2f64, { 2, 5, 1, 1 } },
4116 { ISD::SETCC, MVT::f64, { 1, 5, 1, 1 } },
4117
4118 { ISD::SETCC, MVT::v2i64, { 5, 4, 5, 5 } }, // pcmpeqd/pcmpgtd expansion
4119 { ISD::SETCC, MVT::v4i32, { 1, 1, 1, 1 } },
4120 { ISD::SETCC, MVT::v8i16, { 1, 1, 1, 1 } },
4121 { ISD::SETCC, MVT::v16i8, { 1, 1, 1, 1 } },
4122
4123 { ISD::SELECT, MVT::v2f64, { 2, 2, 3, 3 } }, // andpd + andnpd + orpd
4124 { ISD::SELECT, MVT::f64, { 2, 2, 3, 3 } }, // andpd + andnpd + orpd
4125 { ISD::SELECT, MVT::v2i64, { 2, 2, 3, 3 } }, // pand + pandn + por
4126 { ISD::SELECT, MVT::v4i32, { 2, 2, 3, 3 } }, // pand + pandn + por
4127 { ISD::SELECT, MVT::v8i16, { 2, 2, 3, 3 } }, // pand + pandn + por
4128 { ISD::SELECT, MVT::v16i8, { 2, 2, 3, 3 } }, // pand + pandn + por
4129 };
4130
4131 static const CostKindTblEntry SSE1CostTbl[] = {
4132 { ISD::SETCC, MVT::v4f32, { 2, 5, 1, 1 } },
4133 { ISD::SETCC, MVT::f32, { 1, 5, 1, 1 } },
4134
4135 { ISD::SELECT, MVT::v4f32, { 2, 2, 3, 3 } }, // andps + andnps + orps
4136 { ISD::SELECT, MVT::f32, { 2, 2, 3, 3 } }, // andps + andnps + orps
4137 };
4138
4139 if (ST->useSLMArithCosts())
4140 if (const auto *Entry = CostTableLookup(SLMCostTbl, ISD, MTy))
4141 if (auto KindCost = Entry->Cost[CostKind])
4142 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4143
4144 if (ST->hasBWI())
4145 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
4146 if (auto KindCost = Entry->Cost[CostKind])
4147 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4148
4149 if (ST->hasAVX512())
4150 if (const auto *Entry = CostTableLookup(AVX512CostTbl, ISD, MTy))
4151 if (auto KindCost = Entry->Cost[CostKind])
4152 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4153
4154 if (ST->hasAVX2())
4155 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
4156 if (auto KindCost = Entry->Cost[CostKind])
4157 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4158
4159 if (ST->hasXOP())
4160 if (const auto *Entry = CostTableLookup(XOPCostTbl, ISD, MTy))
4161 if (auto KindCost = Entry->Cost[CostKind])
4162 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4163
4164 if (ST->hasAVX())
4165 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
4166 if (auto KindCost = Entry->Cost[CostKind])
4167 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4168
4169 if (ST->hasSSE42())
4170 if (const auto *Entry = CostTableLookup(SSE42CostTbl, ISD, MTy))
4171 if (auto KindCost = Entry->Cost[CostKind])
4172 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4173
4174 if (ST->hasSSE41())
4175 if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
4176 if (auto KindCost = Entry->Cost[CostKind])
4177 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4178
4179 if (ST->hasSSE2())
4180 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
4181 if (auto KindCost = Entry->Cost[CostKind])
4182 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4183
4184 if (ST->hasSSE1())
4185 if (const auto *Entry = CostTableLookup(SSE1CostTbl, ISD, MTy))
4186 if (auto KindCost = Entry->Cost[CostKind])
4187 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4188
4189 // Assume a 3cy latency for fp select ops.
4190 if (CostKind == TTI::TCK_Latency && Opcode == Instruction::Select)
4191 if (ValTy->getScalarType()->isFloatingPointTy())
4192 return 3;
4193
4194 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
4195 Op1Info, Op2Info, I) +
4196 MaskExpCost;
4197}
4198
4200
4201/// Returns true if \p V is the square root, divided into with the reciprocal
4202/// allowed, and the target replaces the pair with the rsqrt* based estimate,
4203/// costed with the division. The estimate is formed for the legalized type
4204/// \p VT.
4206 const X86TargetLowering &TLI, MVT VT,
4207 TTI::TargetCostKind CostKind) {
4208 using namespace PatternMatch;
4209 if (CostKind != TTI::TCK_RecipThroughput && CostKind != TTI::TCK_Latency)
4210 return false;
4211 const auto *II = dyn_cast_if_present<IntrinsicInst>(V);
4212 if (!II || II->getIntrinsicID() != Intrinsic::sqrt || !II->hasOneUse() ||
4213 !match(II->user_back(), m_FDiv(m_Value(), m_Specific(II))) ||
4214 !cast<FPMathOperator>(II->user_back())->hasAllowReciprocal())
4215 return false;
4216 return TLI.hasSqrtEstimate(VT, /*Reciprocal=*/true) &&
4217 TLI.getRecipEstimateSqrtEnabled(VT, *II->getFunction()) !=
4219}
4220
4223 TTI::TargetCostKind CostKind) const {
4224 // Costs should match the codegen from:
4225 // BITREVERSE: llvm\test\CodeGen\X86\vector-bitreverse.ll
4226 // BSWAP: llvm\test\CodeGen\X86\bswap-vector.ll
4227 // CTLZ: llvm\test\CodeGen\X86\vector-lzcnt-*.ll
4228 // CTPOP: llvm\test\CodeGen\X86\vector-popcnt-*.ll
4229 // CTTZ: llvm\test\CodeGen\X86\vector-tzcnt-*.ll
4230
4231 // TODO: Overflow intrinsics (*ADDO, *SUBO, *MULO) with vector types are not
4232 // specialized in these tables yet.
4233 static const CostKindTblEntry AVX512VBMI2CostTbl[] = {
4234 { ISD::FSHL, MVT::v8i64, { 1, 1, 1, 1 } },
4235 { ISD::FSHL, MVT::v4i64, { 1, 1, 1, 1 } },
4236 { ISD::FSHL, MVT::v2i64, { 1, 1, 1, 1 } },
4237 { ISD::FSHL, MVT::v16i32, { 1, 1, 1, 1 } },
4238 { ISD::FSHL, MVT::v8i32, { 1, 1, 1, 1 } },
4239 { ISD::FSHL, MVT::v4i32, { 1, 1, 1, 1 } },
4240 { ISD::FSHL, MVT::v32i16, { 1, 1, 1, 1 } },
4241 { ISD::FSHL, MVT::v16i16, { 1, 1, 1, 1 } },
4242 { ISD::FSHL, MVT::v8i16, { 1, 1, 1, 1 } },
4243 { ISD::ROTL, MVT::v32i16, { 1, 1, 1, 1 } },
4244 { ISD::ROTL, MVT::v16i16, { 1, 1, 1, 1 } },
4245 { ISD::ROTL, MVT::v8i16, { 1, 1, 1, 1 } },
4246 { ISD::ROTR, MVT::v32i16, { 1, 1, 1, 1 } },
4247 { ISD::ROTR, MVT::v16i16, { 1, 1, 1, 1 } },
4248 { ISD::ROTR, MVT::v8i16, { 1, 1, 1, 1 } },
4249 { X86ISD::VROTLI, MVT::v32i16, { 1, 1, 1, 1 } },
4250 { X86ISD::VROTLI, MVT::v16i16, { 1, 1, 1, 1 } },
4251 { X86ISD::VROTLI, MVT::v8i16, { 1, 1, 1, 1 } },
4252 };
4253 static const CostKindTblEntry AVX512BITALGCostTbl[] = {
4254 { ISD::CTPOP, MVT::v32i16, { 1, 1, 1, 1 } },
4255 { ISD::CTPOP, MVT::v64i8, { 1, 1, 1, 1 } },
4256 { ISD::CTPOP, MVT::v16i16, { 1, 1, 1, 1 } },
4257 { ISD::CTPOP, MVT::v32i8, { 1, 1, 1, 1 } },
4258 { ISD::CTPOP, MVT::v8i16, { 1, 1, 1, 1 } },
4259 { ISD::CTPOP, MVT::v16i8, { 1, 1, 1, 1 } },
4260 };
4261 static const CostKindTblEntry AVX512VPOPCNTDQCostTbl[] = {
4262 { ISD::CTPOP, MVT::v8i64, { 1, 1, 1, 1 } },
4263 { ISD::CTPOP, MVT::v16i32, { 1, 1, 1, 1 } },
4264 { ISD::CTPOP, MVT::v4i64, { 1, 1, 1, 1 } },
4265 { ISD::CTPOP, MVT::v8i32, { 1, 1, 1, 1 } },
4266 { ISD::CTPOP, MVT::v2i64, { 1, 1, 1, 1 } },
4267 { ISD::CTPOP, MVT::v4i32, { 1, 1, 1, 1 } },
4268 };
4269 static const CostKindTblEntry AVX512CDCostTbl[] = {
4270 { ISD::CTLZ, MVT::v8i64, { 1, 5, 1, 1 } },
4271 { ISD::CTLZ, MVT::v16i32, { 1, 5, 1, 1 } },
4272 { ISD::CTLZ, MVT::v32i16, { 18, 27, 23, 27 } },
4273 { ISD::CTLZ, MVT::v64i8, { 3, 16, 9, 11 } },
4274 { ISD::CTLZ, MVT::v4i64, { 1, 5, 1, 1 } },
4275 { ISD::CTLZ, MVT::v8i32, { 1, 5, 1, 1 } },
4276 { ISD::CTLZ, MVT::v16i16, { 8, 19, 11, 13 } },
4277 { ISD::CTLZ, MVT::v32i8, { 2, 11, 9, 10 } },
4278 { ISD::CTLZ, MVT::v2i64, { 1, 5, 1, 1 } },
4279 { ISD::CTLZ, MVT::v4i32, { 1, 5, 1, 1 } },
4280 { ISD::CTLZ, MVT::v8i16, { 3, 15, 4, 6 } },
4281 { ISD::CTLZ, MVT::v16i8, { 2, 10, 9, 10 } },
4282
4283 { ISD::CTTZ, MVT::v8i64, { 2, 8, 6, 7 } },
4284 { ISD::CTTZ, MVT::v16i32, { 2, 8, 6, 7 } },
4285 { ISD::CTTZ, MVT::v4i64, { 1, 8, 6, 6 } },
4286 { ISD::CTTZ, MVT::v8i32, { 1, 8, 6, 6 } },
4287 { ISD::CTTZ, MVT::v2i64, { 1, 8, 6, 6 } },
4288 { ISD::CTTZ, MVT::v4i32, { 1, 8, 6, 6 } },
4289 };
4290 static const CostKindTblEntry AVX512BWCostTbl[] = {
4291 { ISD::ABS, MVT::v32i16, { 1, 1, 1, 1 } },
4292 { ISD::ABS, MVT::v64i8, { 1, 1, 1, 1 } },
4293 { ISD::BITREVERSE, MVT::v2i64, { 3, 10, 10, 11 } },
4294 { ISD::BITREVERSE, MVT::v4i64, { 3, 11, 10, 11 } },
4295 { ISD::BITREVERSE, MVT::v8i64, { 3, 12, 10, 14 } },
4296 { ISD::BITREVERSE, MVT::v4i32, { 3, 10, 10, 11 } },
4297 { ISD::BITREVERSE, MVT::v8i32, { 3, 11, 10, 11 } },
4298 { ISD::BITREVERSE, MVT::v16i32, { 3, 12, 10, 14 } },
4299 { ISD::BITREVERSE, MVT::v8i16, { 3, 10, 10, 11 } },
4300 { ISD::BITREVERSE, MVT::v16i16, { 3, 11, 10, 11 } },
4301 { ISD::BITREVERSE, MVT::v32i16, { 3, 12, 10, 14 } },
4302 { ISD::BITREVERSE, MVT::v16i8, { 2, 5, 9, 9 } },
4303 { ISD::BITREVERSE, MVT::v32i8, { 2, 5, 9, 9 } },
4304 { ISD::BITREVERSE, MVT::v64i8, { 2, 5, 9, 12 } },
4305 { ISD::BSWAP, MVT::v2i64, { 1, 1, 1, 2 } },
4306 { ISD::BSWAP, MVT::v4i64, { 1, 1, 1, 2 } },
4307 { ISD::BSWAP, MVT::v8i64, { 1, 1, 1, 2 } },
4308 { ISD::BSWAP, MVT::v4i32, { 1, 1, 1, 2 } },
4309 { ISD::BSWAP, MVT::v8i32, { 1, 1, 1, 2 } },
4310 { ISD::BSWAP, MVT::v16i32, { 1, 1, 1, 2 } },
4311 { ISD::BSWAP, MVT::v8i16, { 1, 1, 1, 2 } },
4312 { ISD::BSWAP, MVT::v16i16, { 1, 1, 1, 2 } },
4313 { ISD::BSWAP, MVT::v32i16, { 1, 1, 1, 2 } },
4314 { ISD::CTLZ, MVT::v8i64, { 8, 22, 23, 23 } },
4315 { ISD::CTLZ, MVT::v16i32, { 8, 23, 25, 25 } },
4316 { ISD::CTLZ, MVT::v32i16, { 4, 15, 15, 16 } },
4317 { ISD::CTLZ, MVT::v64i8, { 3, 12, 10, 9 } },
4318 { ISD::CTPOP, MVT::v2i64, { 3, 7, 10, 10 } },
4319 { ISD::CTPOP, MVT::v4i64, { 3, 7, 10, 10 } },
4320 { ISD::CTPOP, MVT::v8i64, { 3, 8, 10, 12 } },
4321 { ISD::CTPOP, MVT::v4i32, { 7, 11, 14, 14 } },
4322 { ISD::CTPOP, MVT::v8i32, { 7, 11, 14, 14 } },
4323 { ISD::CTPOP, MVT::v16i32, { 7, 12, 14, 16 } },
4324 { ISD::CTPOP, MVT::v8i16, { 2, 7, 11, 11 } },
4325 { ISD::CTPOP, MVT::v16i16, { 2, 7, 11, 11 } },
4326 { ISD::CTPOP, MVT::v32i16, { 3, 7, 11, 13 } },
4327 { ISD::CTPOP, MVT::v16i8, { 2, 4, 8, 8 } },
4328 { ISD::CTPOP, MVT::v32i8, { 2, 4, 8, 8 } },
4329 { ISD::CTPOP, MVT::v64i8, { 2, 5, 8, 10 } },
4330 { ISD::CTTZ, MVT::v8i16, { 3, 9, 14, 14 } },
4331 { ISD::CTTZ, MVT::v16i16, { 3, 9, 14, 14 } },
4332 { ISD::CTTZ, MVT::v32i16, { 3, 10, 14, 16 } },
4333 { ISD::CTTZ, MVT::v16i8, { 2, 6, 11, 11 } },
4334 { ISD::CTTZ, MVT::v32i8, { 2, 6, 11, 11 } },
4335 { ISD::CTTZ, MVT::v64i8, { 3, 7, 11, 13 } },
4336 { ISD::MULHS, MVT::v32i16, { 1, 5, 1, 1 } },
4337 { ISD::MULHU, MVT::v32i16, { 1, 5, 1, 1 } },
4338 { ISD::ROTL, MVT::v32i16, { 2, 8, 6, 8 } },
4339 { ISD::ROTL, MVT::v16i16, { 2, 8, 6, 7 } },
4340 { ISD::ROTL, MVT::v8i16, { 2, 7, 6, 7 } },
4341 { ISD::ROTL, MVT::v64i8, { 5, 6, 11, 12 } },
4342 { ISD::ROTL, MVT::v32i8, { 5, 15, 7, 10 } },
4343 { ISD::ROTL, MVT::v16i8, { 5, 15, 7, 10 } },
4344 { ISD::ROTR, MVT::v32i16, { 2, 8, 6, 8 } },
4345 { ISD::ROTR, MVT::v16i16, { 2, 8, 6, 7 } },
4346 { ISD::ROTR, MVT::v8i16, { 2, 7, 6, 7 } },
4347 { ISD::ROTR, MVT::v64i8, { 5, 6, 12, 14 } },
4348 { ISD::ROTR, MVT::v32i8, { 5, 14, 6, 9 } },
4349 { ISD::ROTR, MVT::v16i8, { 5, 14, 6, 9 } },
4350 { X86ISD::VROTLI, MVT::v32i16, { 2, 5, 3, 3 } },
4351 { X86ISD::VROTLI, MVT::v16i16, { 1, 5, 3, 3 } },
4352 { X86ISD::VROTLI, MVT::v8i16, { 1, 5, 3, 3 } },
4353 { X86ISD::VROTLI, MVT::v64i8, { 2, 9, 3, 4 } },
4354 { X86ISD::VROTLI, MVT::v32i8, { 1, 9, 3, 4 } },
4355 { X86ISD::VROTLI, MVT::v16i8, { 1, 8, 3, 4 } },
4356 { ISD::SADDSAT, MVT::v32i16, { 1, 1, 1, 1 } },
4357 { ISD::SADDSAT, MVT::v64i8, { 1, 1, 1, 1 } },
4358 { ISD::SMAX, MVT::v32i16, { 1, 1, 1, 1 } },
4359 { ISD::SMAX, MVT::v64i8, { 1, 1, 1, 1 } },
4360 { ISD::SMIN, MVT::v32i16, { 1, 1, 1, 1 } },
4361 { ISD::SMIN, MVT::v64i8, { 1, 1, 1, 1 } },
4362 { ISD::SMULO, MVT::v32i16, { 3, 6, 4, 4 } },
4363 { ISD::SMULO, MVT::v64i8, { 8, 21, 17, 18 } },
4364 { ISD::UMULO, MVT::v32i16, { 2, 5, 3, 3 } },
4365 { ISD::UMULO, MVT::v64i8, { 8, 15, 15, 16 } },
4366 { ISD::SSUBSAT, MVT::v32i16, { 1, 1, 1, 1 } },
4367 { ISD::SSUBSAT, MVT::v64i8, { 1, 1, 1, 1 } },
4368 { ISD::UADDSAT, MVT::v32i16, { 1, 1, 1, 1 } },
4369 { ISD::UADDSAT, MVT::v64i8, { 1, 1, 1, 1 } },
4370 { ISD::UMAX, MVT::v32i16, { 1, 1, 1, 1 } },
4371 { ISD::UMAX, MVT::v64i8, { 1, 1, 1, 1 } },
4372 { ISD::UMIN, MVT::v32i16, { 1, 1, 1, 1 } },
4373 { ISD::UMIN, MVT::v64i8, { 1, 1, 1, 1 } },
4374 { ISD::USUBSAT, MVT::v32i16, { 1, 1, 1, 1 } },
4375 { ISD::USUBSAT, MVT::v64i8, { 1, 1, 1, 1 } },
4376 };
4377 static const CostKindTblEntry AVX512CostTbl[] = {
4378 { ISD::ABS, MVT::v8i64, { 1, 1, 1, 1 } },
4379 { ISD::ABS, MVT::v4i64, { 1, 1, 1, 1 } },
4380 { ISD::ABS, MVT::v2i64, { 1, 1, 1, 1 } },
4381 { ISD::ABS, MVT::v16i32, { 1, 1, 1, 1 } },
4382 { ISD::ABS, MVT::v8i32, { 1, 1, 1, 1 } },
4383 { ISD::ABS, MVT::v32i16, { 2, 7, 4, 4 } },
4384 { ISD::ABS, MVT::v16i16, { 1, 1, 1, 1 } },
4385 { ISD::ABS, MVT::v64i8, { 2, 7, 4, 4 } },
4386 { ISD::ABS, MVT::v32i8, { 1, 1, 1, 1 } },
4387 { ISD::BITREVERSE, MVT::v8i64, { 9, 13, 20, 20 } },
4388 { ISD::BITREVERSE, MVT::v16i32, { 9, 13, 20, 20 } },
4389 { ISD::BITREVERSE, MVT::v32i16, { 9, 13, 20, 20 } },
4390 { ISD::BITREVERSE, MVT::v64i8, { 6, 11, 17, 17 } },
4391 { ISD::BSWAP, MVT::v8i64, { 4, 7, 5, 5 } },
4392 { ISD::BSWAP, MVT::v16i32, { 4, 7, 5, 5 } },
4393 { ISD::BSWAP, MVT::v32i16, { 4, 7, 5, 5 } },
4394 { ISD::CTLZ, MVT::v8i64, { 10, 28, 32, 32 } },
4395 { ISD::CTLZ, MVT::v16i32, { 12, 30, 38, 38 } },
4396 { ISD::CTLZ, MVT::v32i16, { 8, 15, 29, 29 } },
4397 { ISD::CTLZ, MVT::v64i8, { 6, 11, 19, 19 } },
4398 { ISD::CTPOP, MVT::v8i64, { 16, 16, 19, 19 } },
4399 { ISD::CTPOP, MVT::v16i32, { 24, 19, 27, 27 } },
4400 { ISD::CTPOP, MVT::v32i16, { 18, 15, 22, 22 } },
4401 { ISD::CTPOP, MVT::v64i8, { 12, 11, 16, 16 } },
4402 { ISD::CTTZ, MVT::v8i64, { 2, 8, 6, 7 } },
4403 { ISD::CTTZ, MVT::v16i32, { 2, 8, 6, 7 } },
4404 { ISD::CTTZ, MVT::v32i16, { 7, 17, 27, 27 } },
4405 { ISD::CTTZ, MVT::v64i8, { 6, 13, 21, 21 } },
4406 { ISD::MULHS, MVT::v16i32, { 3, 10, 6, 7 } },
4407 { ISD::MULHS, MVT::v8i32, { 3, 9, 6, 6 } },
4408 { ISD::MULHS, MVT::v32i16, { 3, 7, 5, 5 } },
4409 { ISD::MULHS, MVT::v16i16, { 1, 5, 1, 1 } },
4410 { ISD::MULHU, MVT::v16i32, { 3, 10, 6, 7 } },
4411 { ISD::MULHU, MVT::v8i32, { 3, 9, 6, 6 } },
4412 { ISD::MULHU, MVT::v32i16, { 3, 7, 5, 5 } },
4413 { ISD::MULHU, MVT::v16i16, { 1, 5, 1, 1 } },
4414 { ISD::ROTL, MVT::v8i64, { 1, 1, 1, 1 } },
4415 { ISD::ROTL, MVT::v4i64, { 1, 1, 1, 1 } },
4416 { ISD::ROTL, MVT::v2i64, { 1, 1, 1, 1 } },
4417 { ISD::ROTL, MVT::v16i32, { 1, 1, 1, 1 } },
4418 { ISD::ROTL, MVT::v8i32, { 1, 1, 1, 1 } },
4419 { ISD::ROTL, MVT::v4i32, { 1, 1, 1, 1 } },
4420 { ISD::ROTR, MVT::v8i64, { 1, 1, 1, 1 } },
4421 { ISD::ROTR, MVT::v4i64, { 1, 1, 1, 1 } },
4422 { ISD::ROTR, MVT::v2i64, { 1, 1, 1, 1 } },
4423 { ISD::ROTR, MVT::v16i32, { 1, 1, 1, 1 } },
4424 { ISD::ROTR, MVT::v8i32, { 1, 1, 1, 1 } },
4425 { ISD::ROTR, MVT::v4i32, { 1, 1, 1, 1 } },
4426 { X86ISD::VROTLI, MVT::v8i64, { 1, 1, 1, 1 } },
4427 { X86ISD::VROTLI, MVT::v4i64, { 1, 1, 1, 1 } },
4428 { X86ISD::VROTLI, MVT::v2i64, { 1, 1, 1, 1 } },
4429 { X86ISD::VROTLI, MVT::v16i32, { 1, 1, 1, 1 } },
4430 { X86ISD::VROTLI, MVT::v8i32, { 1, 1, 1, 1 } },
4431 { X86ISD::VROTLI, MVT::v4i32, { 1, 1, 1, 1 } },
4432 { ISD::SADDSAT, MVT::v2i64, { 3, 3, 8, 9 } },
4433 { ISD::SADDSAT, MVT::v4i64, { 2, 2, 6, 7 } },
4434 { ISD::SADDSAT, MVT::v8i64, { 3, 3, 6, 7 } },
4435 { ISD::SADDSAT, MVT::v4i32, { 2, 2, 6, 7 } },
4436 { ISD::SADDSAT, MVT::v8i32, { 2, 2, 6, 7 } },
4437 { ISD::SADDSAT, MVT::v16i32, { 3, 3, 6, 7 } },
4438 { ISD::SADDSAT, MVT::v32i16, { 2, 2, 2, 2 } },
4439 { ISD::SADDSAT, MVT::v64i8, { 2, 2, 2, 2 } },
4440 { ISD::SMAX, MVT::v8i64, { 1, 3, 1, 1 } },
4441 { ISD::SMAX, MVT::v16i32, { 1, 1, 1, 1 } },
4442 { ISD::SMAX, MVT::v32i16, { 3, 7, 5, 5 } },
4443 { ISD::SMAX, MVT::v64i8, { 3, 7, 5, 5 } },
4444 { ISD::SMAX, MVT::v4i64, { 1, 3, 1, 1 } },
4445 { ISD::SMAX, MVT::v2i64, { 1, 3, 1, 1 } },
4446 { ISD::SMIN, MVT::v8i64, { 1, 3, 1, 1 } },
4447 { ISD::SMIN, MVT::v16i32, { 1, 1, 1, 1 } },
4448 { ISD::SMIN, MVT::v32i16, { 3, 7, 5, 5 } },
4449 { ISD::SMIN, MVT::v64i8, { 3, 7, 5, 5 } },
4450 { ISD::SMIN, MVT::v4i64, { 1, 3, 1, 1 } },
4451 { ISD::SMIN, MVT::v2i64, { 1, 3, 1, 1 } },
4452 { ISD::SMULO, MVT::v8i64, { 44, 44, 81, 93 } },
4453 { ISD::SMULO, MVT::v16i32, { 5, 12, 9, 11 } },
4454 { ISD::SMULO, MVT::v32i16, { 6, 12, 17, 17 } },
4455 { ISD::SMULO, MVT::v64i8, { 22, 28, 42, 42 } },
4456 { ISD::SSUBSAT, MVT::v2i64, { 2, 13, 9, 10 } },
4457 { ISD::SSUBSAT, MVT::v4i64, { 2, 15, 7, 8 } },
4458 { ISD::SSUBSAT, MVT::v8i64, { 2, 14, 7, 8 } },
4459 { ISD::SSUBSAT, MVT::v4i32, { 2, 14, 7, 8 } },
4460 { ISD::SSUBSAT, MVT::v8i32, { 2, 15, 7, 8 } },
4461 { ISD::SSUBSAT, MVT::v16i32, { 2, 14, 7, 8 } },
4462 { ISD::SSUBSAT, MVT::v32i16, { 2, 2, 2, 2 } },
4463 { ISD::SSUBSAT, MVT::v64i8, { 2, 2, 2, 2 } },
4464 { ISD::UMAX, MVT::v8i64, { 1, 3, 1, 1 } },
4465 { ISD::UMAX, MVT::v16i32, { 1, 1, 1, 1 } },
4466 { ISD::UMAX, MVT::v32i16, { 3, 7, 5, 5 } },
4467 { ISD::UMAX, MVT::v64i8, { 3, 7, 5, 5 } },
4468 { ISD::UMAX, MVT::v4i64, { 1, 3, 1, 1 } },
4469 { ISD::UMAX, MVT::v2i64, { 1, 3, 1, 1 } },
4470 { ISD::UMIN, MVT::v8i64, { 1, 3, 1, 1 } },
4471 { ISD::UMIN, MVT::v16i32, { 1, 1, 1, 1 } },
4472 { ISD::UMIN, MVT::v32i16, { 3, 7, 5, 5 } },
4473 { ISD::UMIN, MVT::v64i8, { 3, 7, 5, 5 } },
4474 { ISD::UMIN, MVT::v4i64, { 1, 3, 1, 1 } },
4475 { ISD::UMIN, MVT::v2i64, { 1, 3, 1, 1 } },
4476 { ISD::UMULO, MVT::v8i64, { 52, 52, 95, 104} },
4477 { ISD::UMULO, MVT::v16i32, { 5, 12, 8, 10 } },
4478 { ISD::UMULO, MVT::v32i16, { 5, 13, 16, 16 } },
4479 { ISD::UMULO, MVT::v64i8, { 18, 24, 30, 30 } },
4480 { ISD::UADDSAT, MVT::v2i64, { 1, 4, 4, 4 } },
4481 { ISD::UADDSAT, MVT::v4i64, { 1, 4, 4, 4 } },
4482 { ISD::UADDSAT, MVT::v8i64, { 1, 4, 4, 4 } },
4483 { ISD::UADDSAT, MVT::v4i32, { 1, 2, 4, 4 } },
4484 { ISD::UADDSAT, MVT::v8i32, { 1, 2, 4, 4 } },
4485 { ISD::UADDSAT, MVT::v16i32, { 2, 2, 4, 4 } },
4486 { ISD::UADDSAT, MVT::v32i16, { 2, 2, 2, 2 } },
4487 { ISD::UADDSAT, MVT::v64i8, { 2, 2, 2, 2 } },
4488 { ISD::USUBSAT, MVT::v2i64, { 1, 4, 2, 2 } },
4489 { ISD::USUBSAT, MVT::v4i64, { 1, 4, 2, 2 } },
4490 { ISD::USUBSAT, MVT::v8i64, { 1, 4, 2, 2 } },
4491 { ISD::USUBSAT, MVT::v8i32, { 1, 2, 2, 2 } },
4492 { ISD::USUBSAT, MVT::v16i32, { 1, 2, 2, 2 } },
4493 { ISD::USUBSAT, MVT::v32i16, { 2, 2, 2, 2 } },
4494 { ISD::USUBSAT, MVT::v64i8, { 2, 2, 2, 2 } },
4495 { ISD::FMAXNUM, MVT::f32, { 2, 2, 3, 3 } },
4496 { ISD::FMAXNUM, MVT::v4f32, { 1, 1, 3, 3 } },
4497 { ISD::FMAXNUM, MVT::v8f32, { 2, 2, 3, 3 } },
4498 { ISD::FMAXNUM, MVT::v16f32, { 4, 4, 3, 3 } },
4499 { ISD::FMAXNUM, MVT::f64, { 2, 2, 3, 3 } },
4500 { ISD::FMAXNUM, MVT::v2f64, { 1, 1, 3, 3 } },
4501 { ISD::FMAXNUM, MVT::v4f64, { 2, 2, 3, 3 } },
4502 { ISD::FMAXNUM, MVT::v8f64, { 3, 3, 3, 3 } },
4503 { ISD::FSQRT, MVT::f32, { 3, 12, 1, 1 } }, // Skylake from http://www.agner.org/
4504 { ISD::FSQRT, MVT::v4f32, { 3, 12, 1, 1 } }, // Skylake from http://www.agner.org/
4505 { ISD::FSQRT, MVT::v8f32, { 6, 12, 1, 1 } }, // Skylake from http://www.agner.org/
4506 { ISD::FSQRT, MVT::v16f32, { 12, 20, 1, 3 } }, // Skylake from http://www.agner.org/
4507 { ISD::FSQRT, MVT::f64, { 6, 18, 1, 1 } }, // Skylake from http://www.agner.org/
4508 { ISD::FSQRT, MVT::v2f64, { 6, 18, 1, 1 } }, // Skylake from http://www.agner.org/
4509 { ISD::FSQRT, MVT::v4f64, { 12, 18, 1, 1 } }, // Skylake from http://www.agner.org/
4510 { ISD::FSQRT, MVT::v8f64, { 24, 32, 1, 3 } }, // Skylake from http://www.agner.org/
4511 };
4512 static const CostKindTblEntry XOPCostTbl[] = {
4513 { ISD::BITREVERSE, MVT::v4i64, { 3, 6, 5, 6 } },
4514 { ISD::BITREVERSE, MVT::v8i32, { 3, 6, 5, 6 } },
4515 { ISD::BITREVERSE, MVT::v16i16, { 3, 6, 5, 6 } },
4516 { ISD::BITREVERSE, MVT::v32i8, { 3, 6, 5, 6 } },
4517 { ISD::BITREVERSE, MVT::v2i64, { 2, 7, 1, 1 } },
4518 { ISD::BITREVERSE, MVT::v4i32, { 2, 7, 1, 1 } },
4519 { ISD::BITREVERSE, MVT::v8i16, { 2, 7, 1, 1 } },
4520 { ISD::BITREVERSE, MVT::v16i8, { 2, 7, 1, 1 } },
4521 { ISD::BITREVERSE, MVT::i64, { 2, 2, 3, 4 } },
4522 { ISD::BITREVERSE, MVT::i32, { 2, 2, 3, 4 } },
4523 { ISD::BITREVERSE, MVT::i16, { 2, 2, 3, 4 } },
4524 { ISD::BITREVERSE, MVT::i8, { 2, 2, 3, 4 } },
4525 // XOP: ROTL = VPROT(X,Y), ROTR = VPROT(X,SUB(0,Y))
4526 { ISD::ROTL, MVT::v4i64, { 4, 7, 5, 6 } },
4527 { ISD::ROTL, MVT::v8i32, { 4, 7, 5, 6 } },
4528 { ISD::ROTL, MVT::v16i16, { 4, 7, 5, 6 } },
4529 { ISD::ROTL, MVT::v32i8, { 4, 7, 5, 6 } },
4530 { ISD::ROTL, MVT::v2i64, { 1, 3, 1, 1 } },
4531 { ISD::ROTL, MVT::v4i32, { 1, 3, 1, 1 } },
4532 { ISD::ROTL, MVT::v8i16, { 1, 3, 1, 1 } },
4533 { ISD::ROTL, MVT::v16i8, { 1, 3, 1, 1 } },
4534 { ISD::ROTR, MVT::v4i64, { 4, 7, 8, 9 } },
4535 { ISD::ROTR, MVT::v8i32, { 4, 7, 8, 9 } },
4536 { ISD::ROTR, MVT::v16i16, { 4, 7, 8, 9 } },
4537 { ISD::ROTR, MVT::v32i8, { 4, 7, 8, 9 } },
4538 { ISD::ROTR, MVT::v2i64, { 1, 3, 3, 3 } },
4539 { ISD::ROTR, MVT::v4i32, { 1, 3, 3, 3 } },
4540 { ISD::ROTR, MVT::v8i16, { 1, 3, 3, 3 } },
4541 { ISD::ROTR, MVT::v16i8, { 1, 3, 3, 3 } },
4542 { X86ISD::VROTLI, MVT::v4i64, { 4, 7, 5, 6 } },
4543 { X86ISD::VROTLI, MVT::v8i32, { 4, 7, 5, 6 } },
4544 { X86ISD::VROTLI, MVT::v16i16, { 4, 7, 5, 6 } },
4545 { X86ISD::VROTLI, MVT::v32i8, { 4, 7, 5, 6 } },
4546 { X86ISD::VROTLI, MVT::v2i64, { 1, 3, 1, 1 } },
4547 { X86ISD::VROTLI, MVT::v4i32, { 1, 3, 1, 1 } },
4548 { X86ISD::VROTLI, MVT::v8i16, { 1, 3, 1, 1 } },
4549 { X86ISD::VROTLI, MVT::v16i8, { 1, 3, 1, 1 } },
4550 };
4551 static const CostKindTblEntry AVX2CostTbl[] = {
4552 { ISD::ABS, MVT::v2i64, { 2, 4, 3, 5 } }, // VBLENDVPD(X,VPSUBQ(0,X),X)
4553 { ISD::ABS, MVT::v4i64, { 2, 4, 3, 5 } }, // VBLENDVPD(X,VPSUBQ(0,X),X)
4554 { ISD::ABS, MVT::v4i32, { 1, 1, 1, 1 } },
4555 { ISD::ABS, MVT::v8i32, { 1, 1, 1, 2 } },
4556 { ISD::ABS, MVT::v8i16, { 1, 1, 1, 1 } },
4557 { ISD::ABS, MVT::v16i16, { 1, 1, 1, 2 } },
4558 { ISD::ABS, MVT::v16i8, { 1, 1, 1, 1 } },
4559 { ISD::ABS, MVT::v32i8, { 1, 1, 1, 2 } },
4560 { ISD::BITREVERSE, MVT::v2i64, { 3, 11, 10, 11 } },
4561 { ISD::BITREVERSE, MVT::v4i64, { 5, 11, 10, 17 } },
4562 { ISD::BITREVERSE, MVT::v4i32, { 3, 11, 10, 11 } },
4563 { ISD::BITREVERSE, MVT::v8i32, { 5, 11, 10, 17 } },
4564 { ISD::BITREVERSE, MVT::v8i16, { 3, 11, 10, 11 } },
4565 { ISD::BITREVERSE, MVT::v16i16, { 5, 11, 10, 17 } },
4566 { ISD::BITREVERSE, MVT::v16i8, { 3, 6, 9, 9 } },
4567 { ISD::BITREVERSE, MVT::v32i8, { 4, 5, 9, 15 } },
4568 { ISD::BSWAP, MVT::v2i64, { 1, 2, 1, 2 } },
4569 { ISD::BSWAP, MVT::v4i64, { 1, 3, 1, 2 } },
4570 { ISD::BSWAP, MVT::v4i32, { 1, 2, 1, 2 } },
4571 { ISD::BSWAP, MVT::v8i32, { 1, 3, 1, 2 } },
4572 { ISD::BSWAP, MVT::v8i16, { 1, 2, 1, 2 } },
4573 { ISD::BSWAP, MVT::v16i16, { 1, 3, 1, 2 } },
4574 { ISD::CTLZ, MVT::v2i64, { 7, 18, 24, 25 } },
4575 { ISD::CTLZ, MVT::v4i64, { 14, 18, 24, 44 } },
4576 { ISD::CTLZ, MVT::v4i32, { 5, 16, 19, 20 } },
4577 { ISD::CTLZ, MVT::v8i32, { 10, 16, 19, 34 } },
4578 { ISD::CTLZ, MVT::v8i16, { 4, 13, 14, 15 } },
4579 { ISD::CTLZ, MVT::v16i16, { 6, 14, 14, 24 } },
4580 { ISD::CTLZ, MVT::v16i8, { 3, 12, 9, 10 } },
4581 { ISD::CTLZ, MVT::v32i8, { 4, 12, 9, 14 } },
4582 { ISD::CTPOP, MVT::v2i64, { 3, 9, 10, 10 } },
4583 { ISD::CTPOP, MVT::v4i64, { 4, 9, 10, 14 } },
4584 { ISD::CTPOP, MVT::v4i32, { 7, 12, 14, 14 } },
4585 { ISD::CTPOP, MVT::v8i32, { 7, 12, 14, 18 } },
4586 { ISD::CTPOP, MVT::v8i16, { 3, 7, 11, 11 } },
4587 { ISD::CTPOP, MVT::v16i16, { 6, 8, 11, 18 } },
4588 { ISD::CTPOP, MVT::v16i8, { 2, 5, 8, 8 } },
4589 { ISD::CTPOP, MVT::v32i8, { 3, 5, 8, 12 } },
4590 { ISD::CTTZ, MVT::v2i64, { 4, 11, 13, 13 } },
4591 { ISD::CTTZ, MVT::v4i64, { 5, 11, 13, 20 } },
4592 { ISD::CTTZ, MVT::v4i32, { 7, 14, 17, 17 } },
4593 { ISD::CTTZ, MVT::v8i32, { 7, 15, 17, 24 } },
4594 { ISD::CTTZ, MVT::v8i16, { 4, 9, 14, 14 } },
4595 { ISD::CTTZ, MVT::v16i16, { 6, 9, 14, 24 } },
4596 { ISD::CTTZ, MVT::v16i8, { 3, 7, 11, 11 } },
4597 { ISD::CTTZ, MVT::v32i8, { 5, 7, 11, 18 } },
4598 { ISD::MULHS, MVT::v8i32, { 4, 9, 6, 12 } },
4599 { ISD::MULHS, MVT::v16i16, { 2, 5, 1, 2 } },
4600 { ISD::MULHU, MVT::v8i32, { 4, 9, 6, 12 } },
4601 { ISD::MULHU, MVT::v16i16, { 2, 5, 1, 2 } },
4602 { ISD::SADDSAT, MVT::v2i64, { 4, 13, 8, 11 } },
4603 { ISD::SADDSAT, MVT::v4i64, { 3, 10, 8, 12 } },
4604 { ISD::SADDSAT, MVT::v4i32, { 2, 6, 7, 9 } },
4605 { ISD::SADDSAT, MVT::v8i32, { 4, 6, 7, 13 } },
4606 { ISD::SADDSAT, MVT::v16i16, { 1, 1, 1, 2 } },
4607 { ISD::SADDSAT, MVT::v32i8, { 1, 1, 1, 2 } },
4608 { ISD::SMAX, MVT::v2i64, { 2, 7, 2, 3 } },
4609 { ISD::SMAX, MVT::v4i64, { 2, 7, 2, 3 } },
4610 { ISD::SMAX, MVT::v8i32, { 1, 1, 1, 2 } },
4611 { ISD::SMAX, MVT::v16i16, { 1, 1, 1, 2 } },
4612 { ISD::SMAX, MVT::v32i8, { 1, 1, 1, 2 } },
4613 { ISD::SMIN, MVT::v2i64, { 2, 7, 2, 3 } },
4614 { ISD::SMIN, MVT::v4i64, { 2, 7, 2, 3 } },
4615 { ISD::SMIN, MVT::v8i32, { 1, 1, 1, 2 } },
4616 { ISD::SMIN, MVT::v16i16, { 1, 1, 1, 2 } },
4617 { ISD::SMIN, MVT::v32i8, { 1, 1, 1, 2 } },
4618 { ISD::SMULO, MVT::v4i64, { 20, 20, 33, 37 } },
4619 { ISD::SMULO, MVT::v2i64, { 8, 8, 13, 15 } },
4620 { ISD::SMULO, MVT::v8i32, { 8, 20, 13, 24 } },
4621 { ISD::SMULO, MVT::v4i32, { 5, 15, 11, 12 } },
4622 { ISD::SMULO, MVT::v16i16, { 4, 14, 8, 14 } },
4623 { ISD::SMULO, MVT::v8i16, { 3, 9, 6, 6 } },
4624 { ISD::SMULO, MVT::v32i8, { 9, 15, 18, 35 } },
4625 { ISD::SMULO, MVT::v16i8, { 6, 22, 14, 21 } },
4626 { ISD::SSUBSAT, MVT::v2i64, { 4, 13, 9, 13 } },
4627 { ISD::SSUBSAT, MVT::v4i64, { 4, 15, 9, 13 } },
4628 { ISD::SSUBSAT, MVT::v4i32, { 3, 14, 9, 11 } },
4629 { ISD::SSUBSAT, MVT::v8i32, { 4, 15, 9, 16 } },
4630 { ISD::SSUBSAT, MVT::v16i16, { 1, 1, 1, 2 } },
4631 { ISD::SSUBSAT, MVT::v32i8, { 1, 1, 1, 2 } },
4632 { ISD::UADDSAT, MVT::v2i64, { 2, 8, 6, 6 } },
4633 { ISD::UADDSAT, MVT::v4i64, { 3, 8, 6, 10 } },
4634 { ISD::UADDSAT, MVT::v8i32, { 2, 2, 4, 8 } },
4635 { ISD::UADDSAT, MVT::v16i16, { 1, 1, 1, 2 } },
4636 { ISD::UADDSAT, MVT::v32i8, { 1, 1, 1, 2 } },
4637 { ISD::UMAX, MVT::v2i64, { 2, 8, 5, 6 } },
4638 { ISD::UMAX, MVT::v4i64, { 2, 8, 5, 8 } },
4639 { ISD::UMAX, MVT::v8i32, { 1, 1, 1, 2 } },
4640 { ISD::UMAX, MVT::v16i16, { 1, 1, 1, 2 } },
4641 { ISD::UMAX, MVT::v32i8, { 1, 1, 1, 2 } },
4642 { ISD::UMIN, MVT::v2i64, { 2, 8, 5, 6 } },
4643 { ISD::UMIN, MVT::v4i64, { 2, 8, 5, 8 } },
4644 { ISD::UMIN, MVT::v8i32, { 1, 1, 1, 2 } },
4645 { ISD::UMIN, MVT::v16i16, { 1, 1, 1, 2 } },
4646 { ISD::UMIN, MVT::v32i8, { 1, 1, 1, 2 } },
4647 { ISD::UMULO, MVT::v4i64, { 24, 24, 39, 43 } },
4648 { ISD::UMULO, MVT::v2i64, { 10, 10, 15, 19 } },
4649 { ISD::UMULO, MVT::v8i32, { 8, 11, 13, 23 } },
4650 { ISD::UMULO, MVT::v4i32, { 5, 12, 11, 12 } },
4651 { ISD::UMULO, MVT::v16i16, { 4, 6, 8, 13 } },
4652 { ISD::UMULO, MVT::v8i16, { 2, 8, 6, 6 } },
4653 { ISD::UMULO, MVT::v32i8, { 9, 13, 17, 33 } },
4654 { ISD::UMULO, MVT::v16i8, { 6, 19, 13, 20 } },
4655 { ISD::USUBSAT, MVT::v2i64, { 2, 7, 6, 6 } },
4656 { ISD::USUBSAT, MVT::v4i64, { 3, 7, 6, 10 } },
4657 { ISD::USUBSAT, MVT::v8i32, { 2, 2, 2, 4 } },
4658 { ISD::USUBSAT, MVT::v16i16, { 1, 1, 1, 2 } },
4659 { ISD::USUBSAT, MVT::v32i8, { 1, 1, 1, 2 } },
4660 { ISD::FMAXNUM, MVT::f32, { 2, 7, 3, 5 } }, // MAXSS + CMPUNORDSS + BLENDVPS
4661 { ISD::FMAXNUM, MVT::v4f32, { 2, 7, 3, 5 } }, // MAXPS + CMPUNORDPS + BLENDVPS
4662 { ISD::FMAXNUM, MVT::v8f32, { 3, 7, 3, 6 } }, // MAXPS + CMPUNORDPS + BLENDVPS
4663 { ISD::FMAXNUM, MVT::f64, { 2, 7, 3, 5 } }, // MAXSD + CMPUNORDSD + BLENDVPD
4664 { ISD::FMAXNUM, MVT::v2f64, { 2, 7, 3, 5 } }, // MAXPD + CMPUNORDPD + BLENDVPD
4665 { ISD::FMAXNUM, MVT::v4f64, { 3, 7, 3, 6 } }, // MAXPD + CMPUNORDPD + BLENDVPD
4666 { ISD::FSQRT, MVT::f32, { 7, 15, 1, 1 } }, // vsqrtss
4667 { ISD::FSQRT, MVT::v4f32, { 7, 15, 1, 1 } }, // vsqrtps
4668 { ISD::FSQRT, MVT::v8f32, { 14, 21, 1, 3 } }, // vsqrtps
4669 { ISD::FSQRT, MVT::f64, { 14, 21, 1, 1 } }, // vsqrtsd
4670 { ISD::FSQRT, MVT::v2f64, { 14, 21, 1, 1 } }, // vsqrtpd
4671 { ISD::FSQRT, MVT::v4f64, { 28, 35, 1, 3 } }, // vsqrtpd
4672 };
4673 static const CostKindTblEntry AVX1CostTbl[] = {
4674 { ISD::ABS, MVT::v4i64, { 6, 8, 6, 12 } }, // VBLENDVPD(X,VPSUBQ(0,X),X)
4675 { ISD::ABS, MVT::v8i32, { 3, 6, 4, 5 } },
4676 { ISD::ABS, MVT::v16i16, { 3, 6, 4, 5 } },
4677 { ISD::ABS, MVT::v32i8, { 3, 6, 4, 5 } },
4678 { ISD::BITREVERSE, MVT::v4i64, { 17, 20, 20, 33 } }, // 2 x 128-bit Op + extract/insert
4679 { ISD::BITREVERSE, MVT::v2i64, { 8, 13, 10, 16 } },
4680 { ISD::BITREVERSE, MVT::v8i32, { 17, 20, 20, 33 } }, // 2 x 128-bit Op + extract/insert
4681 { ISD::BITREVERSE, MVT::v4i32, { 8, 13, 10, 16 } },
4682 { ISD::BITREVERSE, MVT::v16i16, { 17, 20, 20, 33 } }, // 2 x 128-bit Op + extract/insert
4683 { ISD::BITREVERSE, MVT::v8i16, { 8, 13, 10, 16 } },
4684 { ISD::BITREVERSE, MVT::v32i8, { 13, 15, 17, 26 } }, // 2 x 128-bit Op + extract/insert
4685 { ISD::BITREVERSE, MVT::v16i8, { 7, 7, 9, 13 } },
4686 { ISD::BSWAP, MVT::v4i64, { 5, 6, 5, 10 } },
4687 { ISD::BSWAP, MVT::v2i64, { 2, 2, 1, 3 } },
4688 { ISD::BSWAP, MVT::v8i32, { 5, 6, 5, 10 } },
4689 { ISD::BSWAP, MVT::v4i32, { 2, 2, 1, 3 } },
4690 { ISD::BSWAP, MVT::v16i16, { 5, 6, 5, 10 } },
4691 { ISD::BSWAP, MVT::v8i16, { 2, 2, 1, 3 } },
4692 { ISD::CTLZ, MVT::v4i64, { 29, 33, 49, 58 } }, // 2 x 128-bit Op + extract/insert
4693 { ISD::CTLZ, MVT::v2i64, { 14, 24, 24, 28 } },
4694 { ISD::CTLZ, MVT::v8i32, { 24, 28, 39, 48 } }, // 2 x 128-bit Op + extract/insert
4695 { ISD::CTLZ, MVT::v4i32, { 12, 20, 19, 23 } },
4696 { ISD::CTLZ, MVT::v16i16, { 19, 22, 29, 38 } }, // 2 x 128-bit Op + extract/insert
4697 { ISD::CTLZ, MVT::v8i16, { 9, 16, 14, 18 } },
4698 { ISD::CTLZ, MVT::v32i8, { 14, 15, 19, 28 } }, // 2 x 128-bit Op + extract/insert
4699 { ISD::CTLZ, MVT::v16i8, { 7, 12, 9, 13 } },
4700 { ISD::CTPOP, MVT::v4i64, { 14, 18, 19, 28 } }, // 2 x 128-bit Op + extract/insert
4701 { ISD::CTPOP, MVT::v2i64, { 7, 14, 10, 14 } },
4702 { ISD::CTPOP, MVT::v8i32, { 18, 24, 27, 36 } }, // 2 x 128-bit Op + extract/insert
4703 { ISD::CTPOP, MVT::v4i32, { 9, 20, 14, 18 } },
4704 { ISD::CTPOP, MVT::v16i16, { 16, 21, 22, 31 } }, // 2 x 128-bit Op + extract/insert
4705 { ISD::CTPOP, MVT::v8i16, { 8, 18, 11, 15 } },
4706 { ISD::CTPOP, MVT::v32i8, { 13, 15, 16, 25 } }, // 2 x 128-bit Op + extract/insert
4707 { ISD::CTPOP, MVT::v16i8, { 6, 12, 8, 12 } },
4708 { ISD::CTTZ, MVT::v4i64, { 17, 22, 24, 33 } }, // 2 x 128-bit Op + extract/insert
4709 { ISD::CTTZ, MVT::v2i64, { 9, 19, 13, 17 } },
4710 { ISD::CTTZ, MVT::v8i32, { 21, 27, 32, 41 } }, // 2 x 128-bit Op + extract/insert
4711 { ISD::CTTZ, MVT::v4i32, { 11, 24, 17, 21 } },
4712 { ISD::CTTZ, MVT::v16i16, { 18, 24, 27, 36 } }, // 2 x 128-bit Op + extract/insert
4713 { ISD::CTTZ, MVT::v8i16, { 9, 21, 14, 18 } },
4714 { ISD::CTTZ, MVT::v32i8, { 15, 18, 21, 30 } }, // 2 x 128-bit Op + extract/insert
4715 { ISD::CTTZ, MVT::v16i8, { 8, 16, 11, 15 } },
4716 { ISD::MULHS, MVT::v8i32, { 9, 11, 14, 18 } },
4717 { ISD::MULHS, MVT::v16i16, { 3, 7, 5, 6 } },
4718 { ISD::MULHU, MVT::v8i32, { 9, 11, 14, 18 } },
4719 { ISD::MULHU, MVT::v16i16, { 3, 7, 5, 6 } },
4720 { ISD::SADDSAT, MVT::v2i64, { 6, 13, 8, 11 } },
4721 { ISD::SADDSAT, MVT::v4i64, { 13, 20, 15, 25 } }, // 2 x 128-bit Op + extract/insert
4722 { ISD::SADDSAT, MVT::v8i32, { 12, 18, 14, 24 } }, // 2 x 128-bit Op + extract/insert
4723 { ISD::SADDSAT, MVT::v16i16, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4724 { ISD::SADDSAT, MVT::v32i8, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4725 { ISD::SMAX, MVT::v4i64, { 6, 9, 6, 12 } }, // 2 x 128-bit Op + extract/insert
4726 { ISD::SMAX, MVT::v2i64, { 3, 7, 2, 4 } },
4727 { ISD::SMAX, MVT::v8i32, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4728 { ISD::SMAX, MVT::v16i16, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4729 { ISD::SMAX, MVT::v32i8, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4730 { ISD::SMIN, MVT::v4i64, { 6, 9, 6, 12 } }, // 2 x 128-bit Op + extract/insert
4731 { ISD::SMIN, MVT::v2i64, { 3, 7, 2, 3 } },
4732 { ISD::SMIN, MVT::v8i32, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4733 { ISD::SMIN, MVT::v16i16, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4734 { ISD::SMIN, MVT::v32i8, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4735 { ISD::SMULO, MVT::v4i64, { 20, 20, 33, 37 } },
4736 { ISD::SMULO, MVT::v2i64, { 9, 9, 13, 17 } },
4737 { ISD::SMULO, MVT::v8i32, { 15, 20, 24, 29 } },
4738 { ISD::SMULO, MVT::v4i32, { 7, 15, 11, 13 } },
4739 { ISD::SMULO, MVT::v16i16, { 8, 14, 14, 15 } },
4740 { ISD::SMULO, MVT::v8i16, { 3, 9, 6, 6 } },
4741 { ISD::SMULO, MVT::v32i8, { 20, 20, 37, 39 } },
4742 { ISD::SMULO, MVT::v16i8, { 9, 22, 18, 21 } },
4743 { ISD::SSUBSAT, MVT::v2i64, { 7, 13, 9, 13 } },
4744 { ISD::SSUBSAT, MVT::v4i64, { 15, 21, 18, 29 } }, // 2 x 128-bit Op + extract/insert
4745 { ISD::SSUBSAT, MVT::v8i32, { 15, 19, 18, 29 } }, // 2 x 128-bit Op + extract/insert
4746 { ISD::SSUBSAT, MVT::v16i16, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4747 { ISD::SSUBSAT, MVT::v32i8, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4748 { ISD::UADDSAT, MVT::v2i64, { 3, 8, 6, 6 } },
4749 { ISD::UADDSAT, MVT::v4i64, { 8, 11, 14, 15 } }, // 2 x 128-bit Op + extract/insert
4750 { ISD::UADDSAT, MVT::v8i32, { 6, 6, 10, 11 } }, // 2 x 128-bit Op + extract/insert
4751 { ISD::UADDSAT, MVT::v16i16, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4752 { ISD::UADDSAT, MVT::v32i8, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4753 { ISD::UMAX, MVT::v4i64, { 9, 10, 11, 17 } }, // 2 x 128-bit Op + extract/insert
4754 { ISD::UMAX, MVT::v2i64, { 4, 8, 5, 7 } },
4755 { ISD::UMAX, MVT::v8i32, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4756 { ISD::UMAX, MVT::v16i16, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4757 { ISD::UMAX, MVT::v32i8, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4758 { ISD::UMIN, MVT::v4i64, { 9, 10, 11, 17 } }, // 2 x 128-bit Op + extract/insert
4759 { ISD::UMIN, MVT::v2i64, { 4, 8, 5, 7 } },
4760 { ISD::UMIN, MVT::v8i32, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4761 { ISD::UMIN, MVT::v16i16, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4762 { ISD::UMIN, MVT::v32i8, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4763 { ISD::UMULO, MVT::v4i64, { 24, 26, 39, 45 } },
4764 { ISD::UMULO, MVT::v2i64, { 10, 12, 15, 20 } },
4765 { ISD::UMULO, MVT::v8i32, { 14, 15, 23, 28 } },
4766 { ISD::UMULO, MVT::v4i32, { 7, 12, 11, 13 } },
4767 { ISD::UMULO, MVT::v16i16, { 7, 11, 13, 14 } },
4768 { ISD::UMULO, MVT::v8i16, { 3, 8, 6, 6 } },
4769 { ISD::UMULO, MVT::v32i8, { 19, 19, 35, 37 } },
4770 { ISD::UMULO, MVT::v16i8, { 9, 19, 17, 20 } },
4771 { ISD::USUBSAT, MVT::v2i64, { 3, 7, 6, 6 } },
4772 { ISD::USUBSAT, MVT::v4i64, { 8, 10, 14, 15 } }, // 2 x 128-bit Op + extract/insert
4773 { ISD::USUBSAT, MVT::v8i32, { 4, 4, 7, 8 } }, // 2 x 128-bit Op + extract/insert
4774 { ISD::USUBSAT, MVT::v8i32, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4775 { ISD::USUBSAT, MVT::v16i16, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4776 { ISD::USUBSAT, MVT::v32i8, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4777 { ISD::FMAXNUM, MVT::f32, { 3, 6, 3, 5 } }, // MAXSS + CMPUNORDSS + BLENDVPS
4778 { ISD::FMAXNUM, MVT::v4f32, { 3, 6, 3, 5 } }, // MAXPS + CMPUNORDPS + BLENDVPS
4779 { ISD::FMAXNUM, MVT::v8f32, { 5, 7, 3, 10 } }, // MAXPS + CMPUNORDPS + BLENDVPS
4780 { ISD::FMAXNUM, MVT::f64, { 3, 6, 3, 5 } }, // MAXSD + CMPUNORDSD + BLENDVPD
4781 { ISD::FMAXNUM, MVT::v2f64, { 3, 6, 3, 5 } }, // MAXPD + CMPUNORDPD + BLENDVPD
4782 { ISD::FMAXNUM, MVT::v4f64, { 5, 7, 3, 10 } }, // MAXPD + CMPUNORDPD + BLENDVPD
4783 { ISD::FSQRT, MVT::f32, { 21, 21, 1, 1 } }, // vsqrtss
4784 { ISD::FSQRT, MVT::v4f32, { 21, 21, 1, 1 } }, // vsqrtps
4785 { ISD::FSQRT, MVT::v8f32, { 42, 42, 1, 3 } }, // vsqrtps
4786 { ISD::FSQRT, MVT::f64, { 27, 27, 1, 1 } }, // vsqrtsd
4787 { ISD::FSQRT, MVT::v2f64, { 27, 27, 1, 1 } }, // vsqrtpd
4788 { ISD::FSQRT, MVT::v4f64, { 54, 54, 1, 3 } }, // vsqrtpd
4789 };
4790 static const CostKindTblEntry GFNICostTbl[] = {
4791 { ISD::BITREVERSE, MVT::i8, { 3, 3, 3, 4 } }, // gf2p8affineqb
4792 { ISD::BITREVERSE, MVT::i16, { 3, 3, 4, 6 } }, // gf2p8affineqb
4793 { ISD::BITREVERSE, MVT::i32, { 3, 3, 4, 5 } }, // gf2p8affineqb
4794 { ISD::BITREVERSE, MVT::i64, { 3, 3, 4, 6 } }, // gf2p8affineqb
4795 { ISD::BITREVERSE, MVT::v16i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4796 { ISD::BITREVERSE, MVT::v32i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4797 { ISD::BITREVERSE, MVT::v64i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4798 { ISD::BITREVERSE, MVT::v8i16, { 1, 8, 2, 4 } }, // gf2p8affineqb
4799 { ISD::BITREVERSE, MVT::v16i16, { 1, 9, 2, 4 } }, // gf2p8affineqb
4800 { ISD::BITREVERSE, MVT::v32i16, { 1, 9, 2, 4 } }, // gf2p8affineqb
4801 { ISD::BITREVERSE, MVT::v4i32, { 1, 8, 2, 4 } }, // gf2p8affineqb
4802 { ISD::BITREVERSE, MVT::v8i32, { 1, 9, 2, 4 } }, // gf2p8affineqb
4803 { ISD::BITREVERSE, MVT::v16i32, { 1, 9, 2, 4 } }, // gf2p8affineqb
4804 { ISD::BITREVERSE, MVT::v2i64, { 1, 8, 2, 4 } }, // gf2p8affineqb
4805 { ISD::BITREVERSE, MVT::v4i64, { 1, 9, 2, 4 } }, // gf2p8affineqb
4806 { ISD::BITREVERSE, MVT::v8i64, { 1, 9, 2, 4 } }, // gf2p8affineqb
4807 { X86ISD::VROTLI, MVT::v16i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4808 { X86ISD::VROTLI, MVT::v32i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4809 { X86ISD::VROTLI, MVT::v64i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4810 };
4811 static const CostKindTblEntry GLMCostTbl[] = {
4812 { ISD::FSQRT, MVT::f32, { 19, 20, 1, 1 } }, // sqrtss
4813 { ISD::FSQRT, MVT::v4f32, { 37, 41, 1, 5 } }, // sqrtps
4814 { ISD::FSQRT, MVT::f64, { 34, 35, 1, 1 } }, // sqrtsd
4815 { ISD::FSQRT, MVT::v2f64, { 67, 71, 1, 5 } }, // sqrtpd
4816 };
4817 static const CostKindTblEntry SLMCostTbl[] = {
4818 { ISD::BSWAP, MVT::v2i64, { 5, 5, 1, 5 } },
4819 { ISD::BSWAP, MVT::v4i32, { 5, 5, 1, 5 } },
4820 { ISD::BSWAP, MVT::v8i16, { 5, 5, 1, 5 } },
4821 { ISD::FSQRT, MVT::f32, { 20, 20, 1, 1 } }, // sqrtss
4822 { ISD::FSQRT, MVT::v4f32, { 40, 41, 1, 5 } }, // sqrtps
4823 { ISD::FSQRT, MVT::f64, { 35, 35, 1, 1 } }, // sqrtsd
4824 { ISD::FSQRT, MVT::v2f64, { 70, 71, 1, 5 } }, // sqrtpd
4825 };
4826 static const CostKindTblEntry SSE42CostTbl[] = {
4827 { ISD::FMAXNUM, MVT::f32, { 5, 5, 7, 7 } }, // MAXSS + CMPUNORDSS + BLENDVPS
4828 { ISD::FMAXNUM, MVT::v4f32, { 4, 4, 4, 5 } }, // MAXPS + CMPUNORDPS + BLENDVPS
4829 { ISD::FMAXNUM, MVT::f64, { 5, 5, 7, 7 } }, // MAXSD + CMPUNORDSD + BLENDVPD
4830 { ISD::FMAXNUM, MVT::v2f64, { 4, 4, 4, 5 } }, // MAXPD + CMPUNORDPD + BLENDVPD
4831 { ISD::FSQRT, MVT::f32, { 18, 18, 1, 1 } }, // Nehalem from http://www.agner.org/
4832 { ISD::FSQRT, MVT::v4f32, { 18, 18, 1, 1 } }, // Nehalem from http://www.agner.org/
4833 };
4834 static const CostKindTblEntry SSE41CostTbl[] = {
4835 { ISD::ABS, MVT::v2i64, { 3, 4, 3, 5 } }, // BLENDVPD(X,PSUBQ(0,X),X)
4836 { ISD::MULHS, MVT::v4i32, { 3, 9, 6, 7 } },
4837 { ISD::MULHU, MVT::v4i32, { 3, 9, 6, 7 } },
4838 { ISD::SADDSAT, MVT::v2i64, { 10, 14, 17, 21 } },
4839 { ISD::SADDSAT, MVT::v4i32, { 5, 11, 8, 10 } },
4840 { ISD::SSUBSAT, MVT::v2i64, { 12, 19, 25, 29 } },
4841 { ISD::SSUBSAT, MVT::v4i32, { 6, 14, 10, 12 } },
4842 { ISD::SMAX, MVT::v2i64, { 3, 7, 2, 3 } },
4843 { ISD::SMAX, MVT::v4i32, { 1, 1, 1, 1 } },
4844 { ISD::SMAX, MVT::v16i8, { 1, 1, 1, 1 } },
4845 { ISD::SMIN, MVT::v2i64, { 3, 7, 2, 3 } },
4846 { ISD::SMIN, MVT::v4i32, { 1, 1, 1, 1 } },
4847 { ISD::SMIN, MVT::v16i8, { 1, 1, 1, 1 } },
4848 { ISD::SMULO, MVT::v2i64, { 9, 11, 13, 17 } },
4849 { ISD::SMULO, MVT::v4i32, { 20, 24, 13, 19 } },
4850 { ISD::SMULO, MVT::v8i16, { 5, 9, 8, 8 } },
4851 { ISD::SMULO, MVT::v16i8, { 13, 22, 24, 25 } },
4852 { ISD::UADDSAT, MVT::v2i64, { 6, 13, 14, 14 } },
4853 { ISD::UADDSAT, MVT::v4i32, { 2, 2, 4, 4 } },
4854 { ISD::USUBSAT, MVT::v2i64, { 6, 10, 14, 14 } },
4855 { ISD::USUBSAT, MVT::v4i32, { 1, 2, 2, 2 } },
4856 { ISD::UMAX, MVT::v2i64, { 2, 11, 6, 7 } },
4857 { ISD::UMAX, MVT::v4i32, { 1, 1, 1, 1 } },
4858 { ISD::UMAX, MVT::v8i16, { 1, 1, 1, 1 } },
4859 { ISD::UMIN, MVT::v2i64, { 2, 11, 6, 7 } },
4860 { ISD::UMIN, MVT::v4i32, { 1, 1, 1, 1 } },
4861 { ISD::UMIN, MVT::v8i16, { 1, 1, 1, 1 } },
4862 { ISD::UMULO, MVT::v2i64, { 14, 20, 15, 20 } },
4863 { ISD::UMULO, MVT::v4i32, { 19, 22, 12, 18 } },
4864 { ISD::UMULO, MVT::v8i16, { 4, 9, 7, 7 } },
4865 { ISD::UMULO, MVT::v16i8, { 13, 19, 18, 20 } },
4866 };
4867 static const CostKindTblEntry SSSE3CostTbl[] = {
4868 { ISD::ABS, MVT::v4i32, { 1, 2, 1, 1 } },
4869 { ISD::ABS, MVT::v8i16, { 1, 2, 1, 1 } },
4870 { ISD::ABS, MVT::v16i8, { 1, 2, 1, 1 } },
4871 { ISD::BITREVERSE, MVT::v2i64, { 16, 20, 11, 21 } },
4872 { ISD::BITREVERSE, MVT::v4i32, { 16, 20, 11, 21 } },
4873 { ISD::BITREVERSE, MVT::v8i16, { 16, 20, 11, 21 } },
4874 { ISD::BITREVERSE, MVT::v16i8, { 11, 12, 10, 16 } },
4875 { ISD::BSWAP, MVT::v2i64, { 2, 3, 1, 5 } },
4876 { ISD::BSWAP, MVT::v4i32, { 2, 3, 1, 5 } },
4877 { ISD::BSWAP, MVT::v8i16, { 2, 3, 1, 5 } },
4878 { ISD::CTLZ, MVT::v2i64, { 18, 28, 28, 35 } },
4879 { ISD::CTLZ, MVT::v4i32, { 15, 20, 22, 28 } },
4880 { ISD::CTLZ, MVT::v8i16, { 13, 17, 16, 22 } },
4881 { ISD::CTLZ, MVT::v16i8, { 11, 15, 10, 16 } },
4882 { ISD::CTPOP, MVT::v2i64, { 13, 19, 12, 18 } },
4883 { ISD::CTPOP, MVT::v4i32, { 18, 24, 16, 22 } },
4884 { ISD::CTPOP, MVT::v8i16, { 13, 18, 14, 20 } },
4885 { ISD::CTPOP, MVT::v16i8, { 11, 12, 10, 16 } },
4886 { ISD::CTTZ, MVT::v2i64, { 13, 25, 15, 22 } },
4887 { ISD::CTTZ, MVT::v4i32, { 18, 26, 19, 25 } },
4888 { ISD::CTTZ, MVT::v8i16, { 13, 20, 17, 23 } },
4889 { ISD::CTTZ, MVT::v16i8, { 11, 16, 13, 19 } }
4890 };
4891 static const CostKindTblEntry SSE2CostTbl[] = {
4892 { ISD::ABS, MVT::v2i64, { 3, 6, 5, 5 } },
4893 { ISD::ABS, MVT::v4i32, { 1, 4, 4, 4 } },
4894 { ISD::ABS, MVT::v8i16, { 1, 2, 3, 3 } },
4895 { ISD::ABS, MVT::v16i8, { 1, 2, 3, 3 } },
4896 { ISD::BITREVERSE, MVT::v2i64, { 16, 20, 32, 32 } },
4897 { ISD::BITREVERSE, MVT::v4i32, { 16, 20, 30, 30 } },
4898 { ISD::BITREVERSE, MVT::v8i16, { 16, 20, 25, 25 } },
4899 { ISD::BITREVERSE, MVT::v16i8, { 11, 12, 21, 21 } },
4900 { ISD::BSWAP, MVT::v2i64, { 5, 6, 11, 11 } },
4901 { ISD::BSWAP, MVT::v4i32, { 5, 5, 9, 9 } },
4902 { ISD::BSWAP, MVT::v8i16, { 5, 5, 4, 5 } },
4903 { ISD::CTLZ, MVT::v2i64, { 10, 45, 36, 38 } },
4904 { ISD::CTLZ, MVT::v4i32, { 10, 45, 38, 40 } },
4905 { ISD::CTLZ, MVT::v8i16, { 9, 38, 32, 34 } },
4906 { ISD::CTLZ, MVT::v16i8, { 8, 39, 29, 32 } },
4907 { ISD::CTPOP, MVT::v2i64, { 12, 26, 16, 18 } },
4908 { ISD::CTPOP, MVT::v4i32, { 15, 29, 21, 23 } },
4909 { ISD::CTPOP, MVT::v8i16, { 13, 25, 18, 20 } },
4910 { ISD::CTPOP, MVT::v16i8, { 10, 21, 14, 16 } },
4911 { ISD::CTTZ, MVT::v2i64, { 14, 28, 19, 21 } },
4912 { ISD::CTTZ, MVT::v4i32, { 18, 31, 24, 26 } },
4913 { ISD::CTTZ, MVT::v8i16, { 16, 27, 21, 23 } },
4914 { ISD::CTTZ, MVT::v16i8, { 13, 23, 17, 19 } },
4915 { ISD::MULHS, MVT::v4i32, { 5, 11, 15, 15 } },
4916 { ISD::MULHS, MVT::v8i16, { 1, 5, 1, 1 } },
4917 { ISD::MULHU, MVT::v4i32, { 3, 9, 7, 7 } },
4918 { ISD::MULHU, MVT::v8i16, { 1, 5, 1, 1 } },
4919 { ISD::SADDSAT, MVT::v2i64, { 12, 14, 24, 24 } },
4920 { ISD::SADDSAT, MVT::v4i32, { 6, 11, 11, 12 } },
4921 { ISD::SADDSAT, MVT::v8i16, { 1, 2, 1, 1 } },
4922 { ISD::SADDSAT, MVT::v16i8, { 1, 2, 1, 1 } },
4923 { ISD::SMAX, MVT::v2i64, { 4, 8, 15, 15 } },
4924 { ISD::SMAX, MVT::v4i32, { 2, 4, 5, 5 } },
4925 { ISD::SMAX, MVT::v8i16, { 1, 1, 1, 1 } },
4926 { ISD::SMAX, MVT::v16i8, { 2, 4, 5, 5 } },
4927 { ISD::SMIN, MVT::v2i64, { 4, 8, 15, 15 } },
4928 { ISD::SMIN, MVT::v4i32, { 2, 4, 5, 5 } },
4929 { ISD::SMIN, MVT::v8i16, { 1, 1, 1, 1 } },
4930 { ISD::SMIN, MVT::v16i8, { 2, 4, 5, 5 } },
4931 { ISD::SMULO, MVT::v2i64, { 30, 33, 13, 23 } },
4932 { ISD::SMULO, MVT::v4i32, { 20, 24, 23, 23 } },
4933 { ISD::SMULO, MVT::v8i16, { 5, 10, 8, 8 } },
4934 { ISD::SMULO, MVT::v16i8, { 13, 23, 24, 25 } },
4935 { ISD::SSUBSAT, MVT::v2i64, { 16, 19, 31, 31 } },
4936 { ISD::SSUBSAT, MVT::v4i32, { 6, 14, 12, 13 } },
4937 { ISD::SSUBSAT, MVT::v8i16, { 1, 2, 1, 1 } },
4938 { ISD::SSUBSAT, MVT::v16i8, { 1, 2, 1, 1 } },
4939 { ISD::UADDSAT, MVT::v2i64, { 7, 13, 14, 14 } },
4940 { ISD::UADDSAT, MVT::v4i32, { 4, 5, 7, 7 } },
4941 { ISD::UADDSAT, MVT::v8i16, { 1, 2, 1, 1 } },
4942 { ISD::UADDSAT, MVT::v16i8, { 1, 2, 1, 1 } },
4943 { ISD::UMAX, MVT::v2i64, { 4, 8, 15, 15 } },
4944 { ISD::UMAX, MVT::v4i32, { 2, 5, 8, 8 } },
4945 { ISD::UMAX, MVT::v8i16, { 1, 3, 3, 3 } },
4946 { ISD::UMAX, MVT::v16i8, { 1, 1, 1, 1 } },
4947 { ISD::UMIN, MVT::v2i64, { 4, 8, 15, 15 } },
4948 { ISD::UMIN, MVT::v4i32, { 2, 5, 8, 8 } },
4949 { ISD::UMIN, MVT::v8i16, { 1, 3, 3, 3 } },
4950 { ISD::UMIN, MVT::v16i8, { 1, 1, 1, 1 } },
4951 { ISD::UMULO, MVT::v2i64, { 30, 33, 15, 29 } },
4952 { ISD::UMULO, MVT::v4i32, { 19, 22, 14, 18 } },
4953 { ISD::UMULO, MVT::v8i16, { 4, 9, 7, 7 } },
4954 { ISD::UMULO, MVT::v16i8, { 13, 19, 20, 20 } },
4955 { ISD::USUBSAT, MVT::v2i64, { 7, 10, 14, 14 } },
4956 { ISD::USUBSAT, MVT::v4i32, { 4, 4, 7, 7 } },
4957 { ISD::USUBSAT, MVT::v8i16, { 1, 2, 1, 1 } },
4958 { ISD::USUBSAT, MVT::v16i8, { 1, 2, 1, 1 } },
4959 { ISD::FMAXNUM, MVT::f64, { 5, 5, 7, 7 } },
4960 { ISD::FMAXNUM, MVT::v2f64, { 4, 6, 6, 6 } },
4961 { ISD::FSQRT, MVT::f64, { 32, 32, 1, 1 } }, // Nehalem from http://www.agner.org/
4962 { ISD::FSQRT, MVT::v2f64, { 32, 32, 1, 1 } }, // Nehalem from http://www.agner.org/
4963 };
4964 static const CostKindTblEntry SSE1CostTbl[] = {
4965 { ISD::FMAXNUM, MVT::f32, { 5, 5, 7, 7 } },
4966 { ISD::FMAXNUM, MVT::v4f32, { 4, 6, 6, 6 } },
4967 { ISD::FSQRT, MVT::f32, { 28, 30, 1, 2 } }, // Pentium III from http://www.agner.org/
4968 { ISD::FSQRT, MVT::v4f32, { 56, 56, 1, 2 } }, // Pentium III from http://www.agner.org/
4969 };
4970 static const CostKindTblEntry BMI64CostTbl[] = { // 64-bit targets
4971 { ISD::CTTZ, MVT::i64, { 1, 1, 1, 1 } },
4972 };
4973 static const CostKindTblEntry BMI32CostTbl[] = { // 32 or 64-bit targets
4974 { ISD::CTTZ, MVT::i32, { 1, 1, 1, 1 } },
4975 { ISD::CTTZ, MVT::i16, { 2, 1, 1, 1 } },
4976 { ISD::CTTZ, MVT::i8, { 2, 1, 1, 1 } },
4977 };
4978 static const CostKindTblEntry LZCNT64CostTbl[] = { // 64-bit targets
4979 { ISD::CTLZ, MVT::i64, { 1, 1, 1, 1 } },
4980 };
4981 static const CostKindTblEntry LZCNT32CostTbl[] = { // 32 or 64-bit targets
4982 { ISD::CTLZ, MVT::i32, { 1, 1, 1, 1 } },
4983 { ISD::CTLZ, MVT::i16, { 2, 1, 1, 1 } },
4984 { ISD::CTLZ, MVT::i8, { 2, 1, 1, 1 } },
4985 };
4986 static const CostKindTblEntry POPCNT64CostTbl[] = { // 64-bit targets
4987 { ISD::CTPOP, MVT::i64, { 1, 1, 1, 1 } }, // popcnt
4988 };
4989 static const CostKindTblEntry POPCNT32CostTbl[] = { // 32 or 64-bit targets
4990 { ISD::CTPOP, MVT::i32, { 1, 1, 1, 1 } }, // popcnt
4991 { ISD::CTPOP, MVT::i16, { 1, 1, 2, 2 } }, // popcnt(zext())
4992 { ISD::CTPOP, MVT::i8, { 1, 1, 2, 2 } }, // popcnt(zext())
4993 };
4994 static const CostKindTblEntry PCLMULCostTbl[] = {
4995 { ISD::CLMUL, MVT::v2i64, { 3, 12, 4, 8 } }, // MOV+2xPCLMUL+unpack
4996 { ISD::CLMUL, MVT::v4i32, { 8, 18, 12, 16 } }, // MOV+4xPCLMUL+unpack
4997 { ISD::CLMUL, MVT::i64, { 3, 12, 4, 8 } }, // MOV+PCLMUL+MOV
4998 { ISD::CLMUL, MVT::i32, { 3, 12, 4, 8 } }, // MOV+PCLMUL+MOV
4999 { ISD::CLMUL, MVT::i16, { 3, 12, 4, 8 } }, // MOV+PCLMUL+MOV
5000 { ISD::CLMUL, MVT::i8, { 3, 12, 4, 8 } }, // MOV+PCLMUL+MOV
5001 };
5002 static const CostKindTblEntry X64CostTbl[] = { // 64-bit targets
5003 { ISD::ABS, MVT::i64, { 1, 2, 3, 3 } }, // SUB+CMOV
5004 { ISD::BITREVERSE, MVT::i64, { 10, 12, 20, 22 } },
5005 { ISD::BSWAP, MVT::i64, { 1, 2, 1, 2 } },
5006 { ISD::CTLZ, MVT::i64, { 1, 2, 3, 3 } }, // MOV+BSR+XOR
5007 { ISD::CTLZ, MVT::i32, { 1, 2, 3, 3 } }, // MOV+BSR+XOR
5008 { ISD::CTLZ, MVT::i16, { 2, 2, 3, 3 } }, // MOV+BSR+XOR
5009 { ISD::CTLZ, MVT::i8, { 2, 2, 4, 3 } }, // MOV+BSR+XOR
5010 { ISD::CTLZ_ZERO_POISON,MVT::i64,{ 1, 2, 2, 2 } }, // BSR+XOR
5011 { ISD::CTTZ, MVT::i64, { 1, 2, 2, 2 } }, // MOV+BSF
5012 { ISD::CTTZ, MVT::i32, { 1, 2, 2, 2 } }, // MOV+BSF
5013 { ISD::CTTZ, MVT::i16, { 2, 2, 2, 2 } }, // MOV+BSF
5014 { ISD::CTTZ, MVT::i8, { 2, 2, 2, 2 } }, // MOV+BSF
5015 { ISD::CTTZ_ZERO_POISON,MVT::i64,{ 1, 2, 1, 2 } }, // BSF
5016 { ISD::CTPOP, MVT::i64, { 10, 6, 19, 19 } },
5017 { ISD::ROTL, MVT::i64, { 2, 3, 1, 3 } },
5018 { ISD::ROTR, MVT::i64, { 2, 3, 1, 3 } },
5019 { X86ISD::VROTLI, MVT::i64, { 1, 1, 1, 1 } },
5020 { ISD::FSHL, MVT::i64, { 4, 4, 1, 4 } },
5021 { ISD::SADDSAT, MVT::i64, { 4, 4, 7, 10 } },
5022 { ISD::SSUBSAT, MVT::i64, { 4, 5, 8, 11 } },
5023 { ISD::UADDSAT, MVT::i64, { 2, 3, 4, 7 } },
5024 { ISD::USUBSAT, MVT::i64, { 2, 3, 4, 7 } },
5025 { ISD::SMAX, MVT::i64, { 1, 3, 2, 3 } },
5026 { ISD::SMIN, MVT::i64, { 1, 3, 2, 3 } },
5027 { ISD::UMAX, MVT::i64, { 1, 3, 2, 3 } },
5028 { ISD::UMIN, MVT::i64, { 1, 3, 2, 3 } },
5029 { ISD::SADDO, MVT::i64, { 2, 2, 4, 6 } },
5030 { ISD::UADDO, MVT::i64, { 2, 2, 4, 6 } },
5031 { ISD::SMULO, MVT::i64, { 4, 4, 4, 6 } },
5032 { ISD::UMULO, MVT::i64, { 8, 8, 4, 7 } },
5033 };
5034 static const CostKindTblEntry X86CostTbl[] = { // 32 or 64-bit targets
5035 { ISD::ABS, MVT::i32, { 1, 2, 3, 3 } }, // SUB+XOR+SRA or SUB+CMOV
5036 { ISD::ABS, MVT::i16, { 2, 2, 3, 3 } }, // SUB+XOR+SRA or SUB+CMOV
5037 { ISD::ABS, MVT::i8, { 2, 4, 4, 3 } }, // SUB+XOR+SRA
5038 { ISD::BITREVERSE, MVT::i32, { 9, 12, 17, 19 } },
5039 { ISD::BITREVERSE, MVT::i16, { 9, 12, 17, 19 } },
5040 { ISD::BITREVERSE, MVT::i8, { 7, 9, 13, 14 } },
5041 { ISD::BSWAP, MVT::i32, { 1, 1, 1, 1 } },
5042 { ISD::BSWAP, MVT::i16, { 1, 2, 1, 2 } }, // ROL
5043 { ISD::CTLZ, MVT::i32, { 2, 2, 4, 5 } }, // BSR+XOR or BSR+XOR+CMOV
5044 { ISD::CTLZ, MVT::i16, { 2, 2, 4, 5 } }, // BSR+XOR or BSR+XOR+CMOV
5045 { ISD::CTLZ, MVT::i8, { 2, 2, 5, 6 } }, // BSR+XOR or BSR+XOR+CMOV
5046 { ISD::CTLZ_ZERO_POISON,MVT::i32,{ 1, 2, 2, 2 } }, // BSR+XOR
5047 { ISD::CTLZ_ZERO_POISON,MVT::i16,{ 2, 2, 2, 2 } }, // BSR+XOR
5048 { ISD::CTLZ_ZERO_POISON,MVT::i8, { 2, 2, 3, 3 } }, // BSR+XOR
5049 { ISD::CTTZ, MVT::i32, { 2, 2, 3, 3 } }, // TEST+BSF+CMOV/BRANCH
5050 { ISD::CTTZ, MVT::i16, { 2, 2, 2, 3 } }, // TEST+BSF+CMOV/BRANCH
5051 { ISD::CTTZ, MVT::i8, { 2, 2, 2, 3 } }, // TEST+BSF+CMOV/BRANCH
5052 { ISD::CTTZ_ZERO_POISON,MVT::i32,{ 1, 2, 1, 2 } }, // BSF
5053 { ISD::CTTZ_ZERO_POISON,MVT::i16,{ 2, 2, 1, 2 } }, // BSF
5054 { ISD::CTTZ_ZERO_POISON,MVT::i8, { 2, 2, 1, 2 } }, // BSF
5055 { ISD::CTPOP, MVT::i32, { 8, 7, 15, 15 } },
5056 { ISD::CTPOP, MVT::i16, { 9, 8, 17, 17 } },
5057 { ISD::CTPOP, MVT::i8, { 7, 6, 6, 6 } },
5058 { ISD::ROTL, MVT::i32, { 2, 3, 1, 3 } },
5059 { ISD::ROTL, MVT::i16, { 2, 3, 1, 3 } },
5060 { ISD::ROTL, MVT::i8, { 2, 3, 1, 3 } },
5061 { ISD::ROTR, MVT::i32, { 2, 3, 1, 3 } },
5062 { ISD::ROTR, MVT::i16, { 2, 3, 1, 3 } },
5063 { ISD::ROTR, MVT::i8, { 2, 3, 1, 3 } },
5064 { X86ISD::VROTLI, MVT::i32, { 1, 1, 1, 1 } },
5065 { X86ISD::VROTLI, MVT::i16, { 1, 1, 1, 1 } },
5066 { X86ISD::VROTLI, MVT::i8, { 1, 1, 1, 1 } },
5067 { ISD::FSHL, MVT::i32, { 4, 4, 1, 4 } },
5068 { ISD::FSHL, MVT::i16, { 4, 4, 2, 5 } },
5069 { ISD::FSHL, MVT::i8, { 4, 4, 2, 5 } },
5070 { ISD::SADDSAT, MVT::i32, { 3, 4, 6, 9 } },
5071 { ISD::SADDSAT, MVT::i16, { 4, 4, 7, 10 } },
5072 { ISD::SADDSAT, MVT::i8, { 4, 5, 8, 11 } },
5073 { ISD::SSUBSAT, MVT::i32, { 4, 4, 7, 10 } },
5074 { ISD::SSUBSAT, MVT::i16, { 4, 4, 7, 10 } },
5075 { ISD::SSUBSAT, MVT::i8, { 4, 5, 8, 11 } },
5076 { ISD::UADDSAT, MVT::i32, { 2, 3, 4, 7 } },
5077 { ISD::UADDSAT, MVT::i16, { 2, 3, 4, 7 } },
5078 { ISD::UADDSAT, MVT::i8, { 3, 3, 5, 8 } },
5079 { ISD::USUBSAT, MVT::i32, { 2, 3, 4, 7 } },
5080 { ISD::USUBSAT, MVT::i16, { 2, 3, 4, 7 } },
5081 { ISD::USUBSAT, MVT::i8, { 3, 3, 5, 8 } },
5082 { ISD::SMAX, MVT::i32, { 1, 2, 2, 3 } },
5083 { ISD::SMAX, MVT::i16, { 1, 4, 2, 4 } },
5084 { ISD::SMAX, MVT::i8, { 1, 4, 2, 4 } },
5085 { ISD::SMIN, MVT::i32, { 1, 2, 2, 3 } },
5086 { ISD::SMIN, MVT::i16, { 1, 4, 2, 4 } },
5087 { ISD::SMIN, MVT::i8, { 1, 4, 2, 4 } },
5088 { ISD::UMAX, MVT::i32, { 1, 2, 2, 3 } },
5089 { ISD::UMAX, MVT::i16, { 1, 4, 2, 4 } },
5090 { ISD::UMAX, MVT::i8, { 1, 4, 2, 4 } },
5091 { ISD::UMIN, MVT::i32, { 1, 2, 2, 3 } },
5092 { ISD::UMIN, MVT::i16, { 1, 4, 2, 4 } },
5093 { ISD::UMIN, MVT::i8, { 1, 4, 2, 4 } },
5094 { ISD::SADDO, MVT::i32, { 2, 2, 4, 6 } },
5095 { ISD::SADDO, MVT::i16, { 2, 2, 4, 6 } },
5096 { ISD::SADDO, MVT::i8, { 2, 2, 4, 6 } },
5097 { ISD::UADDO, MVT::i32, { 2, 2, 4, 6 } },
5098 { ISD::UADDO, MVT::i16, { 2, 2, 4, 6 } },
5099 { ISD::UADDO, MVT::i8, { 2, 2, 4, 6 } },
5100 { ISD::SMULO, MVT::i32, { 2, 2, 4, 6 } },
5101 { ISD::SMULO, MVT::i16, { 5, 5, 4, 6 } },
5102 { ISD::SMULO, MVT::i8, { 6, 6, 4, 6 } },
5103 { ISD::UMULO, MVT::i32, { 6, 6, 4, 8 } },
5104 { ISD::UMULO, MVT::i16, { 6, 6, 4, 9 } },
5105 { ISD::UMULO, MVT::i8, { 6, 6, 4, 6 } },
5106 };
5107
5108 Type *RetTy = ICA.getReturnType();
5109 Type *OpTy = RetTy;
5110 Intrinsic::ID IID = ICA.getID();
5111 unsigned ISD = ISD::DELETED_NODE;
5112 switch (IID) {
5113 default:
5114 break;
5115 case Intrinsic::abs:
5116 ISD = ISD::ABS;
5117 break;
5118 case Intrinsic::bitreverse:
5120 break;
5121 case Intrinsic::bswap:
5122 ISD = ISD::BSWAP;
5123 break;
5124 case Intrinsic::ctlz:
5125 ISD = ISD::CTLZ;
5126 break;
5127 case Intrinsic::ctpop:
5128 ISD = ISD::CTPOP;
5129 break;
5130 case Intrinsic::cttz:
5131 ISD = ISD::CTTZ;
5132 break;
5133 case Intrinsic::fshl:
5134 ISD = ISD::FSHL;
5135 if (!ICA.isTypeBasedOnly()) {
5136 const SmallVectorImpl<const Value *> &Args = ICA.getArgs();
5137 if (Args[0] == Args[1]) {
5138 ISD = ISD::ROTL;
5139 // Handle uniform constant rotation amounts.
5140 // TODO: Handle funnel-shift cases.
5141 const APInt *Amt;
5142 if (Args[2] &&
5144 ISD = X86ISD::VROTLI;
5145 }
5146 }
5147 break;
5148 case Intrinsic::fshr:
5149 // FSHR has same costs so don't duplicate.
5150 ISD = ISD::FSHL;
5151 if (!ICA.isTypeBasedOnly()) {
5152 const SmallVectorImpl<const Value *> &Args = ICA.getArgs();
5153 if (Args[0] == Args[1]) {
5154 ISD = ISD::ROTR;
5155 // Handle uniform constant rotation amount.
5156 // TODO: Handle funnel-shift cases.
5157 const APInt *Amt;
5158 if (Args[2] &&
5160 ISD = X86ISD::VROTLI;
5161 }
5162 }
5163 break;
5164 case Intrinsic::lrint:
5165 case Intrinsic::llrint: {
5166 // X86 can use the CVTP2SI instructions to lower lrint/llrint calls, which
5167 // have the same costs as the CVTTP2SI (fptosi) instructions
5168 const SmallVectorImpl<Type *> &ArgTys = ICA.getArgTypes();
5169 return getCastInstrCost(Instruction::FPToSI, RetTy, ArgTys[0],
5170 TTI::CastContextHint::None, CostKind);
5171 }
5172 case Intrinsic::maxnum:
5173 case Intrinsic::minnum:
5174 // FMINNUM has same costs so don't duplicate.
5175 ISD = ISD::FMAXNUM;
5176 break;
5177 case Intrinsic::sadd_sat:
5178 ISD = ISD::SADDSAT;
5179 break;
5180 case Intrinsic::smax:
5181 ISD = ISD::SMAX;
5182 break;
5183 case Intrinsic::smin:
5184 ISD = ISD::SMIN;
5185 break;
5186 case Intrinsic::smulh:
5187 ISD = ISD::MULHS;
5188 break;
5189 case Intrinsic::ssub_sat:
5190 ISD = ISD::SSUBSAT;
5191 break;
5192 case Intrinsic::uadd_sat:
5193 ISD = ISD::UADDSAT;
5194 break;
5195 case Intrinsic::umax:
5196 ISD = ISD::UMAX;
5197 break;
5198 case Intrinsic::umin:
5199 ISD = ISD::UMIN;
5200 break;
5201 case Intrinsic::usub_sat:
5202 ISD = ISD::USUBSAT;
5203 break;
5204 case Intrinsic::umulh:
5205 ISD = ISD::MULHU;
5206 break;
5207 case Intrinsic::sqrt:
5208 // The estimate sequence is costed with the division it is folded into.
5209 if (isFoldedIntoRsqrtEstimate(ICA.getInst(), *TLI,
5210 getTypeLegalizationCost(RetTy).second,
5211 CostKind))
5212 return TTI::TCC_Free;
5213 ISD = ISD::FSQRT;
5214 break;
5215 case Intrinsic::sadd_with_overflow:
5216 case Intrinsic::ssub_with_overflow:
5217 // SSUBO has same costs so don't duplicate.
5218 ISD = ISD::SADDO;
5219 OpTy = RetTy->getContainedType(0);
5220 break;
5221 case Intrinsic::uadd_with_overflow:
5222 case Intrinsic::usub_with_overflow:
5223 // USUBO has same costs so don't duplicate.
5224 ISD = ISD::UADDO;
5225 OpTy = RetTy->getContainedType(0);
5226 break;
5227 case Intrinsic::smul_with_overflow:
5228 ISD = ISD::SMULO;
5229 OpTy = RetTy->getContainedType(0);
5230 break;
5231 case Intrinsic::umul_with_overflow:
5232 ISD = ISD::UMULO;
5233 OpTy = RetTy->getContainedType(0);
5234 break;
5235 case Intrinsic::clmul:
5236 ISD = ISD::CLMUL;
5237 break;
5238 }
5239
5240 if (ISD != ISD::DELETED_NODE) {
5241 auto adjustTableCost = [&](int ISD, unsigned Cost,
5242 std::pair<InstructionCost, MVT> LT,
5244 InstructionCost LegalizationCost = LT.first;
5245 MVT MTy = LT.second;
5246
5247 // If there are no NANs to deal with, then these are reduced to a
5248 // single MIN** or MAX** instruction instead of the MIN/CMP/SELECT that we
5249 // assume is used in the non-fast case.
5250 if (ISD == ISD::FMAXNUM || ISD == ISD::FMINNUM) {
5251 if (FMF.noNaNs())
5252 return LegalizationCost * 1;
5253 }
5254
5255 // For cases where some ops can be folded into a load/store, assume free.
5256 if (MTy.isScalarInteger()) {
5257 if (ISD == ISD::BSWAP && ST->hasMOVBE() && ST->hasFastMOVBE()) {
5258 if (const Instruction *II = ICA.getInst()) {
5259 if (II->hasOneUse() && isa<StoreInst>(II->user_back()))
5260 return TTI::TCC_Free;
5261 if (auto *LI = dyn_cast<LoadInst>(II->getOperand(0))) {
5262 if (LI->hasOneUse())
5263 return TTI::TCC_Free;
5264 }
5265 }
5266 }
5267 }
5268
5269 return LegalizationCost * (int)Cost;
5270 };
5271
5272 // Legalize the type.
5273 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(OpTy);
5274 MVT MTy = LT.second;
5275
5276 // Without BMI/LZCNT see if we're only looking for a *_ZERO_POISON cost.
5277 if (((ISD == ISD::CTTZ && !ST->hasBMI()) ||
5278 (ISD == ISD::CTLZ && !ST->hasLZCNT())) &&
5279 !MTy.isVector() && !ICA.isTypeBasedOnly()) {
5280 const SmallVectorImpl<const Value *> &Args = ICA.getArgs();
5281 if (auto *Cst = dyn_cast<ConstantInt>(Args[1]))
5282 if (Cst->isAllOnesValue())
5283 ISD =
5285 }
5286
5287 // FSQRT is a single instruction.
5288 if (ISD == ISD::FSQRT && CostKind == TTI::TCK_CodeSize)
5289 return LT.first;
5290
5291 if (ST->useGLMDivSqrtCosts())
5292 if (const auto *Entry = CostTableLookup(GLMCostTbl, ISD, MTy))
5293 if (auto KindCost = Entry->Cost[CostKind])
5294 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5295
5296 if (ST->useSLMArithCosts())
5297 if (const auto *Entry = CostTableLookup(SLMCostTbl, ISD, MTy))
5298 if (auto KindCost = Entry->Cost[CostKind])
5299 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5300
5301 if (ST->hasVBMI2())
5302 if (const auto *Entry = CostTableLookup(AVX512VBMI2CostTbl, ISD, MTy))
5303 if (auto KindCost = Entry->Cost[CostKind])
5304 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5305
5306 if (ST->hasBITALG())
5307 if (const auto *Entry = CostTableLookup(AVX512BITALGCostTbl, ISD, MTy))
5308 if (auto KindCost = Entry->Cost[CostKind])
5309 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5310
5311 if (ST->hasVPOPCNTDQ())
5312 if (const auto *Entry = CostTableLookup(AVX512VPOPCNTDQCostTbl, ISD, MTy))
5313 if (auto KindCost = Entry->Cost[CostKind])
5314 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5315
5316 if (ST->hasGFNI())
5317 if (const auto *Entry = CostTableLookup(GFNICostTbl, ISD, MTy))
5318 if (auto KindCost = Entry->Cost[CostKind])
5319 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5320
5321 if (ST->hasCDI())
5322 if (const auto *Entry = CostTableLookup(AVX512CDCostTbl, ISD, MTy))
5323 if (auto KindCost = Entry->Cost[CostKind])
5324 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5325
5326 if (ST->hasBWI())
5327 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
5328 if (auto KindCost = Entry->Cost[CostKind])
5329 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5330
5331 if (ST->hasAVX512())
5332 if (const auto *Entry = CostTableLookup(AVX512CostTbl, ISD, MTy))
5333 if (auto KindCost = Entry->Cost[CostKind])
5334 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5335
5336 if (ST->hasXOP())
5337 if (const auto *Entry = CostTableLookup(XOPCostTbl, ISD, MTy))
5338 if (auto KindCost = Entry->Cost[CostKind])
5339 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5340
5341 if (ST->hasAVX2())
5342 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
5343 if (auto KindCost = Entry->Cost[CostKind])
5344 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5345
5346 if (ST->hasAVX())
5347 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
5348 if (auto KindCost = Entry->Cost[CostKind])
5349 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5350
5351 if (ST->hasSSE42())
5352 if (const auto *Entry = CostTableLookup(SSE42CostTbl, ISD, MTy))
5353 if (auto KindCost = Entry->Cost[CostKind])
5354 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5355
5356 if (ST->hasSSE41())
5357 if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
5358 if (auto KindCost = Entry->Cost[CostKind])
5359 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5360
5361 if (ST->hasSSSE3())
5362 if (const auto *Entry = CostTableLookup(SSSE3CostTbl, ISD, MTy))
5363 if (auto KindCost = Entry->Cost[CostKind])
5364 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5365
5366 if (ST->hasSSE2())
5367 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
5368 if (auto KindCost = Entry->Cost[CostKind])
5369 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5370
5371 if (ST->hasSSE1())
5372 if (const auto *Entry = CostTableLookup(SSE1CostTbl, ISD, MTy))
5373 if (auto KindCost = Entry->Cost[CostKind])
5374 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5375
5376 if (ST->hasBMI()) {
5377 if (ST->is64Bit())
5378 if (const auto *Entry = CostTableLookup(BMI64CostTbl, ISD, MTy))
5379 if (auto KindCost = Entry->Cost[CostKind])
5380 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5381
5382 if (const auto *Entry = CostTableLookup(BMI32CostTbl, ISD, MTy))
5383 if (auto KindCost = Entry->Cost[CostKind])
5384 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5385 }
5386
5387 if (ST->hasLZCNT()) {
5388 if (ST->is64Bit())
5389 if (const auto *Entry = CostTableLookup(LZCNT64CostTbl, ISD, MTy))
5390 if (auto KindCost = Entry->Cost[CostKind])
5391 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5392
5393 if (const auto *Entry = CostTableLookup(LZCNT32CostTbl, ISD, MTy))
5394 if (auto KindCost = Entry->Cost[CostKind])
5395 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5396 }
5397
5398 if (ST->hasPOPCNT()) {
5399 if (ST->is64Bit())
5400 if (const auto *Entry = CostTableLookup(POPCNT64CostTbl, ISD, MTy))
5401 if (auto KindCost = Entry->Cost[CostKind])
5402 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5403
5404 if (const auto *Entry = CostTableLookup(POPCNT32CostTbl, ISD, MTy))
5405 if (auto KindCost = Entry->Cost[CostKind])
5406 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5407 }
5408
5409 // FIXME: PCLMUL w/ AVX/AVX512 and VPCLMULQDQ are not handled properly.
5410 if (ST->hasPCLMUL())
5411 if (const auto *Entry = CostTableLookup(PCLMULCostTbl, ISD, MTy))
5412 if (auto KindCost = Entry->Cost[CostKind])
5413 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5414
5415 if (ST->is64Bit())
5416 if (const auto *Entry = CostTableLookup(X64CostTbl, ISD, MTy))
5417 if (auto KindCost = Entry->Cost[CostKind])
5418 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5419
5420 if (const auto *Entry = CostTableLookup(X86CostTbl, ISD, MTy))
5421 if (auto KindCost = Entry->Cost[CostKind])
5422 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5423
5424 // Without arg data, we need to compute the expanded costs of custom lowered
5425 // intrinsics to prevent use of the (very low) default costs.
5426 if (ICA.isTypeBasedOnly() &&
5427 (IID == Intrinsic::fshl || IID == Intrinsic::fshr)) {
5428 Type *CondTy = RetTy->getWithNewBitWidth(1);
5430 Cost += getArithmeticInstrCost(BinaryOperator::Or, RetTy, CostKind);
5431 Cost += getArithmeticInstrCost(BinaryOperator::Sub, RetTy, CostKind);
5432 Cost += getArithmeticInstrCost(BinaryOperator::Shl, RetTy, CostKind);
5433 Cost += getArithmeticInstrCost(BinaryOperator::LShr, RetTy, CostKind);
5434 Cost += getArithmeticInstrCost(BinaryOperator::And, RetTy, CostKind);
5435 Cost += getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy,
5436 CmpInst::ICMP_EQ, CostKind);
5437 Cost += getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy,
5438 CmpInst::ICMP_EQ, CostKind);
5439 return Cost;
5440 }
5441 }
5442
5443 return BaseT::getIntrinsicInstrCost(ICA, CostKind);
5444}
5445
5447 unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,
5448 const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC) const {
5449 static const CostTblEntry SLMCostTbl[] = {
5450 { ISD::EXTRACT_VECTOR_ELT, MVT::i8, 4 },
5451 { ISD::EXTRACT_VECTOR_ELT, MVT::i16, 4 },
5452 { ISD::EXTRACT_VECTOR_ELT, MVT::i32, 4 },
5453 { ISD::EXTRACT_VECTOR_ELT, MVT::i64, 7 }
5454 };
5455
5456 assert(Val->isVectorTy() && "This must be a vector type");
5457 auto *VT = cast<VectorType>(Val);
5458 if (VT->isScalableTy())
5460
5461 Type *ScalarType = Val->getScalarType();
5462 InstructionCost RegisterFileMoveCost = 0;
5463
5464 // Non-immediate extraction/insertion can be handled as a sequence of
5465 // aliased loads+stores via the stack.
5466 if (Index == -1U && (Opcode == Instruction::ExtractElement ||
5467 Opcode == Instruction::InsertElement)) {
5468 // TODO: On some SSE41+ targets, we expand to cmp+splat+select patterns:
5469 // inselt N0, N1, N2 --> select (SplatN2 == {0,1,2...}) ? SplatN1 : N0.
5470
5471 // TODO: Move this to BasicTTIImpl.h? We'd need better gep + index handling.
5472 assert(isa<FixedVectorType>(Val) && "Fixed vector type expected");
5473 Align VecAlign = DL.getPrefTypeAlign(Val);
5474 Align SclAlign = DL.getPrefTypeAlign(ScalarType);
5475
5476 // Extract - store vector to stack, load scalar.
5477 if (Opcode == Instruction::ExtractElement) {
5478 return getMemoryOpCost(Instruction::Store, Val, VecAlign, 0, CostKind) +
5479 getMemoryOpCost(Instruction::Load, ScalarType, SclAlign, 0,
5480 CostKind);
5481 }
5482 // Insert - store vector to stack, store scalar, load vector.
5483 if (Opcode == Instruction::InsertElement) {
5484 return getMemoryOpCost(Instruction::Store, Val, VecAlign, 0, CostKind) +
5485 getMemoryOpCost(Instruction::Store, ScalarType, SclAlign, 0,
5486 CostKind) +
5487 getMemoryOpCost(Instruction::Load, Val, VecAlign, 0, CostKind);
5488 }
5489 }
5490
5491 if (Index != -1U && (Opcode == Instruction::ExtractElement ||
5492 Opcode == Instruction::InsertElement)) {
5493 // Extraction of vXi1 elements are now efficiently handled by MOVMSK.
5494 if (Opcode == Instruction::ExtractElement &&
5495 ScalarType->getScalarSizeInBits() == 1 &&
5496 cast<FixedVectorType>(Val)->getNumElements() > 1)
5497 return 1;
5498
5499 // Legalize the type.
5500 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Val);
5501
5502 // This type is legalized to a scalar type.
5503 if (!LT.second.isVector())
5504 return TTI::TCC_Free;
5505
5506 // The type may be split. Normalize the index to the new type.
5507 unsigned SizeInBits = LT.second.getSizeInBits();
5508 unsigned NumElts = LT.second.getVectorNumElements();
5509 unsigned SubNumElts = NumElts;
5510 Index = Index % NumElts;
5511
5512 // For >128-bit vectors, we need to extract higher 128-bit subvectors.
5513 // For inserts, we also need to insert the subvector back.
5514 if (SizeInBits > 128) {
5515 assert((SizeInBits % 128) == 0 && "Illegal vector");
5516 unsigned NumSubVecs = SizeInBits / 128;
5517 SubNumElts = NumElts / NumSubVecs;
5518 if (SubNumElts <= Index) {
5519 RegisterFileMoveCost += (Opcode == Instruction::InsertElement ? 2 : 1);
5520 Index %= SubNumElts;
5521 }
5522 }
5523
5524 MVT MScalarTy = LT.second.getScalarType();
5525 auto IsCheapPInsrPExtrInsertPS = [&]() {
5526 // Assume pinsr/pextr XMM <-> GPR is relatively cheap on all targets.
5527 // Inserting f32 into index0 is just movss.
5528 // Also, assume insertps is relatively cheap on all >= SSE41 targets.
5529 return (MScalarTy == MVT::i16 && ST->hasSSE2()) ||
5530 (MScalarTy.isInteger() && ST->hasSSE41()) ||
5531 (MScalarTy == MVT::f32 && ST->hasSSE1() && Index == 0 &&
5532 Opcode == Instruction::InsertElement) ||
5533 (MScalarTy == MVT::f32 && ST->hasSSE41() &&
5534 Opcode == Instruction::InsertElement);
5535 };
5536
5537 if (Index == 0) {
5538 // Floating point scalars are already located in index #0.
5539 // Many insertions to #0 can fold away for scalar fp-ops, so let's assume
5540 // true for all.
5541 if (ScalarType->isFloatingPointTy() &&
5542 (Opcode != Instruction::InsertElement || !Op0 ||
5543 isa<UndefValue>(Op0)))
5544 return RegisterFileMoveCost;
5545
5546 if (Opcode == Instruction::InsertElement &&
5548 // Consider the gather cost to be cheap.
5550 return RegisterFileMoveCost;
5551 if (!IsCheapPInsrPExtrInsertPS()) {
5552 // mov constant-to-GPR + movd/movq GPR -> XMM.
5553 if (isa_and_nonnull<Constant>(Op1) && Op1->getType()->isIntegerTy())
5554 return 2 + RegisterFileMoveCost;
5555 // Assume movd/movq GPR -> XMM is relatively cheap on all targets.
5556 return 1 + RegisterFileMoveCost;
5557 }
5558 }
5559
5560 // Assume movd/movq XMM -> GPR is relatively cheap on all targets.
5561 if (ScalarType->isIntegerTy() && Opcode == Instruction::ExtractElement)
5562 return 1 + RegisterFileMoveCost;
5563 }
5564
5565 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5566 assert(ISD && "Unexpected vector opcode");
5567 if (ST->useSLMArithCosts())
5568 if (auto *Entry = CostTableLookup(SLMCostTbl, ISD, MScalarTy))
5569 return Entry->Cost + RegisterFileMoveCost;
5570
5571 // Consider cheap cases.
5572 if (IsCheapPInsrPExtrInsertPS())
5573 return 1 + RegisterFileMoveCost;
5574
5575 // For extractions we just need to shuffle the element to index 0, which
5576 // should be very cheap (assume cost = 1). For insertions we need to shuffle
5577 // the elements to its destination. In both cases we must handle the
5578 // subvector move(s).
5579 // If the vector type is already less than 128-bits then don't reduce it.
5580 // TODO: Under what circumstances should we shuffle using the full width?
5581 InstructionCost ShuffleCost = 1;
5582 if (Opcode == Instruction::InsertElement) {
5583 auto *SubTy = cast<VectorType>(Val);
5584 EVT VT = TLI->getValueType(DL, Val);
5585 if (VT.getScalarType() != MScalarTy || VT.getSizeInBits() >= 128)
5586 SubTy = FixedVectorType::get(ScalarType, SubNumElts);
5587 ShuffleCost = getShuffleCost(TTI::SK_PermuteTwoSrc, SubTy, SubTy,
5588 CostKind, {}, 0, SubTy);
5589 }
5590 int IntOrFpCost = ScalarType->isFloatingPointTy() ? 0 : 1;
5591 return ShuffleCost + IntOrFpCost + RegisterFileMoveCost;
5592 }
5593
5594 return BaseT::getVectorInstrCost(Opcode, Val, CostKind, Index, Op0, Op1,
5595 VIC) +
5596 RegisterFileMoveCost;
5597}
5598
5600 VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract,
5601 TTI::TargetCostKind CostKind, bool ForPoisonSrc, ArrayRef<Value *> VL,
5602 TTI::VectorInstrContext VIC) const {
5603 assert(DemandedElts.getBitWidth() ==
5604 cast<FixedVectorType>(Ty)->getNumElements() &&
5605 "Vector size mismatch");
5606
5607 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
5608 MVT MScalarTy = LT.second.getScalarType();
5609 unsigned LegalVectorBitWidth = LT.second.getSizeInBits();
5611 // The square roots, folded with the divisions into the estimate, are
5612 // computed separately to be inserted.
5613 if (Insert && !VL.empty())
5614 for (unsigned I : seq(DemandedElts.getBitWidth()))
5615 if (DemandedElts[I] &&
5616 isFoldedIntoRsqrtEstimate(VL[I], *TLI, MScalarTy, CostKind))
5618 IntrinsicCostAttributes(Intrinsic::sqrt, VL[I]->getType(),
5619 {VL[I]->getType()}),
5620 CostKind);
5621
5622 constexpr unsigned LaneBitWidth = 128;
5623 assert((LegalVectorBitWidth < LaneBitWidth ||
5624 (LegalVectorBitWidth % LaneBitWidth) == 0) &&
5625 "Illegal vector");
5626
5627 const int NumLegalVectors = LT.first.getValue();
5628 assert(NumLegalVectors >= 0 && "Negative cost!");
5629
5630 // For insertions, a ISD::BUILD_VECTOR style vector initialization can be much
5631 // cheaper than an accumulation of ISD::INSERT_VECTOR_ELT. SLPVectorizer has
5632 // a special heuristic regarding poison input which is passed here in
5633 // ForPoisonSrc.
5634 if (Insert && !ForPoisonSrc) {
5635 // This is nearly identical to BaseT::getScalarizationOverhead(), except
5636 // it is passing nullptr to getVectorInstrCost() for Op0 (instead of
5637 // Constant::getNullValue()), which makes the X86TTIImpl
5638 // getVectorInstrCost() return 0 instead of 1.
5639 for (unsigned I : seq(DemandedElts.getBitWidth())) {
5640 if (!DemandedElts[I])
5641 continue;
5642 Cost += getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, I,
5644 VL.empty() ? nullptr : VL[I],
5646 }
5647 return Cost;
5648 }
5649
5650 if (Insert) {
5651 if ((MScalarTy == MVT::i16 && ST->hasSSE2()) ||
5652 (MScalarTy.isInteger() && ST->hasSSE41()) ||
5653 (MScalarTy == MVT::f32 && ST->hasSSE41())) {
5654 // For types we can insert directly, insertion into 128-bit sub vectors is
5655 // cheap, followed by a cheap chain of concatenations.
5656 if (LegalVectorBitWidth <= LaneBitWidth) {
5657 Cost += BaseT::getScalarizationOverhead(Ty, DemandedElts, Insert,
5658 /*Extract*/ false, CostKind);
5659 } else {
5660 // In each 128-lane, if at least one index is demanded but not all
5661 // indices are demanded and this 128-lane is not the first 128-lane of
5662 // the legalized-vector, then this 128-lane needs a extracti128; If in
5663 // each 128-lane, there is at least one demanded index, this 128-lane
5664 // needs a inserti128.
5665
5666 // The following cases will help you build a better understanding:
5667 // Assume we insert several elements into a v8i32 vector in avx2,
5668 // Case#1: inserting into 1th index needs vpinsrd + inserti128.
5669 // Case#2: inserting into 5th index needs extracti128 + vpinsrd +
5670 // inserti128.
5671 // Case#3: inserting into 4,5,6,7 index needs 4*vpinsrd + inserti128.
5672 assert((LegalVectorBitWidth % LaneBitWidth) == 0 && "Illegal vector");
5673 unsigned NumLegalLanes = LegalVectorBitWidth / LaneBitWidth;
5674 unsigned NumLanesTotal = NumLegalLanes * NumLegalVectors;
5675 unsigned NumLegalElts =
5676 LT.second.getVectorNumElements() * NumLegalVectors;
5677 assert(NumLegalElts >= DemandedElts.getBitWidth() &&
5678 "Vector has been legalized to smaller element count");
5679 assert((NumLegalElts % NumLanesTotal) == 0 &&
5680 "Unexpected elts per lane");
5681 unsigned NumEltsPerLane = NumLegalElts / NumLanesTotal;
5682
5683 APInt WidenedDemandedElts = DemandedElts.zext(NumLegalElts);
5684 auto *LaneTy =
5685 FixedVectorType::get(Ty->getElementType(), NumEltsPerLane);
5686
5687 for (unsigned I = 0; I != NumLanesTotal; ++I) {
5688 APInt LaneEltMask = WidenedDemandedElts.extractBits(
5689 NumEltsPerLane, NumEltsPerLane * I);
5690 if (LaneEltMask.isZero())
5691 continue;
5692 // FIXME: we don't need to extract if all non-demanded elements
5693 // are legalization-inserted padding.
5694 if (!LaneEltMask.isAllOnes())
5695 Cost += getShuffleCost(TTI::SK_ExtractSubvector, Ty, Ty, CostKind,
5696 {}, I * NumEltsPerLane, LaneTy);
5697 Cost += BaseT::getScalarizationOverhead(LaneTy, LaneEltMask, Insert,
5698 /*Extract*/ false, CostKind);
5699 }
5700
5701 APInt AffectedLanes =
5702 APIntOps::ScaleBitMask(WidenedDemandedElts, NumLanesTotal);
5703 APInt FullyAffectedLegalVectors = APIntOps::ScaleBitMask(
5704 AffectedLanes, NumLegalVectors, /*MatchAllBits=*/true);
5705 for (int LegalVec = 0; LegalVec != NumLegalVectors; ++LegalVec) {
5706 for (unsigned Lane = 0; Lane != NumLegalLanes; ++Lane) {
5707 unsigned I = NumLegalLanes * LegalVec + Lane;
5708 // No need to insert unaffected lane; or lane 0 of each legal vector
5709 // iff ALL lanes of that vector were affected and will be inserted.
5710 if (!AffectedLanes[I] ||
5711 (Lane == 0 && FullyAffectedLegalVectors[LegalVec]))
5712 continue;
5713 Cost += getShuffleCost(TTI::SK_InsertSubvector, Ty, Ty, CostKind,
5714 {}, I * NumEltsPerLane, LaneTy);
5715 }
5716 }
5717 }
5718 } else if (LT.second.isVector()) {
5719 // Without fast insertion, we need to use MOVD/MOVQ to pass each demanded
5720 // integer element as a SCALAR_TO_VECTOR, then we build the vector as a
5721 // series of UNPCK followed by CONCAT_VECTORS - all of these can be
5722 // considered cheap.
5723 if (Ty->isIntOrIntVectorTy())
5724 Cost += DemandedElts.popcount();
5725
5726 // Get the smaller of the legalized or original pow2-extended number of
5727 // vector elements, which represents the number of unpacks we'll end up
5728 // performing.
5729 unsigned NumElts = LT.second.getVectorNumElements();
5730 unsigned Pow2Elts =
5731 PowerOf2Ceil(cast<FixedVectorType>(Ty)->getNumElements());
5732 Cost += (std::min<unsigned>(NumElts, Pow2Elts) - 1) * LT.first;
5733 }
5734 }
5735
5736 if (Extract) {
5737 // vXi1 can be efficiently extracted with MOVMSK.
5738 // TODO: AVX512 predicate mask handling.
5739 // NOTE: This doesn't work well for roundtrip scalarization.
5740 if (!Insert && Ty->getScalarSizeInBits() == 1 && !ST->hasAVX512()) {
5741 unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
5742 unsigned MaxElts = ST->hasAVX2() ? 32 : 16;
5743 unsigned MOVMSKCost = (NumElts + MaxElts - 1) / MaxElts;
5744 return MOVMSKCost;
5745 }
5746
5747 if (LT.second.isVector()) {
5748 unsigned NumLegalElts =
5749 LT.second.getVectorNumElements() * NumLegalVectors;
5750 assert(NumLegalElts >= DemandedElts.getBitWidth() &&
5751 "Vector has been legalized to smaller element count");
5752
5753 // If we're extracting elements from a 128-bit subvector lane,
5754 // we only need to extract each lane once, not for every element.
5755 if (LegalVectorBitWidth > LaneBitWidth) {
5756 unsigned NumLegalLanes = LegalVectorBitWidth / LaneBitWidth;
5757 unsigned NumLanesTotal = NumLegalLanes * NumLegalVectors;
5758 assert((NumLegalElts % NumLanesTotal) == 0 &&
5759 "Unexpected elts per lane");
5760 unsigned NumEltsPerLane = NumLegalElts / NumLanesTotal;
5761
5762 // Add cost for each demanded 128-bit subvector extraction.
5763 // Luckily this is a lot easier than for insertion.
5764 APInt WidenedDemandedElts = DemandedElts.zext(NumLegalElts);
5765 auto *LaneTy =
5766 FixedVectorType::get(Ty->getElementType(), NumEltsPerLane);
5767
5768 for (unsigned I = 0; I != NumLanesTotal; ++I) {
5769 APInt LaneEltMask = WidenedDemandedElts.extractBits(
5770 NumEltsPerLane, I * NumEltsPerLane);
5771 if (LaneEltMask.isZero())
5772 continue;
5773 Cost += getShuffleCost(TTI::SK_ExtractSubvector, Ty, Ty, CostKind, {},
5774 I * NumEltsPerLane, LaneTy);
5776 LaneTy, LaneEltMask, /*Insert*/ false, Extract, CostKind);
5777 }
5778
5779 return Cost;
5780 }
5781 }
5782
5783 // Fallback to default extraction.
5784 Cost += BaseT::getScalarizationOverhead(Ty, DemandedElts, /*Insert*/ false,
5785 Extract, CostKind);
5786 }
5787
5788 return Cost;
5789}
5790
5792X86TTIImpl::getReplicationShuffleCost(Type *EltTy, int ReplicationFactor,
5793 int VF, const APInt &DemandedDstElts,
5794 TTI::TargetCostKind CostKind) const {
5795 const unsigned EltTyBits = DL.getTypeSizeInBits(EltTy);
5796 // We don't differentiate element types here, only element bit width.
5797 EltTy = IntegerType::getIntNTy(EltTy->getContext(), EltTyBits);
5798
5799 auto bailout = [&]() {
5800 return BaseT::getReplicationShuffleCost(EltTy, ReplicationFactor, VF,
5801 DemandedDstElts, CostKind);
5802 };
5803
5804 // For now, only deal with AVX512 cases.
5805 if (!ST->hasAVX512())
5806 return bailout();
5807
5808 // Do we have a native shuffle for this element type, or should we promote?
5809 unsigned PromEltTyBits = EltTyBits;
5810 switch (EltTyBits) {
5811 case 32:
5812 case 64:
5813 break; // AVX512F.
5814 case 16:
5815 if (!ST->hasBWI())
5816 PromEltTyBits = 32; // promote to i32, AVX512F.
5817 break; // AVX512BW
5818 case 8:
5819 if (!ST->hasVBMI())
5820 PromEltTyBits = 32; // promote to i32, AVX512F.
5821 break; // AVX512VBMI
5822 case 1:
5823 // There is no support for shuffling i1 elements. We *must* promote.
5824 if (ST->hasBWI()) {
5825 if (ST->hasVBMI())
5826 PromEltTyBits = 8; // promote to i8, AVX512VBMI.
5827 else
5828 PromEltTyBits = 16; // promote to i16, AVX512BW.
5829 break;
5830 }
5831 PromEltTyBits = 32; // promote to i32, AVX512F.
5832 break;
5833 default:
5834 return bailout();
5835 }
5836 auto *PromEltTy = IntegerType::getIntNTy(EltTy->getContext(), PromEltTyBits);
5837
5838 auto *SrcVecTy = FixedVectorType::get(EltTy, VF);
5839 auto *PromSrcVecTy = FixedVectorType::get(PromEltTy, VF);
5840
5841 int NumDstElements = VF * ReplicationFactor;
5842 auto *PromDstVecTy = FixedVectorType::get(PromEltTy, NumDstElements);
5843 auto *DstVecTy = FixedVectorType::get(EltTy, NumDstElements);
5844
5845 // Legalize the types.
5846 MVT LegalSrcVecTy = getTypeLegalizationCost(SrcVecTy).second;
5847 MVT LegalPromSrcVecTy = getTypeLegalizationCost(PromSrcVecTy).second;
5848 MVT LegalPromDstVecTy = getTypeLegalizationCost(PromDstVecTy).second;
5849 MVT LegalDstVecTy = getTypeLegalizationCost(DstVecTy).second;
5850 // They should have legalized into vector types.
5851 if (!LegalSrcVecTy.isVector() || !LegalPromSrcVecTy.isVector() ||
5852 !LegalPromDstVecTy.isVector() || !LegalDstVecTy.isVector())
5853 return bailout();
5854
5855 if (PromEltTyBits != EltTyBits) {
5856 // If we have to perform the shuffle with wider elt type than our data type,
5857 // then we will first need to anyext (we don't care about the new bits)
5858 // the source elements, and then truncate Dst elements.
5859 InstructionCost PromotionCost;
5860 PromotionCost += getCastInstrCost(
5861 Instruction::SExt, /*Dst=*/PromSrcVecTy, /*Src=*/SrcVecTy,
5863 PromotionCost +=
5864 getCastInstrCost(Instruction::Trunc, /*Dst=*/DstVecTy,
5865 /*Src=*/PromDstVecTy,
5867 return PromotionCost + getReplicationShuffleCost(PromEltTy,
5868 ReplicationFactor, VF,
5869 DemandedDstElts, CostKind);
5870 }
5871
5872 assert(LegalSrcVecTy.getScalarSizeInBits() == EltTyBits &&
5873 LegalSrcVecTy.getScalarType() == LegalDstVecTy.getScalarType() &&
5874 "We expect that the legalization doesn't affect the element width, "
5875 "doesn't coalesce/split elements.");
5876
5877 unsigned NumEltsPerDstVec = LegalDstVecTy.getVectorNumElements();
5878 unsigned NumDstVectors =
5879 divideCeil(DstVecTy->getNumElements(), NumEltsPerDstVec);
5880
5881 auto *SingleDstVecTy = FixedVectorType::get(EltTy, NumEltsPerDstVec);
5882
5883 // Not all the produced Dst elements may be demanded. In our case,
5884 // given that a single Dst vector is formed by a single shuffle,
5885 // if all elements that will form a single Dst vector aren't demanded,
5886 // then we won't need to do that shuffle, so adjust the cost accordingly.
5887 APInt DemandedDstVectors = APIntOps::ScaleBitMask(
5888 DemandedDstElts.zext(NumDstVectors * NumEltsPerDstVec), NumDstVectors);
5889 unsigned NumDstVectorsDemanded = DemandedDstVectors.popcount();
5890
5891 InstructionCost SingleShuffleCost =
5892 getShuffleCost(TTI::SK_PermuteSingleSrc, SingleDstVecTy, SingleDstVecTy,
5893 CostKind, /*Mask=*/{},
5894 /*Index=*/0, /*SubTp=*/nullptr);
5895 return NumDstVectorsDemanded * SingleShuffleCost;
5896}
5897
5899 Align Alignment,
5900 unsigned AddressSpace,
5901 TTI::TargetCostKind CostKind,
5902 TTI::OperandValueInfo OpInfo,
5903 const Instruction *I) const {
5904 // FIXME: Load latency isn't handled here
5905 if (Opcode == Instruction::Load && CostKind == TTI::TCK_Latency)
5906 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
5907 CostKind, OpInfo, I);
5908
5909 // TODO: Handle other cost kinds.
5910 if (CostKind != TTI::TCK_RecipThroughput) {
5911 if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {
5912 // Store instruction with index and scale costs 2 Uops.
5913 // Check the preceding GEP to identify non-const indices.
5914 if (auto *GEP = dyn_cast<GetElementPtrInst>(SI->getPointerOperand())) {
5915 if (!all_of(GEP->indices(), [](Value *V) { return isa<Constant>(V); }))
5916 return TTI::TCC_Basic * 2;
5917 }
5918 }
5919 return TTI::TCC_Basic;
5920 }
5921
5922 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5923 "Invalid Opcode");
5924 // Type legalization can't handle structs
5925 if (TLI->getValueType(DL, Src, true) == MVT::Other)
5926 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
5927 CostKind, OpInfo, I);
5928
5929 // Legalize the type.
5930 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Src);
5931
5932 auto *VTy = dyn_cast<FixedVectorType>(Src);
5933
5935
5936 // Add a cost for constant load to vector.
5937 if (Opcode == Instruction::Store && OpInfo.isConstant())
5938 Cost += getMemoryOpCost(Instruction::Load, Src, DL.getABITypeAlign(Src),
5939 /*AddressSpace=*/0, CostKind, OpInfo);
5940
5941 // Handle the simple case of non-vectors.
5942 // NOTE: this assumes that legalization never creates vector from scalars!
5943 if (!VTy || !LT.second.isVector()) {
5944 // Each load/store unit costs 1.
5945 return (LT.second.isFloatingPoint() ? Cost : 0) + LT.first * 1;
5946 }
5947
5948 bool IsLoad = Opcode == Instruction::Load;
5949
5950 Type *EltTy = VTy->getElementType();
5951
5952 const int EltTyBits = DL.getTypeSizeInBits(EltTy);
5953
5954 // Source of truth: how many elements were there in the original IR vector?
5955 const unsigned SrcNumElt = VTy->getNumElements();
5956
5957 // How far have we gotten?
5958 int NumEltRemaining = SrcNumElt;
5959 // Note that we intentionally capture by-reference, NumEltRemaining changes.
5960 auto NumEltDone = [&]() { return SrcNumElt - NumEltRemaining; };
5961
5962 const int MaxLegalOpSizeBytes = divideCeil(LT.second.getSizeInBits(), 8);
5963
5964 // Note that even if we can store 64 bits of an XMM, we still operate on XMM.
5965 const unsigned XMMBits = 128;
5966 if (XMMBits % EltTyBits != 0)
5967 // Vector size must be a multiple of the element size. I.e. no padding.
5968 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
5969 CostKind, OpInfo, I);
5970 const int NumEltPerXMM = XMMBits / EltTyBits;
5971
5972 auto *XMMVecTy = FixedVectorType::get(EltTy, NumEltPerXMM);
5973
5974 for (int CurrOpSizeBytes = MaxLegalOpSizeBytes, SubVecEltsLeft = 0;
5975 NumEltRemaining > 0; CurrOpSizeBytes /= 2) {
5976 // How many elements would a single op deal with at once?
5977 if ((8 * CurrOpSizeBytes) % EltTyBits != 0)
5978 // Vector size must be a multiple of the element size. I.e. no padding.
5979 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
5980 CostKind, OpInfo, I);
5981 int CurrNumEltPerOp = (8 * CurrOpSizeBytes) / EltTyBits;
5982
5983 assert(CurrOpSizeBytes > 0 && CurrNumEltPerOp > 0 && "How'd we get here?");
5984 assert((((NumEltRemaining * EltTyBits) < (2 * 8 * CurrOpSizeBytes)) ||
5985 (CurrOpSizeBytes == MaxLegalOpSizeBytes)) &&
5986 "Unless we haven't halved the op size yet, "
5987 "we have less than two op's sized units of work left.");
5988
5989 auto *CurrVecTy = CurrNumEltPerOp > NumEltPerXMM
5990 ? FixedVectorType::get(EltTy, CurrNumEltPerOp)
5991 : XMMVecTy;
5992
5993 assert(CurrVecTy->getNumElements() % CurrNumEltPerOp == 0 &&
5994 "After halving sizes, the vector elt count is no longer a multiple "
5995 "of number of elements per operation?");
5996 auto *CoalescedVecTy =
5997 CurrNumEltPerOp == 1
5998 ? CurrVecTy
6000 IntegerType::get(Src->getContext(),
6001 EltTyBits * CurrNumEltPerOp),
6002 CurrVecTy->getNumElements() / CurrNumEltPerOp);
6003 assert(DL.getTypeSizeInBits(CoalescedVecTy) ==
6004 DL.getTypeSizeInBits(CurrVecTy) &&
6005 "coalesciing elements doesn't change vector width.");
6006
6007 while (NumEltRemaining > 0) {
6008 assert(SubVecEltsLeft >= 0 && "Subreg element count overconsumtion?");
6009
6010 // Can we use this vector size, as per the remaining element count?
6011 // Iff the vector is naturally aligned, we can do a wide load regardless.
6012 if (NumEltRemaining < CurrNumEltPerOp &&
6013 (!IsLoad || Alignment < CurrOpSizeBytes) && CurrOpSizeBytes != 1)
6014 break; // Try smalled vector size.
6015
6016 // This isn't exactly right. We're using slow unaligned 32-byte accesses
6017 // as a proxy for a double-pumped AVX memory interface such as on
6018 // Sandybridge.
6019 // Sub-32-bit loads/stores will be slower either with PINSR*/PEXTR* or
6020 // will be scalarized.
6021 //
6022 // For a vector load, each non-0th 1/2/4-byte in-lane remainder chunk is
6023 // materialized by a *single* folded PINSR*(mem) that both loads and
6024 // inserts the lane (1B->PINSRB, 2B->PINSRW, 4B->PINSRD; the byte and
6025 // dword folds need SSE4.1, the word fold only SSE2).
6026 // When that fold is available the chunk is one instruction, so it must be
6027 // priced once here (as a plain load) and the separate lane-insert charge
6028 // below must be skipped - otherwise the folded insert is double-counted.
6029 // Stores (the symmetric PEXTR*(mem) fold) are left unchanged here.
6030 bool Is0thSubVec = (NumEltDone() % LT.second.getVectorNumElements()) == 0;
6031 bool FoldedInLaneInsert = IsLoad && !Is0thSubVec &&
6032 ((CurrOpSizeBytes == 1 && ST->hasSSE41()) ||
6033 (CurrOpSizeBytes == 2 && ST->hasSSE2()) ||
6034 (CurrOpSizeBytes == 4 && ST->hasSSE41()));
6035 if (CurrOpSizeBytes == 32 && ST->isUnalignedMem32Slow())
6036 Cost += 2;
6037 else if (CurrOpSizeBytes < 4 && !FoldedInLaneInsert)
6038 Cost += 2;
6039 else
6040 Cost += 1;
6041
6042 // If we're loading a uniform value, then we don't need to split the load,
6043 // loading just a single (widest) vector can be reused by all splits.
6044 if (IsLoad && OpInfo.isUniform())
6045 return Cost;
6046
6047 // If we have fully processed the previous reg, we need to replenish it.
6048 if (SubVecEltsLeft == 0) {
6049 SubVecEltsLeft += CurrVecTy->getNumElements();
6050 // And that's free only for the 0'th subvector of a legalized vector.
6051 if (!Is0thSubVec)
6052 Cost +=
6055 VTy, VTy, CostKind, {}, NumEltDone(), CurrVecTy);
6056 }
6057
6058 // While we can directly load/store ZMM, YMM, and 64-bit halves of XMM,
6059 // for smaller widths (32/16/8) we have to insert/extract them separately.
6060 // Again, it's free for the 0'th subreg (if op is 32/64 bit wide,
6061 // but let's pretend that it is also true for 16/8 bit wide ops...)
6062 if (CurrOpSizeBytes <= 32 / 8 && !Is0thSubVec && !FoldedInLaneInsert) {
6063 int NumEltDoneInCurrXMM = NumEltDone() % NumEltPerXMM;
6064 assert(NumEltDoneInCurrXMM % CurrNumEltPerOp == 0 && "");
6065 int CoalescedVecEltIdx = NumEltDoneInCurrXMM / CurrNumEltPerOp;
6066 APInt DemandedElts =
6067 APInt::getBitsSet(CoalescedVecTy->getNumElements(),
6068 CoalescedVecEltIdx, CoalescedVecEltIdx + 1);
6069 assert(DemandedElts.popcount() == 1 && "Inserting single value");
6070 Cost += getScalarizationOverhead(CoalescedVecTy, DemandedElts, IsLoad,
6071 !IsLoad, CostKind);
6072 }
6073
6074 SubVecEltsLeft -= CurrNumEltPerOp;
6075 NumEltRemaining -= CurrNumEltPerOp;
6076 Alignment = commonAlignment(Alignment, CurrOpSizeBytes);
6077 }
6078 }
6079
6080 assert(NumEltRemaining <= 0 && "Should have processed all the elements.");
6081
6082 return Cost;
6083}
6084
6087 TTI::TargetCostKind CostKind) const {
6088 switch (MICA.getID()) {
6089 case Intrinsic::masked_scatter:
6090 case Intrinsic::masked_gather:
6091 return getGatherScatterOpCost(MICA, CostKind);
6092 case Intrinsic::masked_load:
6093 case Intrinsic::masked_store:
6094 return getMaskedMemoryOpCost(MICA, CostKind);
6095 case Intrinsic::masked_compressstore:
6096 // Fallback to scalarization for slow compressstore targets (e.g. znver4).
6097 if (ST->isVecCompressStoreSlow())
6098 return BaseT::getMemIntrinsicInstrCost(MICA, CostKind);
6099 break;
6100 }
6101
6102 static const CostKindTblEntry AVX512VBMI2CostTable[] = {
6103 { Intrinsic::masked_expandload, MVT::v16i8, { 2, 7, 1, 3 } },
6104 { Intrinsic::masked_expandload, MVT::v32i8, { 2, 8, 1, 3 } },
6105 { Intrinsic::masked_expandload, MVT::v64i8, { 2, 9, 1, 3 } },
6106
6107 { Intrinsic::masked_expandload, MVT::v8i16, { 2, 7, 1, 3 } },
6108 { Intrinsic::masked_expandload, MVT::v16i16, { 2, 8, 1, 3 } },
6109 { Intrinsic::masked_expandload, MVT::v32i16, { 2, 9, 1, 3 } },
6110
6111 { Intrinsic::masked_compressstore, MVT::v16i8, { 3,10, 1, 7 } },
6112 { Intrinsic::masked_compressstore, MVT::v32i8, { 3,11, 1, 7 } },
6113 { Intrinsic::masked_compressstore, MVT::v64i8, { 3,12, 1, 8 } },
6114
6115 { Intrinsic::masked_compressstore, MVT::v8i16, { 3,10, 1, 7 } },
6116 { Intrinsic::masked_compressstore, MVT::v16i16, { 3,11, 1, 7 } },
6117 { Intrinsic::masked_compressstore, MVT::v32i16, { 3,12, 1, 8 } },
6118 };
6119
6120 static const CostKindTblEntry AVX512CostTable[] = {
6121 { Intrinsic::masked_expandload, MVT::v4i32, { 2, 7, 1, 3 } },
6122 { Intrinsic::masked_expandload, MVT::v4f32, { 2, 7, 1, 3 } },
6123 { Intrinsic::masked_expandload, MVT::v8i32, { 2, 8, 1, 3 } },
6124 { Intrinsic::masked_expandload, MVT::v8f32, { 2, 8, 1, 3 } },
6125 { Intrinsic::masked_expandload, MVT::v16i32, { 2, 9, 1, 3 } },
6126 { Intrinsic::masked_expandload, MVT::v16f32, { 2, 9, 1, 3 } },
6127
6128 { Intrinsic::masked_expandload, MVT::v2i64, { 2, 7, 1, 3 } },
6129 { Intrinsic::masked_expandload, MVT::v2f64, { 2, 7, 1, 3 } },
6130 { Intrinsic::masked_expandload, MVT::v4i64, { 2, 8, 1, 3 } },
6131 { Intrinsic::masked_expandload, MVT::v4f64, { 2, 8, 1, 3 } },
6132 { Intrinsic::masked_expandload, MVT::v8i64, { 2, 9, 1, 3 } },
6133 { Intrinsic::masked_expandload, MVT::v8f64, { 2, 9, 1, 3 } },
6134
6135 { Intrinsic::masked_compressstore, MVT::v4i32, { 3,10, 1, 7 } },
6136 { Intrinsic::masked_compressstore, MVT::v4f32, { 3,10, 1, 7 } },
6137 { Intrinsic::masked_compressstore, MVT::v8i32, { 3,11, 1, 7 } },
6138 { Intrinsic::masked_compressstore, MVT::v8f32, { 3,11, 1, 7 } },
6139 { Intrinsic::masked_compressstore, MVT::v16i32, { 3,12, 1, 8 } },
6140 { Intrinsic::masked_compressstore, MVT::v16f32, { 3,12, 1, 8 } },
6141
6142 { Intrinsic::masked_compressstore, MVT::v2i64, { 3,10, 1, 7 } },
6143 { Intrinsic::masked_compressstore, MVT::v2f64, { 3,10, 1, 7 } },
6144 { Intrinsic::masked_compressstore, MVT::v4i64, { 3,11, 1, 7 } },
6145 { Intrinsic::masked_compressstore, MVT::v4f64, { 3,11, 1, 7 } },
6146 { Intrinsic::masked_compressstore, MVT::v8i64, { 3,12, 1, 8 } },
6147 { Intrinsic::masked_compressstore, MVT::v8f64, { 3,12, 1, 8 } },
6148 };
6149
6150 std::pair<InstructionCost, MVT> LT =
6152
6153 if (ST->hasVBMI2())
6154 if (const auto *Entry =
6155 CostTableLookup(AVX512VBMI2CostTable, MICA.getID(), LT.second))
6156 if (auto KindCost = Entry->Cost[CostKind])
6157 return LT.first * *KindCost;
6158
6159 if (ST->hasAVX512())
6160 if (const auto *Entry =
6161 CostTableLookup(AVX512CostTable, MICA.getID(), LT.second))
6162 if (auto KindCost = Entry->Cost[CostKind])
6163 return LT.first * *KindCost;
6164
6165 return BaseT::getMemIntrinsicInstrCost(MICA, CostKind);
6166}
6167
6170 TTI::TargetCostKind CostKind) const {
6171 unsigned Opcode = MICA.getID() == Intrinsic::masked_load ? Instruction::Load
6172 : Instruction::Store;
6173 Type *SrcTy = MICA.getDataType();
6174 Align Alignment = MICA.getAlignment();
6175 unsigned AddressSpace = MICA.getAddressSpace();
6176
6177 bool IsLoad = (Instruction::Load == Opcode);
6178 bool IsStore = (Instruction::Store == Opcode);
6179
6180 auto *SrcVTy = dyn_cast<FixedVectorType>(SrcTy);
6181 if (!SrcVTy)
6182 // To calculate scalar take the regular cost, without mask
6183 return getMemoryOpCost(Opcode, SrcTy, Alignment, AddressSpace, CostKind);
6184
6185 unsigned NumElem = SrcVTy->getNumElements();
6186 auto *MaskTy =
6187 FixedVectorType::get(Type::getInt8Ty(SrcVTy->getContext()), NumElem);
6188 if ((IsLoad && !isLegalMaskedLoad(SrcVTy, Alignment, AddressSpace)) ||
6189 (IsStore && !isLegalMaskedStore(SrcVTy, Alignment, AddressSpace))) {
6190 // Scalarization
6191 APInt DemandedElts = APInt::getAllOnes(NumElem);
6193 MaskTy, DemandedElts, /*Insert*/ false, /*Extract*/ true, CostKind);
6194 InstructionCost ScalarCompareCost = getCmpSelInstrCost(
6195 Instruction::ICmp, Type::getInt8Ty(SrcVTy->getContext()), nullptr,
6196 CmpInst::BAD_ICMP_PREDICATE, CostKind);
6197 InstructionCost BranchCost = getCFInstrCost(Instruction::CondBr, CostKind);
6198 InstructionCost MaskCmpCost = NumElem * (BranchCost + ScalarCompareCost);
6200 SrcVTy, DemandedElts, IsLoad, IsStore, CostKind);
6201 InstructionCost MemopCost =
6202 NumElem * BaseT::getMemoryOpCost(Opcode, SrcVTy->getScalarType(),
6203 Alignment, AddressSpace, CostKind);
6204 return MemopCost + ValueSplitCost + MaskSplitCost + MaskCmpCost;
6205 }
6206
6207 // Legalize the type.
6208 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(SrcVTy);
6209 auto VT = TLI->getValueType(DL, SrcVTy);
6211 MVT Ty = LT.second;
6212 if (Ty == MVT::i16 || Ty == MVT::i32 || Ty == MVT::i64)
6213 // APX masked load/store for scalar is cheap.
6214 return Cost + LT.first;
6215
6216 if (VT.isSimple() && Ty != VT.getSimpleVT() &&
6217 LT.second.getVectorNumElements() == NumElem)
6218 // Promotion requires extend/truncate for data and a shuffle for mask.
6219 Cost += getShuffleCost(TTI::SK_PermuteTwoSrc, SrcVTy, SrcVTy, CostKind, {},
6220 0, nullptr) +
6221 getShuffleCost(TTI::SK_PermuteTwoSrc, MaskTy, MaskTy, CostKind, {},
6222 0, nullptr);
6223
6224 else if (LT.first * Ty.getVectorNumElements() > NumElem) {
6225 auto *NewMaskTy = FixedVectorType::get(MaskTy->getElementType(),
6226 (unsigned)LT.first.getValue() *
6227 Ty.getVectorNumElements());
6228 // Expanding requires fill mask with zeroes
6229 Cost += getShuffleCost(TTI::SK_InsertSubvector, NewMaskTy, NewMaskTy,
6230 CostKind, {}, 0, MaskTy);
6231 }
6232
6233 // Predicate fanout (see getPredicateFanoutCost): only a variable mask needs
6234 // a per-part sub-mask; a constant mask is folded by codegen and pays nothing.
6235 InstructionCost MaskExpCost = 0;
6236 if (MICA.getVariableMask()) {
6237 auto *MaskVecTy =
6238 FixedVectorType::get(Type::getInt1Ty(SrcVTy->getContext()), NumElem);
6239 MaskExpCost = getPredicateFanoutCost(*this, SrcVTy, MaskVecTy);
6240 }
6241
6242 // Pre-AVX512 - each maskmov load costs 2 + store costs ~8.
6243 if (!ST->hasAVX512())
6244 return Cost + LT.first * (IsLoad ? 2 : 8) + MaskExpCost;
6245
6246 // AVX-512 masked load/store is cheaper.
6247 return Cost + LT.first + MaskExpCost;
6248}
6249
6251 ArrayRef<const Value *> Ptrs, const Value *Base,
6252 const TTI::PointersChainInfo &Info, Type *AccessTy,
6253 const TTI::TargetCostKind CostKind) const {
6254 if (Info.isSameBase() && Info.isKnownStride()) {
6255 // If all the pointers have known stride all the differences are translated
6256 // into constants. X86 memory addressing allows encoding it into
6257 // displacement. So we just need to take the base GEP cost.
6258 if (const auto *BaseGEP = dyn_cast<GetElementPtrInst>(Base)) {
6259 SmallVector<const Value *> Indices(BaseGEP->indices());
6260 return getGEPCost(BaseGEP->getSourceElementType(),
6261 BaseGEP->getPointerOperand(), Indices, CostKind,
6262 nullptr);
6263 }
6264 return TTI::TCC_Free;
6265 }
6266 return BaseT::getPointersChainCost(Ptrs, Base, Info, AccessTy, CostKind);
6267}
6268
6271 const SCEV *Ptr,
6272 TTI::TargetCostKind CostKind) const {
6273 // Address computations in vectorized code with non-consecutive addresses will
6274 // likely result in more instructions compared to scalar code where the
6275 // computation can more often be merged into the index mode. The resulting
6276 // extra micro-ops can significantly decrease throughput.
6277 const unsigned NumVectorInstToHideOverhead = 10;
6278
6279 // Cost modeling of Strided Access Computation is hidden by the indexing
6280 // modes of X86 regardless of the stride value. We dont believe that there
6281 // is a difference between constant strided access in gerenal and constant
6282 // strided value which is less than or equal to 64.
6283 // Even in the case of (loop invariant) stride whose value is not known at
6284 // compile time, the address computation will not incur more than one extra
6285 // ADD instruction.
6286 if (PtrTy->isVectorTy() && SE) {
6288 return 1;
6289 if (!ST->hasAVX2()) {
6290 // TODO: AVX2 is the current cut-off because we don't have correct
6291 // interleaving costs for prior ISA's.
6292 if (!BaseT::isStridedAccess(Ptr))
6293 return NumVectorInstToHideOverhead;
6294 }
6295 }
6296
6297 return BaseT::getAddressComputationCost(PtrTy, SE, Ptr, CostKind);
6298}
6299
6301 unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,
6303 TTI::PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp,
6304 TTI::TargetCostKind CostKind, std::optional<FastMathFlags> FMF) const {
6305 auto ExpandCost = [&]() {
6306 return BaseT::getPartialReductionCost(Opcode, InputTypeA, InputTypeB,
6307 AccumType, VF, OpAExtend, OpBExtend,
6308 BinOp, CostKind, FMF);
6309 };
6310
6311 // The dot product instructions multiply-accumulate i8 x i8 -> i32,
6312 // i16 x i16 -> i32, bf16 x bf16 -> f32 or f16 x f16 -> f32. Partial
6313 // reductions may also multiply inputs extended from different types, which
6314 // they can't handle.
6315 if (VF.isScalable() || !BinOp || OpAExtend == TTI::PR_None ||
6316 OpBExtend == TTI::PR_None || InputTypeA != InputTypeB)
6317 return ExpandCost();
6318
6319 unsigned Opc;
6320 if (Opcode == Instruction::Add && *BinOp == Instruction::Mul &&
6321 AccumType->isIntegerTy(32) &&
6322 (InputTypeA->isIntegerTy(8) || InputTypeA->isIntegerTy(16))) {
6323 if (OpAExtend != OpBExtend)
6325 else if (OpAExtend == TTI::PR_SignExtend)
6327 else
6329 } else if (Opcode == Instruction::FAdd && *BinOp == Instruction::FMul &&
6330 AccumType->isFloatTy() &&
6331 (InputTypeA->isBFloatTy() || InputTypeA->isHalfTy())) {
6332 // VDPBF16PS and VDPPHPS, like the expansion, reassociate the additions and
6333 // fuse the multiplications.
6334 if (!FMF || !FMF->allowReassoc() || !FMF->allowContract())
6337 } else {
6338 return ExpandCost();
6339 }
6340
6341 unsigned Ratio =
6342 AccumType->getScalarSizeInBits() / InputTypeA->getScalarSizeInBits();
6343 if (!VF.isKnownMultipleOf(Ratio))
6344 return ExpandCost();
6345
6346 // One dot product per legal accumulator vector. Accumulators narrower than
6347 // a legal vector are widened by expanding the partial reduction instead.
6348 auto *AccVecTy = VectorType::get(AccumType, VF.divideCoefficientBy(Ratio));
6349 auto *InputVecTy = VectorType::get(InputTypeA, VF);
6350 std::pair<InstructionCost, MVT> AccLT = getTypeLegalizationCost(AccVecTy);
6351 std::pair<InstructionCost, MVT> InputLT = getTypeLegalizationCost(InputVecTy);
6352 if (AccLT.second.getFixedSizeInBits() >
6353 AccVecTy->getPrimitiveSizeInBits().getFixedValue() ||
6354 !TLI->isPartialReduceMLALegalOrCustom(Opc, AccLT.second, InputLT.second))
6355 return ExpandCost();
6356
6357 return AccLT.first;
6358}
6359
6362 std::optional<FastMathFlags> FMF,
6363 TTI::TargetCostKind CostKind) const {
6365 return BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);
6366
6367 // We use llvm-mca across all supported CPUs to measure the logic cost stats.
6368 // We use the Intel Architecture Code Analyzer(IACA) to measure the throughput
6369 // and make it as the cost. TODO: Update old IACA numbers to llvm-mca.
6370
6371 static const CostKindTblEntry SLMCostTbl[] = {
6372 { ISD::FADD, MVT::v2f64, {3, 3, 3, 3} },
6373 { ISD::ADD, MVT::v2i64, {5, 5, 5, 5} },
6374 };
6375
6376 static const CostKindTblEntry SSE2CostTbl[] = {
6377 { ISD::FADD, MVT::v2f64, {2, 2, 2, 2} },
6378 { ISD::FADD, MVT::v2f32, {2, 2, 2, 2} },
6379 { ISD::FADD, MVT::v4f32, {4, 4, 4, 4} },
6380 { ISD::ADD, MVT::v2i64, {2, 2, 2, 2} }, // The data reported by the IACA tool is "1.6".
6381 { ISD::ADD, MVT::v2i32, {2, 2, 2, 2} }, // FIXME: chosen to be less than v4i32
6382 { ISD::ADD, MVT::v4i32, {3, 3, 3, 3} }, // The data reported by the IACA tool is "3.3".
6383 { ISD::ADD, MVT::v2i16, {2, 2, 2, 2} }, // The data reported by the IACA tool is "4.3".
6384 { ISD::ADD, MVT::v4i16, {3, 3, 3, 3} }, // The data reported by the IACA tool is "4.3".
6385 { ISD::ADD, MVT::v8i16, {4, 4, 4, 4} }, // The data reported by the IACA tool is "4.3".
6386 { ISD::ADD, MVT::v2i8, {2, 2, 2, 2} },
6387 { ISD::ADD, MVT::v4i8, {2, 2, 2, 2} },
6388 { ISD::ADD, MVT::v8i8, {2, 2, 2, 2} },
6389 { ISD::ADD, MVT::v16i8, {3, 3, 3, 3} },
6390
6391 { ISD::AND, MVT::v2i64, {2, 2, 3, 3} },
6392 { ISD::AND, MVT::v4i32, {3, 4, 5, 5} },
6393 { ISD::AND, MVT::v8i16, {4, 7, 8, 8} },
6394 { ISD::AND, MVT::v16i8, {6,10,11,11} },
6395 { ISD::OR, MVT::v2i64, {2, 2, 3, 3} },
6396 { ISD::OR, MVT::v4i32, {3, 4, 5, 5} },
6397 { ISD::OR, MVT::v8i16, {4, 7, 8, 8} },
6398 { ISD::OR, MVT::v16i8, {6,10,11,11} },
6399 { ISD::XOR, MVT::v2i64, {2, 2, 3, 3} },
6400 { ISD::XOR, MVT::v4i32, {3, 4, 5, 5} },
6401 { ISD::XOR, MVT::v8i16, {4, 7, 8, 8} },
6402 { ISD::XOR, MVT::v16i8, {6,10,11,11} },
6403 };
6404
6405 static const CostKindTblEntry AVX1CostTbl[] = {
6406 { ISD::FADD, MVT::v4f64, {3, 3, 3, 3} },
6407 { ISD::FADD, MVT::v4f32, {3, 3, 3, 3} },
6408 { ISD::FADD, MVT::v8f32, {4, 4, 4, 4} },
6409 { ISD::ADD, MVT::v2i64, {1, 1, 1, 1} }, // The data reported by the IACA tool is "1.5".
6410 { ISD::ADD, MVT::v4i64, {3, 3, 3, 3} },
6411 { ISD::ADD, MVT::v8i32, {5, 5, 5, 5} },
6412 { ISD::ADD, MVT::v16i16, {5, 5, 5, 5} },
6413 { ISD::ADD, MVT::v32i8, {4, 4, 4, 4} },
6414
6415 { ISD::AND, MVT::v4i64, {3, 7, 5, 5} },
6416 { ISD::AND, MVT::v8i32, {4, 9, 7, 7} },
6417 { ISD::AND, MVT::v16i16, {5,11, 9, 9} },
6418 { ISD::AND, MVT::v8i16, {4, 7, 7, 7} },
6419 { ISD::AND, MVT::v32i8, {6,13,11,11} },
6420 { ISD::AND, MVT::v16i8, {5,10, 9, 9} },
6421 { ISD::OR, MVT::v4i64, {3, 7, 5, 5} },
6422 { ISD::OR, MVT::v8i32, {4, 9, 7, 7} },
6423 { ISD::OR, MVT::v16i16, {5,11, 9, 9} },
6424 { ISD::OR, MVT::v8i16, {4, 7, 7, 7} },
6425 { ISD::OR, MVT::v32i8, {6,13,11,11} },
6426 { ISD::OR, MVT::v16i8, {5,10, 9, 9} },
6427 { ISD::XOR, MVT::v4i64, {3, 7, 5, 5} },
6428 { ISD::XOR, MVT::v8i32, {4, 9, 7, 7} },
6429 { ISD::XOR, MVT::v16i16, {5,11, 9, 9} },
6430 { ISD::XOR, MVT::v8i16, {4, 7, 7, 7} },
6431 { ISD::XOR, MVT::v32i8, {6,13,11,11} },
6432 { ISD::XOR, MVT::v16i8, {5,10, 9, 9} },
6433 };
6434
6435 static const CostKindTblEntry AVX2CostTbl[] = {
6436 { ISD::AND, MVT::v4i64, {2, 7, 5, 5} },
6437 { ISD::AND, MVT::v2i64, {1, 2, 3, 3} },
6438 { ISD::AND, MVT::v8i32, {3, 9, 7, 7} },
6439 { ISD::AND, MVT::v4i32, {2, 4, 5, 5} },
6440 { ISD::AND, MVT::v16i16, {3,11, 9, 9} },
6441 { ISD::AND, MVT::v8i16, {2, 6, 7, 7} },
6442 { ISD::AND, MVT::v32i8, {3,13,11,11} },
6443 { ISD::AND, MVT::v16i8, {3, 8, 9, 9} },
6444 { ISD::OR, MVT::v4i64, {2, 7, 5, 5} },
6445 { ISD::OR, MVT::v2i64, {1, 2, 3, 3} },
6446 { ISD::OR, MVT::v8i32, {3, 9, 7, 7} },
6447 { ISD::OR, MVT::v4i32, {2, 4, 5, 5} },
6448 { ISD::OR, MVT::v16i16, {3,11, 9, 9} },
6449 { ISD::OR, MVT::v8i16, {2, 6, 7, 7} },
6450 { ISD::OR, MVT::v32i8, {3,13,11,11} },
6451 { ISD::OR, MVT::v16i8, {3, 8, 9, 9} },
6452 { ISD::XOR, MVT::v4i64, {2, 7, 5, 5} },
6453 { ISD::XOR, MVT::v2i64, {1, 2, 3, 3} },
6454 { ISD::XOR, MVT::v8i32, {3, 9, 7, 7} },
6455 { ISD::XOR, MVT::v4i32, {2, 4, 5, 5} },
6456 { ISD::XOR, MVT::v16i16, {3,11, 9, 9} },
6457 { ISD::XOR, MVT::v8i16, {2, 6, 7, 7} },
6458 { ISD::XOR, MVT::v32i8, {3,13,11,11} },
6459 { ISD::XOR, MVT::v16i8, {3, 8, 9, 9} },
6460 };
6461
6462 static const CostKindTblEntry AVX512FCostTbl[] = {
6463 { ISD::FADD, MVT::v8f64, {4, 4, 4, 4} },
6464 { ISD::FADD, MVT::v16f32, {5, 5, 5, 5} },
6465 { ISD::ADD, MVT::v8i64, {4, 4, 4, 4} },
6466 { ISD::ADD, MVT::v16i32, {6, 6, 6, 6} },
6467
6468 { ISD::AND, MVT::v8i64, {3,10, 7, 7} },
6469 { ISD::AND, MVT::v16i32, {4,12, 9, 9} },
6470 { ISD::AND, MVT::v32i16, {4,14,11,11} },
6471 { ISD::AND, MVT::v64i8, {4,16,13,13} },
6472 { ISD::AND, MVT::v16i8, {2, 8, 9, 9} },
6473 { ISD::OR, MVT::v8i64, {3,10, 7, 7} },
6474 { ISD::OR, MVT::v16i32, {4,12, 9, 9} },
6475 { ISD::OR, MVT::v32i16, {4,14,11,11} },
6476 { ISD::OR, MVT::v64i8, {4,16,13,13} },
6477 { ISD::OR, MVT::v16i8, {2, 8, 9, 9} },
6478 { ISD::XOR, MVT::v8i64, {3,10, 7, 7} },
6479 { ISD::XOR, MVT::v16i32, {4,12, 9, 9} },
6480 { ISD::XOR, MVT::v32i16, {4,14,11,11} },
6481 { ISD::XOR, MVT::v64i8, {4,16,13,13} },
6482 { ISD::XOR, MVT::v16i8, {2, 8, 9, 9} },
6483 };
6484
6485 static const CostKindTblEntry AVX512BWCostTbl[] = {
6486 { ISD::ADD, MVT::v32i16, {7, 7, 7, 7} },
6487 { ISD::ADD, MVT::v64i8, {4, 4, 4, 4} },
6488 };
6489
6490 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6491 assert(ISD && "Invalid opcode");
6492
6493 // Before legalizing the type, give a chance to look up illegal narrow types
6494 // in the table.
6495 // FIXME: Is there a better way to do this?
6496 EVT VT = TLI->getValueType(DL, ValTy);
6497 if (VT.isSimple()) {
6498 MVT MTy = VT.getSimpleVT();
6499 if (ST->useSLMArithCosts())
6500 if (const auto *Entry = CostTableLookup(SLMCostTbl, ISD, MTy))
6501 if (auto KindCost = Entry->Cost[CostKind])
6502 return *KindCost;
6503
6504 if (ST->hasBWI())
6505 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
6506 if (auto KindCost = Entry->Cost[CostKind])
6507 return *KindCost;
6508
6509 if (ST->hasAVX512())
6510 if (const auto *Entry = CostTableLookup(AVX512FCostTbl, ISD, MTy))
6511 if (auto KindCost = Entry->Cost[CostKind])
6512 return *KindCost;
6513
6514 if (ST->hasAVX2())
6515 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
6516 if (auto KindCost = Entry->Cost[CostKind])
6517 return *KindCost;
6518
6519 if (ST->hasAVX())
6520 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
6521 if (auto KindCost = Entry->Cost[CostKind])
6522 return *KindCost;
6523
6524 if (ST->hasSSE2())
6525 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
6526 if (auto KindCost = Entry->Cost[CostKind])
6527 return *KindCost;
6528 }
6529
6530 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
6531
6532 MVT MTy = LT.second;
6533
6534 auto *ValVTy = cast<FixedVectorType>(ValTy);
6535
6536 InstructionCost ArithmeticCost = 0;
6537 if (LT.first != 1 && MTy.isVector() &&
6538 MTy.getVectorNumElements() < ValVTy->getNumElements()) {
6539 // Type needs to be split. We need LT.first - 1 arithmetic ops.
6540 auto *SingleOpTy = FixedVectorType::get(ValVTy->getElementType(),
6541 MTy.getVectorNumElements());
6542 ArithmeticCost = getArithmeticInstrCost(Opcode, SingleOpTy, CostKind);
6543 ArithmeticCost *= LT.first - 1;
6544 }
6545
6546 // FIXME: These assume a naive kshift+binop lowering, which is probably
6547 // conservative in most cases.
6548 static const CostKindTblEntry AVX512BoolReduction[] = {
6549 { ISD::AND, MVT::v2i1, { 3, 3, 3, 3} },
6550 { ISD::AND, MVT::v4i1, { 5, 5, 5, 5} },
6551 { ISD::AND, MVT::v8i1, { 7, 7, 7, 7} },
6552 { ISD::AND, MVT::v16i1, { 9, 9, 9, 9} },
6553 { ISD::AND, MVT::v32i1, {11,11,11,11} },
6554 { ISD::AND, MVT::v64i1, {13,13,13,13} },
6555 { ISD::OR, MVT::v2i1, { 3, 3, 3, 3} },
6556 { ISD::OR, MVT::v4i1, { 5, 5, 5, 5} },
6557 { ISD::OR, MVT::v8i1, { 7, 7, 7, 7} },
6558 { ISD::OR, MVT::v16i1, { 9, 9, 9, 9} },
6559 { ISD::OR, MVT::v32i1, {11,11,11,11} },
6560 { ISD::OR, MVT::v64i1, {13,13,13,13} },
6561 };
6562
6563 static const CostKindTblEntry AVX2BoolReduction[] = {
6564 { ISD::AND, MVT::v16i16, { 2, 2, 2, 2} }, // vpmovmskb + cmp
6565 { ISD::AND, MVT::v32i8, { 2, 2, 2, 2} }, // vpmovmskb + cmp
6566 { ISD::OR, MVT::v16i16, { 2, 2, 2, 2} }, // vpmovmskb + cmp
6567 { ISD::OR, MVT::v32i8, { 2, 2, 2, 2} }, // vpmovmskb + cmp
6568 };
6569
6570 static const CostKindTblEntry AVX1BoolReduction[] = {
6571 { ISD::AND, MVT::v4i64, {2, 2, 2, 2} }, // vmovmskpd + cmp
6572 { ISD::AND, MVT::v8i32, {2, 2, 2, 2} }, // vmovmskps + cmp
6573 { ISD::AND, MVT::v16i16, {4, 4, 4, 4} }, // vextractf128 + vpand + vpmovmskb + cmp
6574 { ISD::AND, MVT::v32i8, {4, 4, 4, 4} }, // vextractf128 + vpand + vpmovmskb + cmp
6575 { ISD::OR, MVT::v4i64, {2, 2, 2, 2} }, // vmovmskpd + cmp
6576 { ISD::OR, MVT::v8i32, {2, 2, 2, 2} }, // vmovmskps + cmp
6577 { ISD::OR, MVT::v16i16, {4, 4, 4, 4} }, // vextractf128 + vpor + vpmovmskb + cmp
6578 { ISD::OR, MVT::v32i8, {4, 4, 4, 4} }, // vextractf128 + vpor + vpmovmskb + cmp
6579 };
6580
6581 static const CostKindTblEntry SSE2BoolReduction[] = {
6582 { ISD::AND, MVT::v2i64, {2, 2, 2, 2} }, // movmskpd + cmp
6583 { ISD::AND, MVT::v4i32, {2, 2, 2, 2} }, // movmskps + cmp
6584 { ISD::AND, MVT::v8i16, {2, 2, 2, 2} }, // pmovmskb + cmp
6585 { ISD::AND, MVT::v16i8, {2, 2, 2, 2} }, // pmovmskb + cmp
6586 { ISD::OR, MVT::v2i64, {2, 2, 2, 2} }, // movmskpd + cmp
6587 { ISD::OR, MVT::v4i32, {2, 2, 2, 2} }, // movmskps + cmp
6588 { ISD::OR, MVT::v8i16, {2, 2, 2, 2} }, // pmovmskb + cmp
6589 { ISD::OR, MVT::v16i8, {2, 2, 2, 2} }, // pmovmskb + cmp
6590 };
6591
6592 // Handle bool allof/anyof vXi1 patterns before we check legal types.
6593 if (ValVTy->getElementType()->isIntegerTy(1)) {
6594 if (ISD == ISD::ADD) {
6595 // vXi1 addition reduction will bitcast to scalar and perform a popcount.
6596 auto *IntTy = IntegerType::getIntNTy(ValVTy->getContext(),
6597 ValVTy->getNumElements());
6598 IntrinsicCostAttributes ICA(Intrinsic::ctpop, IntTy, {IntTy});
6599 return getCastInstrCost(Instruction::BitCast, IntTy, ValVTy,
6601 CostKind) +
6602 getIntrinsicInstrCost(ICA, CostKind);
6603 }
6604
6605 if (ST->hasAVX512())
6606 if (const auto *Entry = CostTableLookup(AVX512BoolReduction, ISD, MTy))
6607 if (auto KindCost = Entry->Cost[CostKind])
6608 return ArithmeticCost + *KindCost;
6609 if (ST->hasAVX2())
6610 if (const auto *Entry = CostTableLookup(AVX2BoolReduction, ISD, MTy))
6611 if (auto KindCost = Entry->Cost[CostKind])
6612 return ArithmeticCost + *KindCost;
6613 if (ST->hasAVX())
6614 if (const auto *Entry = CostTableLookup(AVX1BoolReduction, ISD, MTy))
6615 if (auto KindCost = Entry->Cost[CostKind])
6616 return ArithmeticCost + *KindCost;
6617 if (ST->hasSSE2())
6618 if (const auto *Entry = CostTableLookup(SSE2BoolReduction, ISD, MTy))
6619 if (auto KindCost = Entry->Cost[CostKind])
6620 return ArithmeticCost + *KindCost;
6621
6622 return BaseT::getArithmeticReductionCost(Opcode, ValVTy, FMF, CostKind);
6623 }
6624
6625 // Special case: vXi8 mul reductions are performed as vXi16.
6626 if (ISD == ISD::MUL && MTy.getScalarType() == MVT::i8) {
6627 auto *WideSclTy = IntegerType::get(ValVTy->getContext(), 16);
6628 auto *WideVecTy = FixedVectorType::get(WideSclTy, ValVTy->getNumElements());
6629 return getCastInstrCost(Instruction::ZExt, WideVecTy, ValTy,
6631 CostKind) +
6632 getArithmeticReductionCost(Opcode, WideVecTy, FMF, CostKind);
6633 }
6634
6635 if (ST->useSLMArithCosts())
6636 if (const auto *Entry = CostTableLookup(SLMCostTbl, ISD, MTy))
6637 if (auto KindCost = Entry->Cost[CostKind])
6638 return ArithmeticCost + *KindCost;
6639
6640 if (ST->hasBWI())
6641 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
6642 if (auto KindCost = Entry->Cost[CostKind])
6643 return ArithmeticCost + *KindCost;
6644
6645 if (ST->hasAVX512())
6646 if (const auto *Entry = CostTableLookup(AVX512FCostTbl, ISD, MTy))
6647 if (auto KindCost = Entry->Cost[CostKind])
6648 return ArithmeticCost + *KindCost;
6649
6650 if (ST->hasAVX2())
6651 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
6652 if (auto KindCost = Entry->Cost[CostKind])
6653 return ArithmeticCost + *KindCost;
6654
6655 if (ST->hasAVX())
6656 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
6657 if (auto KindCost = Entry->Cost[CostKind])
6658 return ArithmeticCost + *KindCost;
6659
6660 if (ST->hasSSE2())
6661 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
6662 if (auto KindCost = Entry->Cost[CostKind])
6663 return ArithmeticCost + *KindCost;
6664
6665 unsigned NumVecElts = ValVTy->getNumElements();
6666 unsigned ScalarSize = ValVTy->getScalarSizeInBits();
6667
6668 // Special case power of 2 reductions where the scalar type isn't changed
6669 // by type legalization.
6670 if (!isPowerOf2_32(NumVecElts) || ScalarSize != MTy.getScalarSizeInBits())
6671 return BaseT::getArithmeticReductionCost(Opcode, ValVTy, FMF, CostKind);
6672
6673 InstructionCost ReductionCost = 0;
6674
6675 auto *Ty = ValVTy;
6676 if (LT.first != 1 && MTy.isVector() &&
6677 MTy.getVectorNumElements() < ValVTy->getNumElements()) {
6678 // Type needs to be split. We need LT.first - 1 arithmetic ops.
6679 Ty = FixedVectorType::get(ValVTy->getElementType(),
6680 MTy.getVectorNumElements());
6681 ReductionCost = getArithmeticInstrCost(Opcode, Ty, CostKind);
6682 ReductionCost *= LT.first - 1;
6683 NumVecElts = MTy.getVectorNumElements();
6684 }
6685
6686 // Now handle reduction with the legal type, taking into account size changes
6687 // at each level.
6688 while (NumVecElts > 1) {
6689 // Determine the size of the remaining vector we need to reduce.
6690 unsigned Size = NumVecElts * ScalarSize;
6691 NumVecElts /= 2;
6692 // If we're reducing from 256/512 bits, use an extract_subvector.
6693 if (Size > 128) {
6694 auto *SubTy = FixedVectorType::get(ValVTy->getElementType(), NumVecElts);
6695 ReductionCost += getShuffleCost(TTI::SK_ExtractSubvector, Ty, Ty,
6696 CostKind, {}, NumVecElts, SubTy);
6697 Ty = SubTy;
6698 } else if (Size == 128) {
6699 // Reducing from 128 bits is a permute of v2f64/v2i64.
6700 FixedVectorType *ShufTy;
6701 if (ValVTy->isFloatingPointTy())
6702 ShufTy =
6703 FixedVectorType::get(Type::getDoubleTy(ValVTy->getContext()), 2);
6704 else
6705 ShufTy =
6706 FixedVectorType::get(Type::getInt64Ty(ValVTy->getContext()), 2);
6707 ReductionCost += getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, ShufTy,
6708 CostKind, {}, 0, nullptr);
6709 } else if (Size == 64) {
6710 // Reducing from 64 bits is a shuffle of v4f32/v4i32.
6711 FixedVectorType *ShufTy;
6712 if (ValVTy->isFloatingPointTy())
6713 ShufTy =
6714 FixedVectorType::get(Type::getFloatTy(ValVTy->getContext()), 4);
6715 else
6716 ShufTy =
6717 FixedVectorType::get(Type::getInt32Ty(ValVTy->getContext()), 4);
6718 ReductionCost += getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, ShufTy,
6719 CostKind, {}, 0, nullptr);
6720 } else {
6721 // Reducing from smaller size is a shift by immediate.
6722 auto *ShiftTy = FixedVectorType::get(
6723 Type::getIntNTy(ValVTy->getContext(), Size), 128 / Size);
6724 ReductionCost += getArithmeticInstrCost(
6725 Instruction::LShr, ShiftTy, CostKind,
6728 }
6729
6730 // Add the arithmetic op for this level.
6731 ReductionCost += getArithmeticInstrCost(Opcode, Ty, CostKind);
6732 }
6733
6734 // Add the final extract element to the cost.
6735 return ReductionCost + getVectorInstrCost(Instruction::ExtractElement, Ty,
6736 CostKind, 0, nullptr, nullptr,
6738}
6739
6741 TTI::TargetCostKind CostKind,
6742 FastMathFlags FMF) const {
6743 IntrinsicCostAttributes ICA(IID, Ty, {Ty, Ty}, FMF);
6744 return getIntrinsicInstrCost(ICA, CostKind);
6745}
6746
6749 FastMathFlags FMF,
6750 TTI::TargetCostKind CostKind) const {
6751 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
6752
6753 MVT MTy = LT.second;
6754
6756 if (ValTy->isIntOrIntVectorTy()) {
6757 ISD = (IID == Intrinsic::umin || IID == Intrinsic::umax) ? ISD::UMIN
6758 : ISD::SMIN;
6759 } else {
6760 assert(ValTy->isFPOrFPVectorTy() &&
6761 "Expected float point or integer vector type.");
6762 ISD = (IID == Intrinsic::minnum || IID == Intrinsic::maxnum)
6763 ? ISD::FMINNUM
6764 : ISD::FMINIMUM;
6765 }
6766
6767 // We use llvm-mca across all supported CPUs to measure the cost stats.
6768 static const CostKindTblEntry SSE2CostTbl[] = {
6769 {ISD::SMIN, MVT::v2i64, {3, 4, 5, 6}},
6770 {ISD::UMIN, MVT::v2i64, {3, 4, 5, 6}},
6771 {ISD::SMIN, MVT::v2i32, {2, 2, 5, 6}},
6772 {ISD::UMIN, MVT::v2i32, {2, 2, 5, 6}},
6773 {ISD::SMIN, MVT::v4i32, {3, 7,11,12}},
6774 {ISD::UMIN, MVT::v4i32, {4, 7,14,15}},
6775 {ISD::SMIN, MVT::v2i16, {2, 3, 4, 4}},
6776 {ISD::UMIN, MVT::v2i16, {2, 3, 4, 6}},
6777 {ISD::SMIN, MVT::v4i16, {3, 5, 6, 6}},
6778 {ISD::UMIN, MVT::v4i16, {3, 5, 8, 10}},
6779 {ISD::SMIN, MVT::v8i16, {3, 8, 8, 8}},
6780 {ISD::UMIN, MVT::v8i16, {4, 8,12,14}},
6781 {ISD::SMIN, MVT::v2i8, {2, 3, 5, 6}},
6782 {ISD::UMIN, MVT::v2i8, {2, 3, 4, 4}},
6783 {ISD::SMIN, MVT::v4i8, {4, 6,12,13}},
6784 {ISD::UMIN, MVT::v4i8, {3, 6, 7, 7}},
6785 {ISD::SMIN, MVT::v8i8, {5, 9,18,19}},
6786 {ISD::UMIN, MVT::v8i8, {4, 8, 9, 9}},
6787 {ISD::SMIN, MVT::v16i8, {7,13,24,25}},
6788 {ISD::UMIN, MVT::v16i8, {3,10,11,11}},
6789 };
6790
6791 static const CostKindTblEntry SSE41CostTbl[] = {
6792 {ISD::SMIN, MVT::v2i64, {3, 4, 4, 6}},
6793 {ISD::UMIN, MVT::v2i64, {3, 4, 4, 6}},
6794 {ISD::SMIN, MVT::v2i32, {2, 2, 3, 3}},
6795 {ISD::UMIN, MVT::v2i32, {2, 2, 3, 3}},
6796 {ISD::SMIN, MVT::v4i32, {3, 4, 5, 5}},
6797 {ISD::UMIN, MVT::v4i32, {3, 4, 5, 5}},
6798 {ISD::UMIN, MVT::v2i16, {2, 3, 4, 4}},
6799 {ISD::SMIN, MVT::v4i16, {3, 5, 6, 6}},
6800 {ISD::UMIN, MVT::v4i16, {3, 5, 6, 6}},
6801 {ISD::SMIN, MVT::v8i16, {2, 8, 4, 5}},
6802 {ISD::UMIN, MVT::v8i16, {2, 5, 2, 2}},
6803 {ISD::SMIN, MVT::v2i8, {2, 3, 4, 4}},
6804 {ISD::SMIN, MVT::v4i8, {3, 6, 7, 7}},
6805 {ISD::SMIN, MVT::v8i8, {4, 8, 9, 9}},
6806 {ISD::SMIN, MVT::v16i8, {3,10, 7, 8}},
6807 {ISD::UMIN, MVT::v16i8, {3, 8, 5, 5}},
6808 };
6809
6810 static const CostKindTblEntry AVX1CostTbl[] = {
6811 {ISD::SMIN, MVT::v4i64, {5,11, 7,10}},
6812 {ISD::UMIN, MVT::v4i64, {6,12,10,13}},
6813 {ISD::SMIN, MVT::v8i32, {4, 9, 7, 7}},
6814 {ISD::UMIN, MVT::v8i32, {4, 9, 7, 7}},
6815 {ISD::SMIN, MVT::v16i16, {3,15, 6, 7}},
6816 {ISD::UMIN, MVT::v16i16, {2, 9, 4, 4}},
6817 {ISD::SMIN, MVT::v32i8, {4,17, 8, 9}},
6818 {ISD::UMIN, MVT::v32i8, {3,11, 6, 6}},
6819 };
6820
6821 static const CostKindTblEntry AVX2CostTbl[] = {
6822 {ISD::SMIN, MVT::v4i64, {4,11, 7,10}},
6823 {ISD::UMIN, MVT::v4i64, {4,12,10,13}},
6824 {ISD::SMIN, MVT::v2i32, {1, 2, 3, 3}},
6825 {ISD::UMIN, MVT::v2i32, {1, 2, 3, 3}},
6826 {ISD::UMIN, MVT::v4i32, {2, 4, 5, 5}},
6827 {ISD::SMIN, MVT::v4i32, {2, 4, 5, 5}},
6828 {ISD::SMIN, MVT::v8i32, {3, 9, 7, 7}},
6829 {ISD::UMIN, MVT::v8i32, {3, 9, 7, 7}},
6830 {ISD::SMIN, MVT::v4i16, {2, 4, 5, 5}},
6831 {ISD::UMIN, MVT::v4i16, {2, 4, 5, 5}},
6832 {ISD::SMIN, MVT::v16i16, {2,15, 6, 7}},
6833 {ISD::SMIN, MVT::v8i8, {3, 6, 7, 7}},
6834 {ISD::UMIN, MVT::v8i8, {3, 6, 7, 7}},
6835 {ISD::SMIN, MVT::v32i8, {3,17, 8, 9}},
6836 };
6837
6838 static const CostKindTblEntry AVX512FCostTbl[] = {
6839 {ISD::SMIN, MVT::v2i64, {2, 4, 3, 3}},
6840 {ISD::UMIN, MVT::v2i64, {2, 4, 3, 3}},
6841 {ISD::SMIN, MVT::v4i64, {3,10, 5, 5}},
6842 {ISD::UMIN, MVT::v4i64, {3,10, 5, 5}},
6843 {ISD::SMIN, MVT::v8i64, {5,16, 7, 7}},
6844 {ISD::UMIN, MVT::v8i64, {5,16, 7, 7}},
6845 {ISD::SMIN, MVT::v16i32, {4,12, 9, 9}},
6846 {ISD::UMIN, MVT::v16i32, {4,12, 9, 9}},
6847 };
6848
6849 static const CostKindTblEntry AVX512BWCostTbl[] = {
6850 {ISD::SMIN, MVT::v2i16, {1, 2, 3, 3}},
6851 {ISD::UMIN, MVT::v2i16, {1, 2, 3, 3}},
6852 {ISD::SMIN, MVT::v32i16, {2,19, 8, 9}},
6853 {ISD::UMIN, MVT::v32i16, {2,12, 6, 6}},
6854 {ISD::SMIN, MVT::v2i8, {1, 2, 3, 3}},
6855 {ISD::UMIN, MVT::v2i8, {1, 2, 3, 3}},
6856 {ISD::SMIN, MVT::v4i8, {2, 4, 5, 5}},
6857 {ISD::UMIN, MVT::v4i8, {2, 4, 5, 5}},
6858 {ISD::SMIN, MVT::v16i8, {2,10, 6, 7}},
6859 {ISD::UMIN, MVT::v16i8, {2, 6, 4, 4}},
6860 {ISD::SMIN, MVT::v32i8, {2,17, 8, 9}},
6861 {ISD::UMIN, MVT::v32i8, {2,10, 6, 6}},
6862 {ISD::SMIN, MVT::v64i8, {2,21,10,11}},
6863 {ISD::UMIN, MVT::v64i8, {2,14, 8, 8}},
6864 };
6865
6866 // Before legalizing the type, give a chance to look up illegal narrow types
6867 // in the table.
6868 // FIXME: Is there a better way to do this?
6869 EVT VT = TLI->getValueType(DL, ValTy);
6870 if (VT.isSimple()) {
6871 MVT MTy = VT.getSimpleVT();
6872 if (ST->hasBWI())
6873 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
6874 if (auto KindCost = Entry->Cost[CostKind])
6875 return *KindCost;
6876
6877 if (ST->hasAVX512())
6878 if (const auto *Entry = CostTableLookup(AVX512FCostTbl, ISD, MTy))
6879 if (auto KindCost = Entry->Cost[CostKind])
6880 return *KindCost;
6881
6882 if (ST->hasAVX2())
6883 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
6884 if (auto KindCost = Entry->Cost[CostKind])
6885 return *KindCost;
6886
6887 if (ST->hasAVX())
6888 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
6889 if (auto KindCost = Entry->Cost[CostKind])
6890 return *KindCost;
6891
6892 if (ST->hasSSE41())
6893 if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
6894 if (auto KindCost = Entry->Cost[CostKind])
6895 return *KindCost;
6896
6897 if (ST->hasSSE2())
6898 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
6899 if (auto KindCost = Entry->Cost[CostKind])
6900 return *KindCost;
6901 }
6902
6903 auto *ValVTy = cast<FixedVectorType>(ValTy);
6904 unsigned NumVecElts = ValVTy->getNumElements();
6905
6906 auto *Ty = ValVTy;
6907 InstructionCost MinMaxCost = 0;
6908 if (LT.first != 1 && MTy.isVector() &&
6909 MTy.getVectorNumElements() < ValVTy->getNumElements()) {
6910 // Type needs to be split. We need LT.first - 1 operations ops.
6911 Ty = FixedVectorType::get(ValVTy->getElementType(),
6912 MTy.getVectorNumElements());
6913 MinMaxCost = getMinMaxCost(IID, Ty, CostKind, FMF);
6914 MinMaxCost *= LT.first - 1;
6915 NumVecElts = MTy.getVectorNumElements();
6916 }
6917
6918 if (ST->hasBWI())
6919 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
6920 if (auto KindCost = Entry->Cost[CostKind])
6921 return MinMaxCost + *KindCost;
6922
6923 if (ST->hasAVX512())
6924 if (const auto *Entry = CostTableLookup(AVX512FCostTbl, ISD, MTy))
6925 if (auto KindCost = Entry->Cost[CostKind])
6926 return MinMaxCost + *KindCost;
6927
6928 if (ST->hasAVX2())
6929 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
6930 if (auto KindCost = Entry->Cost[CostKind])
6931 return MinMaxCost + *KindCost;
6932
6933 if (ST->hasAVX())
6934 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
6935 if (auto KindCost = Entry->Cost[CostKind])
6936 return MinMaxCost + *KindCost;
6937
6938 if (ST->hasSSE41())
6939 if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
6940 if (auto KindCost = Entry->Cost[CostKind])
6941 return MinMaxCost + *KindCost;
6942
6943 if (ST->hasSSE2())
6944 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
6945 if (auto KindCost = Entry->Cost[CostKind])
6946 return MinMaxCost + *KindCost;
6947
6948 unsigned ScalarSize = ValTy->getScalarSizeInBits();
6949
6950 // Special case power of 2 reductions where the scalar type isn't changed
6951 // by type legalization.
6952 if (!isPowerOf2_32(ValVTy->getNumElements()) ||
6953 ScalarSize != MTy.getScalarSizeInBits())
6954 return BaseT::getMinMaxReductionCost(IID, ValTy, FMF, CostKind);
6955
6956 // Now handle reduction with the legal type, taking into account size changes
6957 // at each level.
6958 while (NumVecElts > 1) {
6959 // Determine the size of the remaining vector we need to reduce.
6960 unsigned Size = NumVecElts * ScalarSize;
6961 NumVecElts /= 2;
6962 // If we're reducing from 256/512 bits, use an extract_subvector.
6963 if (Size > 128) {
6964 auto *SubTy = FixedVectorType::get(ValVTy->getElementType(), NumVecElts);
6965 MinMaxCost += getShuffleCost(TTI::SK_ExtractSubvector, Ty, Ty, CostKind,
6966 {}, NumVecElts, SubTy);
6967 Ty = SubTy;
6968 } else if (Size == 128) {
6969 // Reducing from 128 bits is a permute of v2f64/v2i64.
6970 VectorType *ShufTy;
6971 if (ValTy->isFloatingPointTy())
6972 ShufTy =
6974 else
6975 ShufTy = FixedVectorType::get(Type::getInt64Ty(ValTy->getContext()), 2);
6976 MinMaxCost += getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, ShufTy,
6977 CostKind, {}, 0, nullptr);
6978 } else if (Size == 64) {
6979 // Reducing from 64 bits is a shuffle of v4f32/v4i32.
6980 FixedVectorType *ShufTy;
6981 if (ValTy->isFloatingPointTy())
6982 ShufTy = FixedVectorType::get(Type::getFloatTy(ValTy->getContext()), 4);
6983 else
6984 ShufTy = FixedVectorType::get(Type::getInt32Ty(ValTy->getContext()), 4);
6985 MinMaxCost += getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, ShufTy,
6986 CostKind, {}, 0, nullptr);
6987 } else {
6988 // Reducing from smaller size is a shift by immediate.
6989 auto *ShiftTy = FixedVectorType::get(
6990 Type::getIntNTy(ValTy->getContext(), Size), 128 / Size);
6991 MinMaxCost += getArithmeticInstrCost(
6992 Instruction::LShr, ShiftTy, TTI::TCK_RecipThroughput,
6995 }
6996
6997 // Add the arithmetic op for this level.
6998 MinMaxCost += getMinMaxCost(IID, Ty, CostKind, FMF);
6999 }
7000
7001 // Add the final extract element to the cost.
7002 return MinMaxCost + getVectorInstrCost(Instruction::ExtractElement, Ty,
7003 CostKind, 0, nullptr, nullptr,
7005}
7006
7007/// Calculate the cost of materializing a 64-bit value. This helper
7008/// method might only calculate a fraction of a larger immediate. Therefore it
7009/// is valid to return a cost of ZERO.
7011 if (Val == 0)
7012 return TTI::TCC_Free;
7013
7014 if (isInt<32>(Val))
7015 return TTI::TCC_Basic;
7016
7017 return 2 * TTI::TCC_Basic;
7018}
7019
7021 TTI::TargetCostKind CostKind) const {
7022 assert(Ty->isIntegerTy());
7023
7024 unsigned BitSize = Ty->getPrimitiveSizeInBits();
7025 if (BitSize == 0)
7026 return ~0U;
7027
7028 // Never hoist constants larger than 128bit, because this might lead to
7029 // incorrect code generation or assertions in codegen.
7030 // Fixme: Create a cost model for types larger than i128 once the codegen
7031 // issues have been fixed.
7032 if (BitSize > 128)
7033 return TTI::TCC_Free;
7034
7035 if (Imm == 0)
7036 return TTI::TCC_Free;
7037
7038 // Sign-extend all constants to a multiple of 64-bit.
7039 APInt ImmVal = Imm;
7040 if (BitSize % 64 != 0)
7041 ImmVal = Imm.sext(alignTo(BitSize, 64));
7042
7043 // Split the constant into 64-bit chunks and calculate the cost for each
7044 // chunk.
7046 for (unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
7047 APInt Tmp = ImmVal.ashr(ShiftVal).sextOrTrunc(64);
7048 int64_t Val = Tmp.getSExtValue();
7049 Cost += getIntImmCost(Val);
7050 }
7051 // We need at least one instruction to materialize the constant.
7052 return std::max<InstructionCost>(1, Cost);
7053}
7054
7056 const APInt &Imm, Type *Ty,
7057 TTI::TargetCostKind CostKind,
7058 Instruction *Inst) const {
7059 assert(Ty->isIntegerTy());
7060
7061 unsigned BitSize = Ty->getPrimitiveSizeInBits();
7062 unsigned ImmBitWidth = Imm.getBitWidth();
7063
7064 // There is no cost model for constants with a bit size of 0. Return TCC_Free
7065 // here, so that constant hoisting will ignore this constant.
7066 if (BitSize == 0)
7067 return TTI::TCC_Free;
7068
7069 unsigned ImmIdx = ~0U;
7070 switch (Opcode) {
7071 default:
7072 return TTI::TCC_Free;
7073 case Instruction::GetElementPtr:
7074 // Always hoist the base address of a GetElementPtr. This prevents the
7075 // creation of new constants for every base constant that gets constant
7076 // folded with the offset.
7077 if (Idx == 0)
7078 return 2 * TTI::TCC_Basic;
7079 return TTI::TCC_Free;
7080 case Instruction::Store:
7081 ImmIdx = 0;
7082 break;
7083 case Instruction::ICmp:
7084 // This is an imperfect hack to prevent constant hoisting of
7085 // compares that might be trying to check if a 64-bit value fits in
7086 // 32-bits. The backend can optimize these cases using a right shift by 32.
7087 // There are other predicates and immediates the backend can use shifts for.
7088 if (Idx == 1 && ImmBitWidth == 64) {
7089 uint64_t ImmVal = Imm.getZExtValue();
7090 if (ImmVal == 0x100000000ULL || ImmVal == 0xffffffff)
7091 return TTI::TCC_Free;
7092
7093 if (auto *Cmp = dyn_cast_or_null<CmpInst>(Inst)) {
7094 if (Cmp->isEquality()) {
7095 KnownBits Known = computeKnownBits(Cmp->getOperand(0), DL);
7096 if (Known.countMinTrailingZeros() >= 32)
7097 return TTI::TCC_Free;
7098 }
7099 }
7100 }
7101 ImmIdx = 1;
7102 break;
7103 case Instruction::And:
7104 // We support 64-bit ANDs with immediates with 32-bits of leading zeroes
7105 // by using a 32-bit operation with implicit zero extension. Detect such
7106 // immediates here as the normal path expects bit 31 to be sign extended.
7107 if (Idx == 1 && ImmBitWidth == 64 && Imm.isIntN(32))
7108 return TTI::TCC_Free;
7109 // If we have BMI then we can use BEXTR/BZHI to mask out upper i64 bits.
7110 if (Idx == 1 && ImmBitWidth == 64 && ST->is64Bit() && ST->hasBMI() &&
7111 Imm.isMask())
7112 return X86TTIImpl::getIntImmCost(ST->hasBMI2() ? 255 : 65535);
7113 ImmIdx = 1;
7114 break;
7115 case Instruction::Add:
7116 case Instruction::Sub:
7117 // For add/sub, we can use the opposite instruction for INT32_MIN.
7118 if (Idx == 1 && ImmBitWidth == 64 && Imm.getZExtValue() == 0x80000000)
7119 return TTI::TCC_Free;
7120 ImmIdx = 1;
7121 break;
7122 case Instruction::UDiv:
7123 case Instruction::SDiv:
7124 case Instruction::URem:
7125 case Instruction::SRem:
7126 // Division by constant is typically expanded later into a different
7127 // instruction sequence. This completely changes the constants.
7128 // Report them as "free" to stop ConstantHoist from marking them as opaque.
7129 return TTI::TCC_Free;
7130 case Instruction::Mul:
7131 case Instruction::Or:
7132 case Instruction::Xor:
7133 ImmIdx = 1;
7134 break;
7135 // Always return TCC_Free for the shift value of a shift instruction.
7136 case Instruction::Shl:
7137 case Instruction::LShr:
7138 case Instruction::AShr:
7139 if (Idx == 1)
7140 return TTI::TCC_Free;
7141 break;
7142 case Instruction::Trunc:
7143 case Instruction::ZExt:
7144 case Instruction::SExt:
7145 case Instruction::IntToPtr:
7146 case Instruction::PtrToInt:
7147 case Instruction::BitCast:
7148 case Instruction::PHI:
7149 case Instruction::Call:
7150 case Instruction::Select:
7151 case Instruction::Ret:
7152 case Instruction::Load:
7153 break;
7154 }
7155
7156 if (Idx == ImmIdx) {
7157 uint64_t NumConstants = divideCeil(BitSize, 64);
7159 return (Cost <= NumConstants * TTI::TCC_Basic)
7160 ? static_cast<int>(TTI::TCC_Free)
7161 : Cost;
7162 }
7163
7164 return X86TTIImpl::getIntImmCost(Imm, Ty, CostKind);
7165}
7166
7169 const APInt &Imm, Type *Ty,
7170 TTI::TargetCostKind CostKind) const {
7171 assert(Ty->isIntegerTy());
7172
7173 unsigned BitSize = Ty->getPrimitiveSizeInBits();
7174 // There is no cost model for constants with a bit size of 0. Return TCC_Free
7175 // here, so that constant hoisting will ignore this constant.
7176 if (BitSize == 0)
7177 return TTI::TCC_Free;
7178
7179 switch (IID) {
7180 default:
7181 return TTI::TCC_Free;
7182 case Intrinsic::sadd_with_overflow:
7183 case Intrinsic::uadd_with_overflow:
7184 case Intrinsic::ssub_with_overflow:
7185 case Intrinsic::usub_with_overflow:
7186 case Intrinsic::smul_with_overflow:
7187 case Intrinsic::umul_with_overflow:
7188 if ((Idx == 1) && Imm.getBitWidth() <= 64 && Imm.isSignedIntN(32))
7189 return TTI::TCC_Free;
7190 break;
7191 case Intrinsic::experimental_stackmap:
7192 if ((Idx < 2) || (Imm.getBitWidth() <= 64 && Imm.isSignedIntN(64)))
7193 return TTI::TCC_Free;
7194 break;
7195 case Intrinsic::experimental_patchpoint_void:
7196 case Intrinsic::experimental_patchpoint:
7197 if ((Idx < 4) || (Imm.getBitWidth() <= 64 && Imm.isSignedIntN(64)))
7198 return TTI::TCC_Free;
7199 break;
7200 }
7201 return X86TTIImpl::getIntImmCost(Imm, Ty, CostKind);
7202}
7203
7205 TTI::TargetCostKind CostKind,
7206 const Instruction *I) const {
7207 if (CostKind != TTI::TCK_RecipThroughput)
7208 return Opcode == Instruction::PHI ? TTI::TCC_Free : TTI::TCC_Basic;
7209 // Branches are assumed to be predicted.
7210 return TTI::TCC_Free;
7211}
7212
7213int X86TTIImpl::getGatherOverhead() const {
7214 // Some CPUs have more overhead for gather. The specified overhead is relative
7215 // to the Load operation. "2" is the number provided by Intel architects. This
7216 // parameter is used for cost estimation of Gather Op and comparison with
7217 // other alternatives.
7218 // TODO: Remove the explicit hasAVX512()?, That would mean we would only
7219 // enable gather with a -march.
7220 if (ST->hasAVX512() || (ST->hasAVX2() && ST->hasFastGather()))
7221 return 2;
7222
7223 return 1024;
7224}
7225
7226int X86TTIImpl::getScatterOverhead() const {
7227 if (ST->hasAVX512())
7228 return 2;
7229
7230 return 1024;
7231}
7232
7233// Return an average cost of Gather / Scatter instruction, maybe improved later.
7234InstructionCost X86TTIImpl::getGSVectorCost(unsigned Opcode,
7235 TTI::TargetCostKind CostKind,
7236 Type *SrcVTy, const Value *Ptr,
7237 Align Alignment,
7238 unsigned AddressSpace) const {
7239
7240 assert(isa<VectorType>(SrcVTy) && "Unexpected type in getGSVectorCost");
7241 unsigned VF = cast<FixedVectorType>(SrcVTy)->getNumElements();
7242
7243 // Try to reduce index size from 64 bit (default for GEP)
7244 // to 32. It is essential for VF 16. If the index can't be reduced to 32, the
7245 // operation will use 16 x 64 indices which do not fit in a zmm and needs
7246 // to split. Also check that the base pointer is the same for all lanes,
7247 // and that there's at most one variable index.
7248 auto getIndexSizeInBits = [](const Value *Ptr, const DataLayout &DL) {
7249 unsigned IndexSize = DL.getPointerSizeInBits();
7250 const GetElementPtrInst *GEP = dyn_cast_or_null<GetElementPtrInst>(Ptr);
7251 if (IndexSize < 64 || !GEP)
7252 return IndexSize;
7253
7254 unsigned NumOfVarIndices = 0;
7255 const Value *Ptrs = GEP->getPointerOperand();
7256 if (Ptrs->getType()->isVectorTy() && !getSplatValue(Ptrs))
7257 return IndexSize;
7258 for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I) {
7259 if (isa<Constant>(GEP->getOperand(I)))
7260 continue;
7261 Type *IndxTy = GEP->getOperand(I)->getType();
7262 if (auto *IndexVTy = dyn_cast<VectorType>(IndxTy))
7263 IndxTy = IndexVTy->getElementType();
7264 if ((IndxTy->getPrimitiveSizeInBits() == 64 &&
7265 !isa<SExtInst>(GEP->getOperand(I))) ||
7266 ++NumOfVarIndices > 1)
7267 return IndexSize; // 64
7268 }
7269 return (unsigned)32;
7270 };
7271
7272 // Trying to reduce IndexSize to 32 bits for vector 16.
7273 // By default the IndexSize is equal to pointer size.
7274 unsigned IndexSize = (ST->hasAVX512() && VF >= 16)
7275 ? getIndexSizeInBits(Ptr, DL)
7276 : DL.getPointerSizeInBits();
7277
7278 auto *IndexVTy = FixedVectorType::get(
7279 IntegerType::get(SrcVTy->getContext(), IndexSize), VF);
7280 std::pair<InstructionCost, MVT> IdxsLT = getTypeLegalizationCost(IndexVTy);
7281 std::pair<InstructionCost, MVT> SrcLT = getTypeLegalizationCost(SrcVTy);
7282 InstructionCost::CostType SplitFactor =
7283 std::max(IdxsLT.first, SrcLT.first).getValue();
7284 if (SplitFactor > 1) {
7285 // Handle splitting of vector of pointers
7286 auto *SplitSrcTy =
7287 FixedVectorType::get(SrcVTy->getScalarType(), VF / SplitFactor);
7288 return SplitFactor * getGSVectorCost(Opcode, CostKind, SplitSrcTy, Ptr,
7289 Alignment, AddressSpace);
7290 }
7291
7292 // If we didn't split, this will be a single gather/scatter instruction.
7293 if (CostKind == TTI::TCK_CodeSize)
7294 return 1;
7295
7296 // The gather / scatter cost is given by Intel architects. It is a rough
7297 // number since we are looking at one instruction in a time.
7298 const int GSOverhead = (Opcode == Instruction::Load) ? getGatherOverhead()
7299 : getScatterOverhead();
7300 return GSOverhead + VF * getMemoryOpCost(Opcode, SrcVTy->getScalarType(),
7301 Alignment, AddressSpace, CostKind);
7302}
7303
7304/// Calculate the cost of Gather / Scatter operation
7307 TTI::TargetCostKind CostKind) const {
7308 bool IsLoad = MICA.getID() == Intrinsic::masked_gather ||
7309 MICA.getID() == Intrinsic::vp_gather;
7310 unsigned Opcode = IsLoad ? Instruction::Load : Instruction::Store;
7311 Type *SrcVTy = MICA.getDataType();
7312 const Value *Ptr = MICA.getPointer();
7313 Align Alignment = MICA.getAlignment();
7314 if ((Opcode == Instruction::Load &&
7315 (!isLegalMaskedGather(SrcVTy, Align(Alignment)) ||
7317 Align(Alignment)))) ||
7318 (Opcode == Instruction::Store &&
7319 (!isLegalMaskedScatter(SrcVTy, Align(Alignment)) ||
7321 Align(Alignment)))))
7322 return BaseT::getMemIntrinsicInstrCost(MICA, CostKind);
7323
7324 assert(SrcVTy->isVectorTy() && "Unexpected data type for Gather/Scatter");
7325 unsigned AddressSpace = MICA.getAddressSpace();
7327 getGSVectorCost(Opcode, CostKind, SrcVTy, Ptr, Alignment, AddressSpace);
7328
7329 // Predicate fanout (see getPredicateFanoutCost); variable mask only.
7330 if (MICA.getVariableMask()) {
7331 auto *MaskVecTy =
7333 cast<FixedVectorType>(SrcVTy)->getNumElements());
7334 Cost += getPredicateFanoutCost(*this, SrcVTy, MaskVecTy);
7335 }
7336 return Cost;
7337}
7338
7340 const TargetTransformInfo::LSRCost &C2) const {
7341 // X86 specific here are "instruction number 1st priority".
7342 return std::tie(C1.Insns, C1.NumRegs, C1.AddRecCost, C1.NumIVMuls,
7343 C1.NumBaseAdds, C1.ScaleCost, C1.ImmCost, C1.SetupCost) <
7344 std::tie(C2.Insns, C2.NumRegs, C2.AddRecCost, C2.NumIVMuls,
7345 C2.NumBaseAdds, C2.ScaleCost, C2.ImmCost, C2.SetupCost);
7346}
7347
7349 return ST->hasMacroFusion() || ST->hasBranchFusion();
7350}
7351
7352static bool isLegalMaskedLoadStore(Type *ScalarTy, const X86Subtarget *ST) {
7353 if (!ST->hasAVX())
7354 return false;
7355
7356 if (ScalarTy->isPointerTy())
7357 return true;
7358
7359 if (ScalarTy->isFloatTy() || ScalarTy->isDoubleTy())
7360 return true;
7361
7362 if ((ScalarTy->isHalfTy() || ScalarTy->isBFloatTy()) && ST->hasBWI())
7363 return true;
7364
7365 if (!ScalarTy->isIntegerTy())
7366 return false;
7367
7368 unsigned IntWidth = ScalarTy->getIntegerBitWidth();
7369 return IntWidth == 32 || IntWidth == 64 ||
7370 ((IntWidth == 8 || IntWidth == 16) && ST->hasBWI());
7371}
7372
7374 unsigned AddressSpace,
7375 TTI::MaskKind MaskKind) const {
7376 Type *ScalarTy = DataTy->getScalarType();
7377
7378 // The backend can't handle a single element vector w/o CFCMOV.
7379 if (isa<VectorType>(DataTy) &&
7380 cast<FixedVectorType>(DataTy)->getNumElements() == 1)
7381 return ST->hasCF() &&
7382 hasConditionalLoadStoreForType(ScalarTy, /*IsStore=*/false);
7383
7384 return isLegalMaskedLoadStore(ScalarTy, ST);
7385}
7386
7388 unsigned AddressSpace,
7389 TTI::MaskKind MaskKind) const {
7390 Type *ScalarTy = DataTy->getScalarType();
7391
7392 // The backend can't handle a single element vector w/o CFCMOV.
7393 if (isa<VectorType>(DataTy) &&
7394 cast<FixedVectorType>(DataTy)->getNumElements() == 1)
7395 return ST->hasCF() &&
7396 hasConditionalLoadStoreForType(ScalarTy, /*IsStore=*/true);
7397
7398 return isLegalMaskedLoadStore(ScalarTy, ST);
7399}
7400
7401bool X86TTIImpl::isLegalNTLoad(Type *DataType, Align Alignment) const {
7402 unsigned DataSize = DL.getTypeStoreSize(DataType);
7403 // The only supported nontemporal loads are for aligned vectors of 16 or 32
7404 // bytes. Note that 32-byte nontemporal vector loads are supported by AVX2
7405 // (the equivalent stores only require AVX).
7406 if (Alignment >= DataSize && (DataSize == 16 || DataSize == 32))
7407 return DataSize == 16 ? ST->hasSSE1() : ST->hasAVX2();
7408
7409 return false;
7410}
7411
7412bool X86TTIImpl::isLegalNTStore(Type *DataType, Align Alignment) const {
7413 unsigned DataSize = DL.getTypeStoreSize(DataType);
7414
7415 // SSE4A supports nontemporal stores of float and double at arbitrary
7416 // alignment.
7417 if (ST->hasSSE4A() && (DataType->isFloatTy() || DataType->isDoubleTy()))
7418 return true;
7419
7420 // Besides the SSE4A subtarget exception above, only aligned stores are
7421 // available nontemporaly on any other subtarget. And only stores with a size
7422 // of 4..32 bytes (powers of 2, only) are permitted.
7423 if (Alignment < DataSize || DataSize < 4 || DataSize > 32 ||
7424 !isPowerOf2_32(DataSize))
7425 return false;
7426
7427 // 32-byte vector nontemporal stores are supported by AVX (the equivalent
7428 // loads require AVX2).
7429 if (DataSize == 32)
7430 return ST->hasAVX();
7431 if (DataSize == 16)
7432 return ST->hasSSE1();
7433 return true;
7434}
7435
7437 ElementCount NumElements) const {
7438 // movddup
7439 return ST->hasSSE3() && !NumElements.isScalable() &&
7440 NumElements.getFixedValue() == 2 &&
7441 ElementTy == Type::getDoubleTy(ElementTy->getContext());
7442}
7443
7444bool X86TTIImpl::isLegalMaskedExpandLoad(Type *DataTy, Align Alignment) const {
7445 if (!isa<VectorType>(DataTy))
7446 return false;
7447
7448 if (!ST->hasAVX512())
7449 return false;
7450
7451 // The backend can't handle a single element vector.
7452 if (cast<FixedVectorType>(DataTy)->getNumElements() == 1)
7453 return false;
7454
7455 Type *ScalarTy = cast<VectorType>(DataTy)->getElementType();
7456
7457 if (ScalarTy->isFloatTy() || ScalarTy->isDoubleTy())
7458 return true;
7459
7460 if (!ScalarTy->isIntegerTy())
7461 return false;
7462
7463 unsigned IntWidth = ScalarTy->getIntegerBitWidth();
7464 return IntWidth == 32 || IntWidth == 64 ||
7465 ((IntWidth == 8 || IntWidth == 16) && ST->hasVBMI2());
7466}
7467
7469 Align Alignment) const {
7470 return isLegalMaskedExpandLoad(DataTy, Alignment);
7471}
7472
7473bool X86TTIImpl::supportsGather() const {
7474 // Some CPUs have better gather performance than others.
7475 // TODO: Remove the explicit ST->hasAVX512()?, That would mean we would only
7476 // enable gather with a -march.
7477 return ST->hasAVX512() || (ST->hasFastGather() && ST->hasAVX2());
7478}
7479
7481 Align Alignment) const {
7482 // Gather / Scatter for vector 2 is not profitable on KNL / SKX
7483 // Vector-4 of gather/scatter instruction does not exist on KNL. We can extend
7484 // it to 8 elements, but zeroing upper bits of the mask vector will add more
7485 // instructions. Right now we give the scalar cost of vector-4 for KNL. TODO:
7486 // Check, maybe the gather/scatter instruction is better in the VariableMask
7487 // case.
7488 unsigned NumElts = cast<FixedVectorType>(VTy)->getNumElements();
7489 return NumElts == 1 ||
7490 (ST->hasAVX512() && (NumElts == 2 || (NumElts == 4 && !ST->hasVLX())));
7491}
7492
7494 Align Alignment) const {
7495 Type *ScalarTy = DataTy->getScalarType();
7496 if (ScalarTy->isPointerTy())
7497 return true;
7498
7499 if (ScalarTy->isFloatTy() || ScalarTy->isDoubleTy())
7500 return true;
7501
7502 if (!ScalarTy->isIntegerTy())
7503 return false;
7504
7505 unsigned IntWidth = ScalarTy->getIntegerBitWidth();
7506 return IntWidth == 32 || IntWidth == 64;
7507}
7508
7509bool X86TTIImpl::isLegalMaskedGather(Type *DataTy, Align Alignment) const {
7510 if (!supportsGather() || !ST->preferGather())
7511 return false;
7512 return isLegalMaskedGatherScatter(DataTy, Alignment);
7513}
7514
7515bool X86TTIImpl::isLegalAltInstr(VectorType *VecTy, unsigned Opcode0,
7516 unsigned Opcode1,
7517 const SmallBitVector &OpcodeMask,
7518 ArrayRef<const Value *> Scalars) const {
7519 // ADDSUBPS 4xf32 SSE3
7520 // VADDSUBPS 4xf32 AVX
7521 // VADDSUBPS 8xf32 AVX2
7522 // ADDSUBPD 2xf64 SSE3
7523 // VADDSUBPD 2xf64 AVX
7524 // VADDSUBPD 4xf64 AVX2
7525
7526 unsigned NumElements = cast<FixedVectorType>(VecTy)->getNumElements();
7527 assert(OpcodeMask.size() == NumElements && "Mask and VecTy are incompatible");
7528 if (!isPowerOf2_32(NumElements))
7529 return false;
7530 // Check the opcode pattern. We apply the mask on the opcode arguments and
7531 // then check if it is what we expect.
7532 auto IsLaneOrder = [&](unsigned EvenOpc, unsigned OddOpc) {
7533 return all_of(seq<unsigned>(0, NumElements), [&](unsigned Lane) {
7534 return (OpcodeMask.test(Lane) ? Opcode1 : Opcode0) ==
7535 (Lane % 2 == 0 ? EvenOpc : OddOpc);
7536 });
7537 };
7538 // We expect FSub for even lanes and FAdd for odd lanes.
7539 const bool IsAddSub = IsLaneOrder(Instruction::FSub, Instruction::FAdd);
7540 // Now check that the pattern is supported by the target ISA.
7541 Type *ElemTy = cast<VectorType>(VecTy)->getElementType();
7542 if (IsAddSub && ST->hasSSE3() &&
7543 ((ElemTy->isFloatTy() && NumElements % 4 == 0) ||
7544 (ElemTy->isDoubleTy() && NumElements % 2 == 0)))
7545 return true;
7546 // The multiplication is fused into every lane: fmaddsub (the even lanes
7547 // subtract and the odd lanes add the product) or fmsubadd (the other way
7548 // round). The subtracted product is the first operand of the subtraction.
7549 using namespace PatternMatch;
7550 auto IsFusedWithFMul = [](const Value *V) {
7551 const auto *I = dyn_cast<Instruction>(V);
7552 if (!I || !I->hasAllowContract())
7553 return false;
7554 auto IsFMul = [&](const Value *Op) {
7555 return match(Op,
7557 cast<Instruction>(Op)->getParent() == I->getParent();
7558 };
7559 return IsFMul(I->getOperand(0)) ||
7560 (I->getOpcode() == Instruction::FAdd && IsFMul(I->getOperand(1)));
7561 };
7562 return ST->hasFMA() && !Scalars.empty() &&
7563 (ElemTy->isFloatTy() || ElemTy->isDoubleTy()) &&
7564 (IsAddSub || IsLaneOrder(Instruction::FAdd, Instruction::FSub)) &&
7565 all_of(Scalars, IsFusedWithFMul);
7566}
7567
7568bool X86TTIImpl::isLegalMaskedScatter(Type *DataType, Align Alignment) const {
7569 // AVX2 doesn't support scatter
7570 if (!ST->hasAVX512() || !ST->preferScatter())
7571 return false;
7572 return isLegalMaskedGatherScatter(DataType, Alignment);
7573}
7574
7575bool X86TTIImpl::hasDivRemOp(Type *DataType, bool IsSigned) const {
7576 EVT VT = TLI->getValueType(DL, DataType);
7577 return TLI->isOperationLegal(IsSigned ? ISD::SDIVREM : ISD::UDIVREM, VT);
7578}
7579
7581 // FDIV is always expensive, even if it has a very low uop count.
7582 // TODO: Still necessary for recent CPUs with low latency/throughput fdiv?
7583 if (I->getOpcode() == Instruction::FDiv)
7584 return true;
7585
7587}
7588
7589bool X86TTIImpl::isFCmpOrdCheaperThanFCmpZero(Type *Ty) const { return false; }
7590
7592 const Function *Callee) const {
7593 const TargetMachine &TM = getTLI()->getTargetMachine();
7594
7595 // Work this as a subsetting of subtarget features.
7596 const X86Subtarget &CallerSubtarget = TM.getSubtarget<X86Subtarget>(*Caller);
7597 const X86Subtarget &CalleeSubtarget = TM.getSubtarget<X86Subtarget>(*Callee);
7598 const FeatureBitset &CallerBits = CallerSubtarget.getFeatureBits();
7599 const FeatureBitset &CalleeBits = CalleeSubtarget.getFeatureBits();
7600
7601 // Check whether callee features are a subset of caller features
7602 // (apart from the ignore list).
7603 const FeatureBitset &InlineIgnoreFeatures =
7604 CallerSubtarget.getInlineIgnoreFeatures();
7605 FeatureBitset RealCallerBits = CallerBits & ~InlineIgnoreFeatures;
7606 FeatureBitset RealCalleeBits = CalleeBits & ~InlineIgnoreFeatures;
7607 if ((RealCallerBits & RealCalleeBits) != RealCalleeBits)
7608 return false;
7609
7610 // If the features are not exactly the same (or there is a difference in
7611 // AVX512 register usage), we need to additionally check for calls
7612 // that may become ABI-incompatible as a result of inlining.
7613 if (RealCallerBits == RealCalleeBits &&
7614 CallerSubtarget.useAVX512Regs() == CalleeSubtarget.useAVX512Regs())
7615 return true;
7616
7617 for (const Instruction &I : instructions(Callee)) {
7618 if (const auto *CB = dyn_cast<CallBase>(&I)) {
7619 // Having more target features is fine for inline ASM and intrinsics.
7620 if (CB->isInlineAsm() || CB->getIntrinsicID() != Intrinsic::not_intrinsic)
7621 continue;
7622
7624 for (Value *Arg : CB->args())
7625 Types.push_back(Arg->getType());
7626 if (!CB->getType()->isVoidTy())
7627 Types.push_back(CB->getType());
7628
7629 // Simple types are always ABI compatible.
7630 auto IsSimpleTy = [](Type *Ty) {
7631 return !Ty->isVectorTy() && !Ty->isAggregateType();
7632 };
7633 if (all_of(Types, IsSimpleTy))
7634 continue;
7635
7636 // Do a precise compatibility check.
7637 if (!areTypesABICompatible(Caller, Callee, Types))
7638 return false;
7639 }
7640 }
7641 return true;
7642}
7643
7645 const Function *Callee,
7646 ArrayRef<Type *> Types) const {
7647 const TargetMachine &TM = getTLI()->getTargetMachine();
7648 const TargetLowering *CallerTLI =
7649 TM.getSubtargetImpl(*Caller)->getTargetLowering();
7650 const TargetLowering *CalleeTLI =
7651 TM.getSubtargetImpl(*Callee)->getTargetLowering();
7652
7653 LLVMContext &Ctx = Caller->getContext();
7654 const DataLayout &DL = Caller->getDataLayout();
7655 CallingConv::ID CC = Callee->getCallingConv();
7656 return all_of(Types, [&](Type *Ty) {
7657 SmallVector<EVT> VTs;
7658 ComputeValueVTs(*CallerTLI, DL, Ty, VTs);
7659 return all_of(VTs, [&](EVT VT) {
7660 return CallerTLI->getRegisterTypeForCallingConv(Ctx, CC, VT) ==
7661 CalleeTLI->getRegisterTypeForCallingConv(Ctx, CC, VT);
7662 });
7663 });
7664}
7665
7667X86TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
7669 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
7670 Options.NumLoadsPerBlock = IsZeroCmp ? 2 : 1;
7671 // All GPR and vector loads can be unaligned.
7672 Options.AllowOverlappingLoads = true;
7673 if (IsZeroCmp) {
7674 // Only enable vector loads for equality comparison. Right now the vector
7675 // version is not as fast for three way compare (see #33329).
7676 const unsigned PreferredWidth = ST->getPreferVectorWidth();
7677 if (PreferredWidth >= 512 && ST->hasAVX512())
7678 Options.LoadSizes.push_back(64);
7679 if (PreferredWidth >= 256 && ST->hasAVX()) Options.LoadSizes.push_back(32);
7680 if (PreferredWidth >= 128 && ST->hasSSE2()) Options.LoadSizes.push_back(16);
7681 }
7682 if (ST->is64Bit()) {
7683 Options.LoadSizes.push_back(8);
7684 }
7685 Options.LoadSizes.push_back(4);
7686 Options.LoadSizes.push_back(2);
7687 Options.LoadSizes.push_back(1);
7688 return Options;
7689}
7690
7692 return supportsGather();
7693}
7694
7696 return false;
7697}
7698
7700 // TODO: We expect this to be beneficial regardless of arch,
7701 // but there are currently some unexplained performance artifacts on Atom.
7702 // As a temporary solution, disable on Atom.
7703 return !(ST->isAtom());
7704}
7705
7707 switch (II->getIntrinsicID()) {
7708 default:
7709 return true;
7710 case Intrinsic::vector_reduce_and:
7711 case Intrinsic::vector_reduce_or:
7712 case Intrinsic::vector_reduce_xor:
7713 case Intrinsic::vector_reduce_mul:
7714 case Intrinsic::vector_reduce_smax:
7715 case Intrinsic::vector_reduce_smin:
7716 case Intrinsic::vector_reduce_umax:
7717 case Intrinsic::vector_reduce_umin:
7718 return false;
7719 }
7720}
7721
7722// Get estimation for interleaved load/store operations and strided load.
7723// \p Indices contains indices for strided load.
7724// \p Factor - the factor of interleaving.
7725// AVX-512 provides 3-src shuffles that significantly reduces the cost.
7727 unsigned Opcode, FixedVectorType *VecTy, unsigned Factor,
7728 ArrayRef<unsigned> Indices, Align Alignment, unsigned AddressSpace,
7729 TTI::TargetCostKind CostKind, bool UseMaskForCond,
7730 bool UseMaskForGaps) const {
7731 // VecTy for interleave memop is <VF*Factor x Elt>.
7732 // So, for VF=4, Interleave Factor = 3, Element type = i32 we have
7733 // VecTy = <12 x i32>.
7734
7735 // Calculate the number of memory operations (NumOfMemOps), required
7736 // for load/store the VecTy.
7737 MVT LegalVT = getTypeLegalizationCost(VecTy).second;
7738 unsigned VecTySize = DL.getTypeStoreSize(VecTy);
7739 unsigned LegalVTSize = LegalVT.getStoreSize();
7740 unsigned NumOfMemOps = (VecTySize + LegalVTSize - 1) / LegalVTSize;
7741
7742 // Get the cost of one memory operation.
7743 auto *SingleMemOpTy = FixedVectorType::get(VecTy->getElementType(),
7744 LegalVT.getVectorNumElements());
7745 InstructionCost MemOpCost;
7746 bool UseMaskedMemOp = UseMaskForCond || UseMaskForGaps;
7747 if (UseMaskedMemOp) {
7748 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
7749 : Intrinsic::masked_store;
7750 MemOpCost = getMaskedMemoryOpCost(
7751 {IID, SingleMemOpTy, Alignment, AddressSpace}, CostKind);
7752 } else
7753 MemOpCost = getMemoryOpCost(Opcode, SingleMemOpTy, Alignment, AddressSpace,
7754 CostKind);
7755
7756 unsigned VF = VecTy->getNumElements() / Factor;
7757 MVT VT =
7758 MVT::getVectorVT(TLI->getSimpleValueType(DL, VecTy->getScalarType()), VF);
7759
7760 InstructionCost MaskCost;
7761 if (UseMaskedMemOp) {
7762 APInt DemandedLoadStoreElts = APInt::getZero(VecTy->getNumElements());
7763 for (unsigned Index : Indices) {
7764 assert(Index < Factor && "Invalid index for interleaved memory op");
7765 for (unsigned Elm = 0; Elm < VF; Elm++)
7766 DemandedLoadStoreElts.setBit(Index + Elm * Factor);
7767 }
7768
7769 Type *I1Type = Type::getInt1Ty(VecTy->getContext());
7770
7771 MaskCost = getReplicationShuffleCost(
7772 I1Type, Factor, VF,
7773 UseMaskForGaps ? DemandedLoadStoreElts
7775 CostKind);
7776
7777 // The Gaps mask is invariant and created outside the loop, therefore the
7778 // cost of creating it is not accounted for here. However if we have both
7779 // a MaskForGaps and some other mask that guards the execution of the
7780 // memory access, we need to account for the cost of And-ing the two masks
7781 // inside the loop.
7782 if (UseMaskForGaps) {
7783 auto *MaskVT = FixedVectorType::get(I1Type, VecTy->getNumElements());
7784 MaskCost += getArithmeticInstrCost(BinaryOperator::And, MaskVT, CostKind);
7785 }
7786 }
7787
7788 if (Opcode == Instruction::Load) {
7789 // The tables (AVX512InterleavedLoadTbl and AVX512InterleavedStoreTbl)
7790 // contain the cost of the optimized shuffle sequence that the
7791 // X86InterleavedAccess pass will generate.
7792 // The cost of loads and stores are computed separately from the table.
7793
7794 // X86InterleavedAccess support only the following interleaved-access group.
7795 static const CostTblEntry AVX512InterleavedLoadTbl[] = {
7796 {3, MVT::v16i8, 12}, //(load 48i8 and) deinterleave into 3 x 16i8
7797 {3, MVT::v32i8, 14}, //(load 96i8 and) deinterleave into 3 x 32i8
7798 {3, MVT::v64i8, 22}, //(load 96i8 and) deinterleave into 3 x 32i8
7799 };
7800
7801 if (const auto *Entry =
7802 CostTableLookup(AVX512InterleavedLoadTbl, Factor, VT))
7803 return MaskCost + NumOfMemOps * MemOpCost + Entry->Cost;
7804 //If an entry does not exist, fallback to the default implementation.
7805
7806 // Kind of shuffle depends on number of loaded values.
7807 // If we load the entire data in one register, we can use a 1-src shuffle.
7808 // Otherwise, we'll merge 2 sources in each operation.
7809 TTI::ShuffleKind ShuffleKind =
7810 (NumOfMemOps > 1) ? TTI::SK_PermuteTwoSrc : TTI::SK_PermuteSingleSrc;
7811
7812 InstructionCost ShuffleCost = getShuffleCost(
7813 ShuffleKind, SingleMemOpTy, SingleMemOpTy, CostKind, {}, 0, nullptr);
7814
7815 unsigned NumOfLoadsInInterleaveGrp =
7816 Indices.size() ? Indices.size() : Factor;
7817 auto *ResultTy = FixedVectorType::get(VecTy->getElementType(),
7818 VecTy->getNumElements() / Factor);
7819 InstructionCost NumOfResults =
7820 getTypeLegalizationCost(ResultTy).first * NumOfLoadsInInterleaveGrp;
7821
7822 // About a half of the loads may be folded in shuffles when we have only
7823 // one result. If we have more than one result, or the loads are masked,
7824 // we do not fold loads at all.
7825 unsigned NumOfUnfoldedLoads =
7826 UseMaskedMemOp || NumOfResults > 1 ? NumOfMemOps : NumOfMemOps / 2;
7827
7828 // Get a number of shuffle operations per result.
7829 unsigned NumOfShufflesPerResult =
7830 std::max((unsigned)1, (unsigned)(NumOfMemOps - 1));
7831
7832 // The SK_MergeTwoSrc shuffle clobbers one of src operands.
7833 // When we have more than one destination, we need additional instructions
7834 // to keep sources.
7835 InstructionCost NumOfMoves = 0;
7836 if (NumOfResults > 1 && ShuffleKind == TTI::SK_PermuteTwoSrc)
7837 NumOfMoves = NumOfResults * NumOfShufflesPerResult / 2;
7838
7839 InstructionCost Cost = NumOfResults * NumOfShufflesPerResult * ShuffleCost +
7840 MaskCost + NumOfUnfoldedLoads * MemOpCost +
7841 NumOfMoves;
7842
7843 return Cost;
7844 }
7845
7846 // Store.
7847 assert(Opcode == Instruction::Store &&
7848 "Expected Store Instruction at this point");
7849 // X86InterleavedAccess support only the following interleaved-access group.
7850 static const CostTblEntry AVX512InterleavedStoreTbl[] = {
7851 {3, MVT::v16i8, 12}, // interleave 3 x 16i8 into 48i8 (and store)
7852 {3, MVT::v32i8, 14}, // interleave 3 x 32i8 into 96i8 (and store)
7853 {3, MVT::v64i8, 26}, // interleave 3 x 64i8 into 96i8 (and store)
7854
7855 {4, MVT::v8i8, 10}, // interleave 4 x 8i8 into 32i8 (and store)
7856 {4, MVT::v16i8, 11}, // interleave 4 x 16i8 into 64i8 (and store)
7857 {4, MVT::v32i8, 14}, // interleave 4 x 32i8 into 128i8 (and store)
7858 {4, MVT::v64i8, 24} // interleave 4 x 32i8 into 256i8 (and store)
7859 };
7860
7861 if (const auto *Entry =
7862 CostTableLookup(AVX512InterleavedStoreTbl, Factor, VT))
7863 return MaskCost + NumOfMemOps * MemOpCost + Entry->Cost;
7864 //If an entry does not exist, fallback to the default implementation.
7865
7866 // There is no strided stores meanwhile. And store can't be folded in
7867 // shuffle.
7868 unsigned NumOfSources = Factor; // The number of values to be merged.
7869 InstructionCost ShuffleCost =
7870 getShuffleCost(TTI::SK_PermuteTwoSrc, SingleMemOpTy, SingleMemOpTy,
7871 CostKind, {}, 0, nullptr);
7872 unsigned NumOfShufflesPerStore = NumOfSources - 1;
7873
7874 // The SK_MergeTwoSrc shuffle clobbers one of src operands.
7875 // We need additional instructions to keep sources.
7876 unsigned NumOfMoves = NumOfMemOps * NumOfShufflesPerStore / 2;
7878 MaskCost +
7879 NumOfMemOps * (MemOpCost + NumOfShufflesPerStore * ShuffleCost) +
7880 NumOfMoves;
7881 return Cost;
7882}
7883
7885 unsigned Opcode, Type *BaseTy, unsigned Factor, ArrayRef<unsigned> Indices,
7886 Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,
7887 bool UseMaskForCond, bool UseMaskForGaps) const {
7888 auto *VecTy = cast<FixedVectorType>(BaseTy);
7889
7890 auto isSupportedOnAVX512 = [&](Type *VecTy) {
7891 Type *EltTy = cast<VectorType>(VecTy)->getElementType();
7892 if (EltTy->isFloatTy() || EltTy->isDoubleTy() || EltTy->isIntegerTy(64) ||
7893 EltTy->isIntegerTy(32) || EltTy->isPointerTy())
7894 return true;
7895 if (EltTy->isIntegerTy(16) || EltTy->isIntegerTy(8) || EltTy->isHalfTy())
7896 return ST->hasBWI();
7897 if (EltTy->isBFloatTy())
7898 return ST->hasBF16();
7899 return false;
7900 };
7901 if (ST->hasAVX512() && isSupportedOnAVX512(VecTy))
7903 Opcode, VecTy, Factor, Indices, Alignment,
7904 AddressSpace, CostKind, UseMaskForCond, UseMaskForGaps);
7905
7906 if (UseMaskForCond || UseMaskForGaps)
7907 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
7908 Alignment, AddressSpace, CostKind,
7909 UseMaskForCond, UseMaskForGaps);
7910
7911 // Get estimation for interleaved load/store operations for SSE-AVX2.
7912 // As opposed to AVX-512, SSE-AVX2 do not have generic shuffles that allow
7913 // computing the cost using a generic formula as a function of generic
7914 // shuffles. We therefore use a lookup table instead, filled according to
7915 // the instruction sequences that codegen currently generates.
7916
7917 // VecTy for interleave memop is <VF*Factor x Elt>.
7918 // So, for VF=4, Interleave Factor = 3, Element type = i32 we have
7919 // VecTy = <12 x i32>.
7920 MVT LegalVT = getTypeLegalizationCost(VecTy).second;
7921
7922 // This function can be called with VecTy=<6xi128>, Factor=3, in which case
7923 // the VF=2, while v2i128 is an unsupported MVT vector type
7924 // (see MachineValueType.h::getVectorVT()).
7925 if (!LegalVT.isVector())
7926 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
7927 Alignment, AddressSpace, CostKind);
7928
7929 unsigned VF = VecTy->getNumElements() / Factor;
7930 Type *ScalarTy = VecTy->getElementType();
7931 // Deduplicate entries, model floats/pointers as appropriately-sized integers.
7932 if (!ScalarTy->isIntegerTy())
7933 ScalarTy =
7934 Type::getIntNTy(ScalarTy->getContext(), DL.getTypeSizeInBits(ScalarTy));
7935
7936 // Get the cost of all the memory operations.
7937 // FIXME: discount dead loads.
7938 InstructionCost MemOpCosts =
7939 getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace, CostKind);
7940
7941 auto *VT = FixedVectorType::get(ScalarTy, VF);
7942 EVT ETy = TLI->getValueType(DL, VT);
7943 if (!ETy.isSimple())
7944 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
7945 Alignment, AddressSpace, CostKind);
7946
7947 // TODO: Complete for other data-types and strides.
7948 // Each combination of Stride, element bit width and VF results in a different
7949 // sequence; The cost tables are therefore accessed with:
7950 // Factor (stride) and VectorType=VFxiN.
7951 // The Cost accounts only for the shuffle sequence;
7952 // The cost of the loads/stores is accounted for separately.
7953 //
7954 static const CostTblEntry AVX2InterleavedLoadTbl[] = {
7955 {2, MVT::v2i8, 2}, // (load 4i8 and) deinterleave into 2 x 2i8
7956 {2, MVT::v4i8, 2}, // (load 8i8 and) deinterleave into 2 x 4i8
7957 {2, MVT::v8i8, 2}, // (load 16i8 and) deinterleave into 2 x 8i8
7958 {2, MVT::v16i8, 4}, // (load 32i8 and) deinterleave into 2 x 16i8
7959 {2, MVT::v32i8, 6}, // (load 64i8 and) deinterleave into 2 x 32i8
7960
7961 {2, MVT::v8i16, 6}, // (load 16i16 and) deinterleave into 2 x 8i16
7962 {2, MVT::v16i16, 9}, // (load 32i16 and) deinterleave into 2 x 16i16
7963 {2, MVT::v32i16, 18}, // (load 64i16 and) deinterleave into 2 x 32i16
7964
7965 {2, MVT::v8i32, 4}, // (load 16i32 and) deinterleave into 2 x 8i32
7966 {2, MVT::v16i32, 8}, // (load 32i32 and) deinterleave into 2 x 16i32
7967 {2, MVT::v32i32, 16}, // (load 64i32 and) deinterleave into 2 x 32i32
7968
7969 {2, MVT::v4i64, 4}, // (load 8i64 and) deinterleave into 2 x 4i64
7970 {2, MVT::v8i64, 8}, // (load 16i64 and) deinterleave into 2 x 8i64
7971 {2, MVT::v16i64, 16}, // (load 32i64 and) deinterleave into 2 x 16i64
7972 {2, MVT::v32i64, 32}, // (load 64i64 and) deinterleave into 2 x 32i64
7973
7974 {3, MVT::v2i8, 3}, // (load 6i8 and) deinterleave into 3 x 2i8
7975 {3, MVT::v4i8, 3}, // (load 12i8 and) deinterleave into 3 x 4i8
7976 {3, MVT::v8i8, 6}, // (load 24i8 and) deinterleave into 3 x 8i8
7977 {3, MVT::v16i8, 11}, // (load 48i8 and) deinterleave into 3 x 16i8
7978 {3, MVT::v32i8, 14}, // (load 96i8 and) deinterleave into 3 x 32i8
7979
7980 {3, MVT::v2i16, 5}, // (load 6i16 and) deinterleave into 3 x 2i16
7981 {3, MVT::v4i16, 7}, // (load 12i16 and) deinterleave into 3 x 4i16
7982 {3, MVT::v8i16, 9}, // (load 24i16 and) deinterleave into 3 x 8i16
7983 {3, MVT::v16i16, 28}, // (load 48i16 and) deinterleave into 3 x 16i16
7984 {3, MVT::v32i16, 56}, // (load 96i16 and) deinterleave into 3 x 32i16
7985
7986 {3, MVT::v2i32, 3}, // (load 6i32 and) deinterleave into 3 x 2i32
7987 {3, MVT::v4i32, 3}, // (load 12i32 and) deinterleave into 3 x 4i32
7988 {3, MVT::v8i32, 7}, // (load 24i32 and) deinterleave into 3 x 8i32
7989 {3, MVT::v16i32, 14}, // (load 48i32 and) deinterleave into 3 x 16i32
7990 {3, MVT::v32i32, 32}, // (load 96i32 and) deinterleave into 3 x 32i32
7991
7992 {3, MVT::v2i64, 1}, // (load 6i64 and) deinterleave into 3 x 2i64
7993 {3, MVT::v4i64, 5}, // (load 12i64 and) deinterleave into 3 x 4i64
7994 {3, MVT::v8i64, 10}, // (load 24i64 and) deinterleave into 3 x 8i64
7995 {3, MVT::v16i64, 20}, // (load 48i64 and) deinterleave into 3 x 16i64
7996
7997 {4, MVT::v2i8, 4}, // (load 8i8 and) deinterleave into 4 x 2i8
7998 {4, MVT::v4i8, 4}, // (load 16i8 and) deinterleave into 4 x 4i8
7999 {4, MVT::v8i8, 12}, // (load 32i8 and) deinterleave into 4 x 8i8
8000 {4, MVT::v16i8, 24}, // (load 64i8 and) deinterleave into 4 x 16i8
8001 {4, MVT::v32i8, 56}, // (load 128i8 and) deinterleave into 4 x 32i8
8002
8003 {4, MVT::v2i16, 6}, // (load 8i16 and) deinterleave into 4 x 2i16
8004 {4, MVT::v4i16, 17}, // (load 16i16 and) deinterleave into 4 x 4i16
8005 {4, MVT::v8i16, 33}, // (load 32i16 and) deinterleave into 4 x 8i16
8006 {4, MVT::v16i16, 75}, // (load 64i16 and) deinterleave into 4 x 16i16
8007 {4, MVT::v32i16, 150}, // (load 128i16 and) deinterleave into 4 x 32i16
8008
8009 {4, MVT::v2i32, 4}, // (load 8i32 and) deinterleave into 4 x 2i32
8010 {4, MVT::v4i32, 8}, // (load 16i32 and) deinterleave into 4 x 4i32
8011 {4, MVT::v8i32, 16}, // (load 32i32 and) deinterleave into 4 x 8i32
8012 {4, MVT::v16i32, 32}, // (load 64i32 and) deinterleave into 4 x 16i32
8013 {4, MVT::v32i32, 68}, // (load 128i32 and) deinterleave into 4 x 32i32
8014
8015 {4, MVT::v2i64, 6}, // (load 8i64 and) deinterleave into 4 x 2i64
8016 {4, MVT::v4i64, 8}, // (load 16i64 and) deinterleave into 4 x 4i64
8017 {4, MVT::v8i64, 20}, // (load 32i64 and) deinterleave into 4 x 8i64
8018 {4, MVT::v16i64, 40}, // (load 64i64 and) deinterleave into 4 x 16i64
8019
8020 {6, MVT::v2i8, 6}, // (load 12i8 and) deinterleave into 6 x 2i8
8021 {6, MVT::v4i8, 14}, // (load 24i8 and) deinterleave into 6 x 4i8
8022 {6, MVT::v8i8, 18}, // (load 48i8 and) deinterleave into 6 x 8i8
8023 {6, MVT::v16i8, 43}, // (load 96i8 and) deinterleave into 6 x 16i8
8024 {6, MVT::v32i8, 82}, // (load 192i8 and) deinterleave into 6 x 32i8
8025
8026 {6, MVT::v2i16, 13}, // (load 12i16 and) deinterleave into 6 x 2i16
8027 {6, MVT::v4i16, 9}, // (load 24i16 and) deinterleave into 6 x 4i16
8028 {6, MVT::v8i16, 39}, // (load 48i16 and) deinterleave into 6 x 8i16
8029 {6, MVT::v16i16, 106}, // (load 96i16 and) deinterleave into 6 x 16i16
8030 {6, MVT::v32i16, 212}, // (load 192i16 and) deinterleave into 6 x 32i16
8031
8032 {6, MVT::v2i32, 6}, // (load 12i32 and) deinterleave into 6 x 2i32
8033 {6, MVT::v4i32, 15}, // (load 24i32 and) deinterleave into 6 x 4i32
8034 {6, MVT::v8i32, 31}, // (load 48i32 and) deinterleave into 6 x 8i32
8035 {6, MVT::v16i32, 64}, // (load 96i32 and) deinterleave into 6 x 16i32
8036
8037 {6, MVT::v2i64, 6}, // (load 12i64 and) deinterleave into 6 x 2i64
8038 {6, MVT::v4i64, 18}, // (load 24i64 and) deinterleave into 6 x 4i64
8039 {6, MVT::v8i64, 36}, // (load 48i64 and) deinterleave into 6 x 8i64
8040
8041 {8, MVT::v8i32, 40} // (load 64i32 and) deinterleave into 8 x 8i32
8042 };
8043
8044 static const CostTblEntry SSSE3InterleavedLoadTbl[] = {
8045 {2, MVT::v4i16, 2}, // (load 8i16 and) deinterleave into 2 x 4i16
8046 };
8047
8048 static const CostTblEntry SSE2InterleavedLoadTbl[] = {
8049 {2, MVT::v2i16, 2}, // (load 4i16 and) deinterleave into 2 x 2i16
8050 {2, MVT::v4i16, 7}, // (load 8i16 and) deinterleave into 2 x 4i16
8051
8052 {2, MVT::v2i32, 2}, // (load 4i32 and) deinterleave into 2 x 2i32
8053 {2, MVT::v4i32, 2}, // (load 8i32 and) deinterleave into 2 x 4i32
8054
8055 {2, MVT::v2i64, 2}, // (load 4i64 and) deinterleave into 2 x 2i64
8056 };
8057
8058 static const CostTblEntry AVX2InterleavedStoreTbl[] = {
8059 {2, MVT::v16i8, 3}, // interleave 2 x 16i8 into 32i8 (and store)
8060 {2, MVT::v32i8, 4}, // interleave 2 x 32i8 into 64i8 (and store)
8061
8062 {2, MVT::v8i16, 3}, // interleave 2 x 8i16 into 16i16 (and store)
8063 {2, MVT::v16i16, 4}, // interleave 2 x 16i16 into 32i16 (and store)
8064 {2, MVT::v32i16, 8}, // interleave 2 x 32i16 into 64i16 (and store)
8065
8066 {2, MVT::v4i32, 2}, // interleave 2 x 4i32 into 8i32 (and store)
8067 {2, MVT::v8i32, 4}, // interleave 2 x 8i32 into 16i32 (and store)
8068 {2, MVT::v16i32, 8}, // interleave 2 x 16i32 into 32i32 (and store)
8069 {2, MVT::v32i32, 16}, // interleave 2 x 32i32 into 64i32 (and store)
8070
8071 {2, MVT::v2i64, 2}, // interleave 2 x 2i64 into 4i64 (and store)
8072 {2, MVT::v4i64, 4}, // interleave 2 x 4i64 into 8i64 (and store)
8073 {2, MVT::v8i64, 8}, // interleave 2 x 8i64 into 16i64 (and store)
8074 {2, MVT::v16i64, 16}, // interleave 2 x 16i64 into 32i64 (and store)
8075 {2, MVT::v32i64, 32}, // interleave 2 x 32i64 into 64i64 (and store)
8076
8077 {3, MVT::v2i8, 4}, // interleave 3 x 2i8 into 6i8 (and store)
8078 {3, MVT::v4i8, 4}, // interleave 3 x 4i8 into 12i8 (and store)
8079 {3, MVT::v8i8, 6}, // interleave 3 x 8i8 into 24i8 (and store)
8080 {3, MVT::v16i8, 11}, // interleave 3 x 16i8 into 48i8 (and store)
8081 {3, MVT::v32i8, 13}, // interleave 3 x 32i8 into 96i8 (and store)
8082
8083 {3, MVT::v2i16, 4}, // interleave 3 x 2i16 into 6i16 (and store)
8084 {3, MVT::v4i16, 6}, // interleave 3 x 4i16 into 12i16 (and store)
8085 {3, MVT::v8i16, 12}, // interleave 3 x 8i16 into 24i16 (and store)
8086 {3, MVT::v16i16, 27}, // interleave 3 x 16i16 into 48i16 (and store)
8087 {3, MVT::v32i16, 54}, // interleave 3 x 32i16 into 96i16 (and store)
8088
8089 {3, MVT::v2i32, 4}, // interleave 3 x 2i32 into 6i32 (and store)
8090 {3, MVT::v4i32, 5}, // interleave 3 x 4i32 into 12i32 (and store)
8091 {3, MVT::v8i32, 11}, // interleave 3 x 8i32 into 24i32 (and store)
8092 {3, MVT::v16i32, 22}, // interleave 3 x 16i32 into 48i32 (and store)
8093 {3, MVT::v32i32, 48}, // interleave 3 x 32i32 into 96i32 (and store)
8094
8095 {3, MVT::v2i64, 4}, // interleave 3 x 2i64 into 6i64 (and store)
8096 {3, MVT::v4i64, 6}, // interleave 3 x 4i64 into 12i64 (and store)
8097 {3, MVT::v8i64, 12}, // interleave 3 x 8i64 into 24i64 (and store)
8098 {3, MVT::v16i64, 24}, // interleave 3 x 16i64 into 48i64 (and store)
8099
8100 {4, MVT::v2i8, 4}, // interleave 4 x 2i8 into 8i8 (and store)
8101 {4, MVT::v4i8, 4}, // interleave 4 x 4i8 into 16i8 (and store)
8102 {4, MVT::v8i8, 4}, // interleave 4 x 8i8 into 32i8 (and store)
8103 {4, MVT::v16i8, 8}, // interleave 4 x 16i8 into 64i8 (and store)
8104 {4, MVT::v32i8, 12}, // interleave 4 x 32i8 into 128i8 (and store)
8105
8106 {4, MVT::v2i16, 2}, // interleave 4 x 2i16 into 8i16 (and store)
8107 {4, MVT::v4i16, 6}, // interleave 4 x 4i16 into 16i16 (and store)
8108 {4, MVT::v8i16, 10}, // interleave 4 x 8i16 into 32i16 (and store)
8109 {4, MVT::v16i16, 32}, // interleave 4 x 16i16 into 64i16 (and store)
8110 {4, MVT::v32i16, 64}, // interleave 4 x 32i16 into 128i16 (and store)
8111
8112 {4, MVT::v2i32, 5}, // interleave 4 x 2i32 into 8i32 (and store)
8113 {4, MVT::v4i32, 6}, // interleave 4 x 4i32 into 16i32 (and store)
8114 {4, MVT::v8i32, 16}, // interleave 4 x 8i32 into 32i32 (and store)
8115 {4, MVT::v16i32, 32}, // interleave 4 x 16i32 into 64i32 (and store)
8116 {4, MVT::v32i32, 64}, // interleave 4 x 32i32 into 128i32 (and store)
8117
8118 {4, MVT::v2i64, 6}, // interleave 4 x 2i64 into 8i64 (and store)
8119 {4, MVT::v4i64, 8}, // interleave 4 x 4i64 into 16i64 (and store)
8120 {4, MVT::v8i64, 20}, // interleave 4 x 8i64 into 32i64 (and store)
8121 {4, MVT::v16i64, 40}, // interleave 4 x 16i64 into 64i64 (and store)
8122
8123 {6, MVT::v2i8, 7}, // interleave 6 x 2i8 into 12i8 (and store)
8124 {6, MVT::v4i8, 9}, // interleave 6 x 4i8 into 24i8 (and store)
8125 {6, MVT::v8i8, 16}, // interleave 6 x 8i8 into 48i8 (and store)
8126 {6, MVT::v16i8, 27}, // interleave 6 x 16i8 into 96i8 (and store)
8127 {6, MVT::v32i8, 90}, // interleave 6 x 32i8 into 192i8 (and store)
8128
8129 {6, MVT::v2i16, 10}, // interleave 6 x 2i16 into 12i16 (and store)
8130 {6, MVT::v4i16, 15}, // interleave 6 x 4i16 into 24i16 (and store)
8131 {6, MVT::v8i16, 21}, // interleave 6 x 8i16 into 48i16 (and store)
8132 {6, MVT::v16i16, 58}, // interleave 6 x 16i16 into 96i16 (and store)
8133 {6, MVT::v32i16, 90}, // interleave 6 x 32i16 into 192i16 (and store)
8134
8135 {6, MVT::v2i32, 9}, // interleave 6 x 2i32 into 12i32 (and store)
8136 {6, MVT::v4i32, 12}, // interleave 6 x 4i32 into 24i32 (and store)
8137 {6, MVT::v8i32, 33}, // interleave 6 x 8i32 into 48i32 (and store)
8138 {6, MVT::v16i32, 66}, // interleave 6 x 16i32 into 96i32 (and store)
8139
8140 {6, MVT::v2i64, 8}, // interleave 6 x 2i64 into 12i64 (and store)
8141 {6, MVT::v4i64, 15}, // interleave 6 x 4i64 into 24i64 (and store)
8142 {6, MVT::v8i64, 30}, // interleave 6 x 8i64 into 48i64 (and store)
8143 };
8144
8145 static const CostTblEntry SSE2InterleavedStoreTbl[] = {
8146 {2, MVT::v2i8, 1}, // interleave 2 x 2i8 into 4i8 (and store)
8147 {2, MVT::v4i8, 1}, // interleave 2 x 4i8 into 8i8 (and store)
8148 {2, MVT::v8i8, 1}, // interleave 2 x 8i8 into 16i8 (and store)
8149
8150 {2, MVT::v2i16, 1}, // interleave 2 x 2i16 into 4i16 (and store)
8151 {2, MVT::v4i16, 1}, // interleave 2 x 4i16 into 8i16 (and store)
8152
8153 {2, MVT::v2i32, 1}, // interleave 2 x 2i32 into 4i32 (and store)
8154 };
8155
8156 if (Opcode == Instruction::Load) {
8157 auto GetDiscountedCost = [Factor, NumMembers = Indices.size(),
8158 MemOpCosts](const CostTblEntry *Entry) {
8159 // NOTE: this is just an approximation!
8160 // It can over/under -estimate the cost!
8161 return MemOpCosts + divideCeil(NumMembers * Entry->Cost, Factor);
8162 };
8163
8164 if (ST->hasAVX2())
8165 if (const auto *Entry = CostTableLookup(AVX2InterleavedLoadTbl, Factor,
8166 ETy.getSimpleVT()))
8167 return GetDiscountedCost(Entry);
8168
8169 if (ST->hasSSSE3())
8170 if (const auto *Entry = CostTableLookup(SSSE3InterleavedLoadTbl, Factor,
8171 ETy.getSimpleVT()))
8172 return GetDiscountedCost(Entry);
8173
8174 if (ST->hasSSE2())
8175 if (const auto *Entry = CostTableLookup(SSE2InterleavedLoadTbl, Factor,
8176 ETy.getSimpleVT()))
8177 return GetDiscountedCost(Entry);
8178 } else {
8179 assert(Opcode == Instruction::Store &&
8180 "Expected Store Instruction at this point");
8181 assert((!Indices.size() || Indices.size() == Factor) &&
8182 "Interleaved store only supports fully-interleaved groups.");
8183 if (ST->hasAVX2())
8184 if (const auto *Entry = CostTableLookup(AVX2InterleavedStoreTbl, Factor,
8185 ETy.getSimpleVT()))
8186 return MemOpCosts + Entry->Cost;
8187
8188 if (ST->hasSSE2())
8189 if (const auto *Entry = CostTableLookup(SSE2InterleavedStoreTbl, Factor,
8190 ETy.getSimpleVT()))
8191 return MemOpCosts + Entry->Cost;
8192 }
8193
8194 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
8195 Alignment, AddressSpace, CostKind,
8196 UseMaskForCond, UseMaskForGaps);
8197}
8198
8200 StackOffset BaseOffset,
8201 bool HasBaseReg, int64_t Scale,
8202 unsigned AddrSpace) const {
8203 // Scaling factors are not free at all.
8204 // An indexed folded instruction, i.e., inst (reg1, reg2, scale),
8205 // will take 2 allocations in the out of order engine instead of 1
8206 // for plain addressing mode, i.e. inst (reg1).
8207 // E.g.,
8208 // vaddps (%rsi,%rdx), %ymm0, %ymm1
8209 // Requires two allocations (one for the load, one for the computation)
8210 // whereas:
8211 // vaddps (%rsi), %ymm0, %ymm1
8212 // Requires just 1 allocation, i.e., freeing allocations for other operations
8213 // and having less micro operations to execute.
8214 //
8215 // For some X86 architectures, this is even worse because for instance for
8216 // stores, the complex addressing mode forces the instruction to use the
8217 // "load" ports instead of the dedicated "store" port.
8218 // E.g., on Haswell:
8219 // vmovaps %ymm1, (%r8, %rdi) can use port 2 or 3.
8220 // vmovaps %ymm1, (%r8) can use port 2, 3, or 7.
8222 AM.BaseGV = BaseGV;
8223 AM.BaseOffs = BaseOffset.getFixed();
8224 AM.HasBaseReg = HasBaseReg;
8225 AM.Scale = Scale;
8226 AM.ScalableOffset = BaseOffset.getScalable();
8227 if (getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace))
8228 // Scale represents reg2 * scale, thus account for 1
8229 // as soon as we use a second register.
8230 return AM.Scale != 0;
8232}
8233
8235 // TODO: Hook MispredictPenalty of SchedMachineModel into this.
8236 return 14;
8237}
8238
8240 unsigned Bits = Ty->getScalarSizeInBits();
8241
8242 // XOP has v16i8/v8i16/v4i32/v2i64 variable vector shifts.
8243 // Splitting for v32i8/v16i16 on XOP+AVX2 targets is still preferred.
8244 if (ST->hasXOP() && (Bits == 8 || Bits == 16 || Bits == 32 || Bits == 64))
8245 return false;
8246
8247 // AVX2 has vpsllv[dq] instructions (and other shifts) that make variable
8248 // shifts just as cheap as scalar ones.
8249 if (ST->hasAVX2() && (Bits == 32 || Bits == 64))
8250 return false;
8251
8252 // AVX512BW has shifts such as vpsllvw.
8253 if (ST->hasBWI() && Bits == 16)
8254 return false;
8255
8256 // Otherwise, it's significantly cheaper to shift by a scalar amount than by a
8257 // fully general vector.
8258 return true;
8259}
8260
8261unsigned X86TTIImpl::getStoreMinimumVF(unsigned VF, Type *ScalarMemTy,
8262 Type *ScalarValTy, Align Alignment,
8263 unsigned AddrSpace) const {
8264 if (ST->hasF16C() && ScalarMemTy->isHalfTy()) {
8265 return 4;
8266 }
8267 return BaseT::getStoreMinimumVF(VF, ScalarMemTy, ScalarValTy, Alignment,
8268 AddrSpace);
8269}
8270
8272 SmallVectorImpl<Use *> &Ops) const {
8273 using namespace llvm::PatternMatch;
8274
8275 if (I->getOpcode() == Instruction::And &&
8276 (ST->hasBMI() || (I->getType()->isVectorTy() && ST->hasSSE2()))) {
8277 for (auto &Op : I->operands()) {
8278 // (and X, (not Y)) -> (andn X, Y)
8279 if (match(Op.get(), m_Not(m_Value())) && !I->getType()->isIntegerTy(8)) {
8280 Ops.push_back(&Op);
8281 return true;
8282 }
8283 // (and X, (splat (not Y))) -> (andn X, (splat Y))
8284 if (match(Op.get(),
8286 m_Value(), m_ZeroMask()))) {
8287 Use &InsertElt = cast<Instruction>(Op)->getOperandUse(0);
8288 Use &Not = cast<Instruction>(InsertElt)->getOperandUse(1);
8289 Ops.push_back(&Not);
8290 Ops.push_back(&InsertElt);
8291 Ops.push_back(&Op);
8292 return true;
8293 }
8294 }
8295 }
8296
8297 FixedVectorType *VTy = dyn_cast<FixedVectorType>(I->getType());
8298 if (!VTy)
8299 return false;
8300
8301 if (I->getOpcode() == Instruction::Mul &&
8302 VTy->getElementType()->isIntegerTy(64)) {
8303 for (auto &Op : I->operands()) {
8304 // Make sure we are not already sinking this operand
8305 if (any_of(Ops, [&](Use *U) { return U->get() == Op; }))
8306 continue;
8307
8308 // Look for PMULDQ pattern where the input is a sext_inreg from vXi32 or
8309 // the PMULUDQ pattern where the input is a zext_inreg from vXi32.
8310 if (ST->hasSSE41() &&
8311 match(Op.get(), m_AShr(m_Shl(m_Value(), m_SpecificInt(32)),
8312 m_SpecificInt(32)))) {
8313 Ops.push_back(&cast<Instruction>(Op)->getOperandUse(0));
8314 Ops.push_back(&Op);
8315 } else if (ST->hasSSE2() &&
8316 match(Op.get(),
8317 m_And(m_Value(), m_SpecificInt(UINT64_C(0xffffffff))))) {
8318 Ops.push_back(&Op);
8319 }
8320 }
8321
8322 return !Ops.empty();
8323 }
8324
8325 // A uniform shift amount in a vector shift or funnel shift may be much
8326 // cheaper than a generic variable vector shift, so make that pattern visible
8327 // to SDAG by sinking the shuffle instruction next to the shift.
8328 int ShiftAmountOpNum = -1;
8329 if (I->isShift())
8330 ShiftAmountOpNum = 1;
8331 else if (auto *II = dyn_cast<IntrinsicInst>(I)) {
8332 if (II->getIntrinsicID() == Intrinsic::fshl ||
8333 II->getIntrinsicID() == Intrinsic::fshr)
8334 ShiftAmountOpNum = 2;
8335 }
8336
8337 if (ShiftAmountOpNum == -1)
8338 return false;
8339
8340 auto *Shuf = dyn_cast<ShuffleVectorInst>(I->getOperand(ShiftAmountOpNum));
8341 if (Shuf && getSplatIndex(Shuf->getShuffleMask()) >= 0 &&
8342 isVectorShiftByScalarCheap(I->getType())) {
8343 Ops.push_back(&I->getOperandUse(ShiftAmountOpNum));
8344 return true;
8345 }
8346
8347 return false;
8348}
8349
8351 bool HasEGPR = ST->hasEGPR();
8352 const TargetMachine &TM = getTLI()->getTargetMachine();
8353
8354 for (User *U : F.users()) {
8356 if (!CB || CB->getCalledOperand() != &F)
8357 continue;
8358 Function *CallerFunc = CB->getFunction();
8359 if (TM.getSubtarget<X86Subtarget>(*CallerFunc).hasEGPR() != HasEGPR)
8360 return false;
8361 }
8362
8363 return true;
8364}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t Imm
Expand Atomic instructions
This file provides a helper that implements much of the TTI interface in terms of the target-independ...
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Cost tables and simple lookup functions.
Hexagon Common GEP
iv users
Definition IVUsers.cpp:48
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static LVOptions Options
Definition LVOptions.cpp:25
CostTblEntryT< CostKindCosts > CostKindTblEntry
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
#define P(N)
int64_t C1
RISCVCC::CondCode CC
This file implements the SmallBitVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
This file describes how to lower LLVM code to machine code.
This pass exposes codegen information to IR-level passes.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
static InstructionCost getPredicateFanoutCost(const X86TTIImpl &TTI, Type *DataVTy, Type *MaskVTy)
static bool isFoldedIntoRsqrtEstimate(const Value *V, const X86TargetLowering &TLI, MVT VT, TTI::TargetCostKind CostKind)
Returns true if V is the square root, divided into with the reciprocal allowed, and the target replac...
static bool isLegalMaskedLoadStore(Type *ScalarTy, const X86Subtarget *ST)
TypeConversionCostTblEntryT< CostKindCosts > TypeConversionCostKindTblEntry
This file a TargetTransformInfoImplBase conforming object specific to the X86 target machine.
static const fltSemantics & IEEEsingle()
Definition APFloat.h:304
static const fltSemantics & IEEEdouble()
Definition APFloat.h:305
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
Definition APFloat.cpp:334
Class for arbitrary precision integers.
Definition APInt.h:78
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition APInt.h:230
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1057
unsigned popcount() const
Count the number of bits set.
Definition APInt.h:1690
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
Definition APInt.h:1350
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:367
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
Definition APInt.h:254
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:376
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1508
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
Definition APInt.cpp:1086
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
Definition APInt.h:829
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:196
LLVM_ABI APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
Definition APInt.cpp:478
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
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 getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
TTI::ShuffleKind improveShuffleKindFromMask(TTI::ShuffleKind Kind, ArrayRef< int > Mask, VectorType *SrcTy, int &Index, VectorType *&SubTy) const
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, Instruction *I=nullptr, int64_t ScalableOffset=0) const override
unsigned getStoreMinimumVF(unsigned VF, Type *ScalarMemTy, Type *ScalarValTy, Align Alignment, unsigned AddrSpace) const override
InstructionCost getScalarizationOverhead(VectorType *InTy, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) 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 *CtxI=nullptr) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) 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 getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
InstructionCost getReplicationShuffleCost(Type *EltTy, int ReplicationFactor, int VF, const APInt &DemandedDstElts, TTI::TargetCostKind CostKind) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *, const SCEV *, TTI::TargetCostKind) const override
InstructionCost getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef< const Value * > Operands, TTI::TargetCostKind CostKind, Type *AccessType) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) 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
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Value * getCalledOperand() const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:743
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:764
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:748
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:751
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:768
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:317
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
Container class for subtarget features.
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:843
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:731
static unsigned getPointerOperandIndex()
static InstructionCost getInvalid(CostType Val=0)
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:338
const SmallVectorImpl< Type * > & getArgTypes() const
const SmallVectorImpl< const Value * > & getArgs() const
const IntrinsicInst * getInst() const
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
Machine Value Type.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
Information for memory intrinsic cost model.
This class represents an analyzed expression in the program.
The main scalar evolution driver.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
bool test(unsigned Idx) const
Returns true if bit Idx is set.
size_type size() const
Returns the number of bits in this bitvector.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:31
static StackOffset getScalable(int64_t Scalable)
Definition TypeSize.h:41
static StackOffset getFixed(int64_t Fixed)
Definition TypeSize.h:40
int getRecipEstimateSqrtEnabled(EVT VT, const Function &F) const
Return a ReciprocalEstimate enum value for a square root of the given type based on the function's at...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
virtual const TargetLowering * getTargetLowering() const
bool isStridedAccess(const SCEV *Ptr) const
unsigned minRequiredElementSize(const Value *Val, bool &isSigned) const
const SCEVConstant * getConstantStrideStep(ScalarEvolution *SE, const SCEV *Ptr) const
virtual bool isExpensiveToSpeculativelyExecute(const Instruction *I) const
virtual InstructionCost getPointersChainCost(ArrayRef< const Value * > Ptrs, const Value *Base, const TTI::PointersChainInfo &Info, Type *AccessTy, const TTI::TargetCostKind CostKind) const
MaskKind
Some targets only support masked load/store with a constant mask.
TargetCostKind
The kind of cost model.
@ TCK_RecipThroughput
Reciprocal throughput.
@ TCK_CodeSize
Instruction code size.
@ TCK_SizeAndLatency
The weighted sum of size and latency.
@ TCK_Latency
The latency of instruction.
static bool requiresOrderedReduction(std::optional< FastMathFlags > FMF)
A helper function to determine the type of reduction algorithm used for a given Opcode and set of Fas...
PopcntSupportKind
Flags indicating the kind of support for population count.
llvm::VectorInstrContext VectorInstrContext
@ TCC_Free
Expected to fold away in lowering.
@ TCC_Basic
The cost of a typical 'add' instruction.
ShuffleKind
The various kinds of shuffle patterns for vector queries.
@ SK_InsertSubvector
InsertSubvector. Index indicates start offset.
@ SK_Select
Selects elements from the corresponding lane of either source operand.
@ SK_PermuteSingleSrc
Shuffle elements of single source vector with any shuffle mask.
@ SK_Transpose
Transpose two vectors.
@ SK_Splice
Concatenates elements from the first input vector with elements of the second input vector.
@ SK_Broadcast
Broadcast element 0 to all other elements.
@ SK_PermuteTwoSrc
Merge elements from two source vectors into one with any shuffle mask.
@ SK_Reverse
Reverse the order of the vector.
@ SK_ExtractSubvector
ExtractSubvector Index indicates start offset.
CastContextHint
Represents a hint about the context in which a cast is used.
@ None
The cast is not used with a load/store of any kind.
CacheLevel
The possible cache levels.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:352
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:355
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:300
LLVM_ABI unsigned getIntegerBitWidth() const
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:283
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
Definition Type.h:258
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:277
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition Type.h:155
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:147
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:297
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:187
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition Type.h:144
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:130
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:222
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition Type.h:158
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:296
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
LLVM_ABI bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
Definition Type.cpp:61
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:303
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
Definition Type.cpp:277
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
Definition Type.h:222
Type * getContainedType(unsigned i) const
This method is used to implement the type iterator (defined at the end of the file).
Definition Type.h:392
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:276
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
Base class of all SIMD vector types.
static VectorType * getExtendedElementVectorType(VectorType *VTy)
This static method is like getInteger except that the element types are twice as wide as the elements...
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
static VectorType * getDoubleElementsVectorType(VectorType *VTy)
This static method returns a VectorType with twice as many elements as the input type and the same el...
Type * getElementType() const
bool useAVX512Regs() const
bool hasAVX512() const
bool hasAVX2() const
bool useFastCCForInternalCall(Function &F) const override
bool isLegalAltInstr(VectorType *VecTy, unsigned Opcode0, unsigned Opcode1, const SmallBitVector &OpcodeMask, ArrayRef< const Value * > Scalars) const override
InstructionCost getReplicationShuffleCost(Type *EltTy, int ReplicationFactor, int VF, const APInt &DemandedDstElts, TTI::TargetCostKind CostKind) const override
bool isLegalNTLoad(Type *DataType, Align Alignment) const override
std::optional< unsigned > getCacheAssociativity(TargetTransformInfo::CacheLevel Level) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
Try to calculate op costs for min/max reduction operations.
bool isLegalBroadcastLoad(Type *ElementTy, ElementCount NumElements) const override
unsigned getRegisterClassForType(bool Vector, Type *Ty) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
Get memory intrinsic cost based on arguments.
unsigned getMaxInterleaveFactor(ElementCount VF, bool HasUnorderedReductions) 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, std::optional< FastMathFlags > FMF) const override
bool isLegalNTStore(Type *DataType, Align Alignment) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
InstructionCost getInterleavedMemoryOpCostAVX512(unsigned Opcode, FixedVectorType *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override
bool isVectorShiftByScalarCheap(Type *Ty) const override
bool isLegalMaskedGather(Type *DataType, Align Alignment) const override
bool shouldExpandReduction(const IntrinsicInst *II) const override
InstructionCost getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, StackOffset BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace) const override
Return the cost of the scaling factor used in the addressing mode represented by AM for this target,...
unsigned getAtomicMemIntrinsicMaxElementSize() 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 *CtxI=nullptr) const override
bool forceScalarizeMaskedGather(VectorType *VTy, Align Alignment) const override
InstructionCost getBranchMispredictPenalty() const override
bool isExpensiveToSpeculativelyExecute(const Instruction *I) const override
bool hasConditionalLoadStoreForType(Type *Ty, bool IsStore) const override
InstructionCost getAltInstrCost(VectorType *VecTy, unsigned Opcode0, unsigned Opcode1, const SmallBitVector &OpcodeMask, TTI::TargetCostKind CostKind, ArrayRef< const Value * > Scalars) const override
bool isLegalMaskedStore(Type *DataType, Align Alignment, unsigned AddressSpace, TTI::MaskKind MaskKind=TTI::MaskKind::VariableOrConstantMask) const override
std::optional< unsigned > getCacheSize(TargetTransformInfo::CacheLevel Level) const override
bool isLegalMaskedGatherScatter(Type *DataType, Align Alignment) const
bool isLegalMaskedLoad(Type *DataType, Align Alignment, unsigned AddressSpace, TTI::MaskKind MaskKind=TTI::MaskKind::VariableOrConstantMask) const override
bool enableInterleavedAccessVectorization() const override
unsigned getLoadStoreVecRegBitWidth(unsigned AS) const override
unsigned getNumberOfRegisters(unsigned ClassID) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
bool isLegalMaskedScatter(Type *DataType, Align Alignment) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
unsigned getStoreMinimumVF(unsigned VF, Type *ScalarMemTy, Type *ScalarValTy, Align Alignment, unsigned AddrSpace) const override
bool hasDivRemOp(Type *DataType, bool IsSigned) const override
bool isLegalMaskedCompressStore(Type *DataType, Align Alignment) const override
InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) const override
bool supportsEfficientVectorElementLoadStore() const override
InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind, Instruction *Inst=nullptr) const override
bool isLegalMaskedExpandLoad(Type *DataType, Align Alignment) const override
TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override
bool isFCmpOrdCheaperThanFCmpZero(Type *Ty) const override
TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override
InstructionCost getPointersChainCost(ArrayRef< const Value * > Ptrs, const Value *Base, const TTI::PointersChainInfo &Info, Type *AccessTy, const TTI::TargetCostKind CostKind) const override
InstructionCost getIntImmCost(int64_t) const
Calculate the cost of materializing a 64-bit value.
InstructionCost getMinMaxCost(Intrinsic::ID IID, Type *Ty, TTI::TargetCostKind CostKind, FastMathFlags FMF) const
InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
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
bool canMacroFuseCmp() const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
InstructionCost getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
bool prefersVectorizedAddressing() const override
bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Type) const override
bool forceScalarizeMaskedScatter(VectorType *VTy, Align Alignment) const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
Get intrinsic cost based on arguments.
bool isProfitableToSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops) const override
InstructionCost getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
Estimate the overhead of scalarizing an instruction.
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getGatherScatterOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
Calculate the cost of Gather / Scatter operation.
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
InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE, const SCEV *Ptr, TTI::TargetCostKind CostKind) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) const override
bool hasSqrtEstimate(EVT VT, bool Reciprocal) const
Return true if VT has the rsqrt* based estimate of the square root, or of its reciprocal if Reciproca...
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
Definition TypeSize.h:181
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:201
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:169
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
Definition TypeSize.h:253
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI APInt ScaleBitMask(const APInt &A, unsigned NewBitWidth, bool MatchAllBits=false)
Splat/Merge neighboring bits to widen/narrow the bitmask represented by.
Definition APInt.cpp:3043
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
ISD namespace - This namespace contains an enum which represents all of the SelectionDAG node types a...
Definition ISDOpcodes.h:26
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition ISDOpcodes.h:43
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:845
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
Definition ISDOpcodes.h:47
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:805
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:906
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:420
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:765
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
Definition ISDOpcodes.h:282
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:796
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:814
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:870
@ PARTIAL_REDUCE_FMLA
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:377
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:822
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:351
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:714
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:581
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:876
@ FMINNUM
FMINNUM/FMAXNUM - Same semantics as the llvm.minnum/maxnum intrinsics.
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:359
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:745
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ FMINIMUM
FMINIMUM/FMAXIMUM - Same semantics as the llvm.minimum/maximum intrinsics.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:952
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
Definition ISDOpcodes.h:813
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:985
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:882
@ PARTIAL_REDUCE_SUMLA
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:368
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::AShr > m_AShr(const LHS &L, const RHS &R)
ap_match< APInt > m_APIntAllowPoison(const APInt *&Res)
Match APInt while allowing poison in splat vector constants.
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
auto m_Value()
Match an arbitrary value and ignore it.
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::FDiv > m_FDiv(const LHS &L, const RHS &R)
AllowFmf_match< T, FastMathFlags::AllowContract > m_AllowContract(const T &SubPattern)
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.
constexpr auto not_equal_to(T &&Arg)
Functor variant of std::not_equal_to that can be used as a UnaryPredicate in functional algorithms li...
Definition STLExtras.h:2196
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
Definition CostTable.h:36
InstructionCost Cost
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
@ Known
Known to have no common set bits.
LLVM_ABI void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl< EVT > &ValueVTs, SmallVectorImpl< EVT > *MemVTs=nullptr, SmallVectorImpl< TypeSize > *Offsets=nullptr, TypeSize StartingOffset=TypeSize::getZero())
ComputeValueVTs - Given an LLVM IR type, compute a sequence of EVTs that represent all the individual...
Definition Analysis.cpp:121
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:546
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
LLVM_ABI unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return the number of times the sign bit of the register is replicated into the other bits.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
Definition MathExtras.h:380
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
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...
Definition Casting.h:547
constexpr int PoisonMaskElem
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
TargetTransformInfo TTI
DWARFExpression::Operation Op
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1901
CostTblEntryT< uint16_t > CostTblEntry
Definition CostTable.h:31
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
Definition STLExtras.h:2035
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:206
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
const TypeConversionCostTblEntryT< CostType > * ConvertCostTableLookup(ArrayRef< TypeConversionCostTblEntryT< CostType > > Tbl, int ISD, MVT Dst, MVT Src)
Find in type conversion cost table.
Definition CostTable.h:67
LLVM_ABI int getSplatIndex(ArrayRef< int > Mask)
If all non-negative Mask elements are the same value, return that value.
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Cost Table Entry.
Definition CostTable.h:26
Extended Value Type.
Definition ValueTypes.h:35
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
unsigned Insns
TODO: Some of these could be merged.
Returns options for expansion of memcmp. IsZeroCmp is.
Describe known properties for a set of pointers.
Type Conversion Cost Table.
Definition CostTable.h:56