Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
LLVM-EXEGESIS(1)		      LLVM			LLVM-EXEGESIS(1)

NAME
     llvm-exegesis - LLVM Machine Instruction Benchmark

SYNOPSIS
     llvm-exegesis [options]

DESCRIPTION
     llvm-exegesis  is	a  benchmarking  tool that uses information available in
     LLVM to measure host  machine  instruction  characteristics  like	latency,
     throughput, or port decomposition.

     Given  an LLVM opcode name and a benchmarking mode, llvm-exegesis generates
     a code snippet that makes execution as serial (resp. as parallel) as possi-
     ble so that we can measure the latency (resp. inverse throughput/uop decom-
     position) of the instruction.  The code snippet is jitted and,  unless  re-
     quested  not  to, executed on the host subtarget. The time taken (resp. re-
     source usage) is measured using hardware performance counters.  The  result
     is printed out as YAML to the standard output.

     The  main	goal  of  this	tool is to automatically (in)validate the LLVM's
     TableDef scheduling models. To that end, we also provide  analysis  of  the
     results.

     llvm-exegesis can also benchmark arbitrary user-provided code snippets.

SUPPORTED PLATFORMS
     llvm-exegesis  currently  only  supports  X86  (64-bit  only), ARM (AArch64
     only), MIPS, and PowerPC (PowerPC64LE only) on Linux for benchmarking.  Not
     all  benchmarking	functionality  is  guaranteed to work on every platform.
     llvm-exegesis also has a separate analysis mode that is supported on  every
     platform that LLVM is.

SNIPPET ANNOTATIONS
     llvm-exegesis  supports  benchmarking arbitrary snippets of assembly.  How-
     ever, benchmarking these snippets often requires some setup  so  that  they
     can  execute  properly.  llvm-exegesis  has five annotations and some addi-
     tional utilities to help with setup so that  snippets  can  be  benchmarked
     properly.

     * LLVM-EXEGESIS-DEFREG <register name> - Adding this annotation to the text
       assembly snippet to be benchmarked marks the register as requiring a def-
       inition.   A value will automatically be provided unless a second parame-
       ter, a hex value, is passed in. This is done with  the  LLVM-EXEGESIS-DE-
       FREG  <register	name>  <hex  value> format. <hex value> is a bit pattern
       used to fill the register. If it is a value smaller than the register, it
       is sign extended to match the size of the register.

     * LLVM-EXEGESIS-LIVEIN <register name> - This annotation allows  specifying
       registers  that should keep their value upon starting the benchmark. Val-
       ues can be passed through registers from the benchmarking setup	in  some
       cases.	The  registers	and the values assigned to them that can be uti-
       lized in the benchmarking script with a LLVM-EXEGESIS-LIVEIN are as  fol-
       lows:

       * Scratch  memory register - The specific register that this value is put
	 in is platform dependent (e.g., it is the RDI register on  X86  Linux).
	 Setting this register as a live in ensures that a pointer to a block of
	 memory  (1MB)	is  placed  within this register that can be used by the
	 snippet.

     * LLVM-EXEGESIS-MEM-DEF <value name> <size> <value> - This  annotation  al-
       lows specifying memory definitions that can later be mapped into the exe-
       cution  process	of  a snippet with the LLVM-EXEGESIS-MEM-MAP annotation.
       Each value is named using the <value name> argument so  that  it  can  be
       referenced later within a map annotation. The size is specified in a dec-
       imal  number  of bytes and the value is given in hexadecimal. If the size
       of the value is less than the specified size, the value will be	repeated
       until  it  fills  the entire section of memory. Using this annotation re-
       quires using the subprocess execution mode.

     * LLVM-EXEGESIS-MEM-MAP <value name> <address> - This annotation allows for
       mapping previously defined memory definitions into the execution  context
       of a process. The value name refers to a previously defined memory defin-
       ition  and the address is a decimal number that specifies the address the
       memory definition should start at. Note that a single  memory  definition
       can  be	mapped	multiple  times. Using this annotation requires the sub-
       process execution mode.

     * LLVM-EXEGESIS-SNIPPET-ADDRESS <address> - This annotation allows for set-
       ting the address where the beginning of the snippet to be  executed  will
       be mapped in at. The address is given in hexadecimal. Note that the snip-
       pet also includes setup code, so the instruction exactly at the specified
       address	will not be the first instruction in the snippet. Using this an-
       notation requires the subprocess execution mode. This is useful in  cases
       where  the  memory accessed by the snippet depends on the location of the
       snippet, like RIP-relative addressing.

     * LLVM-EXEGESIS-LOOP-REGISTER <register name> - This  annotation  specifies
       the  loop register to use for keeping track of the current iteration when
       using the loop repetition mode. llvm-exegesis needs to keep track of  the
       current	loop  iteration  within the loop repetition mode in a performant
       manner (i.e., no memory accesses), and uses a register to do  this.  This
       register has an architecture specific default (e.g., R8 on X86), but this
       might  conflict	with  some snippets. This annotation allows changing the
       register to prevent interference between the loop index register and  the
       snippet.

