mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
e693cbf9f5
This is the first in a series of patches that attempts to migrate existing cost instructions to return a new InstructionCost class in place of a simple integer. This new class is intended to be as light-weight and simple as possible, with a full range of arithmetic and comparison operators that largely mirror the same sets of operations on basic types, such as integers. The main advantage to using an InstructionCost is that it can encode a particular cost state in addition to a value. The initial implementation only has two states - Normal and Invalid - but these could be expanded over time if necessary. An invalid state can be used to represent an unknown cost or an instruction that is prohibitively expensive. This patch adds the new class and changes the getInstructionCost interface to return the new class. Other cost functions, such as getUserCost, etc., will be migrated in future patches as I believe this to be less disruptive. One benefit of this new class is that it provides a way to unify many of the magic costs in the codebase where the cost is set to a deliberately high number to prevent optimisations taking place, e.g. vectorization. It also provides a route to represent the extremely high, and unknown, cost of scalarization of scalable vectors, which is not currently supported. Differential Revision: https://reviews.llvm.org/D91174
116 lines
4.0 KiB
C++
116 lines
4.0 KiB
C++
//===- CostModel.cpp ------ Cost Model Analysis ---------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the cost model analysis. It provides a very basic cost
|
|
// estimation for LLVM-IR. This analysis uses the services of the codegen
|
|
// to approximate the cost of any IR instruction when lowered to machine
|
|
// instructions. The cost results are unit-less and the cost number represents
|
|
// the throughput of the machine assuming that all loads hit the cache, all
|
|
// branches are predicted, etc. The cost numbers can be added in order to
|
|
// compare two or more transformation alternatives.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/Analysis/Passes.h"
|
|
#include "llvm/Analysis/TargetTransformInfo.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/InitializePasses.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
using namespace llvm;
|
|
|
|
static cl::opt<TargetTransformInfo::TargetCostKind> CostKind(
|
|
"cost-kind", cl::desc("Target cost kind"),
|
|
cl::init(TargetTransformInfo::TCK_RecipThroughput),
|
|
cl::values(clEnumValN(TargetTransformInfo::TCK_RecipThroughput,
|
|
"throughput", "Reciprocal throughput"),
|
|
clEnumValN(TargetTransformInfo::TCK_Latency,
|
|
"latency", "Instruction latency"),
|
|
clEnumValN(TargetTransformInfo::TCK_CodeSize,
|
|
"code-size", "Code size"),
|
|
clEnumValN(TargetTransformInfo::TCK_SizeAndLatency,
|
|
"size-latency", "Code size and latency")));
|
|
|
|
|
|
#define CM_NAME "cost-model"
|
|
#define DEBUG_TYPE CM_NAME
|
|
|
|
namespace {
|
|
class CostModelAnalysis : public FunctionPass {
|
|
|
|
public:
|
|
static char ID; // Class identification, replacement for typeinfo
|
|
CostModelAnalysis() : FunctionPass(ID), F(nullptr), TTI(nullptr) {
|
|
initializeCostModelAnalysisPass(
|
|
*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
/// Returns the expected cost of the instruction.
|
|
/// Returns -1 if the cost is unknown.
|
|
/// Note, this method does not cache the cost calculation and it
|
|
/// can be expensive in some cases.
|
|
InstructionCost getInstructionCost(const Instruction *I) const {
|
|
return TTI->getInstructionCost(I, TargetTransformInfo::TCK_RecipThroughput);
|
|
}
|
|
|
|
private:
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
|
bool runOnFunction(Function &F) override;
|
|
void print(raw_ostream &OS, const Module*) const override;
|
|
|
|
/// The function that we analyze.
|
|
Function *F;
|
|
/// Target information.
|
|
const TargetTransformInfo *TTI;
|
|
};
|
|
} // End of anonymous namespace
|
|
|
|
// Register this pass.
|
|
char CostModelAnalysis::ID = 0;
|
|
static const char cm_name[] = "Cost Model Analysis";
|
|
INITIALIZE_PASS_BEGIN(CostModelAnalysis, CM_NAME, cm_name, false, true)
|
|
INITIALIZE_PASS_END (CostModelAnalysis, CM_NAME, cm_name, false, true)
|
|
|
|
FunctionPass *llvm::createCostModelAnalysisPass() {
|
|
return new CostModelAnalysis();
|
|
}
|
|
|
|
void
|
|
CostModelAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AU.setPreservesAll();
|
|
}
|
|
|
|
bool
|
|
CostModelAnalysis::runOnFunction(Function &F) {
|
|
this->F = &F;
|
|
auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();
|
|
TTI = TTIWP ? &TTIWP->getTTI(F) : nullptr;
|
|
|
|
return false;
|
|
}
|
|
|
|
void CostModelAnalysis::print(raw_ostream &OS, const Module*) const {
|
|
if (!F)
|
|
return;
|
|
|
|
for (BasicBlock &B : *F) {
|
|
for (Instruction &Inst : B) {
|
|
InstructionCost Cost = TTI->getInstructionCost(&Inst, CostKind);
|
|
if (auto CostVal = Cost.getValue())
|
|
OS << "Cost Model: Found an estimated cost of " << *CostVal;
|
|
else
|
|
OS << "Cost Model: Unknown cost";
|
|
|
|
OS << " for instruction: " << Inst << "\n";
|
|
}
|
|
}
|
|
}
|