1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00
llvm-mirror/lib/IR/DiagnosticInfo.cpp
David Sherwood e693cbf9f5 [Support] Introduce a new InstructionCost class
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
2020-12-11 08:12:54 +00:00

388 lines
14 KiB
C++

//===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//
//
// 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 different classes involved in low level diagnostics.
//
// Diagnostics reporting is still done as part of the LLVMContext.
//===----------------------------------------------------------------------===//
#include "llvm/IR/DiagnosticInfo.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/InstructionCost.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include <atomic>
#include <cassert>
#include <memory>
#include <string>
using namespace llvm;
int llvm::getNextAvailablePluginDiagnosticKind() {
static std::atomic<int> PluginKindID(DK_FirstPluginKind);
return ++PluginKindID;
}
const char *OptimizationRemarkAnalysis::AlwaysPrint = "";
DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
const Twine &MsgStr,
DiagnosticSeverity Severity)
: DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr), Instr(&I) {
if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
if (SrcLoc->getNumOperands() != 0)
if (const auto *CI =
mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0)))
LocCookie = CI->getZExtValue();
}
}
void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
DP << getMsgStr();
if (getLocCookie())
DP << " at line " << getLocCookie();
}
void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const {
DP << getResourceName() << " limit";
if (getResourceLimit() != 0)
DP << " of " << getResourceLimit();
DP << " exceeded (" << getResourceSize() << ") in " << getFunction();
}
void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const {
DP << "ignoring debug info with an invalid version (" << getMetadataVersion()
<< ") in " << getModule();
}
void DiagnosticInfoIgnoringInvalidDebugMetadata::print(
DiagnosticPrinter &DP) const {
DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier();
}
void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
if (!FileName.empty()) {
DP << getFileName();
if (LineNum > 0)
DP << ":" << getLineNum();
DP << ": ";
}
DP << getMsg();
}
void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const {
if (getFileName())
DP << getFileName() << ": ";
DP << getMsg();
}
void DiagnosticInfo::anchor() {}
void DiagnosticInfoStackSize::anchor() {}
void DiagnosticInfoWithLocationBase::anchor() {}
void DiagnosticInfoIROptimization::anchor() {}
DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) {
if (!DL)
return;
File = DL->getFile();
Line = DL->getLine();
Column = DL->getColumn();
}
DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) {
if (!SP)
return;
File = SP->getFile();
Line = SP->getScopeLine();
Column = 0;
}
StringRef DiagnosticLocation::getRelativePath() const {
return File->getFilename();
}
std::string DiagnosticLocation::getAbsolutePath() const {
StringRef Name = File->getFilename();
if (sys::path::is_absolute(Name))
return std::string(Name);
SmallString<128> Path;
sys::path::append(Path, File->getDirectory(), Name);
return sys::path::remove_leading_dotslash(Path).str();
}
std::string DiagnosticInfoWithLocationBase::getAbsolutePath() const {
return Loc.getAbsolutePath();
}
void DiagnosticInfoWithLocationBase::getLocation(StringRef &RelativePath,
unsigned &Line,
unsigned &Column) const {
RelativePath = Loc.getRelativePath();
Line = Loc.getLine();
Column = Loc.getColumn();
}
const std::string DiagnosticInfoWithLocationBase::getLocationStr() const {
StringRef Filename("<unknown>");
unsigned Line = 0;
unsigned Column = 0;
if (isLocationAvailable())
getLocation(Filename, Line, Column);
return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
const Value *V)
: Key(std::string(Key)) {
if (auto *F = dyn_cast<Function>(V)) {
if (DISubprogram *SP = F->getSubprogram())
Loc = SP;
}
else if (auto *I = dyn_cast<Instruction>(V))
Loc = I->getDebugLoc();
// Only include names that correspond to user variables. FIXME: We should use
// debug info if available to get the name of the user variable.
if (isa<llvm::Argument>(V) || isa<GlobalValue>(V))
Val = std::string(GlobalValue::dropLLVMManglingEscape(V->getName()));
else if (isa<Constant>(V)) {
raw_string_ostream OS(Val);
V->printAsOperand(OS, /*PrintType=*/false);
} else if (auto *I = dyn_cast<Instruction>(V))
Val = I->getOpcodeName();
}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T)
: Key(std::string(Key)) {
raw_string_ostream OS(Val);
OS << *T;
}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S)
: Key(std::string(Key)), Val(S.str()) {}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)
: Key(std::string(Key)), Val(itostr(N)) {}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N)
: Key(std::string(Key)), Val(llvm::to_string(N)) {}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N)
: Key(std::string(Key)), Val(itostr(N)) {}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N)
: Key(std::string(Key)), Val(itostr(N)) {}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N)
: Key(std::string(Key)), Val(utostr(N)) {}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
unsigned long N)
: Key(std::string(Key)), Val(utostr(N)) {}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
unsigned long long N)
: Key(std::string(Key)), Val(utostr(N)) {}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
ElementCount EC)
: Key(std::string(Key)) {
raw_string_ostream OS(Val);
EC.print(OS);
}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
InstructionCost C)
: Key(std::string(Key)) {
raw_string_ostream OS(Val);
C.print(OS);
}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc)
: Key(std::string(Key)), Loc(Loc) {
if (Loc) {
Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" +
Twine(Loc.getCol())).str();
} else {
Val = "<UNKNOWN LOCATION>";
}
}
void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {
DP << getLocationStr() << ": " << getMsg();
if (Hotness)
DP << " (hotness: " << *Hotness << ")";
}
OptimizationRemark::OptimizationRemark(const char *PassName,
StringRef RemarkName,
const DiagnosticLocation &Loc,
const Value *CodeRegion)
: DiagnosticInfoIROptimization(
DK_OptimizationRemark, DS_Remark, PassName, RemarkName,
*cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
OptimizationRemark::OptimizationRemark(const char *PassName,
StringRef RemarkName,
const Instruction *Inst)
: DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
RemarkName, *Inst->getParent()->getParent(),
Inst->getDebugLoc(), Inst->getParent()) {}
static const BasicBlock *getFirstFunctionBlock(const Function *Func) {
return Func->empty() ? nullptr : &Func->front();
}
OptimizationRemark::OptimizationRemark(const char *PassName,
StringRef RemarkName,
const Function *Func)
: DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
RemarkName, *Func, Func->getSubprogram(),
getFirstFunctionBlock(Func)) {}
bool OptimizationRemark::isEnabled() const {
const Function &Fn = getFunction();
LLVMContext &Ctx = Fn.getContext();
return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
}
OptimizationRemarkMissed::OptimizationRemarkMissed(
const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
const Value *CodeRegion)
: DiagnosticInfoIROptimization(
DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName,
*cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
StringRef RemarkName,
const Instruction *Inst)
: DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
PassName, RemarkName,
*Inst->getParent()->getParent(),
Inst->getDebugLoc(), Inst->getParent()) {}
bool OptimizationRemarkMissed::isEnabled() const {
const Function &Fn = getFunction();
LLVMContext &Ctx = Fn.getContext();
return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
}
OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
const Value *CodeRegion)
: DiagnosticInfoIROptimization(
DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName,
*cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
StringRef RemarkName,
const Instruction *Inst)
: DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
PassName, RemarkName,
*Inst->getParent()->getParent(),
Inst->getDebugLoc(), Inst->getParent()) {}
OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName,
const DiagnosticLocation &Loc, const Value *CodeRegion)
: DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName,
*cast<BasicBlock>(CodeRegion)->getParent(),
Loc, CodeRegion) {}
bool OptimizationRemarkAnalysis::isEnabled() const {
const Function &Fn = getFunction();
LLVMContext &Ctx = Fn.getContext();
return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) ||
shouldAlwaysPrint();
}
void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {
DP << Diagnostic;
}
DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure(
const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
const Value *CodeRegion)
: DiagnosticInfoIROptimization(
DK_OptimizationFailure, DS_Warning, PassName, RemarkName,
*cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
bool DiagnosticInfoOptimizationFailure::isEnabled() const {
// Only print warnings.
return getSeverity() == DS_Warning;
}
void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const {
std::string Str;
raw_string_ostream OS(Str);
OS << getLocationStr() << ": in function " << getFunction().getName() << ' '
<< *getFunction().getFunctionType() << ": " << Msg << '\n';
OS.flush();
DP << Str;
}
void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const {
DP << "Instruction selection used fallback path for " << getFunction();
}
void DiagnosticInfoOptimizationBase::insert(StringRef S) {
Args.emplace_back(S);
}
void DiagnosticInfoOptimizationBase::insert(Argument A) {
Args.push_back(std::move(A));
}
void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) {
IsVerbose = true;
}
void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) {
FirstExtraArgIndex = Args.size();
}
std::string DiagnosticInfoOptimizationBase::getMsg() const {
std::string Str;
raw_string_ostream OS(Str);
for (const DiagnosticInfoOptimizationBase::Argument &Arg :
make_range(Args.begin(), FirstExtraArgIndex == -1
? Args.end()
: Args.begin() + FirstExtraArgIndex))
OS << Arg.Val;
return OS.str();
}
void OptimizationRemarkAnalysisFPCommute::anchor() {}
void OptimizationRemarkAnalysisAliasing::anchor() {}