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).
244 lines
7.0 KiB
C++
244 lines
7.0 KiB
C++
//===- SandboxIRBench.cpp -------------------------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// These tests measure the performance of some core SandboxIR functions and
|
|
// compare them against LLVM IR.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "benchmark/benchmark.h"
|
|
#include "llvm/AsmParser/Parser.h"
|
|
#include "llvm/IR/BasicBlock.h"
|
|
#include "llvm/IR/DataLayout.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/Instruction.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/SandboxIR/Function.h"
|
|
#include "llvm/SandboxIR/Instruction.h"
|
|
#include "llvm/SandboxIR/Module.h"
|
|
#include "llvm/Support/SourceMgr.h"
|
|
#include <memory>
|
|
#include <sstream>
|
|
|
|
using namespace llvm;
|
|
|
|
static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
|
|
SMDiagnostic Err;
|
|
std::unique_ptr<Module> M = parseAssemblyString(IR, Err, C);
|
|
if (!M)
|
|
Err.print("SandboxIRBench", errs());
|
|
return M;
|
|
}
|
|
|
|
enum class IR {
|
|
LLVM, ///> LLVM IR
|
|
SBoxNoTracking, ///> Sandbox IR with tracking disabled
|
|
SBoxTracking, ///> Sandbox IR with tracking enabled
|
|
};
|
|
// Traits to get llvm::BasicBlock/sandboxir::BasicBlock from IR::LLVM/IR::SBox.
|
|
template <IR IRTy> struct TypeSelect {};
|
|
template <> struct TypeSelect<IR::LLVM> {
|
|
using BasicBlock = llvm::BasicBlock;
|
|
};
|
|
template <> struct TypeSelect<IR::SBoxNoTracking> {
|
|
using BasicBlock = sandboxir::BasicBlock;
|
|
};
|
|
template <> struct TypeSelect<IR::SBoxTracking> {
|
|
using BasicBlock = sandboxir::BasicBlock;
|
|
};
|
|
|
|
template <IR IRTy>
|
|
static typename TypeSelect<IRTy>::BasicBlock *
|
|
genIR(std::unique_ptr<llvm::Module> &LLVMM, LLVMContext &LLVMCtx,
|
|
sandboxir::Context &Ctx,
|
|
std::function<std::string(unsigned)> GenerateIRStr,
|
|
unsigned NumInstrs = 0u) {
|
|
std::string IRStr = GenerateIRStr(NumInstrs);
|
|
LLVMM = parseIR(LLVMCtx, IRStr.c_str());
|
|
llvm::Function *LLVMF = &*LLVMM->getFunction("foo");
|
|
llvm::BasicBlock *LLVMBB = &*LLVMF->begin();
|
|
|
|
sandboxir::Function *F = Ctx.createFunction(LLVMF);
|
|
sandboxir::BasicBlock *BB = &*F->begin();
|
|
// Start tracking if we are testing with tracking enabled.
|
|
if constexpr (IRTy == IR::SBoxTracking)
|
|
Ctx.save();
|
|
|
|
if constexpr (IRTy == IR::LLVM)
|
|
return LLVMBB;
|
|
else
|
|
return BB;
|
|
}
|
|
|
|
template <IR IRTy> static void finalize(sandboxir::Context &Ctx) {
|
|
// Accept changes if we are tracking.
|
|
if constexpr (IRTy == IR::SBoxTracking)
|
|
Ctx.accept();
|
|
}
|
|
|
|
static std::string generateBBWalkIR(unsigned Size) {
|
|
std::stringstream SS;
|
|
SS << "define void @foo(i32 %v1, i32 %v2) {\n";
|
|
for (auto Cnt : seq<unsigned>(0, Size))
|
|
SS << " %add" << Cnt << " = add i32 %v1, %v2\n";
|
|
SS << "ret void";
|
|
SS << "}";
|
|
return SS.str();
|
|
}
|
|
|
|
template <IR IRTy> static void SBoxIRCreation(benchmark::State &State) {
|
|
static_assert(IRTy != IR::LLVM, "Expected SBoxTracking or SBoxNoTracking");
|
|
LLVMContext LLVMCtx;
|
|
unsigned NumInstrs = State.range(0);
|
|
std::unique_ptr<llvm::Module> LLVMM;
|
|
std::string IRStr = generateBBWalkIR(NumInstrs);
|
|
LLVMM = parseIR(LLVMCtx, IRStr.c_str());
|
|
llvm::Function *LLVMF = &*LLVMM->getFunction("foo");
|
|
|
|
for (auto _ : State) {
|
|
State.PauseTiming();
|
|
sandboxir::Context Ctx(LLVMCtx);
|
|
if constexpr (IRTy == IR::SBoxTracking)
|
|
Ctx.save();
|
|
State.ResumeTiming();
|
|
|
|
sandboxir::Function *F = Ctx.createFunction(LLVMF);
|
|
benchmark::DoNotOptimize(F);
|
|
State.PauseTiming();
|
|
if constexpr (IRTy == IR::SBoxTracking)
|
|
Ctx.accept();
|
|
State.ResumeTiming();
|
|
}
|
|
}
|
|
|
|
template <IR IRTy> static void BBWalk(benchmark::State &State) {
|
|
LLVMContext LLVMCtx;
|
|
sandboxir::Context Ctx(LLVMCtx);
|
|
unsigned NumInstrs = State.range(0);
|
|
std::unique_ptr<llvm::Module> LLVMM;
|
|
auto *BB = genIR<IRTy>(LLVMM, LLVMCtx, Ctx, generateBBWalkIR, NumInstrs);
|
|
for (auto _ : State) {
|
|
// Walk LLVM Instructions.
|
|
for (auto &I : *BB)
|
|
benchmark::DoNotOptimize(I);
|
|
}
|
|
}
|
|
|
|
static std::string generateGetTypeIR(unsigned Size) {
|
|
return R"IR(
|
|
define void @foo(i32 %v1, i32 %v2) {
|
|
%add = add i32 %v1, %v2
|
|
ret void
|
|
}
|
|
)IR";
|
|
}
|
|
|
|
template <IR IRTy> static void GetType(benchmark::State &State) {
|
|
LLVMContext LLVMCtx;
|
|
sandboxir::Context Ctx(LLVMCtx);
|
|
std::unique_ptr<llvm::Module> LLVMM;
|
|
auto *BB = genIR<IRTy>(LLVMM, LLVMCtx, Ctx, generateGetTypeIR);
|
|
auto *I = &*BB->begin();
|
|
for (auto _ : State)
|
|
benchmark::DoNotOptimize(I->getType());
|
|
}
|
|
|
|
static std::string generateRAUWIR(unsigned Size) {
|
|
std::stringstream SS;
|
|
SS << "define void @foo(i32 %v1, i32 %v2) {\n";
|
|
SS << " %def1 = add i32 %v1, %v2\n";
|
|
SS << " %def2 = add i32 %v1, %v2\n";
|
|
for (auto Cnt : seq<unsigned>(0, Size))
|
|
SS << " %add" << Cnt << " = add i32 %def1, %def1\n";
|
|
SS << "ret void";
|
|
SS << "}";
|
|
return SS.str();
|
|
}
|
|
|
|
template <IR IRTy> static void RAUW(benchmark::State &State) {
|
|
LLVMContext LLVMCtx;
|
|
sandboxir::Context Ctx(LLVMCtx);
|
|
std::unique_ptr<llvm::Module> LLVMM;
|
|
unsigned NumInstrs = State.range(0);
|
|
auto *BB = genIR<IRTy>(LLVMM, LLVMCtx, Ctx, generateRAUWIR, NumInstrs);
|
|
auto It = BB->begin();
|
|
auto *Def1 = &*It++;
|
|
auto *Def2 = &*It++;
|
|
for (auto _ : State) {
|
|
Def1->replaceAllUsesWith(Def2);
|
|
Def2->replaceAllUsesWith(Def1);
|
|
}
|
|
finalize<IRTy>(Ctx);
|
|
}
|
|
|
|
static std::string generateRUOWIR(unsigned NumOperands) {
|
|
std::stringstream SS;
|
|
auto GenOps = [&SS, NumOperands]() {
|
|
for (auto Cnt : seq<unsigned>(0, NumOperands)) {
|
|
SS << "i8 %arg" << Cnt;
|
|
bool IsLast = Cnt + 1 == NumOperands;
|
|
if (!IsLast)
|
|
SS << ", ";
|
|
}
|
|
};
|
|
|
|
SS << "define void @foo(";
|
|
GenOps();
|
|
SS << ") {\n";
|
|
|
|
SS << " call void @foo(";
|
|
GenOps();
|
|
SS << ")\n";
|
|
SS << "ret void";
|
|
SS << "}";
|
|
return SS.str();
|
|
}
|
|
|
|
template <IR IRTy> static void RUOW(benchmark::State &State) {
|
|
LLVMContext LLVMCtx;
|
|
sandboxir::Context Ctx(LLVMCtx);
|
|
std::unique_ptr<llvm::Module> LLVMM;
|
|
unsigned NumOperands = State.range(0);
|
|
auto *BB = genIR<IRTy>(LLVMM, LLVMCtx, Ctx, generateRUOWIR, NumOperands);
|
|
|
|
auto It = BB->begin();
|
|
auto *F = BB->getParent();
|
|
auto *Arg0 = F->getArg(0);
|
|
auto *Arg1 = F->getArg(1);
|
|
auto *Call = &*It++;
|
|
for (auto _ : State)
|
|
Call->replaceUsesOfWith(Arg0, Arg1);
|
|
finalize<IRTy>(Ctx);
|
|
}
|
|
|
|
// Measure the time it takes to create Sandbox IR without/with tracking.
|
|
BENCHMARK(SBoxIRCreation<IR::SBoxNoTracking>)
|
|
->Args({10})
|
|
->Args({100})
|
|
->Args({1000});
|
|
BENCHMARK(SBoxIRCreation<IR::SBoxTracking>)
|
|
->Args({10})
|
|
->Args({100})
|
|
->Args({1000});
|
|
|
|
BENCHMARK(GetType<IR::LLVM>);
|
|
BENCHMARK(GetType<IR::SBoxNoTracking>);
|
|
|
|
BENCHMARK(BBWalk<IR::LLVM>)->Args({1024});
|
|
BENCHMARK(BBWalk<IR::SBoxTracking>)->Args({1024});
|
|
|
|
BENCHMARK(RAUW<IR::LLVM>)->Args({512});
|
|
BENCHMARK(RAUW<IR::SBoxNoTracking>)->Args({512});
|
|
BENCHMARK(RAUW<IR::SBoxTracking>)->Args({512});
|
|
|
|
BENCHMARK(RUOW<IR::LLVM>)->Args({4096});
|
|
BENCHMARK(RUOW<IR::SBoxNoTracking>)->Args({4096});
|
|
BENCHMARK(RUOW<IR::SBoxTracking>)->Args({4096});
|
|
|
|
BENCHMARK_MAIN();
|