1 //===- SandboxIRBench.cpp -------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // These tests measure the performance of some core SandboxIR functions and
10 // compare them against LLVM IR.
12 //===----------------------------------------------------------------------===//
14 #include "benchmark/benchmark.h"
15 #include "llvm/AsmParser/Parser.h"
16 #include "llvm/IR/BasicBlock.h"
17 #include "llvm/IR/DataLayout.h"
18 #include "llvm/IR/Function.h"
19 #include "llvm/IR/Instruction.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/SandboxIR/Function.h"
22 #include "llvm/SandboxIR/Instruction.h"
23 #include "llvm/SandboxIR/Module.h"
24 #include "llvm/Support/SourceMgr.h"
30 static std::unique_ptr
<Module
> parseIR(LLVMContext
&C
, const char *IR
) {
32 std::unique_ptr
<Module
> M
= parseAssemblyString(IR
, Err
, C
);
34 Err
.print("SandboxIRBench", errs());
40 SBoxNoTracking
, ///> Sandbox IR with tracking disabled
41 SBoxTracking
, ///> Sandbox IR with tracking enabled
43 // Traits to get llvm::BasicBlock/sandboxir::BasicBlock from IR::LLVM/IR::SBox.
44 template <IR IRTy
> struct TypeSelect
{};
45 template <> struct TypeSelect
<IR::LLVM
> {
46 using BasicBlock
= llvm::BasicBlock
;
48 template <> struct TypeSelect
<IR::SBoxNoTracking
> {
49 using BasicBlock
= sandboxir::BasicBlock
;
51 template <> struct TypeSelect
<IR::SBoxTracking
> {
52 using BasicBlock
= sandboxir::BasicBlock
;
56 static typename TypeSelect
<IRTy
>::BasicBlock
*
57 genIR(std::unique_ptr
<llvm::Module
> &LLVMM
, LLVMContext
&LLVMCtx
,
58 sandboxir::Context
&Ctx
,
59 std::function
<std::string(unsigned)> GenerateIRStr
,
60 unsigned NumInstrs
= 0u) {
61 std::string IRStr
= GenerateIRStr(NumInstrs
);
62 LLVMM
= parseIR(LLVMCtx
, IRStr
.c_str());
63 llvm::Function
*LLVMF
= &*LLVMM
->getFunction("foo");
64 llvm::BasicBlock
*LLVMBB
= &*LLVMF
->begin();
66 sandboxir::Function
*F
= Ctx
.createFunction(LLVMF
);
67 sandboxir::BasicBlock
*BB
= &*F
->begin();
68 // Start tracking if we are testing with tracking enabled.
69 if constexpr (IRTy
== IR::SBoxTracking
)
72 if constexpr (IRTy
== IR::LLVM
)
78 template <IR IRTy
> static void finalize(sandboxir::Context
&Ctx
) {
79 // Accept changes if we are tracking.
80 if constexpr (IRTy
== IR::SBoxTracking
)
84 static std::string
generateBBWalkIR(unsigned Size
) {
86 SS
<< "define void @foo(i32 %v1, i32 %v2) {\n";
87 for (auto Cnt
: seq
<unsigned>(0, Size
))
88 SS
<< " %add" << Cnt
<< " = add i32 %v1, %v2\n";
94 template <IR IRTy
> static void SBoxIRCreation(benchmark::State
&State
) {
95 static_assert(IRTy
!= IR::LLVM
, "Expected SBoxTracking or SBoxNoTracking");
97 unsigned NumInstrs
= State
.range(0);
98 std::unique_ptr
<llvm::Module
> LLVMM
;
99 std::string IRStr
= generateBBWalkIR(NumInstrs
);
100 LLVMM
= parseIR(LLVMCtx
, IRStr
.c_str());
101 llvm::Function
*LLVMF
= &*LLVMM
->getFunction("foo");
103 for (auto _
: State
) {
105 sandboxir::Context
Ctx(LLVMCtx
);
106 if constexpr (IRTy
== IR::SBoxTracking
)
108 State
.ResumeTiming();
110 sandboxir::Function
*F
= Ctx
.createFunction(LLVMF
);
111 benchmark::DoNotOptimize(F
);
113 if constexpr (IRTy
== IR::SBoxTracking
)
115 State
.ResumeTiming();
119 template <IR IRTy
> static void BBWalk(benchmark::State
&State
) {
121 sandboxir::Context
Ctx(LLVMCtx
);
122 unsigned NumInstrs
= State
.range(0);
123 std::unique_ptr
<llvm::Module
> LLVMM
;
124 auto *BB
= genIR
<IRTy
>(LLVMM
, LLVMCtx
, Ctx
, generateBBWalkIR
, NumInstrs
);
125 for (auto _
: State
) {
126 // Walk LLVM Instructions.
128 benchmark::DoNotOptimize(I
);
132 static std::string
generateGetTypeIR(unsigned Size
) {
134 define void @foo(i32 %v1, i32 %v2) {
135 %add = add i32 %v1, %v2
141 template <IR IRTy
> static void GetType(benchmark::State
&State
) {
143 sandboxir::Context
Ctx(LLVMCtx
);
144 std::unique_ptr
<llvm::Module
> LLVMM
;
145 auto *BB
= genIR
<IRTy
>(LLVMM
, LLVMCtx
, Ctx
, generateGetTypeIR
);
146 auto *I
= &*BB
->begin();
148 benchmark::DoNotOptimize(I
->getType());
151 static std::string
generateRAUWIR(unsigned Size
) {
152 std::stringstream SS
;
153 SS
<< "define void @foo(i32 %v1, i32 %v2) {\n";
154 SS
<< " %def1 = add i32 %v1, %v2\n";
155 SS
<< " %def2 = add i32 %v1, %v2\n";
156 for (auto Cnt
: seq
<unsigned>(0, Size
))
157 SS
<< " %add" << Cnt
<< " = add i32 %def1, %def1\n";
163 template <IR IRTy
> static void RAUW(benchmark::State
&State
) {
165 sandboxir::Context
Ctx(LLVMCtx
);
166 std::unique_ptr
<llvm::Module
> LLVMM
;
167 unsigned NumInstrs
= State
.range(0);
168 auto *BB
= genIR
<IRTy
>(LLVMM
, LLVMCtx
, Ctx
, generateRAUWIR
, NumInstrs
);
169 auto It
= BB
->begin();
172 for (auto _
: State
) {
173 Def1
->replaceAllUsesWith(Def2
);
174 Def2
->replaceAllUsesWith(Def1
);
179 static std::string
generateRUOWIR(unsigned NumOperands
) {
180 std::stringstream SS
;
181 auto GenOps
= [&SS
, NumOperands
]() {
182 for (auto Cnt
: seq
<unsigned>(0, NumOperands
)) {
183 SS
<< "i8 %arg" << Cnt
;
184 bool IsLast
= Cnt
+ 1 == NumOperands
;
190 SS
<< "define void @foo(";
194 SS
<< " call void @foo(";
202 template <IR IRTy
> static void RUOW(benchmark::State
&State
) {
204 sandboxir::Context
Ctx(LLVMCtx
);
205 std::unique_ptr
<llvm::Module
> LLVMM
;
206 unsigned NumOperands
= State
.range(0);
207 auto *BB
= genIR
<IRTy
>(LLVMM
, LLVMCtx
, Ctx
, generateRUOWIR
, NumOperands
);
209 auto It
= BB
->begin();
210 auto *F
= BB
->getParent();
211 auto *Arg0
= F
->getArg(0);
212 auto *Arg1
= F
->getArg(1);
215 Call
->replaceUsesOfWith(Arg0
, Arg1
);
219 // Measure the time it takes to create Sandbox IR without/with tracking.
220 BENCHMARK(SBoxIRCreation
<IR::SBoxNoTracking
>)
224 BENCHMARK(SBoxIRCreation
<IR::SBoxTracking
>)
229 BENCHMARK(GetType
<IR::LLVM
>);
230 BENCHMARK(GetType
<IR::SBoxNoTracking
>);
232 BENCHMARK(BBWalk
<IR::LLVM
>)->Args({1024});
233 BENCHMARK(BBWalk
<IR::SBoxTracking
>)->Args({1024});
235 BENCHMARK(RAUW
<IR::LLVM
>)->Args({512});
236 BENCHMARK(RAUW
<IR::SBoxNoTracking
>)->Args({512});
237 BENCHMARK(RAUW
<IR::SBoxTracking
>)->Args({512});
239 BENCHMARK(RUOW
<IR::LLVM
>)->Args({4096});
240 BENCHMARK(RUOW
<IR::SBoxNoTracking
>)->Args({4096});
241 BENCHMARK(RUOW
<IR::SBoxTracking
>)->Args({4096});