209 lines · c
1//===-- NVPTXTargetTransformInfo.h - NVPTX specific TTI ---------*- C++ -*-===//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//===----------------------------------------------------------------------===//8/// \file9/// This file a TargetTransformInfoImplBase conforming object specific to the10/// NVPTX target machine. It uses the target's detailed information to11/// provide more precise answers to certain TTI queries, while letting the12/// target independent and default TTI implementations handle the rest.13///14//===----------------------------------------------------------------------===//15 16#ifndef LLVM_LIB_TARGET_NVPTX_NVPTXTARGETTRANSFORMINFO_H17#define LLVM_LIB_TARGET_NVPTX_NVPTXTARGETTRANSFORMINFO_H18 19#include "MCTargetDesc/NVPTXBaseInfo.h"20#include "NVPTXTargetMachine.h"21#include "NVPTXUtilities.h"22#include "llvm/Analysis/TargetTransformInfo.h"23#include "llvm/CodeGen/BasicTTIImpl.h"24#include "llvm/CodeGen/TargetLowering.h"25#include <optional>26 27namespace llvm {28 29class NVPTXTTIImpl final : public BasicTTIImplBase<NVPTXTTIImpl> {30 typedef BasicTTIImplBase<NVPTXTTIImpl> BaseT;31 typedef TargetTransformInfo TTI;32 friend BaseT;33 34 const NVPTXSubtarget *ST;35 const NVPTXTargetLowering *TLI;36 37 const NVPTXSubtarget *getST() const { return ST; };38 const NVPTXTargetLowering *getTLI() const { return TLI; };39 40public:41 explicit NVPTXTTIImpl(const NVPTXTargetMachine *TM, const Function &F)42 : BaseT(TM, F.getDataLayout()), ST(TM->getSubtargetImpl()),43 TLI(ST->getTargetLowering()) {}44 45 bool hasBranchDivergence(const Function *F = nullptr) const override {46 return true;47 }48 49 bool isSourceOfDivergence(const Value *V) const override;50 51 unsigned getFlatAddressSpace() const override {52 return AddressSpace::ADDRESS_SPACE_GENERIC;53 }54 55 bool56 canHaveNonUndefGlobalInitializerInAddressSpace(unsigned AS) const override {57 return AS != AddressSpace::ADDRESS_SPACE_SHARED &&58 AS != AddressSpace::ADDRESS_SPACE_LOCAL && AS != ADDRESS_SPACE_PARAM;59 }60 61 std::optional<Instruction *>62 instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override;63 64 // Loads and stores can be vectorized if the alignment is at least as big as65 // the load/store we want to vectorize.66 bool isLegalToVectorizeLoadChain(unsigned ChainSizeInBytes, Align Alignment,67 unsigned AddrSpace) const override {68 return Alignment >= ChainSizeInBytes;69 }70 bool isLegalToVectorizeStoreChain(unsigned ChainSizeInBytes, Align Alignment,71 unsigned AddrSpace) const override {72 return isLegalToVectorizeLoadChain(ChainSizeInBytes, Alignment, AddrSpace);73 }74 75 // NVPTX has infinite registers of all kinds, but the actual machine doesn't.76 // We conservatively return 1 here which is just enough to enable the77 // vectorizers but disables heuristics based on the number of registers.78 // FIXME: Return a more reasonable number, while keeping an eye on79 // LoopVectorizer's unrolling heuristics.80 unsigned getNumberOfRegisters(unsigned ClassID) const override { return 1; }81 82 // Only <2 x half> should be vectorized, so always return 32 for the vector83 // register size.84 TypeSize85 getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override {86 return TypeSize::getFixed(32);87 }88 unsigned getMinVectorRegisterBitWidth() const override { return 32; }89 90 bool shouldExpandReduction(const IntrinsicInst *II) const override {91 // Turn off ExpandReductions pass for NVPTX, which doesn't have advanced92 // swizzling operations. Our backend/Selection DAG can expand these93 // reductions with less movs.94 return false;95 }96 97 // We don't want to prevent inlining because of target-cpu and -features98 // attributes that were added to newer versions of LLVM/Clang: There are99 // no incompatible functions in PTX, ptxas will throw errors in such cases.100 bool areInlineCompatible(const Function *Caller,101 const Function *Callee) const override {102 return true;103 }104 105 // Increase the inlining cost threshold by a factor of 11, reflecting that106 // calls are particularly expensive in NVPTX.107 unsigned getInliningThresholdMultiplier() const override { return 11; }108 109 InstructionCost110 getInstructionCost(const User *U, ArrayRef<const Value *> Operands,111 TTI::TargetCostKind CostKind) const override;112 113 InstructionCost getArithmeticInstrCost(114 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,115 TTI::OperandValueInfo Op1Info = {TTI::OK_AnyValue, TTI::OP_None},116 TTI::OperandValueInfo Op2Info = {TTI::OK_AnyValue, TTI::OP_None},117 ArrayRef<const Value *> Args = {},118 const Instruction *CxtI = nullptr) const override;119 120 InstructionCost getScalarizationOverhead(121 VectorType *InTy, const APInt &DemandedElts, bool Insert, bool Extract,122 TTI::TargetCostKind CostKind, bool ForPoisonSrc = true,123 ArrayRef<Value *> VL = {}) const override {124 if (!InTy->getElementCount().isFixed())125 return InstructionCost::getInvalid();126 127 auto VT = getTLI()->getValueType(DL, InTy);128 auto NumElements = InTy->getElementCount().getFixedValue();129 InstructionCost Cost = 0;130 if (Insert && !VL.empty()) {131 bool AllConstant = all_of(seq(NumElements), [&](int Idx) {132 return !DemandedElts[Idx] || isa<Constant>(VL[Idx]);133 });134 if (AllConstant) {135 Cost += TTI::TCC_Free;136 Insert = false;137 }138 }139 if (Insert && NVPTX::isPackedVectorTy(VT) && VT.is32BitVector()) {140 // Can be built in a single 32-bit mov (64-bit regs are emulated in SASS141 // with 2x 32-bit regs)142 Cost += 1;143 Insert = false;144 }145 if (Insert && VT == MVT::v4i8) {146 InstructionCost Cost = 3; // 3 x PRMT147 for (auto Idx : seq(NumElements))148 if (DemandedElts[Idx])149 Cost += 1; // zext operand to i32150 Insert = false;151 }152 return Cost + BaseT::getScalarizationOverhead(InTy, DemandedElts, Insert,153 Extract, CostKind,154 ForPoisonSrc, VL);155 }156 157 void getUnrollingPreferences(Loop *L, ScalarEvolution &SE,158 TTI::UnrollingPreferences &UP,159 OptimizationRemarkEmitter *ORE) const override;160 161 void getPeelingPreferences(Loop *L, ScalarEvolution &SE,162 TTI::PeelingPreferences &PP) const override;163 164 bool hasVolatileVariant(Instruction *I, unsigned AddrSpace) const override {165 // Volatile loads/stores are only supported for shared and global address166 // spaces, or for generic AS that maps to them.167 if (!(AddrSpace == llvm::ADDRESS_SPACE_GENERIC ||168 AddrSpace == llvm::ADDRESS_SPACE_GLOBAL ||169 AddrSpace == llvm::ADDRESS_SPACE_SHARED))170 return false;171 172 switch(I->getOpcode()){173 default:174 return false;175 case Instruction::Load:176 case Instruction::Store:177 return true;178 }179 }180 181 bool collectFlatAddressOperands(SmallVectorImpl<int> &OpIndexes,182 Intrinsic::ID IID) const override;183 184 bool isLegalMaskedStore(Type *DataType, Align Alignment, unsigned AddrSpace,185 TTI::MaskKind MaskKind) const override;186 187 bool isLegalMaskedLoad(Type *DataType, Align Alignment, unsigned AddrSpace,188 TTI::MaskKind MaskKind) const override;189 190 unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const override;191 192 Value *rewriteIntrinsicWithAddressSpace(IntrinsicInst *II, Value *OldV,193 Value *NewV) const override;194 unsigned getAssumedAddrSpace(const Value *V) const override;195 196 void collectKernelLaunchBounds(197 const Function &F,198 SmallVectorImpl<std::pair<StringRef, int64_t>> &LB) const override;199 200 bool shouldBuildRelLookupTables() const override {201 // Self-referential globals are not supported.202 return false;203 }204};205 206} // end namespace llvm207 208#endif209