CostModel.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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. #include "llvm/Analysis/CostModel.h"
  19. #include "llvm/Analysis/Passes.h"
  20. #include "llvm/Analysis/TargetTransformInfo.h"
  21. #include "llvm/IR/Function.h"
  22. #include "llvm/IR/PassManager.h"
  23. #include "llvm/InitializePasses.h"
  24. #include "llvm/Pass.h"
  25. #include "llvm/Support/CommandLine.h"
  26. #include "llvm/Support/raw_ostream.h"
  27. #include "llvm/IR/IntrinsicInst.h"
  28. using namespace llvm;
  29. static cl::opt<TargetTransformInfo::TargetCostKind> CostKind(
  30. "cost-kind", cl::desc("Target cost kind"),
  31. cl::init(TargetTransformInfo::TCK_RecipThroughput),
  32. cl::values(clEnumValN(TargetTransformInfo::TCK_RecipThroughput,
  33. "throughput", "Reciprocal throughput"),
  34. clEnumValN(TargetTransformInfo::TCK_Latency,
  35. "latency", "Instruction latency"),
  36. clEnumValN(TargetTransformInfo::TCK_CodeSize,
  37. "code-size", "Code size"),
  38. clEnumValN(TargetTransformInfo::TCK_SizeAndLatency,
  39. "size-latency", "Code size and latency")));
  40. static cl::opt<bool> TypeBasedIntrinsicCost("type-based-intrinsic-cost",
  41. cl::desc("Calculate intrinsics cost based only on argument types"),
  42. cl::init(false));
  43. #define CM_NAME "cost-model"
  44. #define DEBUG_TYPE CM_NAME
  45. namespace {
  46. class CostModelAnalysis : public FunctionPass {
  47. public:
  48. static char ID; // Class identification, replacement for typeinfo
  49. CostModelAnalysis() : FunctionPass(ID) {
  50. initializeCostModelAnalysisPass(
  51. *PassRegistry::getPassRegistry());
  52. }
  53. private:
  54. void getAnalysisUsage(AnalysisUsage &AU) const override;
  55. bool runOnFunction(Function &F) override;
  56. void print(raw_ostream &OS, const Module*) const override;
  57. /// The function that we analyze.
  58. Function *F = nullptr;
  59. /// Target information.
  60. const TargetTransformInfo *TTI = nullptr;
  61. };
  62. } // End of anonymous namespace
  63. // Register this pass.
  64. char CostModelAnalysis::ID = 0;
  65. static const char cm_name[] = "Cost Model Analysis";
  66. INITIALIZE_PASS_BEGIN(CostModelAnalysis, CM_NAME, cm_name, false, true)
  67. INITIALIZE_PASS_END (CostModelAnalysis, CM_NAME, cm_name, false, true)
  68. FunctionPass *llvm::createCostModelAnalysisPass() {
  69. return new CostModelAnalysis();
  70. }
  71. void
  72. CostModelAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
  73. AU.setPreservesAll();
  74. }
  75. bool
  76. CostModelAnalysis::runOnFunction(Function &F) {
  77. this->F = &F;
  78. auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();
  79. TTI = TTIWP ? &TTIWP->getTTI(F) : nullptr;
  80. return false;
  81. }
  82. void CostModelAnalysis::print(raw_ostream &OS, const Module*) const {
  83. if (!F)
  84. return;
  85. for (BasicBlock &B : *F) {
  86. for (Instruction &Inst : B) {
  87. InstructionCost Cost;
  88. auto *II = dyn_cast<IntrinsicInst>(&Inst);
  89. if (II && TypeBasedIntrinsicCost) {
  90. IntrinsicCostAttributes ICA(II->getIntrinsicID(), *II,
  91. InstructionCost::getInvalid(), true);
  92. Cost = TTI->getIntrinsicInstrCost(ICA, CostKind);
  93. }
  94. else {
  95. Cost = TTI->getInstructionCost(&Inst, CostKind);
  96. }
  97. if (auto CostVal = Cost.getValue())
  98. OS << "Cost Model: Found an estimated cost of " << *CostVal;
  99. else
  100. OS << "Cost Model: Invalid cost";
  101. OS << " for instruction: " << Inst << "\n";
  102. }
  103. }
  104. }
  105. PreservedAnalyses CostModelPrinterPass::run(Function &F,
  106. FunctionAnalysisManager &AM) {
  107. auto &TTI = AM.getResult<TargetIRAnalysis>(F);
  108. OS << "Printing analysis 'Cost Model Analysis' for function '" << F.getName() << "':\n";
  109. for (BasicBlock &B : F) {
  110. for (Instruction &Inst : B) {
  111. // TODO: Use a pass parameter instead of cl::opt CostKind to determine
  112. // which cost kind to print.
  113. InstructionCost Cost;
  114. auto *II = dyn_cast<IntrinsicInst>(&Inst);
  115. if (II && TypeBasedIntrinsicCost) {
  116. IntrinsicCostAttributes ICA(II->getIntrinsicID(), *II,
  117. InstructionCost::getInvalid(), true);
  118. Cost = TTI.getIntrinsicInstrCost(ICA, CostKind);
  119. }
  120. else {
  121. Cost = TTI.getInstructionCost(&Inst, CostKind);
  122. }
  123. if (auto CostVal = Cost.getValue())
  124. OS << "Cost Model: Found an estimated cost of " << *CostVal;
  125. else
  126. OS << "Cost Model: Invalid cost";
  127. OS << " for instruction: " << Inst << "\n";
  128. }
  129. }
  130. return PreservedAnalyses::all();
  131. }