<div dir="ltr">Hi Mikael, sorry I missed your e-mail. Can you confirm that my fix works ?<div>I'll add an option to disable libpfm completely for issues like this one.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Apr 5, 2018 at 9:45 AM, Mikael Holmén <span dir="ltr"><<a href="mailto:mikael.holmen@ericsson.com" target="_blank">mikael.holmen@ericsson.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">And now I suddenly saw you already made an attempt to fix this! :)<br>
<br>
I'll check again.<br>
<br>
Thanks,<br>
Mikael<br>
<br>
On 04/05/2018 09:43 AM, Mikael Holmén via llvm-commits wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Clement,<br>
<br>
Are there any requirements about the perfmon version?<br>
<br>
On several of my buildbots I get compilation failures now:<br>
<br>
../tools/llvm-exegesis/lib/Per<wbr>fHelper.cpp:14:10: fatal error: 'perfmon/perf_event.h' file not found<br>
#include "perfmon/perf_event.h"<br>
<br>
On those machines there does exist a perfmon/pfmlib.h file but not perf_event.h nor pfmlib_perf_event.h. It looks like we have version 3.16 installed acording to pfmlib.h:<br>
<br>
#define PFMLIB_VERSION          (3 << 16 | 10)<br>
<br>
If you require a newer version than that, shouldn't that be checked by the makefiles a well?<br>
<br>
I've also tried to find some CMAKE flag to turn off the pfm support completely with something similar to LLVM_ENABLE_ZLIB but I can't find anything like that.<br>
<br>
Regards,<br>
Mikael<br>
<br>
On 04/04/2018 01:37 PM, Clement Courbet via llvm-commits wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: courbet<br>
Date: Wed Apr  4 04:37:06 2018<br>
New Revision: 329169<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=329169&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=329169&view=rev</a><br>
Log:<br>
Re-land r329156 "Add llvm-exegesis tool."<br>
<br>
Fixed to depend on and initialize the native target instead of X86.<br>
<br>
Added:<br>
     llvm/trunk/docs/CommandGuide/l<wbr>lvm-exegesis.rst<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/CMakeLists.txt<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/LLVMBuild.txt<br>
       - copied, changed from r329157, llvm/trunk/tools/LLVMBuild.txt<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkResult.cpp<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkResult.h<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkRunner.cpp<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkRunner.h<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/CMakeLists.txt<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/InMemoryAssembler.cpp<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/InMemoryAssembler.h<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/InstructionSnippetGenerat<wbr>or.cpp<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/InstructionSnippetGenerat<wbr>or.h<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/LLVMBuild.txt<br>
       - copied, changed from r329157, llvm/trunk/tools/LLVMBuild.txt<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/Latency.cpp<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/Latency.h<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/LlvmState.cpp<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/LlvmState.h<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/OperandGraph.cpp<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/OperandGraph.h<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/PerfHelper.cpp<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/PerfHelper.h<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/Uops.cpp<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/Uops.h<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/X86.cpp<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/lib/X86.h<br>
     llvm/trunk/tools/llvm-exegesis<wbr>/llvm-exegesis.cpp<br>
     llvm/trunk/unittests/tools/llv<wbr>m-exegesis/BenchmarkResultTest<wbr>.cpp<br>
     llvm/trunk/unittests/tools/llv<wbr>m-exegesis/CMakeLists.txt<br>
     llvm/trunk/unittests/tools/llv<wbr>m-exegesis/InMemoryAssemblerTe<wbr>st.cpp<br>
     llvm/trunk/unittests/tools/ll<wbr>vm-exegesis/InstructionSnippet<wbr>GeneratorTest.cpp <br>
     llvm/trunk/unittests/tools/llv<wbr>m-exegesis/OperandGraphTest.<wbr>cpp<br>
     llvm/trunk/unittests/tools/llv<wbr>m-exegesis/PerfHelperTest.cpp<br>
Modified:<br>
     llvm/trunk/cmake/config-ix.cma<wbr>ke<br>
     llvm/trunk/docs/CommandGuide/i<wbr>ndex.rst<br>
     llvm/trunk/docs/ReleaseNotes.r<wbr>st<br>
     llvm/trunk/include/llvm/Config<wbr>/config.h.cmake<br>
     llvm/trunk/tools/LLVMBuild.txt<br>
     llvm/trunk/unittests/tools/CMa<wbr>keLists.txt<br>
<br>
Modified: llvm/trunk/cmake/config-ix.cma<wbr>ke<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/config-ix.cmake?rev=329169&r1=329168&r2=329169&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/cmake/config-<wbr>ix.cmake?rev=329169&r1=329168&<wbr>r2=329169&view=diff</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/cmake/config-ix.cma<wbr>ke (original)<br>
+++ llvm/trunk/cmake/config-ix.cma<wbr>ke Wed Apr  4 04:37:06 2018<br>
@@ -87,6 +87,7 @@ if( NOT PURE_WINDOWS )<br>
    endif()<br>
    check_library_exists(dl dlopen "" HAVE_LIBDL)<br>
    check_library_exists(rt clock_gettime "" HAVE_LIBRT)<br>
+  check_library_exists(pfm pfm_initialize "" HAVE_LIBPFM)<br>
  endif()<br>
  if(HAVE_LIBPTHREAD)<br>
<br>
Modified: llvm/trunk/docs/CommandGuide/i<wbr>ndex.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/index.rst?rev=329169&r1=329168&r2=329169&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/docs/CommandG<wbr>uide/index.rst?rev=329169&r1=<wbr>329168&r2=329169&view=diff</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/docs/CommandGuide/i<wbr>ndex.rst (original)<br>
+++ llvm/trunk/docs/CommandGuide/i<wbr>ndex.rst Wed Apr  4 04:37:06 2018<br>
@@ -53,5 +53,6 @@ Developer Tools<br>
     tblgen<br>
     lit<br>
     llvm-build<br>
+   llvm-exegesis<br>
     llvm-pdbutil<br>
     llvm-readobj<br>
<br>
Added: llvm/trunk/docs/CommandGuide/l<wbr>lvm-exegesis.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llvm-exegesis.rst?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/docs/CommandG<wbr>uide/llvm-exegesis.rst?rev=<wbr>329169&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/docs/CommandGuide/l<wbr>lvm-exegesis.rst (added)<br>
+++ llvm/trunk/docs/CommandGuide/l<wbr>lvm-exegesis.rst Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,58 @@<br>
+llvm-exegesis - LLVM Machine Instruction Benchmark<br>
+=============================<wbr>=====================<br>
+<br>
+SYNOPSIS<br>
+--------<br>
+<br>
+:program:`llvm-exegesis` [*options*]<br>
+<br>
+DESCRIPTION<br>
+-----------<br>
+<br>
+:program:`llvm-exegesis` is a benchmarking tool that uses information available<br>
+in LLVM to measure host machine instruction characteristics like latency or port<br>
+decomposition.<br>
+<br>
+Given an LLVM opcode name and a benchmarking mode, :program:`llvm-exegesis`<br>
+generates a code snippet that makes execution as serial (resp. as parallel) as<br>
+possible so that we can measure the latency (resp. uop decomposition) of the<br>
+instruction.<br>
+The code snippet is jitted and executed on the host subtarget. The time taken<br>
+(resp. resource usage) is measured using hardware performance counters. The<br>
+result is printed out as YAML to the standard output.<br>
+<br>
+The main goal of this tool is to automatically (in)validate the LLVM's TableDef<br>
+scheduling models.<br>
+<br>
+OPTIONS<br>
+-------<br>
+<br>
+.. option:: -help<br>
+<br>
+ Print a summary of command line options.<br>
+<br>
+.. option:: -opcode-index=<LLVM opcode index><br>
+<br>
+ Specify the opcode to measure, by index.<br>
+ Either `opcode-index` or `opcode-name` must be set.<br>
+<br>
+.. option:: -opcode-name=<LLVM opcode name><br>
+<br>
+ Specify the opcode to measure, by name.<br>
+ Either `opcode-index` or `opcode-name` must be set.<br>
+<br>
+.. option:: -benchmark-mode=[Latency|Uops]<br>
+<br>
+ Specify which characteristic of the opcode to measure.<br>
+<br>
+.. option:: -num-repetitions=<Number of repetition><br>
+<br>
+ Specify the number of repetitions of the asm snippet.<br>
+ Higher values lead to more accurate measurements but lengthen the benchmark.<br>
+<br>
+<br>
+EXIT STATUS<br>
+-----------<br>
+<br>
+:program:`llvm-exegesis` returns 0 on success. Otherwise, an error message is<br>
+printed to standard error, and the tool returns a non 0 value.<br>
<br>
Modified: llvm/trunk/docs/ReleaseNotes.r<wbr>st<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ReleaseNotes.rst?rev=329169&r1=329168&r2=329169&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/docs/ReleaseN<wbr>otes.rst?rev=329169&r1=329168&<wbr>r2=329169&view=diff</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/docs/ReleaseNotes.r<wbr>st (original)<br>
+++ llvm/trunk/docs/ReleaseNotes.r<wbr>st Wed Apr  4 04:37:06 2018<br>
@@ -48,6 +48,11 @@ Non-comprehensive list of changes in thi<br>
  * Symbols starting with ``?`` are no longer mangled by LLVM when using the<br>
    Windows ``x`` or ``w`` IR mangling schemes.<br>
+* A new tool named :doc:`llvm-exegesis <CommandGuide/llvm-exegesis>` has been<br>
+  added. :program:`llvm-exegesis` automatically measures instruction scheduling<br>
+  properties (latency/uops) and provides a principled way to edit scheduling<br>
+  models.<br>
+<br>
  * A new tool named :doc:`llvm-mca <CommandGuide/llvm-mca>` has been added.<br>
    :program:`llvm-mca` is a  static performance analysis tool that uses<br>
    information available in LLVM to statically predict the performance of<br>
