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