brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.4 KiB · 3f84cbb Raw
457 lines · cpp
1//===- HexagonTargetTransformInfo.cpp - Hexagon specific TTI pass ---------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7/// \file8/// This file implements a TargetTransformInfo analysis pass specific to the9/// Hexagon target machine. It uses the target's detailed information to provide10/// more precise answers to certain TTI queries, while letting the target11/// independent and default TTI implementations handle the rest.12///13//===----------------------------------------------------------------------===//14 15#include "HexagonTargetTransformInfo.h"16#include "HexagonSubtarget.h"17#include "llvm/Analysis/TargetTransformInfo.h"18#include "llvm/CodeGen/ValueTypes.h"19#include "llvm/IR/InstrTypes.h"20#include "llvm/IR/Instructions.h"21#include "llvm/IR/User.h"22#include "llvm/Support/Casting.h"23#include "llvm/Support/CommandLine.h"24#include "llvm/Transforms/Utils/LoopPeel.h"25#include "llvm/Transforms/Utils/UnrollLoop.h"26 27using namespace llvm;28 29#define DEBUG_TYPE "hexagontti"30 31static cl::opt<bool> HexagonAutoHVX("hexagon-autohvx", cl::init(false),32    cl::Hidden, cl::desc("Enable loop vectorizer for HVX"));33 34cl::opt<bool> HexagonAllowScatterGatherHVX(35    "hexagon-allow-scatter-gather-hvx", cl::init(false), cl::Hidden,36    cl::desc("Allow auto-generation of HVX scatter-gather"));37 38static cl::opt<bool> EnableV68FloatAutoHVX(39    "force-hvx-float", cl::Hidden,40    cl::desc("Enable auto-vectorization of floatint point types on v68."));41 42static cl::opt<bool> EmitLookupTables("hexagon-emit-lookup-tables",43    cl::init(true), cl::Hidden,44    cl::desc("Control lookup table emission on Hexagon target"));45 46static cl::opt<bool> HexagonMaskedVMem("hexagon-masked-vmem", cl::init(true),47    cl::Hidden, cl::desc("Enable masked loads/stores for HVX"));48 49// Constant "cost factor" to make floating point operations more expensive50// in terms of vectorization cost. This isn't the best way, but it should51// do. Ultimately, the cost should use cycles.52static const unsigned FloatFactor = 4;53 54bool HexagonTTIImpl::useHVX() const {55  return ST.useHVXOps() && HexagonAutoHVX;56}57 58bool HexagonTTIImpl::isHVXVectorType(Type *Ty) const {59  auto *VecTy = dyn_cast<VectorType>(Ty);60  if (!VecTy)61    return false;62  if (!ST.isTypeForHVX(VecTy))63    return false;64  if (ST.useHVXV69Ops() || !VecTy->getElementType()->isFloatingPointTy())65    return true;66  return ST.useHVXV68Ops() && EnableV68FloatAutoHVX;67}68 69unsigned HexagonTTIImpl::getTypeNumElements(Type *Ty) const {70  if (auto *VTy = dyn_cast<FixedVectorType>(Ty))71    return VTy->getNumElements();72  assert((Ty->isIntegerTy() || Ty->isFloatingPointTy()) &&73         "Expecting scalar type");74  return 1;75}76 77TargetTransformInfo::PopcntSupportKind78HexagonTTIImpl::getPopcntSupport(unsigned IntTyWidthInBit) const {79  // Return fast hardware support as every input < 64 bits will be promoted80  // to 64 bits.81  return TargetTransformInfo::PSK_FastHardware;82}83 84// The Hexagon target can unroll loops with run-time trip counts.85void HexagonTTIImpl::getUnrollingPreferences(86    Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP,87    OptimizationRemarkEmitter *ORE) const {88  UP.Runtime = UP.Partial = true;89}90 91void HexagonTTIImpl::getPeelingPreferences(Loop *L, ScalarEvolution &SE,92                                           TTI::PeelingPreferences &PP) const {93  BaseT::getPeelingPreferences(L, SE, PP);94  // Only try to peel innermost loops with small runtime trip counts.95  if (L && L->isInnermost() && canPeel(L) &&96      SE.getSmallConstantTripCount(L) == 0 &&97      SE.getSmallConstantMaxTripCount(L) > 0 &&98      SE.getSmallConstantMaxTripCount(L) <= 5) {99    PP.PeelCount = 2;100  }101}102 103TTI::AddressingModeKind104HexagonTTIImpl::getPreferredAddressingMode(const Loop *L,105                                           ScalarEvolution *SE) const {106  return TTI::AMK_PostIndexed;107}108 109/// --- Vector TTI begin ---110 111unsigned HexagonTTIImpl::getNumberOfRegisters(unsigned ClassID) const {112  bool Vector = ClassID == 1;113  if (Vector)114    return useHVX() ? 32 : 0;115  return 32;116}117 118unsigned HexagonTTIImpl::getMaxInterleaveFactor(ElementCount VF) const {119  return useHVX() ? 2 : 1;120}121 122TypeSize123HexagonTTIImpl::getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const {124  switch (K) {125  case TargetTransformInfo::RGK_Scalar:126    return TypeSize::getFixed(32);127  case TargetTransformInfo::RGK_FixedWidthVector:128    return TypeSize::getFixed(getMinVectorRegisterBitWidth());129  case TargetTransformInfo::RGK_ScalableVector:130    return TypeSize::getScalable(0);131  }132 133  llvm_unreachable("Unsupported register kind");134}135 136unsigned HexagonTTIImpl::getMinVectorRegisterBitWidth() const {137  return useHVX() ? ST.getVectorLength()*8 : 32;138}139 140ElementCount HexagonTTIImpl::getMinimumVF(unsigned ElemWidth,141                                          bool IsScalable) const {142  assert(!IsScalable && "Scalable VFs are not supported for Hexagon");143  return ElementCount::getFixed((8 * ST.getVectorLength()) / ElemWidth);144}145 146InstructionCost147HexagonTTIImpl::getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys,148                                 TTI::TargetCostKind CostKind) const {149  return BaseT::getCallInstrCost(F, RetTy, Tys, CostKind);150}151 152InstructionCost153HexagonTTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,154                                      TTI::TargetCostKind CostKind) const {155  if (ICA.getID() == Intrinsic::bswap) {156    std::pair<InstructionCost, MVT> LT =157        getTypeLegalizationCost(ICA.getReturnType());158    return LT.first + 2;159  }160  return BaseT::getIntrinsicInstrCost(ICA, CostKind);161}162 163InstructionCost164HexagonTTIImpl::getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE,165                                          const SCEV *S,166                                          TTI::TargetCostKind CostKind) const {167  return 0;168}169 170InstructionCost HexagonTTIImpl::getMemoryOpCost(unsigned Opcode, Type *Src,171                                                Align Alignment,172                                                unsigned AddressSpace,173                                                TTI::TargetCostKind CostKind,174                                                TTI::OperandValueInfo OpInfo,175                                                const Instruction *I) const {176  assert(Opcode == Instruction::Load || Opcode == Instruction::Store);177  // TODO: Handle other cost kinds.178  if (CostKind != TTI::TCK_RecipThroughput)179    return 1;180 181  if (Opcode == Instruction::Store)182    return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,183                                  CostKind, OpInfo, I);184 185  if (Src->isVectorTy()) {186    VectorType *VecTy = cast<VectorType>(Src);187    unsigned VecWidth = VecTy->getPrimitiveSizeInBits().getFixedValue();188    if (isHVXVectorType(VecTy)) {189      unsigned RegWidth =190          getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector)191              .getFixedValue();192      assert(RegWidth && "Non-zero vector register width expected");193      // Cost of HVX loads.194      if (VecWidth % RegWidth == 0)195        return VecWidth / RegWidth;196      // Cost of constructing HVX vector from scalar loads197      const Align RegAlign(RegWidth / 8);198      if (Alignment > RegAlign)199        Alignment = RegAlign;200      unsigned AlignWidth = 8 * Alignment.value();201      unsigned NumLoads = alignTo(VecWidth, AlignWidth) / AlignWidth;202      return 3 * NumLoads;203    }204 205    // Non-HVX vectors.206    // Add extra cost for floating point types.207    unsigned Cost =208        VecTy->getElementType()->isFloatingPointTy() ? FloatFactor : 1;209 210    // At this point unspecified alignment is considered as Align(1).211    const Align BoundAlignment = std::min(Alignment, Align(8));212    unsigned AlignWidth = 8 * BoundAlignment.value();213    unsigned NumLoads = alignTo(VecWidth, AlignWidth) / AlignWidth;214    if (Alignment == Align(4) || Alignment == Align(8))215      return Cost * NumLoads;216    // Loads of less than 32 bits will need extra inserts to compose a vector.217    assert(BoundAlignment <= Align(8));218    unsigned LogA = Log2(BoundAlignment);219    return (3 - LogA) * Cost * NumLoads;220  }221 222  return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace, CostKind,223                                OpInfo, I);224}225 226InstructionCost227HexagonTTIImpl::getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA,228                                      TTI::TargetCostKind CostKind) const {229  return BaseT::getMaskedMemoryOpCost(MICA, CostKind);230}231 232InstructionCost233HexagonTTIImpl::getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy,234                               VectorType *SrcTy, ArrayRef<int> Mask,235                               TTI::TargetCostKind CostKind, int Index,236                               VectorType *SubTp, ArrayRef<const Value *> Args,237                               const Instruction *CxtI) const {238  return 1;239}240 241InstructionCost HexagonTTIImpl::getGatherScatterOpCost(242    unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask,243    Align Alignment, TTI::TargetCostKind CostKind, const Instruction *I) const {244  return BaseT::getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask,245                                       Alignment, CostKind, I);246}247 248InstructionCost HexagonTTIImpl::getInterleavedMemoryOpCost(249    unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,250    Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,251    bool UseMaskForCond, bool UseMaskForGaps) const {252  if (Indices.size() != Factor || UseMaskForCond || UseMaskForGaps)253    return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,254                                             Alignment, AddressSpace,255                                             CostKind,256                                             UseMaskForCond, UseMaskForGaps);257  return getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace, CostKind);258}259 260InstructionCost HexagonTTIImpl::getCmpSelInstrCost(261    unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,262    TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info,263    TTI::OperandValueInfo Op2Info, const Instruction *I) const {264  if (ValTy->isVectorTy() && CostKind == TTI::TCK_RecipThroughput) {265    if (!isHVXVectorType(ValTy) && ValTy->isFPOrFPVectorTy())266      return InstructionCost::getMax();267    std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);268    if (Opcode == Instruction::FCmp)269      return LT.first + FloatFactor * getTypeNumElements(ValTy);270  }271  return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,272                                   Op1Info, Op2Info, I);273}274 275InstructionCost HexagonTTIImpl::getArithmeticInstrCost(276    unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,277    TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info,278    ArrayRef<const Value *> Args, const Instruction *CxtI) const {279  // TODO: Handle more cost kinds.280  if (CostKind != TTI::TCK_RecipThroughput)281    return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,282                                         Op2Info, Args, CxtI);283 284  if (Ty->isVectorTy()) {285    if (!isHVXVectorType(Ty) && Ty->isFPOrFPVectorTy())286      return InstructionCost::getMax();287    std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);288    if (LT.second.isFloatingPoint())289      return LT.first + FloatFactor * getTypeNumElements(Ty);290  }291  return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info,292                                       Args, CxtI);293}294 295InstructionCost HexagonTTIImpl::getCastInstrCost(unsigned Opcode, Type *DstTy,296                                                 Type *SrcTy,297                                                 TTI::CastContextHint CCH,298                                                 TTI::TargetCostKind CostKind,299                                                 const Instruction *I) const {300  auto isNonHVXFP = [this] (Type *Ty) {301    return Ty->isVectorTy() && !isHVXVectorType(Ty) && Ty->isFPOrFPVectorTy();302  };303  if (isNonHVXFP(SrcTy) || isNonHVXFP(DstTy))304    return InstructionCost::getMax();305 306  if (SrcTy->isFPOrFPVectorTy() || DstTy->isFPOrFPVectorTy()) {307    unsigned SrcN = SrcTy->isFPOrFPVectorTy() ? getTypeNumElements(SrcTy) : 0;308    unsigned DstN = DstTy->isFPOrFPVectorTy() ? getTypeNumElements(DstTy) : 0;309 310    std::pair<InstructionCost, MVT> SrcLT = getTypeLegalizationCost(SrcTy);311    std::pair<InstructionCost, MVT> DstLT = getTypeLegalizationCost(DstTy);312    InstructionCost Cost =313        std::max(SrcLT.first, DstLT.first) + FloatFactor * (SrcN + DstN);314    // TODO: Allow non-throughput costs that aren't binary.315    if (CostKind != TTI::TCK_RecipThroughput)316      return Cost == 0 ? 0 : 1;317    return Cost;318  }319  return 1;320}321 322InstructionCost HexagonTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val,323                                                   TTI::TargetCostKind CostKind,324                                                   unsigned Index,325                                                   const Value *Op0,326                                                   const Value *Op1) const {327  Type *ElemTy = Val->isVectorTy() ? cast<VectorType>(Val)->getElementType()328                                   : Val;329  if (Opcode == Instruction::InsertElement) {330    // Need two rotations for non-zero index.331    unsigned Cost = (Index != 0) ? 2 : 0;332    if (ElemTy->isIntegerTy(32))333      return Cost;334    // If it's not a 32-bit value, there will need to be an extract.335    return Cost + getVectorInstrCost(Instruction::ExtractElement, Val, CostKind,336                                     Index, Op0, Op1);337  }338 339  if (Opcode == Instruction::ExtractElement)340    return 2;341 342  return 1;343}344 345bool HexagonTTIImpl::isLegalMaskedStore(Type *DataType, Align /*Alignment*/,346                                        unsigned /*AddressSpace*/,347                                        TTI::MaskKind /*MaskKind*/) const {348  // This function is called from scalarize-masked-mem-intrin, which runs349  // in pre-isel. Use ST directly instead of calling isHVXVectorType.350  return HexagonMaskedVMem && ST.isTypeForHVX(DataType);351}352 353bool HexagonTTIImpl::isLegalMaskedLoad(Type *DataType, Align /*Alignment*/,354                                       unsigned /*AddressSpace*/,355                                       TTI::MaskKind /*MaskKind*/) const {356  // This function is called from scalarize-masked-mem-intrin, which runs357  // in pre-isel. Use ST directly instead of calling isHVXVectorType.358  return HexagonMaskedVMem && ST.isTypeForHVX(DataType);359}360 361bool HexagonTTIImpl::isLegalMaskedGather(Type *Ty, Align Alignment) const {362  // For now assume we can not deal with all HVX datatypes.363  if (!Ty->isVectorTy() || !ST.isTypeForHVX(Ty) ||364      !HexagonAllowScatterGatherHVX)365    return false;366  // This must be in sync with HexagonVectorCombine pass.367  switch (Ty->getScalarSizeInBits()) {368  case 8:369    return (getTypeNumElements(Ty) == 128);370  case 16:371    if (getTypeNumElements(Ty) == 64 || getTypeNumElements(Ty) == 32)372      return (Alignment >= 2);373    break;374  case 32:375    if (getTypeNumElements(Ty) == 32)376      return (Alignment >= 4);377    break;378  default:379    break;380  }381  return false;382}383 384bool HexagonTTIImpl::isLegalMaskedScatter(Type *Ty, Align Alignment) const {385  if (!Ty->isVectorTy() || !ST.isTypeForHVX(Ty) ||386      !HexagonAllowScatterGatherHVX)387    return false;388  // This must be in sync with HexagonVectorCombine pass.389  switch (Ty->getScalarSizeInBits()) {390  case 8:391    return (getTypeNumElements(Ty) == 128);392  case 16:393    if (getTypeNumElements(Ty) == 64)394      return (Alignment >= 2);395    break;396  case 32:397    if (getTypeNumElements(Ty) == 32)398      return (Alignment >= 4);399    break;400  default:401    break;402  }403  return false;404}405 406bool HexagonTTIImpl::forceScalarizeMaskedGather(VectorType *VTy,407                                                Align Alignment) const {408  return !isLegalMaskedGather(VTy, Alignment);409}410 411bool HexagonTTIImpl::forceScalarizeMaskedScatter(VectorType *VTy,412                                                 Align Alignment) const {413  return !isLegalMaskedScatter(VTy, Alignment);414}415 416/// --- Vector TTI end ---417 418unsigned HexagonTTIImpl::getPrefetchDistance() const {419  return ST.getL1PrefetchDistance();420}421 422unsigned HexagonTTIImpl::getCacheLineSize() const {423  return ST.getL1CacheLineSize();424}425 426InstructionCost427HexagonTTIImpl::getInstructionCost(const User *U,428                                   ArrayRef<const Value *> Operands,429                                   TTI::TargetCostKind CostKind) const {430  auto isCastFoldedIntoLoad = [this](const CastInst *CI) -> bool {431    if (!CI->isIntegerCast())432      return false;433    // Only extensions from an integer type shorter than 32-bit to i32434    // can be folded into the load.435    const DataLayout &DL = getDataLayout();436    unsigned SBW = DL.getTypeSizeInBits(CI->getSrcTy());437    unsigned DBW = DL.getTypeSizeInBits(CI->getDestTy());438    if (DBW != 32 || SBW >= DBW)439      return false;440 441    const LoadInst *LI = dyn_cast<const LoadInst>(CI->getOperand(0));442    // Technically, this code could allow multiple uses of the load, and443    // check if all the uses are the same extension operation, but this444    // should be sufficient for most cases.445    return LI && LI->hasOneUse();446  };447 448  if (const CastInst *CI = dyn_cast<const CastInst>(U))449    if (isCastFoldedIntoLoad(CI))450      return TargetTransformInfo::TCC_Free;451  return BaseT::getInstructionCost(U, Operands, CostKind);452}453 454bool HexagonTTIImpl::shouldBuildLookupTables() const {455  return EmitLookupTables;456}457