LLVM 24.0.0git
LoongArchTargetTransformInfo.cpp
Go to the documentation of this file.
1//===-- LoongArchTargetTransformInfo.cpp - LoongArch specific TTI ---------===//
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/// LoongArch target machine. It uses the target's detailed information to
11/// provide more precise answers to certain TTI queries, while letting the
12/// target independent and default TTI implementations handle the rest.
13///
14//===----------------------------------------------------------------------===//
15
21#include "llvm/IR/InstrTypes.h"
22#include "llvm/IR/Intrinsics.h"
24
25using namespace llvm;
26
27#define DEBUG_TYPE "loongarchtti"
28
30
34 switch (K) {
36 return TypeSize::getFixed(ST->is64Bit() ? 64 : 32);
38 if (ST->hasExtLASX())
39 return TypeSize::getFixed(256);
40 if (ST->hasExtLSX())
41 return TypeSize::getFixed(128);
42 [[fallthrough]];
44 return DefSize;
45 }
46
47 llvm_unreachable("Unsupported register kind");
48}
49
50unsigned LoongArchTTIImpl::getNumberOfRegisters(unsigned ClassID) const {
51 switch (ClassID) {
52 case LoongArchRegisterClass::GPRRC:
53 // 30 = 32 GPRs - r0 (zero register) - r21 (non-allocatable)
54 return 30;
55 case LoongArchRegisterClass::FPRRC:
56 return ST->hasBasicF() ? 32 : 0;
57 case LoongArchRegisterClass::VRRC:
58 return ST->hasExtLSX() ? 32 : 0;
59 }
60 llvm_unreachable("unknown register class");
61}
62
64 Type *Ty) const {
65 if (Vector)
66 return LoongArchRegisterClass::VRRC;
67 if (!Ty)
68 return LoongArchRegisterClass::GPRRC;
69
70 Type *ScalarTy = Ty->getScalarType();
71 if ((ScalarTy->isFloatTy() && ST->hasBasicF()) ||
72 (ScalarTy->isDoubleTy() && ST->hasBasicD())) {
73 return LoongArchRegisterClass::FPRRC;
74 }
75
76 return LoongArchRegisterClass::GPRRC;
77}
78
79unsigned
81 bool HasUnorderedReductions) const {
82 return ST->getMaxInterleaveFactor();
83}
84
85const char *LoongArchTTIImpl::getRegisterClassName(unsigned ClassID) const {
86 switch (ClassID) {
87 case LoongArchRegisterClass::GPRRC:
88 return "LoongArch::GPRRC";
89 case LoongArchRegisterClass::FPRRC:
90 return "LoongArch::FPRRC";
91 case LoongArchRegisterClass::VRRC:
92 return "LoongArch::VRRC";
93 }
94 llvm_unreachable("unknown register class");
95}
96
98LoongArchTTIImpl::getPopcntSupport(unsigned TyWidth) const {
99 assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
100 return ST->hasExtLSX() ? TTI::PSK_FastHardware : TTI::PSK_Software;
101}
102
103unsigned LoongArchTTIImpl::getCacheLineSize() const { return 64; }
104
106 switch (II->getIntrinsicID()) {
107 default:
108 return true;
109 case Intrinsic::vector_reduce_add:
110 case Intrinsic::vector_reduce_and:
111 case Intrinsic::vector_reduce_or:
112 case Intrinsic::vector_reduce_smax:
113 case Intrinsic::vector_reduce_smin:
114 case Intrinsic::vector_reduce_umax:
115 case Intrinsic::vector_reduce_umin:
116 case Intrinsic::vector_reduce_xor:
117 return false;
118 }
119}
120
122 Align Alignment,
123 unsigned AddressSpace,
124 TTI::TargetCostKind CostKind,
126 const Instruction *I) const {
127 // Vectors narrower than 128 bits are widened, and on LA64 loading or storing
128 // one takes a single instruction: FLD.{S/D} or VLDREPL.{B/H} for loads, and
129 // VSTELM.{B/H/W/D} for stores. The generic model costs them as scalarized.
130 // TODO: LA32 splits 64-bit loads and doesn't use VSTELM.{W/D} for stores.
131 auto *VTy = dyn_cast<FixedVectorType>(Src);
132 if (CostKind == TTI::TCK_RecipThroughput && ST->is64Bit() &&
133 ST->hasExtLSX() && VTy && isPowerOf2_32(VTy->getNumElements())) {
134 unsigned Size = VTy->getPrimitiveSizeInBits().getFixedValue();
135 EVT VT = getTLI()->getValueType(DL, Src);
136 if (Size >= 16 && Size < 128 &&
137 getTLI()->getTypeAction(Src->getContext(), VT) ==
139 getTLI()->allowsMemoryAccessForAlignment(Src->getContext(), DL, VT,
140 AddressSpace, Alignment))
141 return 1;
142 }
143
144 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace, CostKind,
145 OpInfo, I);
146}
147
149LoongArchTTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
151
152 if (!ST->hasUAL())
153 return Options;
154
155 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
156 Options.NumLoadsPerBlock = IsZeroCmp ? Options.MaxNumLoads : 1;
157 Options.AllowOverlappingLoads = true;
158
159 // TODO: Support for vectors.
160 if (ST->is64Bit()) {
161 Options.LoadSizes = {8, 4, 2, 1};
162 Options.AllowedTailExpansions = {3, 5, 6};
163 } else {
164 Options.LoadSizes = {4, 2, 1};
165 Options.AllowedTailExpansions = {3};
166 }
167
168 return Options;
169}
170
172 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
174 ArrayRef<const Value *> Args, const Instruction *CxtI) const {
175
176 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
177 int ISD = TLI->InstructionOpcodeToISD(Opcode);
178
179 // Vector multiply by pow2 will be simplified to shifts.
180 // Vector multiply by -pow2 will be simplified to shifts/negates.
181 if (ISD == ISD::MUL && Op2Info.isConstant() &&
182 (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2())) {
184 getArithmeticInstrCost(Instruction::Shl, Ty, CostKind,
185 Op1Info.getNoProps(), Op2Info.getNoProps());
186 if (Op2Info.isNegatedPowerOf2())
187 Cost += getArithmeticInstrCost(Instruction::Sub, Ty, CostKind);
188 return Cost;
189 }
190
191 // On LoongArch, vector signed division by constants power-of-two are
192 // normally expanded to the sequence SRA + SRL + ADD + SRA.
193 // The OperandValue properties may not be the same as that of the previous
194 // operation; conservatively assume OP_None.
195 if ((ISD == ISD::SDIV || ISD == ISD::SREM) && Op2Info.isConstant() &&
196 Op2Info.isPowerOf2()) {
198 2 * getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
199 Op1Info.getNoProps(), Op2Info.getNoProps());
200 Cost += getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
201 Op1Info.getNoProps(), Op2Info.getNoProps());
202 Cost += getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
203 Op1Info.getNoProps(), Op2Info.getNoProps());
204
205 if (ISD == ISD::SREM) {
206 // For SREM: (X % C) is the equivalent of (X - (X/C)*C)
207 Cost +=
208 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
209 Op1Info.getNoProps(), Op2Info.getNoProps());
210 Cost +=
211 getArithmeticInstrCost(Instruction::Sub, Ty, CostKind,
212 Op1Info.getNoProps(), Op2Info.getNoProps());
213 }
214
215 return Cost;
216 }
217 // Vector unsigned division/remainder will be simplified to shifts/masks.
218 if ((ISD == ISD::UDIV || ISD == ISD::UREM) && Op2Info.isConstant() &&
219 Op2Info.isPowerOf2()) {
220 if (ISD == ISD::UDIV)
221 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
222 Op1Info.getNoProps(), Op2Info.getNoProps());
223 // UREM
224 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
225 Op1Info.getNoProps(), Op2Info.getNoProps());
226 }
227
228 static const CostKindTblEntry LSXCostTable[]{
229 {ISD::ADD, MVT::v16i8, {1, 1}}, // vaddi.b/vadd.b
230 {ISD::ADD, MVT::v8i16, {1, 1}}, // vaddi.h/vadd.h
231 {ISD::ADD, MVT::v4i32, {1, 1}}, // vaddi.w/vadd.w
232 {ISD::ADD, MVT::v2i64, {1, 1}}, // vaddi.d/vadd.d
233
234 {ISD::SUB, MVT::v16i8, {1, 1}}, // vsubi.b/vsub.b
235 {ISD::SUB, MVT::v8i16, {1, 1}}, // vsubi.h/vsub.h
236 {ISD::SUB, MVT::v4i32, {1, 1}}, // vsubi.w/vsub.w
237 {ISD::SUB, MVT::v2i64, {1, 1}}, // vsubi.d/vsub.d
238
239 {ISD::MUL, MVT::v16i8, {2, 4}}, // vmul.b
240 {ISD::MUL, MVT::v8i16, {2, 4}}, // vmul.h
241 {ISD::MUL, MVT::v4i32, {2, 4}}, // vmul.w
242 {ISD::MUL, MVT::v2i64, {2, 4}}, // vmul.d
243
244 {ISD::SDIV, MVT::v16i8, {62, 29}}, // vdiv.b
245 {ISD::SDIV, MVT::v8i16, {34, 17}}, // vdiv.h
246 {ISD::SDIV, MVT::v4i32, {22, 11}}, // vdiv.w
247 {ISD::SDIV, MVT::v2i64, {16, 8}}, // vdiv.d
248
249 {ISD::UDIV, MVT::v16i8, {66, 29}}, // vdiv.bu
250 {ISD::UDIV, MVT::v8i16, {36, 17}}, // vdiv.hu
251 {ISD::UDIV, MVT::v4i32, {22, 11}}, // vdiv.wu
252 {ISD::UDIV, MVT::v2i64, {16, 8}}, // vdiv.du
253
254 {ISD::SREM, MVT::v16i8, {76, 38}}, // vmod.b
255 {ISD::SREM, MVT::v8i16, {44, 24}}, // vmod.h
256 {ISD::SREM, MVT::v4i32, {27, 17}}, // vmod.w
257 {ISD::SREM, MVT::v2i64, {19, 14}}, // vmod.d
258
259 {ISD::UREM, MVT::v16i8, {80, 38}}, // vmod.bu
260 {ISD::UREM, MVT::v8i16, {44, 24}}, // vmod.hu
261 {ISD::UREM, MVT::v4i32, {28, 17}}, // vmod.wu
262 {ISD::UREM, MVT::v2i64, {19, 14}}, // vmod.du
263
264 {ISD::SHL, MVT::v16i8, {1, 1}}, // vslli.b/vsll.b
265 {ISD::SHL, MVT::v8i16, {1, 1}}, // vslli.h/vsll.h
266 {ISD::SHL, MVT::v4i32, {1, 1}}, // vslli.w/vsll.w
267 {ISD::SHL, MVT::v2i64, {1, 1}}, // vslli.d/vsll.d
268
269 {ISD::SRL, MVT::v16i8, {1, 1}}, // vsrli.b/vsrl.b
270 {ISD::SRL, MVT::v8i16, {1, 1}}, // vsrli.h/vsrl.h
271 {ISD::SRL, MVT::v4i32, {1, 1}}, // vsrli.w/vsrl.w
272 {ISD::SRL, MVT::v2i64, {1, 1}}, // vsrli.d/vsrl.d
273
274 {ISD::SRA, MVT::v16i8, {1, 1}}, // vsrai.b/vsra.b
275 {ISD::SRA, MVT::v8i16, {1, 1}}, // vsrai.h/vsra.h
276 {ISD::SRA, MVT::v4i32, {1, 1}}, // vsrai.w/vsra.w
277 {ISD::SRA, MVT::v2i64, {1, 1}}, // vsrai.d/vsra.d
278
279 {ISD::AND, MVT::v16i8, {1, 1}}, // vand.b/vand.v
280 {ISD::AND, MVT::v8i16, {1, 1}}, // vand.v
281 {ISD::AND, MVT::v4i32, {1, 1}}, // vand.v
282 {ISD::AND, MVT::v2i64, {1, 1}}, // vand.v
283
284 {ISD::OR, MVT::v16i8, {1, 1}}, // vori.b/vor.v
285 {ISD::OR, MVT::v8i16, {1, 1}}, // vor.v
286 {ISD::OR, MVT::v4i32, {1, 1}}, // vor.v
287 {ISD::OR, MVT::v2i64, {1, 1}}, // vor.v
288
289 {ISD::XOR, MVT::v16i8, {1, 1}}, // vxori.b/vxor.v
290 {ISD::XOR, MVT::v8i16, {1, 1}}, // vxor.v
291 {ISD::XOR, MVT::v4i32, {1, 1}}, // vxor.v
292 {ISD::XOR, MVT::v2i64, {1, 1}}, // vxor.v
293
294 {ISD::FADD, MVT::v4f32, {1, 3}}, // vfadd.s
295 {ISD::FADD, MVT::v2f64, {1, 3}}, // vfadd.d
296
297 {ISD::FSUB, MVT::v4f32, {1, 3}}, // vfsub.s
298 {ISD::FSUB, MVT::v2f64, {1, 3}}, // vfsub.d
299
300 {ISD::FMUL, MVT::v4f32, {2, 5}}, // vfmul.s
301 {ISD::FMUL, MVT::v2f64, {2, 5}}, // vfmul.d
302
303 {ISD::FDIV, MVT::v4f32, {22, 11}}, // vfdiv.s
304 {ISD::FDIV, MVT::v2f64, {16, 8}}, // vfdiv.d
305 };
306
307 if (ST->hasExtLSX()) {
308 if (const auto *Entry = CostTableLookup(LSXCostTable, ISD, LT.second))
309 if (auto KindCost = Entry->Cost[CostKind])
310 return LT.first * *KindCost;
311 }
312
313 static const CostKindTblEntry LASXUniformConstCostTable[]{
314 {ISD::ADD, MVT::v32i8, {1, 1}}, // xvaddi.b/xvadd.b
315 {ISD::ADD, MVT::v16i16, {1, 1}}, // xvaddi.h/xvadd.h
316 {ISD::ADD, MVT::v8i32, {1, 1}}, // xvaddi.w/xvadd.w
317 {ISD::ADD, MVT::v4i64, {1, 1}}, // xvaddi.d/xvadd.d
318
319 {ISD::SUB, MVT::v32i8, {1, 1}}, // xvsubi.b/xvsub.b
320 {ISD::SUB, MVT::v16i16, {1, 1}}, // xvsubi.h/xvsub.h
321 {ISD::SUB, MVT::v8i32, {1, 1}}, // xvsubi.w/xvsub.w
322 {ISD::SUB, MVT::v4i64, {1, 1}}, // xvsubi.d/xvsub.d
323
324 {ISD::MUL, MVT::v32i8, {2, 4}}, // xvmul.b
325 {ISD::MUL, MVT::v16i16, {2, 4}}, // xvmul.h
326 {ISD::MUL, MVT::v8i32, {2, 4}}, // xvmul.w
327 {ISD::MUL, MVT::v4i64, {2, 4}}, // xvmul.d
328
329 {ISD::SDIV, MVT::v32i8, {62, 29}}, // xvdiv.b
330 {ISD::SDIV, MVT::v16i16, {34, 17}}, // xvdiv.h
331 {ISD::SDIV, MVT::v8i32, {22, 11}}, // xvdiv.w
332 {ISD::SDIV, MVT::v4i64, {16, 8}}, // xvdiv.d
333
334 {ISD::UDIV, MVT::v32i8, {66, 29}}, // xvdiv.bu
335 {ISD::UDIV, MVT::v16i16, {36, 17}}, // xvdiv.hu
336 {ISD::UDIV, MVT::v8i32, {22, 11}}, // xvdiv.wu
337 {ISD::UDIV, MVT::v4i64, {16, 8}}, // xvdiv.du
338
339 {ISD::SREM, MVT::v32i8, {76, 38}}, // xvmod.b
340 {ISD::SREM, MVT::v16i16, {44, 24}}, // xvmod.h
341 {ISD::SREM, MVT::v8i32, {28, 17}}, // xvmod.w
342 {ISD::SREM, MVT::v4i64, {19, 14}}, // xvmod.d
343
344 {ISD::UREM, MVT::v32i8, {76, 38}}, // xvmod.bu
345 {ISD::UREM, MVT::v16i16, {43, 24}}, // xvmod.hu
346 {ISD::UREM, MVT::v8i32, {28, 17}}, // xvmod.wu
347 {ISD::UREM, MVT::v4i64, {19, 14}}, // xvmod.du
348
349 {ISD::SHL, MVT::v32i8, {1, 1}}, // xvslli.b/xvsll.b
350 {ISD::SHL, MVT::v16i16, {1, 1}}, // xvslli.h/xvsll.h
351 {ISD::SHL, MVT::v8i32, {1, 1}}, // xvslli.w/xvsll.w
352 {ISD::SHL, MVT::v4i64, {1, 1}}, // xvslli.d/xvsll.d
353
354 {ISD::SRL, MVT::v32i8, {1, 1}}, // xvsrli.b/xvsrl.b
355 {ISD::SRL, MVT::v16i16, {1, 1}}, // xvsrli.h/xvsrl.h
356 {ISD::SRL, MVT::v8i32, {1, 1}}, // xvsrli.w/xvsrl.w
357 {ISD::SRL, MVT::v4i64, {1, 1}}, // xvsrli.d/xvsrl.d
358
359 {ISD::SRA, MVT::v32i8, {1, 1}}, // xvsrai.b/xvsra.b
360 {ISD::SRA, MVT::v16i16, {1, 1}}, // xvsrai.h/xvsra.h
361 {ISD::SRA, MVT::v8i32, {1, 1}}, // xvsrai.w/xvsra.w
362 {ISD::SRA, MVT::v4i64, {1, 1}}, // xvsrai.d/xvsra.d
363
364 {ISD::AND, MVT::v32i8, {1, 1}}, // xvandi.b/xvand.v
365 {ISD::AND, MVT::v16i16, {1, 1}}, // xvand.v
366 {ISD::AND, MVT::v8i32, {1, 1}}, // xvand.v
367 {ISD::AND, MVT::v4i64, {1, 1}}, // xvand.v
368
369 {ISD::OR, MVT::v32i8, {1, 1}}, // xvori.b/xvor.v
370 {ISD::OR, MVT::v16i16, {1, 1}}, // xvor.v
371 {ISD::OR, MVT::v8i32, {1, 1}}, // xvor.v
372 {ISD::OR, MVT::v4i64, {1, 1}}, // xvor.v
373
374 {ISD::XOR, MVT::v32i8, {1, 1}}, // xvxori.b/xvxor.v
375 {ISD::XOR, MVT::v16i16, {1, 1}}, // xvxor.v
376 {ISD::XOR, MVT::v8i32, {1, 1}}, // xvxor.v
377 {ISD::XOR, MVT::v4i64, {1, 1}}, // xvxor.v
378
379 {ISD::FADD, MVT::v8f32, {1, 3}}, // xvfadd.s
380 {ISD::FADD, MVT::v4f64, {1, 3}}, // xvfadd.d
381
382 {ISD::FSUB, MVT::v8f32, {1, 3}}, // xvfsub.s
383 {ISD::FSUB, MVT::v4f64, {1, 3}}, // xvfsub.d
384
385 {ISD::FMUL, MVT::v8f32, {2, 5}}, // xvfmul.s
386 {ISD::FMUL, MVT::v4f64, {2, 5}}, // xvfmul.d
387
388 {ISD::FDIV, MVT::v8f32, {22, 11}}, // xvfdiv.s
389 {ISD::FDIV, MVT::v4f64, {16, 8}}, // xvfdiv.d
390 };
391
392 if (ST->hasExtLASX()) {
393 if (const auto *Entry =
394 CostTableLookup(LASXUniformConstCostTable, ISD, LT.second))
395 if (auto KindCost = Entry->Cost[CostKind])
396 return LT.first * *KindCost;
397 }
398
399 static const CostKindTblEntry LA64CostTable[]{
400 {ISD::ADD, MVT::i64, {1, 1}}, // addi.d/add.d
401 {ISD::SUB, MVT::i64, {1, 1}}, // subi.d/sub.d
402 {ISD::MUL, MVT::i64, {2, 4}}, // mul.d
403
404 {ISD::SDIV, MVT::i64, {26, 18}}, // div.d
405 {ISD::UDIV, MVT::i64, {26, 18}}, // div.du
406 {ISD::SREM, MVT::i64, {26, 18}}, // mod.d
407 {ISD::UREM, MVT::i64, {26, 18}}, // mod.du
408
409 {ISD::SHL, MVT::i64, {1, 1}}, // slli.d/sll.d
410 {ISD::SRL, MVT::i64, {1, 1}}, // srli.d/srl.d
411 {ISD::SRA, MVT::i64, {1, 1}}, // srai.d/sra.d
412
413 {ISD::AND, MVT::i64, {1, 1}}, // andi.d/and.d
414 {ISD::OR, MVT::i64, {1, 1}}, // ori.d/or.d
415 {ISD::XOR, MVT::i64, {1, 1}}, // xori.d/xor.d
416
417 {ISD::FADD, MVT::f64, {1, 3}}, // fadd.d
418 {ISD::FSUB, MVT::f64, {1, 3}}, // fsub.d
419 {ISD::FMUL, MVT::f64, {2, 5}}, // fmul.d
420 {ISD::FDIV, MVT::f64, {9, 12}}, // fdiv.d
421 };
422
423 if (ST->is64Bit()) {
424 if (const auto *Entry = CostTableLookup(LA64CostTable, ISD, LT.second))
425 if (auto KindCost = Entry->Cost[CostKind])
426 return LT.first * *KindCost;
427 }
428
429 static const CostKindTblEntry LA32CostTable[]{
430 {ISD::ADD, MVT::i32, {1, 1}}, // addi.w/add.w
431 {ISD::SUB, MVT::i32, {1, 1}}, // subi.w/sub.w
432 {ISD::MUL, MVT::i32, {2, 4}}, // mul.w
433
434 {ISD::SDIV, MVT::i32, {24, 11}}, // div.w
435 {ISD::UDIV, MVT::i32, {24, 12}}, // div.wu
436 {ISD::SREM, MVT::i32, {24, 11}}, // mod.w
437 {ISD::UREM, MVT::i32, {24, 12}}, // mod.wu
438
439 {ISD::SHL, MVT::i32, {1, 1}}, // slli.w/sll.w
440 {ISD::SRL, MVT::i32, {1, 1}}, // srli.w/srl.w
441 {ISD::SRA, MVT::i32, {1, 1}}, // srai.w/sra.w
442
443 {ISD::AND, MVT::i32, {1, 1}}, // andi.w/and.w
444 {ISD::OR, MVT::i32, {1, 1}}, // ori.w/or.w
445 {ISD::XOR, MVT::i32, {1, 1}}, // xori.w/xor.w
446
447 {ISD::FADD, MVT::f32, {1, 3}}, // fadd.s
448 {ISD::FSUB, MVT::f32, {1, 3}}, // fsub.s
449 {ISD::FMUL, MVT::f32, {2, 5}}, // fmul.s
450 {ISD::FDIV, MVT::f32, {8, 9}}, // fdiv.s
451 };
452
453 if (const auto *Entry = CostTableLookup(LA32CostTable, ISD, LT.second))
454 if (auto KindCost = Entry->Cost[CostKind])
455 return LT.first * *KindCost;
456
457 // Fallback to the default implementation.
458 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info,
459 Args, CxtI);
460}
461
462// Returns true if Ty is a fixed vector type held in a single LSX/LASX register.
463static bool isSingleVRegType(const LoongArchSubtarget *ST, Type *Ty) {
464 auto *VTy = dyn_cast<FixedVectorType>(Ty);
465 if (!VTy)
466 return false;
467 unsigned Bits = VTy->getPrimitiveSizeInBits().getFixedValue();
468 return (Bits == 128 && ST->hasExtLSX()) || (Bits == 256 && ST->hasExtLASX());
469}
470
472 unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,
473 const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC) const {
474 // Element 0 of a floating-point vector is the aliased FPR, so extracting it
475 // is free.
476 if (Opcode == Instruction::ExtractElement && Index == 0 &&
478 return 0;
479 return BaseT::getVectorInstrCost(Opcode, Val, CostKind, Index, Op0, Op1, VIC);
480}
481
483 TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy,
484 TTI::TargetCostKind CostKind, ArrayRef<int> Mask, int Index,
485 VectorType *SubTp, ArrayRef<const Value *> Args, const Instruction *CxtI,
486 TTI::VectorInstrContext VIC) const {
487 if (isSingleVRegType(ST, SrcTy) && DstTy == SrcTy) {
488 Kind = improveShuffleKindFromMask(Kind, Mask, SrcTy, Index, SubTp);
489 unsigned EltBits = SrcTy->getScalarSizeInBits();
490 bool Is128 = SrcTy->getPrimitiveSizeInBits().getFixedValue() == 128;
491 switch (Kind) {
493 // [x]vreplvei.{b/h/w/d}, xvreplve0.{b/h/w/d}, [x]vreplgr2vr.{b/h/w/d}.
494 return 1;
495 case TTI::SK_Reverse:
497 // vshuf4i.{w/d} handles any single-source permutation of 32/64-bit
498 // elements within a 128-bit register.
499 if (Is128 && EltBits >= 32)
500 return 1;
501 break;
502 default:
503 break;
504 }
505 }
506 return BaseT::getShuffleCost(Kind, DstTy, SrcTy, CostKind, Mask, Index, SubTp,
507 Args, CxtI, VIC);
508}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Cost tables and simple lookup functions.
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
static LVOptions Options
Definition LVOptions.cpp:25
CostTblEntryT< CostKindCosts > CostKindTblEntry
static bool isSingleVRegType(const LoongArchSubtarget *ST, Type *Ty)
This file a TargetTransformInfoImplBase conforming object specific to the LoongArch target machine.
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
This pass exposes codegen information to IR-level passes.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
TTI::ShuffleKind improveShuffleKindFromMask(TTI::ShuffleKind Kind, ArrayRef< int > Mask, VectorType *SrcTy, int &Index, VectorType *&SubTy) const
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
std::pair< InstructionCost, MVT > getTypeLegalizationCost(Type *Ty) const
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 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
A wrapper class for inspecting calls to intrinsic functions.
TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override
unsigned getCacheLineSize() const override
unsigned getMaxInterleaveFactor(ElementCount VF, bool HasUnorderedReductions) const override
bool shouldExpandReduction(const IntrinsicInst *II) const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) const override
unsigned getRegisterClassForType(bool Vector, Type *Ty=nullptr) const override
TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) 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
const char * getRegisterClassName(unsigned ClassID) const override
unsigned getNumberOfRegisters(unsigned ClassID) 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 *CxtI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) 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
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override
virtual TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const
TargetCostKind
The kind of cost model.
@ TCK_RecipThroughput
Reciprocal throughput.
PopcntSupportKind
Flags indicating the kind of support for population count.
llvm::VectorInstrContext VectorInstrContext
ShuffleKind
The various kinds of shuffle patterns for vector queries.
@ SK_PermuteSingleSrc
Shuffle elements of single source vector with any shuffle mask.
@ SK_Broadcast
Broadcast element 0 to all other elements.
@ SK_Reverse
Reverse the order of the vector.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:352
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition Type.h:155
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition Type.h:158
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
LLVM Value Representation.
Definition Value.h:75
Base class of all SIMD vector types.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ISD namespace - This namespace contains an enum which represents all of the SelectionDAG node types a...
Definition ISDOpcodes.h:26
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:420
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
This is an optimization pass for GlobalISel generic memory operations.
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
Definition CostTable.h:36
InstructionCost Cost
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
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
Returns options for expansion of memcmp. IsZeroCmp is.