EXAMPLE 1: BENCHMARKING INSTRUCTIONS
     Assume  you  have an X86-64 machine. To measure the latency of a single in-
     struction, run:

	$ llvm-exegesis --mode=latency --opcode-name=ADD64rr

     Measuring the uop decomposition or inverse  throughput  of  an  instruction
     works similarly:

	$ llvm-exegesis --mode=uops --opcode-name=ADD64rr
	$ llvm-exegesis --mode=inverse_throughput --opcode-name=ADD64rr

     The  output  is a YAML document (the default is to write to stdout, but you
     can redirect the output to a file using --benchmarks-file):

	---
	key:
	  opcode_name:	   ADD64rr
	  mode: 	   latency
	  config:	   ''
	cpu_name:	 haswell
	llvm_triple:	 x86_64-unknown-linux-gnu
	num_repetitions: 10000
	measurements:
	  - { key: latency, value: 1.0058, debug_string: '' }
	error:		 ''
	info:		 'explicit self cycles, selecting one aliasing configuration.
	Snippet:
	ADD64rr R8, R8, R10
	'
	...

     To measure the latency of all instructions for the host architecture, run:

	$ llvm-exegesis --mode=latency --opcode-index=-1

EXAMPLE 2: BENCHMARKING A CUSTOM CODE SNIPPET
     To measure the latency/uops of a custom piece of code, you can specify  the
     snippets-file option (- reads from standard input).

	$ echo "vzeroupper" | llvm-exegesis --mode=uops --snippets-file=-

     Real-life code snippets typically depend on registers or memory.  llvm-exe-
     gesis  checks the liveliness of registers (i.e. any register use has a cor-
     responding def or is a "live in"). If your code depends  on  the  value  of
     some registers, you need to use snippet annotations to ensure setup is per-
     formed properly.

     For  example,  the  following  code  snippet  depends on the values of XMM1
     (which will be set by the tool) and the memory buffer passed in  RDI  (live
     in).

	# LLVM-EXEGESIS-LIVEIN RDI
	# LLVM-EXEGESIS-DEFREG XMM1 42
	vmulps	      (%rdi), %xmm1, %xmm2
	vhaddps       %xmm2, %xmm2, %xmm3
	addq $0x10, %rdi

EXAMPLE 3: BENCHMARKING WITH MEMORY ANNOTATIONS
     Some  snippets  require  memory setup in specific places to execute without
     crashing. Setting up  memory  can	be  accomplished  with	the  LLVM-EXEGE-
     SIS-MEM-DEF and LLVM-EXEGESIS-MEM-MAP annotations. To execute the following
     snippet:

	movq $8192, %rax
	movq (%rax), %rdi

     We  need  to have at least eight bytes of memory allocated starting 0x2000.
     We can create the necessary execution environment with the following  anno-
     tations added to the snippet:

	# LLVM-EXEGESIS-MEM-DEF test1 4096 7fffffff
	# LLVM-EXEGESIS-MEM-MAP test1 8192

	movq $8192, %rax
	movq (%rax), %rdi

