diff --git a/llvm/docs/CommandGuide/llvm-exegesis.rst b/llvm/docs/CommandGuide/llvm-exegesis.rst --- a/llvm/docs/CommandGuide/llvm-exegesis.rst +++ b/llvm/docs/CommandGuide/llvm-exegesis.rst @@ -19,9 +19,10 @@ generates a code snippet that makes execution as serial (resp. as parallel) as possible so that we can measure the latency (resp. inverse throughput/uop decomposition) of the instruction. -The code snippet is jitted and executed on the host subtarget. The time taken -(resp. resource usage) is measured using hardware performance counters. The -result is printed out as YAML to the standard output. +The code snippet is jitted and, unless requested not to, executed on the +host subtarget. The time taken (resp. resource 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. @@ -195,6 +196,14 @@ In `analysis` mode, you also need to specify at least one of the `-analysis-clusters-output-file=` and `-analysis-inconsistencies-output-file=`. +.. option:: --dry-run + + 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 performance measurements. + But sometimes, you just want to generate snippets, and this is exactly what + this options allows one to do. + .. option:: -x86-lbr-sample-period= Specify the LBR sampling period - how many branches before we take a sample. diff --git a/llvm/test/tools/llvm-exegesis/AArch64/lit.local.cfg b/llvm/test/tools/llvm-exegesis/AArch64/lit.local.cfg --- a/llvm/test/tools/llvm-exegesis/AArch64/lit.local.cfg +++ b/llvm/test/tools/llvm-exegesis/AArch64/lit.local.cfg @@ -1,7 +1,10 @@ import subprocess import lit.util -if not ('AArch64' in config.root.targets): +if 'native' not in config.available_features: + config.unsupported = True + +elif not ('AArch64' in config.root.targets): # We need support for AArch64. config.unsupported = True diff --git a/llvm/test/tools/llvm-exegesis/Mips/lit.local.cfg b/llvm/test/tools/llvm-exegesis/Mips/lit.local.cfg --- a/llvm/test/tools/llvm-exegesis/Mips/lit.local.cfg +++ b/llvm/test/tools/llvm-exegesis/Mips/lit.local.cfg @@ -1,7 +1,10 @@ import subprocess import lit.util -if not ('Mips' in config.root.targets): +if 'native' not in config.available_features: + config.unsupported = True + +elif not ('Mips' in config.root.targets): # We need support for Mips. config.unsupported = True diff --git a/llvm/test/tools/llvm-exegesis/PowerPC/lit.local.cfg b/llvm/test/tools/llvm-exegesis/PowerPC/lit.local.cfg --- a/llvm/test/tools/llvm-exegesis/PowerPC/lit.local.cfg +++ b/llvm/test/tools/llvm-exegesis/PowerPC/lit.local.cfg @@ -1,7 +1,10 @@ import subprocess import lit.util -if not ('PowerPC' in config.root.targets): +if 'native' not in config.available_features: + config.unsupported = True + +elif not ('PowerPC' in config.root.targets): # We need support for PowerPC. config.unsupported = True diff --git a/llvm/test/tools/llvm-exegesis/X86/analysis-CMOV16rm-noreg-deserialization.test b/llvm/test/tools/llvm-exegesis/X86/analysis-CMOV16rm-noreg-deserialization.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-exegesis/X86/analysis-CMOV16rm-noreg-deserialization.test @@ -0,0 +1,58 @@ +# RUN: llvm-exegesis -mcpu=znver3 -mode=analysis -benchmarks-file=%s -analysis-clusters-output-file=- -analysis-clustering-epsilon=0.1 -analysis-inconsistency-epsilon=0.1 -analysis-numpoints=1 -analysis-clustering=naive | FileCheck -check-prefixes=CHECK-CLUSTERS %s + +# https://bugs.llvm.org/show_bug.cgi?id=41448 +# Verify that deserialization works. Since CMOV16rm has a variant sched class, just printing clusters is sufficient + +--- +mode: uops +key: + instructions: + - 'CMOV16rm AX AX RDI i_0x1 %noreg i_0x0 %noreg i_0x0' + - 'CMOV16rm BP BP RDI i_0x1 %noreg i_0x40 %noreg i_0x0' + - 'CMOV16rm BX BX RDI i_0x1 %noreg i_0x80 %noreg i_0x0' + - 'CMOV16rm CX CX RDI i_0x1 %noreg i_0xc0 %noreg i_0x0' + - 'CMOV16rm DX DX RDI i_0x1 %noreg i_0x100 %noreg i_0x0' + - 'CMOV16rm SI SI RDI i_0x1 %noreg i_0x140 %noreg i_0x0' + - 'CMOV16rm R8W R8W RDI i_0x1 %noreg i_0x180 %noreg i_0x0' + - 'CMOV16rm R9W R9W RDI i_0x1 %noreg i_0x1c0 %noreg i_0x0' + - 'CMOV16rm R10W R10W RDI i_0x1 %noreg i_0x200 %noreg i_0x0' + - 'CMOV16rm R11W R11W RDI i_0x1 %noreg i_0x240 %noreg i_0x0' + - 'CMOV16rm R12W R12W RDI i_0x1 %noreg i_0x280 %noreg i_0x0' + - 'CMOV16rm R13W R13W RDI i_0x1 %noreg i_0x2c0 %noreg i_0x0' + - 'CMOV16rm R14W R14W RDI i_0x1 %noreg i_0x300 %noreg i_0x0' + - 'CMOV16rm R15W R15W RDI i_0x1 %noreg i_0x340 %noreg i_0x0' + config: '' + register_initial_values: + - 'AX=0x0' + - 'EFLAGS=0x0' + - 'BP=0x0' + - 'BX=0x0' + - 'CX=0x0' + - 'DX=0x0' + - 'SI=0x0' + - 'R8W=0x0' + - 'R9W=0x0' + - 'R10W=0x0' + - 'R11W=0x0' + - 'R12W=0x0' + - 'R13W=0x0' + - 'R14W=0x0' + - 'R15W=0x0' +cpu_name: znver3 +llvm_triple: x86_64-pc-linux-gnu +num_repetitions: 10000 +measurements: + - { key: Zn3Int, value: 1.0161, per_snippet_value: 14.2254 } + - { key: Zn3FPU, value: 0, per_snippet_value: 0 } + - { key: Zn3Load, value: 1.003, per_snippet_value: 14.042 } + - { key: Zn3Store, value: 0.0023, per_snippet_value: 0.0322 } + - { key: Zn3Divider, value: 0, per_snippet_value: 0 } + - { key: NumMicroOps, value: 1.0146, per_snippet_value: 14.2044 } +error: '' +info: instruction has tied variables, using static renaming. +assembled_snippet: 5541574156415541545366B800004883EC08C7042400000000C7442404000000009D66BD000066BB000066B9000066BA000066BE00006641B800006641B900006641BA00006641BB00006641BC00006641BD00006641BE00006641BF0000660F4007660F406F40660F409F80000000660F408FC0000000660F409700010000660F40B74001000066440F40878001000066440F408FC001000066440F40970002000066440F409F4002000066440F40A78002000066440F40AFC002000066440F40B70003000066440F40BF40030000660F4007660F406F40660F409F80000000660F408FC0000000660F409700010000660F40B74001000066440F40878001000066440F408FC001000066440F40970002000066440F409F4002000066440F40A78002000066440F40AFC002000066440F40B70003000066440F40BF40030000660F4007660F406F40660F409F80000000660F408FC0000000660F409700010000660F40B74001000066440F40878001000066440F408FC001000066440F40970002000066440F409F4002000066440F40A78002000066440F40AFC002000066440F40B70003000066440F40BF40030000660F4007660F406F40660F409F80000000660F408FC0000000660F409700010000660F40B74001000066440F40878001000066440F408FC001000066440F40970002000066440F409F4002000066440F40A78002000066440F40AFC002000066440F40B70003000066440F40BF400300005B415C415D415E415F5DC3 +... + + +# CHECK-CLUSTERS: {{^}}cluster_id,opcode_name,config,sched_class, +# CHECK-CLUSTERS-NEXT: {{^}}0, diff --git a/llvm/test/tools/llvm-exegesis/X86/inverse_throughput/inverse_throughput-by-opcode-name.s b/llvm/test/tools/llvm-exegesis/X86/inverse_throughput/inverse_throughput-by-opcode-name.s --- a/llvm/test/tools/llvm-exegesis/X86/inverse_throughput/inverse_throughput-by-opcode-name.s +++ b/llvm/test/tools/llvm-exegesis/X86/inverse_throughput/inverse_throughput-by-opcode-name.s @@ -1,9 +1,8 @@ -# RUN: llvm-exegesis -mode=inverse_throughput -opcode-name=ADD32rr -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=inverse_throughput -opcode-name=ADD32rr -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=inverse_throughput --dry-run -opcode-name=ADD32rr -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=inverse_throughput --dry-run -opcode-name=ADD32rr -repetition-mode=loop | FileCheck %s CHECK: --- CHECK-NEXT: mode: inverse_throughput CHECK-NEXT: key: CHECK-NEXT: instructions: CHECK-NEXT: ADD32rr -CHECK: key: inverse_throughput diff --git a/llvm/test/tools/llvm-exegesis/X86/inverse_throughput/lit.local.cfg b/llvm/test/tools/llvm-exegesis/X86/inverse_throughput/lit.local.cfg deleted file mode 100644 --- a/llvm/test/tools/llvm-exegesis/X86/inverse_throughput/lit.local.cfg +++ /dev/null @@ -1,29 +0,0 @@ -import subprocess -import lit.util - -if not ('X86' in config.root.targets): - # We need support for X86. - config.unsupported = True - -elif not ('x86_64' in config.root.host_triple): - # We need to be running on an X86 host. - config.unsupported = True - -else: - # We need libpfm to be installed and allow reading perf counters. We can - # only know that at runtime, so we try to measure the latency of an empty - # code snippet and bail out on error. - llvm_exegesis_exe = lit.util.which('llvm-exegesis', config.llvm_tools_dir) - if not llvm_exegesis_exe: - print('llvm-exegesis not found') - config.unsupported = True - else: - try: - with open(os.devnull, 'w') as quiet: - check_llvm_exegesis_inverse_throughput_result = subprocess.call( - [llvm_exegesis_exe, '-mode', 'inverse_throughput', '-snippets-file', '/dev/null'], stdout=quiet, stderr=quiet) - except OSError: - print('could not exec llvm-exegesis') - config.unsupported = True - if not check_llvm_exegesis_inverse_throughput_result == 0: - config.unsupported = True diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/latency-CMOV32rr.s b/llvm/test/tools/llvm-exegesis/X86/latency/latency-CMOV32rr.s --- a/llvm/test/tools/llvm-exegesis/X86/latency/latency-CMOV32rr.s +++ b/llvm/test/tools/llvm-exegesis/X86/latency/latency-CMOV32rr.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=latency -opcode-name=CMOV32rr -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=latency -opcode-name=CMOV32rr -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=CMOV32rr -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=CMOV32rr -repetition-mode=loop | FileCheck %s CHECK: --- CHECK-NEXT: mode: latency diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/latency-IN16rr.s b/llvm/test/tools/llvm-exegesis/X86/latency/latency-IN16rr.s --- a/llvm/test/tools/llvm-exegesis/X86/latency/latency-IN16rr.s +++ b/llvm/test/tools/llvm-exegesis/X86/latency/latency-IN16rr.s @@ -1,4 +1,4 @@ -# RUN: llvm-exegesis -mode=latency -opcode-name=IN16rr -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=IN16rr -repetition-mode=duplicate | FileCheck %s # FIXME: Sometimes fails with: 'unimplemented operand type' # ALLOW_RETRIES: 2 diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/latency-LEA64_32r.s b/llvm/test/tools/llvm-exegesis/X86/latency/latency-LEA64_32r.s --- a/llvm/test/tools/llvm-exegesis/X86/latency/latency-LEA64_32r.s +++ b/llvm/test/tools/llvm-exegesis/X86/latency/latency-LEA64_32r.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=latency -opcode-name=LEA64_32r -repetition-mode=duplicate -max-configs-per-opcode=2 | FileCheck %s -# RUN: llvm-exegesis -mode=latency -opcode-name=LEA64_32r -repetition-mode=loop -max-configs-per-opcode=2 | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=LEA64_32r -repetition-mode=duplicate -max-configs-per-opcode=2 | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=LEA64_32r -repetition-mode=loop -max-configs-per-opcode=2 | FileCheck %s CHECK: --- CHECK-NEXT: mode: latency diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/latency-LEA64r.s b/llvm/test/tools/llvm-exegesis/X86/latency/latency-LEA64r.s --- a/llvm/test/tools/llvm-exegesis/X86/latency/latency-LEA64r.s +++ b/llvm/test/tools/llvm-exegesis/X86/latency/latency-LEA64r.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=latency -opcode-name=LEA64r -repetition-mode=duplicate -max-configs-per-opcode=2 | FileCheck %s -# RUN: llvm-exegesis -mode=latency -opcode-name=LEA64r -repetition-mode=loop -max-configs-per-opcode=2 | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=LEA64r -repetition-mode=duplicate -max-configs-per-opcode=2 | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=LEA64r -repetition-mode=loop -max-configs-per-opcode=2 | FileCheck %s CHECK: --- CHECK-NEXT: mode: latency diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/latency-SBB8rr.s b/llvm/test/tools/llvm-exegesis/X86/latency/latency-SBB8rr.s --- a/llvm/test/tools/llvm-exegesis/X86/latency/latency-SBB8rr.s +++ b/llvm/test/tools/llvm-exegesis/X86/latency/latency-SBB8rr.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=latency -opcode-name=SBB8rr -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=latency -opcode-name=SBB8rr -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=SBB8rr -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=SBB8rr -repetition-mode=loop | FileCheck %s CHECK: --- CHECK-NEXT: mode: latency diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/latency-SETCCr-cond-codes-sweep.s b/llvm/test/tools/llvm-exegesis/X86/latency/latency-SETCCr-cond-codes-sweep.s --- a/llvm/test/tools/llvm-exegesis/X86/latency/latency-SETCCr-cond-codes-sweep.s +++ b/llvm/test/tools/llvm-exegesis/X86/latency/latency-SETCCr-cond-codes-sweep.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=latency -opcode-name=SETCCr --max-configs-per-opcode=1 | FileCheck %s --check-prefix=CHECK -# RUN: llvm-exegesis -mode=latency -opcode-name=SETCCr --max-configs-per-opcode=256 | FileCheck %s --check-prefix=SWEEP +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=SETCCr --max-configs-per-opcode=1 | FileCheck %s --check-prefix=CHECK +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=SETCCr --max-configs-per-opcode=256 | FileCheck %s --check-prefix=SWEEP CHECK: --- CHECK-NEXT: mode: latency diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/latency-SQRTSSr.s b/llvm/test/tools/llvm-exegesis/X86/latency/latency-SQRTSSr.s --- a/llvm/test/tools/llvm-exegesis/X86/latency/latency-SQRTSSr.s +++ b/llvm/test/tools/llvm-exegesis/X86/latency/latency-SQRTSSr.s @@ -1,4 +1,4 @@ -# RUN: llvm-exegesis -mode=latency -opcode-name=SQRTSSr -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=SQRTSSr -repetition-mode=loop | FileCheck %s # Check that the setup code for MXCSR does not crash the snippet. diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/latency-by-opcode-name.s b/llvm/test/tools/llvm-exegesis/X86/latency/latency-by-opcode-name.s --- a/llvm/test/tools/llvm-exegesis/X86/latency/latency-by-opcode-name.s +++ b/llvm/test/tools/llvm-exegesis/X86/latency/latency-by-opcode-name.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=latency -opcode-name=ADD32rr -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=latency -opcode-name=ADD32rr -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=ADD32rr -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=ADD32rr -repetition-mode=loop | FileCheck %s CHECK: --- CHECK-NEXT: mode: latency diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/lit.local.cfg b/llvm/test/tools/llvm-exegesis/X86/latency/lit.local.cfg deleted file mode 100644 --- a/llvm/test/tools/llvm-exegesis/X86/latency/lit.local.cfg +++ /dev/null @@ -1,29 +0,0 @@ -import subprocess -import lit.util - -if not ('X86' in config.root.targets): - # We need support for X86. - config.unsupported = True - -elif not ('x86_64' in config.root.host_triple): - # We need to be running on an X86 host. - config.unsupported = True - -else: - # We need libpfm to be installed and allow reading perf counters. We can - # only know that at runtime, so we try to measure the latency of an empty - # code snippet and bail out on error. - llvm_exegesis_exe = lit.util.which('llvm-exegesis', config.llvm_tools_dir) - if not llvm_exegesis_exe: - print('llvm-exegesis not found') - config.unsupported = True - else: - try: - with open(os.devnull, 'w') as quiet: - check_llvm_exegesis_latency_result = subprocess.call( - [llvm_exegesis_exe, '-mode', 'latency', '-snippets-file', '/dev/null'], stdout=quiet, stderr=quiet) - except OSError: - print('could not exec llvm-exegesis') - config.unsupported = True - if not check_llvm_exegesis_latency_result == 0: - config.unsupported = True diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/max-configs.test b/llvm/test/tools/llvm-exegesis/X86/latency/max-configs.test --- a/llvm/test/tools/llvm-exegesis/X86/latency/max-configs.test +++ b/llvm/test/tools/llvm-exegesis/X86/latency/max-configs.test @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=latency -opcode-name=SBB8rr -max-configs-per-opcode=1 | FileCheck -check-prefixes=CHECK,CHECK1 %s -# RUN: llvm-exegesis -mode=latency -opcode-name=SBB8rr -max-configs-per-opcode=2 | FileCheck -check-prefixes=CHECK,CHECK2 %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=SBB8rr -max-configs-per-opcode=1 | FileCheck -check-prefixes=CHECK,CHECK1 %s +# RUN: llvm-exegesis -mode=latency --dry-run -opcode-name=SBB8rr -max-configs-per-opcode=2 | FileCheck -check-prefixes=CHECK,CHECK2 %s CHECK: --- CHECK-NEXT: mode: latency diff --git a/llvm/test/tools/llvm-exegesis/X86/lbr/lit.local.cfg b/llvm/test/tools/llvm-exegesis/X86/lbr/lit.local.cfg --- a/llvm/test/tools/llvm-exegesis/X86/lbr/lit.local.cfg +++ b/llvm/test/tools/llvm-exegesis/X86/lbr/lit.local.cfg @@ -1,15 +1,18 @@ import subprocess import lit.util -if not ('X86' in config.root.targets): +if 'native' not in config.available_features: + config.unsupported = True + +elif not ('X86' in config.root.targets): # We need support for X86. config.unsupported = True elif not ('x86_64' in config.root.host_triple): # We need to be running on an X86 host. config.unsupported = True - -else: + +else: # We need libpfm to be installed and the host to be support LBR format with cycles. llvm_exegesis_exe = lit.util.which('llvm-exegesis', config.llvm_tools_dir) if not llvm_exegesis_exe: diff --git a/llvm/test/tools/llvm-exegesis/X86/lit.local.cfg b/llvm/test/tools/llvm-exegesis/X86/lit.local.cfg --- a/llvm/test/tools/llvm-exegesis/X86/lit.local.cfg +++ b/llvm/test/tools/llvm-exegesis/X86/lit.local.cfg @@ -1,7 +1,3 @@ if not ('X86' in config.root.targets): # We need support for X86. config.unsupported = True - -elif not ('x86_64' in config.root.host_triple): - # We need to be running on an X86 host. - config.unsupported = True \ No newline at end of file diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/lit.local.cfg b/llvm/test/tools/llvm-exegesis/X86/uops/lit.local.cfg deleted file mode 100644 --- a/llvm/test/tools/llvm-exegesis/X86/uops/lit.local.cfg +++ /dev/null @@ -1,29 +0,0 @@ -import subprocess -import lit.util - -if not ('X86' in config.root.targets): - # We need support for X86. - config.unsupported = True - -elif not ('x86_64' in config.root.host_triple): - # We need to be running on an X86 host. - config.unsupported = True - -else: - # We need libpfm to be installed and allow reading perf counters. We can - # only know that at runtime, so we try to measure the latency of an empty - # code snippet and bail out on error. - llvm_exegesis_exe = lit.util.which('llvm-exegesis', config.llvm_tools_dir) - if not llvm_exegesis_exe: - print('llvm-exegesis not found') - config.unsupported = True - else: - try: - with open(os.devnull, 'w') as quiet: - check_llvm_exegesis_uops_result = subprocess.call( - [llvm_exegesis_exe, '-mode', 'uops', '-snippets-file', '/dev/null'], stdout=quiet, stderr=quiet) - except OSError: - print('could not exec llvm-exegesis') - config.unsupported = True - if not check_llvm_exegesis_uops_result == 0: - config.unsupported = True \ No newline at end of file diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32mi8.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32mi8.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32mi8.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32mi8.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=ADD32mi8 -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=ADD32mi8 -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=ADD32mi8 -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=ADD32mi8 -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32mr.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32mr.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32mr.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32mr.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=ADD32mr -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=ADD32mr -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=ADD32mr -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=ADD32mr -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32rm.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32rm.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32rm.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD32rm.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=ADD32rm -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=ADD32rm -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=ADD32rm -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=ADD32rm -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD_F32m.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD_F32m.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD_F32m.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-ADD_F32m.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=ADD_F32m -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=ADD_F32m -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=ADD_F32m -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=ADD_F32m -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-BEXTR32rm.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-BEXTR32rm.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-BEXTR32rm.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-BEXTR32rm.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=BEXTR32rm -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=BEXTR32rm -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=BEXTR32rm -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=BEXTR32rm -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-BSF16rm.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-BSF16rm.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-BSF16rm.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-BSF16rm.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=BSF16rm -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=BSF16rm -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=BSF16rm -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=BSF16rm -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-BTR64mr.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-BTR64mr.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-BTR64mr.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-BTR64mr.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=BTR64mr -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=BTR64mr -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=BTR64mr -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=BTR64mr -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-CMOV16rm-noreg-serialization.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-CMOV16rm-noreg-serialization.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-CMOV16rm-noreg-serialization.s @@ -0,0 +1,11 @@ +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=CMOV16rm -benchmarks-file=- | FileCheck %s -check-prefixes=CHECK-YAML + +# https://bugs.llvm.org/show_bug.cgi?id=41448 +# Verify that we correctly serialize RegNo 0 as %noreg, not as an empty string! + +CHECK-YAML: --- +CHECK-YAML-NEXT: mode: uops +CHECK-YAML-NEXT: key: +CHECK-YAML-NEXT: instructions: +CHECK-YAML-NEXT: - 'CMOV16rm {{[A-Z0-9]+}} {{[A-Z0-9]+}} {{[A-Z0-9]+}} i_0x1 %noreg i_0x0 %noreg i_0x{{[0-9a-f]}}' +CHECK-YAML-LAST: ... diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-CMOV16rm-noreg.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-CMOV16rm-noreg.s deleted file mode 100644 --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-CMOV16rm-noreg.s +++ /dev/null @@ -1,17 +0,0 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=CMOV16rm -benchmarks-file=%t.CMOV16rm-uops.yaml -# RUN: FileCheck -check-prefixes=CHECK-YAML -input-file=%t.CMOV16rm-uops.yaml %s -# RUN: llvm-exegesis -mcpu=bdver2 -mode=analysis -benchmarks-file=%t.CMOV16rm-uops.yaml -analysis-clusters-output-file=- -analysis-clustering-epsilon=0.1 -analysis-inconsistency-epsilon=0.1 -analysis-numpoints=1 -analysis-clustering=naive | FileCheck -check-prefixes=CHECK-CLUSTERS %s - -# https://bugs.llvm.org/show_bug.cgi?id=41448 -# 1. Verify that we correctly serialize RegNo 0 as %noreg, not as an empty string! -# 2. Verify that deserialization works. Since CMOV16rm has a variant sched class, just printing clusters is sufficient - -CHECK-YAML: --- -CHECK-YAML-NEXT: mode: uops -CHECK-YAML-NEXT: key: -CHECK-YAML-NEXT: instructions: -CHECK-YAML-NEXT: - 'CMOV16rm {{[A-Z0-9]+}} {{[A-Z0-9]+}} {{[A-Z0-9]+}} i_0x1 %noreg i_0x0 %noreg i_0x{{[0-9a-f]}}' -CHECK-YAML-LAST: ... - -# CHECK-CLUSTERS: {{^}}cluster_id,opcode_name,config,sched_class, -# CHECK-CLUSTERS-NEXT: {{^}}0, diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-FLDENVm.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-FLDENVm.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-FLDENVm.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-FLDENVm.s @@ -1,4 +1,4 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=FLDENVm,FLDL2E -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=FLDENVm,FLDL2E -repetition-mode=duplicate | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-LEA64r.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-LEA64r.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-LEA64r.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-LEA64r.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=LEA64r -repetition-mode=duplicate -max-configs-per-opcode=2 | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=LEA64r -repetition-mode=loop -max-configs-per-opcode=2 | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=LEA64r -repetition-mode=duplicate -max-configs-per-opcode=2 | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=LEA64r -repetition-mode=loop -max-configs-per-opcode=2 | FileCheck %s CHECK: --- CHECK-NEXT: mode: uops diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-POPCNT32rr.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-POPCNT32rr.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-POPCNT32rr.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-POPCNT32rr.s @@ -1,4 +1,4 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=POPCNT32rr 2>&1 | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=POPCNT32rr 2>&1 | FileCheck %s CHECK: --- CHECK-NEXT: mode: uops diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-STD.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-STD.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-STD.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-STD.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=STD -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=STD -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=STD -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=STD -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-VFMADDSS4rm.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-VFMADDSS4rm.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-VFMADDSS4rm.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-VFMADDSS4rm.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=VFMADDSS4rm -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=VFMADDSS4rm -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=VFMADDSS4rm -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=VFMADDSS4rm -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-XCHG64rr.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-XCHG64rr.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-XCHG64rr.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-XCHG64rr.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=XCHG64rr -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=XCHG64rr -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=XCHG64rr -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=XCHG64rr -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-by-opcode-name.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-by-opcode-name.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-by-opcode-name.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-by-opcode-name.s @@ -1,5 +1,5 @@ -# RUN: llvm-exegesis -mode=uops -opcode-name=ADD32rr -repetition-mode=duplicate | FileCheck %s -# RUN: llvm-exegesis -mode=uops -opcode-name=ADD32rr -repetition-mode=loop | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=ADD32rr -repetition-mode=duplicate | FileCheck %s +# RUN: llvm-exegesis -mode=uops --dry-run -opcode-name=ADD32rr -repetition-mode=loop | FileCheck %s CHECK: mode: uops CHECK-NEXT: key: diff --git a/llvm/test/tools/llvm-exegesis/X86/uops/uops-misspelled-div.s b/llvm/test/tools/llvm-exegesis/X86/uops/uops-misspelled-div.s --- a/llvm/test/tools/llvm-exegesis/X86/uops/uops-misspelled-div.s +++ b/llvm/test/tools/llvm-exegesis/X86/uops/uops-misspelled-div.s @@ -1,4 +1,4 @@ -# RUN: not llvm-exegesis -mode=uops -snippets-file=%s 2>&1 | FileCheck %s +# RUN: not llvm-exegesis -mode=uops --dry-run -snippets-file=%s 2>&1 | FileCheck %s # LLVM-EXEGESIS-DEFREG CL 1 # LLVM-EXEGESIS-DEFREG AX 1 diff --git a/llvm/test/tools/llvm-exegesis/lit.local.cfg b/llvm/test/tools/llvm-exegesis/lit.local.cfg deleted file mode 100644 --- a/llvm/test/tools/llvm-exegesis/lit.local.cfg +++ /dev/null @@ -1,2 +0,0 @@ -if 'native' not in config.available_features: - config.unsupported = True diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h @@ -35,7 +35,8 @@ class BenchmarkRunner { public: explicit BenchmarkRunner(const LLVMState &State, - InstructionBenchmark::ModeE Mode); + InstructionBenchmark::ModeE Mode, + bool BenchmarkDryRun); virtual ~BenchmarkRunner(); @@ -77,6 +78,7 @@ protected: const LLVMState &State; const InstructionBenchmark::ModeE Mode; + const bool BenchmarkDryRun; private: virtual Expected> diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -30,8 +30,10 @@ namespace exegesis { BenchmarkRunner::BenchmarkRunner(const LLVMState &State, - InstructionBenchmark::ModeE Mode) - : State(State), Mode(Mode), Scratch(std::make_unique()) {} + InstructionBenchmark::ModeE Mode, + bool BenchmarkDryRun) + : State(State), Mode(Mode), BenchmarkDryRun(BenchmarkDryRun), + Scratch(std::make_unique()) {} BenchmarkRunner::~BenchmarkRunner() = default; @@ -213,6 +215,11 @@ ObjectFile = getObjectFromBuffer(OS.str()); } + if (BenchmarkDryRun) { + InstrBenchmark.Error = "in --dry-run mode, actual measurements skipped."; + continue; + } + const FunctionExecutorImpl Executor(State, std::move(ObjectFile), Scratch.get()); auto NewMeasurements = runMeasurements(Executor); diff --git a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h --- a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h @@ -23,6 +23,7 @@ public: LatencyBenchmarkRunner( const LLVMState &State, InstructionBenchmark::ModeE Mode, + bool BenchmarkDryRun, InstructionBenchmark::ResultAggregationModeE ResultAggMode); ~LatencyBenchmarkRunner() override; diff --git a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp --- a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp @@ -20,8 +20,9 @@ LatencyBenchmarkRunner::LatencyBenchmarkRunner( const LLVMState &State, InstructionBenchmark::ModeE Mode, + bool BenchmarkDryRun, InstructionBenchmark::ResultAggregationModeE ResultAgg) - : BenchmarkRunner(State, Mode) { + : BenchmarkRunner(State, Mode, BenchmarkDryRun) { assert((Mode == InstructionBenchmark::Latency || Mode == InstructionBenchmark::InverseThroughput) && "invalid mode"); diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -155,6 +155,7 @@ // Creates a benchmark runner for the given mode. Expected> createBenchmarkRunner( InstructionBenchmark::ModeE Mode, const LLVMState &State, + bool BenchmarkDryRun, InstructionBenchmark::ResultAggregationModeE ResultAggMode = InstructionBenchmark::Min) const; @@ -193,9 +194,10 @@ const LLVMState &State, const SnippetGenerator::Options &Opts) const; std::unique_ptr virtual createLatencyBenchmarkRunner( const LLVMState &State, InstructionBenchmark::ModeE Mode, + bool BenchmarkDryRun, InstructionBenchmark::ResultAggregationModeE ResultAggMode) const; std::unique_ptr virtual createUopsBenchmarkRunner( - const LLVMState &State, + const LLVMState &State, bool BenchmarkDryRun, InstructionBenchmark::ResultAggregationModeE ResultAggMode) const; const ExegesisTarget *Next = nullptr; diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp --- a/llvm/tools/llvm-exegesis/lib/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/Target.cpp @@ -70,6 +70,7 @@ Expected> ExegesisTarget::createBenchmarkRunner( InstructionBenchmark::ModeE Mode, const LLVMState &State, + bool BenchmarkDryRun, InstructionBenchmark::ResultAggregationModeE ResultAggMode) const { PfmCountersInfo PfmCounters = State.getPfmCounters(); switch (Mode) { @@ -77,21 +78,26 @@ return nullptr; case InstructionBenchmark::Latency: case InstructionBenchmark::InverseThroughput: - if (!PfmCounters.CycleCounter) { + if (!BenchmarkDryRun && !PfmCounters.CycleCounter) { const char *ModeName = Mode == InstructionBenchmark::Latency ? "latency" : "inverse_throughput"; return make_error( Twine("can't run '") .concat(ModeName) - .concat("' mode, sched model does not define a cycle counter.")); + .concat( + "' mode, sched model does not define a cycle counter. You " + "can pass --dry-run to skip the actual benchmarking.")); } - return createLatencyBenchmarkRunner(State, Mode, ResultAggMode); + return createLatencyBenchmarkRunner(State, Mode, BenchmarkDryRun, + ResultAggMode); case InstructionBenchmark::Uops: - if (!PfmCounters.UopsCounter && !PfmCounters.IssueCounters) - return make_error("can't run 'uops' mode, sched model does not " - "define uops or issue counters."); - return createUopsBenchmarkRunner(State, ResultAggMode); + if (!BenchmarkDryRun && !PfmCounters.UopsCounter && + !PfmCounters.IssueCounters) + return make_error( + "can't run 'uops' mode, sched model does not define uops or issue " + "counters. You can pass --dry-run to skip the actual benchmarking."); + return createUopsBenchmarkRunner(State, BenchmarkDryRun, ResultAggMode); } return nullptr; } @@ -108,14 +114,16 @@ std::unique_ptr ExegesisTarget::createLatencyBenchmarkRunner( const LLVMState &State, InstructionBenchmark::ModeE Mode, + bool BenchmarkDryRun, InstructionBenchmark::ResultAggregationModeE ResultAggMode) const { - return std::make_unique(State, Mode, ResultAggMode); + return std::make_unique(State, Mode, BenchmarkDryRun, + ResultAggMode); } std::unique_ptr ExegesisTarget::createUopsBenchmarkRunner( - const LLVMState &State, + const LLVMState &State, bool BenchmarkDryRun, InstructionBenchmark::ResultAggregationModeE /*unused*/) const { - return std::make_unique(State); + return std::make_unique(State, BenchmarkDryRun); } static_assert(std::is_pod::value, diff --git a/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h --- a/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h @@ -21,8 +21,8 @@ class UopsBenchmarkRunner : public BenchmarkRunner { public: - UopsBenchmarkRunner(const LLVMState &State) - : BenchmarkRunner(State, InstructionBenchmark::Uops) {} + UopsBenchmarkRunner(const LLVMState &State, bool BenchmarkDryRun) + : BenchmarkRunner(State, InstructionBenchmark::Uops, BenchmarkDryRun) {} ~UopsBenchmarkRunner() override; static constexpr const size_t kMinNumDifferentAddresses = 6; diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -111,6 +111,12 @@ "All of the above and take the minimum of measurements")), cl::init(exegesis::InstructionBenchmark::Duplicate)); +static cl::opt + BenchmarkDryRun("dry-run", + cl::desc("(only in -mode=?) do everything except actually " + "performing the measurements"), + cl::cat(BenchmarkOptions), cl::init(false)); + static cl::opt NumRepetitions("num-repetitions", cl::desc("number of time to repeat the asm snippet"), @@ -291,12 +297,15 @@ } void benchmarkMain() { + if (!BenchmarkDryRun) { #ifndef HAVE_LIBPFM - ExitWithError("benchmarking unavailable, LLVM was built without libpfm."); + ExitWithError("benchmarking unavailable, LLVM was built without libpfm. " + "You can pass --dry-run to skip the actual benchmarking."); +#else + if (exegesis::pfm::pfmInitialize()) + ExitWithError("cannot initialize libpfm"); #endif - - if (exegesis::pfm::pfmInitialize()) - ExitWithError("cannot initialize libpfm"); + } InitializeAllTargets(); InitializeAllTargetMCs(); @@ -308,11 +317,12 @@ // Preliminary check to ensure features needed for requested // benchmark mode are present on target CPU and/or OS. - ExitOnErr(State.getExegesisTarget().checkFeatureSupport()); + if (!BenchmarkDryRun) + ExitOnErr(State.getExegesisTarget().checkFeatureSupport()); const std::unique_ptr Runner = ExitOnErr(State.getExegesisTarget().createBenchmarkRunner( - BenchmarkMode, State, ResultAggMode)); + BenchmarkMode, State, BenchmarkDryRun, ResultAggMode)); if (!Runner) { ExitWithError("cannot create benchmark runner"); }