<br>
Modified: llvm/trunk/include/llvm/Config<wbr>/config.h.cmake<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Config/config.h.cmake?rev=329169&r1=329168&r2=329169&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>Config/config.h.cmake?rev=<wbr>329169&r1=329168&r2=329169&<wbr>view=diff</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/include/llvm/Config<wbr>/config.h.cmake (original)<br>
+++ llvm/trunk/include/llvm/Config<wbr>/config.h.cmake Wed Apr  4 04:37:06 2018<br>
@@ -91,6 +91,12 @@<br>
  /* Define to 1 if you have the `edit' library (-ledit). */<br>
  #cmakedefine HAVE_LIBEDIT ${HAVE_LIBEDIT}<br>
+/* Define to 1 if you have the `pfm' library (-lpfm). */<br>
+#cmakedefine HAVE_LIBPFM ${HAVE_LIBPFM}<br>
+<br>
+/* Define to 1 if you have the `psapi' library (-lpsapi). */<br>
+#cmakedefine HAVE_LIBPSAPI ${HAVE_LIBPSAPI}<br>
+<br>
  /* Define to 1 if you have the `pthread' library (-lpthread). */<br>
  #cmakedefine HAVE_LIBPTHREAD ${HAVE_LIBPTHREAD}<br>
<br>
Modified: llvm/trunk/tools/LLVMBuild.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/LLVMBuild.txt?rev=329169&r1=329168&r2=329169&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/LLVMBui<wbr>ld.txt?rev=329169&r1=329168&<wbr>r2=329169&view=diff</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/LLVMBuild.txt (original)<br>
+++ llvm/trunk/tools/LLVMBuild.txt Wed Apr  4 04:37:06 2018<br>
@@ -32,6 +32,7 @@ subdirectories =<br>
   llvm-dis<br>
   llvm-dwarfdump<br>
   llvm-dwp<br>
