llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

125 lines
4.0 KiB
C
Raw Normal View History

//===-- BenchmarkResult.h ---------------------------------------*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Defines classes to represent measurements and serialize/deserialize them to
// Yaml.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H
#define LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H
#include "LlvmState.h"
#include "RegisterValue.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/Support/YAMLTraits.h"
#include <limits>
#include <string>
#include <unordered_map>
#include <vector>
namespace llvm {
class Error;
namespace exegesis {
struct InstructionBenchmarkKey {
// The LLVM opcode name.
std::vector<MCInst> Instructions;
// The initial values of the registers.
std::vector<RegisterValue> RegisterInitialValues;
// An opaque configuration, that can be used to separate several benchmarks of
// the same instruction under different configurations.
std::string Config;
};
struct BenchmarkMeasure {
// A helper to create an unscaled BenchmarkMeasure.
static BenchmarkMeasure Create(std::string Key, double Value) {
return {Key, Value, Value};
}
std::string Key;
// This is the per-instruction value, i.e. measured quantity scaled per
// instruction.
double PerInstructionValue;
// This is the per-snippet value, i.e. measured quantity for one repetition of
// the whole snippet.
double PerSnippetValue;
};
// The result of an instruction benchmark.
struct InstructionBenchmark {
InstructionBenchmarkKey Key;
enum ModeE { Unknown, Latency, Uops, InverseThroughput };
ModeE Mode;
std::string CpuName;
std::string LLVMTriple;
[llvm-exegesis] Opcode stabilization / reclusterization (PR40715) Summary: Given an instruction `Opcode`, we can make benchmarks (measurements) of the instruction characteristics/performance. Then, to facilitate further analysis we group the benchmarks with *similar* characteristics into clusters. Now, this is all not entirely deterministic. Some instructions have variable characteristics, depending on their arguments. And thus, if we do several benchmarks of the same instruction `Opcode`, we may end up with *different* performance characteristics measurements. And when we then do clustering, these several benchmarks of the same instruction `Opcode` may end up being clustered into *different* clusters. This is not great for further analysis. We shall find every `Opcode` with benchmarks not in just one cluster, and move *all* the benchmarks of said `Opcode` into one new unstable cluster per `Opcode`. I have solved this by making `ClusterId` a bit field, adding a `IsUnstable` bit, and introducing `-analysis-display-unstable-clusters` switch to toggle between displaying stable-only clusters and unstable-only clusters. The reclusterization is deterministically stable, produces identical reports between runs. (Or at least that is what i'm seeing, maybe it isn't) Timings/comparisons: old (current trunk/head) {F8303582} ``` $ perf stat -r 25 ./bin/llvm-exegesis -mode=analysis -analysis-epsilon=0.5 -benchmarks-file=/home/lebedevri/PileDriver-Sched/benchmarks-inverse_throughput.yaml -analysis-inconsistencies-output-file=/tmp/clusters-old.html no exegesis target for x86_64-unknown-linux-gnu, using default Parsed 43970 benchmark points Printing sched class consistency analysis results to file '/tmp/clusters-old.html' ... no exegesis target for x86_64-unknown-linux-gnu, using default Parsed 43970 benchmark points Printing sched class consistency analysis results to file '/tmp/clusters-old.html' Performance counter stats for './bin/llvm-exegesis -mode=analysis -analysis-epsilon=0.5 -benchmarks-file=/home/lebedevri/PileDriver-Sched/benchmarks-inverse_throughput.yaml -analysis-inconsistencies-output-file=/tmp/clusters-old.html' (25 runs): 6624.73 msec task-clock # 0.999 CPUs utilized ( +- 0.53% ) 172 context-switches # 25.965 M/sec ( +- 29.89% ) 0 cpu-migrations # 0.042 M/sec ( +- 56.54% ) 31073 page-faults # 4690.754 M/sec ( +- 0.08% ) 26538711696 cycles # 4006230.292 GHz ( +- 0.53% ) (83.31%) 2017496807 stalled-cycles-frontend # 7.60% frontend cycles idle ( +- 0.93% ) (83.32%) 13403650062 stalled-cycles-backend # 50.51% backend cycles idle ( +- 0.33% ) (33.37%) 19770706799 instructions # 0.74 insn per cycle # 0.68 stalled cycles per insn ( +- 0.04% ) (50.04%) 4419821812 branches # 667207369.714 M/sec ( +- 0.03% ) (66.69%) 121741669 branch-misses # 2.75% of all branches ( +- 0.28% ) (83.34%) 6.6283 +- 0.0358 seconds time elapsed ( +- 0.54% ) ``` patch, with reclustering but without filtering (i.e. outputting all the stable *and* unstable clusters) {F8303586} ``` $ perf stat -r 25 ./bin/llvm-exegesis -mode=analysis -analysis-epsilon=0.5 -benchmarks-file=/home/lebedevri/PileDriver-Sched/benchmarks-inverse_throughput.yaml -analysis-inconsistencies-output-file=/tmp/clusters-new-all.html no exegesis target for x86_64-unknown-linux-gnu, using default Parsed 43970 benchmark points Printing sched class consistency analysis results to file '/tmp/clusters-new-all.html' ... no exegesis target for x86_64-unknown-linux-gnu, using default Parsed 43970 benchmark points Printing sched class consistency analysis results to file '/tmp/clusters-new-all.html' Performance counter stats for './bin/llvm-exegesis -mode=analysis -analysis-epsilon=0.5 -benchmarks-file=/home/lebedevri/PileDriver-Sched/benchmarks-inverse_throughput.yaml -analysis-inconsistencies-output-file=/tmp/clusters-new-all.html' (25 runs): 6475.29 msec task-clock # 0.999 CPUs utilized ( +- 0.31% ) 213 context-switches # 32.952 M/sec ( +- 23.81% ) 1 cpu-migrations # 0.130 M/sec ( +- 43.84% ) 31287 page-faults # 4832.057 M/sec ( +- 0.08% ) 25939086577 cycles # 4006160.279 GHz ( +- 0.31% ) (83.31%) 1958812858 stalled-cycles-frontend # 7.55% frontend cycles idle ( +- 0.68% ) (83.32%) 13218961512 stalled-cycles-backend # 50.96% backend cycles idle ( +- 0.29% ) (33.37%) 19752995402 instructions # 0.76 insn per cycle # 0.67 stalled cycles per insn ( +- 0.04% ) (50.04%) 4417079244 branches # 682195472.305 M/sec ( +- 0.03% ) (66.70%) 121510065 branch-misses # 2.75% of all branches ( +- 0.19% ) (83.34%) 6.4832 +- 0.0229 seconds time elapsed ( +- 0.35% ) ``` Funnily, *this* measurement shows that said reclustering actually improved performance. patch, with reclustering, only the stable clusters {F8303594} ``` $ perf stat -r 25 ./bin/llvm-exegesis -mode=analysis -analysis-epsilon=0.5 -benchmarks-file=/home/lebedevri/PileDriver-Sched/benchmarks-inverse_throughput.yaml -analysis-inconsistencies-output-file=/tmp/clusters-new-stable.html no exegesis target for x86_64-unknown-linux-gnu, using default Parsed 43970 benchmark points Printing sched class consistency analysis results to file '/tmp/clusters-new-stable.html' ... no exegesis target for x86_64-unknown-linux-gnu, using default Parsed 43970 benchmark points Printing sched class consistency analysis results to file '/tmp/clusters-new-stable.html' Performance counter stats for './bin/llvm-exegesis -mode=analysis -analysis-epsilon=0.5 -benchmarks-file=/home/lebedevri/PileDriver-Sched/benchmarks-inverse_throughput.yaml -analysis-inconsistencies-output-file=/tmp/clusters-new-stable.html' (25 runs): 6387.71 msec task-clock # 0.999 CPUs utilized ( +- 0.13% ) 133 context-switches # 20.792 M/sec ( +- 23.39% ) 0 cpu-migrations # 0.063 M/sec ( +- 61.24% ) 31318 page-faults # 4903.256 M/sec ( +- 0.08% ) 25591984967 cycles # 4006786.266 GHz ( +- 0.13% ) (83.31%) 1881234904 stalled-cycles-frontend # 7.35% frontend cycles idle ( +- 0.25% ) (83.33%) 13209749965 stalled-cycles-backend # 51.62% backend cycles idle ( +- 0.16% ) (33.36%) 19767554347 instructions # 0.77 insn per cycle # 0.67 stalled cycles per insn ( +- 0.04% ) (50.03%) 4417480305 branches # 691618858.046 M/sec ( +- 0.03% ) (66.68%) 118676358 branch-misses # 2.69% of all branches ( +- 0.07% ) (83.33%) 6.3954 +- 0.0118 seconds time elapsed ( +- 0.18% ) ``` Performance improved even further?! Makes sense i guess, less clusters to print. patch, with reclustering, only the unstable clusters {F8303601} ``` $ perf stat -r 25 ./bin/llvm-exegesis -mode=analysis -analysis-epsilon=0.5 -benchmarks-file=/home/lebedevri/PileDriver-Sched/benchmarks-inverse_throughput.yaml -analysis-inconsistencies-output-file=/tmp/clusters-new-unstable.html -analysis-display-unstable-clusters no exegesis target for x86_64-unknown-linux-gnu, using default Parsed 43970 benchmark points Printing sched class consistency analysis results to file '/tmp/clusters-new-unstable.html' ... no exegesis target for x86_64-unknown-linux-gnu, using default Parsed 43970 benchmark points Printing sched class consistency analysis results to file '/tmp/clusters-new-unstable.html' Performance counter stats for './bin/llvm-exegesis -mode=analysis -analysis-epsilon=0.5 -benchmarks-file=/home/lebedevri/PileDriver-Sched/benchmarks-inverse_throughput.yaml -analysis-inconsistencies-output-file=/tmp/clusters-new-unstable.html -analysis-display-unstable-clusters' (25 runs): 6124.96 msec task-clock # 1.000 CPUs utilized ( +- 0.20% ) 194 context-switches # 31.709 M/sec ( +- 20.46% ) 0 cpu-migrations # 0.039 M/sec ( +- 49.77% ) 31413 page-faults # 5129.261 M/sec ( +- 0.06% ) 24536794267 cycles # 4006425.858 GHz ( +- 0.19% ) (83.31%) 1676085087 stalled-cycles-frontend # 6.83% frontend cycles idle ( +- 0.46% ) (83.32%) 13035595603 stalled-cycles-backend # 53.13% backend cycles idle ( +- 0.16% ) (33.36%) 18260877653 instructions # 0.74 insn per cycle # 0.71 stalled cycles per insn ( +- 0.05% ) (50.03%) 4112411983 branches # 671484364.603 M/sec ( +- 0.03% ) (66.68%) 114066929 branch-misses # 2.77% of all branches ( +- 0.11% ) (83.32%) 6.1278 +- 0.0121 seconds time elapsed ( +- 0.20% ) ``` This tells us that the actual `-analysis-inconsistencies-output-file=` outputting only takes ~0.4 sec for 43970 benchmark points (3 whole sweeps) (Also, wow this is fast, it used to take several minutes originally) Fixes [[ https://bugs.llvm.org/show_bug.cgi?id=40715 | PR40715 ]]. Reviewers: courbet, gchatelet Reviewed By: courbet Subscribers: tschuett, jdoerfert, llvm-commits, RKSimon Tags: #llvm Differential Revision: https://reviews.llvm.org/D58355 llvm-svn: 354441
2019-02-20 17:14:04 +08:00
// Which instruction is being benchmarked here?
const MCInst &keyInstruction() const { return Key.Instructions[0]; }
// The number of instructions inside the repeated snippet. For example, if a
// snippet of 3 instructions is repeated 4 times, this is 12.
[llvm-exegesis] Loop unrolling for loop snippet repetitor mode I really needed this, like, factually, yesterday, when verifying dependency breaking idioms for AMD Zen 3 scheduler model. Consider the following example: ``` $ ./bin/llvm-exegesis --mode=inverse_throughput --snippets-file=/tmp/snippet.s --num-repetitions=1000000 --repetition-mode=duplicate Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-4a7e50.o --- mode: inverse_throughput key: instructions: - 'VPXORYrr YMM0 YMM0 YMM0' config: '' register_initial_values: [] cpu_name: znver3 llvm_triple: x86_64-unknown-linux-gnu num_repetitions: 1000000 measurements: - { key: inverse_throughput, value: 0.31025, per_snippet_value: 0.31025 } error: '' info: '' assembled_snippet: C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C5FDEFC0C3 ... ``` What does it tell us? So wait, it can only execute ~3 x86 AVX YMM PXOR zero-idioms per cycle? That doesn't seem right. That's even less than there are pipes supporting this type of op. Now, second example: ``` $ ./bin/llvm-exegesis --mode=inverse_throughput --snippets-file=/tmp/snippet.s --num-repetitions=1000000 --repetition-mode=loop Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-2418b5.o --- mode: inverse_throughput key: instructions: - 'VPXORYrr YMM0 YMM0 YMM0' config: '' register_initial_values: [] cpu_name: znver3 llvm_triple: x86_64-unknown-linux-gnu num_repetitions: 1000000 measurements: - { key: inverse_throughput, value: 1.00011, per_snippet_value: 1.00011 } error: '' info: '' assembled_snippet: 49B80800000000000000C5FDEFC0C5FDEFC04983C0FF75F2C3 ... ``` Now that's just worse. Due to the looping, the throughput completely plummeted, and now we can only do a single instruction/cycle!? That's not great. And final example: ``` $ ./bin/llvm-exegesis --mode=inverse_throughput --snippets-file=/tmp/snippet.s --num-repetitions=1000000 --repetition-mode=loop --loop-body-size=1000 Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-c402e2.o --- mode: inverse_throughput key: instructions: - 'VPXORYrr YMM0 YMM0 YMM0' config: '' register_initial_values: [] cpu_name: znver3 llvm_triple: x86_64-unknown-linux-gnu num_repetitions: 1000000 measurements: - { key: inverse_throughput, value: 0.167087, per_snippet_value: 0.167087 } error: '' info: '' assembled_snippet: 49B80800000000000000C5FDEFC0C5FDEFC04983C0FF75F2C3 ... ``` So if we merge the previous two approaches, do duplicate this single-instruction snippet 1000x (loop-body-size/instruction count in snippet), and run a loop with 1000 iterations over that duplicated/unrolled snippet, the measured throughput goes through the roof, up to 5.9 instructions/cycle, which finally tells us that this idiom is zero-cycle! Reviewed By: courbet Differential Revision: https://reviews.llvm.org/D102522
2021-05-25 16:48:43 +08:00
unsigned NumRepetitions = 0;
[llvm-exegesis] 'Min' repetition mode Summary: As noted in documentation, different repetition modes have different trade-offs: > .. option:: -repetition-mode=[duplicate|loop] > > Specify the repetition mode. `duplicate` will create a large, straight line > basic block with `num-repetitions` copies of the snippet. `loop` will wrap > the snippet in a loop which will be run `num-repetitions` times. The `loop` > mode tends to better hide the effects of the CPU frontend on architectures > that cache decoded instructions, but consumes a register for counting > iterations. Indeed. Example: >>! In D74156#1873657, @lebedev.ri wrote: > At least for `CMOV`, i'm seeing wildly different results > | | Latency | RThroughput | > | duplicate | 1 | 0.8 | > | loop | 2 | 0.6 | > where latency=1 seems correct, and i'd expect the througput to be close to 1/2 (since there are two execution units). This isn't great for analysis, at least for schedule model development. As discussed in excruciating detail in >>! In D74156#1924514, @gchatelet wrote: >>>! In D74156#1920632, @lebedev.ri wrote: >> ... did that explanation of the question i'm having made any sense? > > Thx for digging in the conversation ! > Ok it makes more sense now. > > I discussed it a bit with @courbet: > - We want the analysis tool to stay simple so we'd rather not make it knowledgeable of the repetition mode. > - We'd like to still be able to select either repetition mode to dig into special cases > > So we could add a third `min` repetition mode that would run both and take the minimum. It could be the default option. > Would you have some time to look what it would take to add this third mode? there appears to be an agreement that it is indeed sub-par, and that we should provide an optional, measurement (not analysis!) -time way to rectify the situation. However, the solutions isn't entirely straight-forward. We can just add an actual 'multiplexer' `MinSnippetRepetitor`, because if we just concatenate snippets produced by `DuplicateSnippetRepetitor` and `LoopSnippetRepetitor` and run+measure that, the measurement will naturally be different from what we'd get by running+measuring them separately and taking the min. ([[ https://www.wolframalpha.com/input/?i=%28x%2By%29%2F2+%21%3D+min%28x%2C+y%29 | `time(D+L)/2 != min(time(D), time(L))` ]]) Also, it seems best to me to have a single snippet instead of generating a snippet per repetition mode, since the only difference here is that the loop repetition mode reserves one register for loop counter. As far as i can tell, we can either teach `BenchmarkRunner::runConfiguration()` to produce a single report given multiple repetitors (as in the patch), or do that one layer higher - don't modify `BenchmarkRunner::runConfiguration()`, produce multiple reports, don't actually print each one, but aggregate them somehow and only print the final one. Initially i've gone ahead with the latter approach, but it didn't look like a natural fit; the former (as in the diff) does seem like a better fit to me. There's also a question of the test coverage. It sure currently does work here: ``` $ ./bin/llvm-exegesis --opcode-name=CMOV64rr --mode=inverse_throughput --repetition-mode=duplicate Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-8fb949.o --- mode: inverse_throughput key: instructions: - 'CMOV64rr RAX RAX R11 i_0x0' - 'CMOV64rr RBP RBP R15 i_0x0' - 'CMOV64rr RBX RBX RBX i_0x0' - 'CMOV64rr RCX RCX RBX i_0x0' - 'CMOV64rr RDI RDI R10 i_0x0' - 'CMOV64rr RDX RDX RAX i_0x0' - 'CMOV64rr RSI RSI RAX i_0x0' - 'CMOV64rr R8 R8 R8 i_0x0' - 'CMOV64rr R9 R9 RDX i_0x0' - 'CMOV64rr R10 R10 RBX i_0x0' - 'CMOV64rr R11 R11 R14 i_0x0' - 'CMOV64rr R12 R12 R9 i_0x0' - 'CMOV64rr R13 R13 R12 i_0x0' - 'CMOV64rr R14 R14 R15 i_0x0' - 'CMOV64rr R15 R15 R13 i_0x0' config: '' register_initial_values: - 'RAX=0x0' - 'R11=0x0' - 'EFLAGS=0x0' - 'RBP=0x0' - 'R15=0x0' - 'RBX=0x0' - 'RCX=0x0' - 'RDI=0x0' - 'R10=0x0' - 'RDX=0x0' - 'RSI=0x0' - 'R8=0x0' - 'R9=0x0' - 'R14=0x0' - 'R12=0x0' - 'R13=0x0' cpu_name: bdver2 llvm_triple: x86_64-unknown-linux-gnu num_repetitions: 10000 measurements: - { key: inverse_throughput, value: 0.819, per_snippet_value: 12.285 } error: '' info: instruction has tied variables, using static renaming. assembled_snippet: 5541574156415541545348B8000000000000000049BB00000000000000004883EC08C7042400000000C7442404000000009D48BD000000000000000049BF000000000000000048BB000000000000000048B9000000000000000048BF000000000000000049BA000000000000000048BA000000000000000048BE000000000000000049B8000000000000000049B9000000000000000049BE000000000000000049BC000000000000000049BD0000000000000000490F40C3490F40EF480F40DB480F40CB490F40FA480F40D0480F40F04D0F40C04C0F40CA4C0F40D34D0F40DE4D0F40E14D0F40EC4D0F40F74D0F40FD490F40C35B415C415D415E415F5DC3 ... $ ./bin/llvm-exegesis --opcode-name=CMOV64rr --mode=inverse_throughput --repetition-mode=loop Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-051eb3.o --- mode: inverse_throughput key: instructions: - 'CMOV64rr RAX RAX R11 i_0x0' - 'CMOV64rr RBP RBP RSI i_0x0' - 'CMOV64rr RBX RBX R9 i_0x0' - 'CMOV64rr RCX RCX RSI i_0x0' - 'CMOV64rr RDI RDI RBP i_0x0' - 'CMOV64rr RDX RDX R9 i_0x0' - 'CMOV64rr RSI RSI RDI i_0x0' - 'CMOV64rr R9 R9 R12 i_0x0' - 'CMOV64rr R10 R10 R11 i_0x0' - 'CMOV64rr R11 R11 R9 i_0x0' - 'CMOV64rr R12 R12 RBP i_0x0' - 'CMOV64rr R13 R13 RSI i_0x0' - 'CMOV64rr R14 R14 R14 i_0x0' - 'CMOV64rr R15 R15 R10 i_0x0' config: '' register_initial_values: - 'RAX=0x0' - 'R11=0x0' - 'EFLAGS=0x0' - 'RBP=0x0' - 'RSI=0x0' - 'RBX=0x0' - 'R9=0x0' - 'RCX=0x0' - 'RDI=0x0' - 'RDX=0x0' - 'R12=0x0' - 'R10=0x0' - 'R13=0x0' - 'R14=0x0' - 'R15=0x0' cpu_name: bdver2 llvm_triple: x86_64-unknown-linux-gnu num_repetitions: 10000 measurements: - { key: inverse_throughput, value: 0.6083, per_snippet_value: 8.5162 } error: '' info: instruction has tied variables, using static renaming. assembled_snippet: 5541574156415541545348B8000000000000000049BB00000000000000004883EC08C7042400000000C7442404000000009D48BD000000000000000048BE000000000000000048BB000000000000000049B9000000000000000048B9000000000000000048BF000000000000000048BA000000000000000049BC000000000000000049BA000000000000000049BD000000000000000049BE000000000000000049BF000000000000000049B80200000000000000490F40C3480F40EE490F40D9480F40CE480F40FD490F40D1480F40F74D0F40CC4D0F40D34D0F40D94C0F40E54C0F40EE4D0F40F64D0F40FA4983C0FF75C25B415C415D415E415F5DC3 ... $ ./bin/llvm-exegesis --opcode-name=CMOV64rr --mode=inverse_throughput --repetition-mode=min Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-c7a47d.o Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-2581f1.o --- mode: inverse_throughput key: instructions: - 'CMOV64rr RAX RAX R11 i_0x0' - 'CMOV64rr RBP RBP R10 i_0x0' - 'CMOV64rr RBX RBX R10 i_0x0' - 'CMOV64rr RCX RCX RDX i_0x0' - 'CMOV64rr RDI RDI RAX i_0x0' - 'CMOV64rr RDX RDX R9 i_0x0' - 'CMOV64rr RSI RSI RAX i_0x0' - 'CMOV64rr R9 R9 RBX i_0x0' - 'CMOV64rr R10 R10 R12 i_0x0' - 'CMOV64rr R11 R11 RDI i_0x0' - 'CMOV64rr R12 R12 RDI i_0x0' - 'CMOV64rr R13 R13 RDI i_0x0' - 'CMOV64rr R14 R14 R9 i_0x0' - 'CMOV64rr R15 R15 RBP i_0x0' config: '' register_initial_values: - 'RAX=0x0' - 'R11=0x0' - 'EFLAGS=0x0' - 'RBP=0x0' - 'R10=0x0' - 'RBX=0x0' - 'RCX=0x0' - 'RDX=0x0' - 'RDI=0x0' - 'R9=0x0' - 'RSI=0x0' - 'R12=0x0' - 'R13=0x0' - 'R14=0x0' - 'R15=0x0' cpu_name: bdver2 llvm_triple: x86_64-unknown-linux-gnu num_repetitions: 10000 measurements: - { key: inverse_throughput, value: 0.6073, per_snippet_value: 8.5022 } error: '' info: instruction has tied variables, using static renaming. assembled_snippet: 5541574156415541545348B8000000000000000049BB00000000000000004883EC08C7042400000000C7442404000000009D48BD000000000000000049BA000000000000000048BB000000000000000048B9000000000000000048BA000000000000000048BF000000000000000049B9000000000000000048BE000000000000000049BC000000000000000049BD000000000000000049BE000000000000000049BF0000000000000000490F40C3490F40EA490F40DA480F40CA480F40F8490F40D1480F40F04C0F40CB4D0F40D44C0F40DF4C0F40E74C0F40EF4D0F40F14C0F40FD490F40C3490F40EA5B415C415D415E415F5DC35541574156415541545348B8000000000000000049BB00000000000000004883EC08C7042400000000C7442404000000009D48BD000000000000000049BA000000000000000048BB000000000000000048B9000000000000000048BA000000000000000048BF000000000000000049B9000000000000000048BE000000000000000049BC000000000000000049BD000000000000000049BE000000000000000049BF000000000000000049B80200000000000000490F40C3490F40EA490F40DA480F40CA480F40F8490F40D1480F40F04C0F40CB4D0F40D44C0F40DF4C0F40E74C0F40EF4D0F40F14C0F40FD4983C0FF75C25B415C415D415E415F5DC3 ... ``` but i open to suggestions as to how test that. I also have gone with the suggestion to default to this new mode. This was irking me for some time, so i'm happy to finally see progress here. Looking forward to feedback. Reviewers: courbet, gchatelet Reviewed By: courbet, gchatelet Subscribers: mstojanovic, RKSimon, llvm-commits, courbet, gchatelet Tags: #llvm Differential Revision: https://reviews.llvm.org/D76921
2020-04-02 14:28:35 +08:00
enum RepetitionModeE { Duplicate, Loop, AggregateMin };
// Note that measurements are per instruction.
std::vector<BenchmarkMeasure> Measurements;
std::string Error;
std::string Info;
std::vector<uint8_t> AssembledSnippet;
// How to aggregate measurements.
enum ResultAggregationModeE { Min, Max, Mean, MinVariance };
// Read functions.
static Expected<InstructionBenchmark> readYaml(const LLVMState &State,
StringRef Filename);
static Expected<std::vector<InstructionBenchmark>>
readYamls(const LLVMState &State, StringRef Filename);
class Error readYamlFrom(const LLVMState &State, StringRef InputContent);
// Write functions, non-const because of YAML traits.
class Error writeYamlTo(const LLVMState &State, raw_ostream &S);
class Error writeYaml(const LLVMState &State, const StringRef Filename);
};
bool operator==(const BenchmarkMeasure &A, const BenchmarkMeasure &B);
//------------------------------------------------------------------------------
// Utilities to work with Benchmark measures.
// A class that measures stats over benchmark measures.
class PerInstructionStats {
public:
void push(const BenchmarkMeasure &BM);
double avg() const {
assert(NumValues);
return SumValues / NumValues;
}
double min() const { return MinValue; }
double max() const { return MaxValue; }
const std::string &key() const { return Key; }
private:
std::string Key;
double SumValues = 0.0;
int NumValues = 0;
double MaxValue = std::numeric_limits<double>::min();
double MinValue = std::numeric_limits<double>::max();
};
} // namespace exegesis
} // namespace llvm
#endif // LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H