xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/CostModel.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- CostModel.cpp ------ Cost Model Analysis ---------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the cost model analysis. It provides a very basic cost
100b57cec5SDimitry Andric // estimation for LLVM-IR. This analysis uses the services of the codegen
110b57cec5SDimitry Andric // to approximate the cost of any IR instruction when lowered to machine
120b57cec5SDimitry Andric // instructions. The cost results are unit-less and the cost number represents
130b57cec5SDimitry Andric // the throughput of the machine assuming that all loads hit the cache, all
140b57cec5SDimitry Andric // branches are predicted, etc. The cost numbers can be added in order to
150b57cec5SDimitry Andric // compare two or more transformation alternatives.
160b57cec5SDimitry Andric //
170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
180b57cec5SDimitry Andric 
19349cc55cSDimitry Andric #include "llvm/Analysis/CostModel.h"
200b57cec5SDimitry Andric #include "llvm/Analysis/Passes.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
220b57cec5SDimitry Andric #include "llvm/IR/Function.h"
23349cc55cSDimitry Andric #include "llvm/IR/PassManager.h"
24480093f4SDimitry Andric #include "llvm/InitializePasses.h"
250b57cec5SDimitry Andric #include "llvm/Pass.h"
260b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
270b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
28fcaf7f86SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric static cl::opt<TargetTransformInfo::TargetCostKind> CostKind(
320b57cec5SDimitry Andric     "cost-kind", cl::desc("Target cost kind"),
330b57cec5SDimitry Andric     cl::init(TargetTransformInfo::TCK_RecipThroughput),
340b57cec5SDimitry Andric     cl::values(clEnumValN(TargetTransformInfo::TCK_RecipThroughput,
350b57cec5SDimitry Andric                           "throughput", "Reciprocal throughput"),
360b57cec5SDimitry Andric                clEnumValN(TargetTransformInfo::TCK_Latency,
370b57cec5SDimitry Andric                           "latency", "Instruction latency"),
380b57cec5SDimitry Andric                clEnumValN(TargetTransformInfo::TCK_CodeSize,
39e8d8bef9SDimitry Andric                           "code-size", "Code size"),
40e8d8bef9SDimitry Andric                clEnumValN(TargetTransformInfo::TCK_SizeAndLatency,
41e8d8bef9SDimitry Andric                           "size-latency", "Code size and latency")));
42e8d8bef9SDimitry Andric 
43fcaf7f86SDimitry Andric static cl::opt<bool> TypeBasedIntrinsicCost("type-based-intrinsic-cost",
44fcaf7f86SDimitry Andric     cl::desc("Calculate intrinsics cost based only on argument types"),
45fcaf7f86SDimitry Andric     cl::init(false));
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric #define CM_NAME "cost-model"
480b57cec5SDimitry Andric #define DEBUG_TYPE CM_NAME
490b57cec5SDimitry Andric 
run(Function & F,FunctionAnalysisManager & AM)50349cc55cSDimitry Andric PreservedAnalyses CostModelPrinterPass::run(Function &F,
51349cc55cSDimitry Andric                                             FunctionAnalysisManager &AM) {
52349cc55cSDimitry Andric   auto &TTI = AM.getResult<TargetIRAnalysis>(F);
5381ad6265SDimitry Andric   OS << "Printing analysis 'Cost Model Analysis' for function '" << F.getName() << "':\n";
54349cc55cSDimitry Andric   for (BasicBlock &B : F) {
55349cc55cSDimitry Andric     for (Instruction &Inst : B) {
56349cc55cSDimitry Andric       // TODO: Use a pass parameter instead of cl::opt CostKind to determine
57349cc55cSDimitry Andric       // which cost kind to print.
58fcaf7f86SDimitry Andric       InstructionCost Cost;
59fcaf7f86SDimitry Andric       auto *II = dyn_cast<IntrinsicInst>(&Inst);
60*bdd1243dSDimitry Andric       if (II && TypeBasedIntrinsicCost) {
61fcaf7f86SDimitry Andric         IntrinsicCostAttributes ICA(II->getIntrinsicID(), *II,
62fcaf7f86SDimitry Andric                                     InstructionCost::getInvalid(), true);
63fcaf7f86SDimitry Andric         Cost = TTI.getIntrinsicInstrCost(ICA, CostKind);
64fcaf7f86SDimitry Andric       }
65fcaf7f86SDimitry Andric       else {
66fcaf7f86SDimitry Andric         Cost = TTI.getInstructionCost(&Inst, CostKind);
67fcaf7f86SDimitry Andric       }
68*bdd1243dSDimitry Andric 
69349cc55cSDimitry Andric       if (auto CostVal = Cost.getValue())
70349cc55cSDimitry Andric         OS << "Cost Model: Found an estimated cost of " << *CostVal;
71349cc55cSDimitry Andric       else
72349cc55cSDimitry Andric         OS << "Cost Model: Invalid cost";
73349cc55cSDimitry Andric 
74349cc55cSDimitry Andric       OS << " for instruction: " << Inst << "\n";
75349cc55cSDimitry Andric     }
76349cc55cSDimitry Andric   }
77349cc55cSDimitry Andric   return PreservedAnalyses::all();
78349cc55cSDimitry Andric }
79