[mlir][int-range] Limit xor int range inference to i1 (#116968)
[llvm-project.git] / llvm / benchmarks / SandboxIRBench.cpp
blob45f352697868be09e89fe5046b90ed215880bccf
1 //===- SandboxIRBench.cpp -------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
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"
25 #include <memory>
26 #include <sstream>
28 using namespace llvm;
30 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
31 SMDiagnostic Err;
32 std::unique_ptr<Module> M = parseAssemblyString(IR, Err, C);
33 if (!M)
34 Err.print("SandboxIRBench", errs());
35 return M;
38 enum class IR {
39 LLVM, ///> LLVM IR
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;
55 template <IR IRTy>
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)
70 Ctx.save();
72 if constexpr (IRTy == IR::LLVM)
73 return LLVMBB;
74 else
75 return BB;
78 template <IR IRTy> static void finalize(sandboxir::Context &Ctx) {
79 // Accept changes if we are tracking.
80 if constexpr (IRTy == IR::SBoxTracking)
81 Ctx.accept();
84 static std::string generateBBWalkIR(unsigned Size) {
85 std::stringstream SS;
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";
89 SS << "ret void";
90 SS << "}";
91 return SS.str();
94 template <IR IRTy> static void SBoxIRCreation(benchmark::State &State) {
95 static_assert(IRTy != IR::LLVM, "Expected SBoxTracking or SBoxNoTracking");
96 LLVMContext LLVMCtx;
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) {
104 State.PauseTiming();
105 sandboxir::Context Ctx(LLVMCtx);
106 if constexpr (IRTy == IR::SBoxTracking)
107 Ctx.save();
108 State.ResumeTiming();
110 sandboxir::Function *F = Ctx.createFunction(LLVMF);
111 benchmark::DoNotOptimize(F);
112 State.PauseTiming();
113 if constexpr (IRTy == IR::SBoxTracking)
114 Ctx.accept();
115 State.ResumeTiming();
119 template <IR IRTy> static void BBWalk(benchmark::State &State) {
120 LLVMContext LLVMCtx;
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.
127 for (auto &I : *BB)
128 benchmark::DoNotOptimize(I);
132 static std::string generateGetTypeIR(unsigned Size) {
133 return R"IR(
134 define void @foo(i32 %v1, i32 %v2) {
135 %add = add i32 %v1, %v2
136 ret void
138 )IR";
141 template <IR IRTy> static void GetType(benchmark::State &State) {
142 LLVMContext LLVMCtx;
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();
147 for (auto _ : State)
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";
158 SS << "ret void";
159 SS << "}";
160 return SS.str();
163 template <IR IRTy> static void RAUW(benchmark::State &State) {
164 LLVMContext LLVMCtx;
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();
170 auto *Def1 = &*It++;
171 auto *Def2 = &*It++;
172 for (auto _ : State) {
173 Def1->replaceAllUsesWith(Def2);
174 Def2->replaceAllUsesWith(Def1);
176 finalize<IRTy>(Ctx);
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;
185 if (!IsLast)
186 SS << ", ";
190 SS << "define void @foo(";
191 GenOps();
192 SS << ") {\n";
194 SS << " call void @foo(";
195 GenOps();
196 SS << ")\n";
197 SS << "ret void";
198 SS << "}";
199 return SS.str();
202 template <IR IRTy> static void RUOW(benchmark::State &State) {
203 LLVMContext LLVMCtx;
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);
213 auto *Call = &*It++;
214 for (auto _ : State)
215 Call->replaceUsesOfWith(Arg0, Arg1);
216 finalize<IRTy>(Ctx);
219 // Measure the time it takes to create Sandbox IR without/with tracking.
220 BENCHMARK(SBoxIRCreation<IR::SBoxNoTracking>)
221 ->Args({10})
222 ->Args({100})
223 ->Args({1000});
224 BENCHMARK(SBoxIRCreation<IR::SBoxTracking>)
225 ->Args({10})
226 ->Args({100})
227 ->Args({1000});
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});
243 BENCHMARK_MAIN();