1 //===-- AArch64TargetTransformInfo.cpp - AArch64 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 9 #include "AArch64TargetTransformInfo.h" 10 #include "AArch64ExpandImm.h" 11 #include "MCTargetDesc/AArch64AddressingModes.h" 12 #include "llvm/Analysis/IVDescriptors.h" 13 #include "llvm/Analysis/LoopInfo.h" 14 #include "llvm/Analysis/TargetTransformInfo.h" 15 #include "llvm/CodeGen/BasicTTIImpl.h" 16 #include "llvm/CodeGen/CostTable.h" 17 #include "llvm/CodeGen/TargetLowering.h" 18 #include "llvm/IR/Intrinsics.h" 19 #include "llvm/IR/IntrinsicInst.h" 20 #include "llvm/IR/IntrinsicsAArch64.h" 21 #include "llvm/IR/PatternMatch.h" 22 #include "llvm/Support/Debug.h" 23 #include "llvm/Transforms/InstCombine/InstCombiner.h" 24 #include <algorithm> 25 using namespace llvm; 26 using namespace llvm::PatternMatch; 27 28 #define DEBUG_TYPE "aarch64tti" 29 30 static cl::opt<bool> EnableFalkorHWPFUnrollFix("enable-falkor-hwpf-unroll-fix", 31 cl::init(true), cl::Hidden); 32 33 static cl::opt<unsigned> SVEGatherOverhead("sve-gather-overhead", cl::init(10), 34 cl::Hidden); 35 36 static cl::opt<unsigned> SVEScatterOverhead("sve-scatter-overhead", 37 cl::init(10), cl::Hidden); 38 39 bool AArch64TTIImpl::areInlineCompatible(const Function *Caller, 40 const Function *Callee) const { 41 const TargetMachine &TM = getTLI()->getTargetMachine(); 42 43 const FeatureBitset &CallerBits = 44 TM.getSubtargetImpl(*Caller)->getFeatureBits(); 45 const FeatureBitset &CalleeBits = 46 TM.getSubtargetImpl(*Callee)->getFeatureBits(); 47 48 // Inline a callee if its target-features are a subset of the callers 49 // target-features. 50 return (CallerBits & CalleeBits) == CalleeBits; 51 } 52 53 /// Calculate the cost of materializing a 64-bit value. This helper 54 /// method might only calculate a fraction of a larger immediate. Therefore it 55 /// is valid to return a cost of ZERO. 56 InstructionCost AArch64TTIImpl::getIntImmCost(int64_t Val) { 57 // Check if the immediate can be encoded within an instruction. 58 if (Val == 0 || AArch64_AM::isLogicalImmediate(Val, 64)) 59 return 0; 60 61 if (Val < 0) 62 Val = ~Val; 63 64 // Calculate how many moves we will need to materialize this constant. 65 SmallVector<AArch64_IMM::ImmInsnModel, 4> Insn; 66 AArch64_IMM::expandMOVImm(Val, 64, Insn); 67 return Insn.size(); 68 } 69 70 /// Calculate the cost of materializing the given constant. 71 InstructionCost AArch64TTIImpl::getIntImmCost(const APInt &Imm, Type *Ty, 72 TTI::TargetCostKind CostKind) { 73 assert(Ty->isIntegerTy()); 74 75 unsigned BitSize = Ty->getPrimitiveSizeInBits(); 76 if (BitSize == 0) 77 return ~0U; 78 79 // Sign-extend all constants to a multiple of 64-bit. 80 APInt ImmVal = Imm; 81 if (BitSize & 0x3f) 82 ImmVal = Imm.sext((BitSize + 63) & ~0x3fU); 83 84 // Split the constant into 64-bit chunks and calculate the cost for each 85 // chunk. 86 InstructionCost Cost = 0; 87 for (unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) { 88 APInt Tmp = ImmVal.ashr(ShiftVal).sextOrTrunc(64); 89 int64_t Val = Tmp.getSExtValue(); 90 Cost += getIntImmCost(Val); 91 } 92 // We need at least one instruction to materialze the constant. 93 return std::max<InstructionCost>(1, Cost); 94 } 95 96 InstructionCost AArch64TTIImpl::getIntImmCostInst(unsigned Opcode, unsigned Idx, 97 const APInt &Imm, Type *Ty, 98 TTI::TargetCostKind CostKind, 99 Instruction *Inst) { 100 assert(Ty->isIntegerTy()); 101 102 unsigned BitSize = Ty->getPrimitiveSizeInBits(); 103 // There is no cost model for constants with a bit size of 0. Return TCC_Free 104 // here, so that constant hoisting will ignore this constant. 105 if (BitSize == 0) 106 return TTI::TCC_Free; 107 108 unsigned ImmIdx = ~0U; 109 switch (Opcode) { 110 default: 111 return TTI::TCC_Free; 112 case Instruction::GetElementPtr: 113 // Always hoist the base address of a GetElementPtr. 114 if (Idx == 0) 115 return 2 * TTI::TCC_Basic; 116 return TTI::TCC_Free; 117 case Instruction::Store: 118 ImmIdx = 0; 119 break; 120 case Instruction::Add: 121 case Instruction::Sub: 122 case Instruction::Mul: 123 case Instruction::UDiv: 124 case Instruction::SDiv: 125 case Instruction::URem: 126 case Instruction::SRem: 127 case Instruction::And: 128 case Instruction::Or: 129 case Instruction::Xor: 130 case Instruction::ICmp: 131 ImmIdx = 1; 132 break; 133 // Always return TCC_Free for the shift value of a shift instruction. 134 case Instruction::Shl: 135 case Instruction::LShr: 136 case Instruction::AShr: 137 if (Idx == 1) 138 return TTI::TCC_Free; 139 break; 140 case Instruction::Trunc: 141 case Instruction::ZExt: 142 case Instruction::SExt: 143 case Instruction::IntToPtr: 144 case Instruction::PtrToInt: 145 case Instruction::BitCast: 146 case Instruction::PHI: 147 case Instruction::Call: 148 case Instruction::Select: 149 case Instruction::Ret: 150 case Instruction::Load: 151 break; 152 } 153 154 if (Idx == ImmIdx) { 155 int NumConstants = (BitSize + 63) / 64; 156 InstructionCost Cost = AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind); 157 return (Cost <= NumConstants * TTI::TCC_Basic) 158 ? static_cast<int>(TTI::TCC_Free) 159 : Cost; 160 } 161 return AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind); 162 } 163 164 InstructionCost 165 AArch64TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, 166 const APInt &Imm, Type *Ty, 167 TTI::TargetCostKind CostKind) { 168 assert(Ty->isIntegerTy()); 169 170 unsigned BitSize = Ty->getPrimitiveSizeInBits(); 171 // There is no cost model for constants with a bit size of 0. Return TCC_Free 172 // here, so that constant hoisting will ignore this constant. 173 if (BitSize == 0) 174 return TTI::TCC_Free; 175 176 // Most (all?) AArch64 intrinsics do not support folding immediates into the 177 // selected instruction, so we compute the materialization cost for the 178 // immediate directly. 179 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv) 180 return AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind); 181 182 switch (IID) { 183 default: 184 return TTI::TCC_Free; 185 case Intrinsic::sadd_with_overflow: 186 case Intrinsic::uadd_with_overflow: 187 case Intrinsic::ssub_with_overflow: 188 case Intrinsic::usub_with_overflow: 189 case Intrinsic::smul_with_overflow: 190 case Intrinsic::umul_with_overflow: 191 if (Idx == 1) { 192 int NumConstants = (BitSize + 63) / 64; 193 InstructionCost Cost = AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind); 194 return (Cost <= NumConstants * TTI::TCC_Basic) 195 ? static_cast<int>(TTI::TCC_Free) 196 : Cost; 197 } 198 break; 199 case Intrinsic::experimental_stackmap: 200 if ((Idx < 2) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) 201 return TTI::TCC_Free; 202 break; 203 case Intrinsic::experimental_patchpoint_void: 204 case Intrinsic::experimental_patchpoint_i64: 205 if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) 206 return TTI::TCC_Free; 207 break; 208 case Intrinsic::experimental_gc_statepoint: 209 if ((Idx < 5) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) 210 return TTI::TCC_Free; 211 break; 212 } 213 return AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind); 214 } 215 216 TargetTransformInfo::PopcntSupportKind 217 AArch64TTIImpl::getPopcntSupport(unsigned TyWidth) { 218 assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2"); 219 if (TyWidth == 32 || TyWidth == 64) 220 return TTI::PSK_FastHardware; 221 // TODO: AArch64TargetLowering::LowerCTPOP() supports 128bit popcount. 222 return TTI::PSK_Software; 223 } 224 225 InstructionCost 226 AArch64TTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, 227 TTI::TargetCostKind CostKind) { 228 auto *RetTy = ICA.getReturnType(); 229 switch (ICA.getID()) { 230 case Intrinsic::umin: 231 case Intrinsic::umax: 232 case Intrinsic::smin: 233 case Intrinsic::smax: { 234 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16, 235 MVT::v8i16, MVT::v2i32, MVT::v4i32}; 236 auto LT = TLI->getTypeLegalizationCost(DL, RetTy); 237 // v2i64 types get converted to cmp+bif hence the cost of 2 238 if (LT.second == MVT::v2i64) 239 return LT.first * 2; 240 if (any_of(ValidMinMaxTys, [<](MVT M) { return M == LT.second; })) 241 return LT.first; 242 break; 243 } 244 case Intrinsic::sadd_sat: 245 case Intrinsic::ssub_sat: 246 case Intrinsic::uadd_sat: 247 case Intrinsic::usub_sat: { 248 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16, 249 MVT::v8i16, MVT::v2i32, MVT::v4i32, 250 MVT::v2i64}; 251 auto LT = TLI->getTypeLegalizationCost(DL, RetTy); 252 // This is a base cost of 1 for the vadd, plus 3 extract shifts if we 253 // need to extend the type, as it uses shr(qadd(shl, shl)). 254 unsigned Instrs = 255 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4; 256 if (any_of(ValidSatTys, [<](MVT M) { return M == LT.second; })) 257 return LT.first * Instrs; 258 break; 259 } 260 case Intrinsic::abs: { 261 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16, 262 MVT::v8i16, MVT::v2i32, MVT::v4i32, 263 MVT::v2i64}; 264 auto LT = TLI->getTypeLegalizationCost(DL, RetTy); 265 if (any_of(ValidAbsTys, [<](MVT M) { return M == LT.second; })) 266 return LT.first; 267 break; 268 } 269 case Intrinsic::experimental_stepvector: { 270 InstructionCost Cost = 1; // Cost of the `index' instruction 271 auto LT = TLI->getTypeLegalizationCost(DL, RetTy); 272 // Legalisation of illegal vectors involves an `index' instruction plus 273 // (LT.first - 1) vector adds. 274 if (LT.first > 1) { 275 Type *LegalVTy = EVT(LT.second).getTypeForEVT(RetTy->getContext()); 276 InstructionCost AddCost = 277 getArithmeticInstrCost(Instruction::Add, LegalVTy, CostKind); 278 Cost += AddCost * (LT.first - 1); 279 } 280 return Cost; 281 } 282 case Intrinsic::bitreverse: { 283 static const CostTblEntry BitreverseTbl[] = { 284 {Intrinsic::bitreverse, MVT::i32, 1}, 285 {Intrinsic::bitreverse, MVT::i64, 1}, 286 {Intrinsic::bitreverse, MVT::v8i8, 1}, 287 {Intrinsic::bitreverse, MVT::v16i8, 1}, 288 {Intrinsic::bitreverse, MVT::v4i16, 2}, 289 {Intrinsic::bitreverse, MVT::v8i16, 2}, 290 {Intrinsic::bitreverse, MVT::v2i32, 2}, 291 {Intrinsic::bitreverse, MVT::v4i32, 2}, 292 {Intrinsic::bitreverse, MVT::v1i64, 2}, 293 {Intrinsic::bitreverse, MVT::v2i64, 2}, 294 }; 295 const auto LegalisationCost = TLI->getTypeLegalizationCost(DL, RetTy); 296 const auto *Entry = 297 CostTableLookup(BitreverseTbl, ICA.getID(), LegalisationCost.second); 298 if (Entry) { 299 // Cost Model is using the legal type(i32) that i8 and i16 will be 300 // converted to +1 so that we match the actual lowering cost 301 if (TLI->getValueType(DL, RetTy, true) == MVT::i8 || 302 TLI->getValueType(DL, RetTy, true) == MVT::i16) 303 return LegalisationCost.first * Entry->Cost + 1; 304 305 return LegalisationCost.first * Entry->Cost; 306 } 307 break; 308 } 309 case Intrinsic::ctpop: { 310 static const CostTblEntry CtpopCostTbl[] = { 311 {ISD::CTPOP, MVT::v2i64, 4}, 312 {ISD::CTPOP, MVT::v4i32, 3}, 313 {ISD::CTPOP, MVT::v8i16, 2}, 314 {ISD::CTPOP, MVT::v16i8, 1}, 315 {ISD::CTPOP, MVT::i64, 4}, 316 {ISD::CTPOP, MVT::v2i32, 3}, 317 {ISD::CTPOP, MVT::v4i16, 2}, 318 {ISD::CTPOP, MVT::v8i8, 1}, 319 {ISD::CTPOP, MVT::i32, 5}, 320 }; 321 auto LT = TLI->getTypeLegalizationCost(DL, RetTy); 322 MVT MTy = LT.second; 323 if (const auto *Entry = CostTableLookup(CtpopCostTbl, ISD::CTPOP, MTy)) { 324 // Extra cost of +1 when illegal vector types are legalized by promoting 325 // the integer type. 326 int ExtraCost = MTy.isVector() && MTy.getScalarSizeInBits() != 327 RetTy->getScalarSizeInBits() 328 ? 1 329 : 0; 330 return LT.first * Entry->Cost + ExtraCost; 331 } 332 break; 333 } 334 default: 335 break; 336 } 337 return BaseT::getIntrinsicInstrCost(ICA, CostKind); 338 } 339 340 /// The function will remove redundant reinterprets casting in the presence 341 /// of the control flow 342 static Optional<Instruction *> processPhiNode(InstCombiner &IC, 343 IntrinsicInst &II) { 344 SmallVector<Instruction *, 32> Worklist; 345 auto RequiredType = II.getType(); 346 347 auto *PN = dyn_cast<PHINode>(II.getArgOperand(0)); 348 assert(PN && "Expected Phi Node!"); 349 350 // Don't create a new Phi unless we can remove the old one. 351 if (!PN->hasOneUse()) 352 return None; 353 354 for (Value *IncValPhi : PN->incoming_values()) { 355 auto *Reinterpret = dyn_cast<IntrinsicInst>(IncValPhi); 356 if (!Reinterpret || 357 Reinterpret->getIntrinsicID() != 358 Intrinsic::aarch64_sve_convert_to_svbool || 359 RequiredType != Reinterpret->getArgOperand(0)->getType()) 360 return None; 361 } 362 363 // Create the new Phi 364 LLVMContext &Ctx = PN->getContext(); 365 IRBuilder<> Builder(Ctx); 366 Builder.SetInsertPoint(PN); 367 PHINode *NPN = Builder.CreatePHI(RequiredType, PN->getNumIncomingValues()); 368 Worklist.push_back(PN); 369 370 for (unsigned I = 0; I < PN->getNumIncomingValues(); I++) { 371 auto *Reinterpret = cast<Instruction>(PN->getIncomingValue(I)); 372 NPN->addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(I)); 373 Worklist.push_back(Reinterpret); 374 } 375 376 // Cleanup Phi Node and reinterprets 377 return IC.replaceInstUsesWith(II, NPN); 378 } 379 380 static Optional<Instruction *> instCombineConvertFromSVBool(InstCombiner &IC, 381 IntrinsicInst &II) { 382 // If the reinterpret instruction operand is a PHI Node 383 if (isa<PHINode>(II.getArgOperand(0))) 384 return processPhiNode(IC, II); 385 386 SmallVector<Instruction *, 32> CandidatesForRemoval; 387 Value *Cursor = II.getOperand(0), *EarliestReplacement = nullptr; 388 389 const auto *IVTy = cast<VectorType>(II.getType()); 390 391 // Walk the chain of conversions. 392 while (Cursor) { 393 // If the type of the cursor has fewer lanes than the final result, zeroing 394 // must take place, which breaks the equivalence chain. 395 const auto *CursorVTy = cast<VectorType>(Cursor->getType()); 396 if (CursorVTy->getElementCount().getKnownMinValue() < 397 IVTy->getElementCount().getKnownMinValue()) 398 break; 399 400 // If the cursor has the same type as I, it is a viable replacement. 401 if (Cursor->getType() == IVTy) 402 EarliestReplacement = Cursor; 403 404 auto *IntrinsicCursor = dyn_cast<IntrinsicInst>(Cursor); 405 406 // If this is not an SVE conversion intrinsic, this is the end of the chain. 407 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() == 408 Intrinsic::aarch64_sve_convert_to_svbool || 409 IntrinsicCursor->getIntrinsicID() == 410 Intrinsic::aarch64_sve_convert_from_svbool)) 411 break; 412 413 CandidatesForRemoval.insert(CandidatesForRemoval.begin(), IntrinsicCursor); 414 Cursor = IntrinsicCursor->getOperand(0); 415 } 416 417 // If no viable replacement in the conversion chain was found, there is 418 // nothing to do. 419 if (!EarliestReplacement) 420 return None; 421 422 return IC.replaceInstUsesWith(II, EarliestReplacement); 423 } 424 425 static Optional<Instruction *> instCombineSVEDup(InstCombiner &IC, 426 IntrinsicInst &II) { 427 IntrinsicInst *Pg = dyn_cast<IntrinsicInst>(II.getArgOperand(1)); 428 if (!Pg) 429 return None; 430 431 if (Pg->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue) 432 return None; 433 434 const auto PTruePattern = 435 cast<ConstantInt>(Pg->getOperand(0))->getZExtValue(); 436 if (PTruePattern != AArch64SVEPredPattern::vl1) 437 return None; 438 439 // The intrinsic is inserting into lane zero so use an insert instead. 440 auto *IdxTy = Type::getInt64Ty(II.getContext()); 441 auto *Insert = InsertElementInst::Create( 442 II.getArgOperand(0), II.getArgOperand(2), ConstantInt::get(IdxTy, 0)); 443 Insert->insertBefore(&II); 444 Insert->takeName(&II); 445 446 return IC.replaceInstUsesWith(II, Insert); 447 } 448 449 static Optional<Instruction *> instCombineSVEDupX(InstCombiner &IC, 450 IntrinsicInst &II) { 451 // Replace DupX with a regular IR splat. 452 IRBuilder<> Builder(II.getContext()); 453 Builder.SetInsertPoint(&II); 454 auto *RetTy = cast<ScalableVectorType>(II.getType()); 455 Value *Splat = 456 Builder.CreateVectorSplat(RetTy->getElementCount(), II.getArgOperand(0)); 457 Splat->takeName(&II); 458 return IC.replaceInstUsesWith(II, Splat); 459 } 460 461 static Optional<Instruction *> instCombineSVECmpNE(InstCombiner &IC, 462 IntrinsicInst &II) { 463 LLVMContext &Ctx = II.getContext(); 464 IRBuilder<> Builder(Ctx); 465 Builder.SetInsertPoint(&II); 466 467 // Check that the predicate is all active 468 auto *Pg = dyn_cast<IntrinsicInst>(II.getArgOperand(0)); 469 if (!Pg || Pg->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue) 470 return None; 471 472 const auto PTruePattern = 473 cast<ConstantInt>(Pg->getOperand(0))->getZExtValue(); 474 if (PTruePattern != AArch64SVEPredPattern::all) 475 return None; 476 477 // Check that we have a compare of zero.. 478 auto *SplatValue = 479 dyn_cast_or_null<ConstantInt>(getSplatValue(II.getArgOperand(2))); 480 if (!SplatValue || !SplatValue->isZero()) 481 return None; 482 483 // ..against a dupq 484 auto *DupQLane = dyn_cast<IntrinsicInst>(II.getArgOperand(1)); 485 if (!DupQLane || 486 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane) 487 return None; 488 489 // Where the dupq is a lane 0 replicate of a vector insert 490 if (!cast<ConstantInt>(DupQLane->getArgOperand(1))->isZero()) 491 return None; 492 493 auto *VecIns = dyn_cast<IntrinsicInst>(DupQLane->getArgOperand(0)); 494 if (!VecIns || 495 VecIns->getIntrinsicID() != Intrinsic::experimental_vector_insert) 496 return None; 497 498 // Where the vector insert is a fixed constant vector insert into undef at 499 // index zero 500 if (!isa<UndefValue>(VecIns->getArgOperand(0))) 501 return None; 502 503 if (!cast<ConstantInt>(VecIns->getArgOperand(2))->isZero()) 504 return None; 505 506 auto *ConstVec = dyn_cast<Constant>(VecIns->getArgOperand(1)); 507 if (!ConstVec) 508 return None; 509 510 auto *VecTy = dyn_cast<FixedVectorType>(ConstVec->getType()); 511 auto *OutTy = dyn_cast<ScalableVectorType>(II.getType()); 512 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements()) 513 return None; 514 515 unsigned NumElts = VecTy->getNumElements(); 516 unsigned PredicateBits = 0; 517 518 // Expand intrinsic operands to a 16-bit byte level predicate 519 for (unsigned I = 0; I < NumElts; ++I) { 520 auto *Arg = dyn_cast<ConstantInt>(ConstVec->getAggregateElement(I)); 521 if (!Arg) 522 return None; 523 if (!Arg->isZero()) 524 PredicateBits |= 1 << (I * (16 / NumElts)); 525 } 526 527 // If all bits are zero bail early with an empty predicate 528 if (PredicateBits == 0) { 529 auto *PFalse = Constant::getNullValue(II.getType()); 530 PFalse->takeName(&II); 531 return IC.replaceInstUsesWith(II, PFalse); 532 } 533 534 // Calculate largest predicate type used (where byte predicate is largest) 535 unsigned Mask = 8; 536 for (unsigned I = 0; I < 16; ++I) 537 if ((PredicateBits & (1 << I)) != 0) 538 Mask |= (I % 8); 539 540 unsigned PredSize = Mask & -Mask; 541 auto *PredType = ScalableVectorType::get( 542 Type::getInt1Ty(Ctx), AArch64::SVEBitsPerBlock / (PredSize * 8)); 543 544 // Ensure all relevant bits are set 545 for (unsigned I = 0; I < 16; I += PredSize) 546 if ((PredicateBits & (1 << I)) == 0) 547 return None; 548 549 auto *PTruePat = 550 ConstantInt::get(Type::getInt32Ty(Ctx), AArch64SVEPredPattern::all); 551 auto *PTrue = Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptrue, 552 {PredType}, {PTruePat}); 553 auto *ConvertToSVBool = Builder.CreateIntrinsic( 554 Intrinsic::aarch64_sve_convert_to_svbool, {PredType}, {PTrue}); 555 auto *ConvertFromSVBool = 556 Builder.CreateIntrinsic(Intrinsic::aarch64_sve_convert_from_svbool, 557 {II.getType()}, {ConvertToSVBool}); 558 559 ConvertFromSVBool->takeName(&II); 560 return IC.replaceInstUsesWith(II, ConvertFromSVBool); 561 } 562 563 static Optional<Instruction *> instCombineSVELast(InstCombiner &IC, 564 IntrinsicInst &II) { 565 IRBuilder<> Builder(II.getContext()); 566 Builder.SetInsertPoint(&II); 567 Value *Pg = II.getArgOperand(0); 568 Value *Vec = II.getArgOperand(1); 569 auto IntrinsicID = II.getIntrinsicID(); 570 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta; 571 572 // lastX(splat(X)) --> X 573 if (auto *SplatVal = getSplatValue(Vec)) 574 return IC.replaceInstUsesWith(II, SplatVal); 575 576 // If x and/or y is a splat value then: 577 // lastX (binop (x, y)) --> binop(lastX(x), lastX(y)) 578 Value *LHS, *RHS; 579 if (match(Vec, m_OneUse(m_BinOp(m_Value(LHS), m_Value(RHS))))) { 580 if (isSplatValue(LHS) || isSplatValue(RHS)) { 581 auto *OldBinOp = cast<BinaryOperator>(Vec); 582 auto OpC = OldBinOp->getOpcode(); 583 auto *NewLHS = 584 Builder.CreateIntrinsic(IntrinsicID, {Vec->getType()}, {Pg, LHS}); 585 auto *NewRHS = 586 Builder.CreateIntrinsic(IntrinsicID, {Vec->getType()}, {Pg, RHS}); 587 auto *NewBinOp = BinaryOperator::CreateWithCopiedFlags( 588 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(), &II); 589 return IC.replaceInstUsesWith(II, NewBinOp); 590 } 591 } 592 593 auto *C = dyn_cast<Constant>(Pg); 594 if (IsAfter && C && C->isNullValue()) { 595 // The intrinsic is extracting lane 0 so use an extract instead. 596 auto *IdxTy = Type::getInt64Ty(II.getContext()); 597 auto *Extract = ExtractElementInst::Create(Vec, ConstantInt::get(IdxTy, 0)); 598 Extract->insertBefore(&II); 599 Extract->takeName(&II); 600 return IC.replaceInstUsesWith(II, Extract); 601 } 602 603 auto *IntrPG = dyn_cast<IntrinsicInst>(Pg); 604 if (!IntrPG) 605 return None; 606 607 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue) 608 return None; 609 610 const auto PTruePattern = 611 cast<ConstantInt>(IntrPG->getOperand(0))->getZExtValue(); 612 613 // Can the intrinsic's predicate be converted to a known constant index? 614 unsigned MinNumElts = getNumElementsFromSVEPredPattern(PTruePattern); 615 if (!MinNumElts) 616 return None; 617 618 unsigned Idx = MinNumElts - 1; 619 // Increment the index if extracting the element after the last active 620 // predicate element. 621 if (IsAfter) 622 ++Idx; 623 624 // Ignore extracts whose index is larger than the known minimum vector 625 // length. NOTE: This is an artificial constraint where we prefer to 626 // maintain what the user asked for until an alternative is proven faster. 627 auto *PgVTy = cast<ScalableVectorType>(Pg->getType()); 628 if (Idx >= PgVTy->getMinNumElements()) 629 return None; 630 631 // The intrinsic is extracting a fixed lane so use an extract instead. 632 auto *IdxTy = Type::getInt64Ty(II.getContext()); 633 auto *Extract = ExtractElementInst::Create(Vec, ConstantInt::get(IdxTy, Idx)); 634 Extract->insertBefore(&II); 635 Extract->takeName(&II); 636 return IC.replaceInstUsesWith(II, Extract); 637 } 638 639 static Optional<Instruction *> instCombineRDFFR(InstCombiner &IC, 640 IntrinsicInst &II) { 641 LLVMContext &Ctx = II.getContext(); 642 IRBuilder<> Builder(Ctx); 643 Builder.SetInsertPoint(&II); 644 // Replace rdffr with predicated rdffr.z intrinsic, so that optimizePTestInstr 645 // can work with RDFFR_PP for ptest elimination. 646 auto *AllPat = 647 ConstantInt::get(Type::getInt32Ty(Ctx), AArch64SVEPredPattern::all); 648 auto *PTrue = Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptrue, 649 {II.getType()}, {AllPat}); 650 auto *RDFFR = 651 Builder.CreateIntrinsic(Intrinsic::aarch64_sve_rdffr_z, {}, {PTrue}); 652 RDFFR->takeName(&II); 653 return IC.replaceInstUsesWith(II, RDFFR); 654 } 655 656 static Optional<Instruction *> 657 instCombineSVECntElts(InstCombiner &IC, IntrinsicInst &II, unsigned NumElts) { 658 const auto Pattern = cast<ConstantInt>(II.getArgOperand(0))->getZExtValue(); 659 660 if (Pattern == AArch64SVEPredPattern::all) { 661 LLVMContext &Ctx = II.getContext(); 662 IRBuilder<> Builder(Ctx); 663 Builder.SetInsertPoint(&II); 664 665 Constant *StepVal = ConstantInt::get(II.getType(), NumElts); 666 auto *VScale = Builder.CreateVScale(StepVal); 667 VScale->takeName(&II); 668 return IC.replaceInstUsesWith(II, VScale); 669 } 670 671 unsigned MinNumElts = getNumElementsFromSVEPredPattern(Pattern); 672 673 return MinNumElts && NumElts >= MinNumElts 674 ? Optional<Instruction *>(IC.replaceInstUsesWith( 675 II, ConstantInt::get(II.getType(), MinNumElts))) 676 : None; 677 } 678 679 static Optional<Instruction *> instCombineSVEPTest(InstCombiner &IC, 680 IntrinsicInst &II) { 681 IntrinsicInst *Op1 = dyn_cast<IntrinsicInst>(II.getArgOperand(0)); 682 IntrinsicInst *Op2 = dyn_cast<IntrinsicInst>(II.getArgOperand(1)); 683 684 if (Op1 && Op2 && 685 Op1->getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool && 686 Op2->getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool && 687 Op1->getArgOperand(0)->getType() == Op2->getArgOperand(0)->getType()) { 688 689 IRBuilder<> Builder(II.getContext()); 690 Builder.SetInsertPoint(&II); 691 692 Value *Ops[] = {Op1->getArgOperand(0), Op2->getArgOperand(0)}; 693 Type *Tys[] = {Op1->getArgOperand(0)->getType()}; 694 695 auto *PTest = Builder.CreateIntrinsic(II.getIntrinsicID(), Tys, Ops); 696 697 PTest->takeName(&II); 698 return IC.replaceInstUsesWith(II, PTest); 699 } 700 701 return None; 702 } 703 704 static Optional<Instruction *> instCombineSVEVectorFMLA(InstCombiner &IC, 705 IntrinsicInst &II) { 706 // fold (fadd p a (fmul p b c)) -> (fma p a b c) 707 Value *P = II.getOperand(0); 708 Value *A = II.getOperand(1); 709 auto FMul = II.getOperand(2); 710 Value *B, *C; 711 if (!match(FMul, m_Intrinsic<Intrinsic::aarch64_sve_fmul>( 712 m_Specific(P), m_Value(B), m_Value(C)))) 713 return None; 714 715 if (!FMul->hasOneUse()) 716 return None; 717 718 llvm::FastMathFlags FAddFlags = II.getFastMathFlags(); 719 // Stop the combine when the flags on the inputs differ in case dropping flags 720 // would lead to us missing out on more beneficial optimizations. 721 if (FAddFlags != cast<CallInst>(FMul)->getFastMathFlags()) 722 return None; 723 if (!FAddFlags.allowContract()) 724 return None; 725 726 IRBuilder<> Builder(II.getContext()); 727 Builder.SetInsertPoint(&II); 728 auto FMLA = Builder.CreateIntrinsic(Intrinsic::aarch64_sve_fmla, 729 {II.getType()}, {P, A, B, C}, &II); 730 FMLA->setFastMathFlags(FAddFlags); 731 return IC.replaceInstUsesWith(II, FMLA); 732 } 733 734 static bool isAllActivePredicate(Value *Pred) { 735 // Look through convert.from.svbool(convert.to.svbool(...) chain. 736 Value *UncastedPred; 737 if (match(Pred, m_Intrinsic<Intrinsic::aarch64_sve_convert_from_svbool>( 738 m_Intrinsic<Intrinsic::aarch64_sve_convert_to_svbool>( 739 m_Value(UncastedPred))))) 740 // If the predicate has the same or less lanes than the uncasted 741 // predicate then we know the casting has no effect. 742 if (cast<ScalableVectorType>(Pred->getType())->getMinNumElements() <= 743 cast<ScalableVectorType>(UncastedPred->getType())->getMinNumElements()) 744 Pred = UncastedPred; 745 746 return match(Pred, m_Intrinsic<Intrinsic::aarch64_sve_ptrue>( 747 m_ConstantInt<AArch64SVEPredPattern::all>())); 748 } 749 750 static Optional<Instruction *> 751 instCombineSVELD1(InstCombiner &IC, IntrinsicInst &II, const DataLayout &DL) { 752 IRBuilder<> Builder(II.getContext()); 753 Builder.SetInsertPoint(&II); 754 755 Value *Pred = II.getOperand(0); 756 Value *PtrOp = II.getOperand(1); 757 Type *VecTy = II.getType(); 758 Value *VecPtr = Builder.CreateBitCast(PtrOp, VecTy->getPointerTo()); 759 760 if (isAllActivePredicate(Pred)) { 761 LoadInst *Load = Builder.CreateLoad(VecTy, VecPtr); 762 return IC.replaceInstUsesWith(II, Load); 763 } 764 765 CallInst *MaskedLoad = 766 Builder.CreateMaskedLoad(VecTy, VecPtr, PtrOp->getPointerAlignment(DL), 767 Pred, ConstantAggregateZero::get(VecTy)); 768 return IC.replaceInstUsesWith(II, MaskedLoad); 769 } 770 771 static Optional<Instruction *> 772 instCombineSVEST1(InstCombiner &IC, IntrinsicInst &II, const DataLayout &DL) { 773 IRBuilder<> Builder(II.getContext()); 774 Builder.SetInsertPoint(&II); 775 776 Value *VecOp = II.getOperand(0); 777 Value *Pred = II.getOperand(1); 778 Value *PtrOp = II.getOperand(2); 779 Value *VecPtr = 780 Builder.CreateBitCast(PtrOp, VecOp->getType()->getPointerTo()); 781 782 if (isAllActivePredicate(Pred)) { 783 Builder.CreateStore(VecOp, VecPtr); 784 return IC.eraseInstFromFunction(II); 785 } 786 787 Builder.CreateMaskedStore(VecOp, VecPtr, PtrOp->getPointerAlignment(DL), 788 Pred); 789 return IC.eraseInstFromFunction(II); 790 } 791 792 static Instruction::BinaryOps intrinsicIDToBinOpCode(unsigned Intrinsic) { 793 switch (Intrinsic) { 794 case Intrinsic::aarch64_sve_fmul: 795 return Instruction::BinaryOps::FMul; 796 case Intrinsic::aarch64_sve_fadd: 797 return Instruction::BinaryOps::FAdd; 798 case Intrinsic::aarch64_sve_fsub: 799 return Instruction::BinaryOps::FSub; 800 default: 801 return Instruction::BinaryOpsEnd; 802 } 803 } 804 805 static Optional<Instruction *> instCombineSVEVectorBinOp(InstCombiner &IC, 806 IntrinsicInst &II) { 807 auto *OpPredicate = II.getOperand(0); 808 auto BinOpCode = intrinsicIDToBinOpCode(II.getIntrinsicID()); 809 if (BinOpCode == Instruction::BinaryOpsEnd || 810 !match(OpPredicate, m_Intrinsic<Intrinsic::aarch64_sve_ptrue>( 811 m_ConstantInt<AArch64SVEPredPattern::all>()))) 812 return None; 813 IRBuilder<> Builder(II.getContext()); 814 Builder.SetInsertPoint(&II); 815 Builder.setFastMathFlags(II.getFastMathFlags()); 816 auto BinOp = 817 Builder.CreateBinOp(BinOpCode, II.getOperand(1), II.getOperand(2)); 818 return IC.replaceInstUsesWith(II, BinOp); 819 } 820 821 static Optional<Instruction *> instCombineSVEVectorFAdd(InstCombiner &IC, 822 IntrinsicInst &II) { 823 if (auto FMLA = instCombineSVEVectorFMLA(IC, II)) 824 return FMLA; 825 return instCombineSVEVectorBinOp(IC, II); 826 } 827 828 static Optional<Instruction *> instCombineSVEVectorMul(InstCombiner &IC, 829 IntrinsicInst &II) { 830 auto *OpPredicate = II.getOperand(0); 831 auto *OpMultiplicand = II.getOperand(1); 832 auto *OpMultiplier = II.getOperand(2); 833 834 IRBuilder<> Builder(II.getContext()); 835 Builder.SetInsertPoint(&II); 836 837 // Return true if a given instruction is a unit splat value, false otherwise. 838 auto IsUnitSplat = [](auto *I) { 839 auto *SplatValue = getSplatValue(I); 840 if (!SplatValue) 841 return false; 842 return match(SplatValue, m_FPOne()) || match(SplatValue, m_One()); 843 }; 844 845 // Return true if a given instruction is an aarch64_sve_dup intrinsic call 846 // with a unit splat value, false otherwise. 847 auto IsUnitDup = [](auto *I) { 848 auto *IntrI = dyn_cast<IntrinsicInst>(I); 849 if (!IntrI || IntrI->getIntrinsicID() != Intrinsic::aarch64_sve_dup) 850 return false; 851 852 auto *SplatValue = IntrI->getOperand(2); 853 return match(SplatValue, m_FPOne()) || match(SplatValue, m_One()); 854 }; 855 856 if (IsUnitSplat(OpMultiplier)) { 857 // [f]mul pg %n, (dupx 1) => %n 858 OpMultiplicand->takeName(&II); 859 return IC.replaceInstUsesWith(II, OpMultiplicand); 860 } else if (IsUnitDup(OpMultiplier)) { 861 // [f]mul pg %n, (dup pg 1) => %n 862 auto *DupInst = cast<IntrinsicInst>(OpMultiplier); 863 auto *DupPg = DupInst->getOperand(1); 864 // TODO: this is naive. The optimization is still valid if DupPg 865 // 'encompasses' OpPredicate, not only if they're the same predicate. 866 if (OpPredicate == DupPg) { 867 OpMultiplicand->takeName(&II); 868 return IC.replaceInstUsesWith(II, OpMultiplicand); 869 } 870 } 871 872 return instCombineSVEVectorBinOp(IC, II); 873 } 874 875 static Optional<Instruction *> instCombineSVEUnpack(InstCombiner &IC, 876 IntrinsicInst &II) { 877 IRBuilder<> Builder(II.getContext()); 878 Builder.SetInsertPoint(&II); 879 Value *UnpackArg = II.getArgOperand(0); 880 auto *RetTy = cast<ScalableVectorType>(II.getType()); 881 bool IsSigned = II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi || 882 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo; 883 884 // Hi = uunpkhi(splat(X)) --> Hi = splat(extend(X)) 885 // Lo = uunpklo(splat(X)) --> Lo = splat(extend(X)) 886 if (auto *ScalarArg = getSplatValue(UnpackArg)) { 887 ScalarArg = 888 Builder.CreateIntCast(ScalarArg, RetTy->getScalarType(), IsSigned); 889 Value *NewVal = 890 Builder.CreateVectorSplat(RetTy->getElementCount(), ScalarArg); 891 NewVal->takeName(&II); 892 return IC.replaceInstUsesWith(II, NewVal); 893 } 894 895 return None; 896 } 897 static Optional<Instruction *> instCombineSVETBL(InstCombiner &IC, 898 IntrinsicInst &II) { 899 auto *OpVal = II.getOperand(0); 900 auto *OpIndices = II.getOperand(1); 901 VectorType *VTy = cast<VectorType>(II.getType()); 902 903 // Check whether OpIndices is a constant splat value < minimal element count 904 // of result. 905 auto *SplatValue = dyn_cast_or_null<ConstantInt>(getSplatValue(OpIndices)); 906 if (!SplatValue || 907 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue())) 908 return None; 909 910 // Convert sve_tbl(OpVal sve_dup_x(SplatValue)) to 911 // splat_vector(extractelement(OpVal, SplatValue)) for further optimization. 912 IRBuilder<> Builder(II.getContext()); 913 Builder.SetInsertPoint(&II); 914 auto *Extract = Builder.CreateExtractElement(OpVal, SplatValue); 915 auto *VectorSplat = 916 Builder.CreateVectorSplat(VTy->getElementCount(), Extract); 917 918 VectorSplat->takeName(&II); 919 return IC.replaceInstUsesWith(II, VectorSplat); 920 } 921 922 static Optional<Instruction *> instCombineSVETupleGet(InstCombiner &IC, 923 IntrinsicInst &II) { 924 // Try to remove sequences of tuple get/set. 925 Value *SetTuple, *SetIndex, *SetValue; 926 auto *GetTuple = II.getArgOperand(0); 927 auto *GetIndex = II.getArgOperand(1); 928 // Check that we have tuple_get(GetTuple, GetIndex) where GetTuple is a 929 // call to tuple_set i.e. tuple_set(SetTuple, SetIndex, SetValue). 930 // Make sure that the types of the current intrinsic and SetValue match 931 // in order to safely remove the sequence. 932 if (!match(GetTuple, 933 m_Intrinsic<Intrinsic::aarch64_sve_tuple_set>( 934 m_Value(SetTuple), m_Value(SetIndex), m_Value(SetValue))) || 935 SetValue->getType() != II.getType()) 936 return None; 937 // Case where we get the same index right after setting it. 938 // tuple_get(tuple_set(SetTuple, SetIndex, SetValue), GetIndex) --> SetValue 939 if (GetIndex == SetIndex) 940 return IC.replaceInstUsesWith(II, SetValue); 941 // If we are getting a different index than what was set in the tuple_set 942 // intrinsic. We can just set the input tuple to the one up in the chain. 943 // tuple_get(tuple_set(SetTuple, SetIndex, SetValue), GetIndex) 944 // --> tuple_get(SetTuple, GetIndex) 945 return IC.replaceOperand(II, 0, SetTuple); 946 } 947 948 static Optional<Instruction *> instCombineSVEZip(InstCombiner &IC, 949 IntrinsicInst &II) { 950 // zip1(uzp1(A, B), uzp2(A, B)) --> A 951 // zip2(uzp1(A, B), uzp2(A, B)) --> B 952 Value *A, *B; 953 if (match(II.getArgOperand(0), 954 m_Intrinsic<Intrinsic::aarch64_sve_uzp1>(m_Value(A), m_Value(B))) && 955 match(II.getArgOperand(1), m_Intrinsic<Intrinsic::aarch64_sve_uzp2>( 956 m_Specific(A), m_Specific(B)))) 957 return IC.replaceInstUsesWith( 958 II, (II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ? A : B)); 959 960 return None; 961 } 962 963 static Optional<Instruction *> instCombineLD1GatherIndex(InstCombiner &IC, 964 IntrinsicInst &II) { 965 Value *Mask = II.getOperand(0); 966 Value *BasePtr = II.getOperand(1); 967 Value *Index = II.getOperand(2); 968 Type *Ty = II.getType(); 969 Type *BasePtrTy = BasePtr->getType(); 970 Value *PassThru = ConstantAggregateZero::get(Ty); 971 972 // Contiguous gather => masked load. 973 // (sve.ld1.gather.index Mask BasePtr (sve.index IndexBase 1)) 974 // => (masked.load (gep BasePtr IndexBase) Align Mask zeroinitializer) 975 Value *IndexBase; 976 if (match(Index, m_Intrinsic<Intrinsic::aarch64_sve_index>( 977 m_Value(IndexBase), m_SpecificInt(1)))) { 978 IRBuilder<> Builder(II.getContext()); 979 Builder.SetInsertPoint(&II); 980 981 Align Alignment = 982 BasePtr->getPointerAlignment(II.getModule()->getDataLayout()); 983 984 Type *VecPtrTy = PointerType::getUnqual(Ty); 985 Value *Ptr = Builder.CreateGEP(BasePtrTy->getPointerElementType(), BasePtr, 986 IndexBase); 987 Ptr = Builder.CreateBitCast(Ptr, VecPtrTy); 988 CallInst *MaskedLoad = 989 Builder.CreateMaskedLoad(Ty, Ptr, Alignment, Mask, PassThru); 990 MaskedLoad->takeName(&II); 991 return IC.replaceInstUsesWith(II, MaskedLoad); 992 } 993 994 return None; 995 } 996 997 static Optional<Instruction *> instCombineST1ScatterIndex(InstCombiner &IC, 998 IntrinsicInst &II) { 999 Value *Val = II.getOperand(0); 1000 Value *Mask = II.getOperand(1); 1001 Value *BasePtr = II.getOperand(2); 1002 Value *Index = II.getOperand(3); 1003 Type *Ty = Val->getType(); 1004 Type *BasePtrTy = BasePtr->getType(); 1005 1006 // Contiguous scatter => masked store. 1007 // (sve.ld1.scatter.index Value Mask BasePtr (sve.index IndexBase 1)) 1008 // => (masked.store Value (gep BasePtr IndexBase) Align Mask) 1009 Value *IndexBase; 1010 if (match(Index, m_Intrinsic<Intrinsic::aarch64_sve_index>( 1011 m_Value(IndexBase), m_SpecificInt(1)))) { 1012 IRBuilder<> Builder(II.getContext()); 1013 Builder.SetInsertPoint(&II); 1014 1015 Align Alignment = 1016 BasePtr->getPointerAlignment(II.getModule()->getDataLayout()); 1017 1018 Value *Ptr = Builder.CreateGEP(BasePtrTy->getPointerElementType(), BasePtr, 1019 IndexBase); 1020 Type *VecPtrTy = PointerType::getUnqual(Ty); 1021 Ptr = Builder.CreateBitCast(Ptr, VecPtrTy); 1022 1023 (void)Builder.CreateMaskedStore(Val, Ptr, Alignment, Mask); 1024 1025 return IC.eraseInstFromFunction(II); 1026 } 1027 1028 return None; 1029 } 1030 1031 Optional<Instruction *> 1032 AArch64TTIImpl::instCombineIntrinsic(InstCombiner &IC, 1033 IntrinsicInst &II) const { 1034 Intrinsic::ID IID = II.getIntrinsicID(); 1035 switch (IID) { 1036 default: 1037 break; 1038 case Intrinsic::aarch64_sve_convert_from_svbool: 1039 return instCombineConvertFromSVBool(IC, II); 1040 case Intrinsic::aarch64_sve_dup: 1041 return instCombineSVEDup(IC, II); 1042 case Intrinsic::aarch64_sve_dup_x: 1043 return instCombineSVEDupX(IC, II); 1044 case Intrinsic::aarch64_sve_cmpne: 1045 case Intrinsic::aarch64_sve_cmpne_wide: 1046 return instCombineSVECmpNE(IC, II); 1047 case Intrinsic::aarch64_sve_rdffr: 1048 return instCombineRDFFR(IC, II); 1049 case Intrinsic::aarch64_sve_lasta: 1050 case Intrinsic::aarch64_sve_lastb: 1051 return instCombineSVELast(IC, II); 1052 case Intrinsic::aarch64_sve_cntd: 1053 return instCombineSVECntElts(IC, II, 2); 1054 case Intrinsic::aarch64_sve_cntw: 1055 return instCombineSVECntElts(IC, II, 4); 1056 case Intrinsic::aarch64_sve_cnth: 1057 return instCombineSVECntElts(IC, II, 8); 1058 case Intrinsic::aarch64_sve_cntb: 1059 return instCombineSVECntElts(IC, II, 16); 1060 case Intrinsic::aarch64_sve_ptest_any: 1061 case Intrinsic::aarch64_sve_ptest_first: 1062 case Intrinsic::aarch64_sve_ptest_last: 1063 return instCombineSVEPTest(IC, II); 1064 case Intrinsic::aarch64_sve_mul: 1065 case Intrinsic::aarch64_sve_fmul: 1066 return instCombineSVEVectorMul(IC, II); 1067 case Intrinsic::aarch64_sve_fadd: 1068 return instCombineSVEVectorFAdd(IC, II); 1069 case Intrinsic::aarch64_sve_fsub: 1070 return instCombineSVEVectorBinOp(IC, II); 1071 case Intrinsic::aarch64_sve_tbl: 1072 return instCombineSVETBL(IC, II); 1073 case Intrinsic::aarch64_sve_uunpkhi: 1074 case Intrinsic::aarch64_sve_uunpklo: 1075 case Intrinsic::aarch64_sve_sunpkhi: 1076 case Intrinsic::aarch64_sve_sunpklo: 1077 return instCombineSVEUnpack(IC, II); 1078 case Intrinsic::aarch64_sve_tuple_get: 1079 return instCombineSVETupleGet(IC, II); 1080 case Intrinsic::aarch64_sve_zip1: 1081 case Intrinsic::aarch64_sve_zip2: 1082 return instCombineSVEZip(IC, II); 1083 case Intrinsic::aarch64_sve_ld1_gather_index: 1084 return instCombineLD1GatherIndex(IC, II); 1085 case Intrinsic::aarch64_sve_st1_scatter_index: 1086 return instCombineST1ScatterIndex(IC, II); 1087 case Intrinsic::aarch64_sve_ld1: 1088 return instCombineSVELD1(IC, II, DL); 1089 case Intrinsic::aarch64_sve_st1: 1090 return instCombineSVEST1(IC, II, DL); 1091 } 1092 1093 return None; 1094 } 1095 1096 bool AArch64TTIImpl::isWideningInstruction(Type *DstTy, unsigned Opcode, 1097 ArrayRef<const Value *> Args) { 1098 1099 // A helper that returns a vector type from the given type. The number of 1100 // elements in type Ty determine the vector width. 1101 auto toVectorTy = [&](Type *ArgTy) { 1102 return VectorType::get(ArgTy->getScalarType(), 1103 cast<VectorType>(DstTy)->getElementCount()); 1104 }; 1105 1106 // Exit early if DstTy is not a vector type whose elements are at least 1107 // 16-bits wide. 1108 if (!DstTy->isVectorTy() || DstTy->getScalarSizeInBits() < 16) 1109 return false; 1110 1111 // Determine if the operation has a widening variant. We consider both the 1112 // "long" (e.g., usubl) and "wide" (e.g., usubw) versions of the 1113 // instructions. 1114 // 1115 // TODO: Add additional widening operations (e.g., mul, shl, etc.) once we 1116 // verify that their extending operands are eliminated during code 1117 // generation. 1118 switch (Opcode) { 1119 case Instruction::Add: // UADDL(2), SADDL(2), UADDW(2), SADDW(2). 1120 case Instruction::Sub: // USUBL(2), SSUBL(2), USUBW(2), SSUBW(2). 1121 break; 1122 default: 1123 return false; 1124 } 1125 1126 // To be a widening instruction (either the "wide" or "long" versions), the 1127 // second operand must be a sign- or zero extend having a single user. We 1128 // only consider extends having a single user because they may otherwise not 1129 // be eliminated. 1130 if (Args.size() != 2 || 1131 (!isa<SExtInst>(Args[1]) && !isa<ZExtInst>(Args[1])) || 1132 !Args[1]->hasOneUse()) 1133 return false; 1134 auto *Extend = cast<CastInst>(Args[1]); 1135 1136 // Legalize the destination type and ensure it can be used in a widening 1137 // operation. 1138 auto DstTyL = TLI->getTypeLegalizationCost(DL, DstTy); 1139 unsigned DstElTySize = DstTyL.second.getScalarSizeInBits(); 1140 if (!DstTyL.second.isVector() || DstElTySize != DstTy->getScalarSizeInBits()) 1141 return false; 1142 1143 // Legalize the source type and ensure it can be used in a widening 1144 // operation. 1145 auto *SrcTy = toVectorTy(Extend->getSrcTy()); 1146 auto SrcTyL = TLI->getTypeLegalizationCost(DL, SrcTy); 1147 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits(); 1148 if (!SrcTyL.second.isVector() || SrcElTySize != SrcTy->getScalarSizeInBits()) 1149 return false; 1150 1151 // Get the total number of vector elements in the legalized types. 1152 InstructionCost NumDstEls = 1153 DstTyL.first * DstTyL.second.getVectorMinNumElements(); 1154 InstructionCost NumSrcEls = 1155 SrcTyL.first * SrcTyL.second.getVectorMinNumElements(); 1156 1157 // Return true if the legalized types have the same number of vector elements 1158 // and the destination element type size is twice that of the source type. 1159 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstElTySize; 1160 } 1161 1162 InstructionCost AArch64TTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, 1163 Type *Src, 1164 TTI::CastContextHint CCH, 1165 TTI::TargetCostKind CostKind, 1166 const Instruction *I) { 1167 int ISD = TLI->InstructionOpcodeToISD(Opcode); 1168 assert(ISD && "Invalid opcode"); 1169 1170 // If the cast is observable, and it is used by a widening instruction (e.g., 1171 // uaddl, saddw, etc.), it may be free. 1172 if (I && I->hasOneUse()) { 1173 auto *SingleUser = cast<Instruction>(*I->user_begin()); 1174 SmallVector<const Value *, 4> Operands(SingleUser->operand_values()); 1175 if (isWideningInstruction(Dst, SingleUser->getOpcode(), Operands)) { 1176 // If the cast is the second operand, it is free. We will generate either 1177 // a "wide" or "long" version of the widening instruction. 1178 if (I == SingleUser->getOperand(1)) 1179 return 0; 1180 // If the cast is not the second operand, it will be free if it looks the 1181 // same as the second operand. In this case, we will generate a "long" 1182 // version of the widening instruction. 1183 if (auto *Cast = dyn_cast<CastInst>(SingleUser->getOperand(1))) 1184 if (I->getOpcode() == unsigned(Cast->getOpcode()) && 1185 cast<CastInst>(I)->getSrcTy() == Cast->getSrcTy()) 1186 return 0; 1187 } 1188 } 1189 1190 // TODO: Allow non-throughput costs that aren't binary. 1191 auto AdjustCost = [&CostKind](InstructionCost Cost) -> InstructionCost { 1192 if (CostKind != TTI::TCK_RecipThroughput) 1193 return Cost == 0 ? 0 : 1; 1194 return Cost; 1195 }; 1196 1197 EVT SrcTy = TLI->getValueType(DL, Src); 1198 EVT DstTy = TLI->getValueType(DL, Dst); 1199 1200 if (!SrcTy.isSimple() || !DstTy.isSimple()) 1201 return AdjustCost( 1202 BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I)); 1203 1204 static const TypeConversionCostTblEntry 1205 ConversionTbl[] = { 1206 { ISD::TRUNCATE, MVT::v4i16, MVT::v4i32, 1 }, 1207 { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 0 }, 1208 { ISD::TRUNCATE, MVT::v8i8, MVT::v8i32, 3 }, 1209 { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 6 }, 1210 1211 // Truncations on nxvmiN 1212 { ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i16, 1 }, 1213 { ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i32, 1 }, 1214 { ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i64, 1 }, 1215 { ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i16, 1 }, 1216 { ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i32, 1 }, 1217 { ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i64, 2 }, 1218 { ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i16, 1 }, 1219 { ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i32, 3 }, 1220 { ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i64, 5 }, 1221 { ISD::TRUNCATE, MVT::nxv16i1, MVT::nxv16i8, 1 }, 1222 { ISD::TRUNCATE, MVT::nxv2i16, MVT::nxv2i32, 1 }, 1223 { ISD::TRUNCATE, MVT::nxv2i32, MVT::nxv2i64, 1 }, 1224 { ISD::TRUNCATE, MVT::nxv4i16, MVT::nxv4i32, 1 }, 1225 { ISD::TRUNCATE, MVT::nxv4i32, MVT::nxv4i64, 2 }, 1226 { ISD::TRUNCATE, MVT::nxv8i16, MVT::nxv8i32, 3 }, 1227 { ISD::TRUNCATE, MVT::nxv8i32, MVT::nxv8i64, 6 }, 1228 1229 // The number of shll instructions for the extension. 1230 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i16, 3 }, 1231 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i16, 3 }, 1232 { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 2 }, 1233 { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 2 }, 1234 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i8, 3 }, 1235 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i8, 3 }, 1236 { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 2 }, 1237 { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 2 }, 1238 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i8, 7 }, 1239 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i8, 7 }, 1240 { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i16, 6 }, 1241 { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i16, 6 }, 1242 { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 2 }, 1243 { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 2 }, 1244 { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i8, 6 }, 1245 { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i8, 6 }, 1246 1247 // LowerVectorINT_TO_FP: 1248 { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i32, 1 }, 1249 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, 1 }, 1250 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 1 }, 1251 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 1 }, 1252 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 1 }, 1253 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 1 }, 1254 1255 // Complex: to v2f32 1256 { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i8, 3 }, 1257 { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i16, 3 }, 1258 { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i64, 2 }, 1259 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i8, 3 }, 1260 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i16, 3 }, 1261 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, 2 }, 1262 1263 // Complex: to v4f32 1264 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i8, 4 }, 1265 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i16, 2 }, 1266 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i8, 3 }, 1267 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i16, 2 }, 1268 1269 // Complex: to v8f32 1270 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i8, 10 }, 1271 { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 4 }, 1272 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i8, 10 }, 1273 { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 4 }, 1274 1275 // Complex: to v16f32 1276 { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i8, 21 }, 1277 { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i8, 21 }, 1278 1279 // Complex: to v2f64 1280 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i8, 4 }, 1281 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i16, 4 }, 1282 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i32, 2 }, 1283 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i8, 4 }, 1284 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i16, 4 }, 1285 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 2 }, 1286 1287 1288 // LowerVectorFP_TO_INT 1289 { ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f32, 1 }, 1290 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 1 }, 1291 { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, 1 }, 1292 { ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f32, 1 }, 1293 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 1 }, 1294 { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, 1 }, 1295 1296 // Complex, from v2f32: legal type is v2i32 (no cost) or v2i64 (1 ext). 1297 { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f32, 2 }, 1298 { ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f32, 1 }, 1299 { ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f32, 1 }, 1300 { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f32, 2 }, 1301 { ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f32, 1 }, 1302 { ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f32, 1 }, 1303 1304 // Complex, from v4f32: legal type is v4i16, 1 narrowing => ~2 1305 { ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f32, 2 }, 1306 { ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f32, 2 }, 1307 { ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f32, 2 }, 1308 { ISD::FP_TO_UINT, MVT::v4i8, MVT::v4f32, 2 }, 1309 1310 // Complex, from nxv2f32. 1311 { ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f32, 1 }, 1312 { ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f32, 1 }, 1313 { ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f32, 1 }, 1314 { ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f32, 1 }, 1315 { ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f32, 1 }, 1316 { ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f32, 1 }, 1317 { ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f32, 1 }, 1318 { ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f32, 1 }, 1319 1320 // Complex, from v2f64: legal type is v2i32, 1 narrowing => ~2. 1321 { ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f64, 2 }, 1322 { ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f64, 2 }, 1323 { ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f64, 2 }, 1324 { ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f64, 2 }, 1325 { ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f64, 2 }, 1326 { ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f64, 2 }, 1327 1328 // Complex, from nxv2f64. 1329 { ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f64, 1 }, 1330 { ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f64, 1 }, 1331 { ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f64, 1 }, 1332 { ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f64, 1 }, 1333 { ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f64, 1 }, 1334 { ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f64, 1 }, 1335 { ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f64, 1 }, 1336 { ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f64, 1 }, 1337 1338 // Complex, from nxv4f32. 1339 { ISD::FP_TO_SINT, MVT::nxv4i64, MVT::nxv4f32, 4 }, 1340 { ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f32, 1 }, 1341 { ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f32, 1 }, 1342 { ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f32, 1 }, 1343 { ISD::FP_TO_UINT, MVT::nxv4i64, MVT::nxv4f32, 4 }, 1344 { ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f32, 1 }, 1345 { ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f32, 1 }, 1346 { ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f32, 1 }, 1347 1348 // Complex, from nxv8f64. Illegal -> illegal conversions not required. 1349 { ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f64, 7 }, 1350 { ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f64, 7 }, 1351 { ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f64, 7 }, 1352 { ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f64, 7 }, 1353 1354 // Complex, from nxv4f64. Illegal -> illegal conversions not required. 1355 { ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f64, 3 }, 1356 { ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f64, 3 }, 1357 { ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f64, 3 }, 1358 { ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f64, 3 }, 1359 { ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f64, 3 }, 1360 { ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f64, 3 }, 1361 1362 // Complex, from nxv8f32. Illegal -> illegal conversions not required. 1363 { ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f32, 3 }, 1364 { ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f32, 3 }, 1365 { ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f32, 3 }, 1366 { ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f32, 3 }, 1367 1368 // Complex, from nxv8f16. 1369 { ISD::FP_TO_SINT, MVT::nxv8i64, MVT::nxv8f16, 10 }, 1370 { ISD::FP_TO_SINT, MVT::nxv8i32, MVT::nxv8f16, 4 }, 1371 { ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f16, 1 }, 1372 { ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f16, 1 }, 1373 { ISD::FP_TO_UINT, MVT::nxv8i64, MVT::nxv8f16, 10 }, 1374 { ISD::FP_TO_UINT, MVT::nxv8i32, MVT::nxv8f16, 4 }, 1375 { ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f16, 1 }, 1376 { ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f16, 1 }, 1377 1378 // Complex, from nxv4f16. 1379 { ISD::FP_TO_SINT, MVT::nxv4i64, MVT::nxv4f16, 4 }, 1380 { ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f16, 1 }, 1381 { ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f16, 1 }, 1382 { ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f16, 1 }, 1383 { ISD::FP_TO_UINT, MVT::nxv4i64, MVT::nxv4f16, 4 }, 1384 { ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f16, 1 }, 1385 { ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f16, 1 }, 1386 { ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f16, 1 }, 1387 1388 // Complex, from nxv2f16. 1389 { ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f16, 1 }, 1390 { ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f16, 1 }, 1391 { ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f16, 1 }, 1392 { ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f16, 1 }, 1393 { ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f16, 1 }, 1394 { ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f16, 1 }, 1395 { ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f16, 1 }, 1396 { ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f16, 1 }, 1397 1398 // Truncate from nxvmf32 to nxvmf16. 1399 { ISD::FP_ROUND, MVT::nxv2f16, MVT::nxv2f32, 1 }, 1400 { ISD::FP_ROUND, MVT::nxv4f16, MVT::nxv4f32, 1 }, 1401 { ISD::FP_ROUND, MVT::nxv8f16, MVT::nxv8f32, 3 }, 1402 1403 // Truncate from nxvmf64 to nxvmf16. 1404 { ISD::FP_ROUND, MVT::nxv2f16, MVT::nxv2f64, 1 }, 1405 { ISD::FP_ROUND, MVT::nxv4f16, MVT::nxv4f64, 3 }, 1406 { ISD::FP_ROUND, MVT::nxv8f16, MVT::nxv8f64, 7 }, 1407 1408 // Truncate from nxvmf64 to nxvmf32. 1409 { ISD::FP_ROUND, MVT::nxv2f32, MVT::nxv2f64, 1 }, 1410 { ISD::FP_ROUND, MVT::nxv4f32, MVT::nxv4f64, 3 }, 1411 { ISD::FP_ROUND, MVT::nxv8f32, MVT::nxv8f64, 6 }, 1412 1413 // Extend from nxvmf16 to nxvmf32. 1414 { ISD::FP_EXTEND, MVT::nxv2f32, MVT::nxv2f16, 1}, 1415 { ISD::FP_EXTEND, MVT::nxv4f32, MVT::nxv4f16, 1}, 1416 { ISD::FP_EXTEND, MVT::nxv8f32, MVT::nxv8f16, 2}, 1417 1418 // Extend from nxvmf16 to nxvmf64. 1419 { ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2f16, 1}, 1420 { ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4f16, 2}, 1421 { ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8f16, 4}, 1422 1423 // Extend from nxvmf32 to nxvmf64. 1424 { ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2f32, 1}, 1425 { ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4f32, 2}, 1426 { ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8f32, 6}, 1427 1428 }; 1429 1430 if (const auto *Entry = ConvertCostTableLookup(ConversionTbl, ISD, 1431 DstTy.getSimpleVT(), 1432 SrcTy.getSimpleVT())) 1433 return AdjustCost(Entry->Cost); 1434 1435 return AdjustCost( 1436 BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I)); 1437 } 1438 1439 InstructionCost AArch64TTIImpl::getExtractWithExtendCost(unsigned Opcode, 1440 Type *Dst, 1441 VectorType *VecTy, 1442 unsigned Index) { 1443 1444 // Make sure we were given a valid extend opcode. 1445 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) && 1446 "Invalid opcode"); 1447 1448 // We are extending an element we extract from a vector, so the source type 1449 // of the extend is the element type of the vector. 1450 auto *Src = VecTy->getElementType(); 1451 1452 // Sign- and zero-extends are for integer types only. 1453 assert(isa<IntegerType>(Dst) && isa<IntegerType>(Src) && "Invalid type"); 1454 1455 // Get the cost for the extract. We compute the cost (if any) for the extend 1456 // below. 1457 InstructionCost Cost = 1458 getVectorInstrCost(Instruction::ExtractElement, VecTy, Index); 1459 1460 // Legalize the types. 1461 auto VecLT = TLI->getTypeLegalizationCost(DL, VecTy); 1462 auto DstVT = TLI->getValueType(DL, Dst); 1463 auto SrcVT = TLI->getValueType(DL, Src); 1464 TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput; 1465 1466 // If the resulting type is still a vector and the destination type is legal, 1467 // we may get the extension for free. If not, get the default cost for the 1468 // extend. 1469 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT)) 1470 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None, 1471 CostKind); 1472 1473 // The destination type should be larger than the element type. If not, get 1474 // the default cost for the extend. 1475 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits()) 1476 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None, 1477 CostKind); 1478 1479 switch (Opcode) { 1480 default: 1481 llvm_unreachable("Opcode should be either SExt or ZExt"); 1482 1483 // For sign-extends, we only need a smov, which performs the extension 1484 // automatically. 1485 case Instruction::SExt: 1486 return Cost; 1487 1488 // For zero-extends, the extend is performed automatically by a umov unless 1489 // the destination type is i64 and the element type is i8 or i16. 1490 case Instruction::ZExt: 1491 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u) 1492 return Cost; 1493 } 1494 1495 // If we are unable to perform the extend for free, get the default cost. 1496 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None, 1497 CostKind); 1498 } 1499 1500 InstructionCost AArch64TTIImpl::getCFInstrCost(unsigned Opcode, 1501 TTI::TargetCostKind CostKind, 1502 const Instruction *I) { 1503 if (CostKind != TTI::TCK_RecipThroughput) 1504 return Opcode == Instruction::PHI ? 0 : 1; 1505 assert(CostKind == TTI::TCK_RecipThroughput && "unexpected CostKind"); 1506 // Branches are assumed to be predicted. 1507 return 0; 1508 } 1509 1510 InstructionCost AArch64TTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val, 1511 unsigned Index) { 1512 assert(Val->isVectorTy() && "This must be a vector type"); 1513 1514 if (Index != -1U) { 1515 // Legalize the type. 1516 std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Val); 1517 1518 // This type is legalized to a scalar type. 1519 if (!LT.second.isVector()) 1520 return 0; 1521 1522 // The type may be split. Normalize the index to the new type. 1523 unsigned Width = LT.second.getVectorNumElements(); 1524 Index = Index % Width; 1525 1526 // The element at index zero is already inside the vector. 1527 if (Index == 0) 1528 return 0; 1529 } 1530 1531 // All other insert/extracts cost this much. 1532 return ST->getVectorInsertExtractBaseCost(); 1533 } 1534 1535 InstructionCost AArch64TTIImpl::getArithmeticInstrCost( 1536 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, 1537 TTI::OperandValueKind Opd1Info, TTI::OperandValueKind Opd2Info, 1538 TTI::OperandValueProperties Opd1PropInfo, 1539 TTI::OperandValueProperties Opd2PropInfo, ArrayRef<const Value *> Args, 1540 const Instruction *CxtI) { 1541 // TODO: Handle more cost kinds. 1542 if (CostKind != TTI::TCK_RecipThroughput) 1543 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Opd1Info, 1544 Opd2Info, Opd1PropInfo, 1545 Opd2PropInfo, Args, CxtI); 1546 1547 // Legalize the type. 1548 std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Ty); 1549 1550 // If the instruction is a widening instruction (e.g., uaddl, saddw, etc.), 1551 // add in the widening overhead specified by the sub-target. Since the 1552 // extends feeding widening instructions are performed automatically, they 1553 // aren't present in the generated code and have a zero cost. By adding a 1554 // widening overhead here, we attach the total cost of the combined operation 1555 // to the widening instruction. 1556 InstructionCost Cost = 0; 1557 if (isWideningInstruction(Ty, Opcode, Args)) 1558 Cost += ST->getWideningBaseCost(); 1559 1560 int ISD = TLI->InstructionOpcodeToISD(Opcode); 1561 1562 switch (ISD) { 1563 default: 1564 return Cost + BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Opd1Info, 1565 Opd2Info, 1566 Opd1PropInfo, Opd2PropInfo); 1567 case ISD::SDIV: 1568 if (Opd2Info == TargetTransformInfo::OK_UniformConstantValue && 1569 Opd2PropInfo == TargetTransformInfo::OP_PowerOf2) { 1570 // On AArch64, scalar signed division by constants power-of-two are 1571 // normally expanded to the sequence ADD + CMP + SELECT + SRA. 1572 // The OperandValue properties many not be same as that of previous 1573 // operation; conservatively assume OP_None. 1574 Cost += getArithmeticInstrCost(Instruction::Add, Ty, CostKind, 1575 Opd1Info, Opd2Info, 1576 TargetTransformInfo::OP_None, 1577 TargetTransformInfo::OP_None); 1578 Cost += getArithmeticInstrCost(Instruction::Sub, Ty, CostKind, 1579 Opd1Info, Opd2Info, 1580 TargetTransformInfo::OP_None, 1581 TargetTransformInfo::OP_None); 1582 Cost += getArithmeticInstrCost(Instruction::Select, Ty, CostKind, 1583 Opd1Info, Opd2Info, 1584 TargetTransformInfo::OP_None, 1585 TargetTransformInfo::OP_None); 1586 Cost += getArithmeticInstrCost(Instruction::AShr, Ty, CostKind, 1587 Opd1Info, Opd2Info, 1588 TargetTransformInfo::OP_None, 1589 TargetTransformInfo::OP_None); 1590 return Cost; 1591 } 1592 LLVM_FALLTHROUGH; 1593 case ISD::UDIV: 1594 if (Opd2Info == TargetTransformInfo::OK_UniformConstantValue) { 1595 auto VT = TLI->getValueType(DL, Ty); 1596 if (TLI->isOperationLegalOrCustom(ISD::MULHU, VT)) { 1597 // Vector signed division by constant are expanded to the 1598 // sequence MULHS + ADD/SUB + SRA + SRL + ADD, and unsigned division 1599 // to MULHS + SUB + SRL + ADD + SRL. 1600 InstructionCost MulCost = getArithmeticInstrCost( 1601 Instruction::Mul, Ty, CostKind, Opd1Info, Opd2Info, 1602 TargetTransformInfo::OP_None, TargetTransformInfo::OP_None); 1603 InstructionCost AddCost = getArithmeticInstrCost( 1604 Instruction::Add, Ty, CostKind, Opd1Info, Opd2Info, 1605 TargetTransformInfo::OP_None, TargetTransformInfo::OP_None); 1606 InstructionCost ShrCost = getArithmeticInstrCost( 1607 Instruction::AShr, Ty, CostKind, Opd1Info, Opd2Info, 1608 TargetTransformInfo::OP_None, TargetTransformInfo::OP_None); 1609 return MulCost * 2 + AddCost * 2 + ShrCost * 2 + 1; 1610 } 1611 } 1612 1613 Cost += BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Opd1Info, 1614 Opd2Info, 1615 Opd1PropInfo, Opd2PropInfo); 1616 if (Ty->isVectorTy()) { 1617 // On AArch64, vector divisions are not supported natively and are 1618 // expanded into scalar divisions of each pair of elements. 1619 Cost += getArithmeticInstrCost(Instruction::ExtractElement, Ty, CostKind, 1620 Opd1Info, Opd2Info, Opd1PropInfo, 1621 Opd2PropInfo); 1622 Cost += getArithmeticInstrCost(Instruction::InsertElement, Ty, CostKind, 1623 Opd1Info, Opd2Info, Opd1PropInfo, 1624 Opd2PropInfo); 1625 // TODO: if one of the arguments is scalar, then it's not necessary to 1626 // double the cost of handling the vector elements. 1627 Cost += Cost; 1628 } 1629 return Cost; 1630 1631 case ISD::MUL: 1632 if (LT.second != MVT::v2i64) 1633 return (Cost + 1) * LT.first; 1634 // Since we do not have a MUL.2d instruction, a mul <2 x i64> is expensive 1635 // as elements are extracted from the vectors and the muls scalarized. 1636 // As getScalarizationOverhead is a bit too pessimistic, we estimate the 1637 // cost for a i64 vector directly here, which is: 1638 // - four i64 extracts, 1639 // - two i64 inserts, and 1640 // - two muls. 1641 // So, for a v2i64 with LT.First = 1 the cost is 8, and for a v4i64 with 1642 // LT.first = 2 the cost is 16. 1643 return LT.first * 8; 1644 case ISD::ADD: 1645 case ISD::XOR: 1646 case ISD::OR: 1647 case ISD::AND: 1648 // These nodes are marked as 'custom' for combining purposes only. 1649 // We know that they are legal. See LowerAdd in ISelLowering. 1650 return (Cost + 1) * LT.first; 1651 1652 case ISD::FADD: 1653 case ISD::FSUB: 1654 case ISD::FMUL: 1655 case ISD::FDIV: 1656 case ISD::FNEG: 1657 // These nodes are marked as 'custom' just to lower them to SVE. 1658 // We know said lowering will incur no additional cost. 1659 if (!Ty->getScalarType()->isFP128Ty()) 1660 return (Cost + 2) * LT.first; 1661 1662 return Cost + BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Opd1Info, 1663 Opd2Info, 1664 Opd1PropInfo, Opd2PropInfo); 1665 } 1666 } 1667 1668 InstructionCost AArch64TTIImpl::getAddressComputationCost(Type *Ty, 1669 ScalarEvolution *SE, 1670 const SCEV *Ptr) { 1671 // Address computations in vectorized code with non-consecutive addresses will 1672 // likely result in more instructions compared to scalar code where the 1673 // computation can more often be merged into the index mode. The resulting 1674 // extra micro-ops can significantly decrease throughput. 1675 unsigned NumVectorInstToHideOverhead = 10; 1676 int MaxMergeDistance = 64; 1677 1678 if (Ty->isVectorTy() && SE && 1679 !BaseT::isConstantStridedAccessLessThan(SE, Ptr, MaxMergeDistance + 1)) 1680 return NumVectorInstToHideOverhead; 1681 1682 // In many cases the address computation is not merged into the instruction 1683 // addressing mode. 1684 return 1; 1685 } 1686 1687 InstructionCost AArch64TTIImpl::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, 1688 Type *CondTy, 1689 CmpInst::Predicate VecPred, 1690 TTI::TargetCostKind CostKind, 1691 const Instruction *I) { 1692 // TODO: Handle other cost kinds. 1693 if (CostKind != TTI::TCK_RecipThroughput) 1694 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind, 1695 I); 1696 1697 int ISD = TLI->InstructionOpcodeToISD(Opcode); 1698 // We don't lower some vector selects well that are wider than the register 1699 // width. 1700 if (isa<FixedVectorType>(ValTy) && ISD == ISD::SELECT) { 1701 // We would need this many instructions to hide the scalarization happening. 1702 const int AmortizationCost = 20; 1703 1704 // If VecPred is not set, check if we can get a predicate from the context 1705 // instruction, if its type matches the requested ValTy. 1706 if (VecPred == CmpInst::BAD_ICMP_PREDICATE && I && I->getType() == ValTy) { 1707 CmpInst::Predicate CurrentPred; 1708 if (match(I, m_Select(m_Cmp(CurrentPred, m_Value(), m_Value()), m_Value(), 1709 m_Value()))) 1710 VecPred = CurrentPred; 1711 } 1712 // Check if we have a compare/select chain that can be lowered using CMxx & 1713 // BFI pair. 1714 if (CmpInst::isIntPredicate(VecPred)) { 1715 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16, 1716 MVT::v8i16, MVT::v2i32, MVT::v4i32, 1717 MVT::v2i64}; 1718 auto LT = TLI->getTypeLegalizationCost(DL, ValTy); 1719 if (any_of(ValidMinMaxTys, [<](MVT M) { return M == LT.second; })) 1720 return LT.first; 1721 } 1722 1723 static const TypeConversionCostTblEntry 1724 VectorSelectTbl[] = { 1725 { ISD::SELECT, MVT::v16i1, MVT::v16i16, 16 }, 1726 { ISD::SELECT, MVT::v8i1, MVT::v8i32, 8 }, 1727 { ISD::SELECT, MVT::v16i1, MVT::v16i32, 16 }, 1728 { ISD::SELECT, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost }, 1729 { ISD::SELECT, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost }, 1730 { ISD::SELECT, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost } 1731 }; 1732 1733 EVT SelCondTy = TLI->getValueType(DL, CondTy); 1734 EVT SelValTy = TLI->getValueType(DL, ValTy); 1735 if (SelCondTy.isSimple() && SelValTy.isSimple()) { 1736 if (const auto *Entry = ConvertCostTableLookup(VectorSelectTbl, ISD, 1737 SelCondTy.getSimpleVT(), 1738 SelValTy.getSimpleVT())) 1739 return Entry->Cost; 1740 } 1741 } 1742 // The base case handles scalable vectors fine for now, since it treats the 1743 // cost as 1 * legalization cost. 1744 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind, I); 1745 } 1746 1747 AArch64TTIImpl::TTI::MemCmpExpansionOptions 1748 AArch64TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const { 1749 TTI::MemCmpExpansionOptions Options; 1750 if (ST->requiresStrictAlign()) { 1751 // TODO: Add cost modeling for strict align. Misaligned loads expand to 1752 // a bunch of instructions when strict align is enabled. 1753 return Options; 1754 } 1755 Options.AllowOverlappingLoads = true; 1756 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize); 1757 Options.NumLoadsPerBlock = Options.MaxNumLoads; 1758 // TODO: Though vector loads usually perform well on AArch64, in some targets 1759 // they may wake up the FP unit, which raises the power consumption. Perhaps 1760 // they could be used with no holds barred (-O3). 1761 Options.LoadSizes = {8, 4, 2, 1}; 1762 return Options; 1763 } 1764 1765 InstructionCost 1766 AArch64TTIImpl::getMaskedMemoryOpCost(unsigned Opcode, Type *Src, 1767 Align Alignment, unsigned AddressSpace, 1768 TTI::TargetCostKind CostKind) { 1769 if (!isa<ScalableVectorType>(Src)) 1770 return BaseT::getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace, 1771 CostKind); 1772 auto LT = TLI->getTypeLegalizationCost(DL, Src); 1773 if (!LT.first.isValid()) 1774 return InstructionCost::getInvalid(); 1775 1776 // The code-generator is currently not able to handle scalable vectors 1777 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting 1778 // it. This change will be removed when code-generation for these types is 1779 // sufficiently reliable. 1780 if (cast<VectorType>(Src)->getElementCount() == ElementCount::getScalable(1)) 1781 return InstructionCost::getInvalid(); 1782 1783 return LT.first * 2; 1784 } 1785 1786 static unsigned getSVEGatherScatterOverhead(unsigned Opcode) { 1787 return Opcode == Instruction::Load ? SVEGatherOverhead : SVEScatterOverhead; 1788 } 1789 1790 InstructionCost AArch64TTIImpl::getGatherScatterOpCost( 1791 unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask, 1792 Align Alignment, TTI::TargetCostKind CostKind, const Instruction *I) { 1793 if (useNeonVector(DataTy)) 1794 return BaseT::getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask, 1795 Alignment, CostKind, I); 1796 auto *VT = cast<VectorType>(DataTy); 1797 auto LT = TLI->getTypeLegalizationCost(DL, DataTy); 1798 if (!LT.first.isValid()) 1799 return InstructionCost::getInvalid(); 1800 1801 // The code-generator is currently not able to handle scalable vectors 1802 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting 1803 // it. This change will be removed when code-generation for these types is 1804 // sufficiently reliable. 1805 if (cast<VectorType>(DataTy)->getElementCount() == 1806 ElementCount::getScalable(1)) 1807 return InstructionCost::getInvalid(); 1808 1809 ElementCount LegalVF = LT.second.getVectorElementCount(); 1810 InstructionCost MemOpCost = 1811 getMemoryOpCost(Opcode, VT->getElementType(), Alignment, 0, CostKind, I); 1812 // Add on an overhead cost for using gathers/scatters. 1813 // TODO: At the moment this is applied unilaterally for all CPUs, but at some 1814 // point we may want a per-CPU overhead. 1815 MemOpCost *= getSVEGatherScatterOverhead(Opcode); 1816 return LT.first * MemOpCost * getMaxNumElements(LegalVF); 1817 } 1818 1819 bool AArch64TTIImpl::useNeonVector(const Type *Ty) const { 1820 return isa<FixedVectorType>(Ty) && !ST->useSVEForFixedLengthVectors(); 1821 } 1822 1823 InstructionCost AArch64TTIImpl::getMemoryOpCost(unsigned Opcode, Type *Ty, 1824 MaybeAlign Alignment, 1825 unsigned AddressSpace, 1826 TTI::TargetCostKind CostKind, 1827 const Instruction *I) { 1828 EVT VT = TLI->getValueType(DL, Ty, true); 1829 // Type legalization can't handle structs 1830 if (VT == MVT::Other) 1831 return BaseT::getMemoryOpCost(Opcode, Ty, Alignment, AddressSpace, 1832 CostKind); 1833 1834 auto LT = TLI->getTypeLegalizationCost(DL, Ty); 1835 if (!LT.first.isValid()) 1836 return InstructionCost::getInvalid(); 1837 1838 // The code-generator is currently not able to handle scalable vectors 1839 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting 1840 // it. This change will be removed when code-generation for these types is 1841 // sufficiently reliable. 1842 if (auto *VTy = dyn_cast<ScalableVectorType>(Ty)) 1843 if (VTy->getElementCount() == ElementCount::getScalable(1)) 1844 return InstructionCost::getInvalid(); 1845 1846 // TODO: consider latency as well for TCK_SizeAndLatency. 1847 if (CostKind == TTI::TCK_CodeSize || CostKind == TTI::TCK_SizeAndLatency) 1848 return LT.first; 1849 1850 if (CostKind != TTI::TCK_RecipThroughput) 1851 return 1; 1852 1853 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store && 1854 LT.second.is128BitVector() && (!Alignment || *Alignment < Align(16))) { 1855 // Unaligned stores are extremely inefficient. We don't split all 1856 // unaligned 128-bit stores because the negative impact that has shown in 1857 // practice on inlined block copy code. 1858 // We make such stores expensive so that we will only vectorize if there 1859 // are 6 other instructions getting vectorized. 1860 const int AmortizationCost = 6; 1861 1862 return LT.first * 2 * AmortizationCost; 1863 } 1864 1865 // Check truncating stores and extending loads. 1866 if (useNeonVector(Ty) && 1867 Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) { 1868 // v4i8 types are lowered to scalar a load/store and sshll/xtn. 1869 if (VT == MVT::v4i8) 1870 return 2; 1871 // Otherwise we need to scalarize. 1872 return cast<FixedVectorType>(Ty)->getNumElements() * 2; 1873 } 1874 1875 return LT.first; 1876 } 1877 1878 InstructionCost AArch64TTIImpl::getInterleavedMemoryOpCost( 1879 unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices, 1880 Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, 1881 bool UseMaskForCond, bool UseMaskForGaps) { 1882 assert(Factor >= 2 && "Invalid interleave factor"); 1883 auto *VecVTy = cast<FixedVectorType>(VecTy); 1884 1885 if (!UseMaskForCond && !UseMaskForGaps && 1886 Factor <= TLI->getMaxSupportedInterleaveFactor()) { 1887 unsigned NumElts = VecVTy->getNumElements(); 1888 auto *SubVecTy = 1889 FixedVectorType::get(VecTy->getScalarType(), NumElts / Factor); 1890 1891 // ldN/stN only support legal vector types of size 64 or 128 in bits. 1892 // Accesses having vector types that are a multiple of 128 bits can be 1893 // matched to more than one ldN/stN instruction. 1894 bool UseScalable; 1895 if (NumElts % Factor == 0 && 1896 TLI->isLegalInterleavedAccessType(SubVecTy, DL, UseScalable)) 1897 return Factor * TLI->getNumInterleavedAccesses(SubVecTy, DL, UseScalable); 1898 } 1899 1900 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices, 1901 Alignment, AddressSpace, CostKind, 1902 UseMaskForCond, UseMaskForGaps); 1903 } 1904 1905 InstructionCost 1906 AArch64TTIImpl::getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) { 1907 InstructionCost Cost = 0; 1908 TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput; 1909 for (auto *I : Tys) { 1910 if (!I->isVectorTy()) 1911 continue; 1912 if (I->getScalarSizeInBits() * cast<FixedVectorType>(I)->getNumElements() == 1913 128) 1914 Cost += getMemoryOpCost(Instruction::Store, I, Align(128), 0, CostKind) + 1915 getMemoryOpCost(Instruction::Load, I, Align(128), 0, CostKind); 1916 } 1917 return Cost; 1918 } 1919 1920 unsigned AArch64TTIImpl::getMaxInterleaveFactor(unsigned VF) { 1921 return ST->getMaxInterleaveFactor(); 1922 } 1923 1924 // For Falkor, we want to avoid having too many strided loads in a loop since 1925 // that can exhaust the HW prefetcher resources. We adjust the unroller 1926 // MaxCount preference below to attempt to ensure unrolling doesn't create too 1927 // many strided loads. 1928 static void 1929 getFalkorUnrollingPreferences(Loop *L, ScalarEvolution &SE, 1930 TargetTransformInfo::UnrollingPreferences &UP) { 1931 enum { MaxStridedLoads = 7 }; 1932 auto countStridedLoads = [](Loop *L, ScalarEvolution &SE) { 1933 int StridedLoads = 0; 1934 // FIXME? We could make this more precise by looking at the CFG and 1935 // e.g. not counting loads in each side of an if-then-else diamond. 1936 for (const auto BB : L->blocks()) { 1937 for (auto &I : *BB) { 1938 LoadInst *LMemI = dyn_cast<LoadInst>(&I); 1939 if (!LMemI) 1940 continue; 1941 1942 Value *PtrValue = LMemI->getPointerOperand(); 1943 if (L->isLoopInvariant(PtrValue)) 1944 continue; 1945 1946 const SCEV *LSCEV = SE.getSCEV(PtrValue); 1947 const SCEVAddRecExpr *LSCEVAddRec = dyn_cast<SCEVAddRecExpr>(LSCEV); 1948 if (!LSCEVAddRec || !LSCEVAddRec->isAffine()) 1949 continue; 1950 1951 // FIXME? We could take pairing of unrolled load copies into account 1952 // by looking at the AddRec, but we would probably have to limit this 1953 // to loops with no stores or other memory optimization barriers. 1954 ++StridedLoads; 1955 // We've seen enough strided loads that seeing more won't make a 1956 // difference. 1957 if (StridedLoads > MaxStridedLoads / 2) 1958 return StridedLoads; 1959 } 1960 } 1961 return StridedLoads; 1962 }; 1963 1964 int StridedLoads = countStridedLoads(L, SE); 1965 LLVM_DEBUG(dbgs() << "falkor-hwpf: detected " << StridedLoads 1966 << " strided loads\n"); 1967 // Pick the largest power of 2 unroll count that won't result in too many 1968 // strided loads. 1969 if (StridedLoads) { 1970 UP.MaxCount = 1 << Log2_32(MaxStridedLoads / StridedLoads); 1971 LLVM_DEBUG(dbgs() << "falkor-hwpf: setting unroll MaxCount to " 1972 << UP.MaxCount << '\n'); 1973 } 1974 } 1975 1976 void AArch64TTIImpl::getUnrollingPreferences(Loop *L, ScalarEvolution &SE, 1977 TTI::UnrollingPreferences &UP, 1978 OptimizationRemarkEmitter *ORE) { 1979 // Enable partial unrolling and runtime unrolling. 1980 BaseT::getUnrollingPreferences(L, SE, UP, ORE); 1981 1982 UP.UpperBound = true; 1983 1984 // For inner loop, it is more likely to be a hot one, and the runtime check 1985 // can be promoted out from LICM pass, so the overhead is less, let's try 1986 // a larger threshold to unroll more loops. 1987 if (L->getLoopDepth() > 1) 1988 UP.PartialThreshold *= 2; 1989 1990 // Disable partial & runtime unrolling on -Os. 1991 UP.PartialOptSizeThreshold = 0; 1992 1993 if (ST->getProcFamily() == AArch64Subtarget::Falkor && 1994 EnableFalkorHWPFUnrollFix) 1995 getFalkorUnrollingPreferences(L, SE, UP); 1996 1997 // Scan the loop: don't unroll loops with calls as this could prevent 1998 // inlining. Don't unroll vector loops either, as they don't benefit much from 1999 // unrolling. 2000 for (auto *BB : L->getBlocks()) { 2001 for (auto &I : *BB) { 2002 // Don't unroll vectorised loop. 2003 if (I.getType()->isVectorTy()) 2004 return; 2005 2006 if (isa<CallInst>(I) || isa<InvokeInst>(I)) { 2007 if (const Function *F = cast<CallBase>(I).getCalledFunction()) { 2008 if (!isLoweredToCall(F)) 2009 continue; 2010 } 2011 return; 2012 } 2013 } 2014 } 2015 2016 // Enable runtime unrolling for in-order models 2017 // If mcpu is omitted, getProcFamily() returns AArch64Subtarget::Others, so by 2018 // checking for that case, we can ensure that the default behaviour is 2019 // unchanged 2020 if (ST->getProcFamily() != AArch64Subtarget::Others && 2021 !ST->getSchedModel().isOutOfOrder()) { 2022 UP.Runtime = true; 2023 UP.Partial = true; 2024 UP.UnrollRemainder = true; 2025 UP.DefaultUnrollRuntimeCount = 4; 2026 2027 UP.UnrollAndJam = true; 2028 UP.UnrollAndJamInnerLoopThreshold = 60; 2029 } 2030 } 2031 2032 void AArch64TTIImpl::getPeelingPreferences(Loop *L, ScalarEvolution &SE, 2033 TTI::PeelingPreferences &PP) { 2034 BaseT::getPeelingPreferences(L, SE, PP); 2035 } 2036 2037 Value *AArch64TTIImpl::getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, 2038 Type *ExpectedType) { 2039 switch (Inst->getIntrinsicID()) { 2040 default: 2041 return nullptr; 2042 case Intrinsic::aarch64_neon_st2: 2043 case Intrinsic::aarch64_neon_st3: 2044 case Intrinsic::aarch64_neon_st4: { 2045 // Create a struct type 2046 StructType *ST = dyn_cast<StructType>(ExpectedType); 2047 if (!ST) 2048 return nullptr; 2049 unsigned NumElts = Inst->arg_size() - 1; 2050 if (ST->getNumElements() != NumElts) 2051 return nullptr; 2052 for (unsigned i = 0, e = NumElts; i != e; ++i) { 2053 if (Inst->getArgOperand(i)->getType() != ST->getElementType(i)) 2054 return nullptr; 2055 } 2056 Value *Res = UndefValue::get(ExpectedType); 2057 IRBuilder<> Builder(Inst); 2058 for (unsigned i = 0, e = NumElts; i != e; ++i) { 2059 Value *L = Inst->getArgOperand(i); 2060 Res = Builder.CreateInsertValue(Res, L, i); 2061 } 2062 return Res; 2063 } 2064 case Intrinsic::aarch64_neon_ld2: 2065 case Intrinsic::aarch64_neon_ld3: 2066 case Intrinsic::aarch64_neon_ld4: 2067 if (Inst->getType() == ExpectedType) 2068 return Inst; 2069 return nullptr; 2070 } 2071 } 2072 2073 bool AArch64TTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst, 2074 MemIntrinsicInfo &Info) { 2075 switch (Inst->getIntrinsicID()) { 2076 default: 2077 break; 2078 case Intrinsic::aarch64_neon_ld2: 2079 case Intrinsic::aarch64_neon_ld3: 2080 case Intrinsic::aarch64_neon_ld4: 2081 Info.ReadMem = true; 2082 Info.WriteMem = false; 2083 Info.PtrVal = Inst->getArgOperand(0); 2084 break; 2085 case Intrinsic::aarch64_neon_st2: 2086 case Intrinsic::aarch64_neon_st3: 2087 case Intrinsic::aarch64_neon_st4: 2088 Info.ReadMem = false; 2089 Info.WriteMem = true; 2090 Info.PtrVal = Inst->getArgOperand(Inst->arg_size() - 1); 2091 break; 2092 } 2093 2094 switch (Inst->getIntrinsicID()) { 2095 default: 2096 return false; 2097 case Intrinsic::aarch64_neon_ld2: 2098 case Intrinsic::aarch64_neon_st2: 2099 Info.MatchingId = VECTOR_LDST_TWO_ELEMENTS; 2100 break; 2101 case Intrinsic::aarch64_neon_ld3: 2102 case Intrinsic::aarch64_neon_st3: 2103 Info.MatchingId = VECTOR_LDST_THREE_ELEMENTS; 2104 break; 2105 case Intrinsic::aarch64_neon_ld4: 2106 case Intrinsic::aarch64_neon_st4: 2107 Info.MatchingId = VECTOR_LDST_FOUR_ELEMENTS; 2108 break; 2109 } 2110 return true; 2111 } 2112 2113 /// See if \p I should be considered for address type promotion. We check if \p 2114 /// I is a sext with right type and used in memory accesses. If it used in a 2115 /// "complex" getelementptr, we allow it to be promoted without finding other 2116 /// sext instructions that sign extended the same initial value. A getelementptr 2117 /// is considered as "complex" if it has more than 2 operands. 2118 bool AArch64TTIImpl::shouldConsiderAddressTypePromotion( 2119 const Instruction &I, bool &AllowPromotionWithoutCommonHeader) { 2120 bool Considerable = false; 2121 AllowPromotionWithoutCommonHeader = false; 2122 if (!isa<SExtInst>(&I)) 2123 return false; 2124 Type *ConsideredSExtType = 2125 Type::getInt64Ty(I.getParent()->getParent()->getContext()); 2126 if (I.getType() != ConsideredSExtType) 2127 return false; 2128 // See if the sext is the one with the right type and used in at least one 2129 // GetElementPtrInst. 2130 for (const User *U : I.users()) { 2131 if (const GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(U)) { 2132 Considerable = true; 2133 // A getelementptr is considered as "complex" if it has more than 2 2134 // operands. We will promote a SExt used in such complex GEP as we 2135 // expect some computation to be merged if they are done on 64 bits. 2136 if (GEPInst->getNumOperands() > 2) { 2137 AllowPromotionWithoutCommonHeader = true; 2138 break; 2139 } 2140 } 2141 } 2142 return Considerable; 2143 } 2144 2145 bool AArch64TTIImpl::isLegalToVectorizeReduction( 2146 const RecurrenceDescriptor &RdxDesc, ElementCount VF) const { 2147 if (!VF.isScalable()) 2148 return true; 2149 2150 Type *Ty = RdxDesc.getRecurrenceType(); 2151 if (Ty->isBFloatTy() || !isElementTypeLegalForScalableVector(Ty)) 2152 return false; 2153 2154 switch (RdxDesc.getRecurrenceKind()) { 2155 case RecurKind::Add: 2156 case RecurKind::FAdd: 2157 case RecurKind::And: 2158 case RecurKind::Or: 2159 case RecurKind::Xor: 2160 case RecurKind::SMin: 2161 case RecurKind::SMax: 2162 case RecurKind::UMin: 2163 case RecurKind::UMax: 2164 case RecurKind::FMin: 2165 case RecurKind::FMax: 2166 case RecurKind::SelectICmp: 2167 case RecurKind::SelectFCmp: 2168 case RecurKind::FMulAdd: 2169 return true; 2170 default: 2171 return false; 2172 } 2173 } 2174 2175 InstructionCost 2176 AArch64TTIImpl::getMinMaxReductionCost(VectorType *Ty, VectorType *CondTy, 2177 bool IsUnsigned, 2178 TTI::TargetCostKind CostKind) { 2179 std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Ty); 2180 2181 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16()) 2182 return BaseT::getMinMaxReductionCost(Ty, CondTy, IsUnsigned, CostKind); 2183 2184 assert((isa<ScalableVectorType>(Ty) == isa<ScalableVectorType>(CondTy)) && 2185 "Both vector needs to be equally scalable"); 2186 2187 InstructionCost LegalizationCost = 0; 2188 if (LT.first > 1) { 2189 Type *LegalVTy = EVT(LT.second).getTypeForEVT(Ty->getContext()); 2190 unsigned MinMaxOpcode = 2191 Ty->isFPOrFPVectorTy() 2192 ? Intrinsic::maxnum 2193 : (IsUnsigned ? Intrinsic::umin : Intrinsic::smin); 2194 IntrinsicCostAttributes Attrs(MinMaxOpcode, LegalVTy, {LegalVTy, LegalVTy}); 2195 LegalizationCost = getIntrinsicInstrCost(Attrs, CostKind) * (LT.first - 1); 2196 } 2197 2198 return LegalizationCost + /*Cost of horizontal reduction*/ 2; 2199 } 2200 2201 InstructionCost AArch64TTIImpl::getArithmeticReductionCostSVE( 2202 unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) { 2203 std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, ValTy); 2204 InstructionCost LegalizationCost = 0; 2205 if (LT.first > 1) { 2206 Type *LegalVTy = EVT(LT.second).getTypeForEVT(ValTy->getContext()); 2207 LegalizationCost = getArithmeticInstrCost(Opcode, LegalVTy, CostKind); 2208 LegalizationCost *= LT.first - 1; 2209 } 2210 2211 int ISD = TLI->InstructionOpcodeToISD(Opcode); 2212 assert(ISD && "Invalid opcode"); 2213 // Add the final reduction cost for the legal horizontal reduction 2214 switch (ISD) { 2215 case ISD::ADD: 2216 case ISD::AND: 2217 case ISD::OR: 2218 case ISD::XOR: 2219 case ISD::FADD: 2220 return LegalizationCost + 2; 2221 default: 2222 return InstructionCost::getInvalid(); 2223 } 2224 } 2225 2226 InstructionCost 2227 AArch64TTIImpl::getArithmeticReductionCost(unsigned Opcode, VectorType *ValTy, 2228 Optional<FastMathFlags> FMF, 2229 TTI::TargetCostKind CostKind) { 2230 if (TTI::requiresOrderedReduction(FMF)) { 2231 if (auto *FixedVTy = dyn_cast<FixedVectorType>(ValTy)) { 2232 InstructionCost BaseCost = 2233 BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind); 2234 // Add on extra cost to reflect the extra overhead on some CPUs. We still 2235 // end up vectorizing for more computationally intensive loops. 2236 return BaseCost + FixedVTy->getNumElements(); 2237 } 2238 2239 if (Opcode != Instruction::FAdd) 2240 return InstructionCost::getInvalid(); 2241 2242 auto *VTy = cast<ScalableVectorType>(ValTy); 2243 InstructionCost Cost = 2244 getArithmeticInstrCost(Opcode, VTy->getScalarType(), CostKind); 2245 Cost *= getMaxNumElements(VTy->getElementCount()); 2246 return Cost; 2247 } 2248 2249 if (isa<ScalableVectorType>(ValTy)) 2250 return getArithmeticReductionCostSVE(Opcode, ValTy, CostKind); 2251 2252 std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, ValTy); 2253 MVT MTy = LT.second; 2254 int ISD = TLI->InstructionOpcodeToISD(Opcode); 2255 assert(ISD && "Invalid opcode"); 2256 2257 // Horizontal adds can use the 'addv' instruction. We model the cost of these 2258 // instructions as twice a normal vector add, plus 1 for each legalization 2259 // step (LT.first). This is the only arithmetic vector reduction operation for 2260 // which we have an instruction. 2261 // OR, XOR and AND costs should match the codegen from: 2262 // OR: llvm/test/CodeGen/AArch64/reduce-or.ll 2263 // XOR: llvm/test/CodeGen/AArch64/reduce-xor.ll 2264 // AND: llvm/test/CodeGen/AArch64/reduce-and.ll 2265 static const CostTblEntry CostTblNoPairwise[]{ 2266 {ISD::ADD, MVT::v8i8, 2}, 2267 {ISD::ADD, MVT::v16i8, 2}, 2268 {ISD::ADD, MVT::v4i16, 2}, 2269 {ISD::ADD, MVT::v8i16, 2}, 2270 {ISD::ADD, MVT::v4i32, 2}, 2271 {ISD::OR, MVT::v8i8, 15}, 2272 {ISD::OR, MVT::v16i8, 17}, 2273 {ISD::OR, MVT::v4i16, 7}, 2274 {ISD::OR, MVT::v8i16, 9}, 2275 {ISD::OR, MVT::v2i32, 3}, 2276 {ISD::OR, MVT::v4i32, 5}, 2277 {ISD::OR, MVT::v2i64, 3}, 2278 {ISD::XOR, MVT::v8i8, 15}, 2279 {ISD::XOR, MVT::v16i8, 17}, 2280 {ISD::XOR, MVT::v4i16, 7}, 2281 {ISD::XOR, MVT::v8i16, 9}, 2282 {ISD::XOR, MVT::v2i32, 3}, 2283 {ISD::XOR, MVT::v4i32, 5}, 2284 {ISD::XOR, MVT::v2i64, 3}, 2285 {ISD::AND, MVT::v8i8, 15}, 2286 {ISD::AND, MVT::v16i8, 17}, 2287 {ISD::AND, MVT::v4i16, 7}, 2288 {ISD::AND, MVT::v8i16, 9}, 2289 {ISD::AND, MVT::v2i32, 3}, 2290 {ISD::AND, MVT::v4i32, 5}, 2291 {ISD::AND, MVT::v2i64, 3}, 2292 }; 2293 switch (ISD) { 2294 default: 2295 break; 2296 case ISD::ADD: 2297 if (const auto *Entry = CostTableLookup(CostTblNoPairwise, ISD, MTy)) 2298 return (LT.first - 1) + Entry->Cost; 2299 break; 2300 case ISD::XOR: 2301 case ISD::AND: 2302 case ISD::OR: 2303 const auto *Entry = CostTableLookup(CostTblNoPairwise, ISD, MTy); 2304 if (!Entry) 2305 break; 2306 auto *ValVTy = cast<FixedVectorType>(ValTy); 2307 if (!ValVTy->getElementType()->isIntegerTy(1) && 2308 MTy.getVectorNumElements() <= ValVTy->getNumElements() && 2309 isPowerOf2_32(ValVTy->getNumElements())) { 2310 InstructionCost ExtraCost = 0; 2311 if (LT.first != 1) { 2312 // Type needs to be split, so there is an extra cost of LT.first - 1 2313 // arithmetic ops. 2314 auto *Ty = FixedVectorType::get(ValTy->getElementType(), 2315 MTy.getVectorNumElements()); 2316 ExtraCost = getArithmeticInstrCost(Opcode, Ty, CostKind); 2317 ExtraCost *= LT.first - 1; 2318 } 2319 return Entry->Cost + ExtraCost; 2320 } 2321 break; 2322 } 2323 return BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind); 2324 } 2325 2326 InstructionCost AArch64TTIImpl::getSpliceCost(VectorType *Tp, int Index) { 2327 static const CostTblEntry ShuffleTbl[] = { 2328 { TTI::SK_Splice, MVT::nxv16i8, 1 }, 2329 { TTI::SK_Splice, MVT::nxv8i16, 1 }, 2330 { TTI::SK_Splice, MVT::nxv4i32, 1 }, 2331 { TTI::SK_Splice, MVT::nxv2i64, 1 }, 2332 { TTI::SK_Splice, MVT::nxv2f16, 1 }, 2333 { TTI::SK_Splice, MVT::nxv4f16, 1 }, 2334 { TTI::SK_Splice, MVT::nxv8f16, 1 }, 2335 { TTI::SK_Splice, MVT::nxv2bf16, 1 }, 2336 { TTI::SK_Splice, MVT::nxv4bf16, 1 }, 2337 { TTI::SK_Splice, MVT::nxv8bf16, 1 }, 2338 { TTI::SK_Splice, MVT::nxv2f32, 1 }, 2339 { TTI::SK_Splice, MVT::nxv4f32, 1 }, 2340 { TTI::SK_Splice, MVT::nxv2f64, 1 }, 2341 }; 2342 2343 std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Tp); 2344 Type *LegalVTy = EVT(LT.second).getTypeForEVT(Tp->getContext()); 2345 TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput; 2346 EVT PromotedVT = LT.second.getScalarType() == MVT::i1 2347 ? TLI->getPromotedVTForPredicate(EVT(LT.second)) 2348 : LT.second; 2349 Type *PromotedVTy = EVT(PromotedVT).getTypeForEVT(Tp->getContext()); 2350 InstructionCost LegalizationCost = 0; 2351 if (Index < 0) { 2352 LegalizationCost = 2353 getCmpSelInstrCost(Instruction::ICmp, PromotedVTy, PromotedVTy, 2354 CmpInst::BAD_ICMP_PREDICATE, CostKind) + 2355 getCmpSelInstrCost(Instruction::Select, PromotedVTy, LegalVTy, 2356 CmpInst::BAD_ICMP_PREDICATE, CostKind); 2357 } 2358 2359 // Predicated splice are promoted when lowering. See AArch64ISelLowering.cpp 2360 // Cost performed on a promoted type. 2361 if (LT.second.getScalarType() == MVT::i1) { 2362 LegalizationCost += 2363 getCastInstrCost(Instruction::ZExt, PromotedVTy, LegalVTy, 2364 TTI::CastContextHint::None, CostKind) + 2365 getCastInstrCost(Instruction::Trunc, LegalVTy, PromotedVTy, 2366 TTI::CastContextHint::None, CostKind); 2367 } 2368 const auto *Entry = 2369 CostTableLookup(ShuffleTbl, TTI::SK_Splice, PromotedVT.getSimpleVT()); 2370 assert(Entry && "Illegal Type for Splice"); 2371 LegalizationCost += Entry->Cost; 2372 return LegalizationCost * LT.first; 2373 } 2374 2375 InstructionCost AArch64TTIImpl::getShuffleCost(TTI::ShuffleKind Kind, 2376 VectorType *Tp, 2377 ArrayRef<int> Mask, int Index, 2378 VectorType *SubTp) { 2379 Kind = improveShuffleKindFromMask(Kind, Mask); 2380 if (Kind == TTI::SK_Broadcast || Kind == TTI::SK_Transpose || 2381 Kind == TTI::SK_Select || Kind == TTI::SK_PermuteSingleSrc || 2382 Kind == TTI::SK_Reverse) { 2383 static const CostTblEntry ShuffleTbl[] = { 2384 // Broadcast shuffle kinds can be performed with 'dup'. 2385 { TTI::SK_Broadcast, MVT::v8i8, 1 }, 2386 { TTI::SK_Broadcast, MVT::v16i8, 1 }, 2387 { TTI::SK_Broadcast, MVT::v4i16, 1 }, 2388 { TTI::SK_Broadcast, MVT::v8i16, 1 }, 2389 { TTI::SK_Broadcast, MVT::v2i32, 1 }, 2390 { TTI::SK_Broadcast, MVT::v4i32, 1 }, 2391 { TTI::SK_Broadcast, MVT::v2i64, 1 }, 2392 { TTI::SK_Broadcast, MVT::v2f32, 1 }, 2393 { TTI::SK_Broadcast, MVT::v4f32, 1 }, 2394 { TTI::SK_Broadcast, MVT::v2f64, 1 }, 2395 // Transpose shuffle kinds can be performed with 'trn1/trn2' and 2396 // 'zip1/zip2' instructions. 2397 { TTI::SK_Transpose, MVT::v8i8, 1 }, 2398 { TTI::SK_Transpose, MVT::v16i8, 1 }, 2399 { TTI::SK_Transpose, MVT::v4i16, 1 }, 2400 { TTI::SK_Transpose, MVT::v8i16, 1 }, 2401 { TTI::SK_Transpose, MVT::v2i32, 1 }, 2402 { TTI::SK_Transpose, MVT::v4i32, 1 }, 2403 { TTI::SK_Transpose, MVT::v2i64, 1 }, 2404 { TTI::SK_Transpose, MVT::v2f32, 1 }, 2405 { TTI::SK_Transpose, MVT::v4f32, 1 }, 2406 { TTI::SK_Transpose, MVT::v2f64, 1 }, 2407 // Select shuffle kinds. 2408 // TODO: handle vXi8/vXi16. 2409 { TTI::SK_Select, MVT::v2i32, 1 }, // mov. 2410 { TTI::SK_Select, MVT::v4i32, 2 }, // rev+trn (or similar). 2411 { TTI::SK_Select, MVT::v2i64, 1 }, // mov. 2412 { TTI::SK_Select, MVT::v2f32, 1 }, // mov. 2413 { TTI::SK_Select, MVT::v4f32, 2 }, // rev+trn (or similar). 2414 { TTI::SK_Select, MVT::v2f64, 1 }, // mov. 2415 // PermuteSingleSrc shuffle kinds. 2416 { TTI::SK_PermuteSingleSrc, MVT::v2i32, 1 }, // mov. 2417 { TTI::SK_PermuteSingleSrc, MVT::v4i32, 3 }, // perfectshuffle worst case. 2418 { TTI::SK_PermuteSingleSrc, MVT::v2i64, 1 }, // mov. 2419 { TTI::SK_PermuteSingleSrc, MVT::v2f32, 1 }, // mov. 2420 { TTI::SK_PermuteSingleSrc, MVT::v4f32, 3 }, // perfectshuffle worst case. 2421 { TTI::SK_PermuteSingleSrc, MVT::v2f64, 1 }, // mov. 2422 { TTI::SK_PermuteSingleSrc, MVT::v4i16, 3 }, // perfectshuffle worst case. 2423 { TTI::SK_PermuteSingleSrc, MVT::v4f16, 3 }, // perfectshuffle worst case. 2424 { TTI::SK_PermuteSingleSrc, MVT::v4bf16, 3 }, // perfectshuffle worst case. 2425 { TTI::SK_PermuteSingleSrc, MVT::v8i16, 8 }, // constpool + load + tbl 2426 { TTI::SK_PermuteSingleSrc, MVT::v8f16, 8 }, // constpool + load + tbl 2427 { TTI::SK_PermuteSingleSrc, MVT::v8bf16, 8 }, // constpool + load + tbl 2428 { TTI::SK_PermuteSingleSrc, MVT::v8i8, 8 }, // constpool + load + tbl 2429 { TTI::SK_PermuteSingleSrc, MVT::v16i8, 8 }, // constpool + load + tbl 2430 // Reverse can be lowered with `rev`. 2431 { TTI::SK_Reverse, MVT::v2i32, 1 }, // mov. 2432 { TTI::SK_Reverse, MVT::v4i32, 2 }, // REV64; EXT 2433 { TTI::SK_Reverse, MVT::v2i64, 1 }, // mov. 2434 { TTI::SK_Reverse, MVT::v2f32, 1 }, // mov. 2435 { TTI::SK_Reverse, MVT::v4f32, 2 }, // REV64; EXT 2436 { TTI::SK_Reverse, MVT::v2f64, 1 }, // mov. 2437 // Broadcast shuffle kinds for scalable vectors 2438 { TTI::SK_Broadcast, MVT::nxv16i8, 1 }, 2439 { TTI::SK_Broadcast, MVT::nxv8i16, 1 }, 2440 { TTI::SK_Broadcast, MVT::nxv4i32, 1 }, 2441 { TTI::SK_Broadcast, MVT::nxv2i64, 1 }, 2442 { TTI::SK_Broadcast, MVT::nxv2f16, 1 }, 2443 { TTI::SK_Broadcast, MVT::nxv4f16, 1 }, 2444 { TTI::SK_Broadcast, MVT::nxv8f16, 1 }, 2445 { TTI::SK_Broadcast, MVT::nxv2bf16, 1 }, 2446 { TTI::SK_Broadcast, MVT::nxv4bf16, 1 }, 2447 { TTI::SK_Broadcast, MVT::nxv8bf16, 1 }, 2448 { TTI::SK_Broadcast, MVT::nxv2f32, 1 }, 2449 { TTI::SK_Broadcast, MVT::nxv4f32, 1 }, 2450 { TTI::SK_Broadcast, MVT::nxv2f64, 1 }, 2451 { TTI::SK_Broadcast, MVT::nxv16i1, 1 }, 2452 { TTI::SK_Broadcast, MVT::nxv8i1, 1 }, 2453 { TTI::SK_Broadcast, MVT::nxv4i1, 1 }, 2454 { TTI::SK_Broadcast, MVT::nxv2i1, 1 }, 2455 // Handle the cases for vector.reverse with scalable vectors 2456 { TTI::SK_Reverse, MVT::nxv16i8, 1 }, 2457 { TTI::SK_Reverse, MVT::nxv8i16, 1 }, 2458 { TTI::SK_Reverse, MVT::nxv4i32, 1 }, 2459 { TTI::SK_Reverse, MVT::nxv2i64, 1 }, 2460 { TTI::SK_Reverse, MVT::nxv2f16, 1 }, 2461 { TTI::SK_Reverse, MVT::nxv4f16, 1 }, 2462 { TTI::SK_Reverse, MVT::nxv8f16, 1 }, 2463 { TTI::SK_Reverse, MVT::nxv2bf16, 1 }, 2464 { TTI::SK_Reverse, MVT::nxv4bf16, 1 }, 2465 { TTI::SK_Reverse, MVT::nxv8bf16, 1 }, 2466 { TTI::SK_Reverse, MVT::nxv2f32, 1 }, 2467 { TTI::SK_Reverse, MVT::nxv4f32, 1 }, 2468 { TTI::SK_Reverse, MVT::nxv2f64, 1 }, 2469 { TTI::SK_Reverse, MVT::nxv16i1, 1 }, 2470 { TTI::SK_Reverse, MVT::nxv8i1, 1 }, 2471 { TTI::SK_Reverse, MVT::nxv4i1, 1 }, 2472 { TTI::SK_Reverse, MVT::nxv2i1, 1 }, 2473 }; 2474 std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Tp); 2475 if (const auto *Entry = CostTableLookup(ShuffleTbl, Kind, LT.second)) 2476 return LT.first * Entry->Cost; 2477 } 2478 if (Kind == TTI::SK_Splice && isa<ScalableVectorType>(Tp)) 2479 return getSpliceCost(Tp, Index); 2480 return BaseT::getShuffleCost(Kind, Tp, Mask, Index, SubTp); 2481 } 2482