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#include <optional>
25
26using namespace llvm;
27
28#define DEBUG_TYPE "loongarchtti"
29
30namespace {
31struct CostKindCosts {
32 unsigned LatencyCost = ~0U;
33 unsigned RecipThroughputCost = ~0U;
34 unsigned CodeSizeCost = ~0U;
35 unsigned SizeAndLatencyCost = ~0U;
36
37 std::optional<unsigned>
38 operator[](TargetTransformInfo::TargetCostKind Kind) const {
39 unsigned Cost = ~0U;
40 switch (Kind) {
42 Cost = LatencyCost;
43 break;
45 Cost = RecipThroughputCost;
46 break;
48 Cost = CodeSizeCost;
49 break;
51 Cost = SizeAndLatencyCost;
52 break;
53 }
54 if (Cost == ~0U)
55 return std::nullopt;
56 return Cost;
57 }
58};
59} // namespace
61
65 switch (K) {
67 return TypeSize::getFixed(ST->is64Bit() ? 64 : 32);
69 if (ST->hasExtLASX())
70 return TypeSize::getFixed(256);
71 if (ST->hasExtLSX())
72 return TypeSize::getFixed(128);
73 [[fallthrough]];
75 return DefSize;
76 }
77
78 llvm_unreachable("Unsupported register kind");
79}
80
81unsigned LoongArchTTIImpl::getNumberOfRegisters(unsigned ClassID) const {
82 switch (ClassID) {
83 case LoongArchRegisterClass::GPRRC:
84 // 30 = 32 GPRs - r0 (zero register) - r21 (non-allocatable)
85 return 30;
86 case LoongArchRegisterClass::FPRRC:
87 return ST->hasBasicF() ? 32 : 0;
88 case LoongArchRegisterClass::VRRC:
89 return ST->hasExtLSX() ? 32 : 0;
90 }
91 llvm_unreachable("unknown register class");
92}
93
95 Type *Ty) const {
96 if (Vector)
97 return LoongArchRegisterClass::VRRC;
98 if (!Ty)
99 return LoongArchRegisterClass::GPRRC;
100
101 Type *ScalarTy = Ty->getScalarType();
102 if ((ScalarTy->isFloatTy() && ST->hasBasicF()) ||
103 (ScalarTy->isDoubleTy() && ST->hasBasicD())) {
104 return LoongArchRegisterClass::FPRRC;
105 }
106
107 return LoongArchRegisterClass::GPRRC;
108}
109
110unsigned
112 bool HasUnorderedReductions) const {
113 return ST->getMaxInterleaveFactor();
114}
115
116const char *LoongArchTTIImpl::getRegisterClassName(unsigned ClassID) const {
117 switch (ClassID) {
118 case LoongArchRegisterClass::GPRRC:
119 return "LoongArch::GPRRC";
120 case LoongArchRegisterClass::FPRRC:
121 return "LoongArch::FPRRC";
122 case LoongArchRegisterClass::VRRC:
123 return "LoongArch::VRRC";
124 }
125 llvm_unreachable("unknown register class");
126}
127
129LoongArchTTIImpl::getPopcntSupport(unsigned TyWidth) const {
130 assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
131 return ST->hasExtLSX() ? TTI::PSK_FastHardware : TTI::PSK_Software;
132}
133
134unsigned LoongArchTTIImpl::getCacheLineSize() const { return 64; }
135
136unsigned LoongArchTTIImpl::getPrefetchDistance() const { return 200; }
137
138bool LoongArchTTIImpl::enableWritePrefetching() const { return true; }
139
141 switch (II->getIntrinsicID()) {
142 default:
143 return true;
144 case Intrinsic::vector_reduce_add:
145 case Intrinsic::vector_reduce_and:
146 case Intrinsic::vector_reduce_or:
147 case Intrinsic::vector_reduce_smax:
148 case Intrinsic::vector_reduce_smin:
149 case Intrinsic::vector_reduce_umax:
150 case Intrinsic::vector_reduce_umin:
151 case Intrinsic::vector_reduce_xor:
152 return false;
153 }
154}
155
157 Align Alignment,
158 unsigned AddressSpace,
159 TTI::TargetCostKind CostKind,
161 const Instruction *I) const {
162 // Vectors narrower than 128 bits are widened, and on LA64 loading or storing
163 // one takes a single instruction: FLD.{S/D} or VLDREPL.{B/H} for loads, and
164 // VSTELM.{B/H/W/D} for stores. The generic model costs them as scalarized.
165 // TODO: LA32 splits 64-bit loads and doesn't use VSTELM.{W/D} for stores.
166 auto *VTy = dyn_cast<FixedVectorType>(Src);
167 if (CostKind == TTI::TCK_RecipThroughput && ST->is64Bit() &&
168 ST->hasExtLSX() && VTy && isPowerOf2_32(VTy->getNumElements())) {
169 unsigned Size = VTy->getPrimitiveSizeInBits().getFixedValue();
170 EVT VT = getTLI()->getValueType(DL, Src);
171 if (Size >= 16 && Size < 128 &&
172 getTLI()->getTypeAction(Src->getContext(), VT) ==
174 getTLI()->allowsMemoryAccessForAlignment(Src->getContext(), DL, VT,
175 AddressSpace, Alignment))
176 return 1;
177 }
178
179 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace, CostKind,
180 OpInfo, I);
181}
182
184LoongArchTTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
186
187 if (!ST->hasUAL())
188 return Options;
189
190 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
191 Options.NumLoadsPerBlock = IsZeroCmp ? Options.MaxNumLoads : 1;
192 Options.AllowOverlappingLoads = true;
193
194 // TODO: Support for vectors.
195 if (ST->is64Bit()) {
196 Options.LoadSizes = {8, 4, 2, 1};
197 Options.AllowedTailExpansions = {3, 5, 6};
198 } else {
199 Options.LoadSizes = {4, 2, 1};
200 Options.AllowedTailExpansions = {3};
201 }
202
203 return Options;
204}
205
207 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
209 ArrayRef<const Value *> Args, const Instruction *CxtI) const {
210
211 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
212 int ISD = TLI->InstructionOpcodeToISD(Opcode);
213
214 // Vector multiply by pow2 will be simplified to shifts.
215 // Vector multiply by -pow2 will be simplified to shifts/negates.
216 if (ISD == ISD::MUL && Op2Info.isConstant() &&
217 (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2())) {
219 getArithmeticInstrCost(Instruction::Shl, Ty, CostKind,
220 Op1Info.getNoProps(), Op2Info.getNoProps());
221 if (Op2Info.isNegatedPowerOf2())
222 Cost += getArithmeticInstrCost(Instruction::Sub, Ty, CostKind);
223 return Cost;
224 }
225
226 // On LoongArch, vector signed division by constants power-of-two are
227 // normally expanded to the sequence SRA + SRL + ADD + SRA.
228 // The OperandValue properties may not be the same as that of the previous
229 // operation; conservatively assume OP_None.
230 if ((ISD == ISD::SDIV || ISD == ISD::SREM) && Op2Info.isConstant() &&
231 Op2Info.isPowerOf2()) {
233 2 * getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
234 Op1Info.getNoProps(), Op2Info.getNoProps());
235 Cost += getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
236 Op1Info.getNoProps(), Op2Info.getNoProps());
237 Cost += getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
238 Op1Info.getNoProps(), Op2Info.getNoProps());
239
240 if (ISD == ISD::SREM) {
241 // For SREM: (X % C) is the equivalent of (X - (X/C)*C)
242 Cost +=
243 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
244 Op1Info.getNoProps(), Op2Info.getNoProps());
245 Cost +=
246 getArithmeticInstrCost(Instruction::Sub, Ty, CostKind,
247 Op1Info.getNoProps(), Op2Info.getNoProps());
248 }
249
250 return Cost;
251 }
252 // Vector unsigned division/remainder will be simplified to shifts/masks.
253 if ((ISD == ISD::UDIV || ISD == ISD::UREM) && Op2Info.isConstant() &&
254 Op2Info.isPowerOf2()) {
255 if (ISD == ISD::UDIV)
256 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
257 Op1Info.getNoProps(), Op2Info.getNoProps());
258 // UREM
259 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
260 Op1Info.getNoProps(), Op2Info.getNoProps());
261 }
262
263 static const CostKindTblEntry LSXCostTable[]{
264 {ISD::ADD, MVT::v16i8, {1, 1}}, // vaddi.b/vadd.b
265 {ISD::ADD, MVT::v8i16, {1, 1}}, // vaddi.h/vadd.h
266 {ISD::ADD, MVT::v4i32, {1, 1}}, // vaddi.w/vadd.w
267 {ISD::ADD, MVT::v2i64, {1, 1}}, // vaddi.d/vadd.d
268
269 {ISD::SUB, MVT::v16i8, {1, 1}}, // vsubi.b/vsub.b
270 {ISD::SUB, MVT::v8i16, {1, 1}}, // vsubi.h/vsub.h
271 {ISD::SUB, MVT::v4i32, {1, 1}}, // vsubi.w/vsub.w
272 {ISD::SUB, MVT::v2i64, {1, 1}}, // vsubi.d/vsub.d
273
274 {ISD::MUL, MVT::v16i8, {4, 2}}, // vmul.b
275 {ISD::MUL, MVT::v8i16, {4, 2}}, // vmul.h
276 {ISD::MUL, MVT::v4i32, {4, 2}}, // vmul.w
277 {ISD::MUL, MVT::v2i64, {4, 2}}, // vmul.d
278
279 {ISD::SDIV, MVT::v16i8, {29, 62}}, // vdiv.b
280 {ISD::SDIV, MVT::v8i16, {17, 34}}, // vdiv.h
281 {ISD::SDIV, MVT::v4i32, {11, 22}}, // vdiv.w
282 {ISD::SDIV, MVT::v2i64, {8, 16}}, // vdiv.d
283
284 {ISD::UDIV, MVT::v16i8, {29, 66}}, // vdiv.bu
285 {ISD::UDIV, MVT::v8i16, {17, 36}}, // vdiv.hu
286 {ISD::UDIV, MVT::v4i32, {11, 22}}, // vdiv.wu
287 {ISD::UDIV, MVT::v2i64, {8, 16}}, // vdiv.du
288
289 {ISD::SREM, MVT::v16i8, {38, 76}}, // vmod.b
290 {ISD::SREM, MVT::v8i16, {24, 44}}, // vmod.h
291 {ISD::SREM, MVT::v4i32, {17, 27}}, // vmod.w
292 {ISD::SREM, MVT::v2i64, {14, 19}}, // vmod.d
293
294 {ISD::UREM, MVT::v16i8, {38, 80}}, // vmod.bu
295 {ISD::UREM, MVT::v8i16, {24, 44}}, // vmod.hu
296 {ISD::UREM, MVT::v4i32, {17, 28}}, // vmod.wu
297 {ISD::UREM, MVT::v2i64, {14, 19}}, // vmod.du
298
299 {ISD::SHL, MVT::v16i8, {1, 1}}, // vslli.b/vsll.b
300 {ISD::SHL, MVT::v8i16, {1, 1}}, // vslli.h/vsll.h
301 {ISD::SHL, MVT::v4i32, {1, 1}}, // vslli.w/vsll.w
302 {ISD::SHL, MVT::v2i64, {1, 1}}, // vslli.d/vsll.d
303
304 {ISD::SRL, MVT::v16i8, {1, 1}}, // vsrli.b/vsrl.b
305 {ISD::SRL, MVT::v8i16, {1, 1}}, // vsrli.h/vsrl.h
306 {ISD::SRL, MVT::v4i32, {1, 1}}, // vsrli.w/vsrl.w
307 {ISD::SRL, MVT::v2i64, {1, 1}}, // vsrli.d/vsrl.d
308
309 {ISD::SRA, MVT::v16i8, {1, 1}}, // vsrai.b/vsra.b
310 {ISD::SRA, MVT::v8i16, {1, 1}}, // vsrai.h/vsra.h
311 {ISD::SRA, MVT::v4i32, {1, 1}}, // vsrai.w/vsra.w
312 {ISD::SRA, MVT::v2i64, {1, 1}}, // vsrai.d/vsra.d
313
314 {ISD::AND, MVT::v16i8, {1, 1}}, // vand.b/vand.v
315 {ISD::AND, MVT::v8i16, {1, 1}}, // vand.v
316 {ISD::AND, MVT::v4i32, {1, 1}}, // vand.v
317 {ISD::AND, MVT::v2i64, {1, 1}}, // vand.v
318
319 {ISD::OR, MVT::v16i8, {1, 1}}, // vori.b/vor.v
320 {ISD::OR, MVT::v8i16, {1, 1}}, // vor.v
321 {ISD::OR, MVT::v4i32, {1, 1}}, // vor.v
322 {ISD::OR, MVT::v2i64, {1, 1}}, // vor.v
323
324 {ISD::XOR, MVT::v16i8, {1, 1}}, // vxori.b/vxor.v
325 {ISD::XOR, MVT::v8i16, {1, 1}}, // vxor.v
326 {ISD::XOR, MVT::v4i32, {1, 1}}, // vxor.v
327 {ISD::XOR, MVT::v2i64, {1, 1}}, // vxor.v
328
329 {ISD::FADD, MVT::v4f32, {3, 1}}, // vfadd.s
330 {ISD::FADD, MVT::v2f64, {3, 1}}, // vfadd.d
331
332 {ISD::FSUB, MVT::v4f32, {3, 1}}, // vfsub.s
333 {ISD::FSUB, MVT::v2f64, {3, 1}}, // vfsub.d
334
335 {ISD::FMUL, MVT::v4f32, {5, 2}}, // vfmul.s
336 {ISD::FMUL, MVT::v2f64, {5, 2}}, // vfmul.d
337
338 {ISD::FDIV, MVT::v4f32, {11, 22}}, // vfdiv.s
339 {ISD::FDIV, MVT::v2f64, {8, 16}}, // vfdiv.d
340 };
341
342 if (ST->hasExtLSX()) {
343 if (const auto *Entry = CostTableLookup(LSXCostTable, ISD, LT.second))
344 if (auto KindCost = Entry->Cost[CostKind])
345 return LT.first * *KindCost;
346 }
347
348 static const CostKindTblEntry LASXUniformConstCostTable[]{
349 {ISD::ADD, MVT::v32i8, {1, 1}}, // xvaddi.b/xvadd.b
350 {ISD::ADD, MVT::v16i16, {1, 1}}, // xvaddi.h/xvadd.h
351 {ISD::ADD, MVT::v8i32, {1, 1}}, // xvaddi.w/xvadd.w
352 {ISD::ADD, MVT::v4i64, {1, 1}}, // xvaddi.d/xvadd.d
353
354 {ISD::SUB, MVT::v32i8, {1, 1}}, // xvsubi.b/xvsub.b
355 {ISD::SUB, MVT::v16i16, {1, 1}}, // xvsubi.h/xvsub.h
356 {ISD::SUB, MVT::v8i32, {1, 1}}, // xvsubi.w/xvsub.w
357 {ISD::SUB, MVT::v4i64, {1, 1}}, // xvsubi.d/xvsub.d
358
359 {ISD::MUL, MVT::v32i8, {4, 2}}, // xvmul.b
360 {ISD::MUL, MVT::v16i16, {4, 2}}, // xvmul.h
361 {ISD::MUL, MVT::v8i32, {4, 2}}, // xvmul.w
362 {ISD::MUL, MVT::v4i64, {4, 2}}, // xvmul.d
363
364 {ISD::SDIV, MVT::v32i8, {29, 62}}, // xvdiv.b
365 {ISD::SDIV, MVT::v16i16, {17, 34}}, // xvdiv.h
366 {ISD::SDIV, MVT::v8i32, {11, 22}}, // xvdiv.w
367 {ISD::SDIV, MVT::v4i64, {8, 16}}, // xvdiv.d
368
369 {ISD::UDIV, MVT::v32i8, {29, 66}}, // xvdiv.bu
370 {ISD::UDIV, MVT::v16i16, {17, 36}}, // xvdiv.hu
371 {ISD::UDIV, MVT::v8i32, {11, 22}}, // xvdiv.wu
372 {ISD::UDIV, MVT::v4i64, {8, 16}}, // xvdiv.du
373
374 {ISD::SREM, MVT::v32i8, {38, 76}}, // xvmod.b
375 {ISD::SREM, MVT::v16i16, {24, 44}}, // xvmod.h
376 {ISD::SREM, MVT::v8i32, {17, 28}}, // xvmod.w
377 {ISD::SREM, MVT::v4i64, {14, 19}}, // xvmod.d
378
379 {ISD::UREM, MVT::v32i8, {38, 76}}, // xvmod.bu
380 {ISD::UREM, MVT::v16i16, {24, 43}}, // xvmod.hu
381 {ISD::UREM, MVT::v8i32, {17, 28}}, // xvmod.wu
382 {ISD::UREM, MVT::v4i64, {14, 19}}, // xvmod.du
383
384 {ISD::SHL, MVT::v32i8, {1, 1}}, // xvslli.b/xvsll.b
385 {ISD::SHL, MVT::v16i16, {1, 1}}, // xvslli.h/xvsll.h
386 {ISD::SHL, MVT::v8i32, {1, 1}}, // xvslli.w/xvsll.w
387 {ISD::SHL, MVT::v4i64, {1, 1}}, // xvslli.d/xvsll.d
388
389 {ISD::SRL, MVT::v32i8, {1, 1}}, // xvsrli.b/xvsrl.b
390 {ISD::SRL, MVT::v16i16, {1, 1}}, // xvsrli.h/xvsrl.h
391 {ISD::SRL, MVT::v8i32, {1, 1}}, // xvsrli.w/xvsrl.w
392 {ISD::SRL, MVT::v4i64, {1, 1}}, // xvsrli.d/xvsrl.d
393
394 {ISD::SRA, MVT::v32i8, {1, 1}}, // xvsrai.b/xvsra.b
395 {ISD::SRA, MVT::v16i16, {1, 1}}, // xvsrai.h/xvsra.h
396 {ISD::SRA, MVT::v8i32, {1, 1}}, // xvsrai.w/xvsra.w
397 {ISD::SRA, MVT::v4i64, {1, 1}}, // xvsrai.d/xvsra.d
398
399 {ISD::AND, MVT::v32i8, {1, 1}}, // xvandi.b/xvand.v
400 {ISD::AND, MVT::v16i16, {1, 1}}, // xvand.v
401 {ISD::AND, MVT::v8i32, {1, 1}}, // xvand.v
402 {ISD::AND, MVT::v4i64, {1, 1}}, // xvand.v
403
404 {ISD::OR, MVT::v32i8, {1, 1}}, // xvori.b/xvor.v
405 {ISD::OR, MVT::v16i16, {1, 1}}, // xvor.v
406 {ISD::OR, MVT::v8i32, {1, 1}}, // xvor.v
407 {ISD::OR, MVT::v4i64, {1, 1}}, // xvor.v
408
409 {ISD::XOR, MVT::v32i8, {1, 1}}, // xvxori.b/xvxor.v
410 {ISD::XOR, MVT::v16i16, {1, 1}}, // xvxor.v
411 {ISD::XOR, MVT::v8i32, {1, 1}}, // xvxor.v
412 {ISD::XOR, MVT::v4i64, {1, 1}}, // xvxor.v
413
414 {ISD::FADD, MVT::v8f32, {3, 1}}, // xvfadd.s
415 {ISD::FADD, MVT::v4f64, {3, 1}}, // xvfadd.d
416
417 {ISD::FSUB, MVT::v8f32, {3, 1}}, // xvfsub.s
418 {ISD::FSUB, MVT::v4f64, {3, 1}}, // xvfsub.d
419
420 {ISD::FMUL, MVT::v8f32, {5, 2}}, // xvfmul.s
421 {ISD::FMUL, MVT::v4f64, {5, 2}}, // xvfmul.d
422
423 {ISD::FDIV, MVT::v8f32, {11, 22}}, // xvfdiv.s
424 {ISD::FDIV, MVT::v4f64, {8, 16}}, // xvfdiv.d
425 };
426
427 if (ST->hasExtLASX()) {
428 if (const auto *Entry =
429 CostTableLookup(LASXUniformConstCostTable, ISD, LT.second))
430 if (auto KindCost = Entry->Cost[CostKind])
431 return LT.first * *KindCost;
432 }
433
434 static const CostKindTblEntry LA64CostTable[]{
435 {ISD::ADD, MVT::i64, {1, 1}}, // addi.d/add.d
436 {ISD::SUB, MVT::i64, {1, 1}}, // subi.d/sub.d
437 {ISD::MUL, MVT::i64, {4, 2}}, // mul.d
438
439 {ISD::SDIV, MVT::i64, {18, 26}}, // div.d
440 {ISD::UDIV, MVT::i64, {18, 26}}, // div.du
441 {ISD::SREM, MVT::i64, {18, 26}}, // mod.d
442 {ISD::UREM, MVT::i64, {18, 26}}, // mod.du
443
444 {ISD::SHL, MVT::i64, {1, 1}}, // slli.d/sll.d
445 {ISD::SRL, MVT::i64, {1, 1}}, // srli.d/srl.d
446 {ISD::SRA, MVT::i64, {1, 1}}, // srai.d/sra.d
447
448 {ISD::AND, MVT::i64, {1, 1}}, // andi.d/and.d
449 {ISD::OR, MVT::i64, {1, 1}}, // ori.d/or.d
450 {ISD::XOR, MVT::i64, {1, 1}}, // xori.d/xor.d
451
452 {ISD::FADD, MVT::f64, {3, 1}}, // fadd.d
453 {ISD::FSUB, MVT::f64, {3, 1}}, // fsub.d
454 {ISD::FMUL, MVT::f64, {5, 2}}, // fmul.d
455 {ISD::FDIV, MVT::f64, {12, 9}}, // fdiv.d
456 };
457
458 if (ST->is64Bit()) {
459 if (const auto *Entry = CostTableLookup(LA64CostTable, ISD, LT.second))
460 if (auto KindCost = Entry->Cost[CostKind])
461 return LT.first * *KindCost;
462 }
463
464 static const CostKindTblEntry LA32CostTable[]{
465 {ISD::ADD, MVT::i32, {1, 1}}, // addi.w/add.w
466 {ISD::SUB, MVT::i32, {1, 1}}, // subi.w/sub.w
467 {ISD::MUL, MVT::i32, {4, 2}}, // mul.w
468
469 {ISD::SDIV, MVT::i32, {11, 24}}, // div.w
470 {ISD::UDIV, MVT::i32, {12, 24}}, // div.wu
471 {ISD::SREM, MVT::i32, {11, 24}}, // mod.w
472 {ISD::UREM, MVT::i32, {12, 24}}, // mod.wu
473
474 {ISD::SHL, MVT::i32, {1, 1}}, // slli.w/sll.w
475 {ISD::SRL, MVT::i32, {1, 1}}, // srli.w/srl.w
476 {ISD::SRA, MVT::i32, {1, 1}}, // srai.w/sra.w
477
478 {ISD::AND, MVT::i32, {1, 1}}, // andi.w/and.w
479 {ISD::OR, MVT::i32, {1, 1}}, // ori.w/or.w
480 {ISD::XOR, MVT::i32, {1, 1}}, // xori.w/xor.w
481
482 {ISD::FADD, MVT::f32, {3, 1}}, // fadd.s
483 {ISD::FSUB, MVT::f32, {3, 1}}, // fsub.s
484 {ISD::FMUL, MVT::f32, {5, 2}}, // fmul.s
485 {ISD::FDIV, MVT::f32, {9, 8}}, // fdiv.s
486 };
487
488 if (const auto *Entry = CostTableLookup(LA32CostTable, ISD, LT.second))
489 if (auto KindCost = Entry->Cost[CostKind])
490 return LT.first * *KindCost;
491
492 // Fallback to the default implementation.
493 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info,
494 Args, CxtI);
495}
496
497// Returns true if Ty is a fixed vector type held in a single LSX/LASX register.
498static bool isSingleVRegType(const LoongArchSubtarget *ST, Type *Ty) {
499 auto *VTy = dyn_cast<FixedVectorType>(Ty);
500 if (!VTy)
501 return false;
502 unsigned Bits = VTy->getPrimitiveSizeInBits().getFixedValue();
503 return (Bits == 128 && ST->hasExtLSX()) || (Bits == 256 && ST->hasExtLASX());
504}
505
507 unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,
508 const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC) const {
509 // Element 0 of a floating-point vector is the aliased FPR, so extracting it
510 // is free.
511 if (Opcode == Instruction::ExtractElement && Index == 0 &&
513 return 0;
514 return BaseT::getVectorInstrCost(Opcode, Val, CostKind, Index, Op0, Op1, VIC);
515}
516
518 TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy,
519 TTI::TargetCostKind CostKind, ArrayRef<int> Mask, int Index,
520 VectorType *SubTp, ArrayRef<const Value *> Args, const Instruction *CxtI,
521 TTI::VectorInstrContext VIC) const {
522 if (isSingleVRegType(ST, SrcTy) && DstTy == SrcTy) {
523 Kind = improveShuffleKindFromMask(Kind, Mask, SrcTy, Index, SubTp);
524 unsigned EltBits = SrcTy->getScalarSizeInBits();
525 bool Is128 = SrcTy->getPrimitiveSizeInBits().getFixedValue() == 128;
526 switch (Kind) {
528 // [x]vreplvei.{b/h/w/d}, xvreplve0.{b/h/w/d}, [x]vreplgr2vr.{b/h/w/d}.
529 return 1;
530 case TTI::SK_Reverse:
532 // vshuf4i.{w/d} handles any single-source permutation of 32/64-bit
533 // elements within a 128-bit register.
534 if (Is128 && EltBits >= 32)
535 return 1;
536 break;
537 default:
538 break;
539 }
540 }
541 return BaseT::getShuffleCost(Kind, DstTy, SrcTy, CostKind, Mask, Index, SubTp,
542 Args, CxtI, VIC);
543}
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
unsigned getPrefetchDistance() const override
bool enableWritePrefetching() 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.
@ TCK_CodeSize
Instruction code size.
@ TCK_SizeAndLatency
The weighted sum of size and latency.
@ TCK_Latency
The latency of instruction.
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.