EXAMPLE 4: ANALYSIS
     Assuming  you  have  a  set  of benchmarked instructions (either latency or
     uops) as YAML in file /tmp/benchmarks.yaml, you can analyze the results us-
     ing the following command:

	  $ llvm-exegesis --mode=analysis \
	--benchmarks-file=/tmp/benchmarks.yaml \
	--analysis-clusters-output-file=/tmp/clusters.csv \
	--analysis-inconsistencies-output-file=/tmp/inconsistencies.html

     This will group the instructions into clusters with  the  same  performance
     characteristics.  The  clusters will be written out to /tmp/clusters.csv in
     the following format:

	cluster_id,opcode_name,config,sched_class
	...
	2,ADD32ri8_DB,,WriteALU,1.00
	2,ADD32ri_DB,,WriteALU,1.01
	2,ADD32rr,,WriteALU,1.01
	2,ADD32rr_DB,,WriteALU,1.00
	2,ADD32rr_REV,,WriteALU,1.00
	2,ADD64i32,,WriteALU,1.01
	2,ADD64ri32,,WriteALU,1.01
	2,MOVSX64rr32,,BSWAP32r_BSWAP64r_MOVSX64rr32,1.00
	2,VPADDQYrr,,VPADDBYrr_VPADDDYrr_VPADDQYrr_VPADDWYrr_VPSUBBYrr_VPSUBDYrr_VPSUBQYrr_VPSUBWYrr,1.02
	2,VPSUBQYrr,,VPADDBYrr_VPADDDYrr_VPADDQYrr_VPADDWYrr_VPSUBBYrr_VPSUBDYrr_VPSUBQYrr_VPSUBWYrr,1.01
	2,ADD64ri8,,WriteALU,1.00
	2,SETBr,,WriteSETCC,1.01
	...

     llvm-exegesis will also analyze the clusters to point  out  inconsistencies
     in  the  scheduling  information.	The output is an html file. For example,
     /tmp/inconsistencies.html will contain messages like the following  :  [im-
     age]

     Note that the scheduling class names will be resolved only when llvm-exege-
     sis  is  compiled in debug mode, else only the class id will be shown. This
     does not invalidate any of the analysis results though.

