cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
141 lines
5.4 KiB
C++
141 lines
5.4 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/Analysis/CostModel.h"
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
#include "llvm/Analysis/TargetTransformInfo.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
#include "llvm/IR/PassManager.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace llvm;
|
|
|
|
enum class OutputCostKind {
|
|
RecipThroughput,
|
|
Latency,
|
|
CodeSize,
|
|
SizeAndLatency,
|
|
All,
|
|
};
|
|
|
|
static cl::opt<OutputCostKind> CostKind(
|
|
"cost-kind", cl::desc("Target cost kind"),
|
|
cl::init(OutputCostKind::RecipThroughput),
|
|
cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput",
|
|
"Reciprocal throughput"),
|
|
clEnumValN(OutputCostKind::Latency, "latency",
|
|
"Instruction latency"),
|
|
clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"),
|
|
clEnumValN(OutputCostKind::SizeAndLatency, "size-latency",
|
|
"Code size and latency"),
|
|
clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")));
|
|
|
|
enum class IntrinsicCostStrategy {
|
|
InstructionCost,
|
|
IntrinsicCost,
|
|
TypeBasedIntrinsicCost,
|
|
};
|
|
|
|
static cl::opt<IntrinsicCostStrategy> IntrinsicCost(
|
|
"intrinsic-cost-strategy",
|
|
cl::desc("Costing strategy for intrinsic instructions"),
|
|
cl::init(IntrinsicCostStrategy::InstructionCost),
|
|
cl::values(
|
|
clEnumValN(IntrinsicCostStrategy::InstructionCost, "instruction-cost",
|
|
"Use TargetTransformInfo::getInstructionCost"),
|
|
clEnumValN(IntrinsicCostStrategy::IntrinsicCost, "intrinsic-cost",
|
|
"Use TargetTransformInfo::getIntrinsicInstrCost"),
|
|
clEnumValN(
|
|
IntrinsicCostStrategy::TypeBasedIntrinsicCost,
|
|
"type-based-intrinsic-cost",
|
|
"Calculate the intrinsic cost based only on argument types")));
|
|
|
|
#define CM_NAME "cost-model"
|
|
#define DEBUG_TYPE CM_NAME
|
|
|
|
static InstructionCost getCost(Instruction &Inst, TTI::TargetCostKind CostKind,
|
|
TargetTransformInfo &TTI,
|
|
TargetLibraryInfo &TLI) {
|
|
auto *II = dyn_cast<IntrinsicInst>(&Inst);
|
|
if (II && IntrinsicCost != IntrinsicCostStrategy::InstructionCost) {
|
|
IntrinsicCostAttributes ICA(
|
|
II->getIntrinsicID(), *II, InstructionCost::getInvalid(),
|
|
/*TypeBasedOnly=*/IntrinsicCost ==
|
|
IntrinsicCostStrategy::TypeBasedIntrinsicCost,
|
|
&TLI);
|
|
return TTI.getIntrinsicInstrCost(ICA, CostKind);
|
|
}
|
|
|
|
return TTI.getInstructionCost(&Inst, CostKind);
|
|
}
|
|
|
|
static TTI::TargetCostKind
|
|
OutputCostKindToTargetCostKind(OutputCostKind CostKind) {
|
|
switch (CostKind) {
|
|
case OutputCostKind::RecipThroughput:
|
|
return TTI::TCK_RecipThroughput;
|
|
case OutputCostKind::Latency:
|
|
return TTI::TCK_Latency;
|
|
case OutputCostKind::CodeSize:
|
|
return TTI::TCK_CodeSize;
|
|
case OutputCostKind::SizeAndLatency:
|
|
return TTI::TCK_SizeAndLatency;
|
|
default:
|
|
llvm_unreachable("Unexpected OutputCostKind!");
|
|
};
|
|
}
|
|
|
|
PreservedAnalyses CostModelPrinterPass::run(Function &F,
|
|
FunctionAnalysisManager &AM) {
|
|
auto &TTI = AM.getResult<TargetIRAnalysis>(F);
|
|
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
|
|
OS << "Printing analysis 'Cost Model Analysis' for function '" << F.getName() << "':\n";
|
|
for (BasicBlock &B : F) {
|
|
for (Instruction &Inst : B) {
|
|
OS << "Cost Model: ";
|
|
if (CostKind == OutputCostKind::All) {
|
|
OS << "Found costs of ";
|
|
InstructionCost RThru =
|
|
getCost(Inst, TTI::TCK_RecipThroughput, TTI, TLI);
|
|
InstructionCost CodeSize = getCost(Inst, TTI::TCK_CodeSize, TTI, TLI);
|
|
InstructionCost Lat = getCost(Inst, TTI::TCK_Latency, TTI, TLI);
|
|
InstructionCost SizeLat =
|
|
getCost(Inst, TTI::TCK_SizeAndLatency, TTI, TLI);
|
|
if (RThru == CodeSize && RThru == Lat && RThru == SizeLat)
|
|
OS << RThru;
|
|
else
|
|
OS << "RThru:" << RThru << " CodeSize:" << CodeSize << " Lat:" << Lat
|
|
<< " SizeLat:" << SizeLat;
|
|
OS << " for: " << Inst << "\n";
|
|
} else {
|
|
InstructionCost Cost =
|
|
getCost(Inst, OutputCostKindToTargetCostKind(CostKind), TTI, TLI);
|
|
if (Cost.isValid())
|
|
OS << "Found an estimated cost of " << Cost.getValue();
|
|
else
|
|
OS << "Invalid cost";
|
|
OS << " for instruction: " << Inst << "\n";
|
|
}
|
|
}
|
|
}
|
|
return PreservedAnalyses::all();
|
|
}
|