xref: /freebsd/contrib/llvm-project/llvm/lib/Analysis/CostModel.cpp (revision d54a7d337331d991e039e4f42f6b4dc64aedce08)
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-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This file defines the cost model analysis. It provides a very basic cost
10  // estimation for LLVM-IR. This analysis uses the services of the codegen
11  // to approximate the cost of any IR instruction when lowered to machine
12  // instructions. The cost results are unit-less and the cost number represents
13  // the throughput of the machine assuming that all loads hit the cache, all
14  // branches are predicted, etc. The cost numbers can be added in order to
15  // compare two or more transformation alternatives.
16  //
17  //===----------------------------------------------------------------------===//
18  
19  #include "llvm/Analysis/CostModel.h"
20  #include "llvm/Analysis/Passes.h"
21  #include "llvm/Analysis/TargetTransformInfo.h"
22  #include "llvm/IR/Function.h"
23  #include "llvm/IR/PassManager.h"
24  #include "llvm/InitializePasses.h"
25  #include "llvm/Pass.h"
26  #include "llvm/Support/CommandLine.h"
27  #include "llvm/Support/raw_ostream.h"
28  #include "llvm/IR/IntrinsicInst.h"
29  using namespace llvm;
30  
31  static cl::opt<TargetTransformInfo::TargetCostKind> CostKind(
32      "cost-kind", cl::desc("Target cost kind"),
33      cl::init(TargetTransformInfo::TCK_RecipThroughput),
34      cl::values(clEnumValN(TargetTransformInfo::TCK_RecipThroughput,
35                            "throughput", "Reciprocal throughput"),
36                 clEnumValN(TargetTransformInfo::TCK_Latency,
37                            "latency", "Instruction latency"),
38                 clEnumValN(TargetTransformInfo::TCK_CodeSize,
39                            "code-size", "Code size"),
40                 clEnumValN(TargetTransformInfo::TCK_SizeAndLatency,
41                            "size-latency", "Code size and latency")));
42  
43  static cl::opt<bool> TypeBasedIntrinsicCost("type-based-intrinsic-cost",
44      cl::desc("Calculate intrinsics cost based only on argument types"),
45      cl::init(false));
46  
47  #define CM_NAME "cost-model"
48  #define DEBUG_TYPE CM_NAME
49  
50  namespace {
51    class CostModelAnalysis : public FunctionPass {
52  
53    public:
54      static char ID; // Class identification, replacement for typeinfo
55      CostModelAnalysis() : FunctionPass(ID) {
56        initializeCostModelAnalysisPass(
57          *PassRegistry::getPassRegistry());
58      }
59  
60    private:
61      void getAnalysisUsage(AnalysisUsage &AU) const override;
62      bool runOnFunction(Function &F) override;
63      void print(raw_ostream &OS, const Module*) const override;
64  
65      /// The function that we analyze.
66      Function *F = nullptr;
67      /// Target information.
68      const TargetTransformInfo *TTI = nullptr;
69    };
70  }  // End of anonymous namespace
71  
72  // Register this pass.
73  char CostModelAnalysis::ID = 0;
74  static const char cm_name[] = "Cost Model Analysis";
75  INITIALIZE_PASS_BEGIN(CostModelAnalysis, CM_NAME, cm_name, false, true)
76  INITIALIZE_PASS_END  (CostModelAnalysis, CM_NAME, cm_name, false, true)
77  
78  FunctionPass *llvm::createCostModelAnalysisPass() {
79    return new CostModelAnalysis();
80  }
81  
82  void
83  CostModelAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
84    AU.setPreservesAll();
85  }
86  
87  bool
88  CostModelAnalysis::runOnFunction(Function &F) {
89   this->F = &F;
90   auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();
91   TTI = TTIWP ? &TTIWP->getTTI(F) : nullptr;
92  
93   return false;
94  }
95  
96  void CostModelAnalysis::print(raw_ostream &OS, const Module*) const {
97    if (!F)
98      return;
99  
100    for (BasicBlock &B : *F) {
101      for (Instruction &Inst : B) {
102        InstructionCost Cost;
103        auto *II = dyn_cast<IntrinsicInst>(&Inst);
104        if (II && TypeBasedIntrinsicCost) {
105          IntrinsicCostAttributes ICA(II->getIntrinsicID(), *II,
106                                      InstructionCost::getInvalid(), true);
107          Cost = TTI->getIntrinsicInstrCost(ICA, CostKind);
108        }
109        else {
110          Cost = TTI->getInstructionCost(&Inst, CostKind);
111        }
112  
113        if (auto CostVal = Cost.getValue())
114          OS << "Cost Model: Found an estimated cost of " << *CostVal;
115        else
116          OS << "Cost Model: Invalid cost";
117  
118        OS << " for instruction: " << Inst << "\n";
119      }
120    }
121  }
122  
123  PreservedAnalyses CostModelPrinterPass::run(Function &F,
124                                              FunctionAnalysisManager &AM) {
125    auto &TTI = AM.getResult<TargetIRAnalysis>(F);
126    OS << "Printing analysis 'Cost Model Analysis' for function '" << F.getName() << "':\n";
127    for (BasicBlock &B : F) {
128      for (Instruction &Inst : B) {
129        // TODO: Use a pass parameter instead of cl::opt CostKind to determine
130        // which cost kind to print.
131        InstructionCost Cost;
132        auto *II = dyn_cast<IntrinsicInst>(&Inst);
133        if (II && TypeBasedIntrinsicCost) {
134          IntrinsicCostAttributes ICA(II->getIntrinsicID(), *II,
135                                      InstructionCost::getInvalid(), true);
136          Cost = TTI.getIntrinsicInstrCost(ICA, CostKind);
137        }
138        else {
139          Cost = TTI.getInstructionCost(&Inst, CostKind);
140        }
141  
142        if (auto CostVal = Cost.getValue())
143          OS << "Cost Model: Found an estimated cost of " << *CostVal;
144        else
145          OS << "Cost Model: Invalid cost";
146  
147        OS << " for instruction: " << Inst << "\n";
148      }
149    }
150    return PreservedAnalyses::all();
151  }
152