brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.6 KiB · d2ec7dd Raw
221 lines · cpp
1//===-- AMDGPURemoveIncompatibleFunctions.cpp -----------------------------===//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//9/// \file10/// This pass replaces all uses of functions that use GPU features11/// incompatible with the current GPU with null then deletes the function.12//13//===----------------------------------------------------------------------===//14 15#include "AMDGPURemoveIncompatibleFunctions.h"16#include "AMDGPU.h"17#include "GCNSubtarget.h"18#include "llvm/Analysis/OptimizationRemarkEmitter.h"19#include "llvm/IR/Function.h"20#include "llvm/IR/Module.h"21#include "llvm/Pass.h"22#include "llvm/Target/TargetMachine.h"23 24#define DEBUG_TYPE "amdgpu-remove-incompatible-functions"25 26using namespace llvm;27 28namespace llvm {29extern const SubtargetFeatureKV30    AMDGPUFeatureKV[AMDGPU::NumSubtargetFeatures - 1];31} // namespace llvm32 33namespace {34 35using Generation = AMDGPUSubtarget::Generation;36 37class AMDGPURemoveIncompatibleFunctions {38public:39  AMDGPURemoveIncompatibleFunctions(const TargetMachine *TM = nullptr)40      : TM(TM) {41    assert(TM && "No TargetMachine!");42  }43  /// Checks a single function, returns true if the function must be deleted.44  bool checkFunction(Function &F);45 46  bool run(Module &M) {47    assert(TM->getTargetTriple().isAMDGCN());48 49    SmallVector<Function *, 4> FnsToDelete;50    for (Function &F : M) {51      if (checkFunction(F))52        FnsToDelete.push_back(&F);53    }54 55    for (Function *F : FnsToDelete) {56      F->replaceAllUsesWith(ConstantPointerNull::get(F->getType()));57      F->eraseFromParent();58    }59    return !FnsToDelete.empty();60  }61 62private:63  const TargetMachine *TM = nullptr;64};65 66class AMDGPURemoveIncompatibleFunctionsLegacy : public ModulePass {67public:68  static char ID;69 70  AMDGPURemoveIncompatibleFunctionsLegacy(const TargetMachine *TM)71      : ModulePass(ID), TM(TM) {}72 73  bool runOnModule(Module &M) override {74    AMDGPURemoveIncompatibleFunctions Pass(TM);75    return Pass.run(M);76  }77 78  StringRef getPassName() const override {79    return "AMDGPU Remove Incompatible Functions";80  }81 82  void getAnalysisUsage(AnalysisUsage &AU) const override {}83 84private:85  const TargetMachine *TM = nullptr;86};87 88StringRef getFeatureName(unsigned Feature) {89  for (const SubtargetFeatureKV &KV : AMDGPUFeatureKV)90    if (Feature == KV.Value)91      return KV.Key;92 93  llvm_unreachable("Unknown Target feature");94}95 96const SubtargetSubTypeKV *getGPUInfo(const GCNSubtarget &ST,97                                     StringRef GPUName) {98  for (const SubtargetSubTypeKV &KV : ST.getAllProcessorDescriptions())99    if (StringRef(KV.Key) == GPUName)100      return &KV;101 102  return nullptr;103}104 105constexpr unsigned FeaturesToCheck[] = {AMDGPU::FeatureGFX11Insts,106                                        AMDGPU::FeatureGFX10Insts,107                                        AMDGPU::FeatureGFX9Insts,108                                        AMDGPU::FeatureGFX8Insts,109                                        AMDGPU::FeatureDPP,110                                        AMDGPU::Feature16BitInsts,111                                        AMDGPU::FeatureDot1Insts,112                                        AMDGPU::FeatureDot2Insts,113                                        AMDGPU::FeatureDot3Insts,114                                        AMDGPU::FeatureDot4Insts,115                                        AMDGPU::FeatureDot5Insts,116                                        AMDGPU::FeatureDot6Insts,117                                        AMDGPU::FeatureDot7Insts,118                                        AMDGPU::FeatureDot8Insts,119                                        AMDGPU::FeatureExtendedImageInsts,120                                        AMDGPU::FeatureSMemRealTime,121                                        AMDGPU::FeatureSMemTimeInst,122                                        AMDGPU::FeatureGWS};123 124FeatureBitset expandImpliedFeatures(const FeatureBitset &Features) {125  FeatureBitset Result = Features;126  for (const SubtargetFeatureKV &FE : AMDGPUFeatureKV) {127    if (Features.test(FE.Value) && FE.Implies.any())128      Result |= expandImpliedFeatures(FE.Implies.getAsBitset());129  }130  return Result;131}132 133void reportFunctionRemoved(Function &F, unsigned Feature) {134  OptimizationRemarkEmitter ORE(&F);135  ORE.emit([&]() {136    // Note: we print the function name as part of the diagnostic because if137    // debug info is not present, users get "<unknown>:0:0" as the debug138    // loc. If we didn't print the function name there would be no way to139    // tell which function got removed.140    return OptimizationRemark(DEBUG_TYPE, "AMDGPUIncompatibleFnRemoved", &F)141           << "removing function '" << F.getName() << "': +"142           << getFeatureName(Feature)143           << " is not supported on the current target";144  });145}146} // end anonymous namespace147 148PreservedAnalyses149AMDGPURemoveIncompatibleFunctionsPass::run(Module &M,150                                           ModuleAnalysisManager &MAM) {151  AMDGPURemoveIncompatibleFunctions Impl(TM);152  if (Impl.run(M))153    return PreservedAnalyses::none();154  return PreservedAnalyses::all();155}156 157bool AMDGPURemoveIncompatibleFunctions::checkFunction(Function &F) {158  if (F.isDeclaration())159    return false;160 161  const GCNSubtarget *ST =162      static_cast<const GCNSubtarget *>(TM->getSubtargetImpl(F));163 164  // Check the GPU isn't generic or generic-hsa. Generic is used for testing165  // only and we don't want this pass to interfere with it.166  StringRef GPUName = ST->getCPU();167  if (GPUName.empty() || GPUName.starts_with("generic"))168    return false;169 170  // Try to fetch the GPU's info. If we can't, it's likely an unknown processor171  // so just bail out.172  const SubtargetSubTypeKV *GPUInfo = getGPUInfo(*ST, GPUName);173  if (!GPUInfo)174    return false;175 176  // Get all the features implied by the current GPU, and recursively expand177  // the features that imply other features.178  //179  // e.g. GFX90A implies FeatureGFX9, and FeatureGFX9 implies a whole set of180  // other features.181  const FeatureBitset GPUFeatureBits =182      expandImpliedFeatures(GPUInfo->Implies.getAsBitset());183 184  // Now that the have a FeatureBitset containing all possible features for185  // the chosen GPU, check our list of "suspicious" features.186 187  // Check that the user didn't enable any features that aren't part of that188  // GPU's feature set. We only check a predetermined set of features.189  for (unsigned Feature : FeaturesToCheck) {190    if (ST->hasFeature(Feature) && !GPUFeatureBits.test(Feature)) {191      reportFunctionRemoved(F, Feature);192      return true;193    }194  }195 196  // Delete FeatureWavefrontSize32 functions for197  // gfx9 and below targets that don't support the mode.198  // gfx10, gfx11, gfx12 are implied to support both wave32 and 64 features.199  // They are not in the feature set. So, we need a separate check200  if (!ST->supportsWave32() && ST->hasFeature(AMDGPU::FeatureWavefrontSize32)) {201    reportFunctionRemoved(F, AMDGPU::FeatureWavefrontSize32);202    return true;203  }204  // gfx125x only support FeatureWavefrontSize32.205  if (!ST->supportsWave64() && ST->hasFeature(AMDGPU::FeatureWavefrontSize64)) {206    reportFunctionRemoved(F, AMDGPU::FeatureWavefrontSize64);207    return true;208  }209  return false;210}211 212INITIALIZE_PASS(AMDGPURemoveIncompatibleFunctionsLegacy, DEBUG_TYPE,213                "AMDGPU Remove Incompatible Functions", false, false)214 215char AMDGPURemoveIncompatibleFunctionsLegacy::ID = 0;216 217ModulePass *218llvm::createAMDGPURemoveIncompatibleFunctionsPass(const TargetMachine *TM) {219  return new AMDGPURemoveIncompatibleFunctionsLegacy(TM);220}221