+ llvm-exegesis<br>
   llvm-extract<br>
   llvm-jitlistener<br>
   llvm-link<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/CMakeLists.txt?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/CMakeLists.txt?rev=3291<wbr>69&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/CMakeLists.txt (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/CMakeLists.txt Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,16 @@<br>
+set(LLVM_LINK_COMPONENTS<br>
+  Support<br>
+  native<br>
+  )<br>
+<br>
+add_llvm_tool(llvm-exegesis<br>
+  llvm-exegesis.cpp<br>
+  )<br>
+<br>
+add_subdirectory(lib)<br>
+target_link_libraries(llvm-ex<wbr>egesis PRIVATE LLVMExegesis)<br>
+<br>
+if(HAVE_LIBPFM)<br>
+  target_link_libraries(llvm-exe<wbr>gesis PRIVATE pfm)<br>
+endif()<br>
+<br>
<br>
Copied: llvm/trunk/tools/llvm-exegesis<wbr>/LLVMBuild.txt (from r329157, llvm/trunk/tools/LLVMBuild.txt<wbr>)<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/LLVMBuild.txt?p2=llvm/trunk/tools/llvm-exegesis/LLVMBuild.txt&p1=llvm/trunk/tools/LLVMBuild.txt&r1=329157&r2=329169&rev=329169&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/LLVMBuild.txt?p2=llvm/<wbr>trunk/tools/llvm-exegesis/<wbr>LLVMBuild.txt&p1=llvm/trunk/<wbr>tools/LLVMBuild.txt&r1=329157&<wbr>r2=329169&rev=329169&view=diff</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/LLVMBuild.txt (original)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/LLVMBuild.txt Wed Apr  4 04:37:06 2018<br>
@@ -1,4 +1,4 @@<br>
-;===- ./tools/LLVMBuild.txt ------------------------------<wbr>------*- Conf -*--===;<br>
+;===- ./tools/llvm-exegesis/LLVMBuil<wbr>d.txt ----------------------*- Conf -*--===;<br>
  ;<br>
  ;                     The LLVM Compiler Infrastructure<br>
  ;<br>
@@ -15,44 +15,8 @@<br>
  ;<br>
  ;===--------------------------<wbr>------------------------------<wbr>----------------===; <br>
-[common]<br>
-subdirectories =<br>
- bugpoint<br>
- dsymutil<br>
- llc<br>
- lli<br>
- llvm-ar<br>
- llvm-as<br>
- llvm-bcanalyzer<br>
- llvm-cat<br>
- llvm-cfi-verify<br>
- llvm-cov<br>
- llvm-cvtres<br>
- llvm-diff<br>
- llvm-dis<br>
- llvm-dwarfdump<br>
- llvm-dwp<br>
- llvm-extract<br>
- llvm-jitlistener<br>
- llvm-link<br>
- llvm-lto<br>
- llvm-mc<br>
- llvm-mca<br>
- llvm-modextract<br>
- llvm-mt<br>
- llvm-nm<br>
- llvm-objcopy<br>
- llvm-objdump<br>
- llvm-pdbutil<br>
- llvm-profdata<br>
- llvm-rc<br>
- llvm-rtdyld<br>
- llvm-size<br>
- llvm-split<br>
- opt<br>
- verify-uselistorder<br>
-<br>
  [component_0]<br>
-type = Group<br>
-name = Tools<br>
-parent = $ROOT<br>
+type = Tool<br>
+name = llvm-exegesis<br>
+parent = Tools<br>
+required_libraries = CodeGen ExecutionEngine MC MCJIT Native NativeCodeGen Object Support<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkResult.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/BenchmarkResult.cpp<wbr>?rev=329169&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkResult.cpp (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkResult.cpp Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,85 @@<br>
+//===-- BenchmarkResult.cpp ------------------------------<wbr>-------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+<br>
+#include "BenchmarkResult.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/Support/FileOutputBuffer<wbr>.h"<br>
+#include "llvm/Support/FileSystem.h"<br>
+#include "llvm/Support/Format.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+// Defining YAML traits for IO.<br>
+namespace llvm {<br>
+namespace yaml {<br>
+<br>
+// std::vector<exegesis::Measure> will be rendered as a list.<br>
+template <> struct SequenceElementTraits<exegesis<wbr>::BenchmarkMeasure> {<br>
+  static const bool flow = false;<br>
+};<br>
+<br>
+// exegesis::Measure is rendererd as a flow instead of a list.<br>
+// e.g. { "key": "the key", "value": 0123 }<br>
+template <> struct MappingTraits<exegesis::Benchm<wbr>arkMeasure> {<br>
+  static void mapping(IO &Io, exegesis::BenchmarkMeasure &Obj) {<br>
+    Io.mapRequired("key", Obj.Key);<br>
+    Io.mapRequired("value", Obj.Value);<br>
+    Io.mapOptional("debug_string", Obj.DebugString);<br>
+  }<br>
+  static const bool flow = true;<br>
+};<br>
+<br>
+template <> struct MappingTraits<exegesis::AsmTem<wbr>plate> {<br>
+  static void mapping(IO &Io, exegesis::AsmTemplate &Obj) {<br>
+    Io.mapRequired("name", Obj.Name);<br>
+  }<br>
+};<br>
+<br>
+template <> struct MappingTraits<exegesis::Instru<wbr>ctionBenchmark> {<br>
+  static void mapping(IO &Io, exegesis::InstructionBenchmark &Obj) {<br>
+    Io.mapRequired("asm_template", Obj.AsmTmpl);<br>
+    Io.mapRequired("cpu_name", Obj.CpuName);<br>
+    Io.mapRequired("llvm_triple", Obj.LLVMTriple);<br>
+    Io.mapRequired("num_repetition<wbr>s", Obj.NumRepetitions);<br>
+    Io.mapRequired("measurements", Obj.Measurements);<br>
+    Io.mapRequired("error", Obj.Error);<br>
+  }<br>
+};<br>
+<br>
+} // namespace yaml<br>
+} // namespace llvm<br>
+<br>
+namespace exegesis {<br>
+<br>
+InstructionBenchmark<br>
+InstructionBenchmark::readYam<wbr>lOrDie(llvm::StringRef Filename) {<br>
+  std::unique_ptr<llvm::MemoryBu<wbr>ffer> MemBuffer = llvm::cantFail(<br>
+      llvm::errorOrToExpected(llvm::<wbr>MemoryBuffer::getFile(Filename<wbr>)));<br>
+  llvm::yaml::Input Yin(*MemBuffer);<br>
+  InstructionBenchmark Benchmark;<br>
+  Yin >> Benchmark;<br>
+  return Benchmark;<br>
+}<br>
+<br>
+void InstructionBenchmark::writeYam<wbr>lOrDie(const llvm::StringRef Filename) {<br>
+  if (Filename == "-") {<br>
+    llvm::yaml::Output Yout(llvm::outs());<br>
+    Yout << *this;<br>
+  } else {<br>
+    llvm::SmallString<1024> Buffer;<br>
+    llvm::raw_svector_ostream Ostr(Buffer);<br>
+    llvm::yaml::Output Yout(Ostr);<br>
+    Yout << *this;<br>
+    std::unique_ptr<llvm::FileOutp<wbr>utBuffer> File =<br>
+        llvm::cantFail(llvm::FileOutpu<wbr>tBuffer::create(Filename, Buffer.size()));<br>
+    memcpy(File->getBufferStart(), Buffer.data(), Buffer.size());<br>
+    llvm::cantFail(File->commit())<wbr>;<br>
+  }<br>
+}<br>
+<br>
+} // namespace exegesis<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkResult.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/BenchmarkResult.h?<wbr>rev=329169&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkResult.h (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkResult.h Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,53 @@<br>
+//===-- BenchmarkResult.h ------------------------------<wbr>---------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+///<br>
+/// \file<br>
+/// Defines classes to represent measurements and serialize/deserialize them to<br>
+//  Yaml.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+<br>
+#ifndef LLVM_TOOLS_LLVM_EXEGESIS_BENCH<wbr>MARKRESULT_H<br>
+#define LLVM_TOOLS_LLVM_EXEGESIS_BENCH<wbr>MARKRESULT_H<br>
+<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/Support/YAMLTraits.h"<br>
+#include <string><br>
+#include <vector><br>
+<br>
+namespace exegesis {<br>
+<br>
+struct AsmTemplate {<br>
+  std::string Name;<br>
+};<br>
+<br>
+struct BenchmarkMeasure {<br>
+  std::string Key;<br>
+  double Value;<br>
+  std::string DebugString;<br>
+};<br>
+<br>
+// The result of an instruction benchmark.<br>
+struct InstructionBenchmark {<br>
+  AsmTemplate AsmTmpl;<br>
+  std::string CpuName;<br>
+  std::string LLVMTriple;<br>
+  size_t NumRepetitions = 0;<br>
+  std::vector<BenchmarkMeasure> Measurements;<br>
+  std::string Error;<br>
+<br>
+  static InstructionBenchmark readYamlOrDie(llvm::StringRef Filename);<br>
+<br>
+  // Unfortunately this function is non const because of YAML traits.<br>
+  void writeYamlOrDie(const llvm::StringRef Filename);<br>
+};<br>
+<br>
+} // namespace exegesis<br>
+<br>
+#endif // LLVM_TOOLS_LLVM_EXEGESIS_BENCH<wbr>MARKRESULT_H<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkRunner.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/BenchmarkRunner.cpp<wbr>?rev=329169&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkRunner.cpp (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkRunner.cpp Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,79 @@<br>
+//===-- BenchmarkRunner.cpp ------------------------------<wbr>-------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+<br>
+#include "BenchmarkRunner.h"<br>
+#include "InMemoryAssembler.h"<br>
+#include "llvm/ADT/StringExtras.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/ADT/Twine.h"<br>
+#include <string><br>
+<br>
+namespace exegesis {<br>
+<br>
+BenchmarkRunner::InstructionF<wbr>ilter::~InstructionFilter() = default;<br>
+<br>
+BenchmarkRunner::~BenchmarkRu<wbr>nner() = default;<br>
+<br>
+InstructionBenchmark<br>
+BenchmarkRunner::run(const LLVMState &State, const unsigned Opcode,<br>
+                     unsigned NumRepetitions,<br>
+                     const InstructionFilter &Filter) const {<br>
+  InstructionBenchmark InstrBenchmark;<br>
+<br>
+  <a href="http://InstrBenchmark.AsmTmpl.Name" rel="noreferrer" target="_blank">InstrBenchmark.AsmTmpl.Name</a> =<br>
+      llvm::Twine(getDisplayName())<br>
+          .concat(" ")<br>
+          .concat(State.getInstrInfo().g<wbr>etName(Opcode))<br>
+          .str();<br>
+  InstrBenchmark.CpuName = State.getCpuName();<br>
+  InstrBenchmark.LLVMTriple = State.getTriple();<br>
+  InstrBenchmark.NumRepetitions = NumRepetitions;<br>
+<br>
+  // Ignore instructions that we cannot run.<br>
+  if (State.getInstrInfo().get(Opco<wbr>de).isPseudo()) {<br>
+    InstrBenchmark.Error = "Unsupported opcode: isPseudo";<br>
+    return InstrBenchmark;<br>
+  }<br>
+  if (llvm::Error E = Filter.shouldRun(State, Opcode)) {<br>
+    InstrBenchmark.Error = llvm::toString(std::move(E));<br>
+    return InstrBenchmark;<br>
+  }<br>
+<br>
+  JitFunctionContext Context(State.createTargetMach<wbr>ine());<br>
+  auto ExpectedInstructions =<br>
+      createCode(State, Opcode, NumRepetitions, Context);<br>
+  if (llvm::Error E = ExpectedInstructions.takeError<wbr>()) {<br>
+    InstrBenchmark.Error = llvm::toString(std::move(E));<br>
+    return InstrBenchmark;<br>
+  }<br>
+<br>
+  const std::vector<llvm::MCInst> Instructions = *ExpectedInstructions;<br>
+  const JitFunction Function(std::move(Context), Instructions);<br>
+  const llvm::StringRef CodeBytes = Function.getFunctionBytes();<br>
+<br>
+  std::string AsmExcerpt;<br>
+  constexpr const int ExcerptSize = 100;<br>
+  constexpr const int ExcerptTailSize = 10;<br>
+  if (CodeBytes.size() <= ExcerptSize) {<br>
+    AsmExcerpt = llvm::toHex(CodeBytes);<br>
+  } else {<br>
+    AsmExcerpt =<br>
+        llvm::toHex(CodeBytes.take_fro<wbr>nt(ExcerptSize - ExcerptTailSize + 3));<br>
+    AsmExcerpt += "...";<br>
+    AsmExcerpt += llvm::toHex(CodeBytes.take_bac<wbr>k(ExcerptTailSize));<br>
+  }<br>
+  llvm::outs() << "# Asm excerpt: " << AsmExcerpt << "\n";<br>
+  llvm::outs().flush(); // In case we crash.<br>
+<br>
+  InstrBenchmark.Measurements =<br>
+      runMeasurements(State, Function, NumRepetitions);<br>
+  return InstrBenchmark;<br>
+}<br>
+<br>
+} // namespace exegesis<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkRunner.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/BenchmarkRunner.h?<wbr>rev=329169&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkRunner.h (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/BenchmarkRunner.h Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,64 @@<br>
+//===-- BenchmarkRunner.h ------------------------------<wbr>---------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+///<br>
+/// \file<br>
+/// Defines the abstract BenchmarkRunner class for measuring a certain execution<br>
+/// property of instructions (e.g. latency).<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+<br>
+#ifndef LLVM_TOOLS_LLVM_EXEGESIS_BENCH<wbr>MARKRUNNER_H<br>
+#define LLVM_TOOLS_LLVM_EXEGESIS_BENCH<wbr>MARKRUNNER_H<br>
+<br>
+#include "BenchmarkResult.h"<br>
+#include "InMemoryAssembler.h"<br>
+#include "LlvmState.h"<br>
+#include "llvm/MC/MCInst.h"<br>
+#include "llvm/Support/Error.h"<br>
+#include <vector><br>
+<br>
+namespace exegesis {<br>
+<br>
+// Common code for all benchmark modes.<br>
+class BenchmarkRunner {<br>
+public:<br>
+  // Subtargets can disable running benchmarks for some instructions by<br>
+  // returning an error here.<br>
+  class InstructionFilter {<br>
+  public:<br>
+    virtual ~InstructionFilter();<br>
+<br>
+    virtual llvm::Error shouldRun(const LLVMState &State,<br>
+                             <wbr>     unsigned Opcode) const {<br>
+      return llvm::ErrorSuccess();<br>
+    }<br>
+  };<br>
+<br>
+  virtual ~BenchmarkRunner();<br>
+<br>
+  InstructionBenchmark run(const LLVMState &State, unsigned Opcode,<br>
+                           unsigned NumRepetitions,<br>
+                           const InstructionFilter &Filter) const;<br>
+<br>
+private:<br>
+  virtual const char *getDisplayName() const = 0;<br>
+<br>
+  virtual llvm::Expected<std::vector<llv<wbr>m::MCInst>><br>
+  createCode(const LLVMState &State, unsigned OpcodeIndex,<br>
+             unsigned NumRepetitions,<br>
+             const JitFunctionContext &Context) const = 0;<br>
+<br>
+  virtual std::vector<BenchmarkMeasure><br>
+  runMeasurements(const LLVMState &State, const JitFunction &Function,<br>
+                  unsigned NumRepetitions) const = 0;<br>
+};<br>
+<br>
+} // namespace exegesis<br>
+<br>
+#endif // LLVM_TOOLS_LLVM_EXEGESIS_BENCH<wbr>MARKRUNNER_H<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/CMakeLists.txt?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/CMakeLists.txt?rev=<wbr>329169&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/CMakeLists.txt (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/CMakeLists.txt Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,25 @@<br>
+add_library(LLVMExegesis<br>
+  STATIC<br>
+  BenchmarkResult.cpp<br>
+  BenchmarkRunner.cpp<br>
+  InMemoryAssembler.cpp<br>
+  InstructionSnippetGenerator.cp<wbr>p<br>
+  Latency.cpp<br>
+  LlvmState.cpp<br>
+  OperandGraph.cpp<br>
+  PerfHelper.cpp<br>
+  Uops.cpp<br>
+  X86.cpp<br>
+  )<br>
+<br>
+llvm_update_compile_flags(LLV<wbr>MExegesis)<br>
+llvm_map_components_to_libnam<wbr>es(libs<br>
+  CodeGen<br>
+  ExecutionEngine<br>
+  MC<br>
+  MCJIT<br>
+  Support<br>
+  )<br>
+<br>
+target_link_libraries(LLVMExe<wbr>gesis ${libs})<br>
+set_target_properties(LLVMExe<wbr>gesis PROPERTIES FOLDER "Libraries")<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/InMemoryAssembler.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/InMemoryAssembler.cpp?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/InMemoryAssembler.<wbr>cpp?rev=329169&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/InMemoryAssembler.cpp (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/InMemoryAssembler.cpp Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,226 @@<br>
+//===-- InMemoryAssembler.cpp ------------------------------<wbr>-----*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+<br>
+#include "InMemoryAssembler.h"<br>
+#include "llvm/ADT/SmallVector.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/CodeGen/MachineInstrBuil<wbr>der.h"<br>
+#include "llvm/CodeGen/MachineModuleInf<wbr>o.h"<br>
+#include "llvm/CodeGen/MachineRegisterI<wbr>nfo.h"<br>
+#include "llvm/CodeGen/TargetInstrInfo.<wbr>h"<br>
+#include "llvm/CodeGen/TargetPassConfig<wbr>.h"<br>
+#include "llvm/ExecutionEngine/Executio<wbr>nEngine.h"<br>
+#include "llvm/ExecutionEngine/MCJIT.h"<br>
+#include "llvm/ExecutionEngine/SectionM<wbr>emoryManager.h"<br>
+#include "llvm/IR/LLVMContext.h"<br>
+#include "llvm/IR/LegacyPassManager.h"<br>
+#include "llvm/MC/MCFixup.h"<br>
+#include "llvm/MC/MCInstrDesc.h"<br>
+#include "llvm/Object/Binary.h"<br>
+#include "llvm/Object/ObjectFile.h"<br>
+#include "llvm/PassInfo.h"<br>
+#include "llvm/PassRegistry.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+#include "llvm/Target/TargetMachine.h"<br>
+#include "llvm/Target/TargetOptions.h"<br>
+<br>
+namespace exegesis {<br>
+<br>
+static constexpr const char ModuleID[] = "ExegesisInfoTest";<br>
+static constexpr const char FunctionID[] = "foo";<br>
+<br>
+// Small utility function to add named passes.<br>
+static bool addPass(llvm::PassManagerBase &PM, llvm::StringRef PassName,<br>
+                    llvm::TargetPassConfig &TPC) {<br>
+  const llvm::PassRegistry *PR = llvm::PassRegistry::getPassReg<wbr>istry();<br>
+  const llvm::PassInfo *PI = PR->getPassInfo(PassName);<br>
+  if (!PI) {<br>
+    llvm::errs() << " run-pass " << PassName << " is not registered.\n";<br>
+    return true;<br>
+  }<br>
+<br>
+  if (!PI->getNormalCtor()) {<br>
+    llvm::errs() << " cannot create pass: " << PI->getPassName() << "\n";<br>
+    return true;<br>
+  }<br>
+  llvm::Pass *P = PI->getNormalCtor()();<br>
+  std::string Banner = std::string("After ") + std::string(P->getPassName());<br>
+  PM.add(P);<br>
+  TPC.printAndVerify(Banner);<br>
+<br>
+  return false;<br>
+}<br>
+<br>
+// Creates a void MachineFunction with no argument.<br>
+static llvm::MachineFunction &<br>
+createVoidVoidMachineFunction<wbr>(llvm::StringRef FunctionID, llvm::Module *Module,<br>
+                              llvm::MachineModuleInfo *MMI) {<br>
+  llvm::Type *const ReturnType = llvm::Type::getInt32Ty(Module-<wbr>>getContext());<br>
+  llvm::FunctionType *FunctionType = llvm::FunctionType::get(Return<wbr>Type, false);<br>
+  llvm::Function *const F = llvm::Function::Create(<br>
+      FunctionType, llvm::GlobalValue::InternalLin<wbr>kage, FunctionID, Module);<br>
+  // Making sure we can create a MachineFunction out of this Function even if it<br>
+  // contains no IR.<br>
+  F->setIsMaterializable(true);<br>
+  return MMI->getOrCreateMachineFunctio<wbr>n(*F);<br>
+}<br>
+<br>
+static llvm::object::OwningBinary<llv<wbr>m::object::ObjectFile><br>
+assemble(llvm::Module *Module, std::unique_ptr<llvm::MachineM<wbr>oduleInfo> MMI,<br>
+         llvm::LLVMTargetMachine *LLVMTM) {<br>
+  llvm::legacy::PassManager PM;<br>
+  llvm::MCContext &Context = MMI->getContext();<br>
+<br>
+  llvm::TargetLibraryInfoImpl TLII(llvm::Triple(Module->getT<wbr>argetTriple()));<br>
+  PM.add(new llvm::TargetLibraryInfoWrapper<wbr>Pass(TLII));<br>
+<br>
+  llvm::TargetPassConfig *TPC = LLVMTM->createPassConfig(PM);<br>
+  PM.add(TPC);<br>
+  PM.add(MMI.release());<br>
+  TPC->printAndVerify("MachineFu<wbr>nctionGenerator::assemble");<br>
+  // Adding the following passes:<br>
+  // - machineverifier: checks that the MachineFunction is well formed.<br>
+  // - prologepilog: saves and restore callee saved registers.<br>
+  for (const char *PassName : {"machineverifier", "prologepilog"})<br>
+    if (addPass(PM, PassName, *TPC))<br>
+      llvm::report_fatal_error("Unab<wbr>le to add a mandatory pass");<br>
+  TPC->setInitialized();<br>
+<br>
+  llvm::SmallVector<char, 4096> AsmBuffer;<br>
+  llvm::raw_svector_ostream AsmStream(AsmBuffer);<br>
+  // AsmPrinter is responsible for generating the assembly into AsmBuffer.<br>
+  if (LLVMTM->addAsmPrinter(PM, AsmStream, llvm::TargetMachine::CGFT_Obje<wbr>ctFile,<br>
+                            Context))<br>
+    llvm::report_fatal_error("Cann<wbr>ot add AsmPrinter passes");<br>
+<br>
+  PM.run(*Module); // Run all the passes<br>
+<br>
+  // Storing the generated assembly into a MemoryBuffer that owns the memory.<br>
+  std::unique_ptr<llvm::MemoryBu<wbr>ffer> Buffer =<br>
+      llvm::MemoryBuffer::getMemBuff<wbr>erCopy(AsmStream.str());<br>
+  // Create the ObjectFile from the MemoryBuffer.<br>
+  std::unique_ptr<llvm::object::<wbr>ObjectFile> Obj = llvm::cantFail(<br>
+      llvm::object::ObjectFile::crea<wbr>teObjectFile(Buffer->getMemBuf<wbr>ferRef()));<br>
+  // Returning both the MemoryBuffer and the ObjectFile.<br>
+  return llvm::object::OwningBinary<llv<wbr>m::object::ObjectFile>(<br>
+      std::move(Obj), std::move(Buffer));<br>
+}<br>
+<br>
+static void fillMachineFunction(llvm::Mach<wbr>ineFunction &MF,<br>
+                             <wbr>   llvm::ArrayRef<llvm::MCInst> Instructions) {<br>
+  llvm::MachineBasicBlock *MBB = MF.CreateMachineBasicBlock();<br>
+  MF.push_back(MBB);<br>
+  const llvm::MCInstrInfo *MCII = MF.getTarget().getMCInstrInfo(<wbr>);<br>
+  const llvm::DebugLoc DL;<br>
+  for (const llvm::MCInst &Inst : Instructions) {<br>
+    const unsigned Opcode = Inst.getOpcode();<br>
+    const llvm::MCInstrDesc &MCID = MCII->get(Opcode);<br>
+    llvm::MachineInstrBuilder Builder = llvm::BuildMI(MBB, DL, MCID);<br>
+    for (unsigned OpIndex = 0, E = Inst.getNumOperands(); OpIndex < E;<br>
+         ++OpIndex) {<br>
+      const llvm::MCOperand &Op = Inst.getOperand(OpIndex);<br>
+      if (Op.isReg()) {<br>
+        const bool IsDef = OpIndex < MCID.getNumDefs();<br>
+        unsigned Flags = 0;<br>
+        const llvm::MCOperandInfo &OpInfo = MCID.operands().begin()[OpInde<wbr>x];<br>
+        if (IsDef && !OpInfo.isOptionalDef())<br>
+          Flags |= llvm::RegState::Define;<br>
+        Builder.addReg(Op.getReg(), Flags);<br>
+      } else if (Op.isImm()) {<br>
+        Builder.addImm(Op.getImm());<br>
+      } else {<br>
+        llvm_unreachable("Not yet implemented");<br>
+      }<br>
+    }<br>
+  }<br>
+  // Adding the Return Opcode.<br>
+  const llvm::TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo<wbr>();<br>
+  llvm::BuildMI(MBB, DL, TII->get(TII->getReturnOpcode(<wbr>)));<br>
+}<br>
+<br>
+namespace {<br>
+<br>
+// Implementation of this class relies on the fact that a single object with a<br>
+// single function will be loaded into memory.<br>
+class TrackingSectionMemoryManager : public llvm::SectionMemoryManager {<br>
+public:<br>
+  explicit TrackingSectionMemoryManager(u<wbr>intptr_t *CodeSize)<br>
+      : CodeSize(CodeSize) {}<br>
+<br>
+  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,<br>
+                             <wbr>  unsigned SectionID,<br>
+                             <wbr>  llvm::StringRef SectionName) override {<br>
+    *CodeSize = Size;<br>
+    return llvm::SectionMemoryManager::al<wbr>locateCodeSection(<br>
+        Size, Alignment, SectionID, SectionName);<br>
+  }<br>
+<br>
+private:<br>
+  uintptr_t *const CodeSize = nullptr;<br>
+};<br>
+<br>
+} // namespace<br>
+<br>
+JitFunctionContext::JitFuncti<wbr>onContext(<br>
+    std::unique_ptr<llvm::LLVMTarg<wbr>etMachine> TheTM)<br>
+    : Context(llvm::make_unique<llvm<wbr>::LLVMContext>()), TM(std::move(TheTM)),<br>
+      MMI(llvm::make_unique<llvm::Ma<wbr>chineModuleInfo>(TM.get())),<br>
+      Module(llvm::make_unique<llvm:<wbr>:Module>(ModuleID, *Context)) {<br>
+  Module->setDataLayout(TM->crea<wbr>teDataLayout());<br>
+  MF = &createVoidVoidMachineFunction<wbr>(FunctionID, Module.get(), MMI.get());<br>
+  // We need to instruct the passes that we're done with SSA and virtual<br>
+  // registers.<br>
+  auto &Properties = MF->getProperties();<br>
+  Properties.set(llvm::MachineFu<wbr>nctionProperties::Property::<wbr>NoVRegs);<br>
+  Properties.reset(llvm::Machine<wbr>FunctionProperties::Property::<wbr>IsSSA);<br>
+  Properties.reset(llvm::Machine<wbr>FunctionProperties::Property::<wbr>TracksLiveness); <br>
+  // prologue/epilogue pass needs the reserved registers to be frozen, this is<br>
+  // usually done by the SelectionDAGISel pass.<br>
+  MF->getRegInfo().freezeReserve<wbr>dRegs(*MF);<br>
+  // Saving reserved registers for client.<br>
+  ReservedRegs = MF->getSubtarget().getRegister<wbr>Info()->getReservedRegs(*MF);<br>
+}<br>
+<br>
+JitFunction::JitFunction(JitF<wbr>unctionContext &&Context,<br>
+                         llvm::ArrayRef<llvm::MCInst> Instructions)<br>
+    : FunctionContext(std::move(Cont<wbr>ext)) {<br>
+  fillMachineFunction(*FunctionC<wbr>ontext.MF, Instructions);<br>
+  // We create the pass manager, run the passes and returns the produced<br>
+  // ObjectFile.<br>
+  llvm::object::OwningBinary<llv<wbr>m::object::ObjectFile> ObjHolder =<br>
+      assemble(FunctionContext.Modul<wbr>e.get(), std::move(FunctionContext.MMI)<wbr>,<br>
+               FunctionContext.TM.get());<br>
+  assert(ObjHolder.getBinary() && "cannot create object file");<br>
+  // Initializing the execution engine.<br>
+  // We need to use the JIT EngineKind to be able to add an object file.<br>
+  LLVMLinkInMCJIT();<br>
+  uintptr_t CodeSize = 0;<br>
+  std::string Error;<br>
+  ExecEngine.reset(<br>
+      llvm::EngineBuilder(std::move(<wbr>FunctionContext.Module))<br>
+          .setErrorStr(&Error)<br>
+          .setMCPU(FunctionContext.TM->g<wbr>etTargetCPU())<br>
+          .setEngineKind(llvm::EngineKin<wbr>d::JIT)<br>
+          .setMCJITMemoryManager(<br>
+              llvm::make_unique<TrackingSect<wbr>ionMemoryManager>(&CodeSize))<br>
+          .create(FunctionContext.TM.rel<wbr>ease()));<br>
+  if (!ExecEngine)<br>
+    llvm::report_fatal_error(Error<wbr>);<br>
+  // Adding the generated object file containing the assembled function.<br>
+  // The ExecutionEngine makes sure the object file is copied into an<br>
+  // executable page.<br>
+  ExecEngine->addObjectFile(ObjH<wbr>older.takeBinary().first);<br>
+  // Setting function<br>
+  FunctionBytes =<br>
+      llvm::StringRef(reinterpret_ca<wbr>st<const char *>(<br>
+                          ExecEngine->getFunctionAddress<wbr>(FunctionID)),<br>
+                      CodeSize);<br>
+}<br>
+<br>
+} // namespace exegesis<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/InMemoryAssembler.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/InMemoryAssembler.h?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/InMemoryAssembler.<wbr>h?rev=329169&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/InMemoryAssembler.h (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/InMemoryAssembler.h Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,78 @@<br>
+//===-- InMemoryAssembler.h ------------------------------<wbr>-------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+///<br>
+/// \file<br>
+/// Defines classes to assemble functions composed of a single basic block of<br>
+/// MCInsts.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+<br>
+#ifndef LLVM_TOOLS_LLVM_EXEGESIS_INMEM<wbr>ORYASSEMBLER_H<br>
+#define LLVM_TOOLS_LLVM_EXEGESIS_INMEM<wbr>ORYASSEMBLER_H<br>
+<br>
+#include "llvm/ADT/BitVector.h"<br>
+#include "llvm/CodeGen/MachineFunction.<wbr>h"<br>
+#include "llvm/CodeGen/MachineModuleInf<wbr>o.h"<br>
+#include "llvm/CodeGen/TargetRegisterIn<wbr>fo.h"<br>
+#include "llvm/ExecutionEngine/Executio<wbr>nEngine.h"<br>
+#include "llvm/IR/LLVMContext.h"<br>
+#include "llvm/MC/MCInst.h"<br>
+#include <memory><br>
+#include <vector><br>
+<br>
+namespace exegesis {<br>
+<br>
+// Consumable context for JitFunction below.<br>
+// This temporary object allows for retrieving MachineFunction properties before<br>
+// assembling it.<br>
+class JitFunctionContext {<br>
+public:<br>
+  explicit JitFunctionContext(std::unique<wbr>_ptr<llvm::LLVMTargetMachine> TM);<br>
+  // Movable<br>
+  JitFunctionContext(JitFunction<wbr>Context &&) = default;<br>
+  JitFunctionContext &operator=(JitFunctionContext &&) = default;<br>
+  // Non copyable<br>
+  JitFunctionContext(const JitFunctionContext &) = delete;<br>
+  JitFunctionContext &operator=(const JitFunctionContext &) = delete;<br>
+<br>
+  const llvm::BitVector &getReservedRegs() const { return ReservedRegs; }<br>
+<br>
+private:<br>
+  friend class JitFunction;<br>
+<br>
+  std::unique_ptr<llvm::LLVMCont<wbr>ext> Context;<br>
+  std::unique_ptr<llvm::LLVMTarg<wbr>etMachine> TM;<br>
+  std::unique_ptr<llvm::MachineM<wbr>oduleInfo> MMI;<br>
+  std::unique_ptr<llvm::Module> Module;<br>
+  llvm::MachineFunction *MF = nullptr;<br>
+  llvm::BitVector ReservedRegs;<br>
+};<br>
+<br>
+// Creates a void() function from a sequence of llvm::MCInst.<br>
+class JitFunction {<br>
+public:<br>
+  // Assembles Instructions into an executable function.<br>
+  JitFunction(JitFunctionContext &&Context,<br>
+              llvm::ArrayRef<llvm::MCInst> Instructions);<br>
+<br>
+  // Retrieves the function as an array of bytes.<br>
+  llvm::StringRef getFunctionBytes() const { return FunctionBytes; }<br>
+<br>
+  // Retrieves the callable function.<br>
+  void operator()() const { ((void (*)())FunctionBytes.data())(); }<br>
+<br>
+private:<br>
+  JitFunctionContext FunctionContext;<br>
+  std::unique_ptr<llvm::Executio<wbr>nEngine> ExecEngine;<br>
+  llvm::StringRef FunctionBytes;<br>
+};<br>
+<br>
+} // namespace exegesis<br>
+<br>
+#endif // LLVM_TOOLS_LLVM_EXEGESIS_INMEM<wbr>ORYASSEMBLER_H<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/InstructionSnippetGenerat<wbr>or.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/InstructionSnippetGenerator.cpp?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/InstructionSnippetG<wbr>enerator.cpp?rev=329169&view=<wbr>auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/InstructionSnippetGenerat<wbr>or.cpp (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/InstructionSnippetGenerat<wbr>or.cpp Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,355 @@<br>
+//===-- InstructionSnippetGenerator.cp<wbr>p -------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+<br>
+#include "InstructionSnippetGenerator.h<wbr>"<br>
+#include "llvm/ADT/MapVector.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/ADT/SmallSet.h"<br>
+#include "llvm/MC/MCInstBuilder.h"<br>
+#include <algorithm><br>
+#include <unordered_map><br>
+#include <unordered_set><br>
+<br>
+namespace exegesis {<br>
+<br>
+void Variable::print(llvm::raw_ostr<wbr>eam &OS,<br>
+                     const llvm::MCRegisterInfo *RegInfo) const {<br>
+  OS << "IsUse=" << IsUse << " IsDef=" << IsDef << " possible regs: {";<br>
+  for (const size_t Reg : PossibleRegisters) {<br>
+    if (RegInfo)<br>
+      OS << RegInfo->getName(Reg);<br>
+    else<br>
+      OS << Reg;<br>
+    OS << ",";<br>
+  }<br>
+  OS << "} ";<br>
+  if (ExplicitOperands.empty()) {<br>
+    OS << "implicit";<br>
+  } else {<br>
+    OS << "explicit ops: {";<br>
+    for (const size_t Op : ExplicitOperands)<br>
+      OS << Op << ",";<br>
+    OS << "}";<br>
+  }<br>
+  OS << "\n";<br>
+}<br>
+<br>
+// Update the state of a Variable with an explicit operand.<br>
+static void updateExplicitOperandVariable(<wbr>const llvm::MCRegisterInfo &RegInfo,<br>
+                             <wbr>             const llvm::MCInstrDesc &InstrInfo,<br>
+                             <wbr>             const size_t OpIndex,<br>
+                             <wbr>             const llvm::BitVector &ReservedRegs,<br>
+                             <wbr>             Variable &Var) {<br>
+  const bool IsDef = OpIndex < InstrInfo.getNumDefs();<br>
+  if (IsDef)<br>
+    Var.IsDef = true;<br>
+  if (!IsDef)<br>
+    Var.IsUse = true;<br>
+  Var.ExplicitOperands.push_back<wbr>(OpIndex);<br>
+  const llvm::MCOperandInfo &OpInfo = InstrInfo.opInfo_begin()[OpInd<wbr>ex];<br>
+  if (OpInfo.RegClass >= 0) {<br>
+    Var.IsReg = true;<br>
+    for (const llvm::MCPhysReg &Reg : RegInfo.getRegClass(OpInfo.Reg<wbr>Class)) {<br>
+      if (!ReservedRegs[Reg])<br>
+        Var.PossibleRegisters.insert(R<wbr>eg);<br>
+    }<br>
+  }<br>
+}<br>
+<br>
+static Variable &findVariableWithOperand(llvm:<wbr>:SmallVector<Variable, 8> &Vars,<br>
+                             <wbr>            size_t OpIndex) {<br>
+  // Vars.size() is small (<10) so a linear scan is good enough.<br>
+  for (Variable &Var : Vars) {<br>
+    if (llvm::is_contained(Var.Explic<wbr>itOperands, OpIndex))<br>
+      return Var;<br>
+  }<br>
+  assert(false && "Illegal state");<br>
+  static Variable *const EmptyVariable = new Variable();<br>
+  return *EmptyVariable;<br>
+}<br>
+<br>
+llvm::SmallVector<Variable, 8><br>
+getVariables(const llvm::MCRegisterInfo &RegInfo,<br>
+             const llvm::MCInstrDesc &InstrInfo,<br>
+             const llvm::BitVector &ReservedRegs) {<br>
+  llvm::SmallVector<Variable, 8> Vars;<br>
+  // For each operand, its "tied to" operand or -1.<br>
+  llvm::SmallVector<int, 10> TiedToMap;<br>
+  for (size_t I = 0, E = InstrInfo.getNumOperands(); I < E; ++I) {<br>
+    TiedToMap.push_back(InstrInfo.<wbr>getOperandConstraint(I, llvm::MCOI::TIED_TO));<br>
+  }<br>
+  // Adding non tied operands.<br>
+  for (size_t I = 0, E = InstrInfo.getNumOperands(); I < E; ++I) {<br>
+    if (TiedToMap[I] >= 0)<br>
+      continue; // dropping tied ones.<br>
+    Vars.emplace_back();<br>
+    updateExplicitOperandVariable(<wbr>RegInfo, InstrInfo, I, ReservedRegs,<br>
+                             <wbr>     Vars.back());<br>
+  }<br>
+  // Adding tied operands to existing variables.<br>
+  for (size_t I = 0, E = InstrInfo.getNumOperands(); I < E; ++I) {<br>
+    if (TiedToMap[I] < 0)<br>
+      continue; // dropping non-tied ones.<br>
+    updateExplicitOperandVariable(<wbr>RegInfo, InstrInfo, I, ReservedRegs,<br>
+                             <wbr>     findVariableWithOperand(Vars, TiedToMap[I]));<br>
+  }<br>
+  // Adding implicit defs.<br>
+  for (size_t I = 0, E = InstrInfo.getNumImplicitDefs()<wbr>; I < E; ++I) {<br>
+    Vars.emplace_back();<br>
+    Variable &Var = Vars.back();<br>
+    const llvm::MCPhysReg Reg = InstrInfo.getImplicitDefs()[I]<wbr>;<br>
+    assert(!ReservedRegs[Reg] && "implicit def of reserved register");<br>
+    Var.PossibleRegisters.insert(R<wbr>eg);<br>
+    Var.IsDef = true;<br>
+    Var.IsReg = true;<br>
+  }<br>
+  // Adding implicit uses.<br>
+  for (size_t I = 0, E = InstrInfo.getNumImplicitUses()<wbr>; I < E; ++I) {<br>
+    Vars.emplace_back();<br>
+    Variable &Var = Vars.back();<br>
+    const llvm::MCPhysReg Reg = InstrInfo.getImplicitUses()[I]<wbr>;<br>
+    assert(!ReservedRegs[Reg] && "implicit use of reserved register");<br>
+    Var.PossibleRegisters.insert(R<wbr>eg);<br>
+    Var.IsUse = true;<br>
+    Var.IsReg = true;<br>
+  }<br>
+<br>
+  return Vars;<br>
+}<br>
+<br>
+VariableAssignment::VariableA<wbr>ssignment(size_t VarIdx,<br>
+                             <wbr>          llvm::MCPhysReg AssignedReg)<br>
+    : VarIdx(VarIdx), AssignedReg(AssignedReg) {}<br>
+<br>
+bool VariableAssignment::operator==<wbr>(const VariableAssignment &Other) const {<br>
+  return std::tie(VarIdx, AssignedReg) ==<br>
+         std::tie(Other.VarIdx, Other.AssignedReg);<br>
+}<br>
+<br>
+bool VariableAssignment::operator<(<wbr>const VariableAssignment &Other) const {<br>
+  return std::tie(VarIdx, AssignedReg) <<br>
+         std::tie(Other.VarIdx, Other.AssignedReg);<br>
+}<br>
+<br>
+void dumpAssignmentChain(const llvm::MCRegisterInfo &RegInfo,<br>
+                         const AssignmentChain &Chain) {<br>
+  for (const VariableAssignment &Assignment : Chain) {<br>
+    llvm::outs() << llvm::format("(%d %s) ", Assignment.VarIdx,<br>
+                                 RegInfo.getName(Assignment.As<wbr>signedReg));<br>
+  }<br>
+  llvm::outs() << "\n";<br>
+}<br>
+<br>
+std::vector<AssignmentChain><br>
+computeSequentialAssignmentCh<wbr>ains(const llvm::MCRegisterInfo &RegInfo,<br>
+                             <wbr>     llvm::ArrayRef<Variable> Vars) {<br>
+  using graph::Node;<br>
+  graph::Graph Graph;<br>
+<br>
+  // Add register aliasing to the graph.<br>
+  setupRegisterAliasing(RegInfo, Graph);<br>
+<br>
+  // Adding variables to the graph.<br>
+  for (size_t I = 0, E = Vars.size(); I < E; ++I) {<br>
+    const Variable &Var = Vars[I];<br>
+    const Node N = Node::Var(I);<br>
+    if (Var.IsDef) {<br>
+      Graph.connect(Node::In(), N);<br>
+      for (const size_t Reg : Var.PossibleRegisters)<br>
+        Graph.connect(N, Node::Reg(Reg));<br>
+    }<br>
+    if (Var.IsUse) {<br>
+      Graph.connect(N, Node::Out());<br>
+      for (const size_t Reg : Var.PossibleRegisters)<br>
+        Graph.connect(Node::Reg(Reg), N);<br>
+    }<br>
+  }<br>
+<br>
+  // Find all possible dependency chains (aka all possible paths from In to Out<br>
+  // node).<br>
+  std::vector<AssignmentChain> AllChains;<br>
+  for (;;) {<br>
+    const auto Path = Graph.getPathFrom(Node::In(), Node::Out());<br>
+    if (Path.empty())<br>
+      break;<br>
+    switch (Path.size()) {<br>
+    case 0:<br>
+    case 1:<br>
+    case 2:<br>
+    case 4:<br>
+      assert(false && "Illegal state");<br>
+      break;<br>
+    case 3: { // IN -> variable -> OUT<br>
+      const size_t VarIdx = Path[1].varValue();<br>
+      for (size_t Reg : Vars[VarIdx].PossibleRegisters<wbr>) {<br>
+        AllChains.emplace_back();<br>
+        AllChains.back().emplace(VarId<wbr>x, Reg);<br>
+      }<br>
+      Graph.disconnect(Path[0], Path[1]); // IN -> variable<br>
+      Graph.disconnect(Path[1], Path[2]); // variable -> OUT<br>
+      break;<br>
+    }<br>
+    default: { // IN -> var1 -> Reg[...] -> var2 -> OUT<br>
+      const size_t Last = Path.size() - 1;<br>
+      const size_t Var1 = Path[1].varValue();<br>
+      const llvm::MCPhysReg Reg1 = Path[2].regValue();<br>
+      const llvm::MCPhysReg Reg2 = Path[Last - 2].regValue();<br>
+      const size_t Var2 = Path[Last - 1].varValue();<br>
+      AllChains.emplace_back();<br>
+      AllChains.back().emplace(Var1, Reg1);<br>
+      AllChains.back().emplace(Var2, Reg2);<br>
+      Graph.disconnect(Path[1], Path[2]); // Var1 -> Reg[0]<br>
+      break;<br>
+    }<br>
+    }<br>
+  }<br>
+<br>
+  return AllChains;<br>
+}<br>
+<br>
+std::vector<llvm::MCPhysReg><br>
+getRandomAssignment(llvm::Arr<wbr>ayRef<Variable> Vars,<br>
+                    llvm::ArrayRef<AssignmentChain<wbr>> Chains,<br>
+                    const std::function<size_t(size_t)> &RandomIndexForSize) {<br>
+  // Registers are initialized with 0 (aka NoRegister).<br>
+  std::vector<llvm::MCPhysReg> Registers(Vars.size(), 0);<br>
+  if (Chains.empty())<br>
+    return Registers;<br>
+  // Pick one of the chains and set Registers that are fully constrained (have<br>
+  // no degrees of freedom).<br>
+  const size_t ChainIndex = RandomIndexForSize(Chains.size<wbr>());<br>
+  for (const VariableAssignment Assignment : Chains[ChainIndex])<br>
+    Registers[Assignment.VarIdx] = Assignment.AssignedReg;<br>
+  // Registers with remaining degrees of freedom are assigned randomly.<br>
+  for (size_t I = 0, E = Vars.size(); I < E; ++I) {<br>
+    llvm::MCPhysReg &Reg = Registers[I];<br>
+    const Variable &Var = Vars[I];<br>
+    const auto &PossibleRegisters = Var.PossibleRegisters;<br>
+    if (Reg > 0 || PossibleRegisters.empty())<br>
+      continue;<br>
+    Reg = PossibleRegisters[RandomIndexF<wbr>orSize(PossibleRegisters.size(<wbr>))];<br>
+  }<br>
+  return Registers;<br>
+}<br>
+<br>
+// Finds a matching register `reg` for variable `VarIdx` and sets<br>
+// `RegAssignments[r]` to `VarIdx`. Returns false if no matching can be found.<br>
+// `seen.count(r)` is 1 if register `reg` has been processed.<br>
+static bool findMatchingRegister(<br>
+    llvm::ArrayRef<Variable> Vars, const size_t VarIdx,<br>
+    std::unordered_set<llvm::MCPhy<wbr>sReg> &Seen,<br>
+    std::unordered_map<llvm::MCPhy<wbr>sReg, size_t> &RegAssignments) {<br>
+  for (const llvm::MCPhysReg Reg : Vars[VarIdx].PossibleRegisters<wbr>) {<br>
+    if (!Seen.count(Reg)) {<br>
+      Seen.insert(Reg); // Mark `Reg` as seen.<br>
+      // If `Reg` is not assigned to a variable, or if `Reg` was assigned to a<br>
+      // variable which has an alternate possible register, assign `Reg` to<br>
+      // variable `VarIdx`. Since `Reg` is marked as assigned in the above line,<br>
+      // `RegAssignments[r]` in the following recursive call will not get<br>
+      // assigned `Reg` again.<br>
+      const auto AssignedVarIt = RegAssignments.find(Reg);<br>
+      if (AssignedVarIt == RegAssignments.end() ||<br>
+          findMatchingRegister(Vars, AssignedVarIt->second, Seen,<br>
+                             <wbr>  RegAssignments)) {<br>
+        RegAssignments[Reg] = VarIdx;<br>
+        return true;<br>
+      }<br>
+    }<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+// This is actually a maximum bipartite matching problem:<br>
+//   <a href="https://en.wikipedia.org/wiki/Matching_(graph_theory)#Bipartite_matching" rel="noreferrer" target="_blank">https://en.wikipedia.org/<wbr>wiki/Matching_(graph_theory)#B<wbr>ipartite_matching</a><br>
+// The graph has variables on the left and registers on the right, with an edge<br>
+// between variable `I` and register `Reg` iff<br>
+// `Vars[I].PossibleRegisters.cou<wbr>nt(A)`.<br>
+// Note that a greedy approach won't work for cases like:<br>
+//   Vars[0] PossibleRegisters={C,B}<br>
+//   Vars[1] PossibleRegisters={A,B}<br>
+//   Vars[2] PossibleRegisters={A,C}<br>
+// There is a feasible solution {0->B, 1->A, 2->C}, but the greedy solution is<br>
+// {0->C, 1->A, oops}.<br>
+std::vector<llvm::MCPhysReg><br>
+getExclusiveAssignment(llvm::<wbr>ArrayRef<Variable> Vars) {<br>
+  // `RegAssignments[r]` is the variable id that was assigned register `Reg`.<br>
+  std::unordered_map<llvm::MCPhy<wbr>sReg, size_t> RegAssignments;<br>
+<br>
+  for (size_t VarIdx = 0, E = Vars.size(); VarIdx < E; ++VarIdx) {<br>
+    if (!Vars[VarIdx].IsReg)<br>
+      continue;<br>
+    std::unordered_set<llvm::MCPhy<wbr>sReg> Seen;<br>
+    if (!findMatchingRegister(Vars, VarIdx, Seen, RegAssignments))<br>
+      return {}; // Infeasible.<br>
+  }<br>
+<br>
+  std::vector<llvm::MCPhysReg> Registers(Vars.size(), 0);<br>
+  for (const auto &RegVarIdx : RegAssignments)<br>
+    Registers[RegVarIdx.second] = RegVarIdx.first;<br>
+  return Registers;<br>
+}<br>
+<br>
+std::vector<llvm::MCPhysReg><br>
+getGreedyAssignment(llvm::Arr<wbr>ayRef<Variable> Vars) {<br>
+  std::vector<llvm::MCPhysReg> Registers(Vars.size(), 0);<br>
+  llvm::SmallSet<llvm::MCPhysReg<wbr>, 8> Assigned;<br>
+  for (size_t VarIdx = 0, E = Vars.size(); VarIdx < E; ++VarIdx) {<br>
+    const auto &Var = Vars[VarIdx];<br>
+    if (!Var.IsReg)<br>
+      continue;<br>
+    if (Var.PossibleRegisters.empty()<wbr>)<br>
+      return {};<br>
+    // Try possible registers until an unassigned one is found.<br>
+    for (const auto Reg : Var.PossibleRegisters) {<br>
+      if (Assigned.insert(Reg).second) {<br>
+        Registers[VarIdx] = Reg;<br>
+        break;<br>
+      }<br>
+    }<br>
+    // Fallback to first possible register.<br>
+    if (Registers[VarIdx] == 0)<br>
+      Registers[VarIdx] = Var.PossibleRegisters[0];<br>
+  }<br>
+  return Registers;<br>
+}<br>
+<br>
+llvm::MCInst generateMCInst(const llvm::MCInstrDesc &InstrInfo,<br>
+                            llvm::ArrayRef<Variable> Vars,<br>
+                            llvm::ArrayRef<llvm::MCPhysReg<wbr>> VarRegs) {<br>
+  const size_t NumOperands = InstrInfo.getNumOperands();<br>
+  llvm::SmallVector<llvm::MCPhys<wbr>Reg, 16> OperandToRegister(NumOperands, 0);<br>
+<br>
+  // We browse the variable and for each explicit operands we set the selected<br>
+  // register in the OperandToRegister array.<br>
+  for (size_t I = 0, E = Vars.size(); I < E; ++I) {<br>
+    for (const size_t OpIndex : Vars[I].ExplicitOperands) {<br>
+      OperandToRegister[OpIndex] = VarRegs[I];<br>
+    }<br>
+  }<br>
+<br>
+  // Building the instruction.<br>
+  llvm::MCInstBuilder Builder(InstrInfo.getOpcode())<wbr>;<br>
+  for (size_t I = 0, E = InstrInfo.getNumOperands(); I < E; ++I) {<br>
+    const llvm::MCOperandInfo &OpInfo = InstrInfo.opInfo_begin()[I];<br>
+    switch (OpInfo.OperandType) {<br>
+    case llvm::MCOI::OperandType::OPERA<wbr>ND_REGISTER:<br>
+      Builder.addReg(OperandToRegist<wbr>er[I]);<br>
+      break;<br>
+    case llvm::MCOI::OperandType::OPERA<wbr>ND_IMMEDIATE:<br>
+      Builder.addImm(1);<br>
+      break;<br>
+    default:<br>
+      Builder.addOperand(llvm::MCOpe<wbr>rand());<br>
+    }<br>
+  }<br>
+<br>
+  return Builder;<br>
+}<br>
+<br>
+} // namespace exegesis<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/InstructionSnippetGenerat<wbr>or.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/InstructionSnippetGenerator.h?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/InstructionSnippetG<wbr>enerator.h?rev=329169&view=<wbr>auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/InstructionSnippetGenerat<wbr>or.h (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/InstructionSnippetGenerat<wbr>or.h Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,119 @@<br>
+//===-- InstructionSnippetGenerator.h ---------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+///<br>
+/// \file<br>
+/// Defines helper classes to generate code snippets, in particular register<br>
+/// assignment.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+<br>
+#ifndef LLVM_TOOLS_LLVM_EXEGESIS_INSTR<wbr>UCTIONSNIPPETGENERATOR_H<br>
+#define LLVM_TOOLS_LLVM_EXEGESIS_INSTR<wbr>UCTIONSNIPPETGENERATOR_H<br>
+<br>
+#include "OperandGraph.h"<br>
+#include "llvm/ADT/BitVector.h"<br>
+#include "llvm/ADT/SetVector.h"<br>
+#include "llvm/ADT/SmallVector.h"<br>
+#include "llvm/MC/MCInst.h"<br>
+#include "llvm/MC/MCInstrDesc.h"<br>
+#include "llvm/MC/MCRegisterInfo.h"<br>
+#include <vector><br>
+<br>
+namespace exegesis {<br>
+<br>
+// A Variable represents a set of possible values that we need to choose from.<br>
+// It may represent one or more explicit operands that are tied together, or one<br>
+// implicit operand.<br>
+class Variable final {<br>
+public:<br>
+  bool IsUse = false;<br>
+  bool IsDef = false;<br>
+  bool IsReg = false;<br>
+<br>
+  // Lists all the explicit operand indices that are tied to this variable.<br>
+  // Empty if Variable represents an implicit operand.<br>
+  llvm::SmallVector<size_t, 8> ExplicitOperands;<br>
+<br>
+  // - In case of explicit operands, PossibleRegisters is the expansion of the<br>
+  // operands's RegClass registers. Please note that tied together explicit<br>
+  // operands share the same RegClass.<br>
+  // - In case of implicit operands, PossibleRegisters is a singleton MCPhysReg.<br>
+  llvm::SmallSetVector<llvm::MCP<wbr>hysReg, 16> PossibleRegisters;<br>
+<br>
+  // If RegInfo is null, register names won't get resolved.<br>
+  void print(llvm::raw_ostream &OS, const llvm::MCRegisterInfo *RegInfo) const;<br>
+};<br>
+<br>
+// Builds a model of implicit and explicit operands for InstrDesc into<br>
+// Variables.<br>
+llvm::SmallVector<Variable, 8><br>
+getVariables(const llvm::MCRegisterInfo &RegInfo,<br>
+             const llvm::MCInstrDesc &InstrDesc,<br>
+             const llvm::BitVector &ReservedRegs);<br>
+<br>
+// A simple object to represent a Variable assignement.<br>
+struct VariableAssignment {<br>
+  VariableAssignment(size_t VarIdx, llvm::MCPhysReg AssignedReg);<br>
+<br>
+  size_t VarIdx;<br>
+  llvm::MCPhysReg AssignedReg;<br>
+<br>
+  bool operator==(const VariableAssignment &) const;<br>
+  bool operator<(const VariableAssignment &) const;<br>
+};<br>
+<br>
+// An AssignmentChain is a set of assignement realizing a dependency chain.<br>
+// We inherit from std::set to leverage uniqueness of elements.<br>
+using AssignmentChain = std::set<VariableAssignment>;<br>
+<br>
+// Debug function to print an assignment chain.<br>
+void dumpAssignmentChain(const llvm::MCRegisterInfo &RegInfo,<br>
+                         const AssignmentChain &Chain);<br>
+<br>
+// Inserts Variables into a graph representing register aliasing and finds all<br>
+// the possible dependency chains for this instruction, i.e. all the possible<br>
+// assignement of operands that would make execution of the instruction<br>
+// sequential.<br>
+std::vector<AssignmentChain><br>
+computeSequentialAssignmentCh<wbr>ains(const llvm::MCRegisterInfo &RegInfo,<br>
+                             <wbr>     llvm::ArrayRef<Variable> Vars);<br>
+<br>
+// Selects a random configuration leading to a dependency chain.<br>
+// The result is a vector of the same size as `Vars`.<br>
+// `random_index_for_size` is a functor giving a random value in [0, arg[.<br>
+std::vector<llvm::MCPhysReg><br>
+getRandomAssignment(llvm::Arr<wbr>ayRef<Variable> Vars,<br>
+                    llvm::ArrayRef<AssignmentChain<wbr>> Chains,<br>
+                    const std::function<size_t(size_t)> &RandomIndexForSize);<br>
+<br>
+// Finds an assignment of registers to variables such that no two variables are<br>
+// assigned the same register.<br>
+// The result is a vector of the same size as `Vars`, or `{}` if the<br>
+// assignment is not feasible.<br>
+std::vector<llvm::MCPhysReg><br>
+getExclusiveAssignment(llvm::<wbr>ArrayRef<Variable> Vars);<br>
+<br>
+// Finds a greedy assignment of registers to variables. Each variable gets<br>
+// assigned the first possible register that is not already assigned to a<br>
+// previous variable. If there is no such register, the variable gets assigned<br>
+// the first possible register.<br>
+// The result is a vector of the same size as `Vars`, or `{}` if the<br>
+// assignment is not feasible.<br>
+std::vector<llvm::MCPhysReg><br>
+getGreedyAssignment(llvm::Arr<wbr>ayRef<Variable> Vars);<br>
+<br>
+// Generates an LLVM MCInst with the previously computed variables.<br>
+// Immediate values are set to 1.<br>
+llvm::MCInst generateMCInst(const llvm::MCInstrDesc &InstrDesc,<br>
+                            llvm::ArrayRef<Variable> Vars,<br>
+                            llvm::ArrayRef<llvm::MCPhysReg<wbr>> VarRegs);<br>
+<br>
+} // namespace exegesis<br>
+<br>
+#endif // LLVM_TOOLS_LLVM_EXEGESIS_INSTR<wbr>UCTIONSNIPPETGENERATOR_H<br>
<br>
Copied: llvm/trunk/tools/llvm-exegesis<wbr>/lib/LLVMBuild.txt (from r329157, llvm/trunk/tools/LLVMBuild.txt<wbr>)<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/LLVMBuild.txt?p2=llvm/trunk/tools/llvm-exegesis/lib/LLVMBuild.txt&p1=llvm/trunk/tools/LLVMBuild.txt&r1=329157&r2=329169&rev=329169&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/LLVMBuild.txt?p2=ll<wbr>vm/trunk/tools/llvm-exegesis/<wbr>lib/LLVMBuild.txt&p1=llvm/<wbr>trunk/tools/LLVMBuild.txt&r1=<wbr>329157&r2=329169&rev=329169&<wbr>view=diff</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/LLVMBuild.txt (original)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/LLVMBuild.txt Wed Apr  4 04:37:06 2018<br>
@@ -1,4 +1,4 @@<br>
-;===- ./tools/LLVMBuild.txt ------------------------------<wbr>------*- Conf -*--===;<br>
+;===- ./tools/llvm-exegesis/lib/LLVM<wbr>Build.txt ------------------*- Conf -*--===;<br>
  ;<br>
  ;                     The LLVM Compiler Infrastructure<br>
  ;<br>
@@ -15,44 +15,8 @@<br>
  ;<br>
  ;===--------------------------<wbr>------------------------------<wbr>----------------===; <br>
-[common]<br>
-subdirectories =<br>
- bugpoint<br>
- dsymutil<br>
- llc<br>
- lli<br>
- llvm-ar<br>
- llvm-as<br>
- llvm-bcanalyzer<br>
- llvm-cat<br>
- llvm-cfi-verify<br>
- llvm-cov<br>
- llvm-cvtres<br>
- llvm-diff<br>
- llvm-dis<br>
- llvm-dwarfdump<br>
- llvm-dwp<br>
- llvm-extract<br>
- llvm-jitlistener<br>
- llvm-link<br>
- llvm-lto<br>
- llvm-mc<br>
- llvm-mca<br>
- llvm-modextract<br>
- llvm-mt<br>
- llvm-nm<br>
- llvm-objcopy<br>
- llvm-objdump<br>
- llvm-pdbutil<br>
- llvm-profdata<br>
- llvm-rc<br>
- llvm-rtdyld<br>
- llvm-size<br>
- llvm-split<br>
- opt<br>
- verify-uselistorder<br>
-<br>
  [component_0]<br>
-type = Group<br>
-name = Tools<br>
-parent = $ROOT<br>
+type = Library<br>
+name = Exegesis<br>
+parent = Libraries<br>
+required_libraries = CodeGen ExecutionEngine MC MCJIT Object Support<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/Latency.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/Latency.cpp?rev=329<wbr>169&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/Latency.cpp (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/Latency.cpp Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,95 @@<br>
+//===-- Latency.cpp ------------------------------<wbr>---------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+<br>
+#include "Latency.h"<br>
+#include "BenchmarkResult.h"<br>
+#include "InstructionSnippetGenerator.h<wbr>"<br>
+#include "PerfHelper.h"<br>
+#include "llvm/MC/MCInstrDesc.h"<br>
+#include "llvm/Support/Error.h"<br>
+#include <algorithm><br>
+#include <random><br>
+<br>
+namespace exegesis {<br>
+<br>
+// FIXME: Handle memory, see PR36905.<br>
+static bool isInvalidOperand(const llvm::MCOperandInfo &OpInfo) {<br>
+  switch (OpInfo.OperandType) {<br>
+  default:<br>
+    return true;<br>
+  case llvm::MCOI::OPERAND_IMMEDIATE:<br>
+  case llvm::MCOI::OPERAND_REGISTER:<br>
+    return false;<br>
+  }<br>
+}<br>
+<br>
+static llvm::Error makeError(llvm::Twine Msg) {<br>
+  return llvm::make_error<llvm::StringE<wbr>rror>(Msg,<br>
+                                             llvm::inconvertibleErrorCode(<wbr>));<br>
+}<br>
+<br>
+LatencyBenchmarkRunner::~Late<wbr>ncyBenchmarkRunner() = default;<br>
+<br>
+const char *LatencyBenchmarkRunner::getDi<wbr>splayName() const { return "latency"; }<br>
+<br>
+llvm::Expected<std::vector<ll<wbr>vm::MCInst>> LatencyBenchmarkRunner::create<wbr>Code(<br>
+    const LLVMState &State, const unsigned OpcodeIndex,<br>
+    const unsigned NumRepetitions, const JitFunctionContext &Context) const {<br>
+  std::default_random_engine RandomEngine;<br>
+  const auto GetRandomIndex = [&RandomEngine](size_t Size) {<br>
+    assert(Size > 0 && "trying to get select a random element of an empty set");<br>
+    return std::uniform_int_distribution<<wbr>>(0, Size - 1)(RandomEngine);<br>
+  };<br>
+<br>
+  const auto &InstrInfo = State.getInstrInfo();<br>
+  const auto &RegInfo = State.getRegInfo();<br>
+  const llvm::MCInstrDesc &InstrDesc = InstrInfo.get(OpcodeIndex);<br>
+  for (const llvm::MCOperandInfo &OpInfo : InstrDesc.operands()) {<br>
+    if (isInvalidOperand(OpInfo))<br>
+      return makeError("Only registers and immediates are supported");<br>
+  }<br>
+<br>
+  const auto Vars = getVariables(RegInfo, InstrDesc, Context.getReservedRegs());<br>
+  const std::vector<AssignmentChain> AssignmentChains =<br>
+      computeSequentialAssignmentCha<wbr>ins(RegInfo, Vars);<br>
+  if (AssignmentChains.empty())<br>
+    return makeError("Unable to find a dependency chain.");<br>
+  const std::vector<llvm::MCPhysReg> Regs =<br>
+      getRandomAssignment(Vars, AssignmentChains, GetRandomIndex);<br>
+  const llvm::MCInst Inst = generateMCInst(InstrDesc, Vars, Regs);<br>
+  if (!State.canAssemble(Inst))<br>
+    return makeError("MCInst does not assemble.");<br>
+  return std::vector<llvm::MCInst>(NumR<wbr>epetitions, Inst);<br>
+}<br>
+<br>
+std::vector<BenchmarkMeasure><br>
+LatencyBenchmarkRunner::runMe<wbr>asurements(const LLVMState &State,<br>
+                             <wbr>           const JitFunction &Function,<br>
+                             <wbr>           const unsigned NumRepetitions) const {<br>
+  // Cycle measurements include some overhead from the kernel. Repeat the<br>
+  // measure several times and take the minimum value.<br>
+  constexpr const int NumMeasurements = 30;<br>
+  int64_t MinLatency = std::numeric_limits<int64_t>::<wbr>max();<br>
+  // FIXME: Read the perf event from the MCSchedModel (see PR36984).<br>
+  const pfm::PerfEvent CyclesPerfEvent("UNHALTED_CORE<wbr>_CYCLES");<br>
+  if (!CyclesPerfEvent.valid())<br>
+    llvm::report_fatal_error("inva<wbr>lid perf event 'UNHALTED_CORE_CYCLES'");<br>
+  for (size_t I = 0; I < NumMeasurements; ++I) {<br>
+    pfm::Counter Counter(CyclesPerfEvent);<br>
+    Counter.start();<br>
+    Function();<br>
+    Counter.stop();<br>
+    const int64_t Value = Counter.read();<br>
+    if (Value < MinLatency)<br>
+      MinLatency = Value;<br>
+  }<br>
+  return {{"latency", static_cast<double>(MinLatency<wbr>) / NumRepetitions}};<br>
+}<br>
+<br>
+} // namespace exegesis<br>
<br>
Added: llvm/trunk/tools/llvm-exegesis<wbr>/lib/Latency.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Latency.h?rev=329169&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/tools/llvm-ex<wbr>egesis/lib/Latency.h?rev=32916<wbr>9&view=auto</a> <br>
==============================<wbr>==============================<wbr>================== <br>
--- llvm/trunk/tools/llvm-exegesis<wbr>/lib/Latency.h (added)<br>
+++ llvm/trunk/tools/llvm-exegesis<wbr>/lib/Latency.h Wed Apr  4 04:37:06 2018<br>
@@ -0,0 +1,41 @@<br>
+//===-- Latency.h ------------------------------<wbr>-----------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+///<br>
+/// \file<br>
+/// A BenchmarkRunner implementation to measure instruction latencies.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===// <br>
+<br>
+#ifndef LLVM_TOOLS_LLVM_EXEGESIS_LATEN<wbr>CY_H<br>
+#define LLVM_TOOLS_LLVM_EXEGESIS_LATEN<wbr>CY_H<br>
+<br>
+#include "BenchmarkRunner.h"<br>
+<br>
+namespace exegesis {<br>
+<br>
+class LatencyBenchmarkRunner : public BenchmarkRunner {<br>
+public:<br>
+  ~LatencyBenchmarkRunner() override;<br>
+<br>
+private:<br>
+  const char *getDisplayName() const override;<br>
+<br>
+  llvm::Expected<std::vector<llv<wbr>m::MCInst>><br>
+  createCode(const LLVMState &State, unsigned OpcodeIndex,<br>
+             unsigned NumRepetitions,<br>
+             const JitFunctionContext &Context) const override;<br>
+<br>
+  std::vector<BenchmarkMeasure></blockquote></blockquote>
</blockquote></div><br></div>