1a6b91ac3SNadav Rotem //===- CostModel.cpp ------ Cost Model Analysis ---------------------------===//
2a6b91ac3SNadav Rotem //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a6b91ac3SNadav Rotem //
7a6b91ac3SNadav Rotem //===----------------------------------------------------------------------===//
8a6b91ac3SNadav Rotem //
9a6b91ac3SNadav Rotem // This file defines the cost model analysis. It provides a very basic cost
1099868e4fSNadav Rotem // estimation for LLVM-IR. This analysis uses the services of the codegen
1199868e4fSNadav Rotem // to approximate the cost of any IR instruction when lowered to machine
1299868e4fSNadav Rotem // instructions. The cost results are unit-less and the cost number represents
1399868e4fSNadav Rotem // the throughput of the machine assuming that all loads hit the cache, all
1499868e4fSNadav Rotem // branches are predicted, etc. The cost numbers can be added in order to
1599868e4fSNadav Rotem // compare two or more transformation alternatives.
16a6b91ac3SNadav Rotem //
17a6b91ac3SNadav Rotem //===----------------------------------------------------------------------===//
18a6b91ac3SNadav Rotem
19fe15347aSArthur Eubanks #include "llvm/Analysis/CostModel.h"
20a6b91ac3SNadav Rotem #include "llvm/Analysis/Passes.h"
21d3e73556SChandler Carruth #include "llvm/Analysis/TargetTransformInfo.h"
229fb823bbSChandler Carruth #include "llvm/IR/Function.h"
23fe15347aSArthur Eubanks #include "llvm/IR/PassManager.h"
2405da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
25a6b91ac3SNadav Rotem #include "llvm/Pass.h"
26cae8735aSArnold Schwaighofer #include "llvm/Support/CommandLine.h"
27a6b91ac3SNadav Rotem #include "llvm/Support/raw_ostream.h"
28*41958f76SMalhar Jajoo #include "llvm/IR/IntrinsicInst.h"
29a6b91ac3SNadav Rotem using namespace llvm;
3062d64144SGuozhi Wei
3162d64144SGuozhi Wei static cl::opt<TargetTransformInfo::TargetCostKind> CostKind(
3262d64144SGuozhi Wei "cost-kind", cl::desc("Target cost kind"),
3362d64144SGuozhi Wei cl::init(TargetTransformInfo::TCK_RecipThroughput),
3462d64144SGuozhi Wei cl::values(clEnumValN(TargetTransformInfo::TCK_RecipThroughput,
3562d64144SGuozhi Wei "throughput", "Reciprocal throughput"),
3662d64144SGuozhi Wei clEnumValN(TargetTransformInfo::TCK_Latency,
3762d64144SGuozhi Wei "latency", "Instruction latency"),
3862d64144SGuozhi Wei clEnumValN(TargetTransformInfo::TCK_CodeSize,
39816b0a9cSSanjay Patel "code-size", "Code size"),
40816b0a9cSSanjay Patel clEnumValN(TargetTransformInfo::TCK_SizeAndLatency,
41816b0a9cSSanjay Patel "size-latency", "Code size and latency")));
42816b0a9cSSanjay Patel
43*41958f76SMalhar Jajoo static cl::opt<bool> TypeBasedIntrinsicCost("type-based-intrinsic-cost",
44*41958f76SMalhar Jajoo cl::desc("Calculate intrinsics cost based only on argument types"),
45*41958f76SMalhar Jajoo cl::init(false));
46a6b91ac3SNadav Rotem
47f1221bd0SChandler Carruth #define CM_NAME "cost-model"
48f1221bd0SChandler Carruth #define DEBUG_TYPE CM_NAME
49f1221bd0SChandler Carruth
50a6b91ac3SNadav Rotem namespace {
51a6b91ac3SNadav Rotem class CostModelAnalysis : public FunctionPass {
52a6b91ac3SNadav Rotem
53a6b91ac3SNadav Rotem public:
54a6b91ac3SNadav Rotem static char ID; // Class identification, replacement for typeinfo
CostModelAnalysis()55b752eb88SKazu Hirata CostModelAnalysis() : FunctionPass(ID) {
56a6b91ac3SNadav Rotem initializeCostModelAnalysisPass(
57a6b91ac3SNadav Rotem *PassRegistry::getPassRegistry());
58a6b91ac3SNadav Rotem }
59a6b91ac3SNadav Rotem
60a6b91ac3SNadav Rotem /// Returns the expected cost of the instruction.
61a6b91ac3SNadav Rotem /// Returns -1 if the cost is unknown.
62a6b91ac3SNadav Rotem /// Note, this method does not cache the cost calculation and it
63a6b91ac3SNadav Rotem /// can be expensive in some cases.
getInstructionCost(const Instruction * I) const649b76160eSDavid Sherwood InstructionCost getInstructionCost(const Instruction *I) const {
6562d64144SGuozhi Wei return TTI->getInstructionCost(I, TargetTransformInfo::TCK_RecipThroughput);
6662d64144SGuozhi Wei }
67a6b91ac3SNadav Rotem
68a6b91ac3SNadav Rotem private:
69e9ba759cSCraig Topper void getAnalysisUsage(AnalysisUsage &AU) const override;
70e9ba759cSCraig Topper bool runOnFunction(Function &F) override;
71e9ba759cSCraig Topper void print(raw_ostream &OS, const Module*) const override;
72a6b91ac3SNadav Rotem
73a6b91ac3SNadav Rotem /// The function that we analyze.
74b752eb88SKazu Hirata Function *F = nullptr;
75cf569a8cSChandler Carruth /// Target information.
76b752eb88SKazu Hirata const TargetTransformInfo *TTI = nullptr;
77a6b91ac3SNadav Rotem };
78a6b91ac3SNadav Rotem } // End of anonymous namespace
79a6b91ac3SNadav Rotem
80a6b91ac3SNadav Rotem // Register this pass.
81a6b91ac3SNadav Rotem char CostModelAnalysis::ID = 0;
82a6b91ac3SNadav Rotem static const char cm_name[] = "Cost Model Analysis";
INITIALIZE_PASS_BEGIN(CostModelAnalysis,CM_NAME,cm_name,false,true)83a6b91ac3SNadav Rotem INITIALIZE_PASS_BEGIN(CostModelAnalysis, CM_NAME, cm_name, false, true)
84a6b91ac3SNadav Rotem INITIALIZE_PASS_END (CostModelAnalysis, CM_NAME, cm_name, false, true)
85a6b91ac3SNadav Rotem
86a6b91ac3SNadav Rotem FunctionPass *llvm::createCostModelAnalysisPass() {
87a6b91ac3SNadav Rotem return new CostModelAnalysis();
88a6b91ac3SNadav Rotem }
89a6b91ac3SNadav Rotem
90a6b91ac3SNadav Rotem void
getAnalysisUsage(AnalysisUsage & AU) const91a6b91ac3SNadav Rotem CostModelAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
92a6b91ac3SNadav Rotem AU.setPreservesAll();
93a6b91ac3SNadav Rotem }
94a6b91ac3SNadav Rotem
95a6b91ac3SNadav Rotem bool
runOnFunction(Function & F)96a6b91ac3SNadav Rotem CostModelAnalysis::runOnFunction(Function &F) {
97a6b91ac3SNadav Rotem this->F = &F;
98705b185fSChandler Carruth auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();
99fdb9c573SChandler Carruth TTI = TTIWP ? &TTIWP->getTTI(F) : nullptr;
100a6b91ac3SNadav Rotem
101a6b91ac3SNadav Rotem return false;
102a6b91ac3SNadav Rotem }
103a6b91ac3SNadav Rotem
print(raw_ostream & OS,const Module *) const104a6b91ac3SNadav Rotem void CostModelAnalysis::print(raw_ostream &OS, const Module*) const {
105a6b91ac3SNadav Rotem if (!F)
106a6b91ac3SNadav Rotem return;
107a6b91ac3SNadav Rotem
108aa209150SBenjamin Kramer for (BasicBlock &B : *F) {
109aa209150SBenjamin Kramer for (Instruction &Inst : B) {
110*41958f76SMalhar Jajoo InstructionCost Cost;
111*41958f76SMalhar Jajoo if (TypeBasedIntrinsicCost && isa<IntrinsicInst>(&Inst)) {
112*41958f76SMalhar Jajoo auto *II = dyn_cast<IntrinsicInst>(&Inst);
113*41958f76SMalhar Jajoo IntrinsicCostAttributes ICA(II->getIntrinsicID(), *II,
114*41958f76SMalhar Jajoo InstructionCost::getInvalid(), true);
115*41958f76SMalhar Jajoo Cost = TTI->getIntrinsicInstrCost(ICA, CostKind);
116*41958f76SMalhar Jajoo }
117*41958f76SMalhar Jajoo else {
118*41958f76SMalhar Jajoo Cost = TTI->getInstructionCost(&Inst, CostKind);
119*41958f76SMalhar Jajoo }
1209b76160eSDavid Sherwood if (auto CostVal = Cost.getValue())
1219b76160eSDavid Sherwood OS << "Cost Model: Found an estimated cost of " << *CostVal;
122a6b91ac3SNadav Rotem else
1234ca86074SSander de Smalen OS << "Cost Model: Invalid cost";
124a6b91ac3SNadav Rotem
125aa209150SBenjamin Kramer OS << " for instruction: " << Inst << "\n";
126a6b91ac3SNadav Rotem }
127a6b91ac3SNadav Rotem }
128a6b91ac3SNadav Rotem }
129fe15347aSArthur Eubanks
run(Function & F,FunctionAnalysisManager & AM)130fe15347aSArthur Eubanks PreservedAnalyses CostModelPrinterPass::run(Function &F,
131fe15347aSArthur Eubanks FunctionAnalysisManager &AM) {
132fe15347aSArthur Eubanks auto &TTI = AM.getResult<TargetIRAnalysis>(F);
13341e792d7SArthur Eubanks OS << "Printing analysis 'Cost Model Analysis' for function '" << F.getName() << "':\n";
134fe15347aSArthur Eubanks for (BasicBlock &B : F) {
135fe15347aSArthur Eubanks for (Instruction &Inst : B) {
136fe15347aSArthur Eubanks // TODO: Use a pass parameter instead of cl::opt CostKind to determine
137fe15347aSArthur Eubanks // which cost kind to print.
138*41958f76SMalhar Jajoo InstructionCost Cost;
139*41958f76SMalhar Jajoo if (TypeBasedIntrinsicCost && isa<IntrinsicInst>(&Inst)) {
140*41958f76SMalhar Jajoo auto *II = dyn_cast<IntrinsicInst>(&Inst);
141*41958f76SMalhar Jajoo IntrinsicCostAttributes ICA(II->getIntrinsicID(), *II,
142*41958f76SMalhar Jajoo InstructionCost::getInvalid(), true);
143*41958f76SMalhar Jajoo Cost = TTI.getIntrinsicInstrCost(ICA, CostKind);
144*41958f76SMalhar Jajoo }
145*41958f76SMalhar Jajoo else {
146*41958f76SMalhar Jajoo Cost = TTI.getInstructionCost(&Inst, CostKind);
147*41958f76SMalhar Jajoo }
148fe15347aSArthur Eubanks if (auto CostVal = Cost.getValue())
149fe15347aSArthur Eubanks OS << "Cost Model: Found an estimated cost of " << *CostVal;
150fe15347aSArthur Eubanks else
151fe15347aSArthur Eubanks OS << "Cost Model: Invalid cost";
152fe15347aSArthur Eubanks
153fe15347aSArthur Eubanks OS << " for instruction: " << Inst << "\n";
154fe15347aSArthur Eubanks }
155fe15347aSArthur Eubanks }
156fe15347aSArthur Eubanks return PreservedAnalyses::all();
157fe15347aSArthur Eubanks }
158