1 //===-- AArch64TargetTransformInfo.cpp - AArch64 specific TTI pass --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// This file implements a TargetTransformInfo analysis pass specific to the 11 /// AArch64 target machine. It uses the target's detailed information to provide 12 /// more precise answers to certain TTI queries, while letting the target 13 /// independent and default TTI implementations handle the rest. 14 /// 15 //===----------------------------------------------------------------------===// 16 17 #include "AArch64.h" 18 #include "AArch64TargetMachine.h" 19 #include "MCTargetDesc/AArch64AddressingModes.h" 20 #include "llvm/Analysis/TargetTransformInfo.h" 21 #include "llvm/Support/Debug.h" 22 #include "llvm/Target/CostTable.h" 23 #include "llvm/Target/TargetLowering.h" 24 #include <algorithm> 25 using namespace llvm; 26 27 #define DEBUG_TYPE "aarch64tti" 28 29 // Declare the pass initialization routine locally as target-specific passes 30 // don't have a target-wide initialization entry point, and so we rely on the 31 // pass constructor initialization. 32 namespace llvm { 33 void initializeAArch64TTIPass(PassRegistry &); 34 } 35 36 namespace { 37 38 class AArch64TTI final : public ImmutablePass, public TargetTransformInfo { 39 const AArch64TargetMachine *TM; 40 const AArch64Subtarget *ST; 41 const AArch64TargetLowering *TLI; 42 43 /// Estimate the overhead of scalarizing an instruction. Insert and Extract 44 /// are set if the result needs to be inserted and/or extracted from vectors. 45 unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) const; 46 47 public: 48 AArch64TTI() : ImmutablePass(ID), TM(nullptr), ST(nullptr), TLI(nullptr) { 49 llvm_unreachable("This pass cannot be directly constructed"); 50 } 51 52 AArch64TTI(const AArch64TargetMachine *TM) 53 : ImmutablePass(ID), TM(TM), ST(TM->getSubtargetImpl()), 54 TLI(TM->getSubtargetImpl()->getTargetLowering()) { 55 initializeAArch64TTIPass(*PassRegistry::getPassRegistry()); 56 } 57 58 void initializePass() override { pushTTIStack(this); } 59 60 void getAnalysisUsage(AnalysisUsage &AU) const override { 61 TargetTransformInfo::getAnalysisUsage(AU); 62 } 63 64 /// Pass identification. 65 static char ID; 66 67 /// Provide necessary pointer adjustments for the two base classes. 68 void *getAdjustedAnalysisPointer(const void *ID) override { 69 if (ID == &TargetTransformInfo::ID) 70 return (TargetTransformInfo *)this; 71 return this; 72 } 73 74 /// \name Scalar TTI Implementations 75 /// @{ 76 unsigned getIntImmCost(int64_t Val) const; 77 unsigned getIntImmCost(const APInt &Imm, Type *Ty) const override; 78 unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm, 79 Type *Ty) const override; 80 unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, 81 Type *Ty) const override; 82 PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override; 83 84 /// @} 85 86 /// \name Vector TTI Implementations 87 /// @{ 88 89 unsigned getNumberOfRegisters(bool Vector) const override { 90 if (Vector) { 91 if (ST->hasNEON()) 92 return 32; 93 return 0; 94 } 95 return 31; 96 } 97 98 unsigned getRegisterBitWidth(bool Vector) const override { 99 if (Vector) { 100 if (ST->hasNEON()) 101 return 128; 102 return 0; 103 } 104 return 64; 105 } 106 107 unsigned getMaxInterleaveFactor() const override; 108 109 unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const 110 override; 111 112 unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) const 113 override; 114 115 unsigned getArithmeticInstrCost( 116 unsigned Opcode, Type *Ty, OperandValueKind Opd1Info = OK_AnyValue, 117 OperandValueKind Opd2Info = OK_AnyValue, 118 OperandValueProperties Opd1PropInfo = OP_None, 119 OperandValueProperties Opd2PropInfo = OP_None) const override; 120 121 unsigned getAddressComputationCost(Type *Ty, bool IsComplex) const override; 122 123 unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) const 124 override; 125 126 unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, 127 unsigned AddressSpace) const override; 128 129 unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type*> Tys) const override; 130 131 void getUnrollingPreferences(const Function *F, Loop *L, 132 UnrollingPreferences &UP) const override; 133 134 135 /// @} 136 }; 137 138 } // end anonymous namespace 139 140 INITIALIZE_AG_PASS(AArch64TTI, TargetTransformInfo, "aarch64tti", 141 "AArch64 Target Transform Info", true, true, false) 142 char AArch64TTI::ID = 0; 143 144 ImmutablePass * 145 llvm::createAArch64TargetTransformInfoPass(const AArch64TargetMachine *TM) { 146 return new AArch64TTI(TM); 147 } 148 149 /// \brief Calculate the cost of materializing a 64-bit value. This helper 150 /// method might only calculate a fraction of a larger immediate. Therefore it 151 /// is valid to return a cost of ZERO. 152 unsigned AArch64TTI::getIntImmCost(int64_t Val) const { 153 // Check if the immediate can be encoded within an instruction. 154 if (Val == 0 || AArch64_AM::isLogicalImmediate(Val, 64)) 155 return 0; 156 157 if (Val < 0) 158 Val = ~Val; 159 160 // Calculate how many moves we will need to materialize this constant. 161 unsigned LZ = countLeadingZeros((uint64_t)Val); 162 return (64 - LZ + 15) / 16; 163 } 164 165 /// \brief Calculate the cost of materializing the given constant. 166 unsigned AArch64TTI::getIntImmCost(const APInt &Imm, Type *Ty) const { 167 assert(Ty->isIntegerTy()); 168 169 unsigned BitSize = Ty->getPrimitiveSizeInBits(); 170 if (BitSize == 0) 171 return ~0U; 172 173 // Sign-extend all constants to a multiple of 64-bit. 174 APInt ImmVal = Imm; 175 if (BitSize & 0x3f) 176 ImmVal = Imm.sext((BitSize + 63) & ~0x3fU); 177 178 // Split the constant into 64-bit chunks and calculate the cost for each 179 // chunk. 180 unsigned Cost = 0; 181 for (unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) { 182 APInt Tmp = ImmVal.ashr(ShiftVal).sextOrTrunc(64); 183 int64_t Val = Tmp.getSExtValue(); 184 Cost += getIntImmCost(Val); 185 } 186 // We need at least one instruction to materialze the constant. 187 return std::max(1U, Cost); 188 } 189 190 unsigned AArch64TTI::getIntImmCost(unsigned Opcode, unsigned Idx, 191 const APInt &Imm, Type *Ty) const { 192 assert(Ty->isIntegerTy()); 193 194 unsigned BitSize = Ty->getPrimitiveSizeInBits(); 195 // There is no cost model for constants with a bit size of 0. Return TCC_Free 196 // here, so that constant hoisting will ignore this constant. 197 if (BitSize == 0) 198 return TCC_Free; 199 200 unsigned ImmIdx = ~0U; 201 switch (Opcode) { 202 default: 203 return TCC_Free; 204 case Instruction::GetElementPtr: 205 // Always hoist the base address of a GetElementPtr. 206 if (Idx == 0) 207 return 2 * TCC_Basic; 208 return TCC_Free; 209 case Instruction::Store: 210 ImmIdx = 0; 211 break; 212 case Instruction::Add: 213 case Instruction::Sub: 214 case Instruction::Mul: 215 case Instruction::UDiv: 216 case Instruction::SDiv: 217 case Instruction::URem: 218 case Instruction::SRem: 219 case Instruction::And: 220 case Instruction::Or: 221 case Instruction::Xor: 222 case Instruction::ICmp: 223 ImmIdx = 1; 224 break; 225 // Always return TCC_Free for the shift value of a shift instruction. 226 case Instruction::Shl: 227 case Instruction::LShr: 228 case Instruction::AShr: 229 if (Idx == 1) 230 return TCC_Free; 231 break; 232 case Instruction::Trunc: 233 case Instruction::ZExt: 234 case Instruction::SExt: 235 case Instruction::IntToPtr: 236 case Instruction::PtrToInt: 237 case Instruction::BitCast: 238 case Instruction::PHI: 239 case Instruction::Call: 240 case Instruction::Select: 241 case Instruction::Ret: 242 case Instruction::Load: 243 break; 244 } 245 246 if (Idx == ImmIdx) { 247 unsigned NumConstants = (BitSize + 63) / 64; 248 unsigned Cost = AArch64TTI::getIntImmCost(Imm, Ty); 249 return (Cost <= NumConstants * TCC_Basic) 250 ? static_cast<unsigned>(TCC_Free) : Cost; 251 } 252 return AArch64TTI::getIntImmCost(Imm, Ty); 253 } 254 255 unsigned AArch64TTI::getIntImmCost(Intrinsic::ID IID, unsigned Idx, 256 const APInt &Imm, Type *Ty) const { 257 assert(Ty->isIntegerTy()); 258 259 unsigned BitSize = Ty->getPrimitiveSizeInBits(); 260 // There is no cost model for constants with a bit size of 0. Return TCC_Free 261 // here, so that constant hoisting will ignore this constant. 262 if (BitSize == 0) 263 return TCC_Free; 264 265 switch (IID) { 266 default: 267 return TCC_Free; 268 case Intrinsic::sadd_with_overflow: 269 case Intrinsic::uadd_with_overflow: 270 case Intrinsic::ssub_with_overflow: 271 case Intrinsic::usub_with_overflow: 272 case Intrinsic::smul_with_overflow: 273 case Intrinsic::umul_with_overflow: 274 if (Idx == 1) { 275 unsigned NumConstants = (BitSize + 63) / 64; 276 unsigned Cost = AArch64TTI::getIntImmCost(Imm, Ty); 277 return (Cost <= NumConstants * TCC_Basic) 278 ? static_cast<unsigned>(TCC_Free) : Cost; 279 } 280 break; 281 case Intrinsic::experimental_stackmap: 282 if ((Idx < 2) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) 283 return TCC_Free; 284 break; 285 case Intrinsic::experimental_patchpoint_void: 286 case Intrinsic::experimental_patchpoint_i64: 287 if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) 288 return TCC_Free; 289 break; 290 } 291 return AArch64TTI::getIntImmCost(Imm, Ty); 292 } 293 294 AArch64TTI::PopcntSupportKind 295 AArch64TTI::getPopcntSupport(unsigned TyWidth) const { 296 assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2"); 297 if (TyWidth == 32 || TyWidth == 64) 298 return PSK_FastHardware; 299 // TODO: AArch64TargetLowering::LowerCTPOP() supports 128bit popcount. 300 return PSK_Software; 301 } 302 303 unsigned AArch64TTI::getCastInstrCost(unsigned Opcode, Type *Dst, 304 Type *Src) const { 305 int ISD = TLI->InstructionOpcodeToISD(Opcode); 306 assert(ISD && "Invalid opcode"); 307 308 EVT SrcTy = TLI->getValueType(Src); 309 EVT DstTy = TLI->getValueType(Dst); 310 311 if (!SrcTy.isSimple() || !DstTy.isSimple()) 312 return TargetTransformInfo::getCastInstrCost(Opcode, Dst, Src); 313 314 static const TypeConversionCostTblEntry<MVT> ConversionTbl[] = { 315 // LowerVectorINT_TO_FP: 316 { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i32, 1 }, 317 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, 1 }, 318 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 1 }, 319 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 1 }, 320 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 1 }, 321 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 1 }, 322 323 // Complex: to v2f32 324 { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i8, 3 }, 325 { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i16, 3 }, 326 { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i64, 2 }, 327 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i8, 3 }, 328 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i16, 3 }, 329 { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, 2 }, 330 331 // Complex: to v4f32 332 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i8, 4 }, 333 { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i16, 2 }, 334 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i8, 3 }, 335 { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i16, 2 }, 336 337 // Complex: to v2f64 338 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i8, 4 }, 339 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i16, 4 }, 340 { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i32, 2 }, 341 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i8, 4 }, 342 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i16, 4 }, 343 { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 2 }, 344 345 346 // LowerVectorFP_TO_INT 347 { ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f32, 1 }, 348 { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 1 }, 349 { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, 1 }, 350 { ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f32, 1 }, 351 { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 1 }, 352 { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, 1 }, 353 354 // Complex, from v2f32: legal type is v2i32 (no cost) or v2i64 (1 ext). 355 { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f32, 2 }, 356 { ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f32, 1 }, 357 { ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f32, 1 }, 358 { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f32, 2 }, 359 { ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f32, 1 }, 360 { ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f32, 1 }, 361 362 // Complex, from v4f32: legal type is v4i16, 1 narrowing => ~2 363 { ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f32, 2 }, 364 { ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f32, 2 }, 365 { ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f32, 2 }, 366 { ISD::FP_TO_UINT, MVT::v4i8, MVT::v4f32, 2 }, 367 368 // Complex, from v2f64: legal type is v2i32, 1 narrowing => ~2. 369 { ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f64, 2 }, 370 { ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f64, 2 }, 371 { ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f64, 2 }, 372 { ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f64, 2 }, 373 { ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f64, 2 }, 374 { ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f64, 2 }, 375 }; 376 377 int Idx = ConvertCostTableLookup<MVT>( 378 ConversionTbl, array_lengthof(ConversionTbl), ISD, DstTy.getSimpleVT(), 379 SrcTy.getSimpleVT()); 380 if (Idx != -1) 381 return ConversionTbl[Idx].Cost; 382 383 return TargetTransformInfo::getCastInstrCost(Opcode, Dst, Src); 384 } 385 386 unsigned AArch64TTI::getVectorInstrCost(unsigned Opcode, Type *Val, 387 unsigned Index) const { 388 assert(Val->isVectorTy() && "This must be a vector type"); 389 390 if (Index != -1U) { 391 // Legalize the type. 392 std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(Val); 393 394 // This type is legalized to a scalar type. 395 if (!LT.second.isVector()) 396 return 0; 397 398 // The type may be split. Normalize the index to the new type. 399 unsigned Width = LT.second.getVectorNumElements(); 400 Index = Index % Width; 401 402 // The element at index zero is already inside the vector. 403 if (Index == 0) 404 return 0; 405 } 406 407 // All other insert/extracts cost this much. 408 return 2; 409 } 410 411 unsigned AArch64TTI::getArithmeticInstrCost( 412 unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, 413 OperandValueKind Opd2Info, OperandValueProperties Opd1PropInfo, 414 OperandValueProperties Opd2PropInfo) const { 415 // Legalize the type. 416 std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(Ty); 417 418 int ISD = TLI->InstructionOpcodeToISD(Opcode); 419 420 if (ISD == ISD::SDIV && 421 Opd2Info == TargetTransformInfo::OK_UniformConstantValue && 422 Opd2PropInfo == TargetTransformInfo::OP_PowerOf2) { 423 // On AArch64, scalar signed division by constants power-of-two are 424 // normally expanded to the sequence ADD + CMP + SELECT + SRA. 425 // The OperandValue properties many not be same as that of previous 426 // operation; conservatively assume OP_None. 427 unsigned Cost = 428 getArithmeticInstrCost(Instruction::Add, Ty, Opd1Info, Opd2Info, 429 TargetTransformInfo::OP_None, 430 TargetTransformInfo::OP_None); 431 Cost += getArithmeticInstrCost(Instruction::Sub, Ty, Opd1Info, Opd2Info, 432 TargetTransformInfo::OP_None, 433 TargetTransformInfo::OP_None); 434 Cost += getArithmeticInstrCost(Instruction::Select, Ty, Opd1Info, Opd2Info, 435 TargetTransformInfo::OP_None, 436 TargetTransformInfo::OP_None); 437 Cost += getArithmeticInstrCost(Instruction::AShr, Ty, Opd1Info, Opd2Info, 438 TargetTransformInfo::OP_None, 439 TargetTransformInfo::OP_None); 440 return Cost; 441 } 442 443 switch (ISD) { 444 default: 445 return TargetTransformInfo::getArithmeticInstrCost( 446 Opcode, Ty, Opd1Info, Opd2Info, Opd1PropInfo, Opd2PropInfo); 447 case ISD::ADD: 448 case ISD::MUL: 449 case ISD::XOR: 450 case ISD::OR: 451 case ISD::AND: 452 // These nodes are marked as 'custom' for combining purposes only. 453 // We know that they are legal. See LowerAdd in ISelLowering. 454 return 1 * LT.first; 455 } 456 } 457 458 unsigned AArch64TTI::getAddressComputationCost(Type *Ty, bool IsComplex) const { 459 // Address computations in vectorized code with non-consecutive addresses will 460 // likely result in more instructions compared to scalar code where the 461 // computation can more often be merged into the index mode. The resulting 462 // extra micro-ops can significantly decrease throughput. 463 unsigned NumVectorInstToHideOverhead = 10; 464 465 if (Ty->isVectorTy() && IsComplex) 466 return NumVectorInstToHideOverhead; 467 468 // In many cases the address computation is not merged into the instruction 469 // addressing mode. 470 return 1; 471 } 472 473 unsigned AArch64TTI::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, 474 Type *CondTy) const { 475 476 int ISD = TLI->InstructionOpcodeToISD(Opcode); 477 // We don't lower vector selects well that are wider than the register width. 478 if (ValTy->isVectorTy() && ISD == ISD::SELECT) { 479 // We would need this many instructions to hide the scalarization happening. 480 unsigned AmortizationCost = 20; 481 static const TypeConversionCostTblEntry<MVT::SimpleValueType> 482 VectorSelectTbl[] = { 483 { ISD::SELECT, MVT::v16i1, MVT::v16i16, 16 * AmortizationCost }, 484 { ISD::SELECT, MVT::v8i1, MVT::v8i32, 8 * AmortizationCost }, 485 { ISD::SELECT, MVT::v16i1, MVT::v16i32, 16 * AmortizationCost }, 486 { ISD::SELECT, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost }, 487 { ISD::SELECT, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost }, 488 { ISD::SELECT, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost } 489 }; 490 491 EVT SelCondTy = TLI->getValueType(CondTy); 492 EVT SelValTy = TLI->getValueType(ValTy); 493 if (SelCondTy.isSimple() && SelValTy.isSimple()) { 494 int Idx = 495 ConvertCostTableLookup(VectorSelectTbl, ISD, SelCondTy.getSimpleVT(), 496 SelValTy.getSimpleVT()); 497 if (Idx != -1) 498 return VectorSelectTbl[Idx].Cost; 499 } 500 } 501 return TargetTransformInfo::getCmpSelInstrCost(Opcode, ValTy, CondTy); 502 } 503 504 unsigned AArch64TTI::getMemoryOpCost(unsigned Opcode, Type *Src, 505 unsigned Alignment, 506 unsigned AddressSpace) const { 507 std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(Src); 508 509 if (Opcode == Instruction::Store && Src->isVectorTy() && Alignment != 16 && 510 Src->getVectorElementType()->isIntegerTy(64)) { 511 // Unaligned stores are extremely inefficient. We don't split 512 // unaligned v2i64 stores because the negative impact that has shown in 513 // practice on inlined memcpy code. 514 // We make v2i64 stores expensive so that we will only vectorize if there 515 // are 6 other instructions getting vectorized. 516 unsigned AmortizationCost = 6; 517 518 return LT.first * 2 * AmortizationCost; 519 } 520 521 if (Src->isVectorTy() && Src->getVectorElementType()->isIntegerTy(8) && 522 Src->getVectorNumElements() < 8) { 523 // We scalarize the loads/stores because there is not v.4b register and we 524 // have to promote the elements to v.4h. 525 unsigned NumVecElts = Src->getVectorNumElements(); 526 unsigned NumVectorizableInstsToAmortize = NumVecElts * 2; 527 // We generate 2 instructions per vector element. 528 return NumVectorizableInstsToAmortize * NumVecElts * 2; 529 } 530 531 return LT.first; 532 } 533 534 unsigned AArch64TTI::getCostOfKeepingLiveOverCall(ArrayRef<Type*> Tys) const { 535 unsigned Cost = 0; 536 for (auto *I : Tys) { 537 if (!I->isVectorTy()) 538 continue; 539 if (I->getScalarSizeInBits() * I->getVectorNumElements() == 128) 540 Cost += getMemoryOpCost(Instruction::Store, I, 128, 0) + 541 getMemoryOpCost(Instruction::Load, I, 128, 0); 542 } 543 return Cost; 544 } 545 546 unsigned AArch64TTI::getMaxInterleaveFactor() const { 547 if (ST->isCortexA57()) 548 return 4; 549 return 2; 550 } 551 552 void AArch64TTI::getUnrollingPreferences(const Function *F, Loop *L, 553 UnrollingPreferences &UP) const { 554 // Disable partial & runtime unrolling on -Os. 555 UP.PartialOptSizeThreshold = 0; 556 } 557