OPTIONS
     --help
	    Print a summary of command line options.

     --opcode-index=<LLVM opcode index>
	    Specify the opcode to measure, by index. Specifying -1  will  result
	    in	measuring every existing opcode. See example 1 for details.  Ei-
	    ther opcode-index, opcode-name or snippets-file must be set.

     --opcode-name=<opcode name 1>,<opcode name 2>,...
	    Specify the opcode to measure, by name. Several opcodes can be spec-
	    ified as a comma-separated list. See example 1 for details.   Either
	    opcode-index, opcode-name or snippets-file must be set.

     --snippets-file=<filename>
	    Specify  the  custom  code snippet to measure. See example 2 for de-
	    tails.  Either opcode-index, opcode-name or  snippets-file	must  be
	    set.

     --mode=[latency|uops|inverse_throughput|analysis]
	    Specify  the run mode. Note that some modes have additional require-
	    ments and options.

	    latency mode can be  make use of either RDTSC or LBR.   latency[LBR]
	    is	only  available  on  X86  (at least Skylake).  To run in latency
	    mode, a positive value must be specified  for  x86-lbr-sample-period
	    and --repetition-mode=loop.

	    In	analysis  mode,  you  also  need  to specify at least one of the
	    -analysis-clusters-output-file=  and  -analysis-inconsistencies-out-
	    put-file=.

     --benchmark-phase=[prepare-snippet|prepare-and-assemble-snippet|assem-
     ble-measured-code|measure]
	    By	default, when -mode= is specified, the generated snippet will be
	    executed and measured, and that requires that we are running on  the
	    hardware for which the snippet was generated, and that supports per-
	    formance  measurements.   However,	it  is	possible to stop at some
	    stage before measuring. Choices are: * prepare-snippet: Only  gener-
	    ate  the minimal instruction sequence.  * prepare-and-assemble-snip-
	    pet: Same as prepare-snippet, but also dumps an excerpt of	the  se-
	    quence  (hex  encoded).   *  assemble-measured-code:  Same	as  pre-
	    pare-and-assemble-snippet. but also creates the full  sequence  that
	    can  be  dumped  to  a file using --dump-object-to-disk.  * measure:
	    Same as assemble-measured-code, but also runs the measurement.

     --x86-lbr-sample-period=<nBranches/sample>
	    Specify the LBR sampling period - how many branches before we take a
	    sample.  When a positive value is specified for this option and when
	    the mode is latency, we will use LBRs for  measuring.   On	choosing
	    the  "right" sampling period, a small value is preferred, but throt-
	    tling could occur if the sampling is too frequent.	A  prime  number
	    should be used to avoid consistently skipping certain blocks.

     --x86-disable-upper-sse-registers
	    Using  the upper xmm registers (xmm8-xmm15) forces a longer instruc-
	    tion encoding which may put greater pressure on the  frontend  fetch
	    and  decode  stages, potentially reducing the rate that instructions
	    are dispatched to the backend, particularly on older hardware.  Com-
	    paring  baseline  results  with this mode enabled can help determine
	    the effects of the frontend and can be used to improve  latency  and
	    throughput estimates.

     --repetition-mode=[duplicate|loop|min|middle-half-duplicate|mid-
     dle-half-loop]
	    Specify the repetition mode. duplicate will create a large, straight
	    line  basic  block with min-instructions instructions (repeating the
	    snippet min-instructions/snippet size times). loop will, optionally,
	    duplicate  the  snippet  until  the  loop  body  contains  at  least
	    loop-body-size  instructions,  and	then  wrap  the result in a loop
	    which will execute min-instructions instructions (thus,  again,  re-
	    peating  the  snippet min-instructions/snippet size times). The loop
	    mode, especially with loop unrolling tends to better  hide	the  ef-
	    fects  of  the  CPU frontend on architectures that cache decoded in-
	    structions, but consumes a register for counting iterations. If per-
	    forming an analysis over many opcodes, it may be best to instead use
	    the min mode, which will run each other mode, and produce the  mini-
	    mal  measured  result.  The middle half repetition modes will either
	    duplicate or run the snippet in a loop depending upon  the	specific
	    mode.  The middle half repetition modes will run two benchmarks, one
	    twice the length of the first one, and then subtract the  difference
	    between them to get values without overhead.

     --min-instructions=<Number of instructions>
	    Specify  the  target  number of executed instructions. Note that the
	    actual  repetition	count  of  the	snippet  will  be   min-instruc-
	    tions/snippet  size.   Higher  values lead to more accurate measure-
	    ments but lengthen the benchmark.

     --loop-body-size=<Preferred loop body size>
	    Only effective for -repetition-mode=[loop|min].  Instead of  looping
	    over  the snippet directly, first duplicate it so that the loop body
	    contains at least this many instructions. This  potentially  results
	    in	loop  body  being cached in the CPU Op Cache / Loop Cache, which
	    allows to which may have higher throughput than the CPU decoders.

     --max-configs-per-opcode=<value>
	    Specify the maximum configurations that can be  generated  for  each
	    opcode.   By default this is 1, meaning that we assume that a single
	    measurement is enough to characterize an opcode. This might  not  be
	    true  of all instructions: for example, the performance characteris-
	    tics of the LEA instruction on X86 depends on the value of	assigned
	    registers and immediates. Setting a value of -max-configs-per-opcode
	    larger than 1 allows llvm-exegesis to explore more configurations to
	    discover if some register or immediate assignments lead to different
	    performance characteristics.

     --benchmarks-file=</path/to/file>
	    File to read (analysis mode) or write (latency/uops/inverse_through-
	    put modes) benchmark results. "-" uses stdin/stdout.

     --analysis-clusters-output-file=</path/to/file>
	    If	provided,  write  the analysis clusters as CSV to this file. "-"
	    prints to stdout. By default, this analysis is not run.

     --analysis-inconsistencies-output-file=</path/to/file>
	    If non-empty, write inconsistencies found during  analysis	to  this
	    file. - prints to stdout. By default, this analysis is not run.

     --analysis-filter=[all|reg-only|mem-only]
	    By default, all benchmark results are analysed, but sometimes it may
	    be	useful to only look at those that to not involve memory, or vice
	    versa. This option allows to either keep all benchmarks,  or  filter
	    out (ignore) either all the ones that do involve memory (involve in-
	    structions	that  may  read or write to memory), or the opposite, to
	    only keep such benchmarks.

     --analysis-clustering=[dbscan,naive]
	    Specify the clustering algorithm to use. By default DBSCAN	will  be
	    used.   Naive  clustering algorithm is better for doing further work
	    on the -analysis-inconsistencies-output-file= output, it will create
	    one cluster per opcode, and check that the cluster	is  stable  (all
	    points are neighbours).

     --analysis-numpoints=<dbscan numPoints parameter>
	    Specify  the  numPoints  parameters to be used for DBSCAN clustering
	    (analysis mode, DBSCAN only).

     --analysis-clustering-epsilon=<dbscan epsilon parameter>
	    Specify the epsilon  parameter  used  for  clustering  of  benchmark
	    points (analysis mode).

     --analysis-inconsistency-epsilon=<epsilon>
	    Specify the epsilon parameter used for detection of when the cluster
	    is different from the LLVM schedule profile values (analysis mode).

     --analysis-display-unstable-clusters
	    If	there  is more than one benchmark for an opcode, said benchmarks
	    may end up not being clustered into the same cluster if the measured
	    performance characteristics are different. by default all  such  op-
	    codes  are	filtered out.  This flag will instead show only such un-
	    stable opcodes.

     --ignore-invalid-sched-class=false
	    If set, ignore instructions that do not have a  sched  class  (class
	    idx = 0).

     --mtriple=<triple name>
	    Target triple. See -version for available targets.

     --mcpu=<cpu name>
	    If	set, measure the cpu characteristics using the counters for this
	    CPU. This is useful when creating new sched models (the host CPU  is
	    unknown to LLVM).  (-mcpu=help for details)

     --analysis-override-benchmark-triple-and-cpu
	    By	default,  llvm-exegesis  will  analyze	the  benchmarks  for the
	    triple/CPU they were measured for, but if you want to  analyze  them
	    for  some  other combination (specified via -mtriple/-mcpu), you can
	    pass this flag.

     --dump-object-to-disk=true
	    If set,  llvm-exegesis will dump the generated code to  a  temporary
	    file to enable code inspection. Disabled by default.

     --use-dummy-perf-counters
	    If	set,  llvm-exegesis  will not read any real performance counters
	    and return a dummy value instead. This can be used to ensure a snip-
	    pet doesn't crash when hardware performance counters are unavailable
	    and for debugging llvm-exegesis itself.

     --execution-mode=[inprocess,subprocess]
	    This option specifies what execution mode to use. The inprocess exe-
	    cution mode is the default. The subprocess execution mode allows for
	    additional features such as memory annotations but is currently  re-
	    stricted to X86-64 on Linux.

     --benchmark-repeat-count=<repeat-count>
	    This  option  enables  specifying  the number of times to repeat the
	    measurement  when  performing  latency  measurements.  By	default,
	    llvm-exegesis will repeat a latency measurement enough times to bal-
	    ance run-time and noise reduction.

     --validation-counter=[instructions-retired,l1d-cache-load-misses,

     l1d-cache-store-misses,l1i-cache-load-misses,data-tlb-load-misses,

     data-tld-store-misses,instruction-tlb-load-misses]
	    This  option  enables  the use of validation counters, which measure
	    additional microarchitectural events like cache misses  to	validate
	    snippet  execution	conditions.  These events are measured using the
	    perf subsystem in a group with the performance counter used to  mea-
	    sure  the  value  of  interest.  This flag can be specified multiple
	    times to measure multiple events. The maximum number  of  validation
	    counters is platform dependent.

EXIT STATUS
     llvm-exegesis  returns 0 on success. Otherwise, an error message is printed
     to standard error, and the tool returns a non 0 value.

AUTHOR
     Maintained by the LLVM Team (https://llvm.org/).

COPYRIGHT
     2003-2026, LLVM Project

19				   2026-07-30			LLVM-EXEGESIS(1)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=llvm-exegesis&sektion=1&manpath=FreeBSD+Ports+15.1.quarterly>

home | help