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?
75 unsigned RecipThroughputCost = ~0U;
76 unsigned LatencyCost = ~0U;
77 unsigned CodeSizeCost = ~0U;
78 unsigned SizeAndLatencyCost = ~0U;
79
80 std::optional<unsigned>
82 unsigned Cost = ~0U;
83 switch (Kind) {
86 break;
89 break;
92 break;
95 break;
96 }
97 if (Cost == ~0U)
98 return std::nullopt;
99 return Cost;
100 }
101};
104
106X86TTIImpl::getPopcntSupport(unsigned TyWidth) const {
107 assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
108 // TODO: Currently the __builtin_popcount() implementation using SSE3
109 // instructions is inefficient. Once the problem is fixed, we should
110 // call ST->hasSSE3() instead of ST->hasPOPCNT().
111 return ST->hasPOPCNT() ? TTI::PSK_FastHardware : TTI::PSK_Software;
112}
113
114std::optional<unsigned> X86TTIImpl::getCacheSize(
116 switch (Level) {
118 // - Penryn
119 // - Nehalem
120 // - Westmere
121 // - Sandy Bridge
122 // - Ivy Bridge
123 // - Haswell
124 // - Broadwell
125 // - Skylake
126 // - Kabylake
127 return 32 * 1024; // 32 KiB
129 // - Penryn
130 // - Nehalem
131 // - Westmere
132 // - Sandy Bridge
133 // - Ivy Bridge
134 // - Haswell
135 // - Broadwell
136 // - Skylake
137 // - Kabylake
138 return 256 * 1024; // 256 KiB
139 }
140
141 llvm_unreachable("Unknown TargetTransformInfo::CacheLevel");
142}
143
144std::optional<unsigned> X86TTIImpl::getCacheAssociativity(
146 // - Penryn
147 // - Nehalem
148 // - Westmere
149 // - Sandy Bridge
150 // - Ivy Bridge
151 // - Haswell
152 // - Broadwell
153 // - Skylake
154 // - Kabylake
155 switch (Level) {
157 [[fallthrough]];
159 return 8;
160 }
161
162 llvm_unreachable("Unknown TargetTransformInfo::CacheLevel");
163}
164
166
168 return Vector ? VectorClass
169 : Ty && Ty->isFloatingPointTy() ? ScalarFPClass
170 : GPRClass;
171}
172
173unsigned X86TTIImpl::getNumberOfRegisters(unsigned ClassID) const {
174 if (ClassID == VectorClass && !ST->hasSSE1())
175 return 0;
176
177 if (!ST->is64Bit())
178 return 8;
179
180 if ((ClassID == GPRClass && ST->hasEGPR()) ||
181 (ClassID != GPRClass && ST->hasAVX512()))
182 return 32;
183
184 return 16;
185}
186
188 if (!ST->hasCF())
189 return false;
190 if (!Ty)
191 return true;
192 // Conditional faulting is supported by CFCMOV, which only accepts
193 // 16/32/64-bit operands.
194 // TODO: Support f32/f64 with VMOVSS/VMOVSD with zero mask when it's
195 // profitable.
196 auto *VTy = dyn_cast<FixedVectorType>(Ty);
197 if (!Ty->isIntegerTy() && (!VTy || VTy->getNumElements() != 1))
198 return false;
199 auto *ScalarTy = Ty->getScalarType();
200 switch (cast<IntegerType>(ScalarTy)->getBitWidth()) {
201 default:
202 return false;
203 case 16:
204 case 32:
205 case 64:
206 return true;
207 }
208}
209
212 unsigned PreferVectorWidth = ST->getPreferVectorWidth();
213 switch (K) {
215 return TypeSize::getFixed(ST->is64Bit() ? 64 : 32);
217 if (ST->hasAVX512() && PreferVectorWidth >= 512)
218 return TypeSize::getFixed(512);
219 if (ST->hasAVX() && PreferVectorWidth >= 256)
220 return TypeSize::getFixed(256);
221 if (ST->hasSSE1() && PreferVectorWidth >= 128)
222 return TypeSize::getFixed(128);
223 return TypeSize::getFixed(0);
225 return TypeSize::getScalable(0);
226 }
227
228 llvm_unreachable("Unsupported register kind");
229}
230
235
237 bool HasUnorderedReductions) const {
238 // If the loop will not be vectorized, don't interleave the loop.
239 // Let regular unroll to unroll the loop, which saves the overflow
240 // check and memory check cost.
241 if (VF.isScalar())
242 return 1;
243
244 if (ST->isAtom())
245 return 1;
246
247 // Sandybridge and Haswell have multiple execution ports and pipelined
248 // vector units.
249 if (ST->hasAVX())
250 return 4;
251
252 return 2;
253}
254
256 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
258 ArrayRef<const Value *> Args, const Instruction *CtxI) const {
259
260 // vXi8 multiplications are always promoted to vXi16.
261 // Sub-128-bit types can be extended/packed more efficiently.
262 if (Opcode == Instruction::Mul && Ty->isVectorTy() &&
263 Ty->getPrimitiveSizeInBits() <= 64 && Ty->getScalarSizeInBits() == 8) {
264 Type *WideVecTy =
266 return getCastInstrCost(Instruction::ZExt, WideVecTy, Ty,
268 CostKind) +
269 getCastInstrCost(Instruction::Trunc, Ty, WideVecTy,
271 CostKind) +
272 getArithmeticInstrCost(Opcode, WideVecTy, CostKind, Op1Info, Op2Info);
273 }
274
275 // Legalize the type.
276 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
277
278 int ISD = TLI->InstructionOpcodeToISD(Opcode);
279 assert(ISD && "Invalid opcode");
280
281 if (ISD == ISD::MUL && Args.size() == 2 && LT.second.isVector() &&
282 (LT.second.getScalarType() == MVT::i32 ||
283 LT.second.getScalarType() == MVT::i64)) {
284 // Check if the operands can be represented as a smaller datatype.
285 bool Op1Signed = false, Op2Signed = false;
286 unsigned Op1MinSize = BaseT::minRequiredElementSize(Args[0], Op1Signed);
287 unsigned Op2MinSize = BaseT::minRequiredElementSize(Args[1], Op2Signed);
288 unsigned OpMinSize = std::max(Op1MinSize, Op2MinSize);
289 bool SignedMode = Op1Signed || Op2Signed;
290
291 // If both vXi32 are representable as i15 and at least one is constant,
292 // zero-extended, or sign-extended from vXi16 (or less pre-SSE41) then we
293 // can treat this as PMADDWD which has the same costs as a vXi16 multiply.
294 if (OpMinSize <= 15 && !ST->isPMADDWDSlow() &&
295 LT.second.getScalarType() == MVT::i32) {
296 bool Op1Constant =
297 isa<ConstantDataVector>(Args[0]) || isa<ConstantVector>(Args[0]);
298 bool Op2Constant =
299 isa<ConstantDataVector>(Args[1]) || isa<ConstantVector>(Args[1]);
300 bool Op1Sext = isa<SExtInst>(Args[0]) &&
301 (Op1MinSize == 15 || (Op1MinSize < 15 && !ST->hasSSE41()));
302 bool Op2Sext = isa<SExtInst>(Args[1]) &&
303 (Op2MinSize == 15 || (Op2MinSize < 15 && !ST->hasSSE41()));
304
305 bool IsZeroExtended = !Op1Signed || !Op2Signed;
306 bool IsConstant = Op1Constant || Op2Constant;
307 bool IsSext = Op1Sext || Op2Sext;
308 if (IsConstant || IsZeroExtended || IsSext)
309 LT.second =
310 MVT::getVectorVT(MVT::i16, 2 * LT.second.getVectorNumElements());
311 }
312
313 // Check if the vXi32 operands can be shrunk into a smaller datatype.
314 // This should match the codegen from reduceVMULWidth.
315 // TODO: Make this generic (!ST->SSE41 || ST->isPMULLDSlow()).
316 if (ST->useSLMArithCosts() && LT.second == MVT::v4i32) {
317 if (OpMinSize <= 7)
318 return LT.first * 3; // pmullw/sext
319 if (!SignedMode && OpMinSize <= 8)
320 return LT.first * 3; // pmullw/zext
321 if (OpMinSize <= 15)
322 return LT.first * 5; // pmullw/pmulhw/pshuf
323 if (!SignedMode && OpMinSize <= 16)
324 return LT.first * 5; // pmullw/pmulhw/pshuf
325 }
326
327 // If both vXi64 are representable as (unsigned) i32, then we can perform
328 // the multiple with a single PMULUDQ instruction.
329 // TODO: Add (SSE41+) PMULDQ handling for signed extensions.
330 if (!SignedMode && OpMinSize <= 32 && LT.second.getScalarType() == MVT::i64)
331 ISD = X86ISD::PMULUDQ;
332 }
333
334 // Vector multiply by pow2 will be simplified to shifts.
335 // Vector multiply by -pow2 will be simplified to shifts/negates.
336 if (ISD == ISD::MUL && Op2Info.isConstant() &&
337 (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2())) {
339 getArithmeticInstrCost(Instruction::Shl, Ty, CostKind,
340 Op1Info.getNoProps(), Op2Info.getNoProps());
341 if (Op2Info.isNegatedPowerOf2())
342 Cost += getArithmeticInstrCost(Instruction::Sub, Ty, CostKind);
343 return Cost;
344 }
345
346 // On X86, vector signed division by constants power-of-two are
347 // normally expanded to the sequence SRA + SRL + ADD + SRA.
348 // The OperandValue properties may not be the same as that of the previous
349 // operation; conservatively assume OP_None.
350 if ((ISD == ISD::SDIV || ISD == ISD::SREM) &&
351 Op2Info.isConstant() && Op2Info.isPowerOf2()) {
353 2 * getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
354 Op1Info.getNoProps(), Op2Info.getNoProps());
355 Cost += getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
356 Op1Info.getNoProps(), Op2Info.getNoProps());
357 Cost += getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
358 Op1Info.getNoProps(), Op2Info.getNoProps());
359
360 if (ISD == ISD::SREM) {
361 // For SREM: (X % C) is the equivalent of (X - (X/C)*C)
362 Cost += getArithmeticInstrCost(Instruction::Mul, Ty, CostKind, Op1Info.getNoProps(),
363 Op2Info.getNoProps());
364 Cost += getArithmeticInstrCost(Instruction::Sub, Ty, CostKind, Op1Info.getNoProps(),
365 Op2Info.getNoProps());
366 }
367
368 return Cost;
369 }
370
371 // Vector unsigned division/remainder will be simplified to shifts/masks.
372 if ((ISD == ISD::UDIV || ISD == ISD::UREM) &&
373 Op2Info.isConstant() && Op2Info.isPowerOf2()) {
374 if (ISD == ISD::UDIV)
375 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
376 Op1Info.getNoProps(), Op2Info.getNoProps());
377 // UREM
378 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
379 Op1Info.getNoProps(), Op2Info.getNoProps());
380 }
381
382 // A scalar integer divide/remainder by a constant is not a hardware divide;
383 // it lowers to a magic-number multiply-high plus a few fixup ops. Cost it as
384 // that sequence rather than the generic single-instruction divide, so the
385 // vectorizers do not compare against an artificially cheap scalar lane. The
386 // power-of-two cases are handled above; negated powers of two are left to the
387 // generic handling.
388 if (!Ty->isVectorTy() && Op2Info.isConstant() && !Op2Info.isNegatedPowerOf2() &&
389 (ISD == ISD::UDIV || ISD == ISD::SDIV || ISD == ISD::UREM ||
390 ISD == ISD::SREM)) {
391 unsigned Cost = ISD == ISD::UREM || ISD == ISD::SREM ? 6 : 5;
393 Cost += 2;
394 return LT.first * Cost;
395 }
396
397 static const CostKindTblEntry GFNIUniformConstCostTable[] = {
398 { ISD::SHL, MVT::v16i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
399 { ISD::SRL, MVT::v16i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
400 { ISD::SRA, MVT::v16i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
401 { ISD::SHL, MVT::v32i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
402 { ISD::SRL, MVT::v32i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
403 { ISD::SRA, MVT::v32i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
404 { ISD::SHL, MVT::v64i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
405 { ISD::SRL, MVT::v64i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
406 { ISD::SRA, MVT::v64i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
407 };
408
409 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasGFNI())
410 if (const auto *Entry =
411 CostTableLookup(GFNIUniformConstCostTable, ISD, LT.second))
412 if (auto KindCost = Entry->Cost[CostKind])
413 return LT.first * *KindCost;
414
415 static const CostKindTblEntry AVX512BWUniformConstCostTable[] = {
416 { ISD::SHL, MVT::v16i8, { 1, 7, 2, 3 } }, // psllw + pand.
417 { ISD::SRL, MVT::v16i8, { 1, 7, 2, 3 } }, // psrlw + pand.
418 { ISD::SRA, MVT::v16i8, { 1, 8, 4, 5 } }, // psrlw, pand, pxor, psubb.
419 { ISD::SHL, MVT::v32i8, { 1, 8, 2, 3 } }, // psllw + pand.
420 { ISD::SRL, MVT::v32i8, { 1, 8, 2, 3 } }, // psrlw + pand.
421 { ISD::SRA, MVT::v32i8, { 1, 9, 4, 5 } }, // psrlw, pand, pxor, psubb.
422 { ISD::SHL, MVT::v64i8, { 1, 8, 2, 3 } }, // psllw + pand.
423 { ISD::SRL, MVT::v64i8, { 1, 8, 2, 3 } }, // psrlw + pand.
424 { ISD::SRA, MVT::v64i8, { 1, 9, 4, 6 } }, // psrlw, pand, pxor, psubb.
425
426 { ISD::SHL, MVT::v16i16, { 1, 1, 1, 1 } }, // psllw
427 { ISD::SRL, MVT::v16i16, { 1, 1, 1, 1 } }, // psrlw
428 { ISD::SRA, MVT::v16i16, { 1, 1, 1, 1 } }, // psrlw
429 { ISD::SHL, MVT::v32i16, { 1, 1, 1, 1 } }, // psllw
430 { ISD::SRL, MVT::v32i16, { 1, 1, 1, 1 } }, // psrlw
431 { ISD::SRA, MVT::v32i16, { 1, 1, 1, 1 } }, // psrlw
432 };
433
434 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasBWI())
435 if (const auto *Entry =
436 CostTableLookup(AVX512BWUniformConstCostTable, ISD, LT.second))
437 if (auto KindCost = Entry->Cost[CostKind])
438 return LT.first * *KindCost;
439
440 static const CostKindTblEntry AVX512DQUniformConstCostTable[] = {
441 { ISD::SDIV, MVT::v4i64, { 15 } }, // vpmullq-based MULHS sequence
442 { ISD::SREM, MVT::v4i64, { 17 } }, // vpmullq-based MULHS+mul+sub sequence
443 { ISD::SDIV, MVT::v8i64, { 15 } }, // vpmullq-based MULHS sequence
444 { ISD::SREM, MVT::v8i64, { 17 } }, // vpmullq-based MULHS+mul+sub sequence
445 // The remainder's multiply-back is a single vpmullq with DQ, just like the
446 // pmulld the vXi32 entries above rely on. Without DQ it is another
447 // vpmuludq schoolbook, so the AVX512/AVX2 tables charge more.
448 { ISD::UREM, MVT::v4i64, { 17 } }, // MULHU + vpmullq + sub sequence
449 { ISD::UREM, MVT::v8i64, { 17 } }, // MULHU + vpmullq + sub sequence
450 };
451
452 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasDQI())
453 if (const auto *Entry =
454 CostTableLookup(AVX512DQUniformConstCostTable, ISD, LT.second))
455 if (auto KindCost = Entry->Cost[CostKind])
456 return LT.first * *KindCost;
457
458 static const CostKindTblEntry AVX512UniformConstCostTable[] = {
459 { ISD::SHL, MVT::v64i8, { 2, 12, 5, 6 } }, // psllw + pand.
460 { ISD::SRL, MVT::v64i8, { 2, 12, 5, 6 } }, // psrlw + pand.
461 { ISD::SRA, MVT::v64i8, { 3, 10, 12, 12 } }, // psrlw, pand, pxor, psubb.
462
463 { ISD::SHL, MVT::v16i16, { 2, 7, 4, 4 } }, // psllw + split.
464 { ISD::SRL, MVT::v16i16, { 2, 7, 4, 4 } }, // psrlw + split.
465 { ISD::SRA, MVT::v16i16, { 2, 7, 4, 4 } }, // psraw + split.
466
467 { ISD::SHL, MVT::v8i32, { 1, 1, 1, 1 } }, // pslld
468 { ISD::SRL, MVT::v8i32, { 1, 1, 1, 1 } }, // psrld
469 { ISD::SRA, MVT::v8i32, { 1, 1, 1, 1 } }, // psrad
470 { ISD::SHL, MVT::v16i32, { 1, 1, 1, 1 } }, // pslld
471 { ISD::SRL, MVT::v16i32, { 1, 1, 1, 1 } }, // psrld
472 { ISD::SRA, MVT::v16i32, { 1, 1, 1, 1 } }, // psrad
473
474 { ISD::SRA, MVT::v2i64, { 1, 1, 1, 1 } }, // psraq
475 { ISD::SHL, MVT::v4i64, { 1, 1, 1, 1 } }, // psllq
476 { ISD::SRL, MVT::v4i64, { 1, 1, 1, 1 } }, // psrlq
477 { ISD::SRA, MVT::v4i64, { 1, 1, 1, 1 } }, // psraq
478 { ISD::SHL, MVT::v8i64, { 1, 1, 1, 1 } }, // psllq
479 { ISD::SRL, MVT::v8i64, { 1, 1, 1, 1 } }, // psrlq
480 { ISD::SRA, MVT::v8i64, { 1, 1, 1, 1 } }, // psraq
481
482 { ISD::SDIV, MVT::v16i32, { 6 } }, // pmuludq sequence
483 { ISD::SREM, MVT::v16i32, { 8 } }, // pmuludq+mul+sub sequence
484 { ISD::UDIV, MVT::v16i32, { 5 } }, // pmuludq sequence
485 { ISD::UREM, MVT::v16i32, { 7 } }, // pmuludq+mul+sub sequence
486
487 { ISD::UDIV, MVT::v8i64, { 15 } }, // pmuludq-based MULHU sequence
488 { ISD::UREM, MVT::v8i64, { 21 } }, // pmuludq-based MULHU+mul+sub sequence
489 };
490
491 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasAVX512())
492 if (const auto *Entry =
493 CostTableLookup(AVX512UniformConstCostTable, ISD, LT.second))
494 if (auto KindCost = Entry->Cost[CostKind])
495 return LT.first * *KindCost;
496
497 static const CostKindTblEntry AVX2UniformConstCostTable[] = {
498 { ISD::SHL, MVT::v16i8, { 1, 8, 2, 3 } }, // psllw + pand.
499 { ISD::SRL, MVT::v16i8, { 1, 8, 2, 3 } }, // psrlw + pand.
500 { ISD::SRA, MVT::v16i8, { 2, 10, 5, 6 } }, // psrlw, pand, pxor, psubb.
501 { ISD::SHL, MVT::v32i8, { 2, 8, 2, 4 } }, // psllw + pand.
502 { ISD::SRL, MVT::v32i8, { 2, 8, 2, 4 } }, // psrlw + pand.
503 { ISD::SRA, MVT::v32i8, { 3, 10, 5, 9 } }, // psrlw, pand, pxor, psubb.
504
505 { ISD::SHL, MVT::v8i16, { 1, 1, 1, 1 } }, // psllw
506 { ISD::SRL, MVT::v8i16, { 1, 1, 1, 1 } }, // psrlw
507 { ISD::SRA, MVT::v8i16, { 1, 1, 1, 1 } }, // psraw
508 { ISD::SHL, MVT::v16i16,{ 2, 2, 1, 2 } }, // psllw
509 { ISD::SRL, MVT::v16i16,{ 2, 2, 1, 2 } }, // psrlw
510 { ISD::SRA, MVT::v16i16,{ 2, 2, 1, 2 } }, // psraw
511
512 { ISD::SHL, MVT::v4i32, { 1, 1, 1, 1 } }, // pslld
513 { ISD::SRL, MVT::v4i32, { 1, 1, 1, 1 } }, // psrld
514 { ISD::SRA, MVT::v4i32, { 1, 1, 1, 1 } }, // psrad
515 { ISD::SHL, MVT::v8i32, { 2, 2, 1, 2 } }, // pslld
516 { ISD::SRL, MVT::v8i32, { 2, 2, 1, 2 } }, // psrld
517 { ISD::SRA, MVT::v8i32, { 2, 2, 1, 2 } }, // psrad
518
519 { ISD::SHL, MVT::v2i64, { 1, 1, 1, 1 } }, // psllq
520 { ISD::SRL, MVT::v2i64, { 1, 1, 1, 1 } }, // psrlq
521 { ISD::SRA, MVT::v2i64, { 2, 3, 3, 3 } }, // psrad + shuffle.
522 { ISD::SHL, MVT::v4i64, { 2, 2, 1, 2 } }, // psllq
523 { ISD::SRL, MVT::v4i64, { 2, 2, 1, 2 } }, // psrlq
524 { ISD::SRA, MVT::v4i64, { 4, 4, 3, 6 } }, // psrad + shuffle + split.
525
526 { ISD::SDIV, MVT::v8i32, { 6 } }, // pmuludq sequence
527 { ISD::SREM, MVT::v8i32, { 8 } }, // pmuludq+mul+sub sequence
528 { ISD::UDIV, MVT::v8i32, { 5 } }, // pmuludq sequence
529 { ISD::UREM, MVT::v8i32, { 7 } }, // pmuludq+mul+sub sequence
530
531 { ISD::UDIV, MVT::v4i64, { 15 } }, // pmuludq-based MULHU sequence
532 { ISD::UREM, MVT::v4i64, { 21 } }, // pmuludq-based MULHU+mul+sub sequence
533 };
534
535 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasAVX2())
536 if (const auto *Entry =
537 CostTableLookup(AVX2UniformConstCostTable, ISD, LT.second))
538 if (auto KindCost = Entry->Cost[CostKind])
539 return LT.first * *KindCost;
540
541 static const CostKindTblEntry AVXUniformConstCostTable[] = {
542 { ISD::SHL, MVT::v16i8, { 2, 7, 2, 3 } }, // psllw + pand.
543 { ISD::SRL, MVT::v16i8, { 2, 7, 2, 3 } }, // psrlw + pand.
544 { ISD::SRA, MVT::v16i8, { 3, 9, 5, 6 } }, // psrlw, pand, pxor, psubb.
545 { ISD::SHL, MVT::v32i8, { 4, 7, 7, 8 } }, // 2*(psllw + pand) + split.
546 { ISD::SRL, MVT::v32i8, { 4, 7, 7, 8 } }, // 2*(psrlw + pand) + split.
547 { ISD::SRA, MVT::v32i8, { 7, 7, 12, 13 } }, // 2*(psrlw, pand, pxor, psubb) + split.
548
549 { ISD::SHL, MVT::v8i16, { 1, 2, 1, 1 } }, // psllw.
550 { ISD::SRL, MVT::v8i16, { 1, 2, 1, 1 } }, // psrlw.
551 { ISD::SRA, MVT::v8i16, { 1, 2, 1, 1 } }, // psraw.
552 { ISD::SHL, MVT::v16i16,{ 3, 6, 4, 5 } }, // psllw + split.
553 { ISD::SRL, MVT::v16i16,{ 3, 6, 4, 5 } }, // psrlw + split.
554 { ISD::SRA, MVT::v16i16,{ 3, 6, 4, 5 } }, // psraw + split.
555
556 { ISD::SHL, MVT::v4i32, { 1, 2, 1, 1 } }, // pslld.
557 { ISD::SRL, MVT::v4i32, { 1, 2, 1, 1 } }, // psrld.
558 { ISD::SRA, MVT::v4i32, { 1, 2, 1, 1 } }, // psrad.
559 { ISD::SHL, MVT::v8i32, { 3, 6, 4, 5 } }, // pslld + split.
560 { ISD::SRL, MVT::v8i32, { 3, 6, 4, 5 } }, // psrld + split.
561 { ISD::SRA, MVT::v8i32, { 3, 6, 4, 5 } }, // psrad + split.
562
563 { ISD::SHL, MVT::v2i64, { 1, 2, 1, 1 } }, // psllq.
564 { ISD::SRL, MVT::v2i64, { 1, 2, 1, 1 } }, // psrlq.
565 { ISD::SRA, MVT::v2i64, { 2, 3, 3, 3 } }, // psrad + shuffle.
566 { ISD::SHL, MVT::v4i64, { 3, 6, 4, 5 } }, // 2 x psllq + split.
567 { ISD::SRL, MVT::v4i64, { 3, 6, 4, 5 } }, // 2 x psllq + split.
568 { ISD::SRA, MVT::v4i64, { 5, 7, 8, 9 } }, // 2 x psrad + shuffle + split.
569
570 { ISD::SDIV, MVT::v8i32, { 14 } }, // 2*pmuludq sequence + split.
571 { ISD::SREM, MVT::v8i32, { 18 } }, // 2*pmuludq+mul+sub sequence + split.
572 { ISD::UDIV, MVT::v8i32, { 12 } }, // 2*pmuludq sequence + split.
573 { ISD::UREM, MVT::v8i32, { 16 } }, // 2*pmuludq+mul+sub sequence + split.
574 };
575
576 // XOP has faster vXi8 shifts.
577 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasAVX() &&
578 (!ST->hasXOP() || LT.second.getScalarSizeInBits() != 8))
579 if (const auto *Entry =
580 CostTableLookup(AVXUniformConstCostTable, ISD, LT.second))
581 if (auto KindCost = Entry->Cost[CostKind])
582 return LT.first * *KindCost;
583
584 static const CostKindTblEntry SSE2UniformConstCostTable[] = {
585 { ISD::SHL, MVT::v16i8, { 1, 7, 2, 3 } }, // psllw + pand.
586 { ISD::SRL, MVT::v16i8, { 1, 7, 2, 3 } }, // psrlw + pand.
587 { ISD::SRA, MVT::v16i8, { 3, 9, 5, 6 } }, // psrlw, pand, pxor, psubb.
588
589 { ISD::SHL, MVT::v8i16, { 1, 1, 1, 1 } }, // psllw.
590 { ISD::SRL, MVT::v8i16, { 1, 1, 1, 1 } }, // psrlw.
591 { ISD::SRA, MVT::v8i16, { 1, 1, 1, 1 } }, // psraw.
592
593 { ISD::SHL, MVT::v4i32, { 1, 1, 1, 1 } }, // pslld
594 { ISD::SRL, MVT::v4i32, { 1, 1, 1, 1 } }, // psrld.
595 { ISD::SRA, MVT::v4i32, { 1, 1, 1, 1 } }, // psrad.
596
597 { ISD::SHL, MVT::v2i64, { 1, 1, 1, 1 } }, // psllq.
598 { ISD::SRL, MVT::v2i64, { 1, 1, 1, 1 } }, // psrlq.
599 { ISD::SRA, MVT::v2i64, { 3, 5, 6, 6 } }, // 2 x psrad + shuffle.
600
601 { ISD::SDIV, MVT::v4i32, { 6 } }, // pmuludq sequence
602 { ISD::SREM, MVT::v4i32, { 8 } }, // pmuludq+mul+sub sequence
603 { ISD::UDIV, MVT::v4i32, { 5 } }, // pmuludq sequence
604 { ISD::UREM, MVT::v4i32, { 7 } }, // pmuludq+mul+sub sequence
605 };
606
607 // XOP has faster vXi8 shifts.
608 if (Op2Info.isUniform() && Op2Info.isConstant() && ST->hasSSE2() &&
609 (!ST->hasXOP() || LT.second.getScalarSizeInBits() != 8))
610 if (const auto *Entry =
611 CostTableLookup(SSE2UniformConstCostTable, ISD, LT.second))
612 if (auto KindCost = Entry->Cost[CostKind])
613 return LT.first * *KindCost;
614
615 static const CostKindTblEntry AVX512BWConstCostTable[] = {
616 { ISD::SDIV, MVT::v64i8, { 14 } }, // 2*ext+2*pmulhw sequence
617 { ISD::SREM, MVT::v64i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
618 { ISD::UDIV, MVT::v64i8, { 14 } }, // 2*ext+2*pmulhw sequence
619 { ISD::UREM, MVT::v64i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
620
621 { ISD::SDIV, MVT::v32i16, { 6 } }, // vpmulhw sequence
622 { ISD::SREM, MVT::v32i16, { 8 } }, // vpmulhw+mul+sub sequence
623 { ISD::UDIV, MVT::v32i16, { 6 } }, // vpmulhuw sequence
624 { ISD::UREM, MVT::v32i16, { 8 } }, // vpmulhuw+mul+sub sequence
625 };
626
627 if (Op2Info.isConstant() && ST->hasBWI())
628 if (const auto *Entry =
629 CostTableLookup(AVX512BWConstCostTable, ISD, LT.second))
630 if (auto KindCost = Entry->Cost[CostKind])
631 return LT.first * *KindCost;
632
633 static const CostKindTblEntry AVX512DQConstCostTable[] = {
634 { ISD::SDIV, MVT::v4i64, { 19 } }, // vpmullq-based MULHS sequence
635 { ISD::SREM, MVT::v4i64, { 21 } }, // vpmullq-based MULHS+mul+sub sequence
636 { ISD::SDIV, MVT::v8i64, { 19 } }, // vpmullq-based MULHS sequence
637 { ISD::SREM, MVT::v8i64, { 21 } }, // vpmullq-based MULHS+mul+sub sequence
638 // The remainder's multiply-back is a single vpmullq with DQ, whereas the
639 // AVX512/AVX2 tables have to charge for another vpmuludq schoolbook.
640 { ISD::UREM, MVT::v4i64, { 24 } }, // MULHU + vpmullq + sub sequence
641 { ISD::UREM, MVT::v8i64, { 24 } }, // MULHU + vpmullq + sub sequence
642 };
643
644 if (Op2Info.isConstant() && ST->hasDQI())
645 if (const auto *Entry =
646 CostTableLookup(AVX512DQConstCostTable, ISD, LT.second))
647 if (auto KindCost = Entry->Cost[CostKind])
648 return LT.first * *KindCost;
649
650 static const CostKindTblEntry AVX512ConstCostTable[] = {
651 { ISD::SDIV, MVT::v64i8, { 28 } }, // 4*ext+4*pmulhw sequence
652 { ISD::SREM, MVT::v64i8, { 32 } }, // 4*ext+4*pmulhw+mul+sub sequence
653 { ISD::UDIV, MVT::v64i8, { 28 } }, // 4*ext+4*pmulhw sequence
654 { ISD::UREM, MVT::v64i8, { 32 } }, // 4*ext+4*pmulhw+mul+sub sequence
655
656 { ISD::SDIV, MVT::v32i16, { 12 } }, // 2*vpmulhw sequence
657 { ISD::SREM, MVT::v32i16, { 16 } }, // 2*vpmulhw+mul+sub sequence
658 { ISD::UDIV, MVT::v32i16, { 12 } }, // 2*vpmulhuw sequence
659 { ISD::UREM, MVT::v32i16, { 16 } }, // 2*vpmulhuw+mul+sub sequence
660
661 { ISD::SDIV, MVT::v16i32, { 15 } }, // vpmuldq sequence
662 { ISD::SREM, MVT::v16i32, { 17 } }, // vpmuldq+mul+sub sequence
663 { ISD::UDIV, MVT::v16i32, { 15 } }, // vpmuludq sequence
664 { ISD::UREM, MVT::v16i32, { 17 } }, // vpmuludq+mul+sub sequence
665
666 { ISD::UDIV, MVT::v8i64, { 22 } }, // vpmuludq-based MULHU sequence
667 { ISD::UREM, MVT::v8i64, { 28 } }, // vpmuludq-based MULHU+mul+sub sequence
668 };
669
670 if (Op2Info.isConstant() && ST->hasAVX512())
671 if (const auto *Entry =
672 CostTableLookup(AVX512ConstCostTable, ISD, LT.second))
673 if (auto KindCost = Entry->Cost[CostKind])
674 return LT.first * *KindCost;
675
676 static const CostKindTblEntry AVX2ConstCostTable[] = {
677 { ISD::SDIV, MVT::v32i8, { 14 } }, // 2*ext+2*pmulhw sequence
678 { ISD::SREM, MVT::v32i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
679 { ISD::UDIV, MVT::v32i8, { 14 } }, // 2*ext+2*pmulhw sequence
680 { ISD::UREM, MVT::v32i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
681
682 { ISD::SDIV, MVT::v16i16, { 6 } }, // vpmulhw sequence
683 { ISD::SREM, MVT::v16i16, { 8 } }, // vpmulhw+mul+sub sequence
684 { ISD::UDIV, MVT::v16i16, { 6 } }, // vpmulhuw sequence
685 { ISD::UREM, MVT::v16i16, { 8 } }, // vpmulhuw+mul+sub sequence
686
687 { ISD::SDIV, MVT::v8i32, { 15 } }, // vpmuldq sequence
688 { ISD::SREM, MVT::v8i32, { 19 } }, // vpmuldq+mul+sub sequence
689 { ISD::UDIV, MVT::v8i32, { 15 } }, // vpmuludq sequence
690 { ISD::UREM, MVT::v8i32, { 19 } }, // vpmuludq+mul+sub sequence
691
692 { ISD::UDIV, MVT::v4i64, { 22 } }, // vpmuludq-based MULHU sequence
693 { ISD::UREM, MVT::v4i64, { 28 } }, // vpmuludq-based MULHU+mul+sub sequence
694 };
695
696 if (Op2Info.isConstant() && ST->hasAVX2())
697 if (const auto *Entry = CostTableLookup(AVX2ConstCostTable, ISD, LT.second))
698 if (auto KindCost = Entry->Cost[CostKind])
699 return LT.first * *KindCost;
700
701 static const CostKindTblEntry AVXConstCostTable[] = {
702 { ISD::SDIV, MVT::v32i8, { 30 } }, // 4*ext+4*pmulhw sequence + split.
703 { ISD::SREM, MVT::v32i8, { 34 } }, // 4*ext+4*pmulhw+mul+sub sequence + split.
704 { ISD::UDIV, MVT::v32i8, { 30 } }, // 4*ext+4*pmulhw sequence + split.
705 { ISD::UREM, MVT::v32i8, { 34 } }, // 4*ext+4*pmulhw+mul+sub sequence + split.
706
707 { ISD::SDIV, MVT::v16i16, { 14 } }, // 2*pmulhw sequence + split.
708 { ISD::SREM, MVT::v16i16, { 18 } }, // 2*pmulhw+mul+sub sequence + split.
709 { ISD::UDIV, MVT::v16i16, { 14 } }, // 2*pmulhuw sequence + split.
710 { ISD::UREM, MVT::v16i16, { 18 } }, // 2*pmulhuw+mul+sub sequence + split.
711
712 { ISD::SDIV, MVT::v8i32, { 32 } }, // vpmuludq sequence
713 { ISD::SREM, MVT::v8i32, { 38 } }, // vpmuludq+mul+sub sequence
714 { ISD::UDIV, MVT::v8i32, { 32 } }, // 2*pmuludq sequence + split.
715 { ISD::UREM, MVT::v8i32, { 42 } }, // 2*pmuludq+mul+sub sequence + split.
716 };
717
718 if (Op2Info.isConstant() && ST->hasAVX())
719 if (const auto *Entry = CostTableLookup(AVXConstCostTable, ISD, LT.second))
720 if (auto KindCost = Entry->Cost[CostKind])
721 return LT.first * *KindCost;
722
723 static const CostKindTblEntry SSE41ConstCostTable[] = {
724 { ISD::SDIV, MVT::v4i32, { 15 } }, // vpmuludq sequence
725 { ISD::SREM, MVT::v4i32, { 20 } }, // vpmuludq+mul+sub sequence
726 };
727
728 if (Op2Info.isConstant() && ST->hasSSE41())
729 if (const auto *Entry =
730 CostTableLookup(SSE41ConstCostTable, ISD, LT.second))
731 if (auto KindCost = Entry->Cost[CostKind])
732 return LT.first * *KindCost;
733
734 static const CostKindTblEntry SSE2ConstCostTable[] = {
735 { ISD::SDIV, MVT::v16i8, { 14 } }, // 2*ext+2*pmulhw sequence
736 { ISD::SREM, MVT::v16i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
737 { ISD::UDIV, MVT::v16i8, { 14 } }, // 2*ext+2*pmulhw sequence
738 { ISD::UREM, MVT::v16i8, { 16 } }, // 2*ext+2*pmulhw+mul+sub sequence
739
740 { ISD::SDIV, MVT::v8i16, { 6 } }, // pmulhw sequence
741 { ISD::SREM, MVT::v8i16, { 8 } }, // pmulhw+mul+sub sequence
742 { ISD::UDIV, MVT::v8i16, { 6 } }, // pmulhuw sequence
743 { ISD::UREM, MVT::v8i16, { 8 } }, // pmulhuw+mul+sub sequence
744
745 { ISD::SDIV, MVT::v4i32, { 19 } }, // pmuludq sequence
746 { ISD::SREM, MVT::v4i32, { 24 } }, // pmuludq+mul+sub sequence
747 { ISD::UDIV, MVT::v4i32, { 15 } }, // pmuludq sequence
748 { ISD::UREM, MVT::v4i32, { 20 } }, // pmuludq+mul+sub sequence
749 };
750
751 if (Op2Info.isConstant() && ST->hasSSE2())
752 if (const auto *Entry = CostTableLookup(SSE2ConstCostTable, ISD, LT.second))
753 if (auto KindCost = Entry->Cost[CostKind])
754 return LT.first * *KindCost;
755
756 // rem matches div because the divider returns the remainder for free.
757 static const CostKindTblEntry ScalarVarDivCostTable[] = {
758 { ISD::SDIV, MVT::i8, { 15, 20, 2, 4 } },
759 { ISD::UDIV, MVT::i8, { 15, 20, 2, 4 } },
760 { ISD::SREM, MVT::i8, { 15, 20, 2, 4 } },
761 { ISD::UREM, MVT::i8, { 15, 20, 2, 4 } },
762 { ISD::SDIV, MVT::i16, { 17, 20, 2, 4 } },
763 { ISD::UDIV, MVT::i16, { 17, 20, 2, 4 } },
764 { ISD::SREM, MVT::i16, { 17, 20, 2, 4 } },
765 { ISD::UREM, MVT::i16, { 17, 20, 2, 4 } },
766 { ISD::SDIV, MVT::i32, { 25, 22, 2, 4 } },
767 { ISD::UDIV, MVT::i32, { 25, 22, 2, 4 } },
768 { ISD::SREM, MVT::i32, { 25, 22, 2, 4 } },
769 { ISD::UREM, MVT::i32, { 25, 22, 2, 4 } },
770 { ISD::SDIV, MVT::i64, { 41, 24, 2, 4 } },
771 { ISD::UDIV, MVT::i64, { 41, 24, 2, 4 } },
772 { ISD::SREM, MVT::i64, { 41, 24, 2, 4 } },
773 { ISD::UREM, MVT::i64, { 41, 24, 2, 4 } },
774 };
775
776 if (!LT.second.isVector() && !Op2Info.isConstant())
777 if (const auto *Entry =
778 CostTableLookup(ScalarVarDivCostTable, ISD, LT.second))
779 if (auto KindCost = Entry->Cost[CostKind])
780 return LT.first * *KindCost;
781
782 // Variable divisors lower through a float divide. strictfp needs SAE
783 // rounding which is 512-bit only.
784 bool IsStrictFP =
785 CtxI && CtxI->getFunction()->hasFnAttribute(Attribute::StrictFP);
786 bool IsDivRem = ISD == ISD::UDIV || ISD == ISD::SDIV || ISD == ISD::UREM ||
787 ISD == ISD::SREM;
788 bool VarDivToFP = IsDivRem && !Op2Info.isConstant() &&
789 (!IsStrictFP || ST->useAVX512Regs());
790
791 // i64 needs the qq converts, which are AVX512DQ only. Two tables because the
792 // lowering picks by operand value and not by type.
793 static const CostKindTblEntry AVX512DQExactVarDivCostTable[] = {
794 { ISD::UDIV, MVT::v2i64, { 5 } }, // cvt+divpd sequence
795 { ISD::SDIV, MVT::v2i64, { 5 } },
796 { ISD::UREM, MVT::v2i64, { 5 } },
797 { ISD::SREM, MVT::v2i64, { 5 } },
798 { ISD::UDIV, MVT::v4i64, { 8 } },
799 { ISD::SDIV, MVT::v4i64, { 8 } },
800 { ISD::UREM, MVT::v4i64, { 8 } },
801 { ISD::SREM, MVT::v4i64, { 8 } },
802 { ISD::UDIV, MVT::v8i64, { 16 } },
803 { ISD::SDIV, MVT::v8i64, { 16 } },
804 { ISD::UREM, MVT::v8i64, { 16 } },
805 { ISD::SREM, MVT::v8i64, { 16 } },
806 };
807
808 static const CostKindTblEntry AVX512DQVarDivCostTable[] = {
809 { ISD::UDIV, MVT::v2i64, { 16 } },
810 { ISD::SDIV, MVT::v2i64, { 16 } },
811 { ISD::UREM, MVT::v2i64, { 16 } },
812 { ISD::SREM, MVT::v2i64, { 16 } },
813 { ISD::UDIV, MVT::v4i64, { 16 } },
814 { ISD::SDIV, MVT::v4i64, { 16 } },
815 { ISD::UREM, MVT::v4i64, { 16 } },
816 { ISD::SREM, MVT::v4i64, { 16 } },
817 { ISD::UDIV, MVT::v8i64, { 16 } },
818 { ISD::SDIV, MVT::v8i64, { 18 } },
819 { ISD::UREM, MVT::v8i64, { 16 } },
820 { ISD::SREM, MVT::v8i64, { 18 } },
821 };
822
823 // The DAG combine picks between the two sequences with these same two
824 // queries, so the cost cannot disagree with what codegen emits.
825 bool IsSignedDiv = ISD == ISD::SDIV || ISD == ISD::SREM;
826 auto OperandsFit = [&](unsigned Mantissa) {
827 if (Args.size() != 2 || !CtxI)
828 return false;
829 unsigned EltBits = LT.second.getScalarSizeInBits();
830 const DataLayout &DL = CtxI->getDataLayout();
831 auto Fits = [&](const Value *V) {
832 if (IsSignedDiv)
833 return ComputeNumSignBits(V, DL, /*AC=*/nullptr, CtxI) + Mantissa >
834 EltBits;
835 return computeKnownBits(V, DL, /*AC=*/nullptr, CtxI)
836 .countMaxActiveBits() <= Mantissa;
837 };
838 return Fits(Args[0]) && Fits(Args[1]);
839 };
840
841 // An i32 divide goes through f32 when both operands fit in 24 bits, and
842 // through f64 at twice the vector width when they do not.
843 bool ExactI32 =
844 VarDivToFP && LT.second.getScalarType() == MVT::i32 &&
846
847 if (VarDivToFP && ST->hasDQI() && ST->useAVX512Regs() &&
848 LT.second.getScalarType() == MVT::i64) {
849 bool ExactFPDiv =
851
852 // Only the reciprocal chain multiplies, so only it is vpmullq gated.
853 bool SlowMultiply =
854 !ExactFPDiv && LT.second == MVT::v2i64 && ST->isPMULLQSlow();
855
856 if (!SlowMultiply) {
858 ExactFPDiv ? AVX512DQExactVarDivCostTable : AVX512DQVarDivCostTable;
859 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
860 if (auto KindCost = Entry->Cost[CostKind])
861 return LT.first * *KindCost;
862 }
863 }
864
865 static const CostKindTblEntry AVX512BWVarDivCostTable[] = {
866 { ISD::UDIV, MVT::v16i8, { 10 } }, // unpack+cvt+divps sequence
867 { ISD::SDIV, MVT::v16i8, { 10 } },
868 { ISD::UREM, MVT::v16i8, { 10 } },
869 { ISD::SREM, MVT::v16i8, { 10 } },
870 { ISD::UDIV, MVT::v32i8, { 20 } },
871 { ISD::SDIV, MVT::v32i8, { 20 } },
872 { ISD::UREM, MVT::v32i8, { 20 } },
873 { ISD::SREM, MVT::v32i8, { 20 } },
874 { ISD::UDIV, MVT::v64i8, { 40 } },
875 { ISD::SDIV, MVT::v64i8, { 40 } },
876 { ISD::UREM, MVT::v64i8, { 40 } },
877 { ISD::SREM, MVT::v64i8, { 40 } },
878 { ISD::UDIV, MVT::v8i16, { 5 } },
879 { ISD::SDIV, MVT::v8i16, { 5 } },
880 { ISD::UREM, MVT::v8i16, { 5 } },
881 { ISD::SREM, MVT::v8i16, { 5 } },
882 { ISD::UDIV, MVT::v16i16, { 10 } },
883 { ISD::SDIV, MVT::v16i16, { 10 } },
884 { ISD::UREM, MVT::v16i16, { 10 } },
885 { ISD::SREM, MVT::v16i16, { 10 } },
886 { ISD::UDIV, MVT::v32i16, { 20 } },
887 { ISD::SDIV, MVT::v32i16, { 20 } },
888 { ISD::UREM, MVT::v32i16, { 20 } },
889 { ISD::SREM, MVT::v32i16, { 20 } },
890 { ISD::UDIV, MVT::v4i32, { 8 } }, // cvt+divpd sequence
891 { ISD::SDIV, MVT::v4i32, { 8 } },
892 { ISD::UREM, MVT::v4i32, { 8 } },
893 { ISD::SREM, MVT::v4i32, { 8 } },
894 { ISD::UDIV, MVT::v8i32, { 16 } },
895 { ISD::SDIV, MVT::v8i32, { 16 } },
896 { ISD::UREM, MVT::v8i32, { 16 } },
897 { ISD::SREM, MVT::v8i32, { 16 } },
898 { ISD::UDIV, MVT::v16i32, { 32 } },
899 { ISD::SDIV, MVT::v16i32, { 32 } },
900 { ISD::UREM, MVT::v16i32, { 32 } },
901 { ISD::SREM, MVT::v16i32, { 32 } },
902 };
903
904 static const CostKindTblEntry AVX512BWExactVarDivCostTable[] = {
905 { ISD::UDIV, MVT::v4i32, { 3 } }, // cvt+divps sequence
906 { ISD::SDIV, MVT::v4i32, { 3 } },
907 { ISD::UREM, MVT::v4i32, { 3 } },
908 { ISD::SREM, MVT::v4i32, { 3 } },
909 { ISD::UDIV, MVT::v8i32, { 5 } },
910 { ISD::SDIV, MVT::v8i32, { 5 } },
911 { ISD::UREM, MVT::v8i32, { 5 } },
912 { ISD::SREM, MVT::v8i32, { 5 } },
913 { ISD::UDIV, MVT::v16i32, { 10 } },
914 { ISD::SDIV, MVT::v16i32, { 10 } },
915 { ISD::UREM, MVT::v16i32, { 10 } },
916 { ISD::SREM, MVT::v16i32, { 10 } },
917 };
918
919 if (VarDivToFP && ST->hasBWI()) {
920 ArrayRef<CostKindTblEntry> Tbl = AVX512BWVarDivCostTable;
921 if (ExactI32)
922 Tbl = AVX512BWExactVarDivCostTable;
923 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
924 if (auto KindCost = Entry->Cost[CostKind])
925 return LT.first * *KindCost;
926 }
927
928 static const CostKindTblEntry AVX512VarDivCostTable[] = {
929 { ISD::UDIV, MVT::v16i8, { 14 } }, // unpack+cvt+divps sequence
930 { ISD::SDIV, MVT::v16i8, { 14 } },
931 { ISD::UREM, MVT::v16i8, { 14 } },
932 { ISD::SREM, MVT::v16i8, { 14 } },
933 { ISD::UDIV, MVT::v32i8, { 28 } },
934 { ISD::SDIV, MVT::v32i8, { 28 } },
935 { ISD::UREM, MVT::v32i8, { 28 } },
936 { ISD::SREM, MVT::v32i8, { 28 } },
937 { ISD::UDIV, MVT::v64i8, { 56 } },
938 { ISD::SDIV, MVT::v64i8, { 56 } },
939 { ISD::UREM, MVT::v64i8, { 56 } },
940 { ISD::SREM, MVT::v64i8, { 56 } },
941 { ISD::UDIV, MVT::v8i16, { 14 } },
942 { ISD::SDIV, MVT::v8i16, { 14 } },
943 { ISD::UREM, MVT::v8i16, { 14 } },
944 { ISD::SREM, MVT::v8i16, { 14 } },
945 { ISD::UDIV, MVT::v16i16, { 14 } },
946 { ISD::SDIV, MVT::v16i16, { 14 } },
947 { ISD::UREM, MVT::v16i16, { 14 } },
948 { ISD::SREM, MVT::v16i16, { 14 } },
949 { ISD::UDIV, MVT::v32i16, { 28 } },
950 { ISD::SDIV, MVT::v32i16, { 28 } },
951 { ISD::UREM, MVT::v32i16, { 28 } },
952 { ISD::SREM, MVT::v32i16, { 28 } },
953 { ISD::UDIV, MVT::v4i32, { 28 } }, // cvt+divpd sequence
954 { ISD::SDIV, MVT::v4i32, { 28 } },
955 { ISD::UREM, MVT::v4i32, { 28 } },
956 { ISD::SREM, MVT::v4i32, { 28 } },
957 { ISD::UDIV, MVT::v8i32, { 28 } },
958 { ISD::SDIV, MVT::v8i32, { 28 } },
959 { ISD::UREM, MVT::v8i32, { 28 } },
960 { ISD::SREM, MVT::v8i32, { 28 } },
961 { ISD::UDIV, MVT::v16i32, { 56 } },
962 { ISD::SDIV, MVT::v16i32, { 56 } },
963 { ISD::UREM, MVT::v16i32, { 56 } },
964 { ISD::SREM, MVT::v16i32, { 56 } },
965 };
966
967 static const CostKindTblEntry AVX512ExactVarDivCostTable[] = {
968 { ISD::UDIV, MVT::v4i32, { 7 } }, // cvt+divps sequence
969 { ISD::SDIV, MVT::v4i32, { 7 } },
970 { ISD::UREM, MVT::v4i32, { 7 } },
971 { ISD::SREM, MVT::v4i32, { 7 } },
972 { ISD::UDIV, MVT::v8i32, { 14 } },
973 { ISD::SDIV, MVT::v8i32, { 14 } },
974 { ISD::UREM, MVT::v8i32, { 14 } },
975 { ISD::SREM, MVT::v8i32, { 14 } },
976 { ISD::UDIV, MVT::v16i32, { 14 } },
977 { ISD::SDIV, MVT::v16i32, { 14 } },
978 { ISD::UREM, MVT::v16i32, { 14 } },
979 { ISD::SREM, MVT::v16i32, { 14 } },
980 };
981
982 if (VarDivToFP && ST->hasAVX512()) {
983 ArrayRef<CostKindTblEntry> Tbl = AVX512VarDivCostTable;
984 if (ExactI32)
985 Tbl = AVX512ExactVarDivCostTable;
986 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
987 if (auto KindCost = Entry->Cost[CostKind])
988 return LT.first * *KindCost;
989 }
990
991 static const CostKindTblEntry AVX2VarDivCostTable[] = {
992 { ISD::UDIV, MVT::v16i8, { 28 } }, // unpack+cvt+divps sequence
993 { ISD::SDIV, MVT::v16i8, { 28 } },
994 { ISD::UREM, MVT::v16i8, { 28 } },
995 { ISD::SREM, MVT::v16i8, { 28 } },
996 { ISD::UDIV, MVT::v32i8, { 56 } },
997 { ISD::SDIV, MVT::v32i8, { 56 } },
998 { ISD::UREM, MVT::v32i8, { 56 } },
999 { ISD::SREM, MVT::v32i8, { 56 } },
1000 { ISD::UDIV, MVT::v8i16, { 14 } },
1001 { ISD::SDIV, MVT::v8i16, { 14 } },
1002 { ISD::UREM, MVT::v8i16, { 14 } },
1003 { ISD::SREM, MVT::v8i16, { 14 } },
1004 { ISD::UDIV, MVT::v16i16, { 28 } },
1005 { ISD::SDIV, MVT::v16i16, { 28 } },
1006 { ISD::UREM, MVT::v16i16, { 28 } },
1007 { ISD::SREM, MVT::v16i16, { 28 } },
1008 { ISD::UDIV, MVT::v4i32, { 28 } }, // cvt+divpd sequence
1009 { ISD::SDIV, MVT::v4i32, { 28 } },
1010 { ISD::UREM, MVT::v4i32, { 28 } },
1011 { ISD::SREM, MVT::v4i32, { 28 } },
1012 { ISD::UDIV, MVT::v8i32, { 56 } },
1013 { ISD::SDIV, MVT::v8i32, { 56 } },
1014 { ISD::UREM, MVT::v8i32, { 56 } },
1015 { ISD::SREM, MVT::v8i32, { 56 } },
1016 };
1017
1018 static const CostKindTblEntry AVX2ExactVarDivCostTable[] = {
1019 { ISD::UDIV, MVT::v4i32, { 9 } }, // cvt+divps sequence
1020 { ISD::SDIV, MVT::v4i32, { 8 } },
1021 { ISD::UREM, MVT::v4i32, { 9 } },
1022 { ISD::SREM, MVT::v4i32, { 8 } },
1023 { ISD::UDIV, MVT::v8i32, { 14 } },
1024 { ISD::SDIV, MVT::v8i32, { 14 } },
1025 { ISD::UREM, MVT::v8i32, { 14 } },
1026 { ISD::SREM, MVT::v8i32, { 14 } },
1027 };
1028
1029 if (VarDivToFP && ST->hasAVX2()) {
1030 ArrayRef<CostKindTblEntry> Tbl = AVX2VarDivCostTable;
1031 if (ExactI32)
1032 Tbl = AVX2ExactVarDivCostTable;
1033 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
1034 if (auto KindCost = Entry->Cost[CostKind])
1035 return LT.first * *KindCost;
1036 }
1037
1038 // No unsigned i32 entries below AVX2, where the u32 to f64 converts are
1039 // emulated and the fold stays off.
1040 static const CostKindTblEntry AVX1VarDivCostTable[] = {
1041 { ISD::UDIV, MVT::v16i8, { 56 } }, // unpack+cvt+divps sequence
1042 { ISD::SDIV, MVT::v16i8, { 56 } },
1043 { ISD::UREM, MVT::v16i8, { 56 } },
1044 { ISD::SREM, MVT::v16i8, { 56 } },
1045 { ISD::UDIV, MVT::v32i8, { 112 } },
1046 { ISD::SDIV, MVT::v32i8, { 112 } },
1047 { ISD::UREM, MVT::v32i8, { 112 } },
1048 { ISD::SREM, MVT::v32i8, { 112 } },
1049 { ISD::UDIV, MVT::v8i16, { 28 } },
1050 { ISD::SDIV, MVT::v8i16, { 28 } },
1051 { ISD::UREM, MVT::v8i16, { 28 } },
1052 { ISD::SREM, MVT::v8i16, { 28 } },
1053 { ISD::UDIV, MVT::v16i16, { 56 } },
1054 { ISD::SDIV, MVT::v16i16, { 56 } },
1055 { ISD::UREM, MVT::v16i16, { 56 } },
1056 { ISD::SREM, MVT::v16i16, { 56 } },
1057 { ISD::SDIV, MVT::v4i32, { 44 } }, // cvt+divpd sequence
1058 { ISD::SREM, MVT::v4i32, { 44 } },
1059 { ISD::SDIV, MVT::v8i32, { 88 } },
1060 { ISD::SREM, MVT::v8i32, { 88 } },
1061 };
1062
1063 static const CostKindTblEntry AVX1ExactVarDivCostTable[] = {
1064 { ISD::SDIV, MVT::v4i32, { 14 } }, // cvt+divps sequence
1065 { ISD::SREM, MVT::v4i32, { 14 } },
1066 { ISD::SDIV, MVT::v8i32, { 28 } },
1067 { ISD::SREM, MVT::v8i32, { 28 } },
1068 };
1069
1070 if (VarDivToFP && ST->hasAVX()) {
1071 ArrayRef<CostKindTblEntry> Tbl = AVX1VarDivCostTable;
1072 if (ExactI32)
1073 Tbl = AVX1ExactVarDivCostTable;
1074 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
1075 if (auto KindCost = Entry->Cost[CostKind])
1076 return LT.first * *KindCost;
1077 }
1078
1079 static const CostKindTblEntry SSE2VarDivCostTable[] = {
1080 { ISD::UDIV, MVT::v16i8, { 56 } }, // unpack+cvt+divps sequence
1081 { ISD::SDIV, MVT::v16i8, { 56 } },
1082 { ISD::UREM, MVT::v16i8, { 56 } },
1083 { ISD::SREM, MVT::v16i8, { 56 } },
1084 { ISD::UDIV, MVT::v8i16, { 28 } },
1085 { ISD::SDIV, MVT::v8i16, { 28 } },
1086 { ISD::UREM, MVT::v8i16, { 28 } },
1087 { ISD::SREM, MVT::v8i16, { 28 } },
1088 { ISD::SDIV, MVT::v4i32, { 44 } }, // cvt+divpd sequence
1089 { ISD::SREM, MVT::v4i32, { 44 } },
1090 };
1091
1092 static const CostKindTblEntry SSE2ExactVarDivCostTable[] = {
1093 { ISD::SDIV, MVT::v4i32, { 14 } }, // cvt+divps sequence
1094 { ISD::SREM, MVT::v4i32, { 14 } },
1095 };
1096
1097 if (VarDivToFP && ST->hasSSE2()) {
1098 ArrayRef<CostKindTblEntry> Tbl = SSE2VarDivCostTable;
1099 if (ExactI32)
1100 Tbl = SSE2ExactVarDivCostTable;
1101 if (const auto *Entry = CostTableLookup(Tbl, ISD, LT.second))
1102 if (auto KindCost = Entry->Cost[CostKind])
1103 return LT.first * *KindCost;
1104 }
1105
1106 static const CostKindTblEntry AVX512BWUniformCostTable[] = {
1107 { ISD::SHL, MVT::v16i8, { 3, 5, 5, 7 } }, // psllw + pand.
1108 { ISD::SRL, MVT::v16i8, { 3,10, 5, 8 } }, // psrlw + pand.
1109 { ISD::SRA, MVT::v16i8, { 4,12, 8,12 } }, // psrlw, pand, pxor, psubb.
1110 { ISD::SHL, MVT::v32i8, { 4, 7, 6, 8 } }, // psllw + pand.
1111 { ISD::SRL, MVT::v32i8, { 4, 8, 7, 9 } }, // psrlw + pand.
1112 { ISD::SRA, MVT::v32i8, { 5,10,10,13 } }, // psrlw, pand, pxor, psubb.
1113 { ISD::SHL, MVT::v64i8, { 4, 7, 6, 8 } }, // psllw + pand.
1114 { ISD::SRL, MVT::v64i8, { 4, 8, 7,10 } }, // psrlw + pand.
1115 { ISD::SRA, MVT::v64i8, { 5,10,10,15 } }, // psrlw, pand, pxor, psubb.
1116
1117 { ISD::SHL, MVT::v32i16, { 2, 4, 2, 3 } }, // psllw
1118 { ISD::SRL, MVT::v32i16, { 2, 4, 2, 3 } }, // psrlw
1119 { ISD::SRA, MVT::v32i16, { 2, 4, 2, 3 } }, // psrqw
1120 };
1121
1122 if (ST->hasBWI() && Op2Info.isUniform())
1123 if (const auto *Entry =
1124 CostTableLookup(AVX512BWUniformCostTable, ISD, LT.second))
1125 if (auto KindCost = Entry->Cost[CostKind])
1126 return LT.first * *KindCost;
1127
1128 static const CostKindTblEntry AVX512UniformCostTable[] = {
1129 { ISD::SHL, MVT::v32i16, { 5,10, 5, 7 } }, // psllw + split.
1130 { ISD::SRL, MVT::v32i16, { 5,10, 5, 7 } }, // psrlw + split.
1131 { ISD::SRA, MVT::v32i16, { 5,10, 5, 7 } }, // psraw + split.
1132
1133 { ISD::SHL, MVT::v16i32, { 2, 4, 2, 3 } }, // pslld
1134 { ISD::SRL, MVT::v16i32, { 2, 4, 2, 3 } }, // psrld
1135 { ISD::SRA, MVT::v16i32, { 2, 4, 2, 3 } }, // psrad
1136
1137 { ISD::SRA, MVT::v2i64, { 1, 2, 1, 2 } }, // psraq
1138 { ISD::SHL, MVT::v4i64, { 1, 4, 1, 2 } }, // psllq
1139 { ISD::SRL, MVT::v4i64, { 1, 4, 1, 2 } }, // psrlq
1140 { ISD::SRA, MVT::v4i64, { 1, 4, 1, 2 } }, // psraq
1141 { ISD::SHL, MVT::v8i64, { 1, 4, 1, 2 } }, // psllq
1142 { ISD::SRL, MVT::v8i64, { 1, 4, 1, 2 } }, // psrlq
1143 { ISD::SRA, MVT::v8i64, { 1, 4, 1, 2 } }, // psraq
1144 };
1145
1146 if (ST->hasAVX512() && Op2Info.isUniform())
1147 if (const auto *Entry =
1148 CostTableLookup(AVX512UniformCostTable, ISD, LT.second))
1149 if (auto KindCost = Entry->Cost[CostKind])
1150 return LT.first * *KindCost;
1151
1152 static const CostKindTblEntry AVX2UniformCostTable[] = {
1153 // Uniform splats are cheaper for the following instructions.
1154 { ISD::SHL, MVT::v16i8, { 3, 5, 5, 7 } }, // psllw + pand.
1155 { ISD::SRL, MVT::v16i8, { 3, 9, 5, 8 } }, // psrlw + pand.
1156 { ISD::SRA, MVT::v16i8, { 4, 5, 9,13 } }, // psrlw, pand, pxor, psubb.
1157 { ISD::SHL, MVT::v32i8, { 4, 7, 6, 8 } }, // psllw + pand.
1158 { ISD::SRL, MVT::v32i8, { 4, 8, 7, 9 } }, // psrlw + pand.
1159 { ISD::SRA, MVT::v32i8, { 6, 9,11,16 } }, // psrlw, pand, pxor, psubb.
1160
1161 { ISD::SHL, MVT::v8i16, { 1, 2, 1, 2 } }, // psllw.
1162 { ISD::SRL, MVT::v8i16, { 1, 2, 1, 2 } }, // psrlw.
1163 { ISD::SRA, MVT::v8i16, { 1, 2, 1, 2 } }, // psraw.
1164 { ISD::SHL, MVT::v16i16, { 2, 4, 2, 3 } }, // psllw.
1165 { ISD::SRL, MVT::v16i16, { 2, 4, 2, 3 } }, // psrlw.
1166 { ISD::SRA, MVT::v16i16, { 2, 4, 2, 3 } }, // psraw.
1167
1168 { ISD::SHL, MVT::v4i32, { 1, 2, 1, 2 } }, // pslld
1169 { ISD::SRL, MVT::v4i32, { 1, 2, 1, 2 } }, // psrld
1170 { ISD::SRA, MVT::v4i32, { 1, 2, 1, 2 } }, // psrad
1171 { ISD::SHL, MVT::v8i32, { 2, 4, 2, 3 } }, // pslld
1172 { ISD::SRL, MVT::v8i32, { 2, 4, 2, 3 } }, // psrld
1173 { ISD::SRA, MVT::v8i32, { 2, 4, 2, 3 } }, // psrad
1174
1175 { ISD::SHL, MVT::v2i64, { 1, 2, 1, 2 } }, // psllq
1176 { ISD::SRL, MVT::v2i64, { 1, 2, 1, 2 } }, // psrlq
1177 { ISD::SRA, MVT::v2i64, { 2, 4, 5, 7 } }, // 2 x psrad + shuffle.
1178 { ISD::SHL, MVT::v4i64, { 2, 4, 1, 2 } }, // psllq
1179 { ISD::SRL, MVT::v4i64, { 2, 4, 1, 2 } }, // psrlq
1180 { ISD::SRA, MVT::v4i64, { 4, 6, 5, 9 } }, // 2 x psrad + shuffle.
1181 };
1182
1183 if (ST->hasAVX2() && Op2Info.isUniform())
1184 if (const auto *Entry =
1185 CostTableLookup(AVX2UniformCostTable, ISD, LT.second))
1186 if (auto KindCost = Entry->Cost[CostKind])
1187 return LT.first * *KindCost;
1188
1189 static const CostKindTblEntry AVXUniformCostTable[] = {
1190 { ISD::SHL, MVT::v16i8, { 4, 4, 6, 8 } }, // psllw + pand.
1191 { ISD::SRL, MVT::v16i8, { 4, 8, 5, 8 } }, // psrlw + pand.
1192 { ISD::SRA, MVT::v16i8, { 6, 6, 9,13 } }, // psrlw, pand, pxor, psubb.
1193 { ISD::SHL, MVT::v32i8, { 7, 8,11,14 } }, // psllw + pand + split.
1194 { ISD::SRL, MVT::v32i8, { 7, 9,10,14 } }, // psrlw + pand + split.
1195 { ISD::SRA, MVT::v32i8, { 10,11,16,21 } }, // psrlw, pand, pxor, psubb + split.
1196
1197 { ISD::SHL, MVT::v8i16, { 1, 3, 1, 2 } }, // psllw.
1198 { ISD::SRL, MVT::v8i16, { 1, 3, 1, 2 } }, // psrlw.
1199 { ISD::SRA, MVT::v8i16, { 1, 3, 1, 2 } }, // psraw.
1200 { ISD::SHL, MVT::v16i16, { 3, 7, 5, 7 } }, // psllw + split.
1201 { ISD::SRL, MVT::v16i16, { 3, 7, 5, 7 } }, // psrlw + split.
1202 { ISD::SRA, MVT::v16i16, { 3, 7, 5, 7 } }, // psraw + split.
1203
1204 { ISD::SHL, MVT::v4i32, { 1, 3, 1, 2 } }, // pslld.
1205 { ISD::SRL, MVT::v4i32, { 1, 3, 1, 2 } }, // psrld.
1206 { ISD::SRA, MVT::v4i32, { 1, 3, 1, 2 } }, // psrad.
1207 { ISD::SHL, MVT::v8i32, { 3, 7, 5, 7 } }, // pslld + split.
1208 { ISD::SRL, MVT::v8i32, { 3, 7, 5, 7 } }, // psrld + split.
1209 { ISD::SRA, MVT::v8i32, { 3, 7, 5, 7 } }, // psrad + split.
1210
1211 { ISD::SHL, MVT::v2i64, { 1, 3, 1, 2 } }, // psllq.
1212 { ISD::SRL, MVT::v2i64, { 1, 3, 1, 2 } }, // psrlq.
1213 { ISD::SRA, MVT::v2i64, { 3, 4, 5, 7 } }, // 2 x psrad + shuffle.
1214 { ISD::SHL, MVT::v4i64, { 3, 7, 4, 6 } }, // psllq + split.
1215 { ISD::SRL, MVT::v4i64, { 3, 7, 4, 6 } }, // psrlq + split.
1216 { ISD::SRA, MVT::v4i64, { 6, 7,10,13 } }, // 2 x (2 x psrad + shuffle) + split.
1217 };
1218
1219 // XOP has faster vXi8 shifts.
1220 if (ST->hasAVX() && Op2Info.isUniform() &&
1221 (!ST->hasXOP() || LT.second.getScalarSizeInBits() != 8))
1222 if (const auto *Entry =
1223 CostTableLookup(AVXUniformCostTable, ISD, LT.second))
1224 if (auto KindCost = Entry->Cost[CostKind])
1225 return LT.first * *KindCost;
1226
1227 static const CostKindTblEntry SSE2UniformCostTable[] = {
1228 // Uniform splats are cheaper for the following instructions.
1229 { ISD::SHL, MVT::v16i8, { 9, 10, 6, 9 } }, // psllw + pand.
1230 { ISD::SRL, MVT::v16i8, { 9, 13, 5, 9 } }, // psrlw + pand.
1231 { ISD::SRA, MVT::v16i8, { 11, 15, 9,13 } }, // pcmpgtb sequence.
1232
1233 { ISD::SHL, MVT::v8i16, { 2, 2, 1, 2 } }, // psllw.
1234 { ISD::SRL, MVT::v8i16, { 2, 2, 1, 2 } }, // psrlw.
1235 { ISD::SRA, MVT::v8i16, { 2, 2, 1, 2 } }, // psraw.
1236
1237 { ISD::SHL, MVT::v4i32, { 2, 2, 1, 2 } }, // pslld
1238 { ISD::SRL, MVT::v4i32, { 2, 2, 1, 2 } }, // psrld.
1239 { ISD::SRA, MVT::v4i32, { 2, 2, 1, 2 } }, // psrad.
1240
1241 { ISD::SHL, MVT::v2i64, { 2, 2, 1, 2 } }, // psllq.
1242 { ISD::SRL, MVT::v2i64, { 2, 2, 1, 2 } }, // psrlq.
1243 { ISD::SRA, MVT::v2i64, { 5, 9, 5, 7 } }, // 2*psrlq + xor + sub.
1244 };
1245
1246 if (ST->hasSSE2() && Op2Info.isUniform() &&
1247 (!ST->hasXOP() || LT.second.getScalarSizeInBits() != 8))
1248 if (const auto *Entry =
1249 CostTableLookup(SSE2UniformCostTable, ISD, LT.second))
1250 if (auto KindCost = Entry->Cost[CostKind])
1251 return LT.first * *KindCost;
1252
1253 static const CostKindTblEntry AVX512DQCostTable[] = {
1254 { ISD::MUL, MVT::v2i64, { 2, 15, 1, 3 } }, // pmullq
1255 { ISD::MUL, MVT::v4i64, { 2, 15, 1, 3 } }, // pmullq
1256 { ISD::MUL, MVT::v8i64, { 3, 15, 1, 3 } } // pmullq
1257 };
1258
1259 // Look for AVX512DQ lowering tricks for custom cases.
1260 if (ST->hasDQI())
1261 if (const auto *Entry = CostTableLookup(AVX512DQCostTable, ISD, LT.second))
1262 if (auto KindCost = Entry->Cost[CostKind])
1263 return LT.first * *KindCost;
1264
1265 static const CostKindTblEntry AVX512BWCostTable[] = {
1266 { ISD::SHL, MVT::v16i8, { 4, 8, 4, 5 } }, // extend/vpsllvw/pack sequence.
1267 { ISD::SRL, MVT::v16i8, { 4, 8, 4, 5 } }, // extend/vpsrlvw/pack sequence.
1268 { ISD::SRA, MVT::v16i8, { 4, 8, 4, 5 } }, // extend/vpsravw/pack sequence.
1269 { ISD::SHL, MVT::v32i8, { 4, 23,11,16 } }, // extend/vpsllvw/pack sequence.
1270 { ISD::SRL, MVT::v32i8, { 4, 30,12,18 } }, // extend/vpsrlvw/pack sequence.
1271 { ISD::SRA, MVT::v32i8, { 6, 13,24,30 } }, // extend/vpsravw/pack sequence.
1272 { ISD::SHL, MVT::v64i8, { 6, 19,13,15 } }, // extend/vpsllvw/pack sequence.
1273 { ISD::SRL, MVT::v64i8, { 7, 27,15,18 } }, // extend/vpsrlvw/pack sequence.
1274 { ISD::SRA, MVT::v64i8, { 15, 15,30,30 } }, // extend/vpsravw/pack sequence.
1275
1276 { ISD::SHL, MVT::v8i16, { 1, 1, 1, 1 } }, // vpsllvw
1277 { ISD::SRL, MVT::v8i16, { 1, 1, 1, 1 } }, // vpsrlvw
1278 { ISD::SRA, MVT::v8i16, { 1, 1, 1, 1 } }, // vpsravw
1279 { ISD::SHL, MVT::v16i16, { 1, 1, 1, 1 } }, // vpsllvw
1280 { ISD::SRL, MVT::v16i16, { 1, 1, 1, 1 } }, // vpsrlvw
1281 { ISD::SRA, MVT::v16i16, { 1, 1, 1, 1 } }, // vpsravw
1282 { ISD::SHL, MVT::v32i16, { 1, 1, 1, 1 } }, // vpsllvw
1283 { ISD::SRL, MVT::v32i16, { 1, 1, 1, 1 } }, // vpsrlvw
1284 { ISD::SRA, MVT::v32i16, { 1, 1, 1, 1 } }, // vpsravw
1285
1286 { ISD::ADD, MVT::v64i8, { 1, 1, 1, 1 } }, // paddb
1287 { ISD::ADD, MVT::v32i16, { 1, 1, 1, 1 } }, // paddw
1288
1289 { ISD::ADD, MVT::v32i8, { 1, 1, 1, 1 } }, // paddb
1290 { ISD::ADD, MVT::v16i16, { 1, 1, 1, 1 } }, // paddw
1291 { ISD::ADD, MVT::v8i32, { 1, 1, 1, 1 } }, // paddd
1292 { ISD::ADD, MVT::v4i64, { 1, 1, 1, 1 } }, // paddq
1293
1294 { ISD::SUB, MVT::v64i8, { 1, 1, 1, 1 } }, // psubb
1295 { ISD::SUB, MVT::v32i16, { 1, 1, 1, 1 } }, // psubw
1296
1297 { ISD::MUL, MVT::v16i8, { 4, 12, 4, 5 } }, // extend/pmullw/trunc
1298 { ISD::MUL, MVT::v32i8, { 3, 10, 7,10 } }, // pmaddubsw
1299 { ISD::MUL, MVT::v64i8, { 3, 11, 7,10 } }, // pmaddubsw
1300 { ISD::MUL, MVT::v32i16, { 1, 5, 1, 1 } }, // pmullw
1301
1302 { ISD::SUB, MVT::v32i8, { 1, 1, 1, 1 } }, // psubb
1303 { ISD::SUB, MVT::v16i16, { 1, 1, 1, 1 } }, // psubw
1304 { ISD::SUB, MVT::v8i32, { 1, 1, 1, 1 } }, // psubd
1305 { ISD::SUB, MVT::v4i64, { 1, 1, 1, 1 } }, // psubq
1306 };
1307
1308 // Look for AVX512BW lowering tricks for custom cases.
1309 if (ST->hasBWI())
1310 if (const auto *Entry = CostTableLookup(AVX512BWCostTable, ISD, LT.second))
1311 if (auto KindCost = Entry->Cost[CostKind])
1312 return LT.first * *KindCost;
1313
1314 static const CostKindTblEntry AVX512CostTable[] = {
1315 { ISD::SHL, MVT::v64i8, { 15, 19,27,33 } }, // vpblendv+split sequence.
1316 { ISD::SRL, MVT::v64i8, { 15, 19,30,36 } }, // vpblendv+split sequence.
1317 { ISD::SRA, MVT::v64i8, { 37, 37,51,63 } }, // vpblendv+split sequence.
1318
1319 { ISD::SHL, MVT::v32i16, { 11, 16,11,15 } }, // 2*extend/vpsrlvd/pack sequence.
1320 { ISD::SRL, MVT::v32i16, { 11, 16,11,15 } }, // 2*extend/vpsrlvd/pack sequence.
1321 { ISD::SRA, MVT::v32i16, { 11, 16,11,15 } }, // 2*extend/vpsravd/pack sequence.
1322
1323 { ISD::SHL, MVT::v4i32, { 1, 1, 1, 1 } },
1324 { ISD::SRL, MVT::v4i32, { 1, 1, 1, 1 } },
1325 { ISD::SRA, MVT::v4i32, { 1, 1, 1, 1 } },
1326 { ISD::SHL, MVT::v8i32, { 1, 1, 1, 1 } },
1327 { ISD::SRL, MVT::v8i32, { 1, 1, 1, 1 } },
1328 { ISD::SRA, MVT::v8i32, { 1, 1, 1, 1 } },
1329 { ISD::SHL, MVT::v16i32, { 1, 1, 1, 1 } },
1330 { ISD::SRL, MVT::v16i32, { 1, 1, 1, 1 } },
1331 { ISD::SRA, MVT::v16i32, { 1, 1, 1, 1 } },
1332
1333 { ISD::SHL, MVT::v2i64, { 1, 1, 1, 1 } },
1334 { ISD::SRL, MVT::v2i64, { 1, 1, 1, 1 } },
1335 { ISD::SRA, MVT::v2i64, { 1, 1, 1, 1 } },
1336 { ISD::SHL, MVT::v4i64, { 1, 1, 1, 1 } },
1337 { ISD::SRL, MVT::v4i64, { 1, 1, 1, 1 } },
1338 { ISD::SRA, MVT::v4i64, { 1, 1, 1, 1 } },
1339 { ISD::SHL, MVT::v8i64, { 1, 1, 1, 1 } },
1340 { ISD::SRL, MVT::v8i64, { 1, 1, 1, 1 } },
1341 { ISD::SRA, MVT::v8i64, { 1, 1, 1, 1 } },
1342
1343 { ISD::ADD, MVT::v64i8, { 3, 7, 5, 5 } }, // 2*paddb + split
1344 { ISD::ADD, MVT::v32i16, { 3, 7, 5, 5 } }, // 2*paddw + split
1345
1346 { ISD::SUB, MVT::v64i8, { 3, 7, 5, 5 } }, // 2*psubb + split
1347 { ISD::SUB, MVT::v32i16, { 3, 7, 5, 5 } }, // 2*psubw + split
1348
1349 { ISD::AND, MVT::v32i8, { 1, 1, 1, 1 } },
1350 { ISD::AND, MVT::v16i16, { 1, 1, 1, 1 } },
1351 { ISD::AND, MVT::v8i32, { 1, 1, 1, 1 } },
1352 { ISD::AND, MVT::v4i64, { 1, 1, 1, 1 } },
1353
1354 { ISD::OR, MVT::v32i8, { 1, 1, 1, 1 } },
1355 { ISD::OR, MVT::v16i16, { 1, 1, 1, 1 } },
1356 { ISD::OR, MVT::v8i32, { 1, 1, 1, 1 } },
1357 { ISD::OR, MVT::v4i64, { 1, 1, 1, 1 } },
1358
1359 { ISD::XOR, MVT::v32i8, { 1, 1, 1, 1 } },
1360 { ISD::XOR, MVT::v16i16, { 1, 1, 1, 1 } },
1361 { ISD::XOR, MVT::v8i32, { 1, 1, 1, 1 } },
1362 { ISD::XOR, MVT::v4i64, { 1, 1, 1, 1 } },
1363
1364 { ISD::MUL, MVT::v16i32, { 1, 10, 1, 2 } }, // pmulld (Skylake from agner.org)
1365 { ISD::MUL, MVT::v8i32, { 1, 10, 1, 2 } }, // pmulld (Skylake from agner.org)
1366 { ISD::MUL, MVT::v4i32, { 1, 10, 1, 2 } }, // pmulld (Skylake from agner.org)
1367 { ISD::MUL, MVT::v8i64, { 6, 9, 8, 8 } }, // 3*pmuludq/3*shift/2*add
1368 { ISD::MUL, MVT::i64, { 1 } }, // Skylake from http://www.agner.org/
1369
1370 { X86ISD::PMULUDQ, MVT::v8i64, { 1, 5, 1, 1 } },
1371
1372 { ISD::FNEG, MVT::v8f64, { 1, 1, 1, 2 } }, // Skylake from http://www.agner.org/
1373 { ISD::FADD, MVT::v8f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1374 { ISD::FADD, MVT::v4f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1375 { ISD::FSUB, MVT::v8f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1376 { ISD::FSUB, MVT::v4f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1377 { ISD::FMUL, MVT::v8f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1378 { ISD::FMUL, MVT::v4f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1379 { ISD::FMUL, MVT::v2f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1380 { ISD::FMUL, MVT::f64, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1381
1382 { ISD::FDIV, MVT::f64, { 4, 14, 1, 1 } }, // Skylake from http://www.agner.org/
1383 { ISD::FDIV, MVT::v2f64, { 4, 14, 1, 1 } }, // Skylake from http://www.agner.org/
1384 { ISD::FDIV, MVT::v4f64, { 8, 14, 1, 1 } }, // Skylake from http://www.agner.org/
1385 { ISD::FDIV, MVT::v8f64, { 16, 23, 1, 3 } }, // Skylake from http://www.agner.org/
1386
1387 { ISD::FNEG, MVT::v16f32, { 1, 1, 1, 2 } }, // Skylake from http://www.agner.org/
1388 { ISD::FADD, MVT::v16f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1389 { ISD::FADD, MVT::v8f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1390 { ISD::FSUB, MVT::v16f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1391 { ISD::FSUB, MVT::v8f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1392 { ISD::FMUL, MVT::v16f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1393 { ISD::FMUL, MVT::v8f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1394 { ISD::FMUL, MVT::v4f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1395 { ISD::FMUL, MVT::f32, { 1, 4, 1, 1 } }, // Skylake from http://www.agner.org/
1396
1397 { ISD::FDIV, MVT::f32, { 3, 11, 1, 1 } }, // Skylake from http://www.agner.org/
1398 { ISD::FDIV, MVT::v4f32, { 3, 11, 1, 1 } }, // Skylake from http://www.agner.org/
1399 { ISD::FDIV, MVT::v8f32, { 5, 11, 1, 1 } }, // Skylake from http://www.agner.org/
1400 { ISD::FDIV, MVT::v16f32, { 10, 18, 1, 3 } }, // Skylake from http://www.agner.org/
1401 };
1402
1403 if (ST->hasAVX512())
1404 if (const auto *Entry = CostTableLookup(AVX512CostTable, ISD, LT.second))
1405 if (auto KindCost = Entry->Cost[CostKind])
1406 return LT.first * *KindCost;
1407
1408 static const CostKindTblEntry AVX2ShiftCostTable[] = {
1409 // Shifts on vXi64/vXi32 on AVX2 is legal even though we declare to
1410 // customize them to detect the cases where shift amount is a scalar one.
1411 { ISD::SHL, MVT::v4i32, { 2, 3, 1, 3 } }, // vpsllvd (Haswell from agner.org)
1412 { ISD::SRL, MVT::v4i32, { 2, 3, 1, 3 } }, // vpsrlvd (Haswell from agner.org)
1413 { ISD::SRA, MVT::v4i32, { 2, 3, 1, 3 } }, // vpsravd (Haswell from agner.org)
1414 { ISD::SHL, MVT::v8i32, { 4, 4, 1, 3 } }, // vpsllvd (Haswell from agner.org)
1415 { ISD::SRL, MVT::v8i32, { 4, 4, 1, 3 } }, // vpsrlvd (Haswell from agner.org)
1416 { ISD::SRA, MVT::v8i32, { 4, 4, 1, 3 } }, // vpsravd (Haswell from agner.org)
1417 { ISD::SHL, MVT::v2i64, { 2, 3, 1, 1 } }, // vpsllvq (Haswell from agner.org)
1418 { ISD::SRL, MVT::v2i64, { 2, 3, 1, 1 } }, // vpsrlvq (Haswell from agner.org)
1419 { ISD::SHL, MVT::v4i64, { 4, 4, 1, 2 } }, // vpsllvq (Haswell from agner.org)
1420 { ISD::SRL, MVT::v4i64, { 4, 4, 1, 2 } }, // vpsrlvq (Haswell from agner.org)
1421 };
1422
1423 if (ST->hasAVX512()) {
1424 if (ISD == ISD::SHL && LT.second == MVT::v32i16 && Op2Info.isConstant())
1425 // On AVX512, a packed v32i16 shift left by a constant build_vector
1426 // is lowered into a vector multiply (vpmullw).
1427 return getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
1428 Op1Info.getNoProps(), Op2Info.getNoProps());
1429 }
1430
1431 // Look for AVX2 lowering tricks (XOP is always better at v4i32 shifts).
1432 if (ST->hasAVX2() && !(ST->hasXOP() && LT.second == MVT::v4i32)) {
1433 if (ISD == ISD::SHL && LT.second == MVT::v16i16 &&
1434 Op2Info.isConstant())
1435 // On AVX2, a packed v16i16 shift left by a constant build_vector
1436 // is lowered into a vector multiply (vpmullw).
1437 return getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
1438 Op1Info.getNoProps(), Op2Info.getNoProps());
1439
1440 if (const auto *Entry = CostTableLookup(AVX2ShiftCostTable, ISD, LT.second))
1441 if (auto KindCost = Entry->Cost[CostKind])
1442 return LT.first * *KindCost;
1443 }
1444
1445 static const CostKindTblEntry XOPShiftCostTable[] = {
1446 // 128bit shifts take 1cy, but right shifts require negation beforehand.
1447 { ISD::SHL, MVT::v16i8, { 1, 3, 1, 1 } },
1448 { ISD::SRL, MVT::v16i8, { 2, 3, 1, 1 } },
1449 { ISD::SRA, MVT::v16i8, { 2, 3, 1, 1 } },
1450 { ISD::SHL, MVT::v8i16, { 1, 3, 1, 1 } },
1451 { ISD::SRL, MVT::v8i16, { 2, 3, 1, 1 } },
1452 { ISD::SRA, MVT::v8i16, { 2, 3, 1, 1 } },
1453 { ISD::SHL, MVT::v4i32, { 1, 3, 1, 1 } },
1454 { ISD::SRL, MVT::v4i32, { 2, 3, 1, 1 } },
1455 { ISD::SRA, MVT::v4i32, { 2, 3, 1, 1 } },
1456 { ISD::SHL, MVT::v2i64, { 1, 3, 1, 1 } },
1457 { ISD::SRL, MVT::v2i64, { 2, 3, 1, 1 } },
1458 { ISD::SRA, MVT::v2i64, { 2, 3, 1, 1 } },
1459 // 256bit shifts require splitting if AVX2 didn't catch them above.
1460 { ISD::SHL, MVT::v32i8, { 4, 7, 5, 6 } },
1461 { ISD::SRL, MVT::v32i8, { 6, 7, 5, 6 } },
1462 { ISD::SRA, MVT::v32i8, { 6, 7, 5, 6 } },
1463 { ISD::SHL, MVT::v16i16, { 4, 7, 5, 6 } },
1464 { ISD::SRL, MVT::v16i16, { 6, 7, 5, 6 } },
1465 { ISD::SRA, MVT::v16i16, { 6, 7, 5, 6 } },
1466 { ISD::SHL, MVT::v8i32, { 4, 7, 5, 6 } },
1467 { ISD::SRL, MVT::v8i32, { 6, 7, 5, 6 } },
1468 { ISD::SRA, MVT::v8i32, { 6, 7, 5, 6 } },
1469 { ISD::SHL, MVT::v4i64, { 4, 7, 5, 6 } },
1470 { ISD::SRL, MVT::v4i64, { 6, 7, 5, 6 } },
1471 { ISD::SRA, MVT::v4i64, { 6, 7, 5, 6 } },
1472 };
1473
1474 // Look for XOP lowering tricks.
1475 if (ST->hasXOP()) {
1476 // If the right shift is constant then we'll fold the negation so
1477 // it's as cheap as a left shift.
1478 int ShiftISD = ISD;
1479 if ((ShiftISD == ISD::SRL || ShiftISD == ISD::SRA) && Op2Info.isConstant())
1480 ShiftISD = ISD::SHL;
1481 if (const auto *Entry =
1482 CostTableLookup(XOPShiftCostTable, ShiftISD, LT.second))
1483 if (auto KindCost = Entry->Cost[CostKind])
1484 return LT.first * *KindCost;
1485 }
1486
1487 if (ISD == ISD::SHL && !Op2Info.isUniform() && Op2Info.isConstant()) {
1488 MVT VT = LT.second;
1489 // Vector shift left by non uniform constant can be lowered
1490 // into vector multiply.
1491 if (((VT == MVT::v8i16 || VT == MVT::v4i32) && ST->hasSSE2()) ||
1492 ((VT == MVT::v16i16 || VT == MVT::v8i32) && ST->hasAVX()))
1493 ISD = ISD::MUL;
1494 }
1495
1496 static const CostKindTblEntry GLMCostTable[] = {
1497 { ISD::FDIV, MVT::f32, { 18, 19, 1, 1 } }, // divss
1498 { ISD::FDIV, MVT::v4f32, { 35, 36, 1, 1 } }, // divps
1499 { ISD::FDIV, MVT::f64, { 33, 34, 1, 1 } }, // divsd
1500 { ISD::FDIV, MVT::v2f64, { 65, 66, 1, 1 } }, // divpd
1501 };
1502
1503 if (ST->useGLMDivSqrtCosts())
1504 if (const auto *Entry = CostTableLookup(GLMCostTable, ISD, LT.second))
1505 if (auto KindCost = Entry->Cost[CostKind])
1506 return LT.first * *KindCost;
1507
1508 static const CostKindTblEntry SLMCostTable[] = {
1509 { ISD::MUL, MVT::v4i32, { 11, 11, 1, 7 } }, // pmulld
1510 { ISD::MUL, MVT::v8i16, { 2, 5, 1, 1 } }, // pmullw
1511 { ISD::FMUL, MVT::f64, { 2, 5, 1, 1 } }, // mulsd
1512 { ISD::FMUL, MVT::f32, { 1, 4, 1, 1 } }, // mulss
1513 { ISD::FMUL, MVT::v2f64, { 4, 7, 1, 1 } }, // mulpd
1514 { ISD::FMUL, MVT::v4f32, { 2, 5, 1, 1 } }, // mulps
1515 { ISD::FDIV, MVT::f32, { 17, 19, 1, 1 } }, // divss
1516 { ISD::FDIV, MVT::v4f32, { 39, 39, 1, 6 } }, // divps
1517 { ISD::FDIV, MVT::f64, { 32, 34, 1, 1 } }, // divsd
1518 { ISD::FDIV, MVT::v2f64, { 69, 69, 1, 6 } }, // divpd
1519 { ISD::FADD, MVT::v2f64, { 2, 4, 1, 1 } }, // addpd
1520 { ISD::FSUB, MVT::v2f64, { 2, 4, 1, 1 } }, // subpd
1521 // v2i64/v4i64 mul is custom lowered as a series of long:
1522 // multiplies(3), shifts(3) and adds(2)
1523 // slm muldq version throughput is 2 and addq throughput 4
1524 // thus: 3X2 (muldq throughput) + 3X1 (shift throughput) +
1525 // 3X4 (addq throughput) = 17
1526 { ISD::MUL, MVT::v2i64, { 17, 22, 9, 9 } },
1527 // slm addq\subq throughput is 4
1528 { ISD::ADD, MVT::v2i64, { 4, 2, 1, 2 } },
1529 { ISD::SUB, MVT::v2i64, { 4, 2, 1, 2 } },
1530 };
1531
1532 if (ST->useSLMArithCosts())
1533 if (const auto *Entry = CostTableLookup(SLMCostTable, ISD, LT.second))
1534 if (auto KindCost = Entry->Cost[CostKind])
1535 return LT.first * *KindCost;
1536
1537 static const CostKindTblEntry AVX2CostTable[] = {
1538 { ISD::SHL, MVT::v16i8, { 6, 21,11,16 } }, // vpblendvb sequence.
1539 { ISD::SHL, MVT::v32i8, { 6, 23,11,22 } }, // vpblendvb sequence.
1540 { ISD::SHL, MVT::v8i16, { 5, 18, 5,10 } }, // extend/vpsrlvd/pack sequence.
1541 { ISD::SHL, MVT::v16i16, { 8, 10,10,14 } }, // extend/vpsrlvd/pack sequence.
1542
1543 { ISD::SRL, MVT::v16i8, { 6, 27,12,18 } }, // vpblendvb sequence.
1544 { ISD::SRL, MVT::v32i8, { 8, 30,12,24 } }, // vpblendvb sequence.
1545 { ISD::SRL, MVT::v8i16, { 5, 11, 5,10 } }, // extend/vpsrlvd/pack sequence.
1546 { ISD::SRL, MVT::v16i16, { 8, 10,10,14 } }, // extend/vpsrlvd/pack sequence.
1547
1548 { ISD::SRA, MVT::v16i8, { 17, 17,24,30 } }, // vpblendvb sequence.
1549 { ISD::SRA, MVT::v32i8, { 18, 20,24,43 } }, // vpblendvb sequence.
1550 { ISD::SRA, MVT::v8i16, { 5, 11, 5,10 } }, // extend/vpsravd/pack sequence.
1551 { ISD::SRA, MVT::v16i16, { 8, 10,10,14 } }, // extend/vpsravd/pack sequence.
1552 { ISD::SRA, MVT::v2i64, { 4, 5, 5, 5 } }, // srl/xor/sub sequence.
1553 { ISD::SRA, MVT::v4i64, { 8, 8, 5, 9 } }, // srl/xor/sub sequence.
1554
1555 { ISD::SUB, MVT::v32i8, { 1, 1, 1, 2 } }, // psubb
1556 { ISD::ADD, MVT::v32i8, { 1, 1, 1, 2 } }, // paddb
1557 { ISD::SUB, MVT::v16i16, { 1, 1, 1, 2 } }, // psubw
1558 { ISD::ADD, MVT::v16i16, { 1, 1, 1, 2 } }, // paddw
1559 { ISD::SUB, MVT::v8i32, { 1, 1, 1, 2 } }, // psubd
1560 { ISD::ADD, MVT::v8i32, { 1, 1, 1, 2 } }, // paddd
1561 { ISD::SUB, MVT::v4i64, { 1, 1, 1, 2 } }, // psubq
1562 { ISD::ADD, MVT::v4i64, { 1, 1, 1, 2 } }, // paddq
1563
1564 { ISD::MUL, MVT::v16i8, { 5, 18, 6,12 } }, // extend/pmullw/pack
1565 { ISD::MUL, MVT::v32i8, { 4, 8, 8,16 } }, // pmaddubsw
1566 { ISD::MUL, MVT::v16i16, { 2, 5, 1, 2 } }, // pmullw
1567 { ISD::MUL, MVT::v8i32, { 4, 10, 1, 2 } }, // pmulld
1568 { ISD::MUL, MVT::v4i32, { 2, 10, 1, 2 } }, // pmulld
1569 { ISD::MUL, MVT::v4i64, { 6, 10, 8,13 } }, // 3*pmuludq/3*shift/2*add
1570 { ISD::MUL, MVT::v2i64, { 6, 10, 8, 8 } }, // 3*pmuludq/3*shift/2*add
1571
1572 { X86ISD::PMULUDQ, MVT::v4i64, { 1, 5, 1, 1 } },
1573
1574 { ISD::FNEG, MVT::v4f64, { 1, 1, 1, 2 } }, // vxorpd
1575 { ISD::FNEG, MVT::v8f32, { 1, 1, 1, 2 } }, // vxorps
1576
1577 { ISD::FADD, MVT::f64, { 1, 4, 1, 1 } }, // vaddsd
1578 { ISD::FADD, MVT::f32, { 1, 4, 1, 1 } }, // vaddss
1579 { ISD::FADD, MVT::v2f64, { 1, 4, 1, 1 } }, // vaddpd
1580 { ISD::FADD, MVT::v4f32, { 1, 4, 1, 1 } }, // vaddps
1581 { ISD::FADD, MVT::v4f64, { 1, 4, 1, 2 } }, // vaddpd
1582 { ISD::FADD, MVT::v8f32, { 1, 4, 1, 2 } }, // vaddps
1583
1584 { ISD::FSUB, MVT::f64, { 1, 4, 1, 1 } }, // vsubsd
1585 { ISD::FSUB, MVT::f32, { 1, 4, 1, 1 } }, // vsubss
1586 { ISD::FSUB, MVT::v2f64, { 1, 4, 1, 1 } }, // vsubpd
1587 { ISD::FSUB, MVT::v4f32, { 1, 4, 1, 1 } }, // vsubps
1588 { ISD::FSUB, MVT::v4f64, { 1, 4, 1, 2 } }, // vsubpd
1589 { ISD::FSUB, MVT::v8f32, { 1, 4, 1, 2 } }, // vsubps
1590
1591 { ISD::FMUL, MVT::f64, { 1, 5, 1, 1 } }, // vmulsd
1592 { ISD::FMUL, MVT::f32, { 1, 5, 1, 1 } }, // vmulss
1593 { ISD::FMUL, MVT::v2f64, { 1, 5, 1, 1 } }, // vmulpd
1594 { ISD::FMUL, MVT::v4f32, { 1, 5, 1, 1 } }, // vmulps
1595 { ISD::FMUL, MVT::v4f64, { 1, 5, 1, 2 } }, // vmulpd
1596 { ISD::FMUL, MVT::v8f32, { 1, 5, 1, 2 } }, // vmulps
1597
1598 { ISD::FDIV, MVT::f32, { 7, 13, 1, 1 } }, // vdivss
1599 { ISD::FDIV, MVT::v4f32, { 7, 13, 1, 1 } }, // vdivps
1600 { ISD::FDIV, MVT::v8f32, { 14, 21, 1, 3 } }, // vdivps
1601 { ISD::FDIV, MVT::f64, { 14, 20, 1, 1 } }, // vdivsd
1602 { ISD::FDIV, MVT::v2f64, { 14, 20, 1, 1 } }, // vdivpd
1603 { ISD::FDIV, MVT::v4f64, { 28, 35, 1, 3 } }, // vdivpd
1604 };
1605
1606 // Look for AVX2 lowering tricks for custom cases.
1607 if (ST->hasAVX2())
1608 if (const auto *Entry = CostTableLookup(AVX2CostTable, ISD, LT.second))
1609 if (auto KindCost = Entry->Cost[CostKind])
1610 return LT.first * *KindCost;
1611
1612 static const CostKindTblEntry AVX1CostTable[] = {
1613 // We don't have to scalarize unsupported ops. We can issue two half-sized
1614 // operations and we only need to extract the upper YMM half.
1615 // Two ops + 1 extract + 1 insert = 4.
1616 { ISD::MUL, MVT::v32i8, { 10, 11, 18, 19 } }, // pmaddubsw + split
1617 { ISD::MUL, MVT::v16i8, { 5, 6, 8, 12 } }, // 2*pmaddubsw/3*and/psllw/or
1618 { ISD::MUL, MVT::v16i16, { 4, 8, 5, 6 } }, // pmullw + split
1619 { ISD::MUL, MVT::v8i32, { 5, 8, 5, 10 } }, // pmulld + split
1620 { ISD::MUL, MVT::v4i32, { 2, 5, 1, 3 } }, // pmulld
1621 { ISD::MUL, MVT::v4i64, { 12, 15, 19, 20 } },
1622
1623 { X86ISD::PMULUDQ, MVT::v4i64, { 3, 5, 5, 6 } }, // pmuludq + split
1624
1625 { ISD::AND, MVT::v32i8, { 1, 1, 1, 2 } }, // vandps
1626 { ISD::AND, MVT::v16i16, { 1, 1, 1, 2 } }, // vandps
1627 { ISD::AND, MVT::v8i32, { 1, 1, 1, 2 } }, // vandps
1628 { ISD::AND, MVT::v4i64, { 1, 1, 1, 2 } }, // vandps
1629
1630 { ISD::OR, MVT::v32i8, { 1, 1, 1, 2 } }, // vorps
1631 { ISD::OR, MVT::v16i16, { 1, 1, 1, 2 } }, // vorps
1632 { ISD::OR, MVT::v8i32, { 1, 1, 1, 2 } }, // vorps
1633 { ISD::OR, MVT::v4i64, { 1, 1, 1, 2 } }, // vorps
1634
1635 { ISD::XOR, MVT::v32i8, { 1, 1, 1, 2 } }, // vxorps
1636 { ISD::XOR, MVT::v16i16, { 1, 1, 1, 2 } }, // vxorps
1637 { ISD::XOR, MVT::v8i32, { 1, 1, 1, 2 } }, // vxorps
1638 { ISD::XOR, MVT::v4i64, { 1, 1, 1, 2 } }, // vxorps
1639
1640 { ISD::SUB, MVT::v32i8, { 4, 2, 5, 6 } }, // psubb + split
1641 { ISD::ADD, MVT::v32i8, { 4, 2, 5, 6 } }, // paddb + split
1642 { ISD::SUB, MVT::v16i16, { 4, 2, 5, 6 } }, // psubw + split
1643 { ISD::ADD, MVT::v16i16, { 4, 2, 5, 6 } }, // paddw + split
1644 { ISD::SUB, MVT::v8i32, { 4, 2, 5, 6 } }, // psubd + split
1645 { ISD::ADD, MVT::v8i32, { 4, 2, 5, 6 } }, // paddd + split
1646 { ISD::SUB, MVT::v4i64, { 4, 2, 5, 6 } }, // psubq + split
1647 { ISD::ADD, MVT::v4i64, { 4, 2, 5, 6 } }, // paddq + split
1648 { ISD::SUB, MVT::v2i64, { 1, 1, 1, 1 } }, // psubq
1649 { ISD::ADD, MVT::v2i64, { 1, 1, 1, 1 } }, // paddq
1650
1651 { ISD::SHL, MVT::v16i8, { 10, 21,11,17 } }, // pblendvb sequence.
1652 { ISD::SHL, MVT::v32i8, { 22, 22,27,40 } }, // pblendvb sequence + split.
1653 { ISD::SHL, MVT::v8i16, { 6, 9,11,11 } }, // pblendvb sequence.
1654 { ISD::SHL, MVT::v16i16, { 13, 16,24,25 } }, // pblendvb sequence + split.
1655 { ISD::SHL, MVT::v4i32, { 3, 11, 4, 6 } }, // pslld/paddd/cvttps2dq/pmulld
1656 { ISD::SHL, MVT::v8i32, { 9, 11,12,17 } }, // pslld/paddd/cvttps2dq/pmulld + split
1657 { ISD::SHL, MVT::v2i64, { 2, 4, 4, 6 } }, // Shift each lane + blend.
1658 { ISD::SHL, MVT::v4i64, { 6, 7,11,15 } }, // Shift each lane + blend + split.
1659
1660 { ISD::SRL, MVT::v16i8, { 11, 27,12,18 } }, // pblendvb sequence.
1661 { ISD::SRL, MVT::v32i8, { 23, 23,30,43 } }, // pblendvb sequence + split.
1662 { ISD::SRL, MVT::v8i16, { 13, 16,14,22 } }, // pblendvb sequence.
1663 { ISD::SRL, MVT::v16i16, { 28, 30,31,48 } }, // pblendvb sequence + split.
1664 { ISD::SRL, MVT::v4i32, { 6, 7,12,16 } }, // Shift each lane + blend.
1665 { ISD::SRL, MVT::v8i32, { 14, 14,26,34 } }, // Shift each lane + blend + split.
1666 { ISD::SRL, MVT::v2i64, { 2, 4, 4, 6 } }, // Shift each lane + blend.
1667 { ISD::SRL, MVT::v4i64, { 6, 7,11,15 } }, // Shift each lane + blend + split.
1668
1669 { ISD::SRA, MVT::v16i8, { 21, 22,24,36 } }, // pblendvb sequence.
1670 { ISD::SRA, MVT::v32i8, { 44, 45,51,76 } }, // pblendvb sequence + split.
1671 { ISD::SRA, MVT::v8i16, { 13, 16,14,22 } }, // pblendvb sequence.
1672 { ISD::SRA, MVT::v16i16, { 28, 30,31,48 } }, // pblendvb sequence + split.
1673 { ISD::SRA, MVT::v4i32, { 6, 7,12,16 } }, // Shift each lane + blend.
1674 { ISD::SRA, MVT::v8i32, { 14, 14,26,34 } }, // Shift each lane + blend + split.
1675 { ISD::SRA, MVT::v2i64, { 5, 6,10,14 } }, // Shift each lane + blend.
1676 { ISD::SRA, MVT::v4i64, { 12, 12,22,30 } }, // Shift each lane + blend + split.
1677
1678 { ISD::FNEG, MVT::v4f64, { 2, 2, 1, 2 } }, // BTVER2 from http://www.agner.org/
1679 { ISD::FNEG, MVT::v8f32, { 2, 2, 1, 2 } }, // BTVER2 from http://www.agner.org/
1680
1681 { ISD::FADD, MVT::f64, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1682 { ISD::FADD, MVT::f32, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1683 { ISD::FADD, MVT::v2f64, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1684 { ISD::FADD, MVT::v4f32, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1685 { ISD::FADD, MVT::v4f64, { 2, 5, 1, 2 } }, // BDVER2 from http://www.agner.org/
1686 { ISD::FADD, MVT::v8f32, { 2, 5, 1, 2 } }, // BDVER2 from http://www.agner.org/
1687
1688 { ISD::FSUB, MVT::f64, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1689 { ISD::FSUB, MVT::f32, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1690 { ISD::FSUB, MVT::v2f64, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1691 { ISD::FSUB, MVT::v4f32, { 1, 5, 1, 1 } }, // BDVER2 from http://www.agner.org/
1692 { ISD::FSUB, MVT::v4f64, { 2, 5, 1, 2 } }, // BDVER2 from http://www.agner.org/
1693 { ISD::FSUB, MVT::v8f32, { 2, 5, 1, 2 } }, // BDVER2 from http://www.agner.org/
1694
1695 { ISD::FMUL, MVT::f64, { 2, 5, 1, 1 } }, // BTVER2 from http://www.agner.org/
1696 { ISD::FMUL, MVT::f32, { 1, 5, 1, 1 } }, // BTVER2 from http://www.agner.org/
1697 { ISD::FMUL, MVT::v2f64, { 2, 5, 1, 1 } }, // BTVER2 from http://www.agner.org/
1698 { ISD::FMUL, MVT::v4f32, { 1, 5, 1, 1 } }, // BTVER2 from http://www.agner.org/
1699 { ISD::FMUL, MVT::v4f64, { 4, 5, 1, 2 } }, // BTVER2 from http://www.agner.org/
1700 { ISD::FMUL, MVT::v8f32, { 2, 5, 1, 2 } }, // BTVER2 from http://www.agner.org/
1701
1702 { ISD::FDIV, MVT::f32, { 14, 14, 1, 1 } }, // SNB from http://www.agner.org/
1703 { ISD::FDIV, MVT::v4f32, { 14, 14, 1, 1 } }, // SNB from http://www.agner.org/
1704 { ISD::FDIV, MVT::v8f32, { 28, 29, 1, 3 } }, // SNB from http://www.agner.org/
1705 { ISD::FDIV, MVT::f64, { 22, 22, 1, 1 } }, // SNB from http://www.agner.org/
1706 { ISD::FDIV, MVT::v2f64, { 22, 22, 1, 1 } }, // SNB from http://www.agner.org/
1707 { ISD::FDIV, MVT::v4f64, { 44, 45, 1, 3 } }, // SNB from http://www.agner.org/
1708 };
1709
1710 if (ST->hasAVX())
1711 if (const auto *Entry = CostTableLookup(AVX1CostTable, ISD, LT.second))
1712 if (auto KindCost = Entry->Cost[CostKind])
1713 return LT.first * *KindCost;
1714
1715 static const CostKindTblEntry SSE42CostTable[] = {
1716 { ISD::FADD, MVT::f64, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1717 { ISD::FADD, MVT::f32, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1718 { ISD::FADD, MVT::v2f64, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1719 { ISD::FADD, MVT::v4f32, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1720
1721 { ISD::FSUB, MVT::f64, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1722 { ISD::FSUB, MVT::f32 , { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1723 { ISD::FSUB, MVT::v2f64, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1724 { ISD::FSUB, MVT::v4f32, { 1, 3, 1, 1 } }, // Nehalem from http://www.agner.org/
1725
1726 { ISD::FMUL, MVT::f64, { 1, 5, 1, 1 } }, // Nehalem from http://www.agner.org/
1727 { ISD::FMUL, MVT::f32, { 1, 5, 1, 1 } }, // Nehalem from http://www.agner.org/
1728 { ISD::FMUL, MVT::v2f64, { 1, 5, 1, 1 } }, // Nehalem from http://www.agner.org/
1729 { ISD::FMUL, MVT::v4f32, { 1, 5, 1, 1 } }, // Nehalem from http://www.agner.org/
1730
1731 { ISD::FDIV, MVT::f32, { 14, 14, 1, 1 } }, // Nehalem from http://www.agner.org/
1732 { ISD::FDIV, MVT::v4f32, { 14, 14, 1, 1 } }, // Nehalem from http://www.agner.org/
1733 { ISD::FDIV, MVT::f64, { 22, 22, 1, 1 } }, // Nehalem from http://www.agner.org/
1734 { ISD::FDIV, MVT::v2f64, { 22, 22, 1, 1 } }, // Nehalem from http://www.agner.org/
1735
1736 { ISD::MUL, MVT::v2i64, { 6, 10,10,10 } } // 3*pmuludq/3*shift/2*add
1737 };
1738
1739 if (ST->hasSSE42())
1740 if (const auto *Entry = CostTableLookup(SSE42CostTable, ISD, LT.second))
1741 if (auto KindCost = Entry->Cost[CostKind])
1742 return LT.first * *KindCost;
1743
1744 static const CostKindTblEntry SSE41CostTable[] = {
1745 { ISD::SHL, MVT::v16i8, { 15, 24,17,22 } }, // pblendvb sequence.
1746 { ISD::SHL, MVT::v8i16, { 11, 14,11,11 } }, // pblendvb sequence.
1747 { ISD::SHL, MVT::v4i32, { 14, 20, 4,10 } }, // pslld/paddd/cvttps2dq/pmulld
1748
1749 { ISD::SRL, MVT::v16i8, { 16, 27,18,24 } }, // pblendvb sequence.
1750 { ISD::SRL, MVT::v8i16, { 22, 26,23,27 } }, // pblendvb sequence.
1751 { ISD::SRL, MVT::v4i32, { 16, 17,15,19 } }, // Shift each lane + blend.
1752 { ISD::SRL, MVT::v2i64, { 4, 6, 5, 7 } }, // splat+shuffle sequence.
1753
1754 { ISD::SRA, MVT::v16i8, { 38, 41,30,36 } }, // pblendvb sequence.
1755 { ISD::SRA, MVT::v8i16, { 22, 26,23,27 } }, // pblendvb sequence.
1756 { ISD::SRA, MVT::v4i32, { 16, 17,15,19 } }, // Shift each lane + blend.
1757 { ISD::SRA, MVT::v2i64, { 8, 17, 5, 7 } }, // splat+shuffle sequence.
1758
1759 { ISD::MUL, MVT::v4i32, { 2, 11, 1, 1 } } // pmulld (Nehalem from agner.org)
1760 };
1761
1762 if (ST->hasSSE41())
1763 if (const auto *Entry = CostTableLookup(SSE41CostTable, ISD, LT.second))
1764 if (auto KindCost = Entry->Cost[CostKind])
1765 return LT.first * *KindCost;
1766
1767 static const CostKindTblEntry SSSE3CostTable[] = {
1768 { ISD::MUL, MVT::v16i8, { 5, 18,10,12 } }, // 2*pmaddubsw/3*and/psllw/or
1769 };
1770
1771 if (ST->hasSSSE3())
1772 if (const auto *Entry = CostTableLookup(SSSE3CostTable, ISD, LT.second))
1773 if (auto KindCost = Entry->Cost[CostKind])
1774 return LT.first * *KindCost;
1775
1776 static const CostKindTblEntry SSE2CostTable[] = {
1777 // We don't correctly identify costs of casts because they are marked as
1778 // custom.
1779 { ISD::SHL, MVT::v16i8, { 13, 21,26,28 } }, // cmpgtb sequence.
1780 { ISD::SHL, MVT::v8i16, { 24, 27,16,20 } }, // cmpgtw sequence.
1781 { ISD::SHL, MVT::v4i32, { 17, 19,10,12 } }, // pslld/paddd/cvttps2dq/pmuludq.
1782 { ISD::SHL, MVT::v2i64, { 4, 6, 5, 7 } }, // splat+shuffle sequence.
1783
1784 { ISD::SRL, MVT::v16i8, { 14, 28,27,30 } }, // cmpgtb sequence.
1785 { ISD::SRL, MVT::v8i16, { 16, 19,31,31 } }, // cmpgtw sequence.
1786 { ISD::SRL, MVT::v4i32, { 12, 12,15,19 } }, // Shift each lane + blend.
1787 { ISD::SRL, MVT::v2i64, { 4, 6, 5, 7 } }, // splat+shuffle sequence.
1788
1789 { ISD::SRA, MVT::v16i8, { 27, 30,54,54 } }, // unpacked cmpgtb sequence.
1790 { ISD::SRA, MVT::v8i16, { 16, 19,31,31 } }, // cmpgtw sequence.
1791 { ISD::SRA, MVT::v4i32, { 12, 12,15,19 } }, // Shift each lane + blend.
1792 { ISD::SRA, MVT::v2i64, { 8, 11,12,16 } }, // srl/xor/sub splat+shuffle sequence.
1793
1794 { ISD::AND, MVT::v16i8, { 1, 1, 1, 1 } }, // pand
1795 { ISD::AND, MVT::v8i16, { 1, 1, 1, 1 } }, // pand
1796 { ISD::AND, MVT::v4i32, { 1, 1, 1, 1 } }, // pand
1797 { ISD::AND, MVT::v2i64, { 1, 1, 1, 1 } }, // pand
1798
1799 { ISD::OR, MVT::v16i8, { 1, 1, 1, 1 } }, // por
1800 { ISD::OR, MVT::v8i16, { 1, 1, 1, 1 } }, // por
1801 { ISD::OR, MVT::v4i32, { 1, 1, 1, 1 } }, // por
1802 { ISD::OR, MVT::v2i64, { 1, 1, 1, 1 } }, // por
1803
1804 { ISD::XOR, MVT::v16i8, { 1, 1, 1, 1 } }, // pxor
1805 { ISD::XOR, MVT::v8i16, { 1, 1, 1, 1 } }, // pxor
1806 { ISD::XOR, MVT::v4i32, { 1, 1, 1, 1 } }, // pxor
1807 { ISD::XOR, MVT::v2i64, { 1, 1, 1, 1 } }, // pxor
1808
1809 { ISD::ADD, MVT::v2i64, { 1, 2, 1, 2 } }, // paddq
1810 { ISD::SUB, MVT::v2i64, { 1, 2, 1, 2 } }, // psubq
1811
1812 { ISD::MUL, MVT::v16i8, { 6, 18,12,12 } }, // 2*unpack/2*pmullw/2*and/pack
1813 { ISD::MUL, MVT::v8i16, { 1, 5, 1, 1 } }, // pmullw
1814 { ISD::MUL, MVT::v4i32, { 6, 8, 7, 7 } }, // 3*pmuludq/4*shuffle
1815 { ISD::MUL, MVT::v2i64, { 7, 10,10,10 } }, // 3*pmuludq/3*shift/2*add
1816
1817 { X86ISD::PMULUDQ, MVT::v2i64, { 1, 5, 1, 1 } },
1818
1819 { ISD::FDIV, MVT::f32, { 23, 23, 1, 1 } }, // Pentium IV from http://www.agner.org/
1820 { ISD::FDIV, MVT::v4f32, { 39, 39, 1, 1 } }, // Pentium IV from http://www.agner.org/
1821 { ISD::FDIV, MVT::f64, { 38, 38, 1, 1 } }, // Pentium IV from http://www.agner.org/
1822 { ISD::FDIV, MVT::v2f64, { 69, 69, 1, 1 } }, // Pentium IV from http://www.agner.org/
1823
1824 { ISD::FNEG, MVT::f32, { 1, 1, 1, 1 } }, // Pentium IV from http://www.agner.org/
1825 { ISD::FNEG, MVT::f64, { 1, 1, 1, 1 } }, // Pentium IV from http://www.agner.org/
1826 { ISD::FNEG, MVT::v4f32, { 1, 1, 1, 1 } }, // Pentium IV from http://www.agner.org/
1827 { ISD::FNEG, MVT::v2f64, { 1, 1, 1, 1 } }, // Pentium IV from http://www.agner.org/
1828
1829 { ISD::FADD, MVT::f32, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1830 { ISD::FADD, MVT::f64, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1831 { ISD::FADD, MVT::v2f64, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1832
1833 { ISD::FSUB, MVT::f32, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1834 { ISD::FSUB, MVT::f64, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1835 { ISD::FSUB, MVT::v2f64, { 2, 3, 1, 1 } }, // Pentium IV from http://www.agner.org/
1836
1837 { ISD::FMUL, MVT::f64, { 2, 5, 1, 1 } }, // Pentium IV from http://www.agner.org/
1838 { ISD::FMUL, MVT::v2f64, { 2, 5, 1, 1 } }, // Pentium IV from http://www.agner.org/
1839 };
1840
1841 if (ST->hasSSE2())
1842 if (const auto *Entry = CostTableLookup(SSE2CostTable, ISD, LT.second))
1843 if (auto KindCost = Entry->Cost[CostKind])
1844 return LT.first * *KindCost;
1845
1846 static const CostKindTblEntry SSE1CostTable[] = {
1847 { ISD::FDIV, MVT::f32, { 17, 18, 1, 1 } }, // Pentium III from http://www.agner.org/
1848 { ISD::FDIV, MVT::v4f32, { 34, 48, 1, 1 } }, // Pentium III from http://www.agner.org/
1849
1850 { ISD::FNEG, MVT::f32, { 2, 2, 1, 2 } }, // Pentium III from http://www.agner.org/
1851 { ISD::FNEG, MVT::v4f32, { 2, 2, 1, 2 } }, // Pentium III from http://www.agner.org/
1852
1853 { ISD::FADD, MVT::f32, { 1, 3, 1, 1 } }, // Pentium III from http://www.agner.org/
1854 { ISD::FADD, MVT::v4f32, { 2, 3, 1, 1 } }, // Pentium III from http://www.agner.org/
1855
1856 { ISD::FSUB, MVT::f32, { 1, 3, 1, 1 } }, // Pentium III from http://www.agner.org/
1857 { ISD::FSUB, MVT::v4f32, { 2, 3, 1, 1 } }, // Pentium III from http://www.agner.org/
1858
1859 { ISD::FMUL, MVT::f32, { 2, 5, 1, 1 } }, // Pentium III from http://www.agner.org/
1860 { ISD::FMUL, MVT::v4f32, { 2, 5, 1, 1 } }, // Pentium III from http://www.agner.org/
1861 };
1862
1863 if (ST->hasSSE1())
1864 if (const auto *Entry = CostTableLookup(SSE1CostTable, ISD, LT.second))
1865 if (auto KindCost = Entry->Cost[CostKind])
1866 return LT.first * *KindCost;
1867
1868 static const CostKindTblEntry X64CostTbl[] = { // 64-bit targets
1869 { ISD::ADD, MVT::i64, { 1 } }, // Core (Merom) from http://www.agner.org/
1870 { ISD::SUB, MVT::i64, { 1 } }, // Core (Merom) from http://www.agner.org/
1871 { ISD::MUL, MVT::i64, { 2, 6, 1, 2 } },
1872 };
1873
1874 if (ST->is64Bit())
1875 if (const auto *Entry = CostTableLookup(X64CostTbl, ISD, LT.second))
1876 if (auto KindCost = Entry->Cost[CostKind])
1877 return LT.first * *KindCost;
1878
1879 static const CostKindTblEntry X86CostTbl[] = { // 32 or 64-bit targets
1880 { ISD::ADD, MVT::i8, { 1 } }, // Pentium III from http://www.agner.org/
1881 { ISD::ADD, MVT::i16, { 1 } }, // Pentium III from http://www.agner.org/
1882 { ISD::ADD, MVT::i32, { 1 } }, // Pentium III from http://www.agner.org/
1883
1884 { ISD::SUB, MVT::i8, { 1 } }, // Pentium III from http://www.agner.org/
1885 { ISD::SUB, MVT::i16, { 1 } }, // Pentium III from http://www.agner.org/
1886 { ISD::SUB, MVT::i32, { 1 } }, // Pentium III from http://www.agner.org/
1887
1888 { ISD::MUL, MVT::i8, { 3, 4, 1, 1 } },
1889 { ISD::MUL, MVT::i16, { 2, 4, 1, 1 } },
1890 { ISD::MUL, MVT::i32, { 1, 4, 1, 1 } },
1891
1892 { ISD::FNEG, MVT::f64, { 2, 2, 1, 3 } }, // (x87)
1893 { ISD::FADD, MVT::f64, { 2, 3, 1, 1 } }, // (x87)
1894 { ISD::FSUB, MVT::f64, { 2, 3, 1, 1 } }, // (x87)
1895 { ISD::FMUL, MVT::f64, { 2, 5, 1, 1 } }, // (x87)
1896 { ISD::FDIV, MVT::f64, { 38, 38, 1, 1 } }, // (x87)
1897 };
1898
1899 if (const auto *Entry = CostTableLookup(X86CostTbl, ISD, LT.second))
1900 if (auto KindCost = Entry->Cost[CostKind])
1901 return LT.first * *KindCost;
1902
1903 // It is not a good idea to vectorize division. We have to scalarize it and
1904 // in the process we will often end up having to spilling regular
1905 // registers. The overhead of division is going to dominate most kernels
1906 // anyways so try hard to prevent vectorization of division - it is
1907 // generally a bad idea. Assume somewhat arbitrarily that we have to be able
1908 // to hide "20 cycles" for each lane.
1909 if (CostKind == TTI::TCK_RecipThroughput && LT.second.isVector() &&
1910 (ISD == ISD::SDIV || ISD == ISD::SREM || ISD == ISD::UDIV ||
1911 ISD == ISD::UREM)) {
1912 InstructionCost ScalarCost =
1913 getArithmeticInstrCost(Opcode, Ty->getScalarType(), CostKind,
1914 Op1Info.getNoProps(), Op2Info.getNoProps());
1915 return 20 * LT.first * LT.second.getVectorNumElements() * ScalarCost;
1916 }
1917
1918 // Handle some basic single instruction code size cases.
1919 if (CostKind == TTI::TCK_CodeSize) {
1920 switch (ISD) {
1921 case ISD::FADD:
1922 case ISD::FSUB:
1923 case ISD::FMUL:
1924 case ISD::FDIV:
1925 case ISD::FNEG:
1926 case ISD::AND:
1927 case ISD::OR:
1928 case ISD::XOR:
1929 return LT.first;
1930 break;
1931 }
1932 }
1933
1934 // Fallback to the default implementation.
1935 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info,
1936 Args, CtxI);
1937}
1938
1941 unsigned Opcode1, const SmallBitVector &OpcodeMask,
1943 if (isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask))
1944 return TTI::TCC_Basic;
1946}
1947
1949 TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy,
1951 VectorType *SubTp, ArrayRef<const Value *> Args, const Instruction *CtxI,
1952 TTI::VectorInstrContext VIC) const {
1953 assert((Mask.empty() || DstTy->isScalableTy() ||
1954 Mask.size() == DstTy->getElementCount().getKnownMinValue()) &&
1955 "Expected the Mask to match the return size if given");
1956 assert(SrcTy->getScalarType() == DstTy->getScalarType() &&
1957 "Expected the same scalar types");
1958
1959 // 64-bit packed float vectors (v2f32) are widened to type v4f32.
1960 // 64-bit packed integer vectors (v2i32) are widened to type v4i32.
1961 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(SrcTy);
1962
1963 Kind = improveShuffleKindFromMask(Kind, Mask, SrcTy, Index, SubTp);
1964
1965 // If all args are constant than this will be constant folded away.
1966 if (!Args.empty() &&
1967 all_of(Args, [](const Value *Arg) { return isa<Constant>(Arg); }))
1968 return TTI::TCC_Free;
1969
1970 // Recognize a basic concat_vector shuffle.
1971 if (Kind == TTI::SK_PermuteTwoSrc &&
1972 Mask.size() == (2 * SrcTy->getElementCount().getKnownMinValue()) &&
1973 ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
1977 CostKind, Mask, Mask.size() / 2, SrcTy);
1978
1979 // Treat Transpose as 2-op shuffles - there's no difference in lowering.
1980 if (Kind == TTI::SK_Transpose)
1981 if (LT.second != MVT::v4f64 && LT.second != MVT::v4i64)
1982 Kind = TTI::SK_PermuteTwoSrc;
1983
1984 if (Kind == TTI::SK_Broadcast) {
1985 // For Broadcasts we are splatting the first element from the first input
1986 // register, so only need to reference that input and all the output
1987 // registers are the same.
1988 LT.first = 1;
1989
1990 // If we're broadcasting a load then AVX/AVX2 can do this for free.
1991 // If many-used-load whose every use is one of a small set of operations
1992 // that SLP can rewrite into a single vector lane, codegen can fold it into
1993 // the free broadcast.
1994 using namespace PatternMatch;
1995 auto IsBroadcastLoadFoldUser = [&](const User *U) {
1996 if (isa<InsertElementInst>(U) && U->getOperand(1) == Args[0])
1997 return true;
1998 if (U->getType()->isVectorTy())
1999 return false;
2000 // Terminators (return/branch/switch/indirectbr/resume/invoke EH)
2001 // and phis carry the value across control flow.
2002 if (const auto *I = dyn_cast<Instruction>(U))
2003 if (I->isTerminator() ||
2005 return false;
2006 // Only pure calls can be folded.
2007 if (const auto *CB = dyn_cast<CallBase>(U))
2008 return CB->doesNotAccessMemory() && !CB->mayHaveSideEffects();
2009 return true;
2010 };
2011 auto IsFoldableSLPBroadcastLoad = [&]() {
2012 if (!match(Args[0], m_Load(m_Value())))
2013 return false;
2014 auto *FVT = dyn_cast<FixedVectorType>(DstTy);
2015 if (!FVT)
2016 return false;
2017 // getNumUses() counts each Use, matching the per-lane broadcast
2018 // accounting (a use like `op %x, %x` consumes two broadcast lanes).
2019 if (Args[0]->getNumUses() != FVT->getNumElements())
2020 return false;
2021 return all_of(Args[0]->users(), IsBroadcastLoadFoldUser);
2022 };
2023 if (!Args.empty() &&
2024 (match(Args[0], m_OneUse(m_Load(m_Value()))) ||
2025 IsFoldableSLPBroadcastLoad()) &&
2026 (ST->hasAVX2() ||
2027 (ST->hasAVX() && LT.second.getScalarSizeInBits() >= 32)))
2028 return TTI::TCC_Free;
2029 }
2030
2031 // Attempt to detect a cheaper inlane shuffle, avoiding 128-bit subvector
2032 // permutation.
2033 // Attempt to detect a shuffle mask with a single defined element.
2034 bool IsInLaneShuffle = false;
2035 bool IsSingleElementMask = false;
2036 if (SrcTy->getPrimitiveSizeInBits() > 0 &&
2037 (SrcTy->getPrimitiveSizeInBits() % 128) == 0 &&
2038 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
2039 Mask.size() == SrcTy->getElementCount().getKnownMinValue()) {
2040 unsigned NumLanes = SrcTy->getPrimitiveSizeInBits() / 128;
2041 unsigned NumEltsPerLane = Mask.size() / NumLanes;
2042 if ((Mask.size() % NumLanes) == 0) {
2043 IsInLaneShuffle = all_of(enumerate(Mask), [&](const auto &P) {
2044 return P.value() == PoisonMaskElem ||
2045 ((P.value() % Mask.size()) / NumEltsPerLane) ==
2046 (P.index() / NumEltsPerLane);
2047 });
2048 IsSingleElementMask =
2049 (Mask.size() - 1) == static_cast<unsigned>(count_if(Mask, [](int M) {
2050 return M == PoisonMaskElem;
2051 }));
2052 }
2053 }
2054
2055 // Treat <X x bfloat> shuffles as <X x half>.
2056 if (LT.second.isVectorOf(MVT::bf16))
2057 LT.second = LT.second.changeVectorElementType(MVT::f16);
2058
2059 // Subvector extractions are free if they start at the beginning of a
2060 // vector and cheap if the subvectors are aligned.
2061 if (Kind == TTI::SK_ExtractSubvector && LT.second.isVector()) {
2062 int NumElts = LT.second.getVectorNumElements();
2063 if ((Index % NumElts) == 0)
2064 return TTI::TCC_Free;
2065 std::pair<InstructionCost, MVT> SubLT = getTypeLegalizationCost(SubTp);
2066 if (SubLT.second.isVector()) {
2067 int NumSubElts = SubLT.second.getVectorNumElements();
2068 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
2069 return SubLT.first;
2070 // Handle some cases for widening legalization. For now we only handle
2071 // cases where the original subvector was naturally aligned and evenly
2072 // fit in its legalized subvector type.
2073 // FIXME: Remove some of the alignment restrictions.
2074 // FIXME: We can use permq for 64-bit or larger extracts from 256-bit
2075 // vectors.
2076 int OrigSubElts = cast<FixedVectorType>(SubTp)->getNumElements();
2077 if (NumSubElts > OrigSubElts && (Index % OrigSubElts) == 0 &&
2078 (NumSubElts % OrigSubElts) == 0 &&
2079 LT.second.getVectorElementType() ==
2080 SubLT.second.getVectorElementType() &&
2081 LT.second.getVectorElementType().getSizeInBits() ==
2082 SrcTy->getElementType()->getPrimitiveSizeInBits()) {
2083 assert(NumElts >= NumSubElts && NumElts > OrigSubElts &&
2084 "Unexpected number of elements!");
2085 auto *VecTy = FixedVectorType::get(SrcTy->getElementType(),
2086 LT.second.getVectorNumElements());
2087 auto *SubTy = FixedVectorType::get(SrcTy->getElementType(),
2088 SubLT.second.getVectorNumElements());
2089 int ExtractIndex = alignDown((Index % NumElts), NumSubElts);
2090 InstructionCost ExtractCost =
2092 ExtractIndex, SubTy);
2093
2094 // If the original size is 32-bits or more, we can use pshufd. Otherwise
2095 // if we have SSSE3 we can use pshufb.
2096 if (SubTp->getPrimitiveSizeInBits() >= 32 || ST->hasSSSE3())
2097 return ExtractCost + 1; // pshufd or pshufb
2098
2099 assert(SubTp->getPrimitiveSizeInBits() == 16 &&
2100 "Unexpected vector size");
2101
2102 return ExtractCost + 2; // worst case pshufhw + pshufd
2103 }
2104 }
2105 // If the extract subvector is not optimal, treat it as single op shuffle.
2107 }
2108
2109 // Subvector insertions are cheap if the subvectors are aligned.
2110 // Note that in general, the insertion starting at the beginning of a vector
2111 // isn't free, because we need to preserve the rest of the wide vector,
2112 // but if the destination vector legalizes to the same width as the subvector
2113 // then the insertion will simplify to a (free) register copy.
2114 if (Kind == TTI::SK_InsertSubvector && LT.second.isVector()) {
2115 std::pair<InstructionCost, MVT> DstLT = getTypeLegalizationCost(DstTy);
2116 int NumElts = DstLT.second.getVectorNumElements();
2117 std::pair<InstructionCost, MVT> SubLT = getTypeLegalizationCost(SubTp);
2118 if (SubLT.second.isVector()) {
2119 int NumSubElts = SubLT.second.getVectorNumElements();
2120 bool MatchingTypes =
2121 NumElts == NumSubElts &&
2122 (SubTp->getElementCount().getKnownMinValue() % NumSubElts) == 0;
2123 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
2124 return MatchingTypes ? TTI::TCC_Free : SubLT.first;
2125 }
2126
2127 // Attempt to match MOVSS (Idx == 0) or INSERTPS pattern. This will have
2128 // been matched by improveShuffleKindFromMask as a SK_InsertSubvector of
2129 // v1f32 (legalised to f32) into a v4f32.
2130 if (LT.first == 1 && LT.second == MVT::v4f32 && SubLT.first == 1 &&
2131 SubLT.second == MVT::f32 && (Index == 0 || ST->hasSSE41()))
2132 return 1;
2133
2134 // If the insertion is the lowest subvector then it will be blended
2135 // otherwise treat it like a 2-op shuffle.
2136 Kind =
2137 (Index == 0 && LT.first == 1) ? TTI::SK_Select : TTI::SK_PermuteTwoSrc;
2138 }
2139
2140 // Handle some common (illegal) sub-vector types as they are often very cheap
2141 // to shuffle even on targets without PSHUFB.
2142 EVT VT = TLI->getValueType(DL, SrcTy);
2143 if (VT.isSimple() && VT.isVector() && VT.getSizeInBits() < 128 &&
2144 !ST->hasSSSE3()) {
2145 static const CostKindTblEntry SSE2SubVectorShuffleTbl[] = {
2146 {TTI::SK_Broadcast, MVT::v4i16, {1,1,1,1}}, // pshuflw
2147 {TTI::SK_Broadcast, MVT::v2i16, {1,1,1,1}}, // pshuflw
2148 {TTI::SK_Broadcast, MVT::v8i8, {2,2,2,2}}, // punpck/pshuflw
2149 {TTI::SK_Broadcast, MVT::v4i8, {2,2,2,2}}, // punpck/pshuflw
2150 {TTI::SK_Broadcast, MVT::v2i8, {1,1,1,1}}, // punpck
2151
2152 {TTI::SK_Reverse, MVT::v4i16, {1,1,1,1}}, // pshuflw
2153 {TTI::SK_Reverse, MVT::v2i16, {1,1,1,1}}, // pshuflw
2154 {TTI::SK_Reverse, MVT::v4i8, {3,3,3,3}}, // punpck/pshuflw/packus
2155 {TTI::SK_Reverse, MVT::v2i8, {1,1,1,1}}, // punpck
2156
2157 {TTI::SK_Splice, MVT::v4i16, {2,2,2,2}}, // punpck+psrldq
2158 {TTI::SK_Splice, MVT::v2i16, {2,2,2,2}}, // punpck+psrldq
2159 {TTI::SK_Splice, MVT::v4i8, {2,2,2,2}}, // punpck+psrldq
2160 {TTI::SK_Splice, MVT::v2i8, {2,2,2,2}}, // punpck+psrldq
2161
2162 {TTI::SK_PermuteTwoSrc, MVT::v4i16, {2,2,2,2}}, // punpck/pshuflw
2163 {TTI::SK_PermuteTwoSrc, MVT::v2i16, {2,2,2,2}}, // punpck/pshuflw
2164 {TTI::SK_PermuteTwoSrc, MVT::v8i8, {7,7,7,7}}, // punpck/pshuflw
2165 {TTI::SK_PermuteTwoSrc, MVT::v4i8, {4,4,4,4}}, // punpck/pshuflw
2166 {TTI::SK_PermuteTwoSrc, MVT::v2i8, {2,2,2,2}}, // punpck
2167
2168 {TTI::SK_PermuteSingleSrc, MVT::v4i16, {1,1,1,1}}, // pshuflw
2169 {TTI::SK_PermuteSingleSrc, MVT::v2i16, {1,1,1,1}}, // pshuflw
2170 {TTI::SK_PermuteSingleSrc, MVT::v8i8, {5,5,5,5}}, // punpck/pshuflw
2171 {TTI::SK_PermuteSingleSrc, MVT::v4i8, {3,3,3,3}}, // punpck/pshuflw
2172 {TTI::SK_PermuteSingleSrc, MVT::v2i8, {1,1,1,1}}, // punpck
2173 };
2174
2175 if (ST->hasSSE2())
2176 if (const auto *Entry =
2177 CostTableLookup(SSE2SubVectorShuffleTbl, Kind, VT.getSimpleVT()))
2178 if (auto KindCost = Entry->Cost[CostKind])
2179 return LT.first * *KindCost;
2180 }
2181
2182 // We are going to permute multiple sources and the result will be in multiple
2183 // destinations. Providing an accurate cost only for splits where the element
2184 // type remains the same.
2185 if (LT.first != 1) {
2186 MVT LegalVT = LT.second;
2187 if (LegalVT.isVector() &&
2188 LegalVT.getVectorElementType().getSizeInBits() ==
2189 SrcTy->getElementType()->getPrimitiveSizeInBits() &&
2190 LegalVT.getVectorNumElements() <
2191 cast<FixedVectorType>(SrcTy)->getNumElements()) {
2192 unsigned VecTySize = DL.getTypeStoreSize(SrcTy);
2193 unsigned LegalVTSize = LegalVT.getStoreSize();
2194 // Number of source vectors after legalization:
2195 unsigned NumOfSrcs = (VecTySize + LegalVTSize - 1) / LegalVTSize;
2196 // Number of destination vectors after legalization:
2197 InstructionCost NumOfDests = LT.first;
2198
2199 auto *SingleOpTy = FixedVectorType::get(SrcTy->getElementType(),
2200 LegalVT.getVectorNumElements());
2201
2202 if (!Mask.empty() && NumOfDests.isValid()) {
2203 // Try to perform better estimation of the permutation.
2204 // 1. Split the source/destination vectors into real registers.
2205 // 2. Do the mask analysis to identify which real registers are
2206 // permuted. If more than 1 source registers are used for the
2207 // destination register building, the cost for this destination register
2208 // is (Number_of_source_register - 1) * Cost_PermuteTwoSrc. If only one
2209 // source register is used, build mask and calculate the cost as a cost
2210 // of PermuteSingleSrc.
2211 // Also, for the single register permute we try to identify if the
2212 // destination register is just a copy of the source register or the
2213 // copy of the previous destination register (the cost is
2214 // TTI::TCC_Basic). If the source register is just reused, the cost for
2215 // this operation is TTI::TCC_Free.
2216 NumOfDests =
2218 FixedVectorType::get(SrcTy->getElementType(), Mask.size()))
2219 .first;
2220 unsigned E = NumOfDests.getValue();
2221 unsigned NormalizedVF =
2222 LegalVT.getVectorNumElements() * std::max(NumOfSrcs, E);
2223 unsigned NumOfSrcRegs = NormalizedVF / LegalVT.getVectorNumElements();
2224 unsigned NumOfDestRegs = NormalizedVF / LegalVT.getVectorNumElements();
2225 SmallVector<int> NormalizedMask(NormalizedVF, PoisonMaskElem);
2226 copy(Mask, NormalizedMask.begin());
2227 unsigned PrevSrcReg = 0;
2228 ArrayRef<int> PrevRegMask;
2231 NormalizedMask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs, []() {},
2232 [this, SingleOpTy, CostKind, &PrevSrcReg, &PrevRegMask,
2233 &Cost](ArrayRef<int> RegMask, unsigned SrcReg, unsigned DestReg) {
2234 if (!ShuffleVectorInst::isIdentityMask(RegMask, RegMask.size())) {
2235 // Check if the previous register can be just copied to the next
2236 // one.
2237 if (PrevRegMask.empty() || PrevSrcReg != SrcReg ||
2238 PrevRegMask != RegMask)
2239 Cost +=
2241 SingleOpTy, CostKind, RegMask, 0, nullptr);
2242 else
2243 // Just a copy of previous destination register.
2245 return;
2246 }
2247 if (SrcReg != DestReg &&
2248 any_of(RegMask, not_equal_to(PoisonMaskElem))) {
2249 // Just a copy of the source register.
2251 }
2252 PrevSrcReg = SrcReg;
2253 PrevRegMask = RegMask;
2254 },
2255 [this, SingleOpTy, CostKind,
2256 &Cost](ArrayRef<int> RegMask, unsigned /*Unused*/,
2257 unsigned /*Unused*/, bool /*Unused*/) {
2259 SingleOpTy, CostKind, RegMask, 0, nullptr);
2260 });
2261 return Cost;
2262 }
2263
2264 InstructionCost NumOfShuffles = (NumOfSrcs - 1) * NumOfDests;
2265 return NumOfShuffles * getShuffleCost(TTI::SK_PermuteTwoSrc, SingleOpTy,
2266 SingleOpTy, CostKind, {}, 0,
2267 nullptr);
2268 }
2269
2270 return BaseT::getShuffleCost(Kind, DstTy, SrcTy, CostKind, Mask, Index,
2271 SubTp);
2272 }
2273
2274 // If we're just moving a single element around (probably as an alternative to
2275 // extracting it), we can assume this is cheap.
2276 if (LT.first == 1 && IsInLaneShuffle && IsSingleElementMask)
2277 return TTI::TCC_Basic;
2278
2279 static const CostKindTblEntry AVX512VBMIShuffleTbl[] = {
2280 { TTI::SK_Reverse, MVT::v64i8, { 1, 1, 1, 1 } }, // vpermb
2281 { TTI::SK_Reverse, MVT::v32i8, { 1, 1, 1, 1 } }, // vpermb
2282 { TTI::SK_PermuteSingleSrc, MVT::v64i8, { 1, 1, 1, 1 } }, // vpermb
2283 { TTI::SK_PermuteSingleSrc, MVT::v32i8, { 1, 1, 1, 1 } }, // vpermb
2284 { TTI::SK_PermuteTwoSrc, MVT::v64i8, { 2, 2, 2, 2 } }, // vpermt2b
2285 { TTI::SK_PermuteTwoSrc, MVT::v32i8, { 2, 2, 2, 2 } }, // vpermt2b
2286 { TTI::SK_PermuteTwoSrc, MVT::v16i8, { 2, 2, 2, 2 } } // vpermt2b
2287 };
2288
2289 if (ST->hasVBMI())
2290 if (const auto *Entry =
2291 CostTableLookup(AVX512VBMIShuffleTbl, Kind, LT.second))
2292 if (auto KindCost = Entry->Cost[CostKind])
2293 return LT.first * *KindCost;
2294
2295 static const CostKindTblEntry AVX512BWShuffleTbl[] = {
2296 { TTI::SK_Broadcast, MVT::v32i16, { 1, 3, 1, 1 } }, // vpbroadcastw
2297 { TTI::SK_Broadcast, MVT::v32f16, { 1, 3, 1, 1 } }, // vpbroadcastw
2298 { TTI::SK_Broadcast, MVT::v64i8, { 1, 3, 1, 1 } }, // vpbroadcastb
2299
2300 { TTI::SK_Reverse, MVT::v32i16, { 2, 6, 2, 4 } }, // vpermw
2301 { TTI::SK_Reverse, MVT::v32f16, { 2, 6, 2, 4 } }, // vpermw
2302 { TTI::SK_Reverse, MVT::v16i16, { 2, 2, 2, 2 } }, // vpermw
2303 { TTI::SK_Reverse, MVT::v16f16, { 2, 2, 2, 2 } }, // vpermw
2304 { TTI::SK_Reverse, MVT::v64i8, { 2, 9, 2, 3 } }, // pshufb + vshufi64x2
2305
2306 { TTI::SK_PermuteSingleSrc, MVT::v32i16, { 2, 2, 2, 2 } }, // vpermw
2307 { TTI::SK_PermuteSingleSrc, MVT::v32f16, { 2, 2, 2, 2 } }, // vpermw
2308 { TTI::SK_PermuteSingleSrc, MVT::v16i16, { 2, 2, 2, 2 } }, // vpermw
2309 { TTI::SK_PermuteSingleSrc, MVT::v16f16, { 2, 2, 2, 2 } }, // vpermw
2310 { TTI::SK_PermuteSingleSrc, MVT::v64i8, { 8, 8, 8, 8 } }, // extend to v32i16
2311
2312 { TTI::SK_PermuteTwoSrc, MVT::v32i16,{ 2, 2, 2, 2 } }, // vpermt2w
2313 { TTI::SK_PermuteTwoSrc, MVT::v32f16,{ 2, 2, 2, 2 } }, // vpermt2w
2314 { TTI::SK_PermuteTwoSrc, MVT::v16i16,{ 2, 2, 2, 2 } }, // vpermt2w
2315 { TTI::SK_PermuteTwoSrc, MVT::v8i16, { 2, 2, 2, 2 } }, // vpermt2w
2316 { TTI::SK_PermuteTwoSrc, MVT::v64i8, { 19, 19, 19, 19 } }, // 6 * v32i8 + 1
2317
2318 { TTI::SK_Select, MVT::v32i16, { 1, 1, 1, 1 } }, // vblendmw
2319 { TTI::SK_Select, MVT::v64i8, { 1, 1, 1, 1 } }, // vblendmb
2320
2321 { TTI::SK_Splice, MVT::v32i16, { 2, 2, 2, 2 } }, // vshufi64x2 + palignr
2322 { TTI::SK_Splice, MVT::v32f16, { 2, 2, 2, 2 } }, // vshufi64x2 + palignr
2323 { TTI::SK_Splice, MVT::v64i8, { 2, 2, 2, 2 } }, // vshufi64x2 + palignr
2324 };
2325
2326 if (ST->hasBWI())
2327 if (const auto *Entry =
2328 CostTableLookup(AVX512BWShuffleTbl, Kind, LT.second))
2329 if (auto KindCost = Entry->Cost[CostKind])
2330 return LT.first * *KindCost;
2331
2332 static const CostKindTblEntry AVX512InLaneShuffleTbl[] = {
2333 {TTI::SK_PermuteTwoSrc, MVT::v8f64, { 1, 3, 1, 1 } },
2334 {TTI::SK_PermuteTwoSrc, MVT::v16f32, { 1, 3, 1, 1 } },
2335 {TTI::SK_PermuteTwoSrc, MVT::v8i64, { 1, 3, 1, 1 } },
2336 {TTI::SK_PermuteTwoSrc, MVT::v16i32, { 1, 3, 1, 1 } },
2337 {TTI::SK_PermuteTwoSrc, MVT::v4f64, { 1, 3, 1, 1 } },
2338 {TTI::SK_PermuteTwoSrc, MVT::v8f32, { 1, 3, 1, 1 } },
2339 {TTI::SK_PermuteTwoSrc, MVT::v4i64, { 1, 3, 1, 1 } },
2340 {TTI::SK_PermuteTwoSrc, MVT::v8i32, { 1, 3, 1, 1 } },
2341 };
2342
2343 if (IsInLaneShuffle && ST->hasAVX512())
2344 if (const auto *Entry =
2345 CostTableLookup(AVX512InLaneShuffleTbl, Kind, LT.second))
2346 if (auto KindCost = Entry->Cost[CostKind])
2347 return LT.first * *KindCost;
2348
2349 static const CostKindTblEntry AVX512ShuffleTbl[] = {
2350 {TTI::SK_Broadcast, MVT::v8f64, { 1, 3, 1, 1 } }, // vbroadcastsd
2351 {TTI::SK_Broadcast, MVT::v4f64, { 1, 3, 1, 1 } }, // vbroadcastsd
2352 {TTI::SK_Broadcast, MVT::v16f32, { 1, 3, 1, 1 } }, // vbroadcastss
2353 {TTI::SK_Broadcast, MVT::v8f32, { 1, 3, 1, 1 } }, // vbroadcastss
2354 {TTI::SK_Broadcast, MVT::v8i64, { 1, 3, 1, 1 } }, // vpbroadcastq
2355 {TTI::SK_Broadcast, MVT::v4i64, { 1, 3, 1, 1 } }, // vpbroadcastq
2356 {TTI::SK_Broadcast, MVT::v16i32, { 1, 3, 1, 1 } }, // vpbroadcastd
2357 {TTI::SK_Broadcast, MVT::v8i32, { 1, 3, 1, 1 } }, // vpbroadcastd
2358 {TTI::SK_Broadcast, MVT::v32i16, { 1, 3, 1, 1 } }, // vpbroadcastw
2359 {TTI::SK_Broadcast, MVT::v16i16, { 1, 3, 1, 1 } }, // vpbroadcastw
2360 {TTI::SK_Broadcast, MVT::v32f16, { 1, 3, 1, 1 } }, // vpbroadcastw
2361 {TTI::SK_Broadcast, MVT::v16f16, { 1, 3, 1, 1 } }, // vpbroadcastw
2362 {TTI::SK_Broadcast, MVT::v64i8, { 1, 3, 1, 1 } }, // vpbroadcastb
2363 {TTI::SK_Broadcast, MVT::v32i8, { 1, 3, 1, 1 }}, // vpbroadcastb
2364
2365 {TTI::SK_Reverse, MVT::v8f64, { 1, 5, 2, 3 } }, // vpermpd
2366 {TTI::SK_Reverse, MVT::v16f32, { 1, 3, 2, 3 } }, // vpermps
2367 {TTI::SK_Reverse, MVT::v8i64, { 1, 5, 2, 3 } }, // vpermq
2368 {TTI::SK_Reverse, MVT::v16i32, { 1, 3, 2, 3 } }, // vpermd
2369 {TTI::SK_Reverse, MVT::v32i16, { 7, 7, 7, 7 } }, // per mca
2370 {TTI::SK_Reverse, MVT::v32f16, { 7, 7, 7, 7 } }, // per mca
2371 {TTI::SK_Reverse, MVT::v64i8, { 7, 7, 7, 7 } }, // per mca
2372
2373 {TTI::SK_Splice, MVT::v8f64, { 1, 1, 1, 1 } }, // vpalignd
2374 {TTI::SK_Splice, MVT::v4f64, { 1, 1, 1, 1 } }, // vpalignd
2375 {TTI::SK_Splice, MVT::v16f32, { 1, 1, 1, 1 } }, // vpalignd
2376 {TTI::SK_Splice, MVT::v8f32, { 1, 1, 1, 1 } }, // vpalignd
2377 {TTI::SK_Splice, MVT::v8i64, { 1, 1, 1, 1 } }, // vpalignd
2378 {TTI::SK_Splice, MVT::v4i64, { 1, 1, 1, 1 } }, // vpalignd
2379 {TTI::SK_Splice, MVT::v16i32, { 1, 1, 1, 1 } }, // vpalignd
2380 {TTI::SK_Splice, MVT::v8i32, { 1, 1, 1, 1 } }, // vpalignd
2381 {TTI::SK_Splice, MVT::v32i16, { 4, 4, 4, 4 } }, // split + palignr
2382 {TTI::SK_Splice, MVT::v32f16, { 4, 4, 4, 4 } }, // split + palignr
2383 {TTI::SK_Splice, MVT::v64i8, { 4, 4, 4, 4 } }, // split + palignr
2384
2385 {TTI::SK_PermuteSingleSrc, MVT::v8f64, { 1, 3, 1, 1 } }, // vpermpd
2386 {TTI::SK_PermuteSingleSrc, MVT::v4f64, { 1, 3, 1, 1 } }, // vpermpd
2387 {TTI::SK_PermuteSingleSrc, MVT::v2f64, { 1, 3, 1, 1 } }, // vpermpd
2388 {TTI::SK_PermuteSingleSrc, MVT::v16f32, { 1, 3, 1, 1 } }, // vpermps
2389 {TTI::SK_PermuteSingleSrc, MVT::v8f32, { 1, 3, 1, 1 } }, // vpermps
2390 {TTI::SK_PermuteSingleSrc, MVT::v4f32, { 1, 3, 1, 1 } }, // vpermps
2391 {TTI::SK_PermuteSingleSrc, MVT::v8i64, { 1, 3, 1, 1 } }, // vpermq
2392 {TTI::SK_PermuteSingleSrc, MVT::v4i64, { 1, 3, 1, 1 } }, // vpermq
2393 {TTI::SK_PermuteSingleSrc, MVT::v2i64, { 1, 3, 1, 1 } }, // vpermq
2394 {TTI::SK_PermuteSingleSrc, MVT::v16i32, { 1, 3, 1, 1 } }, // vpermd
2395 {TTI::SK_PermuteSingleSrc, MVT::v8i32, { 1, 3, 1, 1 } }, // vpermd
2396 {TTI::SK_PermuteSingleSrc, MVT::v4i32, { 1, 3, 1, 1 } }, // vpermd
2397 {TTI::SK_PermuteSingleSrc, MVT::v16i8, { 1, 3, 1, 1 } }, // pshufb
2398
2399 {TTI::SK_PermuteTwoSrc, MVT::v8f64, { 2, 3, 1, 1 } }, // vpermt2pd
2400 {TTI::SK_PermuteTwoSrc, MVT::v16f32, { 2, 3, 1, 1 } }, // vpermt2ps
2401 {TTI::SK_PermuteTwoSrc, MVT::v8i64, { 2, 3, 1, 1 } }, // vpermt2q
2402 {TTI::SK_PermuteTwoSrc, MVT::v16i32, { 2, 3, 1, 1 } }, // vpermt2d
2403 {TTI::SK_PermuteTwoSrc, MVT::v4f64, { 2, 3, 1, 1 } }, // vpermt2pd
2404 {TTI::SK_PermuteTwoSrc, MVT::v8f32, { 2, 3, 1, 1 } }, // vpermt2ps
2405 {TTI::SK_PermuteTwoSrc, MVT::v4i64, { 2, 3, 1, 1 } }, // vpermt2q
2406 {TTI::SK_PermuteTwoSrc, MVT::v8i32, { 2, 3, 1, 1 } }, // vpermt2d
2407 {TTI::SK_PermuteTwoSrc, MVT::v2f64, { 1, 3, 1, 1 } },
2408 {TTI::SK_PermuteTwoSrc, MVT::v4f32, { 1, 3, 1, 1 } },
2409 {TTI::SK_PermuteTwoSrc, MVT::v2i64, { 1, 3, 1, 1 } },
2410 {TTI::SK_PermuteTwoSrc, MVT::v4i32, { 1, 3, 1, 1 } },
2411
2412 // FIXME: This just applies the type legalization cost rules above
2413 // assuming these completely split.
2414 {TTI::SK_PermuteSingleSrc, MVT::v32i16, { 14, 14, 14, 14 } },
2415 {TTI::SK_PermuteSingleSrc, MVT::v32f16, { 14, 14, 14, 14 } },
2416 {TTI::SK_PermuteSingleSrc, MVT::v64i8, { 14, 14, 14, 14 } },
2417 {TTI::SK_PermuteTwoSrc, MVT::v32i16, { 42, 42, 42, 42 } },
2418 {TTI::SK_PermuteTwoSrc, MVT::v32f16, { 42, 42, 42, 42 } },
2419 {TTI::SK_PermuteTwoSrc, MVT::v64i8, { 42, 42, 42, 42 } },
2420
2421 {TTI::SK_Select, MVT::v32i16, { 1, 1, 1, 1 } }, // vpternlogq
2422 {TTI::SK_Select, MVT::v32f16, { 1, 1, 1, 1 } }, // vpternlogq
2423 {TTI::SK_Select, MVT::v64i8, { 1, 1, 1, 1 } }, // vpternlogq
2424 {TTI::SK_Select, MVT::v8f64, { 1, 1, 1, 1 } }, // vblendmpd
2425 {TTI::SK_Select, MVT::v16f32, { 1, 1, 1, 1 } }, // vblendmps
2426 {TTI::SK_Select, MVT::v8i64, { 1, 1, 1, 1 } }, // vblendmq
2427 {TTI::SK_Select, MVT::v16i32, { 1, 1, 1, 1 } }, // vblendmd
2428 };
2429
2430 if (ST->hasAVX512())
2431 if (const auto *Entry = CostTableLookup(AVX512ShuffleTbl, Kind, LT.second))
2432 if (auto KindCost = Entry->Cost[CostKind])
2433 return LT.first * *KindCost;
2434
2435 static const CostKindTblEntry AVX2InLaneShuffleTbl[] = {
2436 { TTI::SK_PermuteSingleSrc, MVT::v16i16, { 1, 1, 1, 1 } }, // vpshufb
2437 { TTI::SK_PermuteSingleSrc, MVT::v16f16, { 1, 1, 1, 1 } }, // vpshufb
2438 { TTI::SK_PermuteSingleSrc, MVT::v32i8, { 1, 1, 1, 1 } }, // vpshufb
2439
2440 { TTI::SK_Transpose, MVT::v4f64, { 1, 1, 1, 1 } }, // vshufpd/vunpck
2441 { TTI::SK_Transpose, MVT::v4i64, { 1, 1, 1, 1 } }, // vshufpd/vunpck
2442
2443 { TTI::SK_PermuteTwoSrc, MVT::v4f64, { 2, 2, 2, 2 } }, // 2*vshufpd + vblendpd
2444 { TTI::SK_PermuteTwoSrc, MVT::v8f32, { 2, 2, 2, 2 } }, // 2*vshufps + vblendps
2445 { TTI::SK_PermuteTwoSrc, MVT::v4i64, { 2, 2, 2, 2 } }, // 2*vpshufd + vpblendd
2446 { TTI::SK_PermuteTwoSrc, MVT::v8i32, { 2, 2, 2, 2 } }, // 2*vpshufd + vpblendd
2447 { TTI::SK_PermuteTwoSrc, MVT::v16i16, { 2, 2, 2, 2 } }, // 2*vpshufb + vpor
2448 { TTI::SK_PermuteTwoSrc, MVT::v16f16, { 2, 2, 2, 2 } }, // 2*vpshufb + vpor
2449 { TTI::SK_PermuteTwoSrc, MVT::v32i8, { 2, 2, 2, 2 } }, // 2*vpshufb + vpor
2450 };
2451
2452 if (IsInLaneShuffle && ST->hasAVX2())
2453 if (const auto *Entry =
2454 CostTableLookup(AVX2InLaneShuffleTbl, Kind, LT.second))
2455 if (auto KindCost = Entry->Cost[CostKind])
2456 return LT.first * *KindCost;
2457
2458 static const CostKindTblEntry AVX2ShuffleTbl[] = {
2459 { TTI::SK_Broadcast, MVT::v4f64, { 1, 3, 1, 2 } }, // vbroadcastpd
2460 { TTI::SK_Broadcast, MVT::v8f32, { 1, 3, 1, 2 } }, // vbroadcastps
2461 { TTI::SK_Broadcast, MVT::v4i64, { 1, 3, 1, 2 } }, // vpbroadcastq
2462 { TTI::SK_Broadcast, MVT::v8i32, { 1, 3, 1, 2 } }, // vpbroadcastd
2463 { TTI::SK_Broadcast, MVT::v16i16, { 1, 3, 1, 2 } }, // vpbroadcastw
2464 { TTI::SK_Broadcast, MVT::v8i16, { 1, 3, 1, 1 } }, // vpbroadcastw
2465 { TTI::SK_Broadcast, MVT::v16f16, { 1, 3, 1, 2 } }, // vpbroadcastw
2466 { TTI::SK_Broadcast, MVT::v8f16, { 1, 3, 1, 1 } }, // vpbroadcastw
2467 { TTI::SK_Broadcast, MVT::v32i8, { 1, 3, 1, 2 } }, // vpbroadcastb
2468 { TTI::SK_Broadcast, MVT::v16i8, { 1, 3, 1, 1 } }, // vpbroadcastb
2469
2470 { TTI::SK_Reverse, MVT::v4f64, { 1, 6, 1, 2 } }, // vpermpd
2471 { TTI::SK_Reverse, MVT::v8f32, { 2, 7, 2, 4 } }, // vpermps
2472 { TTI::SK_Reverse, MVT::v4i64, { 1, 6, 1, 2 } }, // vpermq
2473 { TTI::SK_Reverse, MVT::v8i32, { 2, 7, 2, 4 } }, // vpermd
2474 { TTI::SK_Reverse, MVT::v16i16, { 2, 9, 2, 4 } }, // vperm2i128 + pshufb
2475 { TTI::SK_Reverse, MVT::v16f16, { 2, 9, 2, 4 } }, // vperm2i128 + pshufb
2476 { TTI::SK_Reverse, MVT::v32i8, { 2, 9, 2, 4 } }, // vperm2i128 + pshufb
2477
2478 { TTI::SK_Select, MVT::v16i16, { 1, 1, 1, 1 } }, // vpblendvb
2479 { TTI::SK_Select, MVT::v16f16, { 1, 1, 1, 1 } }, // vpblendvb
2480 { TTI::SK_Select, MVT::v32i8, { 1, 1, 1, 1 } }, // vpblendvb
2481
2482 { TTI::SK_Splice, MVT::v8i32, { 2, 2, 2, 2 } }, // vperm2i128 + vpalignr
2483 { TTI::SK_Splice, MVT::v8f32, { 2, 2, 2, 2 } }, // vperm2i128 + vpalignr
2484 { TTI::SK_Splice, MVT::v16i16, { 2, 2, 2, 2 } }, // vperm2i128 + vpalignr
2485 { TTI::SK_Splice, MVT::v16f16, { 2, 2, 2, 2 } }, // vperm2i128 + vpalignr
2486 { TTI::SK_Splice, MVT::v32i8, { 2, 2, 2, 2 } }, // vperm2i128 + vpalignr
2487
2488 { TTI::SK_PermuteSingleSrc, MVT::v4f64, { 1, 1, 1, 1 } }, // vpermpd
2489 { TTI::SK_PermuteSingleSrc, MVT::v8f32, { 1, 1, 1, 1 } }, // vpermps
2490 { TTI::SK_PermuteSingleSrc, MVT::v4i64, { 1, 1, 1, 1 } }, // vpermq
2491 { TTI::SK_PermuteSingleSrc, MVT::v8i32, { 1, 1, 1, 1 } }, // vpermd
2492 { TTI::SK_PermuteSingleSrc, MVT::v16i16, { 4, 4, 4, 4 } },
2493 { TTI::SK_PermuteSingleSrc, MVT::v16f16, { 4, 4, 4, 4 } },
2494 { TTI::SK_PermuteSingleSrc, MVT::v32i8, { 4, 4, 4, 4 } },
2495
2496 { TTI::SK_PermuteTwoSrc, MVT::v4f64, { 3, 3, 3, 3 } }, // 2*vpermpd + vblendpd
2497 { TTI::SK_PermuteTwoSrc, MVT::v8f32, { 3, 3, 3, 3 } }, // 2*vpermps + vblendps
2498 { TTI::SK_PermuteTwoSrc, MVT::v4i64, { 3, 3, 3, 3 } }, // 2*vpermq + vpblendd
2499 { TTI::SK_PermuteTwoSrc, MVT::v8i32, { 3, 3, 3, 3 } }, // 2*vpermd + vpblendd
2500 { TTI::SK_PermuteTwoSrc, MVT::v16i16, { 7, 7, 7, 7 } },
2501 { TTI::SK_PermuteTwoSrc, MVT::v16f16, { 7, 7, 7, 7 } },
2502 { TTI::SK_PermuteTwoSrc, MVT::v32i8, { 7, 7, 7, 7 } },
2503 };
2504
2505 if (ST->hasAVX2())
2506 if (const auto *Entry = CostTableLookup(AVX2ShuffleTbl, Kind, LT.second))
2507 if (auto KindCost = Entry->Cost[CostKind])
2508 return LT.first * *KindCost;
2509
2510 static const CostKindTblEntry XOPShuffleTbl[] = {
2511 { TTI::SK_PermuteSingleSrc, MVT::v4f64, { 2, 2, 2, 2 } }, // vperm2f128 + vpermil2pd
2512 { TTI::SK_PermuteSingleSrc, MVT::v8f32, { 2, 2, 2, 2 } }, // vperm2f128 + vpermil2ps
2513 { TTI::SK_PermuteSingleSrc, MVT::v4i64, { 2, 2, 2, 2 } }, // vperm2f128 + vpermil2pd
2514 { TTI::SK_PermuteSingleSrc, MVT::v8i32, { 2, 2, 2, 2 } }, // vperm2f128 + vpermil2ps
2515 { TTI::SK_PermuteSingleSrc, MVT::v16i16,{ 4, 4, 4, 4 } }, // vextractf128 + 2*vpperm
2516 // + vinsertf128
2517 { TTI::SK_PermuteSingleSrc, MVT::v32i8, { 4, 4, 4, 4 } }, // vextractf128 + 2*vpperm
2518 // + vinsertf128
2519
2520 { TTI::SK_PermuteTwoSrc, MVT::v16i16, { 9, 9, 9, 9 } }, // 2*vextractf128 + 6*vpperm
2521 // + vinsertf128
2522
2523 { TTI::SK_PermuteTwoSrc, MVT::v8i16, { 1, 1, 1, 1 } }, // vpperm
2524 { TTI::SK_PermuteTwoSrc, MVT::v32i8, { 9, 9, 9, 9 } }, // 2*vextractf128 + 6*vpperm
2525 // + vinsertf128
2526 { TTI::SK_PermuteTwoSrc, MVT::v16i8, { 1, 1, 1, 1 } }, // vpperm
2527 };
2528
2529 if (ST->hasXOP())
2530 if (const auto *Entry = CostTableLookup(XOPShuffleTbl, Kind, LT.second))
2531 if (auto KindCost = Entry->Cost[CostKind])
2532 return LT.first * *KindCost;
2533
2534 static const CostKindTblEntry AVX1InLaneShuffleTbl[] = {
2535 { TTI::SK_PermuteSingleSrc, MVT::v4f64, { 1, 1, 1, 1 } }, // vpermilpd
2536 { TTI::SK_PermuteSingleSrc, MVT::v4i64, { 1, 1, 1, 1 } }, // vpermilpd
2537 { TTI::SK_PermuteSingleSrc, MVT::v8f32, { 1, 1, 1, 1 } }, // vpermilps
2538 { TTI::SK_PermuteSingleSrc, MVT::v8i32, { 1, 1, 1, 1 } }, // vpermilps
2539
2540 { TTI::SK_PermuteSingleSrc, MVT::v16i16, { 4, 4, 4, 4 } }, // vextractf128 + 2*pshufb
2541 // + vpor + vinsertf128
2542 { TTI::SK_PermuteSingleSrc, MVT::v16f16, { 4, 4, 4, 4 } }, // vextractf128 + 2*pshufb
2543 // + vpor + vinsertf128
2544 { TTI::SK_PermuteSingleSrc, MVT::v32i8, { 4, 4, 4, 4 } }, // vextractf128 + 2*pshufb
2545 // + vpor + vinsertf128
2546
2547 { TTI::SK_Transpose, MVT::v4f64, { 1, 1, 1, 1 } }, // vshufpd/vunpck
2548 { TTI::SK_Transpose, MVT::v4i64, { 1, 1, 1, 1 } }, // vshufpd/vunpck
2549
2550 { TTI::SK_PermuteTwoSrc, MVT::v4f64, { 2, 2, 2, 2 } }, // 2*vshufpd + vblendpd
2551 { TTI::SK_PermuteTwoSrc, MVT::v8f32, { 2, 2, 2, 2 } }, // 2*vshufps + vblendps
2552 { TTI::SK_PermuteTwoSrc, MVT::v4i64, { 2, 2, 2, 2 } }, // 2*vpermilpd + vblendpd
2553 { TTI::SK_PermuteTwoSrc, MVT::v8i32, { 2, 2, 2, 2 } }, // 2*vpermilps + vblendps
2554 { TTI::SK_PermuteTwoSrc, MVT::v16i16, { 9, 9, 9, 9 } }, // 2*vextractf128 + 4*pshufb
2555 // + 2*vpor + vinsertf128
2556 { TTI::SK_PermuteTwoSrc, MVT::v16f16, { 9, 9, 9, 9 } }, // 2*vextractf128 + 4*pshufb
2557 // + 2*vpor + vinsertf128
2558 { TTI::SK_PermuteTwoSrc, MVT::v32i8, { 9, 9, 9, 9 } }, // 2*vextractf128 + 4*pshufb
2559 // + 2*vpor + vinsertf128
2560 };
2561
2562 if (IsInLaneShuffle && ST->hasAVX())
2563 if (const auto *Entry =
2564 CostTableLookup(AVX1InLaneShuffleTbl, Kind, LT.second))
2565 if (auto KindCost = Entry->Cost[CostKind])
2566 return LT.first * *KindCost;
2567
2568 static const CostKindTblEntry AVX1ShuffleTbl[] = {
2569 {TTI::SK_Broadcast, MVT::v4f64, {2,3,2,3}}, // vperm2f128 + vpermilpd
2570 {TTI::SK_Broadcast, MVT::v8f32, {2,3,2,3}}, // vperm2f128 + vpermilps
2571 {TTI::SK_Broadcast, MVT::v4i64, {2,3,2,3}}, // vperm2f128 + vpermilpd
2572 {TTI::SK_Broadcast, MVT::v8i32, {2,3,2,3}}, // vperm2f128 + vpermilps
2573 {TTI::SK_Broadcast, MVT::v16i16, {2,3,3,4}}, // vpshuflw + vpshufd + vinsertf128
2574 {TTI::SK_Broadcast, MVT::v16f16, {2,3,3,4}}, // vpshuflw + vpshufd + vinsertf128
2575 {TTI::SK_Broadcast, MVT::v32i8, {3,4,3,6}}, // vpshufb + vinsertf128
2576
2577 {TTI::SK_Reverse, MVT::v4f64, {2,6,2,2}}, // vperm2f128 + vpermilpd
2578 {TTI::SK_Reverse, MVT::v8f32, {2,7,2,4}}, // vperm2f128 + vpermilps
2579 {TTI::SK_Reverse, MVT::v4i64, {2,6,2,2}}, // vperm2f128 + vpermilpd
2580 {TTI::SK_Reverse, MVT::v8i32, {2,7,2,4}}, // vperm2f128 + vpermilps
2581 {TTI::SK_Reverse, MVT::v16i16, {2,9,5,5}}, // vextractf128 + 2*pshufb
2582 // + vinsertf128
2583 {TTI::SK_Reverse, MVT::v16f16, {2,9,5,5}}, // vextractf128 + 2*pshufb
2584 // + vinsertf128
2585 {TTI::SK_Reverse, MVT::v32i8, {2,9,5,5}}, // vextractf128 + 2*pshufb
2586 // + vinsertf128
2587
2588 {TTI::SK_Select, MVT::v4i64, {1,1,1,1}}, // vblendpd
2589 {TTI::SK_Select, MVT::v4f64, {1,1,1,1}}, // vblendpd
2590 {TTI::SK_Select, MVT::v8i32, {1,1,1,1}}, // vblendps
2591 {TTI::SK_Select, MVT::v8f32, {1,1,1,1}}, // vblendps
2592 {TTI::SK_Select, MVT::v16i16, {3,3,3,3}}, // vpand + vpandn + vpor
2593 {TTI::SK_Select, MVT::v16f16, {3,3,3,3}}, // vpand + vpandn + vpor
2594 {TTI::SK_Select, MVT::v32i8, {3,3,3,3}}, // vpand + vpandn + vpor
2595
2596 {TTI::SK_Splice, MVT::v4i64, {2,2,2,2}}, // vperm2f128 + shufpd
2597 {TTI::SK_Splice, MVT::v4f64, {2,2,2,2}}, // vperm2f128 + shufpd
2598 {TTI::SK_Splice, MVT::v8i32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2599 {TTI::SK_Splice, MVT::v8f32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2600 {TTI::SK_Splice, MVT::v16i16, {5,5,5,5}}, // 2*vperm2f128 + 2*vpalignr + vinsertf128
2601 {TTI::SK_Splice, MVT::v16f16, {5,5,5,5}}, // 2*vperm2f128 + 2*vpalignr + vinsertf128
2602 {TTI::SK_Splice, MVT::v32i8, {5,5,5,5}}, // 2*vperm2f128 + 2*vpalignr + vinsertf128
2603
2604 {TTI::SK_PermuteSingleSrc, MVT::v4f64, {2,2,2,2}}, // vperm2f128 + vshufpd
2605 {TTI::SK_PermuteSingleSrc, MVT::v4i64, {2,2,2,2}}, // vperm2f128 + vshufpd
2606 {TTI::SK_PermuteSingleSrc, MVT::v8f32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2607 {TTI::SK_PermuteSingleSrc, MVT::v8i32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2608 {TTI::SK_PermuteSingleSrc, MVT::v16i16,{8,8,8,8}}, // vextractf128 + 4*pshufb
2609 // + 2*por + vinsertf128
2610 {TTI::SK_PermuteSingleSrc, MVT::v16f16,{8,8,8,8}}, // vextractf128 + 4*pshufb
2611 // + 2*por + vinsertf128
2612 {TTI::SK_PermuteSingleSrc, MVT::v32i8, {8,8,8,8}}, // vextractf128 + 4*pshufb
2613 // + 2*por + vinsertf128
2614
2615 {TTI::SK_PermuteTwoSrc, MVT::v4f64, {3,3,3,3}}, // 2*vperm2f128 + vshufpd
2616 {TTI::SK_PermuteTwoSrc, MVT::v4i64, {3,3,3,3}}, // 2*vperm2f128 + vshufpd
2617 {TTI::SK_PermuteTwoSrc, MVT::v8f32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2618 {TTI::SK_PermuteTwoSrc, MVT::v8i32, {4,4,4,4}}, // 2*vperm2f128 + 2*vshufps
2619 {TTI::SK_PermuteTwoSrc, MVT::v16i16,{15,15,15,15}}, // 2*vextractf128 + 8*pshufb
2620 // + 4*por + vinsertf128
2621 {TTI::SK_PermuteTwoSrc, MVT::v16f16,{15,15,15,15}}, // 2*vextractf128 + 8*pshufb
2622 // + 4*por + vinsertf128
2623 {TTI::SK_PermuteTwoSrc, MVT::v32i8, {15,15,15,15}}, // 2*vextractf128 + 8*pshufb
2624 // + 4*por + vinsertf128
2625 };
2626
2627 if (ST->hasAVX())
2628 if (const auto *Entry = CostTableLookup(AVX1ShuffleTbl, Kind, LT.second))
2629 if (auto KindCost = Entry->Cost[CostKind])
2630 return LT.first * *KindCost;
2631
2632 static const CostKindTblEntry SSE41ShuffleTbl[] = {
2633 {TTI::SK_Select, MVT::v2i64, {1,1,1,1}}, // pblendw
2634 {TTI::SK_Select, MVT::v2f64, {1,1,1,1}}, // movsd
2635 {TTI::SK_Select, MVT::v4i32, {1,1,1,1}}, // pblendw
2636 {TTI::SK_Select, MVT::v4f32, {1,1,1,1}}, // blendps
2637 {TTI::SK_Select, MVT::v8i16, {1,1,1,1}}, // pblendw
2638 {TTI::SK_Select, MVT::v8f16, {1,1,1,1}}, // pblendw
2639 {TTI::SK_Select, MVT::v16i8, {1,1,1,1}} // pblendvb
2640 };
2641
2642 if (ST->hasSSE41())
2643 if (const auto *Entry = CostTableLookup(SSE41ShuffleTbl, Kind, LT.second))
2644 if (auto KindCost = Entry->Cost[CostKind])
2645 return LT.first * *KindCost;
2646
2647 static const CostKindTblEntry SSSE3ShuffleTbl[] = {
2648 {TTI::SK_Broadcast, MVT::v8i16, {1, 3, 2, 2}}, // pshufb
2649 {TTI::SK_Broadcast, MVT::v8f16, {1, 3, 2, 2}}, // pshufb
2650 {TTI::SK_Broadcast, MVT::v16i8, {1, 3, 2, 2}}, // pshufb
2651
2652 {TTI::SK_Reverse, MVT::v8i16, {1, 2, 1, 2}}, // pshufb
2653 {TTI::SK_Reverse, MVT::v8f16, {1, 2, 1, 2}}, // pshufb
2654 {TTI::SK_Reverse, MVT::v16i8, {1, 2, 1, 2}}, // pshufb
2655
2656 {TTI::SK_Splice, MVT::v4i32, {1, 1, 1, 1}}, // palignr
2657 {TTI::SK_Splice, MVT::v4f32, {1, 1, 1, 1}}, // palignr
2658 {TTI::SK_Splice, MVT::v8i16, {1, 1, 1, 1}}, // palignr
2659 {TTI::SK_Splice, MVT::v8f16, {1, 1, 1, 1}}, // palignr
2660 {TTI::SK_Splice, MVT::v16i8, {1, 1, 1, 1}}, // palignr
2661
2662 {TTI::SK_PermuteSingleSrc, MVT::v8i16, {1, 1, 1, 1}}, // pshufb
2663 {TTI::SK_PermuteSingleSrc, MVT::v8f16, {1, 1, 1, 1}}, // pshufb
2664 {TTI::SK_PermuteSingleSrc, MVT::v16i8, {1, 1, 1, 1}}, // pshufb
2665
2666 {TTI::SK_PermuteTwoSrc, MVT::v8i16, {3, 3, 3, 3}}, // 2*pshufb + por
2667 {TTI::SK_PermuteTwoSrc, MVT::v8f16, {3, 3, 3, 3}}, // 2*pshufb + por
2668 {TTI::SK_PermuteTwoSrc, MVT::v16i8, {3, 3, 3, 3}}, // 2*pshufb + por
2669 };
2670
2671 if (ST->hasSSSE3())
2672 if (const auto *Entry = CostTableLookup(SSSE3ShuffleTbl, Kind, LT.second))
2673 if (auto KindCost = Entry->Cost[CostKind])
2674 return LT.first * *KindCost;
2675
2676 static const CostKindTblEntry SSE2ShuffleTbl[] = {
2677 {TTI::SK_Broadcast, MVT::v2f64, {1, 1, 1, 1}}, // shufpd
2678 {TTI::SK_Broadcast, MVT::v2i64, {1, 1, 1, 1}}, // pshufd
2679 {TTI::SK_Broadcast, MVT::v4i32, {1, 1, 1, 1}}, // pshufd
2680 {TTI::SK_Broadcast, MVT::v8i16, {1, 2, 2, 2}}, // pshuflw + pshufd
2681 {TTI::SK_Broadcast, MVT::v8f16, {1, 2, 2, 2}}, // pshuflw + pshufd
2682 {TTI::SK_Broadcast, MVT::v16i8, {2, 3, 3, 4}}, // unpck + pshuflw + pshufd
2683
2684 {TTI::SK_Reverse, MVT::v2f64, {1, 1, 1, 1}}, // shufpd
2685 {TTI::SK_Reverse, MVT::v2i64, {1, 1, 1, 1}}, // pshufd
2686 {TTI::SK_Reverse, MVT::v4i32, {1, 1, 1, 1}}, // pshufd
2687 {TTI::SK_Reverse, MVT::v8i16, {2, 3, 3, 3}}, // pshuflw + pshufhw + pshufd
2688 {TTI::SK_Reverse, MVT::v8f16, {2, 3, 3, 3}}, // pshuflw + pshufhw + pshufd
2689 {TTI::SK_Reverse, MVT::v16i8, {5, 6,11,11}}, // 2*pshuflw + 2*pshufhw
2690 // + 2*pshufd + 2*unpck + packus
2691
2692 {TTI::SK_Select, MVT::v2i64, {1, 1, 1, 1}}, // movsd
2693 {TTI::SK_Select, MVT::v2f64, {1, 1, 1, 1}}, // movsd
2694 {TTI::SK_Select, MVT::v4i32, {2, 2, 2, 2}}, // 2*shufps
2695 {TTI::SK_Select, MVT::v8i16, {2, 2, 3, 3}}, // pand + pandn + por
2696 {TTI::SK_Select, MVT::v8f16, {2, 2, 3, 3}}, // pand + pandn + por
2697 {TTI::SK_Select, MVT::v16i8, {2, 2, 3, 3}}, // pand + pandn + por
2698
2699 {TTI::SK_Splice, MVT::v2i64, {1, 1, 1, 1}}, // shufpd
2700 {TTI::SK_Splice, MVT::v2f64, {1, 1, 1, 1}}, // shufpd
2701 {TTI::SK_Splice, MVT::v4i32, {2, 2, 2, 2}}, // 2*{unpck,movsd,pshufd}
2702 {TTI::SK_Splice, MVT::v8i16, {3, 3, 3, 3}}, // psrldq + psrlldq + por
2703 {TTI::SK_Splice, MVT::v8f16, {3, 3, 3, 3}}, // psrldq + psrlldq + por
2704 {TTI::SK_Splice, MVT::v16i8, {3, 3, 3, 3}}, // psrldq + psrlldq + por
2705
2706 {TTI::SK_PermuteSingleSrc, MVT::v2f64, {1, 1, 1, 1}}, // shufpd
2707 {TTI::SK_PermuteSingleSrc, MVT::v2i64, {1, 1, 1, 1}}, // pshufd
2708 {TTI::SK_PermuteSingleSrc, MVT::v4i32, {1, 1, 1, 1}}, // pshufd
2709 {TTI::SK_PermuteSingleSrc, MVT::v8i16, {3, 5, 5, 5}}, // 2*pshuflw + 2*pshufhw
2710 // + pshufd/unpck
2711 {TTI::SK_PermuteSingleSrc, MVT::v8f16, {3, 5, 5, 5}}, // 2*pshuflw + 2*pshufhw
2712 // + pshufd/unpck
2713 {TTI::SK_PermuteSingleSrc, MVT::v16i8, {8, 10, 10, 10}}, // 2*pshuflw + 2*pshufhw
2714 // + 2*pshufd + 2*unpck + 2*packus
2715
2716 {TTI::SK_PermuteTwoSrc, MVT::v2f64, {1, 1, 1, 1}}, // shufpd
2717 {TTI::SK_PermuteTwoSrc, MVT::v2i64, {1, 1, 1, 1}}, // shufpd
2718 {TTI::SK_PermuteTwoSrc, MVT::v4i32, {2, 2, 2, 2}}, // 2*{unpck,movsd,pshufd}
2719 {TTI::SK_PermuteTwoSrc, MVT::v8i16, {6, 8, 8, 8}}, // blend+permute
2720 {TTI::SK_PermuteTwoSrc, MVT::v8f16, {6, 8, 8, 8}}, // blend+permute
2721 {TTI::SK_PermuteTwoSrc, MVT::v16i8, {11, 13, 13, 13}}, // blend+permute
2722 };
2723
2724 static const CostTblEntry SSE3BroadcastLoadTbl[] = {
2725 {TTI::SK_Broadcast, MVT::v2f64, 0}, // broadcast handled by movddup
2726 };
2727
2728 if (ST->hasSSE2()) {
2729 bool IsLoad =
2730 llvm::any_of(Args, [](const auto &V) { return isa<LoadInst>(V); });
2731 if (ST->hasSSE3() && IsLoad)
2732 if (const auto *Entry =
2733 CostTableLookup(SSE3BroadcastLoadTbl, Kind, LT.second)) {
2734 assert(isLegalBroadcastLoad(SrcTy->getElementType(),
2735 LT.second.getVectorElementCount()) &&
2736 "Table entry missing from isLegalBroadcastLoad()");
2737 return LT.first * Entry->Cost;
2738 }
2739
2740 if (const auto *Entry = CostTableLookup(SSE2ShuffleTbl, Kind, LT.second))
2741 if (auto KindCost = Entry->Cost[CostKind])
2742 return LT.first * *KindCost;
2743 }
2744
2745 static const CostKindTblEntry SSE1ShuffleTbl[] = {
2746 { TTI::SK_Broadcast, MVT::v4f32, {1,1,1,1} }, // shufps
2747 { TTI::SK_Reverse, MVT::v4f32, {1,1,1,1} }, // shufps
2748 { TTI::SK_Select, MVT::v4f32, {2,2,2,2} }, // 2*shufps
2749 { TTI::SK_Splice, MVT::v4f32, {2,2,2,2} }, // 2*shufps
2750 { TTI::SK_PermuteSingleSrc, MVT::v4f32, {1,1,1,1} }, // shufps
2751 { TTI::SK_PermuteTwoSrc, MVT::v4f32, {2,2,2,2} }, // 2*shufps
2752 };
2753
2754 if (ST->hasSSE1()) {
2755 if (LT.first == 1 && LT.second == MVT::v4f32 && Mask.size() == 4) {
2756 // SHUFPS: both pairs must come from the same source register.
2757 auto MatchSHUFPS = [](int X, int Y) {
2758 return X < 0 || Y < 0 || ((X & 4) == (Y & 4));
2759 };
2760 if (MatchSHUFPS(Mask[0], Mask[1]) && MatchSHUFPS(Mask[2], Mask[3]))
2761 return 1;
2762 }
2763 if (const auto *Entry = CostTableLookup(SSE1ShuffleTbl, Kind, LT.second))
2764 if (auto KindCost = Entry->Cost[CostKind])
2765 return LT.first * *KindCost;
2766 }
2767
2768 return BaseT::getShuffleCost(Kind, DstTy, SrcTy, CostKind, Mask, Index,
2769 SubTp);
2770}
2771
2773 Type *Src,
2776 const Instruction *I) const {
2777 int ISD = TLI->InstructionOpcodeToISD(Opcode);
2778 assert(ISD && "Invalid opcode");
2779
2780 // A narrow (i8/i16) zero-extension used as a GEP *index* can be folded into
2781 // the addressing mode of the consuming memory op, but only if the source is
2782 // already materialised zero-extended in a full register. X86's SIB form
2783 // [base + index*scale + disp] reads the index at full width and does NOT
2784 // zero-extend a narrow index (unlike AArch64's uxtw-extended addressing), so
2785 // a "dirty" narrow source (e.g. an i16 add result used only as an index)
2786 // still needs a dedicated movzx and is not free. Price it as free only with
2787 // positive evidence that no movzx is required.
2788 if (ISD == ISD::ZERO_EXTEND && I && I->hasOneUse() && Src->isIntegerTy() &&
2789 Src->getScalarSizeInBits() < 32) {
2790 const Use &U = *I->use_begin();
2791 if (isa<GetElementPtrInst>(U.getUser()) &&
2792 U.getOperandNo() != GetElementPtrInst::getPointerOperandIndex()) {
2793 const Value *Op = I->getOperand(0);
2794 // Clean sources: an extending load, a zeroext argument, or a value whose
2795 // high bits are provably zero (e.g. from a shift/mask). These mirror the
2796 // proof-based reasoning the middle end uses elsewhere (ValueTracking and
2797 // InstCombine's canEvaluateZExtd); we intentionally do NOT treat a merely
2798 // multiply-used operand as clean, since that is a guess rather than
2799 // proof.
2800 if (isa<LoadInst>(Op))
2801 return TTI::TCC_Free;
2802 if (const auto *A = dyn_cast<Argument>(Op))
2803 if (A->hasAttribute(Attribute::ZExt))
2804 return TTI::TCC_Free;
2805 if (computeKnownBits(Op, I->getDataLayout(), /*AC=*/nullptr, I)
2806 .countMinLeadingZeros() > 0)
2807 return TTI::TCC_Free;
2808 }
2809 }
2810
2811 // The cost tables include both specific, custom (non-legal) src/dst type
2812 // conversions and generic, legalized types. We test for customs first, before
2813 // falling back to legalization.
2814 // FIXME: Need a better design of the cost table to handle non-simple types of
2815 // potential massive combinations (elem_num x src_type x dst_type).
2816 static const TypeConversionCostKindTblEntry AVX512BWConversionTbl[]{
2817 { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i8, { 1, 1, 1, 1 } },
2818 { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i8, { 1, 1, 1, 1 } },
2819
2820 // Mask sign extend has an instruction.
2821 { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 1, 1, 1, 1 } },
2822 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v2i1, { 1, 1, 1, 1 } },
2823 { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 1, 1, 1, 1 } },
2824 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v2i1, { 1, 1, 1, 1 } },
2825 { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 1, 1, 1, 1 } },
2826 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v4i1, { 1, 1, 1, 1 } },
2827 { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 1, 1, 1, 1 } },
2828 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v4i1, { 1, 1, 1, 1 } },
2829 { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 1, 1, 1, 1 } },
2830 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v8i1, { 1, 1, 1, 1 } },
2831 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 1, 1, 1, 1 } },
2832 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, { 1, 1, 1, 1 } },
2833 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } },
2834 { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v32i1, { 1, 1, 1, 1 } },
2835 { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i1, { 1, 1, 1, 1 } },
2836 { ISD::SIGN_EXTEND, MVT::v64i8, MVT::v64i1, { 1, 1, 1, 1 } },
2837 { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v64i1, { 1, 1, 1, 1 } },
2838
2839 // Mask zero extend is a sext + shift.
2840 { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 2, 1, 1, 1 } },
2841 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v2i1, { 2, 1, 1, 1 } },
2842 { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 2, 1, 1, 1 } },
2843 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v2i1, { 2, 1, 1, 1 } },
2844 { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 2, 1, 1, 1 } },
2845 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v4i1, { 2, 1, 1, 1 } },
2846 { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 2, 1, 1, 1 } },
2847 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v4i1, { 2, 1, 1, 1 } },
2848 { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 2, 1, 1, 1 } },
2849 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v8i1, { 2, 1, 1, 1 } },
2850 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 2, 1, 1, 1 } },
2851 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, { 2, 1, 1, 1 } },
2852 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 2, 1, 1, 1 } },
2853 { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v32i1, { 2, 1, 1, 1 } },
2854 { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i1, { 2, 1, 1, 1 } },
2855 { ISD::ZERO_EXTEND, MVT::v64i8, MVT::v64i1, { 2, 1, 1, 1 } },
2856 { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v64i1, { 2, 1, 1, 1 } },
2857
2858 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 2, 1, 1, 1 } },
2859 { ISD::TRUNCATE, MVT::v2i1, MVT::v16i8, { 2, 1, 1, 1 } },
2860 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 2, 1, 1, 1 } },
2861 { ISD::TRUNCATE, MVT::v2i1, MVT::v8i16, { 2, 1, 1, 1 } },
2862 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 2, 1, 1, 1 } },
2863 { ISD::TRUNCATE, MVT::v4i1, MVT::v16i8, { 2, 1, 1, 1 } },
2864 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 2, 1, 1, 1 } },
2865 { ISD::TRUNCATE, MVT::v4i1, MVT::v8i16, { 2, 1, 1, 1 } },
2866 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 2, 1, 1, 1 } },
2867 { ISD::TRUNCATE, MVT::v8i1, MVT::v16i8, { 2, 1, 1, 1 } },
2868 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 2, 1, 1, 1 } },
2869 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 2, 1, 1, 1 } },
2870 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 2, 1, 1, 1 } },
2871 { ISD::TRUNCATE, MVT::v32i1, MVT::v32i8, { 2, 1, 1, 1 } },
2872 { ISD::TRUNCATE, MVT::v32i1, MVT::v32i16, { 2, 1, 1, 1 } },
2873 { ISD::TRUNCATE, MVT::v64i1, MVT::v64i8, { 2, 1, 1, 1 } },
2874 { ISD::TRUNCATE, MVT::v64i1, MVT::v32i16, { 2, 1, 1, 1 } },
2875
2876 { ISD::TRUNCATE, MVT::v32i8, MVT::v32i16, { 2, 1, 1, 1 } },
2877 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 2, 1, 1, 1 } }, // widen to zmm
2878 { ISD::TRUNCATE, MVT::v2i8, MVT::v2i16, { 2, 1, 1, 1 } }, // vpmovwb
2879 { ISD::TRUNCATE, MVT::v4i8, MVT::v4i16, { 2, 1, 1, 1 } }, // vpmovwb
2880 { ISD::TRUNCATE, MVT::v8i8, MVT::v8i16, { 2, 1, 1, 1 } }, // vpmovwb
2881 };
2882
2883 static const TypeConversionCostKindTblEntry AVX512DQConversionTbl[] = {
2884 // Mask sign extend has an instruction.
2885 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } },
2886 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v2i1, { 1, 1, 1, 1 } },
2887 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } },
2888 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } },
2889 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } },
2890 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v16i1, { 1, 1, 1, 1 } },
2891 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i1, { 1, 1, 1, 1 } },
2892 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i1, { 1, 1, 1, 1 } },
2893
2894 // Mask zero extend is a sext + shift.
2895 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1, } },
2896 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v2i1, { 2, 1, 1, 1, } },
2897 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1, } },
2898 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1, } },
2899 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1, } },
2900 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v16i1, { 2, 1, 1, 1, } },
2901 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i1, { 2, 1, 1, 1, } },
2902 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i1, { 2, 1, 1, 1, } },
2903
2904 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } },
2905 { ISD::TRUNCATE, MVT::v2i1, MVT::v4i32, { 2, 1, 1, 1 } },
2906 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } },
2907 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } },
2908 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } },
2909 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, { 2, 1, 1, 1 } },
2910 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i32, { 2, 1, 1, 1 } },
2911 { ISD::TRUNCATE, MVT::v16i1, MVT::v8i64, { 2, 1, 1, 1 } },
2912
2913 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i64, { 1, 1, 1, 1 } },
2914 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i64, { 1, 1, 1, 1 } },
2915
2916 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i64, { 1, 1, 1, 1 } },
2917 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i64, { 1, 1, 1, 1 } },
2918
2919 { ISD::FP_TO_SINT, MVT::v8i64, MVT::v8f32, { 1, 1, 1, 1 } },
2920 { ISD::FP_TO_SINT, MVT::v8i64, MVT::v8f64, { 1, 1, 1, 1 } },
2921
2922 { ISD::FP_TO_UINT, MVT::v8i64, MVT::v8f32, { 1, 1, 1, 1 } },
2923 { ISD::FP_TO_UINT, MVT::v8i64, MVT::v8f64, { 1, 1, 1, 1 } },
2924 };
2925
2926 // TODO: For AVX512DQ + AVX512VL, we also have cheap casts for 128-bit and
2927 // 256-bit wide vectors.
2928
2929 static const TypeConversionCostKindTblEntry AVX512FConversionTbl[] = {
2930 { ISD::FP_EXTEND, MVT::v8f64, MVT::v8f32, { 1, 1, 1, 1 } },
2931 { ISD::FP_EXTEND, MVT::v8f64, MVT::v16f32, { 3, 1, 1, 1 } },
2932 { ISD::FP_EXTEND, MVT::v16f64, MVT::v16f32, { 4, 1, 1, 1 } }, // 2*vcvtps2pd+vextractf64x4
2933 { ISD::FP_EXTEND, MVT::v16f32, MVT::v16f16, { 1, 1, 1, 1 } }, // vcvtph2ps
2934 { ISD::FP_EXTEND, MVT::v8f64, MVT::v8f16, { 2, 1, 1, 1 } }, // vcvtph2ps+vcvtps2pd
2935 { ISD::FP_ROUND, MVT::v8f32, MVT::v8f64, { 1, 1, 1, 1 } },
2936 { ISD::FP_ROUND, MVT::v16f16, MVT::v16f32, { 1, 1, 1, 1 } }, // vcvtps2ph
2937
2938 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
2939 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
2940 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
2941 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
2942 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
2943 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
2944 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
2945 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
2946 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, { 2, 1, 1, 1 } }, // zmm vpslld+vptestmd
2947 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } }, // zmm vpslld+vptestmd
2948 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } }, // zmm vpslld+vptestmd
2949 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd
2950 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } }, // zmm vpsllq+vptestmq
2951 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } }, // zmm vpsllq+vptestmq
2952 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, { 2, 1, 1, 1 } }, // vpsllq+vptestmq
2953 { ISD::TRUNCATE, MVT::v2i8, MVT::v2i32, { 2, 1, 1, 1 } }, // vpmovdb
2954 { ISD::TRUNCATE, MVT::v4i8, MVT::v4i32, { 2, 1, 1, 1 } }, // vpmovdb
2955 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdb
2956 { ISD::TRUNCATE, MVT::v32i8, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdb
2957 { ISD::TRUNCATE, MVT::v64i8, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdb
2958 { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdw
2959 { ISD::TRUNCATE, MVT::v32i16, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdw
2960 { ISD::TRUNCATE, MVT::v2i8, MVT::v2i64, { 2, 1, 1, 1 } }, // vpmovqb
2961 { ISD::TRUNCATE, MVT::v2i16, MVT::v2i64, { 1, 1, 1, 1 } }, // vpshufb
2962 { ISD::TRUNCATE, MVT::v8i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb
2963 { ISD::TRUNCATE, MVT::v16i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb
2964 { ISD::TRUNCATE, MVT::v32i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb
2965 { ISD::TRUNCATE, MVT::v64i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb
2966 { ISD::TRUNCATE, MVT::v8i16, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqw
2967 { ISD::TRUNCATE, MVT::v16i16, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqw
2968 { ISD::TRUNCATE, MVT::v32i16, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqw
2969 { ISD::TRUNCATE, MVT::v8i32, MVT::v8i64, { 1, 1, 1, 1 } }, // vpmovqd
2970 { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 1, 1, 1, 1 } }, // zmm vpmovqd
2971 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i64, { 5, 1, 1, 1 } },// 2*vpmovqd+concat+vpmovdb
2972
2973 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 3, 1, 1, 1 } }, // extend to v16i32
2974 { ISD::TRUNCATE, MVT::v32i8, MVT::v32i16, { 8, 1, 1, 1 } },
2975 { ISD::TRUNCATE, MVT::v64i8, MVT::v32i16, { 8, 1, 1, 1 } },
2976
2977 // Sign extend is zmm vpternlogd+vptruncdb.
2978 // Zero extend is zmm broadcast load+vptruncdw.
2979 { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 3, 1, 1, 1 } },
2980 { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 4, 1, 1, 1 } },
2981 { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 3, 1, 1, 1 } },
2982 { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 4, 1, 1, 1 } },
2983 { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 3, 1, 1, 1 } },
2984 { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 4, 1, 1, 1 } },
2985 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, { 3, 1, 1, 1 } },
2986 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, { 4, 1, 1, 1 } },
2987
2988 // Sign extend is zmm vpternlogd+vptruncdw.
2989 // Zero extend is zmm vpternlogd+vptruncdw+vpsrlw.
2990 { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 3, 1, 1, 1 } },
2991 { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 4, 1, 1, 1 } },
2992 { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 3, 1, 1, 1 } },
2993 { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 4, 1, 1, 1 } },
2994 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 3, 1, 1, 1 } },
2995 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 4, 1, 1, 1 } },
2996 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 3, 1, 1, 1 } },
2997 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 4, 1, 1, 1 } },
2998
2999 { ISD::SIGN_EXTEND, MVT::v2i32, MVT::v2i1, { 1, 1, 1, 1 } }, // zmm vpternlogd
3000 { ISD::ZERO_EXTEND, MVT::v2i32, MVT::v2i1, { 2, 1, 1, 1 } }, // zmm vpternlogd+psrld
3001 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } }, // zmm vpternlogd
3002 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1 } }, // zmm vpternlogd+psrld
3003 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } }, // zmm vpternlogd
3004 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1 } }, // zmm vpternlogd+psrld
3005 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } }, // zmm vpternlogq
3006 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1 } }, // zmm vpternlogq+psrlq
3007 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } }, // zmm vpternlogq
3008 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1 } }, // zmm vpternlogq+psrlq
3009
3010 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i1, { 1, 1, 1, 1 } }, // vpternlogd
3011 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld
3012 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i1, { 1, 1, 1, 1 } }, // vpternlogq
3013 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i1, { 2, 1, 1, 1 } }, // vpternlogq+psrlq
3014
3015 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i8, { 1, 1, 1, 1 } },
3016 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i8, { 1, 1, 1, 1 } },
3017 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i16, { 1, 1, 1, 1 } },
3018 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i16, { 1, 1, 1, 1 } },
3019 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i8, { 1, 1, 1, 1 } },
3020 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i8, { 1, 1, 1, 1 } },
3021 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i16, { 1, 1, 1, 1 } },
3022 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i16, { 1, 1, 1, 1 } },
3023 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i32, { 1, 1, 1, 1 } },
3024 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i32, { 1, 1, 1, 1 } },
3025
3026 { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i8, { 3, 1, 1, 1 } }, // FIXME: May not be right
3027 { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i8, { 3, 1, 1, 1 } }, // FIXME: May not be right
3028
3029 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i1, { 4, 1, 1, 1 } },
3030 { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i1, { 3, 1, 1, 1 } },
3031 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v16i8, { 2, 1, 1, 1 } },
3032 { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i8, { 1, 1, 1, 1 } },
3033 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i16, { 2, 1, 1, 1 } },
3034 { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i16, { 1, 1, 1, 1 } },
3035 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, { 1, 1, 1, 1 } },
3036 { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i32, { 1, 1, 1, 1 } },
3037
3038 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i1, { 4, 1, 1, 1 } },
3039 { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i1, { 3, 1, 1, 1 } },
3040 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v16i8, { 2, 1, 1, 1 } },
3041 { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i8, { 1, 1, 1, 1 } },
3042 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i16, { 2, 1, 1, 1 } },
3043 { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i16, { 1, 1, 1, 1 } },
3044 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, { 1, 1, 1, 1 } },
3045 { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i32, { 1, 1, 1, 1 } },
3046 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i64, {26, 1, 1, 1 } },
3047 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i64, { 5, 1, 1, 1 } },
3048
3049 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f32, { 2, 1, 1, 1 } },
3050 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f64, { 7, 1, 1, 1 } },
3051 { ISD::FP_TO_SINT, MVT::v32i8, MVT::v32f64, {15, 1, 1, 1 } },
3052 { ISD::FP_TO_SINT, MVT::v64i8, MVT::v64f32, {11, 1, 1, 1 } },
3053 { ISD::FP_TO_SINT, MVT::v64i8, MVT::v64f64, {31, 1, 1, 1 } },
3054 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f64, { 3, 1, 1, 1 } },
3055 { ISD::FP_TO_SINT, MVT::v16i16, MVT::v16f64, { 7, 1, 1, 1 } },
3056 { ISD::FP_TO_SINT, MVT::v32i16, MVT::v32f32, { 5, 1, 1, 1 } },
3057 { ISD::FP_TO_SINT, MVT::v32i16, MVT::v32f64, {15, 1, 1, 1 } },
3058 { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, { 1, 1, 1, 1 } },
3059 { ISD::FP_TO_SINT, MVT::v16i32, MVT::v16f64, { 3, 1, 1, 1 } },
3060
3061 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f64, { 1, 1, 1, 1 } },
3062 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f64, { 3, 1, 1, 1 } },
3063 { ISD::FP_TO_UINT, MVT::v8i8, MVT::v8f64, { 3, 1, 1, 1 } },
3064 { ISD::FP_TO_UINT, MVT::v16i32, MVT::v16f32, { 1, 1, 1, 1 } },
3065 { ISD::FP_TO_UINT, MVT::v16i16, MVT::v16f32, { 3, 1, 1, 1 } },
3066 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v16f32, { 3, 1, 1, 1 } },
3067 };
3068
3069 static const TypeConversionCostKindTblEntry AVX512BWVLConversionTbl[] {
3070 // Mask sign extend has an instruction.
3071 { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 1, 1, 1, 1 } },
3072 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v2i1, { 1, 1, 1, 1 } },
3073 { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 1, 1, 1, 1 } },
3074 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v2i1, { 1, 1, 1, 1 } },
3075 { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 1, 1, 1, 1 } },
3076 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v4i1, { 1, 1, 1, 1 } },
3077 { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 1, 1, 1, 1 } },
3078 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v4i1, { 1, 1, 1, 1 } },
3079 { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 1, 1, 1, 1 } },
3080 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v8i1, { 1, 1, 1, 1 } },
3081 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 1, 1, 1, 1 } },
3082 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, { 1, 1, 1, 1 } },
3083 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } },
3084 { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v32i1, { 1, 1, 1, 1 } },
3085 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v32i1, { 1, 1, 1, 1 } },
3086 { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v64i1, { 1, 1, 1, 1 } },
3087 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v64i1, { 1, 1, 1, 1 } },
3088
3089 // Mask zero extend is a sext + shift.
3090 { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 2, 1, 1, 1 } },
3091 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v2i1, { 2, 1, 1, 1 } },
3092 { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 2, 1, 1, 1 } },
3093 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v2i1, { 2, 1, 1, 1 } },
3094 { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 2, 1, 1, 1 } },
3095 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v4i1, { 2, 1, 1, 1 } },
3096 { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 2, 1, 1, 1 } },
3097 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v4i1, { 2, 1, 1, 1 } },
3098 { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 2, 1, 1, 1 } },
3099 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v8i1, { 2, 1, 1, 1 } },
3100 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 2, 1, 1, 1 } },
3101 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, { 2, 1, 1, 1 } },
3102 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 2, 1, 1, 1 } },
3103 { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v32i1, { 2, 1, 1, 1 } },
3104 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v32i1, { 2, 1, 1, 1 } },
3105 { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v64i1, { 2, 1, 1, 1 } },
3106 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v64i1, { 2, 1, 1, 1 } },
3107
3108 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 2, 1, 1, 1 } },
3109 { ISD::TRUNCATE, MVT::v2i1, MVT::v16i8, { 2, 1, 1, 1 } },
3110 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 2, 1, 1, 1 } },
3111 { ISD::TRUNCATE, MVT::v2i1, MVT::v8i16, { 2, 1, 1, 1 } },
3112 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 2, 1, 1, 1 } },
3113 { ISD::TRUNCATE, MVT::v4i1, MVT::v16i8, { 2, 1, 1, 1 } },
3114 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 2, 1, 1, 1 } },
3115 { ISD::TRUNCATE, MVT::v4i1, MVT::v8i16, { 2, 1, 1, 1 } },
3116 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 2, 1, 1, 1 } },
3117 { ISD::TRUNCATE, MVT::v8i1, MVT::v16i8, { 2, 1, 1, 1 } },
3118 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 2, 1, 1, 1 } },
3119 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 2, 1, 1, 1 } },
3120 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 2, 1, 1, 1 } },
3121 { ISD::TRUNCATE, MVT::v32i1, MVT::v32i8, { 2, 1, 1, 1 } },
3122 { ISD::TRUNCATE, MVT::v32i1, MVT::v16i16, { 2, 1, 1, 1 } },
3123 { ISD::TRUNCATE, MVT::v64i1, MVT::v32i8, { 2, 1, 1, 1 } },
3124 { ISD::TRUNCATE, MVT::v64i1, MVT::v16i16, { 2, 1, 1, 1 } },
3125
3126 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 2, 1, 1, 1 } },
3127 };
3128
3129 static const TypeConversionCostKindTblEntry AVX512DQVLConversionTbl[] = {
3130 // Mask sign extend has an instruction.
3131 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } },
3132 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v2i1, { 1, 1, 1, 1 } },
3133 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } },
3134 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i1, { 1, 1, 1, 1 } },
3135 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } },
3136 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i1, { 1, 1, 1, 1 } },
3137 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i1, { 1, 1, 1, 1 } },
3138 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } },
3139
3140 // Mask zero extend is a sext + shift.
3141 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1 } },
3142 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v2i1, { 2, 1, 1, 1 } },
3143 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1 } },
3144 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i1, { 2, 1, 1, 1 } },
3145 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1 } },
3146 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i1, { 2, 1, 1, 1 } },
3147 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i1, { 2, 1, 1, 1 } },
3148 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1 } },
3149
3150 { ISD::TRUNCATE, MVT::v16i1, MVT::v4i64, { 2, 1, 1, 1 } },
3151 { ISD::TRUNCATE, MVT::v16i1, MVT::v8i32, { 2, 1, 1, 1 } },
3152 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } },
3153 { ISD::TRUNCATE, MVT::v2i1, MVT::v4i32, { 2, 1, 1, 1 } },
3154 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } },
3155 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } },
3156 { ISD::TRUNCATE, MVT::v8i1, MVT::v4i64, { 2, 1, 1, 1 } },
3157 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } },
3158
3159 { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i64, { 1, 1, 1, 1 } },
3160 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, { 1, 1, 1, 1 } },
3161 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i64, { 1, 1, 1, 1 } },
3162 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i64, { 1, 1, 1, 1 } },
3163
3164 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, { 1, 1, 1, 1 } },
3165 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 1, 1, 1, 1 } },
3166 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, { 1, 1, 1, 1 } },
3167 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, { 1, 1, 1, 1 } },
3168
3169 { ISD::FP_TO_SINT, MVT::v2i64, MVT::v4f32, { 1, 1, 1, 1 } },
3170 { ISD::FP_TO_SINT, MVT::v4i64, MVT::v4f32, { 1, 1, 1, 1 } },
3171 { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, { 1, 1, 1, 1 } },
3172 { ISD::FP_TO_SINT, MVT::v4i64, MVT::v4f64, { 1, 1, 1, 1 } },
3173
3174 { ISD::FP_TO_UINT, MVT::v2i64, MVT::v4f32, { 1, 1, 1, 1 } },
3175 { ISD::FP_TO_UINT, MVT::v4i64, MVT::v4f32, { 1, 1, 1, 1 } },
3176 { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, { 1, 1, 1, 1 } },
3177 { ISD::FP_TO_UINT, MVT::v4i64, MVT::v4f64, { 1, 1, 1, 1 } },
3178 };
3179
3180 static const TypeConversionCostKindTblEntry AVX512VLConversionTbl[] = {
3181 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
3182 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
3183 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd
3184 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 8, 1, 1, 1 } }, // split+2*v8i8
3185 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
3186 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
3187 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq
3188 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 8, 1, 1, 1 } }, // split+2*v8i16
3189 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd
3190 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd
3191 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd
3192 { ISD::TRUNCATE, MVT::v16i1, MVT::v8i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd
3193 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } }, // vpsllq+vptestmq
3194 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } }, // vpsllq+vptestmq
3195 { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 1, 1, 1, 1 } }, // vpmovqd
3196 { ISD::TRUNCATE, MVT::v4i8, MVT::v4i64, { 2, 1, 1, 1 } }, // vpmovqb
3197 { ISD::TRUNCATE, MVT::v4i16, MVT::v4i64, { 2, 1, 1, 1 } }, // vpmovqw
3198 { ISD::TRUNCATE, MVT::v8i8, MVT::v8i32, { 2, 1, 1, 1 } }, // vpmovwb
3199
3200 // sign extend is vpcmpeq+maskedmove+vpmovdw+vpacksswb
3201 // zero extend is vpcmpeq+maskedmove+vpmovdw+vpsrlw+vpackuswb
3202 { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 5, 1, 1, 1 } },
3203 { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 6, 1, 1, 1 } },
3204 { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 5, 1, 1, 1 } },
3205 { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 6, 1, 1, 1 } },
3206 { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 5, 1, 1, 1 } },
3207 { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 6, 1, 1, 1 } },
3208 { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, {10, 1, 1, 1 } },
3209 { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, {12, 1, 1, 1 } },
3210
3211 // sign extend is vpcmpeq+maskedmove+vpmovdw
3212 // zero extend is vpcmpeq+maskedmove+vpmovdw+vpsrlw
3213 { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 4, 1, 1, 1 } },
3214 { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 5, 1, 1, 1 } },
3215 { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 4, 1, 1, 1 } },
3216 { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 5, 1, 1, 1 } },
3217 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 4, 1, 1, 1 } },
3218 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 5, 1, 1, 1 } },
3219 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, {10, 1, 1, 1 } },
3220 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, {12, 1, 1, 1 } },
3221
3222 { ISD::SIGN_EXTEND, MVT::v2i32, MVT::v2i1, { 1, 1, 1, 1 } }, // vpternlogd
3223 { ISD::ZERO_EXTEND, MVT::v2i32, MVT::v2i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld
3224 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } }, // vpternlogd
3225 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld
3226 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } }, // vpternlogd
3227 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld
3228 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i1, { 1, 1, 1, 1 } }, // vpternlogd
3229 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld
3230
3231 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } }, // vpternlogq
3232 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1 } }, // vpternlogq+psrlq
3233 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } }, // vpternlogq
3234 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1 } }, // vpternlogq+psrlq
3235
3236 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, { 1, 1, 1, 1 } },
3237 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, { 1, 1, 1, 1 } },
3238 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, { 1, 1, 1, 1 } },
3239 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, { 1, 1, 1, 1 } },
3240 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, { 1, 1, 1, 1 } },
3241 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, { 1, 1, 1, 1 } },
3242 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, { 1, 1, 1, 1 } },
3243 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, { 1, 1, 1, 1 } },
3244 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, { 1, 1, 1, 1 } },
3245 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, { 1, 1, 1, 1 } },
3246 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, { 1, 1, 1, 1 } },
3247 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, { 1, 1, 1, 1 } },
3248
3249 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } },
3250 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, { 1, 1, 1, 1 } },
3251 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } },
3252 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, { 1, 1, 1, 1 } },
3253
3254 { ISD::UINT_TO_FP, MVT::f32, MVT::i64, { 1, 1, 1, 1 } },
3255 { ISD::UINT_TO_FP, MVT::f64, MVT::i64, { 1, 1, 1, 1 } },
3256 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } },
3257 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, { 1, 1, 1, 1 } },
3258 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } },
3259 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, { 1, 1, 1, 1 } },
3260 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 1, 1, 1, 1 } },
3261 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 1, 1, 1, 1 } },
3262 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, { 1, 1, 1, 1 } },
3263 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, { 1, 1, 1, 1 } },
3264 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, { 5, 1, 1, 1 } },
3265 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 5, 1, 1, 1 } },
3266 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, { 5, 1, 1, 1 } },
3267
3268 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v8f32, { 2, 1, 1, 1 } },
3269 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f32, { 2, 1, 1, 1 } },
3270 { ISD::FP_TO_SINT, MVT::v32i8, MVT::v32f32, { 5, 1, 1, 1 } },
3271
3272 { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 1, 1, 1, 1 } },
3273 { ISD::FP_TO_UINT, MVT::i64, MVT::f64, { 1, 1, 1, 1 } },
3274 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 1, 1, 1, 1 } },
3275 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 1, 1, 1, 1 } },
3276 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, { 1, 1, 1, 1 } },
3277 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, { 1, 1, 1, 1 } },
3278 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f64, { 1, 1, 1, 1 } },
3279 };
3280
3281 static const TypeConversionCostKindTblEntry AVX2ConversionTbl[] = {
3282 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 3, 1, 1, 1 } },
3283 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 3, 1, 1, 1 } },
3284 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 3, 1, 1, 1 } },
3285 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 3, 1, 1, 1 } },
3286 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } },
3287 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } },
3288
3289 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, { 2, 1, 1, 1 } },
3290 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, { 2, 1, 1, 1 } },
3291 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, { 2, 1, 1, 1 } },
3292 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, { 2, 1, 1, 1 } },
3293 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, { 2, 1, 1, 1 } },
3294 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, { 2, 1, 1, 1 } },
3295 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, { 2, 1, 1, 1 } },
3296 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, { 2, 1, 1, 1 } },
3297 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, { 2, 1, 1, 1 } },
3298 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, { 2, 1, 1, 1 } },
3299 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i16, { 3, 1, 1, 1 } },
3300 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i16, { 3, 1, 1, 1 } },
3301 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, { 2, 1, 1, 1 } },
3302 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, { 2, 1, 1, 1 } },
3303
3304 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } },
3305
3306 { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, { 4, 1, 1, 1 } },
3307 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 4, 1, 1, 1 } },
3308 { ISD::TRUNCATE, MVT::v16i8, MVT::v8i16, { 1, 1, 1, 1 } },
3309 { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, { 1, 1, 1, 1 } },
3310 { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, { 1, 1, 1, 1 } },
3311 { ISD::TRUNCATE, MVT::v16i8, MVT::v8i32, { 4, 1, 1, 1 } },
3312 { ISD::TRUNCATE, MVT::v16i8, MVT::v4i64, { 4, 1, 1, 1 } },
3313 { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, { 1, 1, 1, 1 } },
3314 { ISD::TRUNCATE, MVT::v8i16, MVT::v2i64, { 1, 1, 1, 1 } },
3315 { ISD::TRUNCATE, MVT::v8i16, MVT::v4i64, { 5, 1, 1, 1 } },
3316 { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 1, 1, 1, 1 } },
3317 { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, { 2, 1, 1, 1 } },
3318
3319 { ISD::FP_EXTEND, MVT::v8f64, MVT::v8f32, { 3, 1, 1, 1 } },
3320 { ISD::FP_ROUND, MVT::v8f32, MVT::v8f64, { 3, 1, 1, 1 } },
3321
3322 { ISD::FP_TO_SINT, MVT::v16i16, MVT::v8f32, { 1, 1, 1, 1 } },
3323 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f64, { 1, 1, 1, 1 } },
3324 { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f32, { 1, 1, 1, 1 } },
3325 { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, { 3, 1, 1, 1 } },
3326
3327 { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 3, 1, 1, 1 } },
3328 { ISD::FP_TO_UINT, MVT::i64, MVT::f64, { 3, 1, 1, 1 } },
3329 { ISD::FP_TO_UINT, MVT::v16i16, MVT::v8f32, { 1, 1, 1, 1 } },
3330 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 3, 1, 1, 1 } },
3331 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } },
3332 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, { 4, 1, 1, 1 } },
3333 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, { 3, 1, 1, 1 } },
3334 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v4f64, { 4, 1, 1, 1 } },
3335
3336 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 2, 1, 1, 1 } },
3337 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, { 2, 1, 1, 1 } },
3338 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 2, 1, 1, 1 } },
3339 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, { 2, 1, 1, 1 } },
3340 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, { 1, 1, 1, 1 } },
3341 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i32, { 1, 1, 1, 1 } },
3342 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, { 3, 1, 1, 1 } },
3343
3344 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 2, 1, 1, 1 } },
3345 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, { 2, 1, 1, 1 } },
3346 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 2, 1, 1, 1 } },
3347 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, { 2, 1, 1, 1 } },
3348 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 2, 1, 1, 1 } },
3349 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, { 1, 1, 1, 1 } },
3350 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 2, 1, 1, 1 } },
3351 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, { 2, 1, 1, 1 } },
3352 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, { 2, 1, 1, 1 } },
3353 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, { 4, 1, 1, 1 } },
3354 };
3355
3356 static const TypeConversionCostKindTblEntry AVXConversionTbl[] = {
3357 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 4, 1, 1, 1 } },
3358 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 4, 1, 1, 1 } },
3359 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 4, 1, 1, 1 } },
3360 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 4, 1, 1, 1 } },
3361 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 4, 1, 1, 1 } },
3362 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 4, 1, 1, 1 } },
3363
3364 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, { 3, 1, 1, 1 } },
3365 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, { 3, 1, 1, 1 } },
3366 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, { 3, 1, 1, 1 } },
3367 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, { 3, 1, 1, 1 } },
3368 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, { 3, 1, 1, 1 } },
3369 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, { 3, 1, 1, 1 } },
3370 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, { 3, 1, 1, 1 } },
3371 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, { 3, 1, 1, 1 } },
3372 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, { 3, 1, 1, 1 } },
3373 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, { 3, 1, 1, 1 } },
3374 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, { 3, 1, 1, 1 } },
3375 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, { 3, 1, 1, 1 } },
3376
3377 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 4, 1, 1, 1 } },
3378 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 5, 1, 1, 1 } },
3379 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 4, 1, 1, 1 } },
3380 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, { 9, 1, 1, 1 } },
3381 { ISD::TRUNCATE, MVT::v16i1, MVT::v16i64, {11, 1, 1, 1 } },
3382
3383 { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, { 6, 1, 1, 1 } },
3384 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 6, 1, 1, 1 } },
3385 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 2, 1, 1, 1 } }, // and+extract+packuswb
3386 { ISD::TRUNCATE, MVT::v16i8, MVT::v8i32, { 5, 1, 1, 1 } },
3387 { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, { 5, 1, 1, 1 } },
3388 { ISD::TRUNCATE, MVT::v16i8, MVT::v4i64, { 5, 1, 1, 1 } },
3389 { ISD::TRUNCATE, MVT::v8i16, MVT::v4i64, { 3, 1, 1, 1 } }, // and+extract+2*packusdw
3390 { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 2, 1, 1, 1 } },
3391
3392 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i1, { 3, 1, 1, 1 } },
3393 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i1, { 3, 1, 1, 1 } },
3394 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i1, { 8, 1, 1, 1 } },
3395 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, { 4, 1, 1, 1 } },
3396 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v16i8, { 2, 1, 1, 1 } },
3397 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, { 4, 1, 1, 1 } },
3398 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v8i16, { 2, 1, 1, 1 } },
3399 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, { 2, 1, 1, 1 } },
3400 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i32, { 2, 1, 1, 1 } },
3401 { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, { 4, 1, 1, 1 } },
3402 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v2i64, { 5, 1, 1, 1 } },
3403 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i64, { 8, 1, 1, 1 } },
3404
3405 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i1, { 7, 1, 1, 1 } },
3406 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i1, { 7, 1, 1, 1 } },
3407 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i1, { 6, 1, 1, 1 } },
3408 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, { 4, 1, 1, 1 } },
3409 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v16i8, { 2, 1, 1, 1 } },
3410 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, { 4, 1, 1, 1 } },
3411 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v8i16, { 2, 1, 1, 1 } },
3412 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 4, 1, 1, 1 } },
3413 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, { 4, 1, 1, 1 } },
3414 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 5, 1, 1, 1 } },
3415 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, { 6, 1, 1, 1 } },
3416 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, { 8, 1, 1, 1 } },
3417 { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, {10, 1, 1, 1 } },
3418 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, {10, 1, 1, 1 } },
3419 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, {18, 1, 1, 1 } },
3420 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 5, 1, 1, 1 } },
3421 { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, {10, 1, 1, 1 } },
3422
3423 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v8f32, { 2, 1, 1, 1 } },
3424 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f64, { 2, 1, 1, 1 } },
3425 { ISD::FP_TO_SINT, MVT::v32i8, MVT::v8f32, { 2, 1, 1, 1 } },
3426 { ISD::FP_TO_SINT, MVT::v32i8, MVT::v4f64, { 2, 1, 1, 1 } },
3427 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f32, { 2, 1, 1, 1 } },
3428 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f64, { 2, 1, 1, 1 } },
3429 { ISD::FP_TO_SINT, MVT::v16i16, MVT::v8f32, { 2, 1, 1, 1 } },
3430 { ISD::FP_TO_SINT, MVT::v16i16, MVT::v4f64, { 2, 1, 1, 1 } },
3431 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f64, { 2, 1, 1, 1 } },
3432 { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f32, { 2, 1, 1, 1 } },
3433 { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, { 5, 1, 1, 1 } },
3434
3435 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v8f32, { 2, 1, 1, 1 } },
3436 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f64, { 2, 1, 1, 1 } },
3437 { ISD::FP_TO_UINT, MVT::v32i8, MVT::v8f32, { 2, 1, 1, 1 } },
3438 { ISD::FP_TO_UINT, MVT::v32i8, MVT::v4f64, { 2, 1, 1, 1 } },
3439 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f32, { 2, 1, 1, 1 } },
3440 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f64, { 2, 1, 1, 1 } },
3441 { ISD::FP_TO_UINT, MVT::v16i16, MVT::v8f32, { 2, 1, 1, 1 } },
3442 { ISD::FP_TO_UINT, MVT::v16i16, MVT::v4f64, { 2, 1, 1, 1 } },
3443 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 3, 1, 1, 1 } },
3444 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } },
3445 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, { 6, 1, 1, 1 } },
3446 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, { 7, 1, 1, 1 } },
3447 { ISD::FP_TO_UINT, MVT::v8i32, MVT::v4f64, { 7, 1, 1, 1 } },
3448
3449 { ISD::FP_EXTEND, MVT::v4f64, MVT::v4f32, { 1, 1, 1, 1 } },
3450 { ISD::FP_ROUND, MVT::v4f32, MVT::v4f64, { 1, 1, 1, 1 } },
3451 };
3452
3453 static const TypeConversionCostKindTblEntry SSE41ConversionTbl[] = {
3454 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v16i8, { 1, 1, 1, 1 } },
3455 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v16i8, { 1, 1, 1, 1 } },
3456 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v16i8, { 1, 1, 1, 1 } },
3457 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v16i8, { 1, 1, 1, 1 } },
3458 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v16i8, { 1, 1, 1, 1 } },
3459 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v16i8, { 1, 1, 1, 1 } },
3460 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v8i16, { 1, 1, 1, 1 } },
3461 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v8i16, { 1, 1, 1, 1 } },
3462 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v8i16, { 1, 1, 1, 1 } },
3463 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v8i16, { 1, 1, 1, 1 } },
3464 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v4i32, { 1, 1, 1, 1 } },
3465 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v4i32, { 1, 1, 1, 1 } },
3466
3467 // These truncates end up widening elements.
3468 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 1, 1, 1, 1 } }, // PMOVXZBQ
3469 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 1, 1, 1, 1 } }, // PMOVXZWQ
3470 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 1, 1, 1, 1 } }, // PMOVXZBD
3471
3472 { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, { 2, 1, 1, 1 } },
3473 { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, { 2, 1, 1, 1 } },
3474 { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, { 2, 1, 1, 1 } },
3475
3476 { ISD::SINT_TO_FP, MVT::f32, MVT::i32, { 1, 1, 1, 1 } },
3477 { ISD::SINT_TO_FP, MVT::f64, MVT::i32, { 1, 1, 1, 1 } },
3478 { ISD::SINT_TO_FP, MVT::f32, MVT::i64, { 1, 1, 1, 1 } },
3479 { ISD::SINT_TO_FP, MVT::f64, MVT::i64, { 1, 1, 1, 1 } },
3480 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v16i8, { 1, 1, 1, 1 } },
3481 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } },
3482 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v8i16, { 1, 1, 1, 1 } },
3483 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } },
3484 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, { 1, 1, 1, 1 } },
3485 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v4i32, { 1, 1, 1, 1 } },
3486 { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, { 2, 1, 1, 1 } },
3487
3488 { ISD::UINT_TO_FP, MVT::f32, MVT::i32, { 1, 1, 1, 1 } },
3489 { ISD::UINT_TO_FP, MVT::f64, MVT::i32, { 1, 1, 1, 1 } },
3490 { ISD::UINT_TO_FP, MVT::f32, MVT::i64, { 4, 1, 1, 1 } },
3491 { ISD::UINT_TO_FP, MVT::f64, MVT::i64, { 4, 1, 1, 1 } },
3492 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v16i8, { 1, 1, 1, 1 } },
3493 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } },
3494 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v8i16, { 1, 1, 1, 1 } },
3495 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } },
3496 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 3, 1, 1, 1 } },
3497 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 3, 1, 1, 1 } },
3498 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v4i32, { 2, 1, 1, 1 } },
3499 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v2i64, {12, 1, 1, 1 } },
3500 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, {22, 1, 1, 1 } },
3501 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 4, 1, 1, 1 } },
3502
3503 { ISD::FP_TO_SINT, MVT::i32, MVT::f32, { 1, 1, 1, 1 } },
3504 { ISD::FP_TO_SINT, MVT::i64, MVT::f32, { 1, 1, 1, 1 } },
3505 { ISD::FP_TO_SINT, MVT::i32, MVT::f64, { 1, 1, 1, 1 } },
3506 { ISD::FP_TO_SINT, MVT::i64, MVT::f64, { 1, 1, 1, 1 } },
3507 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f32, { 2, 1, 1, 1 } },
3508 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v2f64, { 2, 1, 1, 1 } },
3509 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f32, { 1, 1, 1, 1 } },
3510 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v2f64, { 1, 1, 1, 1 } },
3511 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, { 1, 1, 1, 1 } },
3512 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v2f64, { 1, 1, 1, 1 } },
3513
3514 { ISD::FP_TO_UINT, MVT::i32, MVT::f32, { 1, 1, 1, 1 } },
3515 { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 4, 1, 1, 1 } },
3516 { ISD::FP_TO_UINT, MVT::i32, MVT::f64, { 1, 1, 1, 1 } },
3517 { ISD::FP_TO_UINT, MVT::i64, MVT::f64, { 4, 1, 1, 1 } },
3518 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f32, { 2, 1, 1, 1 } },
3519 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v2f64, { 2, 1, 1, 1 } },
3520 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f32, { 1, 1, 1, 1 } },
3521 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v2f64, { 1, 1, 1, 1 } },
3522 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 4, 1, 1, 1 } },
3523 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } },
3524 };
3525
3526 static const TypeConversionCostKindTblEntry SSE2ConversionTbl[] = {
3527 // These are somewhat magic numbers justified by comparing the
3528 // output of llvm-mca for our various supported scheduler models
3529 // and basing it off the worst case scenario.
3530 { ISD::SINT_TO_FP, MVT::f32, MVT::i32, { 3, 1, 1, 1 } },
3531 { ISD::SINT_TO_FP, MVT::f64, MVT::i32, { 3, 1, 1, 1 } },
3532 { ISD::SINT_TO_FP, MVT::f32, MVT::i64, { 3, 1, 1, 1 } },
3533 { ISD::SINT_TO_FP, MVT::f64, MVT::i64, { 3, 1, 1, 1 } },
3534 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v16i8, { 3, 1, 1, 1 } },
3535 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 4, 1, 1, 1 } },
3536 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v8i16, { 3, 1, 1, 1 } },
3537 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 4, 1, 1, 1 } },
3538 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, { 3, 1, 1, 1 } },
3539 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v4i32, { 4, 1, 1, 1 } },
3540 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v2i64, { 8, 1, 1, 1 } },
3541 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, { 8, 1, 1, 1 } },
3542
3543 { ISD::UINT_TO_FP, MVT::f32, MVT::i32, { 3, 1, 1, 1 } },
3544 { ISD::UINT_TO_FP, MVT::f64, MVT::i32, { 3, 1, 1, 1 } },
3545 { ISD::UINT_TO_FP, MVT::f32, MVT::i64, { 8, 1, 1, 1 } },
3546 { ISD::UINT_TO_FP, MVT::f64, MVT::i64, { 9, 1, 1, 1 } },
3547 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 4, 1, 1, 1 } },
3548 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v16i8, { 4, 1, 1, 1 } },
3549 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v8i16, { 4, 1, 1, 1 } },
3550 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 4, 1, 1, 1 } },
3551 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 7, 1, 1, 1 } },
3552 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v4i32, { 7, 1, 1, 1 } },
3553 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 5, 1, 1, 1 } },
3554 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, {15, 1, 1, 1 } },
3555 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v2i64, {18, 1, 1, 1 } },
3556
3557 { ISD::FP_TO_SINT, MVT::i32, MVT::f32, { 4, 1, 1, 1 } },
3558 { ISD::FP_TO_SINT, MVT::i64, MVT::f32, { 4, 1, 1, 1 } },
3559 { ISD::FP_TO_SINT, MVT::i32, MVT::f64, { 4, 1, 1, 1 } },
3560 { ISD::FP_TO_SINT, MVT::i64, MVT::f64, { 4, 1, 1, 1 } },
3561 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f32, { 6, 1, 1, 1 } },
3562 { ISD::FP_TO_SINT, MVT::v16i8, MVT::v2f64, { 6, 1, 1, 1 } },
3563 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f32, { 5, 1, 1, 1 } },
3564 { ISD::FP_TO_SINT, MVT::v8i16, MVT::v2f64, { 5, 1, 1, 1 } },
3565 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, { 4, 1, 1, 1 } },
3566 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } },
3567
3568 { ISD::FP_TO_UINT, MVT::i32, MVT::f32, { 4, 1, 1, 1 } },
3569 { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 4, 1, 1, 1 } },
3570 { ISD::FP_TO_UINT, MVT::i32, MVT::f64, { 4, 1, 1, 1 } },
3571 { ISD::FP_TO_UINT, MVT::i64, MVT::f64, {15, 1, 1, 1 } },
3572 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f32, { 6, 1, 1, 1 } },
3573 { ISD::FP_TO_UINT, MVT::v16i8, MVT::v2f64, { 6, 1, 1, 1 } },
3574 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f32, { 5, 1, 1, 1 } },
3575 { ISD::FP_TO_UINT, MVT::v8i16, MVT::v2f64, { 5, 1, 1, 1 } },
3576 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 8, 1, 1, 1 } },
3577 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 8, 1, 1, 1 } },
3578
3579 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v16i8, { 4, 1, 1, 1 } },
3580 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v16i8, { 4, 1, 1, 1 } },
3581 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v16i8, { 2, 1, 1, 1 } },
3582 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v16i8, { 3, 1, 1, 1 } },
3583 { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v16i8, { 1, 1, 1, 1 } },
3584 { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v16i8, { 2, 1, 1, 1 } },
3585 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v8i16, { 2, 1, 1, 1 } },
3586 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v8i16, { 3, 1, 1, 1 } },
3587 { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v8i16, { 1, 1, 1, 1 } },
3588 { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v8i16, { 2, 1, 1, 1 } },
3589 { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v4i32, { 1, 1, 1, 1 } },
3590 { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v4i32, { 2, 1, 1, 1 } },
3591
3592 // These truncates are really widening elements.
3593 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, { 1, 1, 1, 1 } }, // PSHUFD
3594 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 2, 1, 1, 1 } }, // PUNPCKLWD+DQ
3595 { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 3, 1, 1, 1 } }, // PUNPCKLBW+WD+PSHUFD
3596 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 1, 1, 1, 1 } }, // PUNPCKLWD
3597 { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 2, 1, 1, 1 } }, // PUNPCKLBW+WD
3598 { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 1, 1, 1, 1 } }, // PUNPCKLBW
3599
3600 { ISD::TRUNCATE, MVT::v16i8, MVT::v8i16, { 2, 1, 1, 1 } }, // PAND+PACKUSWB
3601 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 3, 1, 1, 1 } },
3602 { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, { 3, 1, 1, 1 } }, // PAND+2*PACKUSWB
3603 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 7, 1, 1, 1 } },
3604 { ISD::TRUNCATE, MVT::v2i16, MVT::v2i32, { 1, 1, 1, 1 } },
3605 { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, { 3, 1, 1, 1 } },
3606 { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, { 5, 1, 1, 1 } },
3607 { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, {10, 1, 1, 1 } },
3608 { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, { 4, 1, 1, 1 } }, // PAND+3*PACKUSWB
3609 { ISD::TRUNCATE, MVT::v8i16, MVT::v2i64, { 2, 1, 1, 1 } }, // PSHUFD+PSHUFLW
3610 { ISD::TRUNCATE, MVT::v4i32, MVT::v2i64, { 1, 1, 1, 1 } }, // PSHUFD
3611 };
3612
3613 static const TypeConversionCostKindTblEntry F16ConversionTbl[] = {
3614 { ISD::FP_ROUND, MVT::f16, MVT::f32, { 1, 1, 1, 1 } },
3615 { ISD::FP_ROUND, MVT::v8f16, MVT::v8f32, { 1, 1, 1, 1 } },
3616 { ISD::FP_ROUND, MVT::v4f16, MVT::v4f32, { 1, 1, 1, 1 } },
3617 { ISD::FP_EXTEND, MVT::f32, MVT::f16, { 1, 1, 1, 1 } },
3618 { ISD::FP_EXTEND, MVT::f64, MVT::f16, { 2, 1, 1, 1 } }, // vcvtph2ps+vcvtps2pd
3619 { ISD::FP_EXTEND, MVT::v8f32, MVT::v8f16, { 1, 1, 1, 1 } },
3620 { ISD::FP_EXTEND, MVT::v4f32, MVT::v4f16, { 1, 1, 1, 1 } },
3621 { ISD::FP_EXTEND, MVT::v4f64, MVT::v4f16, { 2, 1, 1, 1 } }, // vcvtph2ps+vcvtps2pd
3622 };
3623
3624 // Attempt to map directly to (simple) MVT types to let us match custom entries.
3625 EVT SrcTy = TLI->getValueType(DL, Src);
3626 EVT DstTy = TLI->getValueType(DL, Dst);
3627
3628 // If we're sign-extending a vector comparison result back to the comparison
3629 // width, this will be free without AVX512 (or for 8/16-bit types without
3630 // BWI).
3631 if (!ST->hasAVX512() || (!ST->hasBWI() && DstTy.getScalarSizeInBits() < 32)) {
3632 if (I && Opcode == Instruction::CastOps::SExt &&
3633 SrcTy.isFixedLengthVectorOf(MVT::i1)) {
3634 if (auto *CmpI = dyn_cast<CmpInst>(I->getOperand(0))) {
3635 Type *CmpTy = CmpI->getOperand(0)->getType();
3636 if (CmpTy->getScalarSizeInBits() == DstTy.getScalarSizeInBits())
3637 return TTI::TCC_Free;
3638 }
3639 }
3640 }
3641
3642 // The function getSimpleVT only handles simple value types.
3643 if (SrcTy.isSimple() && DstTy.isSimple()) {
3644 MVT SimpleSrcTy = SrcTy.getSimpleVT();
3645 MVT SimpleDstTy = DstTy.getSimpleVT();
3646
3647 if (ST->useAVX512Regs()) {
3648 if (ST->hasBWI())
3649 if (const auto *Entry = ConvertCostTableLookup(
3650 AVX512BWConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
3651 if (auto KindCost = Entry->Cost[CostKind])
3652 return *KindCost;
3653
3654 if (ST->hasDQI())
3655 if (const auto *Entry = ConvertCostTableLookup(
3656 AVX512DQConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
3657 if (auto KindCost = Entry->Cost[CostKind])
3658 return *KindCost;
3659
3660 if (ST->hasAVX512())
3661 if (const auto *Entry = ConvertCostTableLookup(
3662 AVX512FConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
3663 if (auto KindCost = Entry->Cost[CostKind])
3664 return *KindCost;
3665 }
3666
3667 if (ST->hasBWI())
3668 if (const auto *Entry = ConvertCostTableLookup(
3669 AVX512BWVLConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
3670 if (auto KindCost = Entry->Cost[CostKind])
3671 return *KindCost;
3672
3673 if (ST->hasDQI())
3674 if (const auto *Entry = ConvertCostTableLookup(
3675 AVX512DQVLConversionTbl, ISD, SimpleDstTy, SimpleSrcTy))
3676 if (auto KindCost = Entry->Cost[CostKind])
3677 return *KindCost;
3678
3679 if (ST->hasAVX512())
3680 if (const auto *Entry = ConvertCostTableLookup(AVX512VLConversionTbl, ISD,
3681 SimpleDstTy, SimpleSrcTy))
3682 if (auto KindCost = Entry->Cost[CostKind])
3683 return *KindCost;
3684
3685 if (ST->hasAVX2()) {
3686 if (const auto *Entry = ConvertCostTableLookup(AVX2ConversionTbl, ISD,
3687 SimpleDstTy, SimpleSrcTy))
3688 if (auto KindCost = Entry->Cost[CostKind])
3689 return *KindCost;
3690 }
3691
3692 if (ST->hasAVX()) {
3693 if (const auto *Entry = ConvertCostTableLookup(AVXConversionTbl, ISD,
3694 SimpleDstTy, SimpleSrcTy))
3695 if (auto KindCost = Entry->Cost[CostKind])
3696 return *KindCost;
3697 }
3698
3699 if (ST->hasF16C()) {
3700 if (const auto *Entry = ConvertCostTableLookup(F16ConversionTbl, ISD,
3701 SimpleDstTy, SimpleSrcTy))
3702 if (auto KindCost = Entry->Cost[CostKind])
3703 return *KindCost;
3704 }
3705
3706 if (ST->hasSSE41()) {
3707 if (const auto *Entry = ConvertCostTableLookup(SSE41ConversionTbl, ISD,
3708 SimpleDstTy, SimpleSrcTy))
3709 if (auto KindCost = Entry->Cost[CostKind])
3710 return *KindCost;
3711 }
3712
3713 if (ST->hasSSE2()) {
3714 if (const auto *Entry = ConvertCostTableLookup(SSE2ConversionTbl, ISD,
3715 SimpleDstTy, SimpleSrcTy))
3716 if (auto KindCost = Entry->Cost[CostKind])
3717 return *KindCost;
3718 }
3719
3720 if ((ISD == ISD::FP_ROUND && SimpleDstTy == MVT::f16) ||
3721 (ISD == ISD::FP_EXTEND && SimpleSrcTy == MVT::f16)) {
3722 // fp16 conversions not covered by any table entries require a libcall.
3723 // Return a large (arbitrary) number to model this.
3724 return InstructionCost(64);
3725 }
3726 }
3727
3728 // Fall back to legalized types.
3729 std::pair<InstructionCost, MVT> LTSrc = getTypeLegalizationCost(Src);
3730 std::pair<InstructionCost, MVT> LTDest = getTypeLegalizationCost(Dst);
3731
3732 // If we're truncating to the same legalized type - just assume its free.
3733 if (ISD == ISD::TRUNCATE && LTSrc.second == LTDest.second)
3734 return TTI::TCC_Free;
3735
3736 if (ST->useAVX512Regs()) {
3737 if (ST->hasBWI())
3738 if (const auto *Entry = ConvertCostTableLookup(
3739 AVX512BWConversionTbl, ISD, LTDest.second, LTSrc.second))
3740 if (auto KindCost = Entry->Cost[CostKind])
3741 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3742
3743 if (ST->hasDQI())
3744 if (const auto *Entry = ConvertCostTableLookup(
3745 AVX512DQConversionTbl, ISD, LTDest.second, LTSrc.second))
3746 if (auto KindCost = Entry->Cost[CostKind])
3747 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3748
3749 if (ST->hasAVX512())
3750 if (const auto *Entry = ConvertCostTableLookup(
3751 AVX512FConversionTbl, ISD, LTDest.second, LTSrc.second))
3752 if (auto KindCost = Entry->Cost[CostKind])
3753 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3754 }
3755
3756 if (ST->hasBWI())
3757 if (const auto *Entry = ConvertCostTableLookup(AVX512BWVLConversionTbl, ISD,
3758 LTDest.second, LTSrc.second))
3759 if (auto KindCost = Entry->Cost[CostKind])
3760 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3761
3762 if (ST->hasDQI())
3763 if (const auto *Entry = ConvertCostTableLookup(AVX512DQVLConversionTbl, ISD,
3764 LTDest.second, LTSrc.second))
3765 if (auto KindCost = Entry->Cost[CostKind])
3766 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3767
3768 if (ST->hasAVX512())
3769 if (const auto *Entry = ConvertCostTableLookup(AVX512VLConversionTbl, ISD,
3770 LTDest.second, LTSrc.second))
3771 if (auto KindCost = Entry->Cost[CostKind])
3772 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3773
3774 if (ST->hasAVX2())
3775 if (const auto *Entry = ConvertCostTableLookup(AVX2ConversionTbl, ISD,
3776 LTDest.second, LTSrc.second))
3777 if (auto KindCost = Entry->Cost[CostKind])
3778 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3779
3780 if (ST->hasAVX())
3781 if (const auto *Entry = ConvertCostTableLookup(AVXConversionTbl, ISD,
3782 LTDest.second, LTSrc.second))
3783 if (auto KindCost = Entry->Cost[CostKind])
3784 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3785
3786 if (ST->hasF16C()) {
3787 if (const auto *Entry = ConvertCostTableLookup(F16ConversionTbl, ISD,
3788 LTDest.second, LTSrc.second))
3789 if (auto KindCost = Entry->Cost[CostKind])
3790 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3791 }
3792
3793 if (ST->hasSSE41())
3794 if (const auto *Entry = ConvertCostTableLookup(SSE41ConversionTbl, ISD,
3795 LTDest.second, LTSrc.second))
3796 if (auto KindCost = Entry->Cost[CostKind])
3797 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3798
3799 if (ST->hasSSE2())
3800 if (const auto *Entry = ConvertCostTableLookup(SSE2ConversionTbl, ISD,
3801 LTDest.second, LTSrc.second))
3802 if (auto KindCost = Entry->Cost[CostKind])
3803 return std::max(LTSrc.first, LTDest.first) * *KindCost;
3804
3805 // Fallback, for i8/i16 sitofp/uitofp cases we need to extend to i32 for
3806 // sitofp.
3807 if ((ISD == ISD::SINT_TO_FP || ISD == ISD::UINT_TO_FP) &&
3808 1 < Src->getScalarSizeInBits() && Src->getScalarSizeInBits() < 32) {
3809 Type *ExtSrc = Src->getWithNewBitWidth(32);
3810 unsigned ExtOpc =
3811 (ISD == ISD::SINT_TO_FP) ? Instruction::SExt : Instruction::ZExt;
3812
3813 // For scalar loads the extend would be free.
3814 InstructionCost ExtCost = 0;
3815 if (!(Src->isIntegerTy() && I && isa<LoadInst>(I->getOperand(0))))
3816 ExtCost = getCastInstrCost(ExtOpc, ExtSrc, Src, CCH, CostKind);
3817
3818 return ExtCost + getCastInstrCost(Instruction::SIToFP, Dst, ExtSrc,
3820 }
3821
3822 // Fallback for fptosi/fptoui i8/i16 cases we need to truncate from fptosi
3823 // i32.
3824 if ((ISD == ISD::FP_TO_SINT || ISD == ISD::FP_TO_UINT) &&
3825 1 < Dst->getScalarSizeInBits() && Dst->getScalarSizeInBits() < 32) {
3826 Type *TruncDst = Dst->getWithNewBitWidth(32);
3827 return getCastInstrCost(Instruction::FPToSI, TruncDst, Src, CCH, CostKind) +
3828 getCastInstrCost(Instruction::Trunc, Dst, TruncDst,
3830 }
3831
3832 // TODO: Allow non-throughput costs that aren't binary.
3833 auto AdjustCost = [&CostKind](InstructionCost Cost,
3836 return Cost == 0 ? 0 : N;
3837 return Cost * N;
3838 };
3839 return AdjustCost(
3840 BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I));
3841}
3842
3843// Additive cost for a predicated op's "predicate fanout": a select, masked
3844// load/store or gather/scatter keeps a compact <N x i1> mask, but if its data
3845// legalizes into more parts than the mask, codegen builds a sub-mask per extra
3846// part (kshiftr on AVX-512, unpack/extend on SSE/AVX) the per-part tables miss.
3847// FanoutCostPerPart is a tie-break: it beats the vectorizer's widest-VF bias.
3849 Type *DataVTy, Type *MaskVTy) {
3850 constexpr unsigned FanoutCostPerPart = 4;
3851 unsigned DataParts = TTI.getNumberOfParts(DataVTy);
3852 unsigned MaskParts = TTI.getNumberOfParts(MaskVTy);
3853 if (DataParts > MaskParts && MaskParts > 0)
3854 return InstructionCost((DataParts - MaskParts) * FanoutCostPerPart);
3855 return InstructionCost(0);
3856}
3857
3859 unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,
3861 TTI::OperandValueInfo Op2Info, const Instruction *I) const {
3862 // Early out if this type isn't scalar/vector integer/float.
3863 if (!(ValTy->isIntOrIntVectorTy() || ValTy->isFPOrFPVectorTy()))
3864 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
3865 Op1Info, Op2Info, I);
3866
3867 // Legalize the type.
3868 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
3869
3870 MVT MTy = LT.second;
3871
3872 int ISD = TLI->InstructionOpcodeToISD(Opcode);
3873 assert(ISD && "Invalid opcode");
3874
3875 // Predicate fanout (see getPredicateFanoutCost), AVX-512 only: on SSE/AVX a
3876 // select blend is already priced per part, so charging it there shrinks VF.
3877 InstructionCost MaskExpCost = 0;
3878 if (Opcode == Instruction::Select && ST->hasAVX512() &&
3880 MaskExpCost = getPredicateFanoutCost(*this, ValTy, CondTy);
3881
3882 InstructionCost ExtraCost = 0;
3883 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) {
3884 // Some vector comparison predicates cost extra instructions.
3885 // TODO: Adjust ExtraCost based on CostKind?
3886 // TODO: Should we invert this and assume worst case cmp costs
3887 // and reduce for particular predicates?
3888 if (MTy.isVector() &&
3889 !((ST->hasXOP() && (!ST->hasAVX2() || MTy.is128BitVector())) ||
3890 (ST->hasAVX512() && 32 <= MTy.getScalarSizeInBits()) ||
3891 ST->hasBWI())) {
3892 // Fallback to I if a specific predicate wasn't specified.
3893 CmpInst::Predicate Pred = VecPred;
3894 if (I && (Pred == CmpInst::BAD_ICMP_PREDICATE ||
3896 Pred = cast<CmpInst>(I)->getPredicate();
3897
3898 bool CmpWithConstant = false;
3899 if (auto *CmpInstr = dyn_cast_or_null<CmpInst>(I))
3900 CmpWithConstant = isa<Constant>(CmpInstr->getOperand(1));
3901
3902 switch (Pred) {
3904 // xor(cmpeq(x,y),-1)
3905 ExtraCost = CmpWithConstant ? 0 : 1;
3906 break;
3909 // xor(cmpgt(x,y),-1)
3910 ExtraCost = CmpWithConstant ? 0 : 1;
3911 break;
3914 // cmpgt(xor(x,signbit),xor(y,signbit))
3915 // xor(cmpeq(pmaxu(x,y),x),-1)
3916 ExtraCost = CmpWithConstant ? 1 : 2;
3917 break;
3920 if ((ST->hasSSE41() && MTy.getScalarSizeInBits() == 32) ||
3921 (ST->hasSSE2() && MTy.getScalarSizeInBits() < 32)) {
3922 // cmpeq(psubus(x,y),0)
3923 // cmpeq(pminu(x,y),x)
3924 ExtraCost = 1;
3925 } else {
3926 // xor(cmpgt(xor(x,signbit),xor(y,signbit)),-1)
3927 ExtraCost = CmpWithConstant ? 2 : 3;
3928 }
3929 break;
3932 // Without AVX we need to expand FCMP_ONE/FCMP_UEQ cases.
3933 // Use FCMP_UEQ expansion - FCMP_ONE should be the same.
3934 if (CondTy && !ST->hasAVX())
3935 return getCmpSelInstrCost(Opcode, ValTy, CondTy,
3937 Op1Info, Op2Info) +
3938 getCmpSelInstrCost(Opcode, ValTy, CondTy,
3940 Op1Info, Op2Info) +
3941 getArithmeticInstrCost(Instruction::Or, CondTy, CostKind);
3942
3943 break;
3946 // Assume worst case scenario and add the maximum extra cost.
3947 ExtraCost = 3;
3948 break;
3949 default:
3950 break;
3951 }
3952 }
3953 }
3954
3955 static const CostKindTblEntry SLMCostTbl[] = {
3956 // slm pcmpeq/pcmpgt throughput is 2
3957 { ISD::SETCC, MVT::v2i64, { 2, 5, 1, 2 } },
3958 // slm pblendvb/blendvpd/blendvps throughput is 4
3959 { ISD::SELECT, MVT::v2f64, { 4, 4, 1, 3 } }, // vblendvpd
3960 { ISD::SELECT, MVT::v4f32, { 4, 4, 1, 3 } }, // vblendvps
3961 { ISD::SELECT, MVT::v2i64, { 4, 4, 1, 3 } }, // pblendvb
3962 { ISD::SELECT, MVT::v8i32, { 4, 4, 1, 3 } }, // pblendvb
3963 { ISD::SELECT, MVT::v8i16, { 4, 4, 1, 3 } }, // pblendvb
3964 { ISD::SELECT, MVT::v16i8, { 4, 4, 1, 3 } }, // pblendvb
3965 };
3966
3967 static const CostKindTblEntry AVX512BWCostTbl[] = {
3968 { ISD::SETCC, MVT::v32i16, { 1, 1, 1, 1 } },
3969 { ISD::SETCC, MVT::v16i16, { 1, 1, 1, 1 } },
3970 { ISD::SETCC, MVT::v64i8, { 1, 1, 1, 1 } },
3971 { ISD::SETCC, MVT::v32i8, { 1, 1, 1, 1 } },
3972
3973 { ISD::SELECT, MVT::v32i16, { 1, 1, 1, 1 } },
3974 { ISD::SELECT, MVT::v64i8, { 1, 1, 1, 1 } },
3975 };
3976
3977 static const CostKindTblEntry AVX512CostTbl[] = {
3978 { ISD::SETCC, MVT::v8f64, { 1, 4, 1, 1 } },
3979 { ISD::SETCC, MVT::v4f64, { 1, 4, 1, 1 } },
3980 { ISD::SETCC, MVT::v16f32, { 1, 4, 1, 1 } },
3981 { ISD::SETCC, MVT::v8f32, { 1, 4, 1, 1 } },
3982
3983 { ISD::SETCC, MVT::v8i64, { 1, 1, 1, 1 } },
3984 { ISD::SETCC, MVT::v4i64, { 1, 1, 1, 1 } },
3985 { ISD::SETCC, MVT::v2i64, { 1, 1, 1, 1 } },
3986 { ISD::SETCC, MVT::v16i32, { 1, 1, 1, 1 } },
3987 { ISD::SETCC, MVT::v8i32, { 1, 1, 1, 1 } },
3988 { ISD::SETCC, MVT::v32i16, { 3, 7, 5, 5 } },
3989 { ISD::SETCC, MVT::v64i8, { 3, 7, 5, 5 } },
3990
3991 { ISD::SELECT, MVT::v8i64, { 1, 1, 1, 1 } },
3992 { ISD::SELECT, MVT::v4i64, { 1, 1, 1, 1 } },
3993 { ISD::SELECT, MVT::v2i64, { 1, 1, 1, 1 } },
3994 { ISD::SELECT, MVT::v16i32, { 1, 1, 1, 1 } },
3995 { ISD::SELECT, MVT::v8i32, { 1, 1, 1, 1 } },
3996 { ISD::SELECT, MVT::v4i32, { 1, 1, 1, 1 } },
3997 { ISD::SELECT, MVT::v8f64, { 1, 1, 1, 1 } },
3998 { ISD::SELECT, MVT::v4f64, { 1, 1, 1, 1 } },
3999 { ISD::SELECT, MVT::v2f64, { 1, 1, 1, 1 } },
4000 { ISD::SELECT, MVT::f64, { 1, 1, 1, 1 } },
4001 { ISD::SELECT, MVT::v16f32, { 1, 1, 1, 1 } },
4002 { ISD::SELECT, MVT::v8f32 , { 1, 1, 1, 1 } },
4003 { ISD::SELECT, MVT::v4f32, { 1, 1, 1, 1 } },
4004 { ISD::SELECT, MVT::f32 , { 1, 1, 1, 1 } },
4005
4006 { ISD::SELECT, MVT::v32i16, { 2, 2, 4, 4 } },
4007 { ISD::SELECT, MVT::v16i16, { 1, 1, 1, 1 } },
4008 { ISD::SELECT, MVT::v8i16, { 1, 1, 1, 1 } },
4009 { ISD::SELECT, MVT::v64i8, { 2, 2, 4, 4 } },
4010 { ISD::SELECT, MVT::v32i8, { 1, 1, 1, 1 } },
4011 { ISD::SELECT, MVT::v16i8, { 1, 1, 1, 1 } },
4012 };
4013
4014 static const CostKindTblEntry AVX2CostTbl[] = {
4015 { ISD::SETCC, MVT::v4f64, { 1, 4, 1, 2 } },
4016 { ISD::SETCC, MVT::v2f64, { 1, 4, 1, 1 } },
4017 { ISD::SETCC, MVT::f64, { 1, 4, 1, 1 } },
4018 { ISD::SETCC, MVT::v8f32, { 1, 4, 1, 2 } },
4019 { ISD::SETCC, MVT::v4f32, { 1, 4, 1, 1 } },
4020 { ISD::SETCC, MVT::f32, { 1, 4, 1, 1 } },
4021
4022 { ISD::SETCC, MVT::v4i64, { 1, 1, 1, 2 } },
4023 { ISD::SETCC, MVT::v8i32, { 1, 1, 1, 2 } },
4024 { ISD::SETCC, MVT::v16i16, { 1, 1, 1, 2 } },
4025 { ISD::SETCC, MVT::v32i8, { 1, 1, 1, 2 } },
4026
4027 { ISD::SELECT, MVT::v4f64, { 2, 2, 1, 2 } }, // vblendvpd
4028 { ISD::SELECT, MVT::v8f32, { 2, 2, 1, 2 } }, // vblendvps
4029 { ISD::SELECT, MVT::v4i64, { 2, 2, 1, 2 } }, // pblendvb
4030 { ISD::SELECT, MVT::v8i32, { 2, 2, 1, 2 } }, // pblendvb
4031 { ISD::SELECT, MVT::v16i16, { 2, 2, 1, 2 } }, // pblendvb
4032 { ISD::SELECT, MVT::v32i8, { 2, 2, 1, 2 } }, // pblendvb
4033 };
4034
4035 static const CostKindTblEntry XOPCostTbl[] = {
4036 { ISD::SETCC, MVT::v4i64, { 4, 2, 5, 6 } },
4037 { ISD::SETCC, MVT::v2i64, { 1, 1, 1, 1 } },
4038 };
4039
4040 static const CostKindTblEntry AVX1CostTbl[] = {
4041 { ISD::SETCC, MVT::v4f64, { 2, 3, 1, 2 } },
4042 { ISD::SETCC, MVT::v2f64, { 1, 3, 1, 1 } },
4043 { ISD::SETCC, MVT::f64, { 1, 3, 1, 1 } },
4044 { ISD::SETCC, MVT::v8f32, { 2, 3, 1, 2 } },
4045 { ISD::SETCC, MVT::v4f32, { 1, 3, 1, 1 } },
4046 { ISD::SETCC, MVT::f32, { 1, 3, 1, 1 } },
4047
4048 // AVX1 does not support 8-wide integer compare.
4049 { ISD::SETCC, MVT::v4i64, { 4, 2, 5, 6 } },
4050 { ISD::SETCC, MVT::v8i32, { 4, 2, 5, 6 } },
4051 { ISD::SETCC, MVT::v16i16, { 4, 2, 5, 6 } },
4052 { ISD::SETCC, MVT::v32i8, { 4, 2, 5, 6 } },
4053
4054 { ISD::SELECT, MVT::v4f64, { 3, 3, 1, 2 } }, // vblendvpd
4055 { ISD::SELECT, MVT::v8f32, { 3, 3, 1, 2 } }, // vblendvps
4056 { ISD::SELECT, MVT::v4i64, { 3, 3, 1, 2 } }, // vblendvpd
4057 { ISD::SELECT, MVT::v8i32, { 3, 3, 1, 2 } }, // vblendvps
4058 { ISD::SELECT, MVT::v16i16, { 3, 3, 3, 3 } }, // vandps + vandnps + vorps
4059 { ISD::SELECT, MVT::v32i8, { 3, 3, 3, 3 } }, // vandps + vandnps + vorps
4060 };
4061
4062 static const CostKindTblEntry SSE42CostTbl[] = {
4063 { ISD::SETCC, MVT::v2i64, { 1, 2, 1, 2 } },
4064 };
4065
4066 static const CostKindTblEntry SSE41CostTbl[] = {
4067 { ISD::SETCC, MVT::v2f64, { 1, 5, 1, 1 } },
4068 { ISD::SETCC, MVT::v4f32, { 1, 5, 1, 1 } },
4069
4070 { ISD::SELECT, MVT::v2f64, { 2, 2, 1, 2 } }, // blendvpd
4071 { ISD::SELECT, MVT::f64, { 2, 2, 1, 2 } }, // blendvpd
4072 { ISD::SELECT, MVT::v4f32, { 2, 2, 1, 2 } }, // blendvps
4073 { ISD::SELECT, MVT::f32 , { 2, 2, 1, 2 } }, // blendvps
4074 { ISD::SELECT, MVT::v2i64, { 2, 2, 1, 2 } }, // pblendvb
4075 { ISD::SELECT, MVT::v4i32, { 2, 2, 1, 2 } }, // pblendvb
4076 { ISD::SELECT, MVT::v8i16, { 2, 2, 1, 2 } }, // pblendvb
4077 { ISD::SELECT, MVT::v16i8, { 2, 2, 1, 2 } }, // pblendvb
4078 };
4079
4080 static const CostKindTblEntry SSE2CostTbl[] = {
4081 { ISD::SETCC, MVT::v2f64, { 2, 5, 1, 1 } },
4082 { ISD::SETCC, MVT::f64, { 1, 5, 1, 1 } },
4083
4084 { ISD::SETCC, MVT::v2i64, { 5, 4, 5, 5 } }, // pcmpeqd/pcmpgtd expansion
4085 { ISD::SETCC, MVT::v4i32, { 1, 1, 1, 1 } },
4086 { ISD::SETCC, MVT::v8i16, { 1, 1, 1, 1 } },
4087 { ISD::SETCC, MVT::v16i8, { 1, 1, 1, 1 } },
4088
4089 { ISD::SELECT, MVT::v2f64, { 2, 2, 3, 3 } }, // andpd + andnpd + orpd
4090 { ISD::SELECT, MVT::f64, { 2, 2, 3, 3 } }, // andpd + andnpd + orpd
4091 { ISD::SELECT, MVT::v2i64, { 2, 2, 3, 3 } }, // pand + pandn + por
4092 { ISD::SELECT, MVT::v4i32, { 2, 2, 3, 3 } }, // pand + pandn + por
4093 { ISD::SELECT, MVT::v8i16, { 2, 2, 3, 3 } }, // pand + pandn + por
4094 { ISD::SELECT, MVT::v16i8, { 2, 2, 3, 3 } }, // pand + pandn + por
4095 };
4096
4097 static const CostKindTblEntry SSE1CostTbl[] = {
4098 { ISD::SETCC, MVT::v4f32, { 2, 5, 1, 1 } },
4099 { ISD::SETCC, MVT::f32, { 1, 5, 1, 1 } },
4100
4101 { ISD::SELECT, MVT::v4f32, { 2, 2, 3, 3 } }, // andps + andnps + orps
4102 { ISD::SELECT, MVT::f32, { 2, 2, 3, 3 } }, // andps + andnps + orps
4103 };
4104
4105 if (ST->useSLMArithCosts())
4106 if (const auto *Entry = CostTableLookup(SLMCostTbl, ISD, MTy))
4107 if (auto KindCost = Entry->Cost[CostKind])
4108 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4109
4110 if (ST->hasBWI())
4111 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
4112 if (auto KindCost = Entry->Cost[CostKind])
4113 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4114
4115 if (ST->hasAVX512())
4116 if (const auto *Entry = CostTableLookup(AVX512CostTbl, ISD, MTy))
4117 if (auto KindCost = Entry->Cost[CostKind])
4118 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4119
4120 if (ST->hasAVX2())
4121 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
4122 if (auto KindCost = Entry->Cost[CostKind])
4123 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4124
4125 if (ST->hasXOP())
4126 if (const auto *Entry = CostTableLookup(XOPCostTbl, ISD, MTy))
4127 if (auto KindCost = Entry->Cost[CostKind])
4128 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4129
4130 if (ST->hasAVX())
4131 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
4132 if (auto KindCost = Entry->Cost[CostKind])
4133 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4134
4135 if (ST->hasSSE42())
4136 if (const auto *Entry = CostTableLookup(SSE42CostTbl, ISD, MTy))
4137 if (auto KindCost = Entry->Cost[CostKind])
4138 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4139
4140 if (ST->hasSSE41())
4141 if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
4142 if (auto KindCost = Entry->Cost[CostKind])
4143 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4144
4145 if (ST->hasSSE2())
4146 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
4147 if (auto KindCost = Entry->Cost[CostKind])
4148 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4149
4150 if (ST->hasSSE1())
4151 if (const auto *Entry = CostTableLookup(SSE1CostTbl, ISD, MTy))
4152 if (auto KindCost = Entry->Cost[CostKind])
4153 return LT.first * (ExtraCost + *KindCost) + MaskExpCost;
4154
4155 // Assume a 3cy latency for fp select ops.
4156 if (CostKind == TTI::TCK_Latency && Opcode == Instruction::Select)
4157 if (ValTy->getScalarType()->isFloatingPointTy())
4158 return 3;
4159
4160 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
4161 Op1Info, Op2Info, I) +
4162 MaskExpCost;
4163}
4164
4166
4170 // Costs should match the codegen from:
4171 // BITREVERSE: llvm\test\CodeGen\X86\vector-bitreverse.ll
4172 // BSWAP: llvm\test\CodeGen\X86\bswap-vector.ll
4173 // CTLZ: llvm\test\CodeGen\X86\vector-lzcnt-*.ll
4174 // CTPOP: llvm\test\CodeGen\X86\vector-popcnt-*.ll
4175 // CTTZ: llvm\test\CodeGen\X86\vector-tzcnt-*.ll
4176
4177 // TODO: Overflow intrinsics (*ADDO, *SUBO, *MULO) with vector types are not
4178 // specialized in these tables yet.
4179 static const CostKindTblEntry AVX512VBMI2CostTbl[] = {
4180 { ISD::FSHL, MVT::v8i64, { 1, 1, 1, 1 } },
4181 { ISD::FSHL, MVT::v4i64, { 1, 1, 1, 1 } },
4182 { ISD::FSHL, MVT::v2i64, { 1, 1, 1, 1 } },
4183 { ISD::FSHL, MVT::v16i32, { 1, 1, 1, 1 } },
4184 { ISD::FSHL, MVT::v8i32, { 1, 1, 1, 1 } },
4185 { ISD::FSHL, MVT::v4i32, { 1, 1, 1, 1 } },
4186 { ISD::FSHL, MVT::v32i16, { 1, 1, 1, 1 } },
4187 { ISD::FSHL, MVT::v16i16, { 1, 1, 1, 1 } },
4188 { ISD::FSHL, MVT::v8i16, { 1, 1, 1, 1 } },
4189 { ISD::ROTL, MVT::v32i16, { 1, 1, 1, 1 } },
4190 { ISD::ROTL, MVT::v16i16, { 1, 1, 1, 1 } },
4191 { ISD::ROTL, MVT::v8i16, { 1, 1, 1, 1 } },
4192 { ISD::ROTR, MVT::v32i16, { 1, 1, 1, 1 } },
4193 { ISD::ROTR, MVT::v16i16, { 1, 1, 1, 1 } },
4194 { ISD::ROTR, MVT::v8i16, { 1, 1, 1, 1 } },
4195 { X86ISD::VROTLI, MVT::v32i16, { 1, 1, 1, 1 } },
4196 { X86ISD::VROTLI, MVT::v16i16, { 1, 1, 1, 1 } },
4197 { X86ISD::VROTLI, MVT::v8i16, { 1, 1, 1, 1 } },
4198 };
4199 static const CostKindTblEntry AVX512BITALGCostTbl[] = {
4200 { ISD::CTPOP, MVT::v32i16, { 1, 1, 1, 1 } },
4201 { ISD::CTPOP, MVT::v64i8, { 1, 1, 1, 1 } },
4202 { ISD::CTPOP, MVT::v16i16, { 1, 1, 1, 1 } },
4203 { ISD::CTPOP, MVT::v32i8, { 1, 1, 1, 1 } },
4204 { ISD::CTPOP, MVT::v8i16, { 1, 1, 1, 1 } },
4205 { ISD::CTPOP, MVT::v16i8, { 1, 1, 1, 1 } },
4206 };
4207 static const CostKindTblEntry AVX512VPOPCNTDQCostTbl[] = {
4208 { ISD::CTPOP, MVT::v8i64, { 1, 1, 1, 1 } },
4209 { ISD::CTPOP, MVT::v16i32, { 1, 1, 1, 1 } },
4210 { ISD::CTPOP, MVT::v4i64, { 1, 1, 1, 1 } },
4211 { ISD::CTPOP, MVT::v8i32, { 1, 1, 1, 1 } },
4212 { ISD::CTPOP, MVT::v2i64, { 1, 1, 1, 1 } },
4213 { ISD::CTPOP, MVT::v4i32, { 1, 1, 1, 1 } },
4214 };
4215 static const CostKindTblEntry AVX512CDCostTbl[] = {
4216 { ISD::CTLZ, MVT::v8i64, { 1, 5, 1, 1 } },
4217 { ISD::CTLZ, MVT::v16i32, { 1, 5, 1, 1 } },
4218 { ISD::CTLZ, MVT::v32i16, { 18, 27, 23, 27 } },
4219 { ISD::CTLZ, MVT::v64i8, { 3, 16, 9, 11 } },
4220 { ISD::CTLZ, MVT::v4i64, { 1, 5, 1, 1 } },
4221 { ISD::CTLZ, MVT::v8i32, { 1, 5, 1, 1 } },
4222 { ISD::CTLZ, MVT::v16i16, { 8, 19, 11, 13 } },
4223 { ISD::CTLZ, MVT::v32i8, { 2, 11, 9, 10 } },
4224 { ISD::CTLZ, MVT::v2i64, { 1, 5, 1, 1 } },
4225 { ISD::CTLZ, MVT::v4i32, { 1, 5, 1, 1 } },
4226 { ISD::CTLZ, MVT::v8i16, { 3, 15, 4, 6 } },
4227 { ISD::CTLZ, MVT::v16i8, { 2, 10, 9, 10 } },
4228
4229 { ISD::CTTZ, MVT::v8i64, { 2, 8, 6, 7 } },
4230 { ISD::CTTZ, MVT::v16i32, { 2, 8, 6, 7 } },
4231 { ISD::CTTZ, MVT::v4i64, { 1, 8, 6, 6 } },
4232 { ISD::CTTZ, MVT::v8i32, { 1, 8, 6, 6 } },
4233 { ISD::CTTZ, MVT::v2i64, { 1, 8, 6, 6 } },
4234 { ISD::CTTZ, MVT::v4i32, { 1, 8, 6, 6 } },
4235 };
4236 static const CostKindTblEntry AVX512BWCostTbl[] = {
4237 { ISD::ABS, MVT::v32i16, { 1, 1, 1, 1 } },
4238 { ISD::ABS, MVT::v64i8, { 1, 1, 1, 1 } },
4239 { ISD::BITREVERSE, MVT::v2i64, { 3, 10, 10, 11 } },
4240 { ISD::BITREVERSE, MVT::v4i64, { 3, 11, 10, 11 } },
4241 { ISD::BITREVERSE, MVT::v8i64, { 3, 12, 10, 14 } },
4242 { ISD::BITREVERSE, MVT::v4i32, { 3, 10, 10, 11 } },
4243 { ISD::BITREVERSE, MVT::v8i32, { 3, 11, 10, 11 } },
4244 { ISD::BITREVERSE, MVT::v16i32, { 3, 12, 10, 14 } },
4245 { ISD::BITREVERSE, MVT::v8i16, { 3, 10, 10, 11 } },
4246 { ISD::BITREVERSE, MVT::v16i16, { 3, 11, 10, 11 } },
4247 { ISD::BITREVERSE, MVT::v32i16, { 3, 12, 10, 14 } },
4248 { ISD::BITREVERSE, MVT::v16i8, { 2, 5, 9, 9 } },
4249 { ISD::BITREVERSE, MVT::v32i8, { 2, 5, 9, 9 } },
4250 { ISD::BITREVERSE, MVT::v64i8, { 2, 5, 9, 12 } },
4251 { ISD::BSWAP, MVT::v2i64, { 1, 1, 1, 2 } },
4252 { ISD::BSWAP, MVT::v4i64, { 1, 1, 1, 2 } },
4253 { ISD::BSWAP, MVT::v8i64, { 1, 1, 1, 2 } },
4254 { ISD::BSWAP, MVT::v4i32, { 1, 1, 1, 2 } },
4255 { ISD::BSWAP, MVT::v8i32, { 1, 1, 1, 2 } },
4256 { ISD::BSWAP, MVT::v16i32, { 1, 1, 1, 2 } },
4257 { ISD::BSWAP, MVT::v8i16, { 1, 1, 1, 2 } },
4258 { ISD::BSWAP, MVT::v16i16, { 1, 1, 1, 2 } },
4259 { ISD::BSWAP, MVT::v32i16, { 1, 1, 1, 2 } },
4260 { ISD::CTLZ, MVT::v8i64, { 8, 22, 23, 23 } },
4261 { ISD::CTLZ, MVT::v16i32, { 8, 23, 25, 25 } },
4262 { ISD::CTLZ, MVT::v32i16, { 4, 15, 15, 16 } },
4263 { ISD::CTLZ, MVT::v64i8, { 3, 12, 10, 9 } },
4264 { ISD::CTPOP, MVT::v2i64, { 3, 7, 10, 10 } },
4265 { ISD::CTPOP, MVT::v4i64, { 3, 7, 10, 10 } },
4266 { ISD::CTPOP, MVT::v8i64, { 3, 8, 10, 12 } },
4267 { ISD::CTPOP, MVT::v4i32, { 7, 11, 14, 14 } },
4268 { ISD::CTPOP, MVT::v8i32, { 7, 11, 14, 14 } },
4269 { ISD::CTPOP, MVT::v16i32, { 7, 12, 14, 16 } },
4270 { ISD::CTPOP, MVT::v8i16, { 2, 7, 11, 11 } },
4271 { ISD::CTPOP, MVT::v16i16, { 2, 7, 11, 11 } },
4272 { ISD::CTPOP, MVT::v32i16, { 3, 7, 11, 13 } },
4273 { ISD::CTPOP, MVT::v16i8, { 2, 4, 8, 8 } },
4274 { ISD::CTPOP, MVT::v32i8, { 2, 4, 8, 8 } },
4275 { ISD::CTPOP, MVT::v64i8, { 2, 5, 8, 10 } },
4276 { ISD::CTTZ, MVT::v8i16, { 3, 9, 14, 14 } },
4277 { ISD::CTTZ, MVT::v16i16, { 3, 9, 14, 14 } },
4278 { ISD::CTTZ, MVT::v32i16, { 3, 10, 14, 16 } },
4279 { ISD::CTTZ, MVT::v16i8, { 2, 6, 11, 11 } },
4280 { ISD::CTTZ, MVT::v32i8, { 2, 6, 11, 11 } },
4281 { ISD::CTTZ, MVT::v64i8, { 3, 7, 11, 13 } },
4282 { ISD::MULHS, MVT::v32i16, { 1, 5, 1, 1 } },
4283 { ISD::MULHU, MVT::v32i16, { 1, 5, 1, 1 } },
4284 { ISD::ROTL, MVT::v32i16, { 2, 8, 6, 8 } },
4285 { ISD::ROTL, MVT::v16i16, { 2, 8, 6, 7 } },
4286 { ISD::ROTL, MVT::v8i16, { 2, 7, 6, 7 } },
4287 { ISD::ROTL, MVT::v64i8, { 5, 6, 11, 12 } },
4288 { ISD::ROTL, MVT::v32i8, { 5, 15, 7, 10 } },
4289 { ISD::ROTL, MVT::v16i8, { 5, 15, 7, 10 } },
4290 { ISD::ROTR, MVT::v32i16, { 2, 8, 6, 8 } },
4291 { ISD::ROTR, MVT::v16i16, { 2, 8, 6, 7 } },
4292 { ISD::ROTR, MVT::v8i16, { 2, 7, 6, 7 } },
4293 { ISD::ROTR, MVT::v64i8, { 5, 6, 12, 14 } },
4294 { ISD::ROTR, MVT::v32i8, { 5, 14, 6, 9 } },
4295 { ISD::ROTR, MVT::v16i8, { 5, 14, 6, 9 } },
4296 { X86ISD::VROTLI, MVT::v32i16, { 2, 5, 3, 3 } },
4297 { X86ISD::VROTLI, MVT::v16i16, { 1, 5, 3, 3 } },
4298 { X86ISD::VROTLI, MVT::v8i16, { 1, 5, 3, 3 } },
4299 { X86ISD::VROTLI, MVT::v64i8, { 2, 9, 3, 4 } },
4300 { X86ISD::VROTLI, MVT::v32i8, { 1, 9, 3, 4 } },
4301 { X86ISD::VROTLI, MVT::v16i8, { 1, 8, 3, 4 } },
4302 { ISD::SADDSAT, MVT::v32i16, { 1, 1, 1, 1 } },
4303 { ISD::SADDSAT, MVT::v64i8, { 1, 1, 1, 1 } },
4304 { ISD::SMAX, MVT::v32i16, { 1, 1, 1, 1 } },
4305 { ISD::SMAX, MVT::v64i8, { 1, 1, 1, 1 } },
4306 { ISD::SMIN, MVT::v32i16, { 1, 1, 1, 1 } },
4307 { ISD::SMIN, MVT::v64i8, { 1, 1, 1, 1 } },
4308 { ISD::SMULO, MVT::v32i16, { 3, 6, 4, 4 } },
4309 { ISD::SMULO, MVT::v64i8, { 8, 21, 17, 18 } },
4310 { ISD::UMULO, MVT::v32i16, { 2, 5, 3, 3 } },
4311 { ISD::UMULO, MVT::v64i8, { 8, 15, 15, 16 } },
4312 { ISD::SSUBSAT, MVT::v32i16, { 1, 1, 1, 1 } },
4313 { ISD::SSUBSAT, MVT::v64i8, { 1, 1, 1, 1 } },
4314 { ISD::UADDSAT, MVT::v32i16, { 1, 1, 1, 1 } },
4315 { ISD::UADDSAT, MVT::v64i8, { 1, 1, 1, 1 } },
4316 { ISD::UMAX, MVT::v32i16, { 1, 1, 1, 1 } },
4317 { ISD::UMAX, MVT::v64i8, { 1, 1, 1, 1 } },
4318 { ISD::UMIN, MVT::v32i16, { 1, 1, 1, 1 } },
4319 { ISD::UMIN, MVT::v64i8, { 1, 1, 1, 1 } },
4320 { ISD::USUBSAT, MVT::v32i16, { 1, 1, 1, 1 } },
4321 { ISD::USUBSAT, MVT::v64i8, { 1, 1, 1, 1 } },
4322 };
4323 static const CostKindTblEntry AVX512CostTbl[] = {
4324 { ISD::ABS, MVT::v8i64, { 1, 1, 1, 1 } },
4325 { ISD::ABS, MVT::v4i64, { 1, 1, 1, 1 } },
4326 { ISD::ABS, MVT::v2i64, { 1, 1, 1, 1 } },
4327 { ISD::ABS, MVT::v16i32, { 1, 1, 1, 1 } },
4328 { ISD::ABS, MVT::v8i32, { 1, 1, 1, 1 } },
4329 { ISD::ABS, MVT::v32i16, { 2, 7, 4, 4 } },
4330 { ISD::ABS, MVT::v16i16, { 1, 1, 1, 1 } },
4331 { ISD::ABS, MVT::v64i8, { 2, 7, 4, 4 } },
4332 { ISD::ABS, MVT::v32i8, { 1, 1, 1, 1 } },
4333 { ISD::BITREVERSE, MVT::v8i64, { 9, 13, 20, 20 } },
4334 { ISD::BITREVERSE, MVT::v16i32, { 9, 13, 20, 20 } },
4335 { ISD::BITREVERSE, MVT::v32i16, { 9, 13, 20, 20 } },
4336 { ISD::BITREVERSE, MVT::v64i8, { 6, 11, 17, 17 } },
4337 { ISD::BSWAP, MVT::v8i64, { 4, 7, 5, 5 } },
4338 { ISD::BSWAP, MVT::v16i32, { 4, 7, 5, 5 } },
4339 { ISD::BSWAP, MVT::v32i16, { 4, 7, 5, 5 } },
4340 { ISD::CTLZ, MVT::v8i64, { 10, 28, 32, 32 } },
4341 { ISD::CTLZ, MVT::v16i32, { 12, 30, 38, 38 } },
4342 { ISD::CTLZ, MVT::v32i16, { 8, 15, 29, 29 } },
4343 { ISD::CTLZ, MVT::v64i8, { 6, 11, 19, 19 } },
4344 { ISD::CTPOP, MVT::v8i64, { 16, 16, 19, 19 } },
4345 { ISD::CTPOP, MVT::v16i32, { 24, 19, 27, 27 } },
4346 { ISD::CTPOP, MVT::v32i16, { 18, 15, 22, 22 } },
4347 { ISD::CTPOP, MVT::v64i8, { 12, 11, 16, 16 } },
4348 { ISD::CTTZ, MVT::v8i64, { 2, 8, 6, 7 } },
4349 { ISD::CTTZ, MVT::v16i32, { 2, 8, 6, 7 } },
4350 { ISD::CTTZ, MVT::v32i16, { 7, 17, 27, 27 } },
4351 { ISD::CTTZ, MVT::v64i8, { 6, 13, 21, 21 } },
4352 { ISD::MULHS, MVT::v16i32, { 3, 10, 6, 7 } },
4353 { ISD::MULHS, MVT::v8i32, { 3, 9, 6, 6 } },
4354 { ISD::MULHS, MVT::v32i16, { 3, 7, 5, 5 } },
4355 { ISD::MULHS, MVT::v16i16, { 1, 5, 1, 1 } },
4356 { ISD::MULHU, MVT::v16i32, { 3, 10, 6, 7 } },
4357 { ISD::MULHU, MVT::v8i32, { 3, 9, 6, 6 } },
4358 { ISD::MULHU, MVT::v32i16, { 3, 7, 5, 5 } },
4359 { ISD::MULHU, MVT::v16i16, { 1, 5, 1, 1 } },
4360 { ISD::ROTL, MVT::v8i64, { 1, 1, 1, 1 } },
4361 { ISD::ROTL, MVT::v4i64, { 1, 1, 1, 1 } },
4362 { ISD::ROTL, MVT::v2i64, { 1, 1, 1, 1 } },
4363 { ISD::ROTL, MVT::v16i32, { 1, 1, 1, 1 } },
4364 { ISD::ROTL, MVT::v8i32, { 1, 1, 1, 1 } },
4365 { ISD::ROTL, MVT::v4i32, { 1, 1, 1, 1 } },
4366 { ISD::ROTR, MVT::v8i64, { 1, 1, 1, 1 } },
4367 { ISD::ROTR, MVT::v4i64, { 1, 1, 1, 1 } },
4368 { ISD::ROTR, MVT::v2i64, { 1, 1, 1, 1 } },
4369 { ISD::ROTR, MVT::v16i32, { 1, 1, 1, 1 } },
4370 { ISD::ROTR, MVT::v8i32, { 1, 1, 1, 1 } },
4371 { ISD::ROTR, MVT::v4i32, { 1, 1, 1, 1 } },
4372 { X86ISD::VROTLI, MVT::v8i64, { 1, 1, 1, 1 } },
4373 { X86ISD::VROTLI, MVT::v4i64, { 1, 1, 1, 1 } },
4374 { X86ISD::VROTLI, MVT::v2i64, { 1, 1, 1, 1 } },
4375 { X86ISD::VROTLI, MVT::v16i32, { 1, 1, 1, 1 } },
4376 { X86ISD::VROTLI, MVT::v8i32, { 1, 1, 1, 1 } },
4377 { X86ISD::VROTLI, MVT::v4i32, { 1, 1, 1, 1 } },
4378 { ISD::SADDSAT, MVT::v2i64, { 3, 3, 8, 9 } },
4379 { ISD::SADDSAT, MVT::v4i64, { 2, 2, 6, 7 } },
4380 { ISD::SADDSAT, MVT::v8i64, { 3, 3, 6, 7 } },
4381 { ISD::SADDSAT, MVT::v4i32, { 2, 2, 6, 7 } },
4382 { ISD::SADDSAT, MVT::v8i32, { 2, 2, 6, 7 } },
4383 { ISD::SADDSAT, MVT::v16i32, { 3, 3, 6, 7 } },
4384 { ISD::SADDSAT, MVT::v32i16, { 2, 2, 2, 2 } },
4385 { ISD::SADDSAT, MVT::v64i8, { 2, 2, 2, 2 } },
4386 { ISD::SMAX, MVT::v8i64, { 1, 3, 1, 1 } },
4387 { ISD::SMAX, MVT::v16i32, { 1, 1, 1, 1 } },
4388 { ISD::SMAX, MVT::v32i16, { 3, 7, 5, 5 } },
4389 { ISD::SMAX, MVT::v64i8, { 3, 7, 5, 5 } },
4390 { ISD::SMAX, MVT::v4i64, { 1, 3, 1, 1 } },
4391 { ISD::SMAX, MVT::v2i64, { 1, 3, 1, 1 } },
4392 { ISD::SMIN, MVT::v8i64, { 1, 3, 1, 1 } },
4393 { ISD::SMIN, MVT::v16i32, { 1, 1, 1, 1 } },
4394 { ISD::SMIN, MVT::v32i16, { 3, 7, 5, 5 } },
4395 { ISD::SMIN, MVT::v64i8, { 3, 7, 5, 5 } },
4396 { ISD::SMIN, MVT::v4i64, { 1, 3, 1, 1 } },
4397 { ISD::SMIN, MVT::v2i64, { 1, 3, 1, 1 } },
4398 { ISD::SMULO, MVT::v8i64, { 44, 44, 81, 93 } },
4399 { ISD::SMULO, MVT::v16i32, { 5, 12, 9, 11 } },
4400 { ISD::SMULO, MVT::v32i16, { 6, 12, 17, 17 } },
4401 { ISD::SMULO, MVT::v64i8, { 22, 28, 42, 42 } },
4402 { ISD::SSUBSAT, MVT::v2i64, { 2, 13, 9, 10 } },
4403 { ISD::SSUBSAT, MVT::v4i64, { 2, 15, 7, 8 } },
4404 { ISD::SSUBSAT, MVT::v8i64, { 2, 14, 7, 8 } },
4405 { ISD::SSUBSAT, MVT::v4i32, { 2, 14, 7, 8 } },
4406 { ISD::SSUBSAT, MVT::v8i32, { 2, 15, 7, 8 } },
4407 { ISD::SSUBSAT, MVT::v16i32, { 2, 14, 7, 8 } },
4408 { ISD::SSUBSAT, MVT::v32i16, { 2, 2, 2, 2 } },
4409 { ISD::SSUBSAT, MVT::v64i8, { 2, 2, 2, 2 } },
4410 { ISD::UMAX, MVT::v8i64, { 1, 3, 1, 1 } },
4411 { ISD::UMAX, MVT::v16i32, { 1, 1, 1, 1 } },
4412 { ISD::UMAX, MVT::v32i16, { 3, 7, 5, 5 } },
4413 { ISD::UMAX, MVT::v64i8, { 3, 7, 5, 5 } },
4414 { ISD::UMAX, MVT::v4i64, { 1, 3, 1, 1 } },
4415 { ISD::UMAX, MVT::v2i64, { 1, 3, 1, 1 } },
4416 { ISD::UMIN, MVT::v8i64, { 1, 3, 1, 1 } },
4417 { ISD::UMIN, MVT::v16i32, { 1, 1, 1, 1 } },
4418 { ISD::UMIN, MVT::v32i16, { 3, 7, 5, 5 } },
4419 { ISD::UMIN, MVT::v64i8, { 3, 7, 5, 5 } },
4420 { ISD::UMIN, MVT::v4i64, { 1, 3, 1, 1 } },
4421 { ISD::UMIN, MVT::v2i64, { 1, 3, 1, 1 } },
4422 { ISD::UMULO, MVT::v8i64, { 52, 52, 95, 104} },
4423 { ISD::UMULO, MVT::v16i32, { 5, 12, 8, 10 } },
4424 { ISD::UMULO, MVT::v32i16, { 5, 13, 16, 16 } },
4425 { ISD::UMULO, MVT::v64i8, { 18, 24, 30, 30 } },
4426 { ISD::UADDSAT, MVT::v2i64, { 1, 4, 4, 4 } },
4427 { ISD::UADDSAT, MVT::v4i64, { 1, 4, 4, 4 } },
4428 { ISD::UADDSAT, MVT::v8i64, { 1, 4, 4, 4 } },
4429 { ISD::UADDSAT, MVT::v4i32, { 1, 2, 4, 4 } },
4430 { ISD::UADDSAT, MVT::v8i32, { 1, 2, 4, 4 } },
4431 { ISD::UADDSAT, MVT::v16i32, { 2, 2, 4, 4 } },
4432 { ISD::UADDSAT, MVT::v32i16, { 2, 2, 2, 2 } },
4433 { ISD::UADDSAT, MVT::v64i8, { 2, 2, 2, 2 } },
4434 { ISD::USUBSAT, MVT::v2i64, { 1, 4, 2, 2 } },
4435 { ISD::USUBSAT, MVT::v4i64, { 1, 4, 2, 2 } },
4436 { ISD::USUBSAT, MVT::v8i64, { 1, 4, 2, 2 } },
4437 { ISD::USUBSAT, MVT::v8i32, { 1, 2, 2, 2 } },
4438 { ISD::USUBSAT, MVT::v16i32, { 1, 2, 2, 2 } },
4439 { ISD::USUBSAT, MVT::v32i16, { 2, 2, 2, 2 } },
4440 { ISD::USUBSAT, MVT::v64i8, { 2, 2, 2, 2 } },
4441 { ISD::FMAXNUM, MVT::f32, { 2, 2, 3, 3 } },
4442 { ISD::FMAXNUM, MVT::v4f32, { 1, 1, 3, 3 } },
4443 { ISD::FMAXNUM, MVT::v8f32, { 2, 2, 3, 3 } },
4444 { ISD::FMAXNUM, MVT::v16f32, { 4, 4, 3, 3 } },
4445 { ISD::FMAXNUM, MVT::f64, { 2, 2, 3, 3 } },
4446 { ISD::FMAXNUM, MVT::v2f64, { 1, 1, 3, 3 } },
4447 { ISD::FMAXNUM, MVT::v4f64, { 2, 2, 3, 3 } },
4448 { ISD::FMAXNUM, MVT::v8f64, { 3, 3, 3, 3 } },
4449 { ISD::FSQRT, MVT::f32, { 3, 12, 1, 1 } }, // Skylake from http://www.agner.org/
4450 { ISD::FSQRT, MVT::v4f32, { 3, 12, 1, 1 } }, // Skylake from http://www.agner.org/
4451 { ISD::FSQRT, MVT::v8f32, { 6, 12, 1, 1 } }, // Skylake from http://www.agner.org/
4452 { ISD::FSQRT, MVT::v16f32, { 12, 20, 1, 3 } }, // Skylake from http://www.agner.org/
4453 { ISD::FSQRT, MVT::f64, { 6, 18, 1, 1 } }, // Skylake from http://www.agner.org/
4454 { ISD::FSQRT, MVT::v2f64, { 6, 18, 1, 1 } }, // Skylake from http://www.agner.org/
4455 { ISD::FSQRT, MVT::v4f64, { 12, 18, 1, 1 } }, // Skylake from http://www.agner.org/
4456 { ISD::FSQRT, MVT::v8f64, { 24, 32, 1, 3 } }, // Skylake from http://www.agner.org/
4457 };
4458 static const CostKindTblEntry XOPCostTbl[] = {
4459 { ISD::BITREVERSE, MVT::v4i64, { 3, 6, 5, 6 } },
4460 { ISD::BITREVERSE, MVT::v8i32, { 3, 6, 5, 6 } },
4461 { ISD::BITREVERSE, MVT::v16i16, { 3, 6, 5, 6 } },
4462 { ISD::BITREVERSE, MVT::v32i8, { 3, 6, 5, 6 } },
4463 { ISD::BITREVERSE, MVT::v2i64, { 2, 7, 1, 1 } },
4464 { ISD::BITREVERSE, MVT::v4i32, { 2, 7, 1, 1 } },
4465 { ISD::BITREVERSE, MVT::v8i16, { 2, 7, 1, 1 } },
4466 { ISD::BITREVERSE, MVT::v16i8, { 2, 7, 1, 1 } },
4467 { ISD::BITREVERSE, MVT::i64, { 2, 2, 3, 4 } },
4468 { ISD::BITREVERSE, MVT::i32, { 2, 2, 3, 4 } },
4469 { ISD::BITREVERSE, MVT::i16, { 2, 2, 3, 4 } },
4470 { ISD::BITREVERSE, MVT::i8, { 2, 2, 3, 4 } },
4471 // XOP: ROTL = VPROT(X,Y), ROTR = VPROT(X,SUB(0,Y))
4472 { ISD::ROTL, MVT::v4i64, { 4, 7, 5, 6 } },
4473 { ISD::ROTL, MVT::v8i32, { 4, 7, 5, 6 } },
4474 { ISD::ROTL, MVT::v16i16, { 4, 7, 5, 6 } },
4475 { ISD::ROTL, MVT::v32i8, { 4, 7, 5, 6 } },
4476 { ISD::ROTL, MVT::v2i64, { 1, 3, 1, 1 } },
4477 { ISD::ROTL, MVT::v4i32, { 1, 3, 1, 1 } },
4478 { ISD::ROTL, MVT::v8i16, { 1, 3, 1, 1 } },
4479 { ISD::ROTL, MVT::v16i8, { 1, 3, 1, 1 } },
4480 { ISD::ROTR, MVT::v4i64, { 4, 7, 8, 9 } },
4481 { ISD::ROTR, MVT::v8i32, { 4, 7, 8, 9 } },
4482 { ISD::ROTR, MVT::v16i16, { 4, 7, 8, 9 } },
4483 { ISD::ROTR, MVT::v32i8, { 4, 7, 8, 9 } },
4484 { ISD::ROTR, MVT::v2i64, { 1, 3, 3, 3 } },
4485 { ISD::ROTR, MVT::v4i32, { 1, 3, 3, 3 } },
4486 { ISD::ROTR, MVT::v8i16, { 1, 3, 3, 3 } },
4487 { ISD::ROTR, MVT::v16i8, { 1, 3, 3, 3 } },
4488 { X86ISD::VROTLI, MVT::v4i64, { 4, 7, 5, 6 } },
4489 { X86ISD::VROTLI, MVT::v8i32, { 4, 7, 5, 6 } },
4490 { X86ISD::VROTLI, MVT::v16i16, { 4, 7, 5, 6 } },
4491 { X86ISD::VROTLI, MVT::v32i8, { 4, 7, 5, 6 } },
4492 { X86ISD::VROTLI, MVT::v2i64, { 1, 3, 1, 1 } },
4493 { X86ISD::VROTLI, MVT::v4i32, { 1, 3, 1, 1 } },
4494 { X86ISD::VROTLI, MVT::v8i16, { 1, 3, 1, 1 } },
4495 { X86ISD::VROTLI, MVT::v16i8, { 1, 3, 1, 1 } },
4496 };
4497 static const CostKindTblEntry AVX2CostTbl[] = {
4498 { ISD::ABS, MVT::v2i64, { 2, 4, 3, 5 } }, // VBLENDVPD(X,VPSUBQ(0,X),X)
4499 { ISD::ABS, MVT::v4i64, { 2, 4, 3, 5 } }, // VBLENDVPD(X,VPSUBQ(0,X),X)
4500 { ISD::ABS, MVT::v4i32, { 1, 1, 1, 1 } },
4501 { ISD::ABS, MVT::v8i32, { 1, 1, 1, 2 } },
4502 { ISD::ABS, MVT::v8i16, { 1, 1, 1, 1 } },
4503 { ISD::ABS, MVT::v16i16, { 1, 1, 1, 2 } },
4504 { ISD::ABS, MVT::v16i8, { 1, 1, 1, 1 } },
4505 { ISD::ABS, MVT::v32i8, { 1, 1, 1, 2 } },
4506 { ISD::BITREVERSE, MVT::v2i64, { 3, 11, 10, 11 } },
4507 { ISD::BITREVERSE, MVT::v4i64, { 5, 11, 10, 17 } },
4508 { ISD::BITREVERSE, MVT::v4i32, { 3, 11, 10, 11 } },
4509 { ISD::BITREVERSE, MVT::v8i32, { 5, 11, 10, 17 } },
4510 { ISD::BITREVERSE, MVT::v8i16, { 3, 11, 10, 11 } },
4511 { ISD::BITREVERSE, MVT::v16i16, { 5, 11, 10, 17 } },
4512 { ISD::BITREVERSE, MVT::v16i8, { 3, 6, 9, 9 } },
4513 { ISD::BITREVERSE, MVT::v32i8, { 4, 5, 9, 15 } },
4514 { ISD::BSWAP, MVT::v2i64, { 1, 2, 1, 2 } },
4515 { ISD::BSWAP, MVT::v4i64, { 1, 3, 1, 2 } },
4516 { ISD::BSWAP, MVT::v4i32, { 1, 2, 1, 2 } },
4517 { ISD::BSWAP, MVT::v8i32, { 1, 3, 1, 2 } },
4518 { ISD::BSWAP, MVT::v8i16, { 1, 2, 1, 2 } },
4519 { ISD::BSWAP, MVT::v16i16, { 1, 3, 1, 2 } },
4520 { ISD::CTLZ, MVT::v2i64, { 7, 18, 24, 25 } },
4521 { ISD::CTLZ, MVT::v4i64, { 14, 18, 24, 44 } },
4522 { ISD::CTLZ, MVT::v4i32, { 5, 16, 19, 20 } },
4523 { ISD::CTLZ, MVT::v8i32, { 10, 16, 19, 34 } },
4524 { ISD::CTLZ, MVT::v8i16, { 4, 13, 14, 15 } },
4525 { ISD::CTLZ, MVT::v16i16, { 6, 14, 14, 24 } },
4526 { ISD::CTLZ, MVT::v16i8, { 3, 12, 9, 10 } },
4527 { ISD::CTLZ, MVT::v32i8, { 4, 12, 9, 14 } },
4528 { ISD::CTPOP, MVT::v2i64, { 3, 9, 10, 10 } },
4529 { ISD::CTPOP, MVT::v4i64, { 4, 9, 10, 14 } },
4530 { ISD::CTPOP, MVT::v4i32, { 7, 12, 14, 14 } },
4531 { ISD::CTPOP, MVT::v8i32, { 7, 12, 14, 18 } },
4532 { ISD::CTPOP, MVT::v8i16, { 3, 7, 11, 11 } },
4533 { ISD::CTPOP, MVT::v16i16, { 6, 8, 11, 18 } },
4534 { ISD::CTPOP, MVT::v16i8, { 2, 5, 8, 8 } },
4535 { ISD::CTPOP, MVT::v32i8, { 3, 5, 8, 12 } },
4536 { ISD::CTTZ, MVT::v2i64, { 4, 11, 13, 13 } },
4537 { ISD::CTTZ, MVT::v4i64, { 5, 11, 13, 20 } },
4538 { ISD::CTTZ, MVT::v4i32, { 7, 14, 17, 17 } },
4539 { ISD::CTTZ, MVT::v8i32, { 7, 15, 17, 24 } },
4540 { ISD::CTTZ, MVT::v8i16, { 4, 9, 14, 14 } },
4541 { ISD::CTTZ, MVT::v16i16, { 6, 9, 14, 24 } },
4542 { ISD::CTTZ, MVT::v16i8, { 3, 7, 11, 11 } },
4543 { ISD::CTTZ, MVT::v32i8, { 5, 7, 11, 18 } },
4544 { ISD::MULHS, MVT::v8i32, { 4, 9, 6, 12 } },
4545 { ISD::MULHS, MVT::v16i16, { 2, 5, 1, 2 } },
4546 { ISD::MULHU, MVT::v8i32, { 4, 9, 6, 12 } },
4547 { ISD::MULHU, MVT::v16i16, { 2, 5, 1, 2 } },
4548 { ISD::SADDSAT, MVT::v2i64, { 4, 13, 8, 11 } },
4549 { ISD::SADDSAT, MVT::v4i64, { 3, 10, 8, 12 } },
4550 { ISD::SADDSAT, MVT::v4i32, { 2, 6, 7, 9 } },
4551 { ISD::SADDSAT, MVT::v8i32, { 4, 6, 7, 13 } },
4552 { ISD::SADDSAT, MVT::v16i16, { 1, 1, 1, 2 } },
4553 { ISD::SADDSAT, MVT::v32i8, { 1, 1, 1, 2 } },
4554 { ISD::SMAX, MVT::v2i64, { 2, 7, 2, 3 } },
4555 { ISD::SMAX, MVT::v4i64, { 2, 7, 2, 3 } },
4556 { ISD::SMAX, MVT::v8i32, { 1, 1, 1, 2 } },
4557 { ISD::SMAX, MVT::v16i16, { 1, 1, 1, 2 } },
4558 { ISD::SMAX, MVT::v32i8, { 1, 1, 1, 2 } },
4559 { ISD::SMIN, MVT::v2i64, { 2, 7, 2, 3 } },
4560 { ISD::SMIN, MVT::v4i64, { 2, 7, 2, 3 } },
4561 { ISD::SMIN, MVT::v8i32, { 1, 1, 1, 2 } },
4562 { ISD::SMIN, MVT::v16i16, { 1, 1, 1, 2 } },
4563 { ISD::SMIN, MVT::v32i8, { 1, 1, 1, 2 } },
4564 { ISD::SMULO, MVT::v4i64, { 20, 20, 33, 37 } },
4565 { ISD::SMULO, MVT::v2i64, { 8, 8, 13, 15 } },
4566 { ISD::SMULO, MVT::v8i32, { 8, 20, 13, 24 } },
4567 { ISD::SMULO, MVT::v4i32, { 5, 15, 11, 12 } },
4568 { ISD::SMULO, MVT::v16i16, { 4, 14, 8, 14 } },
4569 { ISD::SMULO, MVT::v8i16, { 3, 9, 6, 6 } },
4570 { ISD::SMULO, MVT::v32i8, { 9, 15, 18, 35 } },
4571 { ISD::SMULO, MVT::v16i8, { 6, 22, 14, 21 } },
4572 { ISD::SSUBSAT, MVT::v2i64, { 4, 13, 9, 13 } },
4573 { ISD::SSUBSAT, MVT::v4i64, { 4, 15, 9, 13 } },
4574 { ISD::SSUBSAT, MVT::v4i32, { 3, 14, 9, 11 } },
4575 { ISD::SSUBSAT, MVT::v8i32, { 4, 15, 9, 16 } },
4576 { ISD::SSUBSAT, MVT::v16i16, { 1, 1, 1, 2 } },
4577 { ISD::SSUBSAT, MVT::v32i8, { 1, 1, 1, 2 } },
4578 { ISD::UADDSAT, MVT::v2i64, { 2, 8, 6, 6 } },
4579 { ISD::UADDSAT, MVT::v4i64, { 3, 8, 6, 10 } },
4580 { ISD::UADDSAT, MVT::v8i32, { 2, 2, 4, 8 } },
4581 { ISD::UADDSAT, MVT::v16i16, { 1, 1, 1, 2 } },
4582 { ISD::UADDSAT, MVT::v32i8, { 1, 1, 1, 2 } },
4583 { ISD::UMAX, MVT::v2i64, { 2, 8, 5, 6 } },
4584 { ISD::UMAX, MVT::v4i64, { 2, 8, 5, 8 } },
4585 { ISD::UMAX, MVT::v8i32, { 1, 1, 1, 2 } },
4586 { ISD::UMAX, MVT::v16i16, { 1, 1, 1, 2 } },
4587 { ISD::UMAX, MVT::v32i8, { 1, 1, 1, 2 } },
4588 { ISD::UMIN, MVT::v2i64, { 2, 8, 5, 6 } },
4589 { ISD::UMIN, MVT::v4i64, { 2, 8, 5, 8 } },
4590 { ISD::UMIN, MVT::v8i32, { 1, 1, 1, 2 } },
4591 { ISD::UMIN, MVT::v16i16, { 1, 1, 1, 2 } },
4592 { ISD::UMIN, MVT::v32i8, { 1, 1, 1, 2 } },
4593 { ISD::UMULO, MVT::v4i64, { 24, 24, 39, 43 } },
4594 { ISD::UMULO, MVT::v2i64, { 10, 10, 15, 19 } },
4595 { ISD::UMULO, MVT::v8i32, { 8, 11, 13, 23 } },
4596 { ISD::UMULO, MVT::v4i32, { 5, 12, 11, 12 } },
4597 { ISD::UMULO, MVT::v16i16, { 4, 6, 8, 13 } },
4598 { ISD::UMULO, MVT::v8i16, { 2, 8, 6, 6 } },
4599 { ISD::UMULO, MVT::v32i8, { 9, 13, 17, 33 } },
4600 { ISD::UMULO, MVT::v16i8, { 6, 19, 13, 20 } },
4601 { ISD::USUBSAT, MVT::v2i64, { 2, 7, 6, 6 } },
4602 { ISD::USUBSAT, MVT::v4i64, { 3, 7, 6, 10 } },
4603 { ISD::USUBSAT, MVT::v8i32, { 2, 2, 2, 4 } },
4604 { ISD::USUBSAT, MVT::v16i16, { 1, 1, 1, 2 } },
4605 { ISD::USUBSAT, MVT::v32i8, { 1, 1, 1, 2 } },
4606 { ISD::FMAXNUM, MVT::f32, { 2, 7, 3, 5 } }, // MAXSS + CMPUNORDSS + BLENDVPS
4607 { ISD::FMAXNUM, MVT::v4f32, { 2, 7, 3, 5 } }, // MAXPS + CMPUNORDPS + BLENDVPS
4608 { ISD::FMAXNUM, MVT::v8f32, { 3, 7, 3, 6 } }, // MAXPS + CMPUNORDPS + BLENDVPS
4609 { ISD::FMAXNUM, MVT::f64, { 2, 7, 3, 5 } }, // MAXSD + CMPUNORDSD + BLENDVPD
4610 { ISD::FMAXNUM, MVT::v2f64, { 2, 7, 3, 5 } }, // MAXPD + CMPUNORDPD + BLENDVPD
4611 { ISD::FMAXNUM, MVT::v4f64, { 3, 7, 3, 6 } }, // MAXPD + CMPUNORDPD + BLENDVPD
4612 { ISD::FSQRT, MVT::f32, { 7, 15, 1, 1 } }, // vsqrtss
4613 { ISD::FSQRT, MVT::v4f32, { 7, 15, 1, 1 } }, // vsqrtps
4614 { ISD::FSQRT, MVT::v8f32, { 14, 21, 1, 3 } }, // vsqrtps
4615 { ISD::FSQRT, MVT::f64, { 14, 21, 1, 1 } }, // vsqrtsd
4616 { ISD::FSQRT, MVT::v2f64, { 14, 21, 1, 1 } }, // vsqrtpd
4617 { ISD::FSQRT, MVT::v4f64, { 28, 35, 1, 3 } }, // vsqrtpd
4618 };
4619 static const CostKindTblEntry AVX1CostTbl[] = {
4620 { ISD::ABS, MVT::v4i64, { 6, 8, 6, 12 } }, // VBLENDVPD(X,VPSUBQ(0,X),X)
4621 { ISD::ABS, MVT::v8i32, { 3, 6, 4, 5 } },
4622 { ISD::ABS, MVT::v16i16, { 3, 6, 4, 5 } },
4623 { ISD::ABS, MVT::v32i8, { 3, 6, 4, 5 } },
4624 { ISD::BITREVERSE, MVT::v4i64, { 17, 20, 20, 33 } }, // 2 x 128-bit Op + extract/insert
4625 { ISD::BITREVERSE, MVT::v2i64, { 8, 13, 10, 16 } },
4626 { ISD::BITREVERSE, MVT::v8i32, { 17, 20, 20, 33 } }, // 2 x 128-bit Op + extract/insert
4627 { ISD::BITREVERSE, MVT::v4i32, { 8, 13, 10, 16 } },
4628 { ISD::BITREVERSE, MVT::v16i16, { 17, 20, 20, 33 } }, // 2 x 128-bit Op + extract/insert
4629 { ISD::BITREVERSE, MVT::v8i16, { 8, 13, 10, 16 } },
4630 { ISD::BITREVERSE, MVT::v32i8, { 13, 15, 17, 26 } }, // 2 x 128-bit Op + extract/insert
4631 { ISD::BITREVERSE, MVT::v16i8, { 7, 7, 9, 13 } },
4632 { ISD::BSWAP, MVT::v4i64, { 5, 6, 5, 10 } },
4633 { ISD::BSWAP, MVT::v2i64, { 2, 2, 1, 3 } },
4634 { ISD::BSWAP, MVT::v8i32, { 5, 6, 5, 10 } },
4635 { ISD::BSWAP, MVT::v4i32, { 2, 2, 1, 3 } },
4636 { ISD::BSWAP, MVT::v16i16, { 5, 6, 5, 10 } },
4637 { ISD::BSWAP, MVT::v8i16, { 2, 2, 1, 3 } },
4638 { ISD::CTLZ, MVT::v4i64, { 29, 33, 49, 58 } }, // 2 x 128-bit Op + extract/insert
4639 { ISD::CTLZ, MVT::v2i64, { 14, 24, 24, 28 } },
4640 { ISD::CTLZ, MVT::v8i32, { 24, 28, 39, 48 } }, // 2 x 128-bit Op + extract/insert
4641 { ISD::CTLZ, MVT::v4i32, { 12, 20, 19, 23 } },
4642 { ISD::CTLZ, MVT::v16i16, { 19, 22, 29, 38 } }, // 2 x 128-bit Op + extract/insert
4643 { ISD::CTLZ, MVT::v8i16, { 9, 16, 14, 18 } },
4644 { ISD::CTLZ, MVT::v32i8, { 14, 15, 19, 28 } }, // 2 x 128-bit Op + extract/insert
4645 { ISD::CTLZ, MVT::v16i8, { 7, 12, 9, 13 } },
4646 { ISD::CTPOP, MVT::v4i64, { 14, 18, 19, 28 } }, // 2 x 128-bit Op + extract/insert
4647 { ISD::CTPOP, MVT::v2i64, { 7, 14, 10, 14 } },
4648 { ISD::CTPOP, MVT::v8i32, { 18, 24, 27, 36 } }, // 2 x 128-bit Op + extract/insert
4649 { ISD::CTPOP, MVT::v4i32, { 9, 20, 14, 18 } },
4650 { ISD::CTPOP, MVT::v16i16, { 16, 21, 22, 31 } }, // 2 x 128-bit Op + extract/insert
4651 { ISD::CTPOP, MVT::v8i16, { 8, 18, 11, 15 } },
4652 { ISD::CTPOP, MVT::v32i8, { 13, 15, 16, 25 } }, // 2 x 128-bit Op + extract/insert
4653 { ISD::CTPOP, MVT::v16i8, { 6, 12, 8, 12 } },
4654 { ISD::CTTZ, MVT::v4i64, { 17, 22, 24, 33 } }, // 2 x 128-bit Op + extract/insert
4655 { ISD::CTTZ, MVT::v2i64, { 9, 19, 13, 17 } },
4656 { ISD::CTTZ, MVT::v8i32, { 21, 27, 32, 41 } }, // 2 x 128-bit Op + extract/insert
4657 { ISD::CTTZ, MVT::v4i32, { 11, 24, 17, 21 } },
4658 { ISD::CTTZ, MVT::v16i16, { 18, 24, 27, 36 } }, // 2 x 128-bit Op + extract/insert
4659 { ISD::CTTZ, MVT::v8i16, { 9, 21, 14, 18 } },
4660 { ISD::CTTZ, MVT::v32i8, { 15, 18, 21, 30 } }, // 2 x 128-bit Op + extract/insert
4661 { ISD::CTTZ, MVT::v16i8, { 8, 16, 11, 15 } },
4662 { ISD::MULHS, MVT::v8i32, { 9, 11, 14, 18 } },
4663 { ISD::MULHS, MVT::v16i16, { 3, 7, 5, 6 } },
4664 { ISD::MULHU, MVT::v8i32, { 9, 11, 14, 18 } },
4665 { ISD::MULHU, MVT::v16i16, { 3, 7, 5, 6 } },
4666 { ISD::SADDSAT, MVT::v2i64, { 6, 13, 8, 11 } },
4667 { ISD::SADDSAT, MVT::v4i64, { 13, 20, 15, 25 } }, // 2 x 128-bit Op + extract/insert
4668 { ISD::SADDSAT, MVT::v8i32, { 12, 18, 14, 24 } }, // 2 x 128-bit Op + extract/insert
4669 { ISD::SADDSAT, MVT::v16i16, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4670 { ISD::SADDSAT, MVT::v32i8, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4671 { ISD::SMAX, MVT::v4i64, { 6, 9, 6, 12 } }, // 2 x 128-bit Op + extract/insert
4672 { ISD::SMAX, MVT::v2i64, { 3, 7, 2, 4 } },
4673 { ISD::SMAX, MVT::v8i32, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4674 { ISD::SMAX, MVT::v16i16, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4675 { ISD::SMAX, MVT::v32i8, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4676 { ISD::SMIN, MVT::v4i64, { 6, 9, 6, 12 } }, // 2 x 128-bit Op + extract/insert
4677 { ISD::SMIN, MVT::v2i64, { 3, 7, 2, 3 } },
4678 { ISD::SMIN, MVT::v8i32, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4679 { ISD::SMIN, MVT::v16i16, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4680 { ISD::SMIN, MVT::v32i8, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4681 { ISD::SMULO, MVT::v4i64, { 20, 20, 33, 37 } },
4682 { ISD::SMULO, MVT::v2i64, { 9, 9, 13, 17 } },
4683 { ISD::SMULO, MVT::v8i32, { 15, 20, 24, 29 } },
4684 { ISD::SMULO, MVT::v4i32, { 7, 15, 11, 13 } },
4685 { ISD::SMULO, MVT::v16i16, { 8, 14, 14, 15 } },
4686 { ISD::SMULO, MVT::v8i16, { 3, 9, 6, 6 } },
4687 { ISD::SMULO, MVT::v32i8, { 20, 20, 37, 39 } },
4688 { ISD::SMULO, MVT::v16i8, { 9, 22, 18, 21 } },
4689 { ISD::SSUBSAT, MVT::v2i64, { 7, 13, 9, 13 } },
4690 { ISD::SSUBSAT, MVT::v4i64, { 15, 21, 18, 29 } }, // 2 x 128-bit Op + extract/insert
4691 { ISD::SSUBSAT, MVT::v8i32, { 15, 19, 18, 29 } }, // 2 x 128-bit Op + extract/insert
4692 { ISD::SSUBSAT, MVT::v16i16, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4693 { ISD::SSUBSAT, MVT::v32i8, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4694 { ISD::UADDSAT, MVT::v2i64, { 3, 8, 6, 6 } },
4695 { ISD::UADDSAT, MVT::v4i64, { 8, 11, 14, 15 } }, // 2 x 128-bit Op + extract/insert
4696 { ISD::UADDSAT, MVT::v8i32, { 6, 6, 10, 11 } }, // 2 x 128-bit Op + extract/insert
4697 { ISD::UADDSAT, MVT::v16i16, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4698 { ISD::UADDSAT, MVT::v32i8, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4699 { ISD::UMAX, MVT::v4i64, { 9, 10, 11, 17 } }, // 2 x 128-bit Op + extract/insert
4700 { ISD::UMAX, MVT::v2i64, { 4, 8, 5, 7 } },
4701 { ISD::UMAX, MVT::v8i32, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4702 { ISD::UMAX, MVT::v16i16, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4703 { ISD::UMAX, MVT::v32i8, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4704 { ISD::UMIN, MVT::v4i64, { 9, 10, 11, 17 } }, // 2 x 128-bit Op + extract/insert
4705 { ISD::UMIN, MVT::v2i64, { 4, 8, 5, 7 } },
4706 { ISD::UMIN, MVT::v8i32, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4707 { ISD::UMIN, MVT::v16i16, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4708 { ISD::UMIN, MVT::v32i8, { 4, 6, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4709 { ISD::UMULO, MVT::v4i64, { 24, 26, 39, 45 } },
4710 { ISD::UMULO, MVT::v2i64, { 10, 12, 15, 20 } },
4711 { ISD::UMULO, MVT::v8i32, { 14, 15, 23, 28 } },
4712 { ISD::UMULO, MVT::v4i32, { 7, 12, 11, 13 } },
4713 { ISD::UMULO, MVT::v16i16, { 7, 11, 13, 14 } },
4714 { ISD::UMULO, MVT::v8i16, { 3, 8, 6, 6 } },
4715 { ISD::UMULO, MVT::v32i8, { 19, 19, 35, 37 } },
4716 { ISD::UMULO, MVT::v16i8, { 9, 19, 17, 20 } },
4717 { ISD::USUBSAT, MVT::v2i64, { 3, 7, 6, 6 } },
4718 { ISD::USUBSAT, MVT::v4i64, { 8, 10, 14, 15 } }, // 2 x 128-bit Op + extract/insert
4719 { ISD::USUBSAT, MVT::v8i32, { 4, 4, 7, 8 } }, // 2 x 128-bit Op + extract/insert
4720 { ISD::USUBSAT, MVT::v8i32, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4721 { ISD::USUBSAT, MVT::v16i16, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4722 { ISD::USUBSAT, MVT::v32i8, { 3, 3, 5, 6 } }, // 2 x 128-bit Op + extract/insert
4723 { ISD::FMAXNUM, MVT::f32, { 3, 6, 3, 5 } }, // MAXSS + CMPUNORDSS + BLENDVPS
4724 { ISD::FMAXNUM, MVT::v4f32, { 3, 6, 3, 5 } }, // MAXPS + CMPUNORDPS + BLENDVPS
4725 { ISD::FMAXNUM, MVT::v8f32, { 5, 7, 3, 10 } }, // MAXPS + CMPUNORDPS + BLENDVPS
4726 { ISD::FMAXNUM, MVT::f64, { 3, 6, 3, 5 } }, // MAXSD + CMPUNORDSD + BLENDVPD
4727 { ISD::FMAXNUM, MVT::v2f64, { 3, 6, 3, 5 } }, // MAXPD + CMPUNORDPD + BLENDVPD
4728 { ISD::FMAXNUM, MVT::v4f64, { 5, 7, 3, 10 } }, // MAXPD + CMPUNORDPD + BLENDVPD
4729 { ISD::FSQRT, MVT::f32, { 21, 21, 1, 1 } }, // vsqrtss
4730 { ISD::FSQRT, MVT::v4f32, { 21, 21, 1, 1 } }, // vsqrtps
4731 { ISD::FSQRT, MVT::v8f32, { 42, 42, 1, 3 } }, // vsqrtps
4732 { ISD::FSQRT, MVT::f64, { 27, 27, 1, 1 } }, // vsqrtsd
4733 { ISD::FSQRT, MVT::v2f64, { 27, 27, 1, 1 } }, // vsqrtpd
4734 { ISD::FSQRT, MVT::v4f64, { 54, 54, 1, 3 } }, // vsqrtpd
4735 };
4736 static const CostKindTblEntry GFNICostTbl[] = {
4737 { ISD::BITREVERSE, MVT::i8, { 3, 3, 3, 4 } }, // gf2p8affineqb
4738 { ISD::BITREVERSE, MVT::i16, { 3, 3, 4, 6 } }, // gf2p8affineqb
4739 { ISD::BITREVERSE, MVT::i32, { 3, 3, 4, 5 } }, // gf2p8affineqb
4740 { ISD::BITREVERSE, MVT::i64, { 3, 3, 4, 6 } }, // gf2p8affineqb
4741 { ISD::BITREVERSE, MVT::v16i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4742 { ISD::BITREVERSE, MVT::v32i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4743 { ISD::BITREVERSE, MVT::v64i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4744 { ISD::BITREVERSE, MVT::v8i16, { 1, 8, 2, 4 } }, // gf2p8affineqb
4745 { ISD::BITREVERSE, MVT::v16i16, { 1, 9, 2, 4 } }, // gf2p8affineqb
4746 { ISD::BITREVERSE, MVT::v32i16, { 1, 9, 2, 4 } }, // gf2p8affineqb
4747 { ISD::BITREVERSE, MVT::v4i32, { 1, 8, 2, 4 } }, // gf2p8affineqb
4748 { ISD::BITREVERSE, MVT::v8i32, { 1, 9, 2, 4 } }, // gf2p8affineqb
4749 { ISD::BITREVERSE, MVT::v16i32, { 1, 9, 2, 4 } }, // gf2p8affineqb
4750 { ISD::BITREVERSE, MVT::v2i64, { 1, 8, 2, 4 } }, // gf2p8affineqb
4751 { ISD::BITREVERSE, MVT::v4i64, { 1, 9, 2, 4 } }, // gf2p8affineqb
4752 { ISD::BITREVERSE, MVT::v8i64, { 1, 9, 2, 4 } }, // gf2p8affineqb
4753 { X86ISD::VROTLI, MVT::v16i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4754 { X86ISD::VROTLI, MVT::v32i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4755 { X86ISD::VROTLI, MVT::v64i8, { 1, 6, 1, 2 } }, // gf2p8affineqb
4756 };
4757 static const CostKindTblEntry GLMCostTbl[] = {
4758 { ISD::FSQRT, MVT::f32, { 19, 20, 1, 1 } }, // sqrtss
4759 { ISD::FSQRT, MVT::v4f32, { 37, 41, 1, 5 } }, // sqrtps
4760 { ISD::FSQRT, MVT::f64, { 34, 35, 1, 1 } }, // sqrtsd
4761 { ISD::FSQRT, MVT::v2f64, { 67, 71, 1, 5 } }, // sqrtpd
4762 };
4763 static const CostKindTblEntry SLMCostTbl[] = {
4764 { ISD::BSWAP, MVT::v2i64, { 5, 5, 1, 5 } },
4765 { ISD::BSWAP, MVT::v4i32, { 5, 5, 1, 5 } },
4766 { ISD::BSWAP, MVT::v8i16, { 5, 5, 1, 5 } },
4767 { ISD::FSQRT, MVT::f32, { 20, 20, 1, 1 } }, // sqrtss
4768 { ISD::FSQRT, MVT::v4f32, { 40, 41, 1, 5 } }, // sqrtps
4769 { ISD::FSQRT, MVT::f64, { 35, 35, 1, 1 } }, // sqrtsd
4770 { ISD::FSQRT, MVT::v2f64, { 70, 71, 1, 5 } }, // sqrtpd
4771 };
4772 static const CostKindTblEntry SSE42CostTbl[] = {
4773 { ISD::FMAXNUM, MVT::f32, { 5, 5, 7, 7 } }, // MAXSS + CMPUNORDSS + BLENDVPS
4774 { ISD::FMAXNUM, MVT::v4f32, { 4, 4, 4, 5 } }, // MAXPS + CMPUNORDPS + BLENDVPS
4775 { ISD::FMAXNUM, MVT::f64, { 5, 5, 7, 7 } }, // MAXSD + CMPUNORDSD + BLENDVPD
4776 { ISD::FMAXNUM, MVT::v2f64, { 4, 4, 4, 5 } }, // MAXPD + CMPUNORDPD + BLENDVPD
4777 { ISD::FSQRT, MVT::f32, { 18, 18, 1, 1 } }, // Nehalem from http://www.agner.org/
4778 { ISD::FSQRT, MVT::v4f32, { 18, 18, 1, 1 } }, // Nehalem from http://www.agner.org/
4779 };
4780 static const CostKindTblEntry SSE41CostTbl[] = {
4781 { ISD::ABS, MVT::v2i64, { 3, 4, 3, 5 } }, // BLENDVPD(X,PSUBQ(0,X),X)
4782 { ISD::MULHS, MVT::v4i32, { 3, 9, 6, 7 } },
4783 { ISD::MULHU, MVT::v4i32, { 3, 9, 6, 7 } },
4784 { ISD::SADDSAT, MVT::v2i64, { 10, 14, 17, 21 } },
4785 { ISD::SADDSAT, MVT::v4i32, { 5, 11, 8, 10 } },
4786 { ISD::SSUBSAT, MVT::v2i64, { 12, 19, 25, 29 } },
4787 { ISD::SSUBSAT, MVT::v4i32, { 6, 14, 10, 12 } },
4788 { ISD::SMAX, MVT::v2i64, { 3, 7, 2, 3 } },
4789 { ISD::SMAX, MVT::v4i32, { 1, 1, 1, 1 } },
4790 { ISD::SMAX, MVT::v16i8, { 1, 1, 1, 1 } },
4791 { ISD::SMIN, MVT::v2i64, { 3, 7, 2, 3 } },
4792 { ISD::SMIN, MVT::v4i32, { 1, 1, 1, 1 } },
4793 { ISD::SMIN, MVT::v16i8, { 1, 1, 1, 1 } },
4794 { ISD::SMULO, MVT::v2i64, { 9, 11, 13, 17 } },
4795 { ISD::SMULO, MVT::v4i32, { 20, 24, 13, 19 } },
4796 { ISD::SMULO, MVT::v8i16, { 5, 9, 8, 8 } },
4797 { ISD::SMULO, MVT::v16i8, { 13, 22, 24, 25 } },
4798 { ISD::UADDSAT, MVT::v2i64, { 6, 13, 14, 14 } },
4799 { ISD::UADDSAT, MVT::v4i32, { 2, 2, 4, 4 } },
4800 { ISD::USUBSAT, MVT::v2i64, { 6, 10, 14, 14 } },
4801 { ISD::USUBSAT, MVT::v4i32, { 1, 2, 2, 2 } },
4802 { ISD::UMAX, MVT::v2i64, { 2, 11, 6, 7 } },
4803 { ISD::UMAX, MVT::v4i32, { 1, 1, 1, 1 } },
4804 { ISD::UMAX, MVT::v8i16, { 1, 1, 1, 1 } },
4805 { ISD::UMIN, MVT::v2i64, { 2, 11, 6, 7 } },
4806 { ISD::UMIN, MVT::v4i32, { 1, 1, 1, 1 } },
4807 { ISD::UMIN, MVT::v8i16, { 1, 1, 1, 1 } },
4808 { ISD::UMULO, MVT::v2i64, { 14, 20, 15, 20 } },
4809 { ISD::UMULO, MVT::v4i32, { 19, 22, 12, 18 } },
4810 { ISD::UMULO, MVT::v8i16, { 4, 9, 7, 7 } },
4811 { ISD::UMULO, MVT::v16i8, { 13, 19, 18, 20 } },
4812 };
4813 static const CostKindTblEntry SSSE3CostTbl[] = {
4814 { ISD::ABS, MVT::v4i32, { 1, 2, 1, 1 } },
4815 { ISD::ABS, MVT::v8i16, { 1, 2, 1, 1 } },
4816 { ISD::ABS, MVT::v16i8, { 1, 2, 1, 1 } },
4817 { ISD::BITREVERSE, MVT::v2i64, { 16, 20, 11, 21 } },
4818 { ISD::BITREVERSE, MVT::v4i32, { 16, 20, 11, 21 } },
4819 { ISD::BITREVERSE, MVT::v8i16, { 16, 20, 11, 21 } },
4820 { ISD::BITREVERSE, MVT::v16i8, { 11, 12, 10, 16 } },
4821 { ISD::BSWAP, MVT::v2i64, { 2, 3, 1, 5 } },
4822 { ISD::BSWAP, MVT::v4i32, { 2, 3, 1, 5 } },
4823 { ISD::BSWAP, MVT::v8i16, { 2, 3, 1, 5 } },
4824 { ISD::CTLZ, MVT::v2i64, { 18, 28, 28, 35 } },
4825 { ISD::CTLZ, MVT::v4i32, { 15, 20, 22, 28 } },
4826 { ISD::CTLZ, MVT::v8i16, { 13, 17, 16, 22 } },
4827 { ISD::CTLZ, MVT::v16i8, { 11, 15, 10, 16 } },
4828 { ISD::CTPOP, MVT::v2i64, { 13, 19, 12, 18 } },
4829 { ISD::CTPOP, MVT::v4i32, { 18, 24, 16, 22 } },
4830 { ISD::CTPOP, MVT::v8i16, { 13, 18, 14, 20 } },
4831 { ISD::CTPOP, MVT::v16i8, { 11, 12, 10, 16 } },
4832 { ISD::CTTZ, MVT::v2i64, { 13, 25, 15, 22 } },
4833 { ISD::CTTZ, MVT::v4i32, { 18, 26, 19, 25 } },
4834 { ISD::CTTZ, MVT::v8i16, { 13, 20, 17, 23 } },
4835 { ISD::CTTZ, MVT::v16i8, { 11, 16, 13, 19 } }
4836 };
4837 static const CostKindTblEntry SSE2CostTbl[] = {
4838 { ISD::ABS, MVT::v2i64, { 3, 6, 5, 5 } },
4839 { ISD::ABS, MVT::v4i32, { 1, 4, 4, 4 } },
4840 { ISD::ABS, MVT::v8i16, { 1, 2, 3, 3 } },
4841 { ISD::ABS, MVT::v16i8, { 1, 2, 3, 3 } },
4842 { ISD::BITREVERSE, MVT::v2i64, { 16, 20, 32, 32 } },
4843 { ISD::BITREVERSE, MVT::v4i32, { 16, 20, 30, 30 } },
4844 { ISD::BITREVERSE, MVT::v8i16, { 16, 20, 25, 25 } },
4845 { ISD::BITREVERSE, MVT::v16i8, { 11, 12, 21, 21 } },
4846 { ISD::BSWAP, MVT::v2i64, { 5, 6, 11, 11 } },
4847 { ISD::BSWAP, MVT::v4i32, { 5, 5, 9, 9 } },
4848 { ISD::BSWAP, MVT::v8i16, { 5, 5, 4, 5 } },
4849 { ISD::CTLZ, MVT::v2i64, { 10, 45, 36, 38 } },
4850 { ISD::CTLZ, MVT::v4i32, { 10, 45, 38, 40 } },
4851 { ISD::CTLZ, MVT::v8i16, { 9, 38, 32, 34 } },
4852 { ISD::CTLZ, MVT::v16i8, { 8, 39, 29, 32 } },
4853 { ISD::CTPOP, MVT::v2i64, { 12, 26, 16, 18 } },
4854 { ISD::CTPOP, MVT::v4i32, { 15, 29, 21, 23 } },
4855 { ISD::CTPOP, MVT::v8i16, { 13, 25, 18, 20 } },
4856 { ISD::CTPOP, MVT::v16i8, { 10, 21, 14, 16 } },
4857 { ISD::CTTZ, MVT::v2i64, { 14, 28, 19, 21 } },
4858 { ISD::CTTZ, MVT::v4i32, { 18, 31, 24, 26 } },
4859 { ISD::CTTZ, MVT::v8i16, { 16, 27, 21, 23 } },
4860 { ISD::CTTZ, MVT::v16i8, { 13, 23, 17, 19 } },
4861 { ISD::MULHS, MVT::v4i32, { 5, 11, 15, 15 } },
4862 { ISD::MULHS, MVT::v8i16, { 1, 5, 1, 1 } },
4863 { ISD::MULHU, MVT::v4i32, { 3, 9, 7, 7 } },
4864 { ISD::MULHU, MVT::v8i16, { 1, 5, 1, 1 } },
4865 { ISD::SADDSAT, MVT::v2i64, { 12, 14, 24, 24 } },
4866 { ISD::SADDSAT, MVT::v4i32, { 6, 11, 11, 12 } },
4867 { ISD::SADDSAT, MVT::v8i16, { 1, 2, 1, 1 } },
4868 { ISD::SADDSAT, MVT::v16i8, { 1, 2, 1, 1 } },
4869 { ISD::SMAX, MVT::v2i64, { 4, 8, 15, 15 } },
4870 { ISD::SMAX, MVT::v4i32, { 2, 4, 5, 5 } },
4871 { ISD::SMAX, MVT::v8i16, { 1, 1, 1, 1 } },
4872 { ISD::SMAX, MVT::v16i8, { 2, 4, 5, 5 } },
4873 { ISD::SMIN, MVT::v2i64, { 4, 8, 15, 15 } },
4874 { ISD::SMIN, MVT::v4i32, { 2, 4, 5, 5 } },
4875 { ISD::SMIN, MVT::v8i16, { 1, 1, 1, 1 } },
4876 { ISD::SMIN, MVT::v16i8, { 2, 4, 5, 5 } },
4877 { ISD::SMULO, MVT::v2i64, { 30, 33, 13, 23 } },
4878 { ISD::SMULO, MVT::v4i32, { 20, 24, 23, 23 } },
4879 { ISD::SMULO, MVT::v8i16, { 5, 10, 8, 8 } },
4880 { ISD::SMULO, MVT::v16i8, { 13, 23, 24, 25 } },
4881 { ISD::SSUBSAT, MVT::v2i64, { 16, 19, 31, 31 } },
4882 { ISD::SSUBSAT, MVT::v4i32, { 6, 14, 12, 13 } },
4883 { ISD::SSUBSAT, MVT::v8i16, { 1, 2, 1, 1 } },
4884 { ISD::SSUBSAT, MVT::v16i8, { 1, 2, 1, 1 } },
4885 { ISD::UADDSAT, MVT::v2i64, { 7, 13, 14, 14 } },
4886 { ISD::UADDSAT, MVT::v4i32, { 4, 5, 7, 7 } },
4887 { ISD::UADDSAT, MVT::v8i16, { 1, 2, 1, 1 } },
4888 { ISD::UADDSAT, MVT::v16i8, { 1, 2, 1, 1 } },
4889 { ISD::UMAX, MVT::v2i64, { 4, 8, 15, 15 } },
4890 { ISD::UMAX, MVT::v4i32, { 2, 5, 8, 8 } },
4891 { ISD::UMAX, MVT::v8i16, { 1, 3, 3, 3 } },
4892 { ISD::UMAX, MVT::v16i8, { 1, 1, 1, 1 } },
4893 { ISD::UMIN, MVT::v2i64, { 4, 8, 15, 15 } },
4894 { ISD::UMIN, MVT::v4i32, { 2, 5, 8, 8 } },
4895 { ISD::UMIN, MVT::v8i16, { 1, 3, 3, 3 } },
4896 { ISD::UMIN, MVT::v16i8, { 1, 1, 1, 1 } },
4897 { ISD::UMULO, MVT::v2i64, { 30, 33, 15, 29 } },
4898 { ISD::UMULO, MVT::v4i32, { 19, 22, 14, 18 } },
4899 { ISD::UMULO, MVT::v8i16, { 4, 9, 7, 7 } },
4900 { ISD::UMULO, MVT::v16i8, { 13, 19, 20, 20 } },
4901 { ISD::USUBSAT, MVT::v2i64, { 7, 10, 14, 14 } },
4902 { ISD::USUBSAT, MVT::v4i32, { 4, 4, 7, 7 } },
4903 { ISD::USUBSAT, MVT::v8i16, { 1, 2, 1, 1 } },
4904 { ISD::USUBSAT, MVT::v16i8, { 1, 2, 1, 1 } },
4905 { ISD::FMAXNUM, MVT::f64, { 5, 5, 7, 7 } },
4906 { ISD::FMAXNUM, MVT::v2f64, { 4, 6, 6, 6 } },
4907 { ISD::FSQRT, MVT::f64, { 32, 32, 1, 1 } }, // Nehalem from http://www.agner.org/
4908 { ISD::FSQRT, MVT::v2f64, { 32, 32, 1, 1 } }, // Nehalem from http://www.agner.org/
4909 };
4910 static const CostKindTblEntry SSE1CostTbl[] = {
4911 { ISD::FMAXNUM, MVT::f32, { 5, 5, 7, 7 } },
4912 { ISD::FMAXNUM, MVT::v4f32, { 4, 6, 6, 6 } },
4913 { ISD::FSQRT, MVT::f32, { 28, 30, 1, 2 } }, // Pentium III from http://www.agner.org/
4914 { ISD::FSQRT, MVT::v4f32, { 56, 56, 1, 2 } }, // Pentium III from http://www.agner.org/
4915 };
4916 static const CostKindTblEntry BMI64CostTbl[] = { // 64-bit targets
4917 { ISD::CTTZ, MVT::i64, { 1, 1, 1, 1 } },
4918 };
4919 static const CostKindTblEntry BMI32CostTbl[] = { // 32 or 64-bit targets
4920 { ISD::CTTZ, MVT::i32, { 1, 1, 1, 1 } },
4921 { ISD::CTTZ, MVT::i16, { 2, 1, 1, 1 } },
4922 { ISD::CTTZ, MVT::i8, { 2, 1, 1, 1 } },
4923 };
4924 static const CostKindTblEntry LZCNT64CostTbl[] = { // 64-bit targets
4925 { ISD::CTLZ, MVT::i64, { 1, 1, 1, 1 } },
4926 };
4927 static const CostKindTblEntry LZCNT32CostTbl[] = { // 32 or 64-bit targets
4928 { ISD::CTLZ, MVT::i32, { 1, 1, 1, 1 } },
4929 { ISD::CTLZ, MVT::i16, { 2, 1, 1, 1 } },
4930 { ISD::CTLZ, MVT::i8, { 2, 1, 1, 1 } },
4931 };
4932 static const CostKindTblEntry POPCNT64CostTbl[] = { // 64-bit targets
4933 { ISD::CTPOP, MVT::i64, { 1, 1, 1, 1 } }, // popcnt
4934 };
4935 static const CostKindTblEntry POPCNT32CostTbl[] = { // 32 or 64-bit targets
4936 { ISD::CTPOP, MVT::i32, { 1, 1, 1, 1 } }, // popcnt
4937 { ISD::CTPOP, MVT::i16, { 1, 1, 2, 2 } }, // popcnt(zext())
4938 { ISD::CTPOP, MVT::i8, { 1, 1, 2, 2 } }, // popcnt(zext())
4939 };
4940 static const CostKindTblEntry PCLMULCostTbl[] = {
4941 { ISD::CLMUL, MVT::v2i64, { 3, 12, 4, 8 } }, // MOV+2xPCLMUL+unpack
4942 { ISD::CLMUL, MVT::v4i32, { 8, 18, 12, 16 } }, // MOV+4xPCLMUL+unpack
4943 { ISD::CLMUL, MVT::i64, { 3, 12, 4, 8 } }, // MOV+PCLMUL+MOV
4944 { ISD::CLMUL, MVT::i32, { 3, 12, 4, 8 } }, // MOV+PCLMUL+MOV
4945 { ISD::CLMUL, MVT::i16, { 3, 12, 4, 8 } }, // MOV+PCLMUL+MOV
4946 { ISD::CLMUL, MVT::i8, { 3, 12, 4, 8 } }, // MOV+PCLMUL+MOV
4947 };
4948 static const CostKindTblEntry X64CostTbl[] = { // 64-bit targets
4949 { ISD::ABS, MVT::i64, { 1, 2, 3, 3 } }, // SUB+CMOV
4950 { ISD::BITREVERSE, MVT::i64, { 10, 12, 20, 22 } },
4951 { ISD::BSWAP, MVT::i64, { 1, 2, 1, 2 } },
4952 { ISD::CTLZ, MVT::i64, { 1, 2, 3, 3 } }, // MOV+BSR+XOR
4953 { ISD::CTLZ, MVT::i32, { 1, 2, 3, 3 } }, // MOV+BSR+XOR
4954 { ISD::CTLZ, MVT::i16, { 2, 2, 3, 3 } }, // MOV+BSR+XOR
4955 { ISD::CTLZ, MVT::i8, { 2, 2, 4, 3 } }, // MOV+BSR+XOR
4956 { ISD::CTLZ_ZERO_POISON,MVT::i64,{ 1, 2, 2, 2 } }, // BSR+XOR
4957 { ISD::CTTZ, MVT::i64, { 1, 2, 2, 2 } }, // MOV+BSF
4958 { ISD::CTTZ, MVT::i32, { 1, 2, 2, 2 } }, // MOV+BSF
4959 { ISD::CTTZ, MVT::i16, { 2, 2, 2, 2 } }, // MOV+BSF
4960 { ISD::CTTZ, MVT::i8, { 2, 2, 2, 2 } }, // MOV+BSF
4961 { ISD::CTTZ_ZERO_POISON,MVT::i64,{ 1, 2, 1, 2 } }, // BSF
4962 { ISD::CTPOP, MVT::i64, { 10, 6, 19, 19 } },
4963 { ISD::ROTL, MVT::i64, { 2, 3, 1, 3 } },
4964 { ISD::ROTR, MVT::i64, { 2, 3, 1, 3 } },
4965 { X86ISD::VROTLI, MVT::i64, { 1, 1, 1, 1 } },
4966 { ISD::FSHL, MVT::i64, { 4, 4, 1, 4 } },
4967 { ISD::SADDSAT, MVT::i64, { 4, 4, 7, 10 } },
4968 { ISD::SSUBSAT, MVT::i64, { 4, 5, 8, 11 } },
4969 { ISD::UADDSAT, MVT::i64, { 2, 3, 4, 7 } },
4970 { ISD::USUBSAT, MVT::i64, { 2, 3, 4, 7 } },
4971 { ISD::SMAX, MVT::i64, { 1, 3, 2, 3 } },
4972 { ISD::SMIN, MVT::i64, { 1, 3, 2, 3 } },
4973 { ISD::UMAX, MVT::i64, { 1, 3, 2, 3 } },
4974 { ISD::UMIN, MVT::i64, { 1, 3, 2, 3 } },
4975 { ISD::SADDO, MVT::i64, { 2, 2, 4, 6 } },
4976 { ISD::UADDO, MVT::i64, { 2, 2, 4, 6 } },
4977 { ISD::SMULO, MVT::i64, { 4, 4, 4, 6 } },
4978 { ISD::UMULO, MVT::i64, { 8, 8, 4, 7 } },
4979 };
4980 static const CostKindTblEntry X86CostTbl[] = { // 32 or 64-bit targets
4981 { ISD::ABS, MVT::i32, { 1, 2, 3, 3 } }, // SUB+XOR+SRA or SUB+CMOV
4982 { ISD::ABS, MVT::i16, { 2, 2, 3, 3 } }, // SUB+XOR+SRA or SUB+CMOV
4983 { ISD::ABS, MVT::i8, { 2, 4, 4, 3 } }, // SUB+XOR+SRA
4984 { ISD::BITREVERSE, MVT::i32, { 9, 12, 17, 19 } },
4985 { ISD::BITREVERSE, MVT::i16, { 9, 12, 17, 19 } },
4986 { ISD::BITREVERSE, MVT::i8, { 7, 9, 13, 14 } },
4987 { ISD::BSWAP, MVT::i32, { 1, 1, 1, 1 } },
4988 { ISD::BSWAP, MVT::i16, { 1, 2, 1, 2 } }, // ROL
4989 { ISD::CTLZ, MVT::i32, { 2, 2, 4, 5 } }, // BSR+XOR or BSR+XOR+CMOV
4990 { ISD::CTLZ, MVT::i16, { 2, 2, 4, 5 } }, // BSR+XOR or BSR+XOR+CMOV
4991 { ISD::CTLZ, MVT::i8, { 2, 2, 5, 6 } }, // BSR+XOR or BSR+XOR+CMOV
4992 { ISD::CTLZ_ZERO_POISON,MVT::i32,{ 1, 2, 2, 2 } }, // BSR+XOR
4993 { ISD::CTLZ_ZERO_POISON,MVT::i16,{ 2, 2, 2, 2 } }, // BSR+XOR
4994 { ISD::CTLZ_ZERO_POISON,MVT::i8, { 2, 2, 3, 3 } }, // BSR+XOR
4995 { ISD::CTTZ, MVT::i32, { 2, 2, 3, 3 } }, // TEST+BSF+CMOV/BRANCH
4996 { ISD::CTTZ, MVT::i16, { 2, 2, 2, 3 } }, // TEST+BSF+CMOV/BRANCH
4997 { ISD::CTTZ, MVT::i8, { 2, 2, 2, 3 } }, // TEST+BSF+CMOV/BRANCH
4998 { ISD::CTTZ_ZERO_POISON,MVT::i32,{ 1, 2, 1, 2 } }, // BSF
4999 { ISD::CTTZ_ZERO_POISON,MVT::i16,{ 2, 2, 1, 2 } }, // BSF
5000 { ISD::CTTZ_ZERO_POISON,MVT::i8, { 2, 2, 1, 2 } }, // BSF
5001 { ISD::CTPOP, MVT::i32, { 8, 7, 15, 15 } },
5002 { ISD::CTPOP, MVT::i16, { 9, 8, 17, 17 } },
5003 { ISD::CTPOP, MVT::i8, { 7, 6, 6, 6 } },
5004 { ISD::ROTL, MVT::i32, { 2, 3, 1, 3 } },
5005 { ISD::ROTL, MVT::i16, { 2, 3, 1, 3 } },
5006 { ISD::ROTL, MVT::i8, { 2, 3, 1, 3 } },
5007 { ISD::ROTR, MVT::i32, { 2, 3, 1, 3 } },
5008 { ISD::ROTR, MVT::i16, { 2, 3, 1, 3 } },
5009 { ISD::ROTR, MVT::i8, { 2, 3, 1, 3 } },
5010 { X86ISD::VROTLI, MVT::i32, { 1, 1, 1, 1 } },
5011 { X86ISD::VROTLI, MVT::i16, { 1, 1, 1, 1 } },
5012 { X86ISD::VROTLI, MVT::i8, { 1, 1, 1, 1 } },
5013 { ISD::FSHL, MVT::i32, { 4, 4, 1, 4 } },
5014 { ISD::FSHL, MVT::i16, { 4, 4, 2, 5 } },
5015 { ISD::FSHL, MVT::i8, { 4, 4, 2, 5 } },
5016 { ISD::SADDSAT, MVT::i32, { 3, 4, 6, 9 } },
5017 { ISD::SADDSAT, MVT::i16, { 4, 4, 7, 10 } },
5018 { ISD::SADDSAT, MVT::i8, { 4, 5, 8, 11 } },
5019 { ISD::SSUBSAT, MVT::i32, { 4, 4, 7, 10 } },
5020 { ISD::SSUBSAT, MVT::i16, { 4, 4, 7, 10 } },
5021 { ISD::SSUBSAT, MVT::i8, { 4, 5, 8, 11 } },
5022 { ISD::UADDSAT, MVT::i32, { 2, 3, 4, 7 } },
5023 { ISD::UADDSAT, MVT::i16, { 2, 3, 4, 7 } },
5024 { ISD::UADDSAT, MVT::i8, { 3, 3, 5, 8 } },
5025 { ISD::USUBSAT, MVT::i32, { 2, 3, 4, 7 } },
5026 { ISD::USUBSAT, MVT::i16, { 2, 3, 4, 7 } },
5027 { ISD::USUBSAT, MVT::i8, { 3, 3, 5, 8 } },
5028 { ISD::SMAX, MVT::i32, { 1, 2, 2, 3 } },
5029 { ISD::SMAX, MVT::i16, { 1, 4, 2, 4 } },
5030 { ISD::SMAX, MVT::i8, { 1, 4, 2, 4 } },
5031 { ISD::SMIN, MVT::i32, { 1, 2, 2, 3 } },
5032 { ISD::SMIN, MVT::i16, { 1, 4, 2, 4 } },
5033 { ISD::SMIN, MVT::i8, { 1, 4, 2, 4 } },
5034 { ISD::UMAX, MVT::i32, { 1, 2, 2, 3 } },
5035 { ISD::UMAX, MVT::i16, { 1, 4, 2, 4 } },
5036 { ISD::UMAX, MVT::i8, { 1, 4, 2, 4 } },
5037 { ISD::UMIN, MVT::i32, { 1, 2, 2, 3 } },
5038 { ISD::UMIN, MVT::i16, { 1, 4, 2, 4 } },
5039 { ISD::UMIN, MVT::i8, { 1, 4, 2, 4 } },
5040 { ISD::SADDO, MVT::i32, { 2, 2, 4, 6 } },
5041 { ISD::SADDO, MVT::i16, { 2, 2, 4, 6 } },
5042 { ISD::SADDO, MVT::i8, { 2, 2, 4, 6 } },
5043 { ISD::UADDO, MVT::i32, { 2, 2, 4, 6 } },
5044 { ISD::UADDO, MVT::i16, { 2, 2, 4, 6 } },
5045 { ISD::UADDO, MVT::i8, { 2, 2, 4, 6 } },
5046 { ISD::SMULO, MVT::i32, { 2, 2, 4, 6 } },
5047 { ISD::SMULO, MVT::i16, { 5, 5, 4, 6 } },
5048 { ISD::SMULO, MVT::i8, { 6, 6, 4, 6 } },
5049 { ISD::UMULO, MVT::i32, { 6, 6, 4, 8 } },
5050 { ISD::UMULO, MVT::i16, { 6, 6, 4, 9 } },
5051 { ISD::UMULO, MVT::i8, { 6, 6, 4, 6 } },
5052 };
5053
5054 Type *RetTy = ICA.getReturnType();
5055 Type *OpTy = RetTy;
5056 Intrinsic::ID IID = ICA.getID();
5057 unsigned ISD = ISD::DELETED_NODE;
5058 switch (IID) {
5059 default:
5060 break;
5061 case Intrinsic::abs:
5062 ISD = ISD::ABS;
5063 break;
5064 case Intrinsic::bitreverse:
5066 break;
5067 case Intrinsic::bswap:
5068 ISD = ISD::BSWAP;
5069 break;
5070 case Intrinsic::ctlz:
5071 ISD = ISD::CTLZ;
5072 break;
5073 case Intrinsic::ctpop:
5074 ISD = ISD::CTPOP;
5075 break;
5076 case Intrinsic::cttz:
5077 ISD = ISD::CTTZ;
5078 break;
5079 case Intrinsic::fshl:
5080 ISD = ISD::FSHL;
5081 if (!ICA.isTypeBasedOnly()) {
5082 const SmallVectorImpl<const Value *> &Args = ICA.getArgs();
5083 if (Args[0] == Args[1]) {
5084 ISD = ISD::ROTL;
5085 // Handle uniform constant rotation amounts.
5086 // TODO: Handle funnel-shift cases.
5087 const APInt *Amt;
5088 if (Args[2] &&
5090 ISD = X86ISD::VROTLI;
5091 }
5092 }
5093 break;
5094 case Intrinsic::fshr:
5095 // FSHR has same costs so don't duplicate.
5096 ISD = ISD::FSHL;
5097 if (!ICA.isTypeBasedOnly()) {
5098 const SmallVectorImpl<const Value *> &Args = ICA.getArgs();
5099 if (Args[0] == Args[1]) {
5100 ISD = ISD::ROTR;
5101 // Handle uniform constant rotation amount.
5102 // TODO: Handle funnel-shift cases.
5103 const APInt *Amt;
5104 if (Args[2] &&
5106 ISD = X86ISD::VROTLI;
5107 }
5108 }
5109 break;
5110 case Intrinsic::lrint:
5111 case Intrinsic::llrint: {
5112 // X86 can use the CVTP2SI instructions to lower lrint/llrint calls, which
5113 // have the same costs as the CVTTP2SI (fptosi) instructions
5114 const SmallVectorImpl<Type *> &ArgTys = ICA.getArgTypes();
5115 return getCastInstrCost(Instruction::FPToSI, RetTy, ArgTys[0],
5117 }
5118 case Intrinsic::maxnum:
5119 case Intrinsic::minnum:
5120 // FMINNUM has same costs so don't duplicate.
5121 ISD = ISD::FMAXNUM;
5122 break;
5123 case Intrinsic::sadd_sat:
5124 ISD = ISD::SADDSAT;
5125 break;
5126 case Intrinsic::smax:
5127 ISD = ISD::SMAX;
5128 break;
5129 case Intrinsic::smin:
5130 ISD = ISD::SMIN;
5131 break;
5132 case Intrinsic::smulh:
5133 ISD = ISD::MULHS;
5134 break;
5135 case Intrinsic::ssub_sat:
5136 ISD = ISD::SSUBSAT;
5137 break;
5138 case Intrinsic::uadd_sat:
5139 ISD = ISD::UADDSAT;
5140 break;
5141 case Intrinsic::umax:
5142 ISD = ISD::UMAX;
5143 break;
5144 case Intrinsic::umin:
5145 ISD = ISD::UMIN;
5146 break;
5147 case Intrinsic::usub_sat:
5148 ISD = ISD::USUBSAT;
5149 break;
5150 case Intrinsic::umulh:
5151 ISD = ISD::MULHU;
5152 break;
5153 case Intrinsic::sqrt:
5154 ISD = ISD::FSQRT;
5155 break;
5156 case Intrinsic::sadd_with_overflow:
5157 case Intrinsic::ssub_with_overflow:
5158 // SSUBO has same costs so don't duplicate.
5159 ISD = ISD::SADDO;
5160 OpTy = RetTy->getContainedType(0);
5161 break;
5162 case Intrinsic::uadd_with_overflow:
5163 case Intrinsic::usub_with_overflow:
5164 // USUBO has same costs so don't duplicate.
5165 ISD = ISD::UADDO;
5166 OpTy = RetTy->getContainedType(0);
5167 break;
5168 case Intrinsic::smul_with_overflow:
5169 ISD = ISD::SMULO;
5170 OpTy = RetTy->getContainedType(0);
5171 break;
5172 case Intrinsic::umul_with_overflow:
5173 ISD = ISD::UMULO;
5174 OpTy = RetTy->getContainedType(0);
5175 break;
5176 case Intrinsic::clmul:
5177 ISD = ISD::CLMUL;
5178 break;
5179 }
5180
5181 if (ISD != ISD::DELETED_NODE) {
5182 auto adjustTableCost = [&](int ISD, unsigned Cost,
5183 std::pair<InstructionCost, MVT> LT,
5185 InstructionCost LegalizationCost = LT.first;
5186 MVT MTy = LT.second;
5187
5188 // If there are no NANs to deal with, then these are reduced to a
5189 // single MIN** or MAX** instruction instead of the MIN/CMP/SELECT that we
5190 // assume is used in the non-fast case.
5191 if (ISD == ISD::FMAXNUM || ISD == ISD::FMINNUM) {
5192 if (FMF.noNaNs())
5193 return LegalizationCost * 1;
5194 }
5195
5196 // For cases where some ops can be folded into a load/store, assume free.
5197 if (MTy.isScalarInteger()) {
5198 if (ISD == ISD::BSWAP && ST->hasMOVBE() && ST->hasFastMOVBE()) {
5199 if (const Instruction *II = ICA.getInst()) {
5200 if (II->hasOneUse() && isa<StoreInst>(II->user_back()))
5201 return TTI::TCC_Free;
5202 if (auto *LI = dyn_cast<LoadInst>(II->getOperand(0))) {
5203 if (LI->hasOneUse())
5204 return TTI::TCC_Free;
5205 }
5206 }
5207 }
5208 }
5209
5210 return LegalizationCost * (int)Cost;
5211 };
5212
5213 // Legalize the type.
5214 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(OpTy);
5215 MVT MTy = LT.second;
5216
5217 // Without BMI/LZCNT see if we're only looking for a *_ZERO_POISON cost.
5218 if (((ISD == ISD::CTTZ && !ST->hasBMI()) ||
5219 (ISD == ISD::CTLZ && !ST->hasLZCNT())) &&
5220 !MTy.isVector() && !ICA.isTypeBasedOnly()) {
5221 const SmallVectorImpl<const Value *> &Args = ICA.getArgs();
5222 if (auto *Cst = dyn_cast<ConstantInt>(Args[1]))
5223 if (Cst->isAllOnesValue())
5224 ISD =
5226 }
5227
5228 // FSQRT is a single instruction.
5230 return LT.first;
5231
5232 if (ST->useGLMDivSqrtCosts())
5233 if (const auto *Entry = CostTableLookup(GLMCostTbl, ISD, MTy))
5234 if (auto KindCost = Entry->Cost[CostKind])
5235 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5236
5237 if (ST->useSLMArithCosts())
5238 if (const auto *Entry = CostTableLookup(SLMCostTbl, ISD, MTy))
5239 if (auto KindCost = Entry->Cost[CostKind])
5240 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5241
5242 if (ST->hasVBMI2())
5243 if (const auto *Entry = CostTableLookup(AVX512VBMI2CostTbl, ISD, MTy))
5244 if (auto KindCost = Entry->Cost[CostKind])
5245 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5246
5247 if (ST->hasBITALG())
5248 if (const auto *Entry = CostTableLookup(AVX512BITALGCostTbl, ISD, MTy))
5249 if (auto KindCost = Entry->Cost[CostKind])
5250 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5251
5252 if (ST->hasVPOPCNTDQ())
5253 if (const auto *Entry = CostTableLookup(AVX512VPOPCNTDQCostTbl, ISD, MTy))
5254 if (auto KindCost = Entry->Cost[CostKind])
5255 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5256
5257 if (ST->hasGFNI())
5258 if (const auto *Entry = CostTableLookup(GFNICostTbl, ISD, MTy))
5259 if (auto KindCost = Entry->Cost[CostKind])
5260 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5261
5262 if (ST->hasCDI())
5263 if (const auto *Entry = CostTableLookup(AVX512CDCostTbl, ISD, MTy))
5264 if (auto KindCost = Entry->Cost[CostKind])
5265 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5266
5267 if (ST->hasBWI())
5268 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
5269 if (auto KindCost = Entry->Cost[CostKind])
5270 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5271
5272 if (ST->hasAVX512())
5273 if (const auto *Entry = CostTableLookup(AVX512CostTbl, ISD, MTy))
5274 if (auto KindCost = Entry->Cost[CostKind])
5275 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5276
5277 if (ST->hasXOP())
5278 if (const auto *Entry = CostTableLookup(XOPCostTbl, ISD, MTy))
5279 if (auto KindCost = Entry->Cost[CostKind])
5280 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5281
5282 if (ST->hasAVX2())
5283 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
5284 if (auto KindCost = Entry->Cost[CostKind])
5285 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5286
5287 if (ST->hasAVX())
5288 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
5289 if (auto KindCost = Entry->Cost[CostKind])
5290 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5291
5292 if (ST->hasSSE42())
5293 if (const auto *Entry = CostTableLookup(SSE42CostTbl, ISD, MTy))
5294 if (auto KindCost = Entry->Cost[CostKind])
5295 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5296
5297 if (ST->hasSSE41())
5298 if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
5299 if (auto KindCost = Entry->Cost[CostKind])
5300 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5301
5302 if (ST->hasSSSE3())
5303 if (const auto *Entry = CostTableLookup(SSSE3CostTbl, ISD, MTy))
5304 if (auto KindCost = Entry->Cost[CostKind])
5305 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5306
5307 if (ST->hasSSE2())
5308 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
5309 if (auto KindCost = Entry->Cost[CostKind])
5310 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5311
5312 if (ST->hasSSE1())
5313 if (const auto *Entry = CostTableLookup(SSE1CostTbl, ISD, MTy))
5314 if (auto KindCost = Entry->Cost[CostKind])
5315 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5316
5317 if (ST->hasBMI()) {
5318 if (ST->is64Bit())
5319 if (const auto *Entry = CostTableLookup(BMI64CostTbl, ISD, MTy))
5320 if (auto KindCost = Entry->Cost[CostKind])
5321 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5322
5323 if (const auto *Entry = CostTableLookup(BMI32CostTbl, ISD, MTy))
5324 if (auto KindCost = Entry->Cost[CostKind])
5325 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5326 }
5327
5328 if (ST->hasLZCNT()) {
5329 if (ST->is64Bit())
5330 if (const auto *Entry = CostTableLookup(LZCNT64CostTbl, ISD, MTy))
5331 if (auto KindCost = Entry->Cost[CostKind])
5332 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5333
5334 if (const auto *Entry = CostTableLookup(LZCNT32CostTbl, ISD, MTy))
5335 if (auto KindCost = Entry->Cost[CostKind])
5336 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5337 }
5338
5339 if (ST->hasPOPCNT()) {
5340 if (ST->is64Bit())
5341 if (const auto *Entry = CostTableLookup(POPCNT64CostTbl, ISD, MTy))
5342 if (auto KindCost = Entry->Cost[CostKind])
5343 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5344
5345 if (const auto *Entry = CostTableLookup(POPCNT32CostTbl, ISD, MTy))
5346 if (auto KindCost = Entry->Cost[CostKind])
5347 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5348 }
5349
5350 // FIXME: PCLMUL w/ AVX/AVX512 and VPCLMULQDQ are not handled properly.
5351 if (ST->hasPCLMUL())
5352 if (const auto *Entry = CostTableLookup(PCLMULCostTbl, ISD, MTy))
5353 if (auto KindCost = Entry->Cost[CostKind])
5354 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5355
5356 if (ST->is64Bit())
5357 if (const auto *Entry = CostTableLookup(X64CostTbl, ISD, MTy))
5358 if (auto KindCost = Entry->Cost[CostKind])
5359 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5360
5361 if (const auto *Entry = CostTableLookup(X86CostTbl, ISD, MTy))
5362 if (auto KindCost = Entry->Cost[CostKind])
5363 return adjustTableCost(Entry->ISD, *KindCost, LT, ICA.getFlags());
5364
5365 // Without arg data, we need to compute the expanded costs of custom lowered
5366 // intrinsics to prevent use of the (very low) default costs.
5367 if (ICA.isTypeBasedOnly() &&
5368 (IID == Intrinsic::fshl || IID == Intrinsic::fshr)) {
5369 Type *CondTy = RetTy->getWithNewBitWidth(1);
5371 Cost += getArithmeticInstrCost(BinaryOperator::Or, RetTy, CostKind);
5372 Cost += getArithmeticInstrCost(BinaryOperator::Sub, RetTy, CostKind);
5373 Cost += getArithmeticInstrCost(BinaryOperator::Shl, RetTy, CostKind);
5374 Cost += getArithmeticInstrCost(BinaryOperator::LShr, RetTy, CostKind);
5375 Cost += getArithmeticInstrCost(BinaryOperator::And, RetTy, CostKind);
5376 Cost += getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy,
5378 Cost += getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy,
5380 return Cost;
5381 }
5382 }
5383
5385}
5386
5388 unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,
5389 const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC) const {
5390 static const CostTblEntry SLMCostTbl[] = {
5391 { ISD::EXTRACT_VECTOR_ELT, MVT::i8, 4 },
5392 { ISD::EXTRACT_VECTOR_ELT, MVT::i16, 4 },
5393 { ISD::EXTRACT_VECTOR_ELT, MVT::i32, 4 },
5394 { ISD::EXTRACT_VECTOR_ELT, MVT::i64, 7 }
5395 };
5396
5397 assert(Val->isVectorTy() && "This must be a vector type");
5398 auto *VT = cast<VectorType>(Val);
5399 if (VT->isScalableTy())
5401
5402 Type *ScalarType = Val->getScalarType();
5403 InstructionCost RegisterFileMoveCost = 0;
5404
5405 // Non-immediate extraction/insertion can be handled as a sequence of
5406 // aliased loads+stores via the stack.
5407 if (Index == -1U && (Opcode == Instruction::ExtractElement ||
5408 Opcode == Instruction::InsertElement)) {
5409 // TODO: On some SSE41+ targets, we expand to cmp+splat+select patterns:
5410 // inselt N0, N1, N2 --> select (SplatN2 == {0,1,2...}) ? SplatN1 : N0.
5411
5412 // TODO: Move this to BasicTTIImpl.h? We'd need better gep + index handling.
5413 assert(isa<FixedVectorType>(Val) && "Fixed vector type expected");
5414 Align VecAlign = DL.getPrefTypeAlign(Val);
5415 Align SclAlign = DL.getPrefTypeAlign(ScalarType);
5416
5417 // Extract - store vector to stack, load scalar.
5418 if (Opcode == Instruction::ExtractElement) {
5419 return getMemoryOpCost(Instruction::Store, Val, VecAlign, 0, CostKind) +
5420 getMemoryOpCost(Instruction::Load, ScalarType, SclAlign, 0,
5421 CostKind);
5422 }
5423 // Insert - store vector to stack, store scalar, load vector.
5424 if (Opcode == Instruction::InsertElement) {
5425 return getMemoryOpCost(Instruction::Store, Val, VecAlign, 0, CostKind) +
5426 getMemoryOpCost(Instruction::Store, ScalarType, SclAlign, 0,
5427 CostKind) +
5428 getMemoryOpCost(Instruction::Load, Val, VecAlign, 0, CostKind);
5429 }
5430 }
5431
5432 if (Index != -1U && (Opcode == Instruction::ExtractElement ||
5433 Opcode == Instruction::InsertElement)) {
5434 // Extraction of vXi1 elements are now efficiently handled by MOVMSK.
5435 if (Opcode == Instruction::ExtractElement &&
5436 ScalarType->getScalarSizeInBits() == 1 &&
5437 cast<FixedVectorType>(Val)->getNumElements() > 1)
5438 return 1;
5439
5440 // Legalize the type.
5441 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Val);
5442
5443 // This type is legalized to a scalar type.
5444 if (!LT.second.isVector())
5445 return TTI::TCC_Free;
5446
5447 // The type may be split. Normalize the index to the new type.
5448 unsigned SizeInBits = LT.second.getSizeInBits();
5449 unsigned NumElts = LT.second.getVectorNumElements();
5450 unsigned SubNumElts = NumElts;
5451 Index = Index % NumElts;
5452
5453 // For >128-bit vectors, we need to extract higher 128-bit subvectors.
5454 // For inserts, we also need to insert the subvector back.
5455 if (SizeInBits > 128) {
5456 assert((SizeInBits % 128) == 0 && "Illegal vector");
5457 unsigned NumSubVecs = SizeInBits / 128;
5458 SubNumElts = NumElts / NumSubVecs;
5459 if (SubNumElts <= Index) {
5460 RegisterFileMoveCost += (Opcode == Instruction::InsertElement ? 2 : 1);
5461 Index %= SubNumElts;
5462 }
5463 }
5464
5465 MVT MScalarTy = LT.second.getScalarType();
5466 auto IsCheapPInsrPExtrInsertPS = [&]() {
5467 // Assume pinsr/pextr XMM <-> GPR is relatively cheap on all targets.
5468 // Inserting f32 into index0 is just movss.
5469 // Also, assume insertps is relatively cheap on all >= SSE41 targets.
5470 return (MScalarTy == MVT::i16 && ST->hasSSE2()) ||
5471 (MScalarTy.isInteger() && ST->hasSSE41()) ||
5472 (MScalarTy == MVT::f32 && ST->hasSSE1() && Index == 0 &&
5473 Opcode == Instruction::InsertElement) ||
5474 (MScalarTy == MVT::f32 && ST->hasSSE41() &&
5475 Opcode == Instruction::InsertElement);
5476 };
5477
5478 if (Index == 0) {
5479 // Floating point scalars are already located in index #0.
5480 // Many insertions to #0 can fold away for scalar fp-ops, so let's assume
5481 // true for all.
5482 if (ScalarType->isFloatingPointTy() &&
5483 (Opcode != Instruction::InsertElement || !Op0 ||
5484 isa<UndefValue>(Op0)))
5485 return RegisterFileMoveCost;
5486
5487 if (Opcode == Instruction::InsertElement &&
5489 // Consider the gather cost to be cheap.
5491 return RegisterFileMoveCost;
5492 if (!IsCheapPInsrPExtrInsertPS()) {
5493 // mov constant-to-GPR + movd/movq GPR -> XMM.
5494 if (isa_and_nonnull<Constant>(Op1) && Op1->getType()->isIntegerTy())
5495 return 2 + RegisterFileMoveCost;
5496 // Assume movd/movq GPR -> XMM is relatively cheap on all targets.
5497 return 1 + RegisterFileMoveCost;
5498 }
5499 }
5500
5501 // Assume movd/movq XMM -> GPR is relatively cheap on all targets.
5502 if (ScalarType->isIntegerTy() && Opcode == Instruction::ExtractElement)
5503 return 1 + RegisterFileMoveCost;
5504 }
5505
5506 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5507 assert(ISD && "Unexpected vector opcode");
5508 if (ST->useSLMArithCosts())
5509 if (auto *Entry = CostTableLookup(SLMCostTbl, ISD, MScalarTy))
5510 return Entry->Cost + RegisterFileMoveCost;
5511
5512 // Consider cheap cases.
5513 if (IsCheapPInsrPExtrInsertPS())
5514 return 1 + RegisterFileMoveCost;
5515
5516 // For extractions we just need to shuffle the element to index 0, which
5517 // should be very cheap (assume cost = 1). For insertions we need to shuffle
5518 // the elements to its destination. In both cases we must handle the
5519 // subvector move(s).
5520 // If the vector type is already less than 128-bits then don't reduce it.
5521 // TODO: Under what circumstances should we shuffle using the full width?
5522 InstructionCost ShuffleCost = 1;
5523 if (Opcode == Instruction::InsertElement) {
5524 auto *SubTy = cast<VectorType>(Val);
5525 EVT VT = TLI->getValueType(DL, Val);
5526 if (VT.getScalarType() != MScalarTy || VT.getSizeInBits() >= 128)
5527 SubTy = FixedVectorType::get(ScalarType, SubNumElts);
5528 ShuffleCost = getShuffleCost(TTI::SK_PermuteTwoSrc, SubTy, SubTy,
5529 CostKind, {}, 0, SubTy);
5530 }
5531 int IntOrFpCost = ScalarType->isFloatingPointTy() ? 0 : 1;
5532 return ShuffleCost + IntOrFpCost + RegisterFileMoveCost;
5533 }
5534
5535 return BaseT::getVectorInstrCost(Opcode, Val, CostKind, Index, Op0, Op1,
5536 VIC) +
5537 RegisterFileMoveCost;
5538}
5539
5541 VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract,
5542 TTI::TargetCostKind CostKind, bool ForPoisonSrc, ArrayRef<Value *> VL,
5543 TTI::VectorInstrContext VIC) const {
5544 assert(DemandedElts.getBitWidth() ==
5545 cast<FixedVectorType>(Ty)->getNumElements() &&
5546 "Vector size mismatch");
5547
5548 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
5549 MVT MScalarTy = LT.second.getScalarType();
5550 unsigned LegalVectorBitWidth = LT.second.getSizeInBits();
5552
5553 constexpr unsigned LaneBitWidth = 128;
5554 assert((LegalVectorBitWidth < LaneBitWidth ||
5555 (LegalVectorBitWidth % LaneBitWidth) == 0) &&
5556 "Illegal vector");
5557
5558 const int NumLegalVectors = LT.first.getValue();
5559 assert(NumLegalVectors >= 0 && "Negative cost!");
5560
5561 // For insertions, a ISD::BUILD_VECTOR style vector initialization can be much
5562 // cheaper than an accumulation of ISD::INSERT_VECTOR_ELT. SLPVectorizer has
5563 // a special heuristic regarding poison input which is passed here in
5564 // ForPoisonSrc.
5565 if (Insert && !ForPoisonSrc) {
5566 // This is nearly identical to BaseT::getScalarizationOverhead(), except
5567 // it is passing nullptr to getVectorInstrCost() for Op0 (instead of
5568 // Constant::getNullValue()), which makes the X86TTIImpl
5569 // getVectorInstrCost() return 0 instead of 1.
5570 for (unsigned I : seq(DemandedElts.getBitWidth())) {
5571 if (!DemandedElts[I])
5572 continue;
5573 Cost += getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, I,
5575 VL.empty() ? nullptr : VL[I],
5577 }
5578 return Cost;
5579 }
5580
5581 if (Insert) {
5582 if ((MScalarTy == MVT::i16 && ST->hasSSE2()) ||
5583 (MScalarTy.isInteger() && ST->hasSSE41()) ||
5584 (MScalarTy == MVT::f32 && ST->hasSSE41())) {
5585 // For types we can insert directly, insertion into 128-bit sub vectors is
5586 // cheap, followed by a cheap chain of concatenations.
5587 if (LegalVectorBitWidth <= LaneBitWidth) {
5588 Cost += BaseT::getScalarizationOverhead(Ty, DemandedElts, Insert,
5589 /*Extract*/ false, CostKind);
5590 } else {
5591 // In each 128-lane, if at least one index is demanded but not all
5592 // indices are demanded and this 128-lane is not the first 128-lane of
5593 // the legalized-vector, then this 128-lane needs a extracti128; If in
5594 // each 128-lane, there is at least one demanded index, this 128-lane
5595 // needs a inserti128.
5596
5597 // The following cases will help you build a better understanding:
5598 // Assume we insert several elements into a v8i32 vector in avx2,
5599 // Case#1: inserting into 1th index needs vpinsrd + inserti128.
5600 // Case#2: inserting into 5th index needs extracti128 + vpinsrd +
5601 // inserti128.
5602 // Case#3: inserting into 4,5,6,7 index needs 4*vpinsrd + inserti128.
5603 assert((LegalVectorBitWidth % LaneBitWidth) == 0 && "Illegal vector");
5604 unsigned NumLegalLanes = LegalVectorBitWidth / LaneBitWidth;
5605 unsigned NumLanesTotal = NumLegalLanes * NumLegalVectors;
5606 unsigned NumLegalElts =
5607 LT.second.getVectorNumElements() * NumLegalVectors;
5608 assert(NumLegalElts >= DemandedElts.getBitWidth() &&
5609 "Vector has been legalized to smaller element count");
5610 assert((NumLegalElts % NumLanesTotal) == 0 &&
5611 "Unexpected elts per lane");
5612 unsigned NumEltsPerLane = NumLegalElts / NumLanesTotal;
5613
5614 APInt WidenedDemandedElts = DemandedElts.zext(NumLegalElts);
5615 auto *LaneTy =
5616 FixedVectorType::get(Ty->getElementType(), NumEltsPerLane);
5617
5618 for (unsigned I = 0; I != NumLanesTotal; ++I) {
5619 APInt LaneEltMask = WidenedDemandedElts.extractBits(
5620 NumEltsPerLane, NumEltsPerLane * I);
5621 if (LaneEltMask.isZero())
5622 continue;
5623 // FIXME: we don't need to extract if all non-demanded elements
5624 // are legalization-inserted padding.
5625 if (!LaneEltMask.isAllOnes())
5627 {}, I * NumEltsPerLane, LaneTy);
5628 Cost += BaseT::getScalarizationOverhead(LaneTy, LaneEltMask, Insert,
5629 /*Extract*/ false, CostKind);
5630 }
5631
5632 APInt AffectedLanes =
5633 APIntOps::ScaleBitMask(WidenedDemandedElts, NumLanesTotal);
5634 APInt FullyAffectedLegalVectors = APIntOps::ScaleBitMask(
5635 AffectedLanes, NumLegalVectors, /*MatchAllBits=*/true);
5636 for (int LegalVec = 0; LegalVec != NumLegalVectors; ++LegalVec) {
5637 for (unsigned Lane = 0; Lane != NumLegalLanes; ++Lane) {
5638 unsigned I = NumLegalLanes * LegalVec + Lane;
5639 // No need to insert unaffected lane; or lane 0 of each legal vector
5640 // iff ALL lanes of that vector were affected and will be inserted.
5641 if (!AffectedLanes[I] ||
5642 (Lane == 0 && FullyAffectedLegalVectors[LegalVec]))
5643 continue;
5645 {}, I * NumEltsPerLane, LaneTy);
5646 }
5647 }
5648 }
5649 } else if (LT.second.isVector()) {
5650 // Without fast insertion, we need to use MOVD/MOVQ to pass each demanded
5651 // integer element as a SCALAR_TO_VECTOR, then we build the vector as a
5652 // series of UNPCK followed by CONCAT_VECTORS - all of these can be
5653 // considered cheap.
5654 if (Ty->isIntOrIntVectorTy())
5655 Cost += DemandedElts.popcount();
5656
5657 // Get the smaller of the legalized or original pow2-extended number of
5658 // vector elements, which represents the number of unpacks we'll end up
5659 // performing.
5660 unsigned NumElts = LT.second.getVectorNumElements();
5661 unsigned Pow2Elts =
5662 PowerOf2Ceil(cast<FixedVectorType>(Ty)->getNumElements());
5663 Cost += (std::min<unsigned>(NumElts, Pow2Elts) - 1) * LT.first;
5664 }
5665 }
5666
5667 if (Extract) {
5668 // vXi1 can be efficiently extracted with MOVMSK.
5669 // TODO: AVX512 predicate mask handling.
5670 // NOTE: This doesn't work well for roundtrip scalarization.
5671 if (!Insert && Ty->getScalarSizeInBits() == 1 && !ST->hasAVX512()) {
5672 unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
5673 unsigned MaxElts = ST->hasAVX2() ? 32 : 16;
5674 unsigned MOVMSKCost = (NumElts + MaxElts - 1) / MaxElts;
5675 return MOVMSKCost;
5676 }
5677
5678 if (LT.second.isVector()) {
5679 unsigned NumLegalElts =
5680 LT.second.getVectorNumElements() * NumLegalVectors;
5681 assert(NumLegalElts >= DemandedElts.getBitWidth() &&
5682 "Vector has been legalized to smaller element count");
5683
5684 // If we're extracting elements from a 128-bit subvector lane,
5685 // we only need to extract each lane once, not for every element.
5686 if (LegalVectorBitWidth > LaneBitWidth) {
5687 unsigned NumLegalLanes = LegalVectorBitWidth / LaneBitWidth;
5688 unsigned NumLanesTotal = NumLegalLanes * NumLegalVectors;
5689 assert((NumLegalElts % NumLanesTotal) == 0 &&
5690 "Unexpected elts per lane");
5691 unsigned NumEltsPerLane = NumLegalElts / NumLanesTotal;
5692
5693 // Add cost for each demanded 128-bit subvector extraction.
5694 // Luckily this is a lot easier than for insertion.
5695 APInt WidenedDemandedElts = DemandedElts.zext(NumLegalElts);
5696 auto *LaneTy =
5697 FixedVectorType::get(Ty->getElementType(), NumEltsPerLane);
5698
5699 for (unsigned I = 0; I != NumLanesTotal; ++I) {
5700 APInt LaneEltMask = WidenedDemandedElts.extractBits(
5701 NumEltsPerLane, I * NumEltsPerLane);
5702 if (LaneEltMask.isZero())
5703 continue;
5705 I * NumEltsPerLane, LaneTy);
5707 LaneTy, LaneEltMask, /*Insert*/ false, Extract, CostKind);
5708 }
5709
5710 return Cost;
5711 }
5712 }
5713
5714 // Fallback to default extraction.
5715 Cost += BaseT::getScalarizationOverhead(Ty, DemandedElts, /*Insert*/ false,
5716 Extract, CostKind);
5717 }
5718
5719 return Cost;
5720}
5721
5723X86TTIImpl::getReplicationShuffleCost(Type *EltTy, int ReplicationFactor,
5724 int VF, const APInt &DemandedDstElts,
5726 const unsigned EltTyBits = DL.getTypeSizeInBits(EltTy);
5727 // We don't differentiate element types here, only element bit width.
5728 EltTy = IntegerType::getIntNTy(EltTy->getContext(), EltTyBits);
5729
5730 auto bailout = [&]() {
5731 return BaseT::getReplicationShuffleCost(EltTy, ReplicationFactor, VF,
5732 DemandedDstElts, CostKind);
5733 };
5734
5735 // For now, only deal with AVX512 cases.
5736 if (!ST->hasAVX512())
5737 return bailout();
5738
5739 // Do we have a native shuffle for this element type, or should we promote?
5740 unsigned PromEltTyBits = EltTyBits;
5741 switch (EltTyBits) {
5742 case 32:
5743 case 64:
5744 break; // AVX512F.
5745 case 16:
5746 if (!ST->hasBWI())
5747 PromEltTyBits = 32; // promote to i32, AVX512F.
5748 break; // AVX512BW
5749 case 8:
5750 if (!ST->hasVBMI())
5751 PromEltTyBits = 32; // promote to i32, AVX512F.
5752 break; // AVX512VBMI
5753 case 1:
5754 // There is no support for shuffling i1 elements. We *must* promote.
5755 if (ST->hasBWI()) {
5756 if (ST->hasVBMI())
5757 PromEltTyBits = 8; // promote to i8, AVX512VBMI.
5758 else
5759 PromEltTyBits = 16; // promote to i16, AVX512BW.
5760 break;
5761 }
5762 PromEltTyBits = 32; // promote to i32, AVX512F.
5763 break;
5764 default:
5765 return bailout();
5766 }
5767 auto *PromEltTy = IntegerType::getIntNTy(EltTy->getContext(), PromEltTyBits);
5768
5769 auto *SrcVecTy = FixedVectorType::get(EltTy, VF);
5770 auto *PromSrcVecTy = FixedVectorType::get(PromEltTy, VF);
5771
5772 int NumDstElements = VF * ReplicationFactor;
5773 auto *PromDstVecTy = FixedVectorType::get(PromEltTy, NumDstElements);
5774 auto *DstVecTy = FixedVectorType::get(EltTy, NumDstElements);
5775
5776 // Legalize the types.
5777 MVT LegalSrcVecTy = getTypeLegalizationCost(SrcVecTy).second;
5778 MVT LegalPromSrcVecTy = getTypeLegalizationCost(PromSrcVecTy).second;
5779 MVT LegalPromDstVecTy = getTypeLegalizationCost(PromDstVecTy).second;
5780 MVT LegalDstVecTy = getTypeLegalizationCost(DstVecTy).second;
5781 // They should have legalized into vector types.
5782 if (!LegalSrcVecTy.isVector() || !LegalPromSrcVecTy.isVector() ||
5783 !LegalPromDstVecTy.isVector() || !LegalDstVecTy.isVector())
5784 return bailout();
5785
5786 if (PromEltTyBits != EltTyBits) {
5787 // If we have to perform the shuffle with wider elt type than our data type,
5788 // then we will first need to anyext (we don't care about the new bits)
5789 // the source elements, and then truncate Dst elements.
5790 InstructionCost PromotionCost;
5791 PromotionCost += getCastInstrCost(
5792 Instruction::SExt, /*Dst=*/PromSrcVecTy, /*Src=*/SrcVecTy,
5794 PromotionCost +=
5795 getCastInstrCost(Instruction::Trunc, /*Dst=*/DstVecTy,
5796 /*Src=*/PromDstVecTy,
5798 return PromotionCost + getReplicationShuffleCost(PromEltTy,
5799 ReplicationFactor, VF,
5800 DemandedDstElts, CostKind);
5801 }
5802
5803 assert(LegalSrcVecTy.getScalarSizeInBits() == EltTyBits &&
5804 LegalSrcVecTy.getScalarType() == LegalDstVecTy.getScalarType() &&
5805 "We expect that the legalization doesn't affect the element width, "
5806 "doesn't coalesce/split elements.");
5807
5808 unsigned NumEltsPerDstVec = LegalDstVecTy.getVectorNumElements();
5809 unsigned NumDstVectors =
5810 divideCeil(DstVecTy->getNumElements(), NumEltsPerDstVec);
5811
5812 auto *SingleDstVecTy = FixedVectorType::get(EltTy, NumEltsPerDstVec);
5813
5814 // Not all the produced Dst elements may be demanded. In our case,
5815 // given that a single Dst vector is formed by a single shuffle,
5816 // if all elements that will form a single Dst vector aren't demanded,
5817 // then we won't need to do that shuffle, so adjust the cost accordingly.
5818 APInt DemandedDstVectors = APIntOps::ScaleBitMask(
5819 DemandedDstElts.zext(NumDstVectors * NumEltsPerDstVec), NumDstVectors);
5820 unsigned NumDstVectorsDemanded = DemandedDstVectors.popcount();
5821
5822 InstructionCost SingleShuffleCost =
5823 getShuffleCost(TTI::SK_PermuteSingleSrc, SingleDstVecTy, SingleDstVecTy,
5824 CostKind, /*Mask=*/{},
5825 /*Index=*/0, /*SubTp=*/nullptr);
5826 return NumDstVectorsDemanded * SingleShuffleCost;
5827}
5828
5830 Align Alignment,
5831 unsigned AddressSpace,
5833 TTI::OperandValueInfo OpInfo,
5834 const Instruction *I) const {
5835 // FIXME: Load latency isn't handled here
5836 if (Opcode == Instruction::Load && CostKind == TTI::TCK_Latency)
5837 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
5838 CostKind, OpInfo, I);
5839
5840 // TODO: Handle other cost kinds.
5842 if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {
5843 // Store instruction with index and scale costs 2 Uops.
5844 // Check the preceding GEP to identify non-const indices.
5845 if (auto *GEP = dyn_cast<GetElementPtrInst>(SI->getPointerOperand())) {
5846 if (!all_of(GEP->indices(), [](Value *V) { return isa<Constant>(V); }))
5847 return TTI::TCC_Basic * 2;
5848 }
5849 }
5850 return TTI::TCC_Basic;
5851 }
5852
5853 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5854 "Invalid Opcode");
5855 // Type legalization can't handle structs
5856 if (TLI->getValueType(DL, Src, true) == MVT::Other)
5857 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
5858 CostKind, OpInfo, I);
5859
5860 // Legalize the type.
5861 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Src);
5862
5863 auto *VTy = dyn_cast<FixedVectorType>(Src);
5864
5866
5867 // Add a cost for constant load to vector.
5868 if (Opcode == Instruction::Store && OpInfo.isConstant())
5869 Cost += getMemoryOpCost(Instruction::Load, Src, DL.getABITypeAlign(Src),
5870 /*AddressSpace=*/0, CostKind, OpInfo);
5871
5872 // Handle the simple case of non-vectors.
5873 // NOTE: this assumes that legalization never creates vector from scalars!
5874 if (!VTy || !LT.second.isVector()) {
5875 // Each load/store unit costs 1.
5876 return (LT.second.isFloatingPoint() ? Cost : 0) + LT.first * 1;
5877 }
5878
5879 bool IsLoad = Opcode == Instruction::Load;
5880
5881 Type *EltTy = VTy->getElementType();
5882
5883 const int EltTyBits = DL.getTypeSizeInBits(EltTy);
5884
5885 // Source of truth: how many elements were there in the original IR vector?
5886 const unsigned SrcNumElt = VTy->getNumElements();
5887
5888 // How far have we gotten?
5889 int NumEltRemaining = SrcNumElt;
5890 // Note that we intentionally capture by-reference, NumEltRemaining changes.
5891 auto NumEltDone = [&]() { return SrcNumElt - NumEltRemaining; };
5892
5893 const int MaxLegalOpSizeBytes = divideCeil(LT.second.getSizeInBits(), 8);
5894
5895 // Note that even if we can store 64 bits of an XMM, we still operate on XMM.
5896 const unsigned XMMBits = 128;
5897 if (XMMBits % EltTyBits != 0)
5898 // Vector size must be a multiple of the element size. I.e. no padding.
5899 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
5900 CostKind, OpInfo, I);
5901 const int NumEltPerXMM = XMMBits / EltTyBits;
5902
5903 auto *XMMVecTy = FixedVectorType::get(EltTy, NumEltPerXMM);
5904
5905 for (int CurrOpSizeBytes = MaxLegalOpSizeBytes, SubVecEltsLeft = 0;
5906 NumEltRemaining > 0; CurrOpSizeBytes /= 2) {
5907 // How many elements would a single op deal with at once?
5908 if ((8 * CurrOpSizeBytes) % EltTyBits != 0)
5909 // Vector size must be a multiple of the element size. I.e. no padding.
5910 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
5911 CostKind, OpInfo, I);
5912 int CurrNumEltPerOp = (8 * CurrOpSizeBytes) / EltTyBits;
5913
5914 assert(CurrOpSizeBytes > 0 && CurrNumEltPerOp > 0 && "How'd we get here?");
5915 assert((((NumEltRemaining * EltTyBits) < (2 * 8 * CurrOpSizeBytes)) ||
5916 (CurrOpSizeBytes == MaxLegalOpSizeBytes)) &&
5917 "Unless we haven't halved the op size yet, "
5918 "we have less than two op's sized units of work left.");
5919
5920 auto *CurrVecTy = CurrNumEltPerOp > NumEltPerXMM
5921 ? FixedVectorType::get(EltTy, CurrNumEltPerOp)
5922 : XMMVecTy;
5923
5924 assert(CurrVecTy->getNumElements() % CurrNumEltPerOp == 0 &&
5925 "After halving sizes, the vector elt count is no longer a multiple "
5926 "of number of elements per operation?");
5927 auto *CoalescedVecTy =
5928 CurrNumEltPerOp == 1
5929 ? CurrVecTy
5931 IntegerType::get(Src->getContext(),
5932 EltTyBits * CurrNumEltPerOp),
5933 CurrVecTy->getNumElements() / CurrNumEltPerOp);
5934 assert(DL.getTypeSizeInBits(CoalescedVecTy) ==
5935 DL.getTypeSizeInBits(CurrVecTy) &&
5936 "coalesciing elements doesn't change vector width.");
5937
5938 while (NumEltRemaining > 0) {
5939 assert(SubVecEltsLeft >= 0 && "Subreg element count overconsumtion?");
5940
5941 // Can we use this vector size, as per the remaining element count?
5942 // Iff the vector is naturally aligned, we can do a wide load regardless.
5943 if (NumEltRemaining < CurrNumEltPerOp &&
5944 (!IsLoad || Alignment < CurrOpSizeBytes) && CurrOpSizeBytes != 1)
5945 break; // Try smalled vector size.
5946
5947 // This isn't exactly right. We're using slow unaligned 32-byte accesses
5948 // as a proxy for a double-pumped AVX memory interface such as on
5949 // Sandybridge.
5950 // Sub-32-bit loads/stores will be slower either with PINSR*/PEXTR* or
5951 // will be scalarized.
5952 //
5953 // For a vector load, each non-0th 1/2/4-byte in-lane remainder chunk is
5954 // materialized by a *single* folded PINSR*(mem) that both loads and
5955 // inserts the lane (1B->PINSRB, 2B->PINSRW, 4B->PINSRD; the byte and
5956 // dword folds need SSE4.1, the word fold only SSE2).
5957 // When that fold is available the chunk is one instruction, so it must be
5958 // priced once here (as a plain load) and the separate lane-insert charge
5959 // below must be skipped - otherwise the folded insert is double-counted.
5960 // Stores (the symmetric PEXTR*(mem) fold) are left unchanged here.
5961 bool Is0thSubVec = (NumEltDone() % LT.second.getVectorNumElements()) == 0;
5962 bool FoldedInLaneInsert = IsLoad && !Is0thSubVec &&
5963 ((CurrOpSizeBytes == 1 && ST->hasSSE41()) ||
5964 (CurrOpSizeBytes == 2 && ST->hasSSE2()) ||
5965 (CurrOpSizeBytes == 4 && ST->hasSSE41()));
5966 if (CurrOpSizeBytes == 32 && ST->isUnalignedMem32Slow())
5967 Cost += 2;
5968 else if (CurrOpSizeBytes < 4 && !FoldedInLaneInsert)
5969 Cost += 2;
5970 else
5971 Cost += 1;
5972
5973 // If we're loading a uniform value, then we don't need to split the load,
5974 // loading just a single (widest) vector can be reused by all splits.
5975 if (IsLoad && OpInfo.isUniform())
5976 return Cost;
5977
5978 // If we have fully processed the previous reg, we need to replenish it.
5979 if (SubVecEltsLeft == 0) {
5980 SubVecEltsLeft += CurrVecTy->getNumElements();
5981 // And that's free only for the 0'th subvector of a legalized vector.
5982 if (!Is0thSubVec)
5983 Cost +=
5986 VTy, VTy, CostKind, {}, NumEltDone(), CurrVecTy);
5987 }
5988
5989 // While we can directly load/store ZMM, YMM, and 64-bit halves of XMM,
5990 // for smaller widths (32/16/8) we have to insert/extract them separately.
5991 // Again, it's free for the 0'th subreg (if op is 32/64 bit wide,
5992 // but let's pretend that it is also true for 16/8 bit wide ops...)
5993 if (CurrOpSizeBytes <= 32 / 8 && !Is0thSubVec && !FoldedInLaneInsert) {
5994 int NumEltDoneInCurrXMM = NumEltDone() % NumEltPerXMM;
5995 assert(NumEltDoneInCurrXMM % CurrNumEltPerOp == 0 && "");
5996 int CoalescedVecEltIdx = NumEltDoneInCurrXMM / CurrNumEltPerOp;
5997 APInt DemandedElts =
5998 APInt::getBitsSet(CoalescedVecTy->getNumElements(),
5999 CoalescedVecEltIdx, CoalescedVecEltIdx + 1);
6000 assert(DemandedElts.popcount() == 1 && "Inserting single value");
6001 Cost += getScalarizationOverhead(CoalescedVecTy, DemandedElts, IsLoad,
6002 !IsLoad, CostKind);
6003 }
6004
6005 SubVecEltsLeft -= CurrNumEltPerOp;
6006 NumEltRemaining -= CurrNumEltPerOp;
6007 Alignment = commonAlignment(Alignment, CurrOpSizeBytes);
6008 }
6009 }
6010
6011 assert(NumEltRemaining <= 0 && "Should have processed all the elements.");
6012
6013 return Cost;
6014}
6015
6019 switch (MICA.getID()) {
6020 case Intrinsic::masked_scatter:
6021 case Intrinsic::masked_gather:
6022 return getGatherScatterOpCost(MICA, CostKind);
6023 case Intrinsic::masked_load:
6024 case Intrinsic::masked_store:
6025 return getMaskedMemoryOpCost(MICA, CostKind);
6026 case Intrinsic::masked_compressstore:
6027 // Fallback to scalarization for slow compressstore targets (e.g. znver4).
6028 if (ST->isVecCompressStoreSlow())
6030 break;
6031 }
6032
6033 static const CostKindTblEntry AVX512VBMI2CostTable[] = {
6034 { Intrinsic::masked_expandload, MVT::v16i8, { 2, 7, 1, 3 } },
6035 { Intrinsic::masked_expandload, MVT::v32i8, { 2, 8, 1, 3 } },
6036 { Intrinsic::masked_expandload, MVT::v64i8, { 2, 9, 1, 3 } },
6037
6038 { Intrinsic::masked_expandload, MVT::v8i16, { 2, 7, 1, 3 } },
6039 { Intrinsic::masked_expandload, MVT::v16i16, { 2, 8, 1, 3 } },
6040 { Intrinsic::masked_expandload, MVT::v32i16, { 2, 9, 1, 3 } },
6041
6042 { Intrinsic::masked_compressstore, MVT::v16i8, { 3,10, 1, 7 } },
6043 { Intrinsic::masked_compressstore, MVT::v32i8, { 3,11, 1, 7 } },
6044 { Intrinsic::masked_compressstore, MVT::v64i8, { 3,12, 1, 8 } },
6045
6046 { Intrinsic::masked_compressstore, MVT::v8i16, { 3,10, 1, 7 } },
6047 { Intrinsic::masked_compressstore, MVT::v16i16, { 3,11, 1, 7 } },
6048 { Intrinsic::masked_compressstore, MVT::v32i16, { 3,12, 1, 8 } },
6049 };
6050
6051 static const CostKindTblEntry AVX512CostTable[] = {
6052 { Intrinsic::masked_expandload, MVT::v4i32, { 2, 7, 1, 3 } },
6053 { Intrinsic::masked_expandload, MVT::v4f32, { 2, 7, 1, 3 } },
6054 { Intrinsic::masked_expandload, MVT::v8i32, { 2, 8, 1, 3 } },
6055 { Intrinsic::masked_expandload, MVT::v8f32, { 2, 8, 1, 3 } },
6056 { Intrinsic::masked_expandload, MVT::v16i32, { 2, 9, 1, 3 } },
6057 { Intrinsic::masked_expandload, MVT::v16f32, { 2, 9, 1, 3 } },
6058
6059 { Intrinsic::masked_expandload, MVT::v2i64, { 2, 7, 1, 3 } },
6060 { Intrinsic::masked_expandload, MVT::v2f64, { 2, 7, 1, 3 } },
6061 { Intrinsic::masked_expandload, MVT::v4i64, { 2, 8, 1, 3 } },
6062 { Intrinsic::masked_expandload, MVT::v4f64, { 2, 8, 1, 3 } },
6063 { Intrinsic::masked_expandload, MVT::v8i64, { 2, 9, 1, 3 } },
6064 { Intrinsic::masked_expandload, MVT::v8f64, { 2, 9, 1, 3 } },
6065
6066 { Intrinsic::masked_compressstore, MVT::v4i32, { 3,10, 1, 7 } },
6067 { Intrinsic::masked_compressstore, MVT::v4f32, { 3,10, 1, 7 } },
6068 { Intrinsic::masked_compressstore, MVT::v8i32, { 3,11, 1, 7 } },
6069 { Intrinsic::masked_compressstore, MVT::v8f32, { 3,11, 1, 7 } },
6070 { Intrinsic::masked_compressstore, MVT::v16i32, { 3,12, 1, 8 } },
6071 { Intrinsic::masked_compressstore, MVT::v16f32, { 3,12, 1, 8 } },
6072
6073 { Intrinsic::masked_compressstore, MVT::v2i64, { 3,10, 1, 7 } },
6074 { Intrinsic::masked_compressstore, MVT::v2f64, { 3,10, 1, 7 } },
6075 { Intrinsic::masked_compressstore, MVT::v4i64, { 3,11, 1, 7 } },
6076 { Intrinsic::masked_compressstore, MVT::v4f64, { 3,11, 1, 7 } },
6077 { Intrinsic::masked_compressstore, MVT::v8i64, { 3,12, 1, 8 } },
6078 { Intrinsic::masked_compressstore, MVT::v8f64, { 3,12, 1, 8 } },
6079 };
6080
6081 std::pair<InstructionCost, MVT> LT =
6083
6084 if (ST->hasVBMI2())
6085 if (const auto *Entry =
6086 CostTableLookup(AVX512VBMI2CostTable, MICA.getID(), LT.second))
6087 if (auto KindCost = Entry->Cost[CostKind])
6088 return LT.first * *KindCost;
6089
6090 if (ST->hasAVX512())
6091 if (const auto *Entry =
6092 CostTableLookup(AVX512CostTable, MICA.getID(), LT.second))
6093 if (auto KindCost = Entry->Cost[CostKind])
6094 return LT.first * *KindCost;
6095
6097}
6098
6102 unsigned Opcode = MICA.getID() == Intrinsic::masked_load ? Instruction::Load
6103 : Instruction::Store;
6104 Type *SrcTy = MICA.getDataType();
6105 Align Alignment = MICA.getAlignment();
6106 unsigned AddressSpace = MICA.getAddressSpace();
6107
6108 bool IsLoad = (Instruction::Load == Opcode);
6109 bool IsStore = (Instruction::Store == Opcode);
6110
6111 auto *SrcVTy = dyn_cast<FixedVectorType>(SrcTy);
6112 if (!SrcVTy)
6113 // To calculate scalar take the regular cost, without mask
6114 return getMemoryOpCost(Opcode, SrcTy, Alignment, AddressSpace, CostKind);
6115
6116 unsigned NumElem = SrcVTy->getNumElements();
6117 auto *MaskTy =
6118 FixedVectorType::get(Type::getInt8Ty(SrcVTy->getContext()), NumElem);
6119 if ((IsLoad && !isLegalMaskedLoad(SrcVTy, Alignment, AddressSpace)) ||
6120 (IsStore && !isLegalMaskedStore(SrcVTy, Alignment, AddressSpace))) {
6121 // Scalarization
6122 APInt DemandedElts = APInt::getAllOnes(NumElem);
6124 MaskTy, DemandedElts, /*Insert*/ false, /*Extract*/ true, CostKind);
6125 InstructionCost ScalarCompareCost = getCmpSelInstrCost(
6126 Instruction::ICmp, Type::getInt8Ty(SrcVTy->getContext()), nullptr,
6128 InstructionCost BranchCost = getCFInstrCost(Instruction::CondBr, CostKind);
6129 InstructionCost MaskCmpCost = NumElem * (BranchCost + ScalarCompareCost);
6131 SrcVTy, DemandedElts, IsLoad, IsStore, CostKind);
6132 InstructionCost MemopCost =
6133 NumElem * BaseT::getMemoryOpCost(Opcode, SrcVTy->getScalarType(),
6134 Alignment, AddressSpace, CostKind);
6135 return MemopCost + ValueSplitCost + MaskSplitCost + MaskCmpCost;
6136 }
6137
6138 // Legalize the type.
6139 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(SrcVTy);
6140 auto VT = TLI->getValueType(DL, SrcVTy);
6142 MVT Ty = LT.second;
6143 if (Ty == MVT::i16 || Ty == MVT::i32 || Ty == MVT::i64)
6144 // APX masked load/store for scalar is cheap.
6145 return Cost + LT.first;
6146
6147 if (VT.isSimple() && Ty != VT.getSimpleVT() &&
6148 LT.second.getVectorNumElements() == NumElem)
6149 // Promotion requires extend/truncate for data and a shuffle for mask.
6150 Cost += getShuffleCost(TTI::SK_PermuteTwoSrc, SrcVTy, SrcVTy, CostKind, {},
6151 0, nullptr) +
6152 getShuffleCost(TTI::SK_PermuteTwoSrc, MaskTy, MaskTy, CostKind, {},
6153 0, nullptr);
6154
6155 else if (LT.first * Ty.getVectorNumElements() > NumElem) {
6156 auto *NewMaskTy = FixedVectorType::get(MaskTy->getElementType(),
6157 (unsigned)LT.first.getValue() *
6158 Ty.getVectorNumElements());
6159 // Expanding requires fill mask with zeroes
6160 Cost += getShuffleCost(TTI::SK_InsertSubvector, NewMaskTy, NewMaskTy,
6161 CostKind, {}, 0, MaskTy);
6162 }
6163
6164 // Predicate fanout (see getPredicateFanoutCost): only a variable mask needs
6165 // a per-part sub-mask; a constant mask is folded by codegen and pays nothing.
6166 InstructionCost MaskExpCost = 0;
6167 if (MICA.getVariableMask()) {
6168 auto *MaskVecTy =
6169 FixedVectorType::get(Type::getInt1Ty(SrcVTy->getContext()), NumElem);
6170 MaskExpCost = getPredicateFanoutCost(*this, SrcVTy, MaskVecTy);
6171 }
6172
6173 // Pre-AVX512 - each maskmov load costs 2 + store costs ~8.
6174 if (!ST->hasAVX512())
6175 return Cost + LT.first * (IsLoad ? 2 : 8) + MaskExpCost;
6176
6177 // AVX-512 masked load/store is cheaper.
6178 return Cost + LT.first + MaskExpCost;
6179}
6180
6182 ArrayRef<const Value *> Ptrs, const Value *Base,
6183 const TTI::PointersChainInfo &Info, Type *AccessTy,
6184 const TTI::TargetCostKind CostKind) const {
6185 if (Info.isSameBase() && Info.isKnownStride()) {
6186 // If all the pointers have known stride all the differences are translated
6187 // into constants. X86 memory addressing allows encoding it into
6188 // displacement. So we just need to take the base GEP cost.
6189 if (const auto *BaseGEP = dyn_cast<GetElementPtrInst>(Base)) {
6190 SmallVector<const Value *> Indices(BaseGEP->indices());
6191 return getGEPCost(BaseGEP->getSourceElementType(),
6192 BaseGEP->getPointerOperand(), Indices, CostKind,
6193 nullptr);
6194 }
6195 return TTI::TCC_Free;
6196 }
6197 return BaseT::getPointersChainCost(Ptrs, Base, Info, AccessTy, CostKind);
6198}
6199
6202 const SCEV *Ptr,
6204 // Address computations in vectorized code with non-consecutive addresses will
6205 // likely result in more instructions compared to scalar code where the
6206 // computation can more often be merged into the index mode. The resulting
6207 // extra micro-ops can significantly decrease throughput.
6208 const unsigned NumVectorInstToHideOverhead = 10;
6209
6210 // Cost modeling of Strided Access Computation is hidden by the indexing
6211 // modes of X86 regardless of the stride value. We dont believe that there
6212 // is a difference between constant strided access in gerenal and constant
6213 // strided value which is less than or equal to 64.
6214 // Even in the case of (loop invariant) stride whose value is not known at
6215 // compile time, the address computation will not incur more than one extra
6216 // ADD instruction.
6217 if (PtrTy->isVectorTy() && SE) {
6219 return 1;
6220 if (!ST->hasAVX2()) {
6221 // TODO: AVX2 is the current cut-off because we don't have correct
6222 // interleaving costs for prior ISA's.
6223 if (!BaseT::isStridedAccess(Ptr))
6224 return NumVectorInstToHideOverhead;
6225 }
6226 }
6227
6228 return BaseT::getAddressComputationCost(PtrTy, SE, Ptr, CostKind);
6229}
6230
6232 unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,
6234 TTI::PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp,
6235 TTI::TargetCostKind CostKind, std::optional<FastMathFlags> FMF) const {
6236 auto ExpandCost = [&]() {
6237 return BaseT::getPartialReductionCost(Opcode, InputTypeA, InputTypeB,
6238 AccumType, VF, OpAExtend, OpBExtend,
6239 BinOp, CostKind, FMF);
6240 };
6241
6242 // The dot product instructions multiply-accumulate i8 x i8 -> i32,
6243 // i16 x i16 -> i32, bf16 x bf16 -> f32 or f16 x f16 -> f32. Partial
6244 // reductions may also multiply inputs extended from different types, which
6245 // they can't handle.
6246 if (VF.isScalable() || !BinOp || OpAExtend == TTI::PR_None ||
6247 OpBExtend == TTI::PR_None || InputTypeA != InputTypeB)
6248 return ExpandCost();
6249
6250 unsigned Opc;
6251 if (Opcode == Instruction::Add && *BinOp == Instruction::Mul &&
6252 AccumType->isIntegerTy(32) &&
6253 (InputTypeA->isIntegerTy(8) || InputTypeA->isIntegerTy(16))) {
6254 if (OpAExtend != OpBExtend)
6256 else if (OpAExtend == TTI::PR_SignExtend)
6258 else
6260 } else if (Opcode == Instruction::FAdd && *BinOp == Instruction::FMul &&
6261 AccumType->isFloatTy() &&
6262 (InputTypeA->isBFloatTy() || InputTypeA->isHalfTy())) {
6263 // VDPBF16PS and VDPPHPS, like the expansion, reassociate the additions and
6264 // fuse the multiplications.
6265 if (!FMF || !FMF->allowReassoc() || !FMF->allowContract())
6268 } else {
6269 return ExpandCost();
6270 }
6271
6272 unsigned Ratio =
6273 AccumType->getScalarSizeInBits() / InputTypeA->getScalarSizeInBits();
6274 if (!VF.isKnownMultipleOf(Ratio))
6275 return ExpandCost();
6276
6277 // One dot product per legal accumulator vector. Accumulators narrower than
6278 // a legal vector are widened by expanding the partial reduction instead.
6279 auto *AccVecTy = VectorType::get(AccumType, VF.divideCoefficientBy(Ratio));
6280 auto *InputVecTy = VectorType::get(InputTypeA, VF);
6281 std::pair<InstructionCost, MVT> AccLT = getTypeLegalizationCost(AccVecTy);
6282 std::pair<InstructionCost, MVT> InputLT = getTypeLegalizationCost(InputVecTy);
6283 if (AccLT.second.getFixedSizeInBits() >
6284 AccVecTy->getPrimitiveSizeInBits().getFixedValue() ||
6285 !TLI->isPartialReduceMLALegalOrCustom(Opc, AccLT.second, InputLT.second))
6286 return ExpandCost();
6287
6288 return AccLT.first;
6289}
6290
6293 std::optional<FastMathFlags> FMF,
6296 return BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);
6297
6298 // We use llvm-mca across all supported CPUs to measure the logic cost stats.
6299 // We use the Intel Architecture Code Analyzer(IACA) to measure the throughput
6300 // and make it as the cost. TODO: Update old IACA numbers to llvm-mca.
6301
6302 static const CostKindTblEntry SLMCostTbl[] = {
6303 { ISD::FADD, MVT::v2f64, {3, 3, 3, 3} },
6304 { ISD::ADD, MVT::v2i64, {5, 5, 5, 5} },
6305 };
6306
6307 static const CostKindTblEntry SSE2CostTbl[] = {
6308 { ISD::FADD, MVT::v2f64, {2, 2, 2, 2} },
6309 { ISD::FADD, MVT::v2f32, {2, 2, 2, 2} },
6310 { ISD::FADD, MVT::v4f32, {4, 4, 4, 4} },
6311 { ISD::ADD, MVT::v2i64, {2, 2, 2, 2} }, // The data reported by the IACA tool is "1.6".
6312 { ISD::ADD, MVT::v2i32, {2, 2, 2, 2} }, // FIXME: chosen to be less than v4i32
6313 { ISD::ADD, MVT::v4i32, {3, 3, 3, 3} }, // The data reported by the IACA tool is "3.3".
6314 { ISD::ADD, MVT::v2i16, {2, 2, 2, 2} }, // The data reported by the IACA tool is "4.3".
6315 { ISD::ADD, MVT::v4i16, {3, 3, 3, 3} }, // The data reported by the IACA tool is "4.3".
6316 { ISD::ADD, MVT::v8i16, {4, 4, 4, 4} }, // The data reported by the IACA tool is "4.3".
6317 { ISD::ADD, MVT::v2i8, {2, 2, 2, 2} },
6318 { ISD::ADD, MVT::v4i8, {2, 2, 2, 2} },
6319 { ISD::ADD, MVT::v8i8, {2, 2, 2, 2} },
6320 { ISD::ADD, MVT::v16i8, {3, 3, 3, 3} },
6321
6322 { ISD::AND, MVT::v2i64, {2, 2, 3, 3} },
6323 { ISD::AND, MVT::v4i32, {3, 4, 5, 5} },
6324 { ISD::AND, MVT::v8i16, {4, 7, 8, 8} },
6325 { ISD::AND, MVT::v16i8, {6,10,11,11} },
6326 { ISD::OR, MVT::v2i64, {2, 2, 3, 3} },
6327 { ISD::OR, MVT::v4i32, {3, 4, 5, 5} },
6328 { ISD::OR, MVT::v8i16, {4, 7, 8, 8} },
6329 { ISD::OR, MVT::v16i8, {6,10,11,11} },
6330 { ISD::XOR, MVT::v2i64, {2, 2, 3, 3} },
6331 { ISD::XOR, MVT::v4i32, {3, 4, 5, 5} },
6332 { ISD::XOR, MVT::v8i16, {4, 7, 8, 8} },
6333 { ISD::XOR, MVT::v16i8, {6,10,11,11} },
6334 };
6335
6336 static const CostKindTblEntry AVX1CostTbl[] = {
6337 { ISD::FADD, MVT::v4f64, {3, 3, 3, 3} },
6338 { ISD::FADD, MVT::v4f32, {3, 3, 3, 3} },
6339 { ISD::FADD, MVT::v8f32, {4, 4, 4, 4} },
6340 { ISD::ADD, MVT::v2i64, {1, 1, 1, 1} }, // The data reported by the IACA tool is "1.5".
6341 { ISD::ADD, MVT::v4i64, {3, 3, 3, 3} },
6342 { ISD::ADD, MVT::v8i32, {5, 5, 5, 5} },
6343 { ISD::ADD, MVT::v16i16, {5, 5, 5, 5} },
6344 { ISD::ADD, MVT::v32i8, {4, 4, 4, 4} },
6345
6346 { ISD::AND, MVT::v4i64, {3, 7, 5, 5} },
6347 { ISD::AND, MVT::v8i32, {4, 9, 7, 7} },
6348 { ISD::AND, MVT::v16i16, {5,11, 9, 9} },
6349 { ISD::AND, MVT::v8i16, {4, 7, 7, 7} },
6350 { ISD::AND, MVT::v32i8, {6,13,11,11} },
6351 { ISD::AND, MVT::v16i8, {5,10, 9, 9} },
6352 { ISD::OR, MVT::v4i64, {3, 7, 5, 5} },
6353 { ISD::OR, MVT::v8i32, {4, 9, 7, 7} },
6354 { ISD::OR, MVT::v16i16, {5,11, 9, 9} },
6355 { ISD::OR, MVT::v8i16, {4, 7, 7, 7} },
6356 { ISD::OR, MVT::v32i8, {6,13,11,11} },
6357 { ISD::OR, MVT::v16i8, {5,10, 9, 9} },
6358 { ISD::XOR, MVT::v4i64, {3, 7, 5, 5} },
6359 { ISD::XOR, MVT::v8i32, {4, 9, 7, 7} },
6360 { ISD::XOR, MVT::v16i16, {5,11, 9, 9} },
6361 { ISD::XOR, MVT::v8i16, {4, 7, 7, 7} },
6362 { ISD::XOR, MVT::v32i8, {6,13,11,11} },
6363 { ISD::XOR, MVT::v16i8, {5,10, 9, 9} },
6364 };
6365
6366 static const CostKindTblEntry AVX2CostTbl[] = {
6367 { ISD::AND, MVT::v4i64, {2, 7, 5, 5} },
6368 { ISD::AND, MVT::v2i64, {1, 2, 3, 3} },
6369 { ISD::AND, MVT::v8i32, {3, 9, 7, 7} },
6370 { ISD::AND, MVT::v4i32, {2, 4, 5, 5} },
6371 { ISD::AND, MVT::v16i16, {3,11, 9, 9} },
6372 { ISD::AND, MVT::v8i16, {2, 6, 7, 7} },
6373 { ISD::AND, MVT::v32i8, {3,13,11,11} },
6374 { ISD::AND, MVT::v16i8, {3, 8, 9, 9} },
6375 { ISD::OR, MVT::v4i64, {2, 7, 5, 5} },
6376 { ISD::OR, MVT::v2i64, {1, 2, 3, 3} },
6377 { ISD::OR, MVT::v8i32, {3, 9, 7, 7} },
6378 { ISD::OR, MVT::v4i32, {2, 4, 5, 5} },
6379 { ISD::OR, MVT::v16i16, {3,11, 9, 9} },
6380 { ISD::OR, MVT::v8i16, {2, 6, 7, 7} },
6381 { ISD::OR, MVT::v32i8, {3,13,11,11} },
6382 { ISD::OR, MVT::v16i8, {3, 8, 9, 9} },
6383 { ISD::XOR, MVT::v4i64, {2, 7, 5, 5} },
6384 { ISD::XOR, MVT::v2i64, {1, 2, 3, 3} },
6385 { ISD::XOR, MVT::v8i32, {3, 9, 7, 7} },
6386 { ISD::XOR, MVT::v4i32, {2, 4, 5, 5} },
6387 { ISD::XOR, MVT::v16i16, {3,11, 9, 9} },
6388 { ISD::XOR, MVT::v8i16, {2, 6, 7, 7} },
6389 { ISD::XOR, MVT::v32i8, {3,13,11,11} },
6390 { ISD::XOR, MVT::v16i8, {3, 8, 9, 9} },
6391 };
6392
6393 static const CostKindTblEntry AVX512FCostTbl[] = {
6394 { ISD::FADD, MVT::v8f64, {4, 4, 4, 4} },
6395 { ISD::FADD, MVT::v16f32, {5, 5, 5, 5} },
6396 { ISD::ADD, MVT::v8i64, {4, 4, 4, 4} },
6397 { ISD::ADD, MVT::v16i32, {6, 6, 6, 6} },
6398
6399 { ISD::AND, MVT::v8i64, {3,10, 7, 7} },
6400 { ISD::AND, MVT::v16i32, {4,12, 9, 9} },
6401 { ISD::AND, MVT::v32i16, {4,14,11,11} },
6402 { ISD::AND, MVT::v64i8, {4,16,13,13} },
6403 { ISD::AND, MVT::v16i8, {2, 8, 9, 9} },
6404 { ISD::OR, MVT::v8i64, {3,10, 7, 7} },
6405 { ISD::OR, MVT::v16i32, {4,12, 9, 9} },
6406 { ISD::OR, MVT::v32i16, {4,14,11,11} },
6407 { ISD::OR, MVT::v64i8, {4,16,13,13} },
6408 { ISD::OR, MVT::v16i8, {2, 8, 9, 9} },
6409 { ISD::XOR, MVT::v8i64, {3,10, 7, 7} },
6410 { ISD::XOR, MVT::v16i32, {4,12, 9, 9} },
6411 { ISD::XOR, MVT::v32i16, {4,14,11,11} },
6412 { ISD::XOR, MVT::v64i8, {4,16,13,13} },
6413 { ISD::XOR, MVT::v16i8, {2, 8, 9, 9} },
6414 };
6415
6416 static const CostKindTblEntry AVX512BWCostTbl[] = {
6417 { ISD::ADD, MVT::v32i16, {7, 7, 7, 7} },
6418 { ISD::ADD, MVT::v64i8, {4, 4, 4, 4} },
6419 };
6420
6421 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6422 assert(ISD && "Invalid opcode");
6423
6424 // Before legalizing the type, give a chance to look up illegal narrow types
6425 // in the table.
6426 // FIXME: Is there a better way to do this?
6427 EVT VT = TLI->getValueType(DL, ValTy);
6428 if (VT.isSimple()) {
6429 MVT MTy = VT.getSimpleVT();
6430 if (ST->useSLMArithCosts())
6431 if (const auto *Entry = CostTableLookup(SLMCostTbl, ISD, MTy))
6432 if (auto KindCost = Entry->Cost[CostKind])
6433 return *KindCost;
6434
6435 if (ST->hasBWI())
6436 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
6437 if (auto KindCost = Entry->Cost[CostKind])
6438 return *KindCost;
6439
6440 if (ST->hasAVX512())
6441 if (const auto *Entry = CostTableLookup(AVX512FCostTbl, ISD, MTy))
6442 if (auto KindCost = Entry->Cost[CostKind])
6443 return *KindCost;
6444
6445 if (ST->hasAVX2())
6446 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
6447 if (auto KindCost = Entry->Cost[CostKind])
6448 return *KindCost;
6449
6450 if (ST->hasAVX())
6451 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
6452 if (auto KindCost = Entry->Cost[CostKind])
6453 return *KindCost;
6454
6455 if (ST->hasSSE2())
6456 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
6457 if (auto KindCost = Entry->Cost[CostKind])
6458 return *KindCost;
6459 }
6460
6461 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
6462
6463 MVT MTy = LT.second;
6464
6465 auto *ValVTy = cast<FixedVectorType>(ValTy);
6466
6467 InstructionCost ArithmeticCost = 0;
6468 if (LT.first != 1 && MTy.isVector() &&
6469 MTy.getVectorNumElements() < ValVTy->getNumElements()) {
6470 // Type needs to be split. We need LT.first - 1 arithmetic ops.
6471 auto *SingleOpTy = FixedVectorType::get(ValVTy->getElementType(),
6472 MTy.getVectorNumElements());
6473 ArithmeticCost = getArithmeticInstrCost(Opcode, SingleOpTy, CostKind);
6474 ArithmeticCost *= LT.first - 1;
6475 }
6476
6477 // FIXME: These assume a naive kshift+binop lowering, which is probably
6478 // conservative in most cases.
6479 static const CostKindTblEntry AVX512BoolReduction[] = {
6480 { ISD::AND, MVT::v2i1, { 3, 3, 3, 3} },
6481 { ISD::AND, MVT::v4i1, { 5, 5, 5, 5} },
6482 { ISD::AND, MVT::v8i1, { 7, 7, 7, 7} },
6483 { ISD::AND, MVT::v16i1, { 9, 9, 9, 9} },
6484 { ISD::AND, MVT::v32i1, {11,11,11,11} },
6485 { ISD::AND, MVT::v64i1, {13,13,13,13} },
6486 { ISD::OR, MVT::v2i1, { 3, 3, 3, 3} },
6487 { ISD::OR, MVT::v4i1, { 5, 5, 5, 5} },
6488 { ISD::OR, MVT::v8i1, { 7, 7, 7, 7} },
6489 { ISD::OR, MVT::v16i1, { 9, 9, 9, 9} },
6490 { ISD::OR, MVT::v32i1, {11,11,11,11} },
6491 { ISD::OR, MVT::v64i1, {13,13,13,13} },
6492 };
6493
6494 static const CostKindTblEntry AVX2BoolReduction[] = {
6495 { ISD::AND, MVT::v16i16, { 2, 2, 2, 2} }, // vpmovmskb + cmp
6496 { ISD::AND, MVT::v32i8, { 2, 2, 2, 2} }, // vpmovmskb + cmp
6497 { ISD::OR, MVT::v16i16, { 2, 2, 2, 2} }, // vpmovmskb + cmp
6498 { ISD::OR, MVT::v32i8, { 2, 2, 2, 2} }, // vpmovmskb + cmp
6499 };
6500
6501 static const CostKindTblEntry AVX1BoolReduction[] = {
6502 { ISD::AND, MVT::v4i64, {2, 2, 2, 2} }, // vmovmskpd + cmp
6503 { ISD::AND, MVT::v8i32, {2, 2, 2, 2} }, // vmovmskps + cmp
6504 { ISD::AND, MVT::v16i16, {4, 4, 4, 4} }, // vextractf128 + vpand + vpmovmskb + cmp
6505 { ISD::AND, MVT::v32i8, {4, 4, 4, 4} }, // vextractf128 + vpand + vpmovmskb + cmp
6506 { ISD::OR, MVT::v4i64, {2, 2, 2, 2} }, // vmovmskpd + cmp
6507 { ISD::OR, MVT::v8i32, {2, 2, 2, 2} }, // vmovmskps + cmp
6508 { ISD::OR, MVT::v16i16, {4, 4, 4, 4} }, // vextractf128 + vpor + vpmovmskb + cmp
6509 { ISD::OR, MVT::v32i8, {4, 4, 4, 4} }, // vextractf128 + vpor + vpmovmskb + cmp
6510 };
6511
6512 static const CostKindTblEntry SSE2BoolReduction[] = {
6513 { ISD::AND, MVT::v2i64, {2, 2, 2, 2} }, // movmskpd + cmp
6514 { ISD::AND, MVT::v4i32, {2, 2, 2, 2} }, // movmskps + cmp
6515 { ISD::AND, MVT::v8i16, {2, 2, 2, 2} }, // pmovmskb + cmp
6516 { ISD::AND, MVT::v16i8, {2, 2, 2, 2} }, // pmovmskb + cmp
6517 { ISD::OR, MVT::v2i64, {2, 2, 2, 2} }, // movmskpd + cmp
6518 { ISD::OR, MVT::v4i32, {2, 2, 2, 2} }, // movmskps + cmp
6519 { ISD::OR, MVT::v8i16, {2, 2, 2, 2} }, // pmovmskb + cmp
6520 { ISD::OR, MVT::v16i8, {2, 2, 2, 2} }, // pmovmskb + cmp
6521 };
6522
6523 // Handle bool allof/anyof vXi1 patterns before we check legal types.
6524 if (ValVTy->getElementType()->isIntegerTy(1)) {
6525 if (ISD == ISD::ADD) {
6526 // vXi1 addition reduction will bitcast to scalar and perform a popcount.
6527 auto *IntTy = IntegerType::getIntNTy(ValVTy->getContext(),
6528 ValVTy->getNumElements());
6529 IntrinsicCostAttributes ICA(Intrinsic::ctpop, IntTy, {IntTy});
6530 return getCastInstrCost(Instruction::BitCast, IntTy, ValVTy,
6532 CostKind) +
6534 }
6535
6536 if (ST->hasAVX512())
6537 if (const auto *Entry = CostTableLookup(AVX512BoolReduction, ISD, MTy))
6538 if (auto KindCost = Entry->Cost[CostKind])
6539 return ArithmeticCost + *KindCost;
6540 if (ST->hasAVX2())
6541 if (const auto *Entry = CostTableLookup(AVX2BoolReduction, ISD, MTy))
6542 if (auto KindCost = Entry->Cost[CostKind])
6543 return ArithmeticCost + *KindCost;
6544 if (ST->hasAVX())
6545 if (const auto *Entry = CostTableLookup(AVX1BoolReduction, ISD, MTy))
6546 if (auto KindCost = Entry->Cost[CostKind])
6547 return ArithmeticCost + *KindCost;
6548 if (ST->hasSSE2())
6549 if (const auto *Entry = CostTableLookup(SSE2BoolReduction, ISD, MTy))
6550 if (auto KindCost = Entry->Cost[CostKind])
6551 return ArithmeticCost + *KindCost;
6552
6553 return BaseT::getArithmeticReductionCost(Opcode, ValVTy, FMF, CostKind);
6554 }
6555
6556 // Special case: vXi8 mul reductions are performed as vXi16.
6557 if (ISD == ISD::MUL && MTy.getScalarType() == MVT::i8) {
6558 auto *WideSclTy = IntegerType::get(ValVTy->getContext(), 16);
6559 auto *WideVecTy = FixedVectorType::get(WideSclTy, ValVTy->getNumElements());
6560 return getCastInstrCost(Instruction::ZExt, WideVecTy, ValTy,
6562 CostKind) +
6563 getArithmeticReductionCost(Opcode, WideVecTy, FMF, CostKind);
6564 }
6565
6566 if (ST->useSLMArithCosts())
6567 if (const auto *Entry = CostTableLookup(SLMCostTbl, ISD, MTy))
6568 if (auto KindCost = Entry->Cost[CostKind])
6569 return ArithmeticCost + *KindCost;
6570
6571 if (ST->hasBWI())
6572 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
6573 if (auto KindCost = Entry->Cost[CostKind])
6574 return ArithmeticCost + *KindCost;
6575
6576 if (ST->hasAVX512())
6577 if (const auto *Entry = CostTableLookup(AVX512FCostTbl, ISD, MTy))
6578 if (auto KindCost = Entry->Cost[CostKind])
6579 return ArithmeticCost + *KindCost;
6580
6581 if (ST->hasAVX2())
6582 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
6583 if (auto KindCost = Entry->Cost[CostKind])
6584 return ArithmeticCost + *KindCost;
6585
6586 if (ST->hasAVX())
6587 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
6588 if (auto KindCost = Entry->Cost[CostKind])
6589 return ArithmeticCost + *KindCost;
6590
6591 if (ST->hasSSE2())
6592 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
6593 if (auto KindCost = Entry->Cost[CostKind])
6594 return ArithmeticCost + *KindCost;
6595
6596 unsigned NumVecElts = ValVTy->getNumElements();
6597 unsigned ScalarSize = ValVTy->getScalarSizeInBits();
6598
6599 // Special case power of 2 reductions where the scalar type isn't changed
6600 // by type legalization.
6601 if (!isPowerOf2_32(NumVecElts) || ScalarSize != MTy.getScalarSizeInBits())
6602 return BaseT::getArithmeticReductionCost(Opcode, ValVTy, FMF, CostKind);
6603
6604 InstructionCost ReductionCost = 0;
6605
6606 auto *Ty = ValVTy;
6607 if (LT.first != 1 && MTy.isVector() &&
6608 MTy.getVectorNumElements() < ValVTy->getNumElements()) {
6609 // Type needs to be split. We need LT.first - 1 arithmetic ops.
6610 Ty = FixedVectorType::get(ValVTy->getElementType(),
6611 MTy.getVectorNumElements());
6612 ReductionCost = getArithmeticInstrCost(Opcode, Ty, CostKind);
6613 ReductionCost *= LT.first - 1;
6614 NumVecElts = MTy.getVectorNumElements();
6615 }
6616
6617 // Now handle reduction with the legal type, taking into account size changes
6618 // at each level.
6619 while (NumVecElts > 1) {
6620 // Determine the size of the remaining vector we need to reduce.
6621 unsigned Size = NumVecElts * ScalarSize;
6622 NumVecElts /= 2;
6623 // If we're reducing from 256/512 bits, use an extract_subvector.
6624 if (Size > 128) {
6625 auto *SubTy = FixedVectorType::get(ValVTy->getElementType(), NumVecElts);
6626 ReductionCost += getShuffleCost(TTI::SK_ExtractSubvector, Ty, Ty,
6627 CostKind, {}, NumVecElts, SubTy);
6628 Ty = SubTy;
6629 } else if (Size == 128) {
6630 // Reducing from 128 bits is a permute of v2f64/v2i64.
6631 FixedVectorType *ShufTy;
6632 if (ValVTy->isFloatingPointTy())
6633 ShufTy =
6634 FixedVectorType::get(Type::getDoubleTy(ValVTy->getContext()), 2);
6635 else
6636 ShufTy =
6637 FixedVectorType::get(Type::getInt64Ty(ValVTy->getContext()), 2);
6638 ReductionCost += getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, ShufTy,
6639 CostKind, {}, 0, nullptr);
6640 } else if (Size == 64) {
6641 // Reducing from 64 bits is a shuffle of v4f32/v4i32.
6642 FixedVectorType *ShufTy;
6643 if (ValVTy->isFloatingPointTy())
6644 ShufTy =
6645 FixedVectorType::get(Type::getFloatTy(ValVTy->getContext()), 4);
6646 else
6647 ShufTy =
6648 FixedVectorType::get(Type::getInt32Ty(ValVTy->getContext()), 4);
6649 ReductionCost += getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, ShufTy,
6650 CostKind, {}, 0, nullptr);
6651 } else {
6652 // Reducing from smaller size is a shift by immediate.
6653 auto *ShiftTy = FixedVectorType::get(
6654 Type::getIntNTy(ValVTy->getContext(), Size), 128 / Size);
6655 ReductionCost += getArithmeticInstrCost(
6656 Instruction::LShr, ShiftTy, CostKind,
6659 }
6660
6661 // Add the arithmetic op for this level.
6662 ReductionCost += getArithmeticInstrCost(Opcode, Ty, CostKind);
6663 }
6664
6665 // Add the final extract element to the cost.
6666 return ReductionCost + getVectorInstrCost(Instruction::ExtractElement, Ty,
6667 CostKind, 0, nullptr, nullptr,
6669}
6670
6673 FastMathFlags FMF) const {
6674 IntrinsicCostAttributes ICA(IID, Ty, {Ty, Ty}, FMF);
6675 return getIntrinsicInstrCost(ICA, CostKind);
6676}
6677
6680 FastMathFlags FMF,
6682 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
6683
6684 MVT MTy = LT.second;
6685
6687 if (ValTy->isIntOrIntVectorTy()) {
6688 ISD = (IID == Intrinsic::umin || IID == Intrinsic::umax) ? ISD::UMIN
6689 : ISD::SMIN;
6690 } else {
6691 assert(ValTy->isFPOrFPVectorTy() &&
6692 "Expected float point or integer vector type.");
6693 ISD = (IID == Intrinsic::minnum || IID == Intrinsic::maxnum)
6694 ? ISD::FMINNUM
6695 : ISD::FMINIMUM;
6696 }
6697
6698 // We use llvm-mca across all supported CPUs to measure the cost stats.
6699 static const CostKindTblEntry SSE2CostTbl[] = {
6700 {ISD::SMIN, MVT::v2i64, {3, 4, 5, 6}},
6701 {ISD::UMIN, MVT::v2i64, {3, 4, 5, 6}},
6702 {ISD::SMIN, MVT::v2i32, {2, 2, 5, 6}},
6703 {ISD::UMIN, MVT::v2i32, {2, 2, 5, 6}},
6704 {ISD::SMIN, MVT::v4i32, {3, 7,11,12}},
6705 {ISD::UMIN, MVT::v4i32, {4, 7,14,15}},
6706 {ISD::SMIN, MVT::v2i16, {2, 3, 4, 4}},
6707 {ISD::UMIN, MVT::v2i16, {2, 3, 4, 6}},
6708 {ISD::SMIN, MVT::v4i16, {3, 5, 6, 6}},
6709 {ISD::UMIN, MVT::v4i16, {3, 5, 8, 10}},
6710 {ISD::SMIN, MVT::v8i16, {3, 8, 8, 8}},
6711 {ISD::UMIN, MVT::v8i16, {4, 8,12,14}},
6712 {ISD::SMIN, MVT::v2i8, {2, 3, 5, 6}},
6713 {ISD::UMIN, MVT::v2i8, {2, 3, 4, 4}},
6714 {ISD::SMIN, MVT::v4i8, {4, 6,12,13}},
6715 {ISD::UMIN, MVT::v4i8, {3, 6, 7, 7}},
6716 {ISD::SMIN, MVT::v8i8, {5, 9,18,19}},
6717 {ISD::UMIN, MVT::v8i8, {4, 8, 9, 9}},
6718 {ISD::SMIN, MVT::v16i8, {7,13,24,25}},
6719 {ISD::UMIN, MVT::v16i8, {3,10,11,11}},
6720 };
6721
6722 static const CostKindTblEntry SSE41CostTbl[] = {
6723 {ISD::SMIN, MVT::v2i64, {3, 4, 4, 6}},
6724 {ISD::UMIN, MVT::v2i64, {3, 4, 4, 6}},
6725 {ISD::SMIN, MVT::v2i32, {2, 2, 3, 3}},
6726 {ISD::UMIN, MVT::v2i32, {2, 2, 3, 3}},
6727 {ISD::SMIN, MVT::v4i32, {3, 4, 5, 5}},
6728 {ISD::UMIN, MVT::v4i32, {3, 4, 5, 5}},
6729 {ISD::UMIN, MVT::v2i16, {2, 3, 4, 4}},
6730 {ISD::SMIN, MVT::v4i16, {3, 5, 6, 6}},
6731 {ISD::UMIN, MVT::v4i16, {3, 5, 6, 6}},
6732 {ISD::SMIN, MVT::v8i16, {2, 8, 4, 5}},
6733 {ISD::UMIN, MVT::v8i16, {2, 5, 2, 2}},
6734 {ISD::SMIN, MVT::v2i8, {2, 3, 4, 4}},
6735 {ISD::SMIN, MVT::v4i8, {3, 6, 7, 7}},
6736 {ISD::SMIN, MVT::v8i8, {4, 8, 9, 9}},
6737 {ISD::SMIN, MVT::v16i8, {3,10, 7, 8}},
6738 {ISD::UMIN, MVT::v16i8, {3, 8, 5, 5}},
6739 };
6740
6741 static const CostKindTblEntry AVX1CostTbl[] = {
6742 {ISD::SMIN, MVT::v4i64, {5,11, 7,10}},
6743 {ISD::UMIN, MVT::v4i64, {6,12,10,13}},
6744 {ISD::SMIN, MVT::v8i32, {4, 9, 7, 7}},
6745 {ISD::UMIN, MVT::v8i32, {4, 9, 7, 7}},
6746 {ISD::SMIN, MVT::v16i16, {3,15, 6, 7}},
6747 {ISD::UMIN, MVT::v16i16, {2, 9, 4, 4}},
6748 {ISD::SMIN, MVT::v32i8, {4,17, 8, 9}},
6749 {ISD::UMIN, MVT::v32i8, {3,11, 6, 6}},
6750 };
6751
6752 static const CostKindTblEntry AVX2CostTbl[] = {
6753 {ISD::SMIN, MVT::v4i64, {4,11, 7,10}},
6754 {ISD::UMIN, MVT::v4i64, {4,12,10,13}},
6755 {ISD::SMIN, MVT::v2i32, {1, 2, 3, 3}},
6756 {ISD::UMIN, MVT::v2i32, {1, 2, 3, 3}},
6757 {ISD::UMIN, MVT::v4i32, {2, 4, 5, 5}},
6758 {ISD::SMIN, MVT::v4i32, {2, 4, 5, 5}},
6759 {ISD::SMIN, MVT::v8i32, {3, 9, 7, 7}},
6760 {ISD::UMIN, MVT::v8i32, {3, 9, 7, 7}},
6761 {ISD::SMIN, MVT::v4i16, {2, 4, 5, 5}},
6762 {ISD::UMIN, MVT::v4i16, {2, 4, 5, 5}},
6763 {ISD::SMIN, MVT::v16i16, {2,15, 6, 7}},
6764 {ISD::SMIN, MVT::v8i8, {3, 6, 7, 7}},
6765 {ISD::UMIN, MVT::v8i8, {3, 6, 7, 7}},
6766 {ISD::SMIN, MVT::v32i8, {3,17, 8, 9}},
6767 };
6768
6769 static const CostKindTblEntry AVX512FCostTbl[] = {
6770 {ISD::SMIN, MVT::v2i64, {2, 4, 3, 3}},
6771 {ISD::UMIN, MVT::v2i64, {2, 4, 3, 3}},
6772 {ISD::SMIN, MVT::v4i64, {3,10, 5, 5}},
6773 {ISD::UMIN, MVT::v4i64, {3,10, 5, 5}},
6774 {ISD::SMIN, MVT::v8i64, {5,16, 7, 7}},
6775 {ISD::UMIN, MVT::v8i64, {5,16, 7, 7}},
6776 {ISD::SMIN, MVT::v16i32, {4,12, 9, 9}},
6777 {ISD::UMIN, MVT::v16i32, {4,12, 9, 9}},
6778 };
6779
6780 static const CostKindTblEntry AVX512BWCostTbl[] = {
6781 {ISD::SMIN, MVT::v2i16, {1, 2, 3, 3}},
6782 {ISD::UMIN, MVT::v2i16, {1, 2, 3, 3}},
6783 {ISD::SMIN, MVT::v32i16, {2,19, 8, 9}},
6784 {ISD::UMIN, MVT::v32i16, {2,12, 6, 6}},
6785 {ISD::SMIN, MVT::v2i8, {1, 2, 3, 3}},
6786 {ISD::UMIN, MVT::v2i8, {1, 2, 3, 3}},
6787 {ISD::SMIN, MVT::v4i8, {2, 4, 5, 5}},
6788 {ISD::UMIN, MVT::v4i8, {2, 4, 5, 5}},
6789 {ISD::SMIN, MVT::v16i8, {2,10, 6, 7}},
6790 {ISD::UMIN, MVT::v16i8, {2, 6, 4, 4}},
6791 {ISD::SMIN, MVT::v32i8, {2,17, 8, 9}},
6792 {ISD::UMIN, MVT::v32i8, {2,10, 6, 6}},
6793 {ISD::SMIN, MVT::v64i8, {2,21,10,11}},
6794 {ISD::UMIN, MVT::v64i8, {2,14, 8, 8}},
6795 };
6796
6797 // Before legalizing the type, give a chance to look up illegal narrow types
6798 // in the table.
6799 // FIXME: Is there a better way to do this?
6800 EVT VT = TLI->getValueType(DL, ValTy);
6801 if (VT.isSimple()) {
6802 MVT MTy = VT.getSimpleVT();
6803 if (ST->hasBWI())
6804 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
6805 if (auto KindCost = Entry->Cost[CostKind])
6806 return *KindCost;
6807
6808 if (ST->hasAVX512())
6809 if (const auto *Entry = CostTableLookup(AVX512FCostTbl, ISD, MTy))
6810 if (auto KindCost = Entry->Cost[CostKind])
6811 return *KindCost;
6812
6813 if (ST->hasAVX2())
6814 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
6815 if (auto KindCost = Entry->Cost[CostKind])
6816 return *KindCost;
6817
6818 if (ST->hasAVX())
6819 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
6820 if (auto KindCost = Entry->Cost[CostKind])
6821 return *KindCost;
6822
6823 if (ST->hasSSE41())
6824 if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
6825 if (auto KindCost = Entry->Cost[CostKind])
6826 return *KindCost;
6827
6828 if (ST->hasSSE2())
6829 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
6830 if (auto KindCost = Entry->Cost[CostKind])
6831 return *KindCost;
6832 }
6833
6834 auto *ValVTy = cast<FixedVectorType>(ValTy);
6835 unsigned NumVecElts = ValVTy->getNumElements();
6836
6837 auto *Ty = ValVTy;
6838 InstructionCost MinMaxCost = 0;
6839 if (LT.first != 1 && MTy.isVector() &&
6840 MTy.getVectorNumElements() < ValVTy->getNumElements()) {
6841 // Type needs to be split. We need LT.first - 1 operations ops.
6842 Ty = FixedVectorType::get(ValVTy->getElementType(),
6843 MTy.getVectorNumElements());
6844 MinMaxCost = getMinMaxCost(IID, Ty, CostKind, FMF);
6845 MinMaxCost *= LT.first - 1;
6846 NumVecElts = MTy.getVectorNumElements();
6847 }
6848
6849 if (ST->hasBWI())
6850 if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
6851 if (auto KindCost = Entry->Cost[CostKind])
6852 return MinMaxCost + *KindCost;
6853
6854 if (ST->hasAVX512())
6855 if (const auto *Entry = CostTableLookup(AVX512FCostTbl, ISD, MTy))
6856 if (auto KindCost = Entry->Cost[CostKind])
6857 return MinMaxCost + *KindCost;
6858
6859 if (ST->hasAVX2())
6860 if (const auto *Entry = CostTableLookup(AVX2CostTbl, ISD, MTy))
6861 if (auto KindCost = Entry->Cost[CostKind])
6862 return MinMaxCost + *KindCost;
6863
6864 if (ST->hasAVX())
6865 if (const auto *Entry = CostTableLookup(AVX1CostTbl, ISD, MTy))
6866 if (auto KindCost = Entry->Cost[CostKind])
6867 return MinMaxCost + *KindCost;
6868
6869 if (ST->hasSSE41())
6870 if (const auto *Entry = CostTableLookup(SSE41CostTbl, ISD, MTy))
6871 if (auto KindCost = Entry->Cost[CostKind])
6872 return MinMaxCost + *KindCost;
6873
6874 if (ST->hasSSE2())
6875 if (const auto *Entry = CostTableLookup(SSE2CostTbl, ISD, MTy))
6876 if (auto KindCost = Entry->Cost[CostKind])
6877 return MinMaxCost + *KindCost;
6878
6879 unsigned ScalarSize = ValTy->getScalarSizeInBits();
6880
6881 // Special case power of 2 reductions where the scalar type isn't changed
6882 // by type legalization.
6883 if (!isPowerOf2_32(ValVTy->getNumElements()) ||
6884 ScalarSize != MTy.getScalarSizeInBits())
6885 return BaseT::getMinMaxReductionCost(IID, ValTy, FMF, CostKind);
6886
6887 // Now handle reduction with the legal type, taking into account size changes
6888 // at each level.
6889 while (NumVecElts > 1) {
6890 // Determine the size of the remaining vector we need to reduce.
6891 unsigned Size = NumVecElts * ScalarSize;
6892 NumVecElts /= 2;
6893 // If we're reducing from 256/512 bits, use an extract_subvector.
6894 if (Size > 128) {
6895 auto *SubTy = FixedVectorType::get(ValVTy->getElementType(), NumVecElts);
6896 MinMaxCost += getShuffleCost(TTI::SK_ExtractSubvector, Ty, Ty, CostKind,
6897 {}, NumVecElts, SubTy);
6898 Ty = SubTy;
6899 } else if (Size == 128) {
6900 // Reducing from 128 bits is a permute of v2f64/v2i64.
6901 VectorType *ShufTy;
6902 if (ValTy->isFloatingPointTy())
6903 ShufTy =
6905 else
6906 ShufTy = FixedVectorType::get(Type::getInt64Ty(ValTy->getContext()), 2);
6907 MinMaxCost += getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, ShufTy,
6908 CostKind, {}, 0, nullptr);
6909 } else if (Size == 64) {
6910 // Reducing from 64 bits is a shuffle of v4f32/v4i32.
6911 FixedVectorType *ShufTy;
6912 if (ValTy->isFloatingPointTy())
6913 ShufTy = FixedVectorType::get(Type::getFloatTy(ValTy->getContext()), 4);
6914 else
6915 ShufTy = FixedVectorType::get(Type::getInt32Ty(ValTy->getContext()), 4);
6916 MinMaxCost += getShuffleCost(TTI::SK_PermuteSingleSrc, ShufTy, ShufTy,
6917 CostKind, {}, 0, nullptr);
6918 } else {
6919 // Reducing from smaller size is a shift by immediate.
6920 auto *ShiftTy = FixedVectorType::get(
6921 Type::getIntNTy(ValTy->getContext(), Size), 128 / Size);
6922 MinMaxCost += getArithmeticInstrCost(
6923 Instruction::LShr, ShiftTy, TTI::TCK_RecipThroughput,
6926 }
6927
6928 // Add the arithmetic op for this level.
6929 MinMaxCost += getMinMaxCost(IID, Ty, CostKind, FMF);
6930 }
6931
6932 // Add the final extract element to the cost.
6933 return MinMaxCost + getVectorInstrCost(Instruction::ExtractElement, Ty,
6934 CostKind, 0, nullptr, nullptr,
6936}
6937
6938/// Calculate the cost of materializing a 64-bit value. This helper
6939/// method might only calculate a fraction of a larger immediate. Therefore it
6940/// is valid to return a cost of ZERO.
6942 if (Val == 0)
6943 return TTI::TCC_Free;
6944
6945 if (isInt<32>(Val))
6946 return TTI::TCC_Basic;
6947
6948 return 2 * TTI::TCC_Basic;
6949}
6950
6953 assert(Ty->isIntegerTy());
6954
6955 unsigned BitSize = Ty->getPrimitiveSizeInBits();
6956 if (BitSize == 0)
6957 return ~0U;
6958
6959 // Never hoist constants larger than 128bit, because this might lead to
6960 // incorrect code generation or assertions in codegen.
6961 // Fixme: Create a cost model for types larger than i128 once the codegen
6962 // issues have been fixed.
6963 if (BitSize > 128)
6964 return TTI::TCC_Free;
6965
6966 if (Imm == 0)
6967 return TTI::TCC_Free;
6968
6969 // Sign-extend all constants to a multiple of 64-bit.
6970 APInt ImmVal = Imm;
6971 if (BitSize % 64 != 0)
6972 ImmVal = Imm.sext(alignTo(BitSize, 64));
6973
6974 // Split the constant into 64-bit chunks and calculate the cost for each
6975 // chunk.
6977 for (unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
6978 APInt Tmp = ImmVal.ashr(ShiftVal).sextOrTrunc(64);
6979 int64_t Val = Tmp.getSExtValue();
6980 Cost += getIntImmCost(Val);
6981 }
6982 // We need at least one instruction to materialize the constant.
6983 return std::max<InstructionCost>(1, Cost);
6984}
6985
6987 const APInt &Imm, Type *Ty,
6989 Instruction *Inst) const {
6990 assert(Ty->isIntegerTy());
6991
6992 unsigned BitSize = Ty->getPrimitiveSizeInBits();
6993 unsigned ImmBitWidth = Imm.getBitWidth();
6994
6995 // There is no cost model for constants with a bit size of 0. Return TCC_Free
6996 // here, so that constant hoisting will ignore this constant.
6997 if (BitSize == 0)
6998 return TTI::TCC_Free;
6999
7000 unsigned ImmIdx = ~0U;
7001 switch (Opcode) {
7002 default:
7003 return TTI::TCC_Free;
7004 case Instruction::GetElementPtr:
7005 // Always hoist the base address of a GetElementPtr. This prevents the
7006 // creation of new constants for every base constant that gets constant
7007 // folded with the offset.
7008 if (Idx == 0)
7009 return 2 * TTI::TCC_Basic;
7010 return TTI::TCC_Free;
7011 case Instruction::Store:
7012 ImmIdx = 0;
7013 break;
7014 case Instruction::ICmp:
7015 // This is an imperfect hack to prevent constant hoisting of
7016 // compares that might be trying to check if a 64-bit value fits in
7017 // 32-bits. The backend can optimize these cases using a right shift by 32.
7018 // There are other predicates and immediates the backend can use shifts for.
7019 if (Idx == 1 && ImmBitWidth == 64) {
7020 uint64_t ImmVal = Imm.getZExtValue();
7021 if (ImmVal == 0x100000000ULL || ImmVal == 0xffffffff)
7022 return TTI::TCC_Free;
7023
7024 if (auto *Cmp = dyn_cast_or_null<CmpInst>(Inst)) {
7025 if (Cmp->isEquality()) {
7026 KnownBits Known = computeKnownBits(Cmp->getOperand(0), DL);
7027 if (Known.countMinTrailingZeros() >= 32)
7028 return TTI::TCC_Free;
7029 }
7030 }
7031 }
7032 ImmIdx = 1;
7033 break;
7034 case Instruction::And:
7035 // We support 64-bit ANDs with immediates with 32-bits of leading zeroes
7036 // by using a 32-bit operation with implicit zero extension. Detect such
7037 // immediates here as the normal path expects bit 31 to be sign extended.
7038 if (Idx == 1 && ImmBitWidth == 64 && Imm.isIntN(32))
7039 return TTI::TCC_Free;
7040 // If we have BMI then we can use BEXTR/BZHI to mask out upper i64 bits.
7041 if (Idx == 1 && ImmBitWidth == 64 && ST->is64Bit() && ST->hasBMI() &&
7042 Imm.isMask())
7043 return X86TTIImpl::getIntImmCost(ST->hasBMI2() ? 255 : 65535);
7044 ImmIdx = 1;
7045 break;
7046 case Instruction::Add:
7047 case Instruction::Sub:
7048 // For add/sub, we can use the opposite instruction for INT32_MIN.
7049 if (Idx == 1 && ImmBitWidth == 64 && Imm.getZExtValue() == 0x80000000)
7050 return TTI::TCC_Free;
7051 ImmIdx = 1;
7052 break;
7053 case Instruction::UDiv:
7054 case Instruction::SDiv:
7055 case Instruction::URem:
7056 case Instruction::SRem:
7057 // Division by constant is typically expanded later into a different
7058 // instruction sequence. This completely changes the constants.
7059 // Report them as "free" to stop ConstantHoist from marking them as opaque.
7060 return TTI::TCC_Free;
7061 case Instruction::Mul:
7062 case Instruction::Or:
7063 case Instruction::Xor:
7064 ImmIdx = 1;
7065 break;
7066 // Always return TCC_Free for the shift value of a shift instruction.
7067 case Instruction::Shl:
7068 case Instruction::LShr:
7069 case Instruction::AShr:
7070 if (Idx == 1)
7071 return TTI::TCC_Free;
7072 break;
7073 case Instruction::Trunc:
7074 case Instruction::ZExt:
7075 case Instruction::SExt:
7076 case Instruction::IntToPtr:
7077 case Instruction::PtrToInt:
7078 case Instruction::BitCast:
7079 case Instruction::PHI:
7080 case Instruction::Call:
7081 case Instruction::Select:
7082 case Instruction::Ret:
7083 case Instruction::Load:
7084 break;
7085 }
7086
7087 if (Idx == ImmIdx) {
7088 uint64_t NumConstants = divideCeil(BitSize, 64);
7090 return (Cost <= NumConstants * TTI::TCC_Basic)
7091 ? static_cast<int>(TTI::TCC_Free)
7092 : Cost;
7093 }
7094
7096}
7097
7100 const APInt &Imm, Type *Ty,
7102 assert(Ty->isIntegerTy());
7103
7104 unsigned BitSize = Ty->getPrimitiveSizeInBits();
7105 // There is no cost model for constants with a bit size of 0. Return TCC_Free
7106 // here, so that constant hoisting will ignore this constant.
7107 if (BitSize == 0)
7108 return TTI::TCC_Free;
7109
7110 switch (IID) {
7111 default:
7112 return TTI::TCC_Free;
7113 case Intrinsic::sadd_with_overflow:
7114 case Intrinsic::uadd_with_overflow:
7115 case Intrinsic::ssub_with_overflow:
7116 case Intrinsic::usub_with_overflow:
7117 case Intrinsic::smul_with_overflow:
7118 case Intrinsic::umul_with_overflow:
7119 if ((Idx == 1) && Imm.getBitWidth() <= 64 && Imm.isSignedIntN(32))
7120 return TTI::TCC_Free;
7121 break;
7122 case Intrinsic::experimental_stackmap:
7123 if ((Idx < 2) || (Imm.getBitWidth() <= 64 && Imm.isSignedIntN(64)))
7124 return TTI::TCC_Free;
7125 break;
7126 case Intrinsic::experimental_patchpoint_void:
7127 case Intrinsic::experimental_patchpoint:
7128 if ((Idx < 4) || (Imm.getBitWidth() <= 64 && Imm.isSignedIntN(64)))
7129 return TTI::TCC_Free;
7130 break;
7131 }
7133}
7134
7137 const Instruction *I) const {
7139 return Opcode == Instruction::PHI ? TTI::TCC_Free : TTI::TCC_Basic;
7140 // Branches are assumed to be predicted.
7141 return TTI::TCC_Free;
7142}
7143
7144int X86TTIImpl::getGatherOverhead() const {
7145 // Some CPUs have more overhead for gather. The specified overhead is relative
7146 // to the Load operation. "2" is the number provided by Intel architects. This
7147 // parameter is used for cost estimation of Gather Op and comparison with
7148 // other alternatives.
7149 // TODO: Remove the explicit hasAVX512()?, That would mean we would only
7150 // enable gather with a -march.
7151 if (ST->hasAVX512() || (ST->hasAVX2() && ST->hasFastGather()))
7152 return 2;
7153
7154 return 1024;
7155}
7156
7157int X86TTIImpl::getScatterOverhead() const {
7158 if (ST->hasAVX512())
7159 return 2;
7160
7161 return 1024;
7162}
7163
7164// Return an average cost of Gather / Scatter instruction, maybe improved later.
7165InstructionCost X86TTIImpl::getGSVectorCost(unsigned Opcode,
7167 Type *SrcVTy, const Value *Ptr,
7168 Align Alignment,
7169 unsigned AddressSpace) const {
7170
7171 assert(isa<VectorType>(SrcVTy) && "Unexpected type in getGSVectorCost");
7172 unsigned VF = cast<FixedVectorType>(SrcVTy)->getNumElements();
7173
7174 // Try to reduce index size from 64 bit (default for GEP)
7175 // to 32. It is essential for VF 16. If the index can't be reduced to 32, the
7176 // operation will use 16 x 64 indices which do not fit in a zmm and needs
7177 // to split. Also check that the base pointer is the same for all lanes,
7178 // and that there's at most one variable index.
7179 auto getIndexSizeInBits = [](const Value *Ptr, const DataLayout &DL) {
7180 unsigned IndexSize = DL.getPointerSizeInBits();
7181 const GetElementPtrInst *GEP = dyn_cast_or_null<GetElementPtrInst>(Ptr);
7182 if (IndexSize < 64 || !GEP)
7183 return IndexSize;
7184
7185 unsigned NumOfVarIndices = 0;
7186 const Value *Ptrs = GEP->getPointerOperand();
7187 if (Ptrs->getType()->isVectorTy() && !getSplatValue(Ptrs))
7188 return IndexSize;
7189 for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I) {
7190 if (isa<Constant>(GEP->getOperand(I)))
7191 continue;
7192 Type *IndxTy = GEP->getOperand(I)->getType();
7193 if (auto *IndexVTy = dyn_cast<VectorType>(IndxTy))
7194 IndxTy = IndexVTy->getElementType();
7195 if ((IndxTy->getPrimitiveSizeInBits() == 64 &&
7196 !isa<SExtInst>(GEP->getOperand(I))) ||
7197 ++NumOfVarIndices > 1)
7198 return IndexSize; // 64
7199 }
7200 return (unsigned)32;
7201 };
7202
7203 // Trying to reduce IndexSize to 32 bits for vector 16.
7204 // By default the IndexSize is equal to pointer size.
7205 unsigned IndexSize = (ST->hasAVX512() && VF >= 16)
7206 ? getIndexSizeInBits(Ptr, DL)
7207 : DL.getPointerSizeInBits();
7208
7209 auto *IndexVTy = FixedVectorType::get(
7210 IntegerType::get(SrcVTy->getContext(), IndexSize), VF);
7211 std::pair<InstructionCost, MVT> IdxsLT = getTypeLegalizationCost(IndexVTy);
7212 std::pair<InstructionCost, MVT> SrcLT = getTypeLegalizationCost(SrcVTy);
7213 InstructionCost::CostType SplitFactor =
7214 std::max(IdxsLT.first, SrcLT.first).getValue();
7215 if (SplitFactor > 1) {
7216 // Handle splitting of vector of pointers
7217 auto *SplitSrcTy =
7218 FixedVectorType::get(SrcVTy->getScalarType(), VF / SplitFactor);
7219 return SplitFactor * getGSVectorCost(Opcode, CostKind, SplitSrcTy, Ptr,
7220 Alignment, AddressSpace);
7221 }
7222
7223 // If we didn't split, this will be a single gather/scatter instruction.
7225 return 1;
7226
7227 // The gather / scatter cost is given by Intel architects. It is a rough
7228 // number since we are looking at one instruction in a time.
7229 const int GSOverhead = (Opcode == Instruction::Load) ? getGatherOverhead()
7230 : getScatterOverhead();
7231 return GSOverhead + VF * getMemoryOpCost(Opcode, SrcVTy->getScalarType(),
7232 Alignment, AddressSpace, CostKind);
7233}
7234
7235/// Calculate the cost of Gather / Scatter operation
7239 bool IsLoad = MICA.getID() == Intrinsic::masked_gather ||
7240 MICA.getID() == Intrinsic::vp_gather;
7241 unsigned Opcode = IsLoad ? Instruction::Load : Instruction::Store;
7242 Type *SrcVTy = MICA.getDataType();
7243 const Value *Ptr = MICA.getPointer();
7244 Align Alignment = MICA.getAlignment();
7245 if ((Opcode == Instruction::Load &&
7246 (!isLegalMaskedGather(SrcVTy, Align(Alignment)) ||
7248 Align(Alignment)))) ||
7249 (Opcode == Instruction::Store &&
7250 (!isLegalMaskedScatter(SrcVTy, Align(Alignment)) ||
7252 Align(Alignment)))))
7254
7255 assert(SrcVTy->isVectorTy() && "Unexpected data type for Gather/Scatter");
7256 unsigned AddressSpace = MICA.getAddressSpace();
7258 getGSVectorCost(Opcode, CostKind, SrcVTy, Ptr, Alignment, AddressSpace);
7259
7260 // Predicate fanout (see getPredicateFanoutCost); variable mask only.
7261 if (MICA.getVariableMask()) {
7262 auto *MaskVecTy =
7264 cast<FixedVectorType>(SrcVTy)->getNumElements());
7265 Cost += getPredicateFanoutCost(*this, SrcVTy, MaskVecTy);
7266 }
7267 return Cost;
7268}
7269
7271 const TargetTransformInfo::LSRCost &C2) const {
7272 // X86 specific here are "instruction number 1st priority".
7273 return std::tie(C1.Insns, C1.NumRegs, C1.AddRecCost, C1.NumIVMuls,
7274 C1.NumBaseAdds, C1.ScaleCost, C1.ImmCost, C1.SetupCost) <
7275 std::tie(C2.Insns, C2.NumRegs, C2.AddRecCost, C2.NumIVMuls,
7276 C2.NumBaseAdds, C2.ScaleCost, C2.ImmCost, C2.SetupCost);
7277}
7278
7280 return ST->hasMacroFusion() || ST->hasBranchFusion();
7281}
7282
7283static bool isLegalMaskedLoadStore(Type *ScalarTy, const X86Subtarget *ST) {
7284 if (!ST->hasAVX())
7285 return false;
7286
7287 if (ScalarTy->isPointerTy())
7288 return true;
7289
7290 if (ScalarTy->isFloatTy() || ScalarTy->isDoubleTy())
7291 return true;
7292
7293 if (ScalarTy->isHalfTy() && ST->hasBWI())
7294 return true;
7295
7296 if (ScalarTy->isBFloatTy() && ST->hasBF16())
7297 return true;
7298
7299 if (!ScalarTy->isIntegerTy())
7300 return false;
7301
7302 unsigned IntWidth = ScalarTy->getIntegerBitWidth();
7303 return IntWidth == 32 || IntWidth == 64 ||
7304 ((IntWidth == 8 || IntWidth == 16) && ST->hasBWI());
7305}
7306
7308 unsigned AddressSpace,
7309 TTI::MaskKind MaskKind) const {
7310 Type *ScalarTy = DataTy->getScalarType();
7311
7312 // The backend can't handle a single element vector w/o CFCMOV.
7313 if (isa<VectorType>(DataTy) &&
7314 cast<FixedVectorType>(DataTy)->getNumElements() == 1)
7315 return ST->hasCF() &&
7316 hasConditionalLoadStoreForType(ScalarTy, /*IsStore=*/false);
7317
7318 return isLegalMaskedLoadStore(ScalarTy, ST);
7319}
7320
7322 unsigned AddressSpace,
7323 TTI::MaskKind MaskKind) const {
7324 Type *ScalarTy = DataTy->getScalarType();
7325
7326 // The backend can't handle a single element vector w/o CFCMOV.
7327 if (isa<VectorType>(DataTy) &&
7328 cast<FixedVectorType>(DataTy)->getNumElements() == 1)
7329 return ST->hasCF() &&
7330 hasConditionalLoadStoreForType(ScalarTy, /*IsStore=*/true);
7331
7332 return isLegalMaskedLoadStore(ScalarTy, ST);
7333}
7334
7335bool X86TTIImpl::isLegalNTLoad(Type *DataType, Align Alignment) const {
7336 unsigned DataSize = DL.getTypeStoreSize(DataType);
7337 // The only supported nontemporal loads are for aligned vectors of 16 or 32
7338 // bytes. Note that 32-byte nontemporal vector loads are supported by AVX2
7339 // (the equivalent stores only require AVX).
7340 if (Alignment >= DataSize && (DataSize == 16 || DataSize == 32))
7341 return DataSize == 16 ? ST->hasSSE1() : ST->hasAVX2();
7342
7343 return false;
7344}
7345
7346bool X86TTIImpl::isLegalNTStore(Type *DataType, Align Alignment) const {
7347 unsigned DataSize = DL.getTypeStoreSize(DataType);
7348
7349 // SSE4A supports nontemporal stores of float and double at arbitrary
7350 // alignment.
7351 if (ST->hasSSE4A() && (DataType->isFloatTy() || DataType->isDoubleTy()))
7352 return true;
7353
7354 // Besides the SSE4A subtarget exception above, only aligned stores are
7355 // available nontemporaly on any other subtarget. And only stores with a size
7356 // of 4..32 bytes (powers of 2, only) are permitted.
7357 if (Alignment < DataSize || DataSize < 4 || DataSize > 32 ||
7358 !isPowerOf2_32(DataSize))
7359 return false;
7360
7361 // 32-byte vector nontemporal stores are supported by AVX (the equivalent
7362 // loads require AVX2).
7363 if (DataSize == 32)
7364 return ST->hasAVX();
7365 if (DataSize == 16)
7366 return ST->hasSSE1();
7367 return true;
7368}
7369
7371 ElementCount NumElements) const {
7372 // movddup
7373 return ST->hasSSE3() && !NumElements.isScalable() &&
7374 NumElements.getFixedValue() == 2 &&
7375 ElementTy == Type::getDoubleTy(ElementTy->getContext());
7376}
7377
7378bool X86TTIImpl::isLegalMaskedExpandLoad(Type *DataTy, Align Alignment) const {
7379 if (!isa<VectorType>(DataTy))
7380 return false;
7381
7382 if (!ST->hasAVX512())
7383 return false;
7384
7385 // The backend can't handle a single element vector.
7386 if (cast<FixedVectorType>(DataTy)->getNumElements() == 1)
7387 return false;
7388
7389 Type *ScalarTy = cast<VectorType>(DataTy)->getElementType();
7390
7391 if (ScalarTy->isFloatTy() || ScalarTy->isDoubleTy())
7392 return true;
7393
7394 if (!ScalarTy->isIntegerTy())
7395 return false;
7396
7397 unsigned IntWidth = ScalarTy->getIntegerBitWidth();
7398 return IntWidth == 32 || IntWidth == 64 ||
7399 ((IntWidth == 8 || IntWidth == 16) && ST->hasVBMI2());
7400}
7401
7403 Align Alignment) const {
7404 return isLegalMaskedExpandLoad(DataTy, Alignment);
7405}
7406
7407bool X86TTIImpl::supportsGather() const {
7408 // Some CPUs have better gather performance than others.
7409 // TODO: Remove the explicit ST->hasAVX512()?, That would mean we would only
7410 // enable gather with a -march.
7411 return ST->hasAVX512() || (ST->hasFastGather() && ST->hasAVX2());
7412}
7413
7415 Align Alignment) const {
7416 // Gather / Scatter for vector 2 is not profitable on KNL / SKX
7417 // Vector-4 of gather/scatter instruction does not exist on KNL. We can extend
7418 // it to 8 elements, but zeroing upper bits of the mask vector will add more
7419 // instructions. Right now we give the scalar cost of vector-4 for KNL. TODO:
7420 // Check, maybe the gather/scatter instruction is better in the VariableMask
7421 // case.
7422 unsigned NumElts = cast<FixedVectorType>(VTy)->getNumElements();
7423 return NumElts == 1 ||
7424 (ST->hasAVX512() && (NumElts == 2 || (NumElts == 4 && !ST->hasVLX())));
7425}
7426
7428 Align Alignment) const {
7429 Type *ScalarTy = DataTy->getScalarType();
7430 if (ScalarTy->isPointerTy())
7431 return true;
7432
7433 if (ScalarTy->isFloatTy() || ScalarTy->isDoubleTy())
7434 return true;
7435
7436 if (!ScalarTy->isIntegerTy())
7437 return false;
7438
7439 unsigned IntWidth = ScalarTy->getIntegerBitWidth();
7440 return IntWidth == 32 || IntWidth == 64;
7441}
7442
7443bool X86TTIImpl::isLegalMaskedGather(Type *DataTy, Align Alignment) const {
7444 if (!supportsGather() || !ST->preferGather())
7445 return false;
7446 return isLegalMaskedGatherScatter(DataTy, Alignment);
7447}
7448
7449bool X86TTIImpl::isLegalAltInstr(VectorType *VecTy, unsigned Opcode0,
7450 unsigned Opcode1,
7451 const SmallBitVector &OpcodeMask) const {
7452 // ADDSUBPS 4xf32 SSE3
7453 // VADDSUBPS 4xf32 AVX
7454 // VADDSUBPS 8xf32 AVX2
7455 // ADDSUBPD 2xf64 SSE3
7456 // VADDSUBPD 2xf64 AVX
7457 // VADDSUBPD 4xf64 AVX2
7458
7459 unsigned NumElements = cast<FixedVectorType>(VecTy)->getNumElements();
7460 assert(OpcodeMask.size() == NumElements && "Mask and VecTy are incompatible");
7461 if (!isPowerOf2_32(NumElements))
7462 return false;
7463 // Check the opcode pattern. We apply the mask on the opcode arguments and
7464 // then check if it is what we expect.
7465 for (int Lane : seq<int>(0, NumElements)) {
7466 unsigned Opc = OpcodeMask.test(Lane) ? Opcode1 : Opcode0;
7467 // We expect FSub for even lanes and FAdd for odd lanes.
7468 if (Lane % 2 == 0 && Opc != Instruction::FSub)
7469 return false;
7470 if (Lane % 2 == 1 && Opc != Instruction::FAdd)
7471 return false;
7472 }
7473 // Now check that the pattern is supported by the target ISA.
7474 Type *ElemTy = cast<VectorType>(VecTy)->getElementType();
7475 if (ElemTy->isFloatTy())
7476 return ST->hasSSE3() && NumElements % 4 == 0;
7477 if (ElemTy->isDoubleTy())
7478 return ST->hasSSE3() && NumElements % 2 == 0;
7479 return false;
7480}
7481
7482bool X86TTIImpl::isLegalMaskedScatter(Type *DataType, Align Alignment) const {
7483 // AVX2 doesn't support scatter
7484 if (!ST->hasAVX512() || !ST->preferScatter())
7485 return false;
7486 return isLegalMaskedGatherScatter(DataType, Alignment);
7487}
7488
7489bool X86TTIImpl::hasDivRemOp(Type *DataType, bool IsSigned) const {
7490 EVT VT = TLI->getValueType(DL, DataType);
7491 return TLI->isOperationLegal(IsSigned ? ISD::SDIVREM : ISD::UDIVREM, VT);
7492}
7493
7495 // FDIV is always expensive, even if it has a very low uop count.
7496 // TODO: Still necessary for recent CPUs with low latency/throughput fdiv?
7497 if (I->getOpcode() == Instruction::FDiv)
7498 return true;
7499
7501}
7502
7503bool X86TTIImpl::isFCmpOrdCheaperThanFCmpZero(Type *Ty) const { return false; }
7504
7506 const Function *Callee) const {
7507 const TargetMachine &TM = getTLI()->getTargetMachine();
7508
7509 // Work this as a subsetting of subtarget features.
7510 const X86Subtarget &CallerSubtarget = TM.getSubtarget<X86Subtarget>(*Caller);
7511 const X86Subtarget &CalleeSubtarget = TM.getSubtarget<X86Subtarget>(*Callee);
7512 const FeatureBitset &CallerBits = CallerSubtarget.getFeatureBits();
7513 const FeatureBitset &CalleeBits = CalleeSubtarget.getFeatureBits();
7514
7515 // Check whether callee features are a subset of caller features
7516 // (apart from the ignore list).
7517 const FeatureBitset &InlineIgnoreFeatures =
7518 CallerSubtarget.getInlineIgnoreFeatures();
7519 FeatureBitset RealCallerBits = CallerBits & ~InlineIgnoreFeatures;
7520 FeatureBitset RealCalleeBits = CalleeBits & ~InlineIgnoreFeatures;
7521 if ((RealCallerBits & RealCalleeBits) != RealCalleeBits)
7522 return false;
7523
7524 // If the features are not exactly the same (or there is a difference in
7525 // AVX512 register usage), we need to additionally check for calls
7526 // that may become ABI-incompatible as a result of inlining.
7527 if (RealCallerBits == RealCalleeBits &&
7528 CallerSubtarget.useAVX512Regs() == CalleeSubtarget.useAVX512Regs())
7529 return true;
7530
7531 for (const Instruction &I : instructions(Callee)) {
7532 if (const auto *CB = dyn_cast<CallBase>(&I)) {
7533 // Having more target features is fine for inline ASM and intrinsics.
7534 if (CB->isInlineAsm() || CB->getIntrinsicID() != Intrinsic::not_intrinsic)
7535 continue;
7536
7538 for (Value *Arg : CB->args())
7539 Types.push_back(Arg->getType());
7540 if (!CB->getType()->isVoidTy())
7541 Types.push_back(CB->getType());
7542
7543 // Simple types are always ABI compatible.
7544 auto IsSimpleTy = [](Type *Ty) {
7545 return !Ty->isVectorTy() && !Ty->isAggregateType();
7546 };
7547 if (all_of(Types, IsSimpleTy))
7548 continue;
7549
7550 // Do a precise compatibility check.
7551 if (!areTypesABICompatible(Caller, Callee, Types))
7552 return false;
7553 }
7554 }
7555 return true;
7556}
7557
7559 const Function *Callee,
7560 ArrayRef<Type *> Types) const {
7561 const TargetMachine &TM = getTLI()->getTargetMachine();
7562 const TargetLowering *CallerTLI =
7563 TM.getSubtargetImpl(*Caller)->getTargetLowering();
7564 const TargetLowering *CalleeTLI =
7565 TM.getSubtargetImpl(*Callee)->getTargetLowering();
7566
7567 LLVMContext &Ctx = Caller->getContext();
7568 const DataLayout &DL = Caller->getDataLayout();
7569 CallingConv::ID CC = Callee->getCallingConv();
7570 return all_of(Types, [&](Type *Ty) {
7571 SmallVector<EVT> VTs;
7572 ComputeValueVTs(*CallerTLI, DL, Ty, VTs);
7573 return all_of(VTs, [&](EVT VT) {
7574 return CallerTLI->getRegisterTypeForCallingConv(Ctx, CC, VT) ==
7575 CalleeTLI->getRegisterTypeForCallingConv(Ctx, CC, VT);
7576 });
7577 });
7578}
7579
7581X86TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
7583 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
7584 Options.NumLoadsPerBlock = IsZeroCmp ? 2 : 1;
7585 // All GPR and vector loads can be unaligned.
7586 Options.AllowOverlappingLoads = true;
7587 if (IsZeroCmp) {
7588 // Only enable vector loads for equality comparison. Right now the vector
7589 // version is not as fast for three way compare (see #33329).
7590 const unsigned PreferredWidth = ST->getPreferVectorWidth();
7591 if (PreferredWidth >= 512 && ST->hasAVX512())
7592 Options.LoadSizes.push_back(64);
7593 if (PreferredWidth >= 256 && ST->hasAVX()) Options.LoadSizes.push_back(32);
7594 if (PreferredWidth >= 128 && ST->hasSSE2()) Options.LoadSizes.push_back(16);
7595 }
7596 if (ST->is64Bit()) {
7597 Options.LoadSizes.push_back(8);
7598 }
7599 Options.LoadSizes.push_back(4);
7600 Options.LoadSizes.push_back(2);
7601 Options.LoadSizes.push_back(1);
7602 return Options;
7603}
7604
7606 return supportsGather();
7607}
7608
7610 return false;
7611}
7612
7614 // TODO: We expect this to be beneficial regardless of arch,
7615 // but there are currently some unexplained performance artifacts on Atom.
7616 // As a temporary solution, disable on Atom.
7617 return !(ST->isAtom());
7618}
7619
7621 switch (II->getIntrinsicID()) {
7622 default:
7623 return true;
7624 case Intrinsic::vector_reduce_and:
7625 case Intrinsic::vector_reduce_or:
7626 case Intrinsic::vector_reduce_xor:
7627 case Intrinsic::vector_reduce_mul:
7628 case Intrinsic::vector_reduce_smax:
7629 case Intrinsic::vector_reduce_smin:
7630 case Intrinsic::vector_reduce_umax:
7631 case Intrinsic::vector_reduce_umin:
7632 return false;
7633 }
7634}
7635
7636// Get estimation for interleaved load/store operations and strided load.
7637// \p Indices contains indices for strided load.
7638// \p Factor - the factor of interleaving.
7639// AVX-512 provides 3-src shuffles that significantly reduces the cost.
7641 unsigned Opcode, FixedVectorType *VecTy, unsigned Factor,
7642 ArrayRef<unsigned> Indices, Align Alignment, unsigned AddressSpace,
7643 TTI::TargetCostKind CostKind, bool UseMaskForCond,
7644 bool UseMaskForGaps) const {
7645 // VecTy for interleave memop is <VF*Factor x Elt>.
7646 // So, for VF=4, Interleave Factor = 3, Element type = i32 we have
7647 // VecTy = <12 x i32>.
7648
7649 // Calculate the number of memory operations (NumOfMemOps), required
7650 // for load/store the VecTy.
7651 MVT LegalVT = getTypeLegalizationCost(VecTy).second;
7652 unsigned VecTySize = DL.getTypeStoreSize(VecTy);
7653 unsigned LegalVTSize = LegalVT.getStoreSize();
7654 unsigned NumOfMemOps = (VecTySize + LegalVTSize - 1) / LegalVTSize;
7655
7656 // Get the cost of one memory operation.
7657 auto *SingleMemOpTy = FixedVectorType::get(VecTy->getElementType(),
7658 LegalVT.getVectorNumElements());
7659 InstructionCost MemOpCost;
7660 bool UseMaskedMemOp = UseMaskForCond || UseMaskForGaps;
7661 if (UseMaskedMemOp) {
7662 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
7663 : Intrinsic::masked_store;
7664 MemOpCost = getMaskedMemoryOpCost(
7665 {IID, SingleMemOpTy, Alignment, AddressSpace}, CostKind);
7666 } else
7667 MemOpCost = getMemoryOpCost(Opcode, SingleMemOpTy, Alignment, AddressSpace,
7668 CostKind);
7669
7670 unsigned VF = VecTy->getNumElements() / Factor;
7671 MVT VT =
7672 MVT::getVectorVT(TLI->getSimpleValueType(DL, VecTy->getScalarType()), VF);
7673
7674 InstructionCost MaskCost;
7675 if (UseMaskedMemOp) {
7676 APInt DemandedLoadStoreElts = APInt::getZero(VecTy->getNumElements());
7677 for (unsigned Index : Indices) {
7678 assert(Index < Factor && "Invalid index for interleaved memory op");
7679 for (unsigned Elm = 0; Elm < VF; Elm++)
7680 DemandedLoadStoreElts.setBit(Index + Elm * Factor);
7681 }
7682
7683 Type *I1Type = Type::getInt1Ty(VecTy->getContext());
7684
7685 MaskCost = getReplicationShuffleCost(
7686 I1Type, Factor, VF,
7687 UseMaskForGaps ? DemandedLoadStoreElts
7689 CostKind);
7690
7691 // The Gaps mask is invariant and created outside the loop, therefore the
7692 // cost of creating it is not accounted for here. However if we have both
7693 // a MaskForGaps and some other mask that guards the execution of the
7694 // memory access, we need to account for the cost of And-ing the two masks
7695 // inside the loop.
7696 if (UseMaskForGaps) {
7697 auto *MaskVT = FixedVectorType::get(I1Type, VecTy->getNumElements());
7698 MaskCost += getArithmeticInstrCost(BinaryOperator::And, MaskVT, CostKind);
7699 }
7700 }
7701
7702 if (Opcode == Instruction::Load) {
7703 // The tables (AVX512InterleavedLoadTbl and AVX512InterleavedStoreTbl)
7704 // contain the cost of the optimized shuffle sequence that the
7705 // X86InterleavedAccess pass will generate.
7706 // The cost of loads and stores are computed separately from the table.
7707
7708 // X86InterleavedAccess support only the following interleaved-access group.
7709 static const CostTblEntry AVX512InterleavedLoadTbl[] = {
7710 {3, MVT::v16i8, 12}, //(load 48i8 and) deinterleave into 3 x 16i8
7711 {3, MVT::v32i8, 14}, //(load 96i8 and) deinterleave into 3 x 32i8
7712 {3, MVT::v64i8, 22}, //(load 96i8 and) deinterleave into 3 x 32i8
7713 };
7714
7715 if (const auto *Entry =
7716 CostTableLookup(AVX512InterleavedLoadTbl, Factor, VT))
7717 return MaskCost + NumOfMemOps * MemOpCost + Entry->Cost;
7718 //If an entry does not exist, fallback to the default implementation.
7719
7720 // Kind of shuffle depends on number of loaded values.
7721 // If we load the entire data in one register, we can use a 1-src shuffle.
7722 // Otherwise, we'll merge 2 sources in each operation.
7723 TTI::ShuffleKind ShuffleKind =
7724 (NumOfMemOps > 1) ? TTI::SK_PermuteTwoSrc : TTI::SK_PermuteSingleSrc;
7725
7726 InstructionCost ShuffleCost = getShuffleCost(
7727 ShuffleKind, SingleMemOpTy, SingleMemOpTy, CostKind, {}, 0, nullptr);
7728
7729 unsigned NumOfLoadsInInterleaveGrp =
7730 Indices.size() ? Indices.size() : Factor;
7731 auto *ResultTy = FixedVectorType::get(VecTy->getElementType(),
7732 VecTy->getNumElements() / Factor);
7733 InstructionCost NumOfResults =
7734 getTypeLegalizationCost(ResultTy).first * NumOfLoadsInInterleaveGrp;
7735
7736 // About a half of the loads may be folded in shuffles when we have only
7737 // one result. If we have more than one result, or the loads are masked,
7738 // we do not fold loads at all.
7739 unsigned NumOfUnfoldedLoads =
7740 UseMaskedMemOp || NumOfResults > 1 ? NumOfMemOps : NumOfMemOps / 2;
7741
7742 // Get a number of shuffle operations per result.
7743 unsigned NumOfShufflesPerResult =
7744 std::max((unsigned)1, (unsigned)(NumOfMemOps - 1));
7745
7746 // The SK_MergeTwoSrc shuffle clobbers one of src operands.
7747 // When we have more than one destination, we need additional instructions
7748 // to keep sources.
7749 InstructionCost NumOfMoves = 0;
7750 if (NumOfResults > 1 && ShuffleKind == TTI::SK_PermuteTwoSrc)
7751 NumOfMoves = NumOfResults * NumOfShufflesPerResult / 2;
7752
7753 InstructionCost Cost = NumOfResults * NumOfShufflesPerResult * ShuffleCost +
7754 MaskCost + NumOfUnfoldedLoads * MemOpCost +
7755 NumOfMoves;
7756
7757 return Cost;
7758 }
7759
7760 // Store.
7761 assert(Opcode == Instruction::Store &&
7762 "Expected Store Instruction at this point");
7763 // X86InterleavedAccess support only the following interleaved-access group.
7764 static const CostTblEntry AVX512InterleavedStoreTbl[] = {
7765 {3, MVT::v16i8, 12}, // interleave 3 x 16i8 into 48i8 (and store)
7766 {3, MVT::v32i8, 14}, // interleave 3 x 32i8 into 96i8 (and store)
7767 {3, MVT::v64i8, 26}, // interleave 3 x 64i8 into 96i8 (and store)
7768
7769 {4, MVT::v8i8, 10}, // interleave 4 x 8i8 into 32i8 (and store)
7770 {4, MVT::v16i8, 11}, // interleave 4 x 16i8 into 64i8 (and store)
7771 {4, MVT::v32i8, 14}, // interleave 4 x 32i8 into 128i8 (and store)
7772 {4, MVT::v64i8, 24} // interleave 4 x 32i8 into 256i8 (and store)
7773 };
7774
7775 if (const auto *Entry =
7776 CostTableLookup(AVX512InterleavedStoreTbl, Factor, VT))
7777 return MaskCost + NumOfMemOps * MemOpCost + Entry->Cost;
7778 //If an entry does not exist, fallback to the default implementation.
7779
7780 // There is no strided stores meanwhile. And store can't be folded in
7781 // shuffle.
7782 unsigned NumOfSources = Factor; // The number of values to be merged.
7783 InstructionCost ShuffleCost =
7784 getShuffleCost(TTI::SK_PermuteTwoSrc, SingleMemOpTy, SingleMemOpTy,
7785 CostKind, {}, 0, nullptr);
7786 unsigned NumOfShufflesPerStore = NumOfSources - 1;
7787
7788 // The SK_MergeTwoSrc shuffle clobbers one of src operands.
7789 // We need additional instructions to keep sources.
7790 unsigned NumOfMoves = NumOfMemOps * NumOfShufflesPerStore / 2;
7792 MaskCost +
7793 NumOfMemOps * (MemOpCost + NumOfShufflesPerStore * ShuffleCost) +
7794 NumOfMoves;
7795 return Cost;
7796}
7797
7799 unsigned Opcode, Type *BaseTy, unsigned Factor, ArrayRef<unsigned> Indices,
7800 Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,
7801 bool UseMaskForCond, bool UseMaskForGaps) const {
7802 auto *VecTy = cast<FixedVectorType>(BaseTy);
7803
7804 auto isSupportedOnAVX512 = [&](Type *VecTy) {
7805 Type *EltTy = cast<VectorType>(VecTy)->getElementType();
7806 if (EltTy->isFloatTy() || EltTy->isDoubleTy() || EltTy->isIntegerTy(64) ||
7807 EltTy->isIntegerTy(32) || EltTy->isPointerTy())
7808 return true;
7809 if (EltTy->isIntegerTy(16) || EltTy->isIntegerTy(8) || EltTy->isHalfTy())
7810 return ST->hasBWI();
7811 if (EltTy->isBFloatTy())
7812 return ST->hasBF16();
7813 return false;
7814 };
7815 if (ST->hasAVX512() && isSupportedOnAVX512(VecTy))
7817 Opcode, VecTy, Factor, Indices, Alignment,
7818 AddressSpace, CostKind, UseMaskForCond, UseMaskForGaps);
7819
7820 if (UseMaskForCond || UseMaskForGaps)
7821 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
7822 Alignment, AddressSpace, CostKind,
7823 UseMaskForCond, UseMaskForGaps);
7824
7825 // Get estimation for interleaved load/store operations for SSE-AVX2.
7826 // As opposed to AVX-512, SSE-AVX2 do not have generic shuffles that allow
7827 // computing the cost using a generic formula as a function of generic
7828 // shuffles. We therefore use a lookup table instead, filled according to
7829 // the instruction sequences that codegen currently generates.
7830
7831 // VecTy for interleave memop is <VF*Factor x Elt>.
7832 // So, for VF=4, Interleave Factor = 3, Element type = i32 we have
7833 // VecTy = <12 x i32>.
7834 MVT LegalVT = getTypeLegalizationCost(VecTy).second;
7835
7836 // This function can be called with VecTy=<6xi128>, Factor=3, in which case
7837 // the VF=2, while v2i128 is an unsupported MVT vector type
7838 // (see MachineValueType.h::getVectorVT()).
7839 if (!LegalVT.isVector())
7840 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
7841 Alignment, AddressSpace, CostKind);
7842
7843 unsigned VF = VecTy->getNumElements() / Factor;
7844 Type *ScalarTy = VecTy->getElementType();
7845 // Deduplicate entries, model floats/pointers as appropriately-sized integers.
7846 if (!ScalarTy->isIntegerTy())
7847 ScalarTy =
7848 Type::getIntNTy(ScalarTy->getContext(), DL.getTypeSizeInBits(ScalarTy));
7849
7850 // Get the cost of all the memory operations.
7851 // FIXME: discount dead loads.
7852 InstructionCost MemOpCosts =
7853 getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace, CostKind);
7854
7855 auto *VT = FixedVectorType::get(ScalarTy, VF);
7856 EVT ETy = TLI->getValueType(DL, VT);
7857 if (!ETy.isSimple())
7858 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
7859 Alignment, AddressSpace, CostKind);
7860
7861 // TODO: Complete for other data-types and strides.
7862 // Each combination of Stride, element bit width and VF results in a different
7863 // sequence; The cost tables are therefore accessed with:
7864 // Factor (stride) and VectorType=VFxiN.
7865 // The Cost accounts only for the shuffle sequence;
7866 // The cost of the loads/stores is accounted for separately.
7867 //
7868 static const CostTblEntry AVX2InterleavedLoadTbl[] = {
7869 {2, MVT::v2i8, 2}, // (load 4i8 and) deinterleave into 2 x 2i8
7870 {2, MVT::v4i8, 2}, // (load 8i8 and) deinterleave into 2 x 4i8
7871 {2, MVT::v8i8, 2}, // (load 16i8 and) deinterleave into 2 x 8i8
7872 {2, MVT::v16i8, 4}, // (load 32i8 and) deinterleave into 2 x 16i8
7873 {2, MVT::v32i8, 6}, // (load 64i8 and) deinterleave into 2 x 32i8
7874
7875 {2, MVT::v8i16, 6}, // (load 16i16 and) deinterleave into 2 x 8i16
7876 {2, MVT::v16i16, 9}, // (load 32i16 and) deinterleave into 2 x 16i16
7877 {2, MVT::v32i16, 18}, // (load 64i16 and) deinterleave into 2 x 32i16
7878
7879 {2, MVT::v8i32, 4}, // (load 16i32 and) deinterleave into 2 x 8i32
7880 {2, MVT::v16i32, 8}, // (load 32i32 and) deinterleave into 2 x 16i32
7881 {2, MVT::v32i32, 16}, // (load 64i32 and) deinterleave into 2 x 32i32
7882
7883 {2, MVT::v4i64, 4}, // (load 8i64 and) deinterleave into 2 x 4i64
7884 {2, MVT::v8i64, 8}, // (load 16i64 and) deinterleave into 2 x 8i64
7885 {2, MVT::v16i64, 16}, // (load 32i64 and) deinterleave into 2 x 16i64
7886 {2, MVT::v32i64, 32}, // (load 64i64 and) deinterleave into 2 x 32i64
7887
7888 {3, MVT::v2i8, 3}, // (load 6i8 and) deinterleave into 3 x 2i8
7889 {3, MVT::v4i8, 3}, // (load 12i8 and) deinterleave into 3 x 4i8
7890 {3, MVT::v8i8, 6}, // (load 24i8 and) deinterleave into 3 x 8i8
7891 {3, MVT::v16i8, 11}, // (load 48i8 and) deinterleave into 3 x 16i8
7892 {3, MVT::v32i8, 14}, // (load 96i8 and) deinterleave into 3 x 32i8
7893
7894 {3, MVT::v2i16, 5}, // (load 6i16 and) deinterleave into 3 x 2i16
7895 {3, MVT::v4i16, 7}, // (load 12i16 and) deinterleave into 3 x 4i16
7896 {3, MVT::v8i16, 9}, // (load 24i16 and) deinterleave into 3 x 8i16
7897 {3, MVT::v16i16, 28}, // (load 48i16 and) deinterleave into 3 x 16i16
7898 {3, MVT::v32i16, 56}, // (load 96i16 and) deinterleave into 3 x 32i16
7899
7900 {3, MVT::v2i32, 3}, // (load 6i32 and) deinterleave into 3 x 2i32
7901 {3, MVT::v4i32, 3}, // (load 12i32 and) deinterleave into 3 x 4i32
7902 {3, MVT::v8i32, 7}, // (load 24i32 and) deinterleave into 3 x 8i32
7903 {3, MVT::v16i32, 14}, // (load 48i32 and) deinterleave into 3 x 16i32
7904 {3, MVT::v32i32, 32}, // (load 96i32 and) deinterleave into 3 x 32i32
7905
7906 {3, MVT::v2i64, 1}, // (load 6i64 and) deinterleave into 3 x 2i64
7907 {3, MVT::v4i64, 5}, // (load 12i64 and) deinterleave into 3 x 4i64
7908 {3, MVT::v8i64, 10}, // (load 24i64 and) deinterleave into 3 x 8i64
7909 {3, MVT::v16i64, 20}, // (load 48i64 and) deinterleave into 3 x 16i64
7910
7911 {4, MVT::v2i8, 4}, // (load 8i8 and) deinterleave into 4 x 2i8
7912 {4, MVT::v4i8, 4}, // (load 16i8 and) deinterleave into 4 x 4i8
7913 {4, MVT::v8i8, 12}, // (load 32i8 and) deinterleave into 4 x 8i8
7914 {4, MVT::v16i8, 24}, // (load 64i8 and) deinterleave into 4 x 16i8
7915 {4, MVT::v32i8, 56}, // (load 128i8 and) deinterleave into 4 x 32i8
7916
7917 {4, MVT::v2i16, 6}, // (load 8i16 and) deinterleave into 4 x 2i16
7918 {4, MVT::v4i16, 17}, // (load 16i16 and) deinterleave into 4 x 4i16
7919 {4, MVT::v8i16, 33}, // (load 32i16 and) deinterleave into 4 x 8i16
7920 {4, MVT::v16i16, 75}, // (load 64i16 and) deinterleave into 4 x 16i16
7921 {4, MVT::v32i16, 150}, // (load 128i16 and) deinterleave into 4 x 32i16
7922
7923 {4, MVT::v2i32, 4}, // (load 8i32 and) deinterleave into 4 x 2i32
7924 {4, MVT::v4i32, 8}, // (load 16i32 and) deinterleave into 4 x 4i32
7925 {4, MVT::v8i32, 16}, // (load 32i32 and) deinterleave into 4 x 8i32
7926 {4, MVT::v16i32, 32}, // (load 64i32 and) deinterleave into 4 x 16i32
7927 {4, MVT::v32i32, 68}, // (load 128i32 and) deinterleave into 4 x 32i32
7928
7929 {4, MVT::v2i64, 6}, // (load 8i64 and) deinterleave into 4 x 2i64
7930 {4, MVT::v4i64, 8}, // (load 16i64 and) deinterleave into 4 x 4i64
7931 {4, MVT::v8i64, 20}, // (load 32i64 and) deinterleave into 4 x 8i64
7932 {4, MVT::v16i64, 40}, // (load 64i64 and) deinterleave into 4 x 16i64
7933
7934 {6, MVT::v2i8, 6}, // (load 12i8 and) deinterleave into 6 x 2i8
7935 {6, MVT::v4i8, 14}, // (load 24i8 and) deinterleave into 6 x 4i8
7936 {6, MVT::v8i8, 18}, // (load 48i8 and) deinterleave into 6 x 8i8
7937 {6, MVT::v16i8, 43}, // (load 96i8 and) deinterleave into 6 x 16i8
7938 {6, MVT::v32i8, 82}, // (load 192i8 and) deinterleave into 6 x 32i8
7939
7940 {6, MVT::v2i16, 13}, // (load 12i16 and) deinterleave into 6 x 2i16
7941 {6, MVT::v4i16, 9}, // (load 24i16 and) deinterleave into 6 x 4i16
7942 {6, MVT::v8i16, 39}, // (load 48i16 and) deinterleave into 6 x 8i16
7943 {6, MVT::v16i16, 106}, // (load 96i16 and) deinterleave into 6 x 16i16
7944 {6, MVT::v32i16, 212}, // (load 192i16 and) deinterleave into 6 x 32i16
7945
7946 {6, MVT::v2i32, 6}, // (load 12i32 and) deinterleave into 6 x 2i32
7947 {6, MVT::v4i32, 15}, // (load 24i32 and) deinterleave into 6 x 4i32
7948 {6, MVT::v8i32, 31}, // (load 48i32 and) deinterleave into 6 x 8i32
7949 {6, MVT::v16i32, 64}, // (load 96i32 and) deinterleave into 6 x 16i32
7950
7951 {6, MVT::v2i64, 6}, // (load 12i64 and) deinterleave into 6 x 2i64
7952 {6, MVT::v4i64, 18}, // (load 24i64 and) deinterleave into 6 x 4i64
7953 {6, MVT::v8i64, 36}, // (load 48i64 and) deinterleave into 6 x 8i64
7954
7955 {8, MVT::v8i32, 40} // (load 64i32 and) deinterleave into 8 x 8i32
7956 };
7957
7958 static const CostTblEntry SSSE3InterleavedLoadTbl[] = {
7959 {2, MVT::v4i16, 2}, // (load 8i16 and) deinterleave into 2 x 4i16
7960 };
7961
7962 static const CostTblEntry SSE2InterleavedLoadTbl[] = {
7963 {2, MVT::v2i16, 2}, // (load 4i16 and) deinterleave into 2 x 2i16
7964 {2, MVT::v4i16, 7}, // (load 8i16 and) deinterleave into 2 x 4i16
7965
7966 {2, MVT::v2i32, 2}, // (load 4i32 and) deinterleave into 2 x 2i32
7967 {2, MVT::v4i32, 2}, // (load 8i32 and) deinterleave into 2 x 4i32
7968
7969 {2, MVT::v2i64, 2}, // (load 4i64 and) deinterleave into 2 x 2i64
7970 };
7971
7972 static const CostTblEntry AVX2InterleavedStoreTbl[] = {
7973 {2, MVT::v16i8, 3}, // interleave 2 x 16i8 into 32i8 (and store)
7974 {2, MVT::v32i8, 4}, // interleave 2 x 32i8 into 64i8 (and store)
7975
7976 {2, MVT::v8i16, 3}, // interleave 2 x 8i16 into 16i16 (and store)
7977 {2, MVT::v16i16, 4}, // interleave 2 x 16i16 into 32i16 (and store)
7978 {2, MVT::v32i16, 8}, // interleave 2 x 32i16 into 64i16 (and store)
7979
7980 {2, MVT::v4i32, 2}, // interleave 2 x 4i32 into 8i32 (and store)
7981 {2, MVT::v8i32, 4}, // interleave 2 x 8i32 into 16i32 (and store)
7982 {2, MVT::v16i32, 8}, // interleave 2 x 16i32 into 32i32 (and store)
7983 {2, MVT::v32i32, 16}, // interleave 2 x 32i32 into 64i32 (and store)
7984
7985 {2, MVT::v2i64, 2}, // interleave 2 x 2i64 into 4i64 (and store)
7986 {2, MVT::v4i64, 4}, // interleave 2 x 4i64 into 8i64 (and store)
7987 {2, MVT::v8i64, 8}, // interleave 2 x 8i64 into 16i64 (and store)
7988 {2, MVT::v16i64, 16}, // interleave 2 x 16i64 into 32i64 (and store)
7989 {2, MVT::v32i64, 32}, // interleave 2 x 32i64 into 64i64 (and store)
7990
7991 {3, MVT::v2i8, 4}, // interleave 3 x 2i8 into 6i8 (and store)
7992 {3, MVT::v4i8, 4}, // interleave 3 x 4i8 into 12i8 (and store)
7993 {3, MVT::v8i8, 6}, // interleave 3 x 8i8 into 24i8 (and store)
7994 {3, MVT::v16i8, 11}, // interleave 3 x 16i8 into 48i8 (and store)
7995 {3, MVT::v32i8, 13}, // interleave 3 x 32i8 into 96i8 (and store)
7996
7997 {3, MVT::v2i16, 4}, // interleave 3 x 2i16 into 6i16 (and store)
7998 {3, MVT::v4i16, 6}, // interleave 3 x 4i16 into 12i16 (and store)
7999 {3, MVT::v8i16, 12}, // interleave 3 x 8i16 into 24i16 (and store)
8000 {3, MVT::v16i16, 27}, // interleave 3 x 16i16 into 48i16 (and store)
8001 {3, MVT::v32i16, 54}, // interleave 3 x 32i16 into 96i16 (and store)
8002
8003 {3, MVT::v2i32, 4}, // interleave 3 x 2i32 into 6i32 (and store)
8004 {3, MVT::v4i32, 5}, // interleave 3 x 4i32 into 12i32 (and store)
8005 {3, MVT::v8i32, 11}, // interleave 3 x 8i32 into 24i32 (and store)
8006 {3, MVT::v16i32, 22}, // interleave 3 x 16i32 into 48i32 (and store)
8007 {3, MVT::v32i32, 48}, // interleave 3 x 32i32 into 96i32 (and store)
8008
8009 {3, MVT::v2i64, 4}, // interleave 3 x 2i64 into 6i64 (and store)
8010 {3, MVT::v4i64, 6}, // interleave 3 x 4i64 into 12i64 (and store)
8011 {3, MVT::v8i64, 12}, // interleave 3 x 8i64 into 24i64 (and store)
8012 {3, MVT::v16i64, 24}, // interleave 3 x 16i64 into 48i64 (and store)
8013
8014 {4, MVT::v2i8, 4}, // interleave 4 x 2i8 into 8i8 (and store)
8015 {4, MVT::v4i8, 4}, // interleave 4 x 4i8 into 16i8 (and store)
8016 {4, MVT::v8i8, 4}, // interleave 4 x 8i8 into 32i8 (and store)
8017 {4, MVT::v16i8, 8}, // interleave 4 x 16i8 into 64i8 (and store)
8018 {4, MVT::v32i8, 12}, // interleave 4 x 32i8 into 128i8 (and store)
8019
8020 {4, MVT::v2i16, 2}, // interleave 4 x 2i16 into 8i16 (and store)
8021 {4, MVT::v4i16, 6}, // interleave 4 x 4i16 into 16i16 (and store)
8022 {4, MVT::v8i16, 10}, // interleave 4 x 8i16 into 32i16 (and store)
8023 {4, MVT::v16i16, 32}, // interleave 4 x 16i16 into 64i16 (and store)
8024 {4, MVT::v32i16, 64}, // interleave 4 x 32i16 into 128i16 (and store)
8025
8026 {4, MVT::v2i32, 5}, // interleave 4 x 2i32 into 8i32 (and store)
8027 {4, MVT::v4i32, 6}, // interleave 4 x 4i32 into 16i32 (and store)
8028 {4, MVT::v8i32, 16}, // interleave 4 x 8i32 into 32i32 (and store)
8029 {4, MVT::v16i32, 32}, // interleave 4 x 16i32 into 64i32 (and store)
8030 {4, MVT::v32i32, 64}, // interleave 4 x 32i32 into 128i32 (and store)
8031
8032 {4, MVT::v2i64, 6}, // interleave 4 x 2i64 into 8i64 (and store)
8033 {4, MVT::v4i64, 8}, // interleave 4 x 4i64 into 16i64 (and store)
8034 {4, MVT::v8i64, 20}, // interleave 4 x 8i64 into 32i64 (and store)
8035 {4, MVT::v16i64, 40}, // interleave 4 x 16i64 into 64i64 (and store)
8036
8037 {6, MVT::v2i8, 7}, // interleave 6 x 2i8 into 12i8 (and store)
8038 {6, MVT::v4i8, 9}, // interleave 6 x 4i8 into 24i8 (and store)
8039 {6, MVT::v8i8, 16}, // interleave 6 x 8i8 into 48i8 (and store)
8040 {6, MVT::v16i8, 27}, // interleave 6 x 16i8 into 96i8 (and store)
8041 {6, MVT::v32i8, 90}, // interleave 6 x 32i8 into 192i8 (and store)
8042
8043 {6, MVT::v2i16, 10}, // interleave 6 x 2i16 into 12i16 (and store)
8044 {6, MVT::v4i16, 15}, // interleave 6 x 4i16 into 24i16 (and store)
8045 {6, MVT::v8i16, 21}, // interleave 6 x 8i16 into 48i16 (and store)
8046 {6, MVT::v16i16, 58}, // interleave 6 x 16i16 into 96i16 (and store)
8047 {6, MVT::v32i16, 90}, // interleave 6 x 32i16 into 192i16 (and store)
8048
8049 {6, MVT::v2i32, 9}, // interleave 6 x 2i32 into 12i32 (and store)
8050 {6, MVT::v4i32, 12}, // interleave 6 x 4i32 into 24i32 (and store)
8051 {6, MVT::v8i32, 33}, // interleave 6 x 8i32 into 48i32 (and store)
8052 {6, MVT::v16i32, 66}, // interleave 6 x 16i32 into 96i32 (and store)
8053
8054 {6, MVT::v2i64, 8}, // interleave 6 x 2i64 into 12i64 (and store)
8055 {6, MVT::v4i64, 15}, // interleave 6 x 4i64 into 24i64 (and store)
8056 {6, MVT::v8i64, 30}, // interleave 6 x 8i64 into 48i64 (and store)
8057 };
8058
8059 static const CostTblEntry SSE2InterleavedStoreTbl[] = {
8060 {2, MVT::v2i8, 1}, // interleave 2 x 2i8 into 4i8 (and store)
8061 {2, MVT::v4i8, 1}, // interleave 2 x 4i8 into 8i8 (and store)
8062 {2, MVT::v8i8, 1}, // interleave 2 x 8i8 into 16i8 (and store)
8063
8064 {2, MVT::v2i16, 1}, // interleave 2 x 2i16 into 4i16 (and store)
8065 {2, MVT::v4i16, 1}, // interleave 2 x 4i16 into 8i16 (and store)
8066
8067 {2, MVT::v2i32, 1}, // interleave 2 x 2i32 into 4i32 (and store)
8068 };
8069
8070 if (Opcode == Instruction::Load) {
8071 auto GetDiscountedCost = [Factor, NumMembers = Indices.size(),
8072 MemOpCosts](const CostTblEntry *Entry) {
8073 // NOTE: this is just an approximation!
8074 // It can over/under -estimate the cost!
8075 return MemOpCosts + divideCeil(NumMembers * Entry->Cost, Factor);
8076 };
8077
8078 if (ST->hasAVX2())
8079 if (const auto *Entry = CostTableLookup(AVX2InterleavedLoadTbl, Factor,
8080 ETy.getSimpleVT()))
8081 return GetDiscountedCost(Entry);
8082
8083 if (ST->hasSSSE3())
8084 if (const auto *Entry = CostTableLookup(SSSE3InterleavedLoadTbl, Factor,
8085 ETy.getSimpleVT()))
8086 return GetDiscountedCost(Entry);
8087
8088 if (ST->hasSSE2())
8089 if (const auto *Entry = CostTableLookup(SSE2InterleavedLoadTbl, Factor,
8090 ETy.getSimpleVT()))
8091 return GetDiscountedCost(Entry);
8092 } else {
8093 assert(Opcode == Instruction::Store &&
8094 "Expected Store Instruction at this point");
8095 assert((!Indices.size() || Indices.size() == Factor) &&
8096 "Interleaved store only supports fully-interleaved groups.");
8097 if (ST->hasAVX2())
8098 if (const auto *Entry = CostTableLookup(AVX2InterleavedStoreTbl, Factor,
8099 ETy.getSimpleVT()))
8100 return MemOpCosts + Entry->Cost;
8101
8102 if (ST->hasSSE2())
8103 if (const auto *Entry = CostTableLookup(SSE2InterleavedStoreTbl, Factor,
8104 ETy.getSimpleVT()))
8105 return MemOpCosts + Entry->Cost;
8106 }
8107
8108 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
8109 Alignment, AddressSpace, CostKind,
8110 UseMaskForCond, UseMaskForGaps);
8111}
8112
8114 StackOffset BaseOffset,
8115 bool HasBaseReg, int64_t Scale,
8116 unsigned AddrSpace) const {
8117 // Scaling factors are not free at all.
8118 // An indexed folded instruction, i.e., inst (reg1, reg2, scale),
8119 // will take 2 allocations in the out of order engine instead of 1
8120 // for plain addressing mode, i.e. inst (reg1).
8121 // E.g.,
8122 // vaddps (%rsi,%rdx), %ymm0, %ymm1
8123 // Requires two allocations (one for the load, one for the computation)
8124 // whereas:
8125 // vaddps (%rsi), %ymm0, %ymm1
8126 // Requires just 1 allocation, i.e., freeing allocations for other operations
8127 // and having less micro operations to execute.
8128 //
8129 // For some X86 architectures, this is even worse because for instance for
8130 // stores, the complex addressing mode forces the instruction to use the
8131 // "load" ports instead of the dedicated "store" port.
8132 // E.g., on Haswell:
8133 // vmovaps %ymm1, (%r8, %rdi) can use port 2 or 3.
8134 // vmovaps %ymm1, (%r8) can use port 2, 3, or 7.
8136 AM.BaseGV = BaseGV;
8137 AM.BaseOffs = BaseOffset.getFixed();
8138 AM.HasBaseReg = HasBaseReg;
8139 AM.Scale = Scale;
8140 AM.ScalableOffset = BaseOffset.getScalable();
8141 if (getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace))
8142 // Scale represents reg2 * scale, thus account for 1
8143 // as soon as we use a second register.
8144 return AM.Scale != 0;
8146}
8147
8149 // TODO: Hook MispredictPenalty of SchedMachineModel into this.
8150 return 14;
8151}
8152
8154 unsigned Bits = Ty->getScalarSizeInBits();
8155
8156 // XOP has v16i8/v8i16/v4i32/v2i64 variable vector shifts.
8157 // Splitting for v32i8/v16i16 on XOP+AVX2 targets is still preferred.
8158 if (ST->hasXOP() && (Bits == 8 || Bits == 16 || Bits == 32 || Bits == 64))
8159 return false;
8160
8161 // AVX2 has vpsllv[dq] instructions (and other shifts) that make variable
8162 // shifts just as cheap as scalar ones.
8163 if (ST->hasAVX2() && (Bits == 32 || Bits == 64))
8164 return false;
8165
8166 // AVX512BW has shifts such as vpsllvw.
8167 if (ST->hasBWI() && Bits == 16)
8168 return false;
8169
8170 // Otherwise, it's significantly cheaper to shift by a scalar amount than by a
8171 // fully general vector.
8172 return true;
8173}
8174
8175unsigned X86TTIImpl::getStoreMinimumVF(unsigned VF, Type *ScalarMemTy,
8176 Type *ScalarValTy, Align Alignment,
8177 unsigned AddrSpace) const {
8178 if (ST->hasF16C() && ScalarMemTy->isHalfTy()) {
8179 return 4;
8180 }
8181 return BaseT::getStoreMinimumVF(VF, ScalarMemTy, ScalarValTy, Alignment,
8182 AddrSpace);
8183}
8184
8186 SmallVectorImpl<Use *> &Ops) const {
8187 using namespace llvm::PatternMatch;
8188
8189 if (I->getOpcode() == Instruction::And &&
8190 (ST->hasBMI() || (I->getType()->isVectorTy() && ST->hasSSE2()))) {
8191 for (auto &Op : I->operands()) {
8192 // (and X, (not Y)) -> (andn X, Y)
8193 if (match(Op.get(), m_Not(m_Value())) && !I->getType()->isIntegerTy(8)) {
8194 Ops.push_back(&Op);
8195 return true;
8196 }
8197 // (and X, (splat (not Y))) -> (andn X, (splat Y))
8198 if (match(Op.get(),
8200 m_Value(), m_ZeroMask()))) {
8201 Use &InsertElt = cast<Instruction>(Op)->getOperandUse(0);
8202 Use &Not = cast<Instruction>(InsertElt)->getOperandUse(1);
8203 Ops.push_back(&Not);
8204 Ops.push_back(&InsertElt);
8205 Ops.push_back(&Op);
8206 return true;
8207 }
8208 }
8209 }
8210
8211 FixedVectorType *VTy = dyn_cast<FixedVectorType>(I->getType());
8212 if (!VTy)
8213 return false;
8214
8215 if (I->getOpcode() == Instruction::Mul &&
8216 VTy->getElementType()->isIntegerTy(64)) {
8217 for (auto &Op : I->operands()) {
8218 // Make sure we are not already sinking this operand
8219 if (any_of(Ops, [&](Use *U) { return U->get() == Op; }))
8220 continue;
8221
8222 // Look for PMULDQ pattern where the input is a sext_inreg from vXi32 or
8223 // the PMULUDQ pattern where the input is a zext_inreg from vXi32.
8224 if (ST->hasSSE41() &&
8225 match(Op.get(), m_AShr(m_Shl(m_Value(), m_SpecificInt(32)),
8226 m_SpecificInt(32)))) {
8227 Ops.push_back(&cast<Instruction>(Op)->getOperandUse(0));
8228 Ops.push_back(&Op);
8229 } else if (ST->hasSSE2() &&
8230 match(Op.get(),
8231 m_And(m_Value(), m_SpecificInt(UINT64_C(0xffffffff))))) {
8232 Ops.push_back(&Op);
8233 }
8234 }
8235
8236 return !Ops.empty();
8237 }
8238
8239 // A uniform shift amount in a vector shift or funnel shift may be much
8240 // cheaper than a generic variable vector shift, so make that pattern visible
8241 // to SDAG by sinking the shuffle instruction next to the shift.
8242 int ShiftAmountOpNum = -1;
8243 if (I->isShift())
8244 ShiftAmountOpNum = 1;
8245 else if (auto *II = dyn_cast<IntrinsicInst>(I)) {
8246 if (II->getIntrinsicID() == Intrinsic::fshl ||
8247 II->getIntrinsicID() == Intrinsic::fshr)
8248 ShiftAmountOpNum = 2;
8249 }
8250
8251 if (ShiftAmountOpNum == -1)
8252 return false;
8253
8254 auto *Shuf = dyn_cast<ShuffleVectorInst>(I->getOperand(ShiftAmountOpNum));
8255 if (Shuf && getSplatIndex(Shuf->getShuffleMask()) >= 0 &&
8256 isVectorShiftByScalarCheap(I->getType())) {
8257 Ops.push_back(&I->getOperandUse(ShiftAmountOpNum));
8258 return true;
8259 }
8260
8261 return false;
8262}
8263
8265 bool HasEGPR = ST->hasEGPR();
8266 const TargetMachine &TM = getTLI()->getTargetMachine();
8267
8268 for (User *U : F.users()) {
8270 if (!CB || CB->getCalledOperand() != &F)
8271 continue;
8272 Function *CallerFunc = CB->getFunction();
8273 if (TM.getSubtarget<X86Subtarget>(*CallerFunc).hasEGPR() != HasEGPR)
8274 return false;
8275 }
8276
8277 return true;
8278}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned 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:857
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
Cost tables and simple lookup functions.
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
#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)
This file implements the SmallBitVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
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.
CostTblEntryT< CostKindCosts > CostKindTblEntry
static InstructionCost getPredicateFanoutCost(const X86TTIImpl &TTI, Type *DataVTy, Type *MaskVTy)
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:329
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:316
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:730
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.
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:68
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:30
static StackOffset getScalable(int64_t Scalable)
Definition TypeSize.h:40
static StackOffset getFixed(int64_t Fixed)
Definition TypeSize.h:39
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:339
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:342
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
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
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
bool isLegalAltInstr(VectorType *VecTy, unsigned Opcode0, unsigned Opcode1, const SmallBitVector &OpcodeMask) const override
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
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
InstructionCost getAltInstrCost(VectorType *VecTy, unsigned Opcode0, unsigned Opcode1, const SmallBitVector &OpcodeMask, TTI::TargetCostKind CostKind) 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
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:180
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
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:252
#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:837
@ 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:797
@ 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:898
@ 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:757
@ 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:788
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:806
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:862
@ 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:814
@ 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:779
@ 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:868
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:359
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:737
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:996
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:944
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:749
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
Definition ISDOpcodes.h:805
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:977
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:874
@ 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.
bool match(Val *V, const Pattern &P)
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)
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
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:541
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:144
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:201
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
std::optional< unsigned > operator[](TargetTransformInfo::TargetCostKind Kind) const
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