brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · 6d8bd7d Raw
141 lines · cpp
1//===- CostModel.cpp ------ Cost Model Analysis ---------------------------===//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// This file defines the cost model analysis. It provides a very basic cost10// estimation for LLVM-IR. This analysis uses the services of the codegen11// to approximate the cost of any IR instruction when lowered to machine12// instructions. The cost results are unit-less and the cost number represents13// the throughput of the machine assuming that all loads hit the cache, all14// branches are predicted, etc. The cost numbers can be added in order to15// compare two or more transformation alternatives.16//17//===----------------------------------------------------------------------===//18 19#include "llvm/Analysis/CostModel.h"20#include "llvm/Analysis/TargetLibraryInfo.h"21#include "llvm/Analysis/TargetTransformInfo.h"22#include "llvm/IR/Function.h"23#include "llvm/IR/IntrinsicInst.h"24#include "llvm/IR/PassManager.h"25#include "llvm/Pass.h"26#include "llvm/Support/CommandLine.h"27#include "llvm/Support/raw_ostream.h"28 29using namespace llvm;30 31enum class OutputCostKind {32  RecipThroughput,33  Latency,34  CodeSize,35  SizeAndLatency,36  All,37};38 39static cl::opt<OutputCostKind> CostKind(40    "cost-kind", cl::desc("Target cost kind"),41    cl::init(OutputCostKind::RecipThroughput),42    cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput",43                          "Reciprocal throughput"),44               clEnumValN(OutputCostKind::Latency, "latency",45                          "Instruction latency"),46               clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"),47               clEnumValN(OutputCostKind::SizeAndLatency, "size-latency",48                          "Code size and latency"),49               clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")));50 51enum class IntrinsicCostStrategy {52  InstructionCost,53  IntrinsicCost,54  TypeBasedIntrinsicCost,55};56 57static cl::opt<IntrinsicCostStrategy> IntrinsicCost(58    "intrinsic-cost-strategy",59    cl::desc("Costing strategy for intrinsic instructions"),60    cl::init(IntrinsicCostStrategy::InstructionCost),61    cl::values(62        clEnumValN(IntrinsicCostStrategy::InstructionCost, "instruction-cost",63                   "Use TargetTransformInfo::getInstructionCost"),64        clEnumValN(IntrinsicCostStrategy::IntrinsicCost, "intrinsic-cost",65                   "Use TargetTransformInfo::getIntrinsicInstrCost"),66        clEnumValN(67            IntrinsicCostStrategy::TypeBasedIntrinsicCost,68            "type-based-intrinsic-cost",69            "Calculate the intrinsic cost based only on argument types")));70 71#define CM_NAME "cost-model"72#define DEBUG_TYPE CM_NAME73 74static InstructionCost getCost(Instruction &Inst, TTI::TargetCostKind CostKind,75                               TargetTransformInfo &TTI,76                               TargetLibraryInfo &TLI) {77  auto *II = dyn_cast<IntrinsicInst>(&Inst);78  if (II && IntrinsicCost != IntrinsicCostStrategy::InstructionCost) {79    IntrinsicCostAttributes ICA(80        II->getIntrinsicID(), *II, InstructionCost::getInvalid(),81        /*TypeBasedOnly=*/IntrinsicCost ==82            IntrinsicCostStrategy::TypeBasedIntrinsicCost,83        &TLI);84    return TTI.getIntrinsicInstrCost(ICA, CostKind);85  }86 87  return TTI.getInstructionCost(&Inst, CostKind);88}89 90static TTI::TargetCostKind91OutputCostKindToTargetCostKind(OutputCostKind CostKind) {92  switch (CostKind) {93  case OutputCostKind::RecipThroughput:94    return TTI::TCK_RecipThroughput;95  case OutputCostKind::Latency:96    return TTI::TCK_Latency;97  case OutputCostKind::CodeSize:98    return TTI::TCK_CodeSize;99  case OutputCostKind::SizeAndLatency:100    return TTI::TCK_SizeAndLatency;101  default:102    llvm_unreachable("Unexpected OutputCostKind!");103  };104}105 106PreservedAnalyses CostModelPrinterPass::run(Function &F,107                                            FunctionAnalysisManager &AM) {108  auto &TTI = AM.getResult<TargetIRAnalysis>(F);109  auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);110  OS << "Printing analysis 'Cost Model Analysis' for function '" << F.getName() << "':\n";111  for (BasicBlock &B : F) {112    for (Instruction &Inst : B) {113      OS << "Cost Model: ";114      if (CostKind == OutputCostKind::All) {115        OS << "Found costs of ";116        InstructionCost RThru =117            getCost(Inst, TTI::TCK_RecipThroughput, TTI, TLI);118        InstructionCost CodeSize = getCost(Inst, TTI::TCK_CodeSize, TTI, TLI);119        InstructionCost Lat = getCost(Inst, TTI::TCK_Latency, TTI, TLI);120        InstructionCost SizeLat =121            getCost(Inst, TTI::TCK_SizeAndLatency, TTI, TLI);122        if (RThru == CodeSize && RThru == Lat && RThru == SizeLat)123          OS << RThru;124        else125          OS << "RThru:" << RThru << " CodeSize:" << CodeSize << " Lat:" << Lat126             << " SizeLat:" << SizeLat;127        OS << " for: " << Inst << "\n";128      } else {129        InstructionCost Cost =130            getCost(Inst, OutputCostKindToTargetCostKind(CostKind), TTI, TLI);131        if (Cost.isValid())132          OS << "Found an estimated cost of " << Cost.getValue();133        else134          OS << "Invalid cost";135        OS << " for instruction: " << Inst << "\n";136      }137    }138  }139  return PreservedAnalyses::all();140}141