[llvm] r319324 - Add opt-viewer testing

Adam Nemet via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 29 09:07:41 PST 2017


Author: anemet
Date: Wed Nov 29 09:07:41 2017
New Revision: 319324

URL: http://llvm.org/viewvc/llvm-project?rev=319324&view=rev
Log:
Add opt-viewer testing

Detects whether we have the Python modules (pygments, yaml) required by
opt-viewer and hooks this up to REQUIRES.

This fixes https://bugs.llvm.org/show_bug.cgi?id=34129 (the lack of opt-viewer
testing).

It's also related to https://github.com/apple/swift/pull/12938 and the idea is
to expose LLVM_HAVE_OPT_VIEWER_MODULES to the Swift cmake.

Differential Revision: https://reviews.llvm.org/D40202

Fixes since the first commit:
1. Disable syntax highlighting as different versions of pygments generate
different HTML
2. Use llvm-cxxfilt from the build

Added:
    llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.c
    llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.h
    llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.yaml
    llvm/trunk/test/tools/opt-viewer/Outputs/basic/basic_or.c.html
    llvm/trunk/test/tools/opt-viewer/Outputs/basic/basic_or.h.html
    llvm/trunk/test/tools/opt-viewer/Outputs/basic/index.html
    llvm/trunk/test/tools/opt-viewer/Outputs/basic/style.css
    llvm/trunk/test/tools/opt-viewer/basic.test
    llvm/trunk/test/tools/opt-viewer/lit.local.cfg
Modified:
    llvm/trunk/cmake/config-ix.cmake
    llvm/trunk/test/lit.cfg.py
    llvm/trunk/test/lit.site.cfg.py.in
    llvm/trunk/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
    llvm/trunk/tools/opt-viewer/opt-viewer.py
    llvm/trunk/tools/opt-viewer/optrecord.py

Modified: llvm/trunk/cmake/config-ix.cmake
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/config-ix.cmake?rev=319324&r1=319323&r2=319324&view=diff
==============================================================================
--- llvm/trunk/cmake/config-ix.cmake (original)
+++ llvm/trunk/cmake/config-ix.cmake Wed Nov 29 09:07:41 2017
@@ -628,3 +628,34 @@ else()
 endif()
 
 string(REPLACE " " ";" LLVM_BINDINGS_LIST "${LLVM_BINDINGS}")
+
+function(find_python_module module)
+  string(TOUPPER ${module} module_upper)
+  set(FOUND_VAR PY_${module_upper}_FOUND)
+
+  execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "import ${module}"
+    RESULT_VARIABLE status
+    ERROR_QUIET)
+
+  if(status)
+    set(${FOUND_VAR} 0 PARENT_SCOPE)
+    message(STATUS "Could NOT find Python module ${module}")
+  else()
+    set(${FOUND_VAR} 1 PARENT_SCOPE)
+    message(STATUS "Found Python module ${module}")
+  endif()
+endfunction()
+
+set (PYTHON_MODULES
+  pygments
+  yaml
+  )
+foreach(module ${PYTHON_MODULES})
+  find_python_module(${module})
+endforeach()
+
+if(PY_PYGMENTS_FOUND AND PY_YAML_FOUND)
+  set (LLVM_HAVE_OPT_VIEWER_MODULES 1)
+else()
+  set (LLVM_HAVE_OPT_VIEWER_MODULES 0)
+endif()

Modified: llvm/trunk/test/lit.cfg.py
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/lit.cfg.py?rev=319324&r1=319323&r2=319324&view=diff
==============================================================================
--- llvm/trunk/test/lit.cfg.py (original)
+++ llvm/trunk/test/lit.cfg.py Wed Nov 29 09:07:41 2017
@@ -123,6 +123,7 @@ if config.have_ocamlopt:
     ocamlopt_command = '%s ocamlopt -cclib -L%s -cclib -Wl,-rpath,%s %s' % (
         config.ocamlfind_executable, config.llvm_lib_dir, config.llvm_lib_dir, config.ocaml_flags)
 
+opt_viewer_cmd = '%s %s/tools/opt-viewer/opt-viewer.py' % (sys.executable, config.llvm_src_root)
 
 tools = [
     ToolSubst('%lli', FindTool('lli'), post='.', extra_args=lli_args),
@@ -132,6 +133,7 @@ tools = [
     ToolSubst('%ld64', ld64_cmd, unresolved='ignore'),
     ToolSubst('%ocamlc', ocamlc_command, unresolved='ignore'),
     ToolSubst('%ocamlopt', ocamlopt_command, unresolved='ignore'),
+    ToolSubst('%opt-viewer', opt_viewer_cmd),
 ]
 
 # FIXME: Why do we have both `lli` and `%lli` that do slightly different things?
@@ -286,3 +288,6 @@ if config.have_libxar:
 
 if config.llvm_libxml2_enabled == '1':
     config.available_features.add('libxml2')
+
+if config.have_opt_viewer_modules:
+    config.available_features.add('have_opt_viewer_modules')

Modified: llvm/trunk/test/lit.site.cfg.py.in
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/lit.site.cfg.py.in?rev=319324&r1=319323&r2=319324&view=diff
==============================================================================
--- llvm/trunk/test/lit.site.cfg.py.in (original)
+++ llvm/trunk/test/lit.site.cfg.py.in Wed Nov 29 09:07:41 2017
@@ -43,6 +43,7 @@ config.link_llvm_dylib = @LLVM_LINK_LLVM
 config.llvm_libxml2_enabled = "@LLVM_LIBXML2_ENABLED@"
 config.llvm_host_triple = '@LLVM_HOST_TRIPLE@'
 config.host_arch = "@HOST_ARCH@"
+config.have_opt_viewer_modules = @LLVM_HAVE_OPT_VIEWER_MODULES@
 
 # Support substitution of the tools_dir with user parameters. This is
 # used when we can't determine the tool dir at configuration time.

Added: llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.c
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.c?rev=319324&view=auto
==============================================================================
--- llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.c (added)
+++ llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.c Wed Nov 29 09:07:41 2017
@@ -0,0 +1,21 @@
+void bar();
+void foo() { bar(); }
+
+#include "or.h"
+
+void Test(int *res, int *c, int *d, int *p, int n) {
+  int i;
+
+#pragma clang loop vectorize(assume_safety)
+  for (i = 0; i < 1600; i++) {
+    res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];
+  }
+
+  for (i = 0; i < 16; i++) {
+    res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];
+  }
+
+  foo();
+
+  foo(); bar(); foo();
+}

Added: llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.h?rev=319324&view=auto
==============================================================================
--- llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.h (added)
+++ llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.h Wed Nov 29 09:07:41 2017
@@ -0,0 +1,16 @@
+void TestH(int *res, int *c, int *d, int *p, int n) {
+  int i;
+
+#pragma clang loop vectorize(assume_safety)
+  for (i = 0; i < 1600; i++) {
+    res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];
+  }
+
+  for (i = 0; i < 16; i++) {
+    res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];
+  }
+
+  foo();
+
+  foo(); bar(); foo();
+}

Added: llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.yaml?rev=319324&view=auto
==============================================================================
--- llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.yaml (added)
+++ llvm/trunk/test/tools/opt-viewer/Inputs/basic/or.yaml Wed Nov 29 09:07:41 2017
@@ -0,0 +1,227 @@
+--- !Missed
+Pass:            inline
+Name:            NoDefinition
+DebugLoc:        { File: basic/or.c, Line: 2, Column: 14 }
+Function:        foo
+Args:
+  - Callee:          bar
+  - String:          ' will not be inlined into '
+  - Caller:          foo
+  - String:          ' because its definition is unavailable'
+...
+--- !Missed
+Pass:            inline
+Name:            NoDefinition
+DebugLoc:        { File: basic/or.h, Line: 15, Column: 10 }
+Function:        TestH
+Args:
+  - Callee:          bar
+  - String:          ' will not be inlined into '
+  - Caller:          TestH
+  - String:          ' because its definition is unavailable'
+...
+--- !Analysis
+Pass:            inline
+Name:            CanBeInlined
+DebugLoc:        { File: basic/or.h, Line: 13, Column: 3 }
+Function:        TestH
+Args:
+  - Callee:          foo
+  - String:          ' can be inlined into '
+  - Caller:          TestH
+  - String:          ' with cost='
+  - Cost:            '30'
+  - String:          ' (threshold='
+  - Threshold:       '412'
+  - String:          ')'
+...
+--- !Passed
+Pass:            inline
+Name:            Inlined
+DebugLoc:        { File: basic/or.h, Line: 13, Column: 3 }
+Function:        TestH
+Args:
+  - Callee:          foo
+  - String:          ' inlined into '
+  - Caller:          TestH
+...
+--- !Analysis
+Pass:            inline
+Name:            CanBeInlined
+DebugLoc:        { File: basic/or.h, Line: 15, Column: 3 }
+Function:        TestH
+Args:
+  - Callee:          foo
+  - String:          ' can be inlined into '
+  - Caller:          TestH
+  - String:          ' with cost='
+  - Cost:            '30'
+  - String:          ' (threshold='
+  - Threshold:       '412'
+  - String:          ')'
+...
+--- !Passed
+Pass:            inline
+Name:            Inlined
+DebugLoc:        { File: basic/or.h, Line: 15, Column: 3 }
+Function:        TestH
+Args:
+  - Callee:          foo
+  - String:          ' inlined into '
+  - Caller:          TestH
+...
+--- !Analysis
+Pass:            inline
+Name:            CanBeInlined
+DebugLoc:        { File: basic/or.h, Line: 15, Column: 17 }
+Function:        TestH
+Args:
+  - Callee:          foo
+  - String:          ' can be inlined into '
+  - Caller:          TestH
+  - String:          ' with cost='
+  - Cost:            '30'
+  - String:          ' (threshold='
+  - Threshold:       '412'
+  - String:          ')'
+...
+--- !Passed
+Pass:            inline
+Name:            Inlined
+DebugLoc:        { File: basic/or.h, Line: 15, Column: 17 }
+Function:        TestH
+Args:
+  - Callee:          foo
+  - String:          ' inlined into '
+  - Caller:          TestH
+...
+--- !Passed
+Pass:            loop-unroll
+Name:            FullyUnrolled
+DebugLoc:        { File: basic/or.h, Line: 9, Column: 3 }
+Function:        TestH
+Args:
+  - String:          'completely unrolled loop with '
+  - UnrollCount:     '16'
+  - String:          ' iterations'
+...
+--- !Missed
+Pass:            inline
+Name:            NoDefinition
+DebugLoc:        { File: basic/or.c, Line: 20, Column: 10 }
+Function:        Test
+Args:
+  - Callee:          bar
+  - String:          ' will not be inlined into '
+  - Caller:          Test
+  - String:          ' because its definition is unavailable'
+...
+--- !Analysis
+Pass:            inline
+Name:            CanBeInlined
+DebugLoc:        { File: basic/or.c, Line: 18, Column: 3 }
+Function:        Test
+Args:
+  - Callee:          foo
+  - String:          ' can be inlined into '
+  - Caller:          Test
+  - String:          ' with cost='
+  - Cost:            '30'
+  - String:          ' (threshold='
+  - Threshold:       '412'
+  - String:          ')'
+...
+--- !Passed
+Pass:            inline
+Name:            Inlined
+DebugLoc:        { File: basic/or.c, Line: 18, Column: 3 }
+Function:        Test
+Args:
+  - Callee:          foo
+  - String:          ' inlined into '
+  - Caller:          Test
+...
+--- !Analysis
+Pass:            inline
+Name:            CanBeInlined
+DebugLoc:        { File: basic/or.c, Line: 20, Column: 3 }
+Function:        Test
+Args:
+  - Callee:          foo
+  - String:          ' can be inlined into '
+  - Caller:          Test
+  - String:          ' with cost='
+  - Cost:            '30'
+  - String:          ' (threshold='
+  - Threshold:       '412'
+  - String:          ')'
+...
+--- !Passed
+Pass:            inline
+Name:            Inlined
+DebugLoc:        { File: basic/or.c, Line: 20, Column: 3 }
+Function:        Test
+Args:
+  - Callee:          foo
+  - String:          ' inlined into '
+  - Caller:          Test
+...
+--- !Analysis
+Pass:            inline
+Name:            CanBeInlined
+DebugLoc:        { File: basic/or.c, Line: 20, Column: 17 }
+Function:        Test
+Args:
+  - Callee:          foo
+  - String:          ' can be inlined into '
+  - Caller:          Test
+  - String:          ' with cost='
+  - Cost:            '30'
+  - String:          ' (threshold='
+  - Threshold:       '412'
+  - String:          ')'
+...
+--- !Passed
+Pass:            inline
+Name:            Inlined
+DebugLoc:        { File: basic/or.c, Line: 20, Column: 17 }
+Function:        Test
+Args:
+  - Callee:          foo
+  - String:          ' inlined into '
+  - Caller:          Test
+...
+--- !Passed
+Pass:            loop-unroll
+Name:            FullyUnrolled
+DebugLoc:        { File: basic/or.c, Line: 14, Column: 3 }
+Function:        Test
+Args:
+  - String:          'completely unrolled loop with '
+  - UnrollCount:     '16'
+  - String:          ' iterations'
+...
+--- !Passed
+Pass:            loop-vectorize
+Name:            Vectorized
+DebugLoc:        { File: basic/or.h, Line: 5, Column: 3 }
+Function:        TestH
+Args:
+  - String:          'vectorized loop (vectorization width: '
+  - VectorizationFactor: '4'
+  - String:          ', interleaved count: '
+  - InterleaveCount: '2'
+  - String:          ')'
+...
+--- !Passed
+Pass:            loop-vectorize
+Name:            Vectorized
+DebugLoc:        { File: basic/or.c, Line: 10, Column: 3 }
+Function:        Test
+Args:
+  - String:          'vectorized loop (vectorization width: '
+  - VectorizationFactor: '4'
+  - String:          ', interleaved count: '
+  - InterleaveCount: '2'
+  - String:          ')'
+...

Added: llvm/trunk/test/tools/opt-viewer/Outputs/basic/basic_or.c.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/opt-viewer/Outputs/basic/basic_or.c.html?rev=319324&view=auto
==============================================================================
--- llvm/trunk/test/tools/opt-viewer/Outputs/basic/basic_or.c.html (added)
+++ llvm/trunk/test/tools/opt-viewer/Outputs/basic/basic_or.c.html Wed Nov 29 09:07:41 2017
@@ -0,0 +1,257 @@
+
+<html>
+<head>
+<link rel='stylesheet' type='text/css' href='style.css'>
+</head>
+<body>
+<div class="centered">
+<table class="source">
+<thead>
+<tr>
+<th style="width: 2%">Line</td>
+<th style="width: 3%">Hotness</td>
+<th style="width: 10%">Optimization</td>
+<th style="width: 70%">Source</td>
+<th style="width: 15%">Inline Context</td>
+</tr>
+</thead>
+<tbody>
+
+<tr>
+<td><a name="L1">1</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>void bar();</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L2">2</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>void foo() { bar(); }</pre></div></td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-red">inline</td>
+<td><pre style="display:inline">             </pre><span class="column-entry-yellow"> bar will not be inlined into foo because its definition is unavailable </span></td>
+<td class="column-entry-yellow">foo</td>
+</tr>
+
+<tr>
+<td><a name="L3">3</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L4">4</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>#include "or.h"</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L5">5</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L6">6</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>void Test(int *res, int *c, int *d, int *p, int n) {</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L7">7</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  int i;</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L8">8</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L9">9</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>#pragma clang loop vectorize(assume_safety)</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L10">10</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  for (i = 0; i < 1600; i++) {</pre></div></td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-green">loop-vectorize</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> vectorized loop (vectorization width: 4, interleaved count: 2) </span></td>
+<td class="column-entry-yellow">Test</td>
+</tr>
+
+<tr>
+<td><a name="L11">11</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>    res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L12">12</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  }</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L13">13</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L14">14</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  for (i = 0; i < 16; i++) {</pre></div></td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-green">loop-unroll</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> completely unrolled loop with 16 iterations </span></td>
+<td class="column-entry-yellow">Test</td>
+</tr>
+
+<tr>
+<td><a name="L15">15</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>    res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L16">16</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  }</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L17">17</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L18">18</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  foo();</pre></div></td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-white">inline</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> foo can be inlined into Test with cost=30 (threshold=412) </span></td>
+<td class="column-entry-yellow">Test</td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-green">inline</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> foo inlined into Test </span></td>
+<td class="column-entry-yellow">Test</td>
+</tr>
+
+<tr>
+<td><a name="L19">19</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L20">20</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  foo(); bar(); foo();</pre></div></td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-red">inline</td>
+<td><pre style="display:inline">         </pre><span class="column-entry-yellow"> bar will not be inlined into Test because its definition is unavailable </span></td>
+<td class="column-entry-yellow">Test</td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-white">inline</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> foo can be inlined into Test with cost=30 (threshold=412) </span></td>
+<td class="column-entry-yellow">Test</td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-green">inline</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> foo inlined into Test </span></td>
+<td class="column-entry-yellow">Test</td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-white">inline</td>
+<td><pre style="display:inline">                </pre><span class="column-entry-yellow"> foo can be inlined into Test with cost=30 (threshold=412) </span></td>
+<td class="column-entry-yellow">Test</td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-green">inline</td>
+<td><pre style="display:inline">                </pre><span class="column-entry-yellow"> foo inlined into Test </span></td>
+<td class="column-entry-yellow">Test</td>
+</tr>
+
+<tr>
+<td><a name="L21">21</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>}</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L22">22</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+</tbody>
+</table>
+</body>
+</html>

Added: llvm/trunk/test/tools/opt-viewer/Outputs/basic/basic_or.h.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/opt-viewer/Outputs/basic/basic_or.h.html?rev=319324&view=auto
==============================================================================
--- llvm/trunk/test/tools/opt-viewer/Outputs/basic/basic_or.h.html (added)
+++ llvm/trunk/test/tools/opt-viewer/Outputs/basic/basic_or.h.html Wed Nov 29 09:07:41 2017
@@ -0,0 +1,214 @@
+
+<html>
+<head>
+<link rel='stylesheet' type='text/css' href='style.css'>
+</head>
+<body>
+<div class="centered">
+<table class="source">
+<thead>
+<tr>
+<th style="width: 2%">Line</td>
+<th style="width: 3%">Hotness</td>
+<th style="width: 10%">Optimization</td>
+<th style="width: 70%">Source</td>
+<th style="width: 15%">Inline Context</td>
+</tr>
+</thead>
+<tbody>
+
+<tr>
+<td><a name="L1">1</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>void TestH(int *res, int *c, int *d, int *p, int n) {</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L2">2</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  int i;</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L3">3</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L4">4</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>#pragma clang loop vectorize(assume_safety)</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L5">5</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  for (i = 0; i < 1600; i++) {</pre></div></td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-green">loop-vectorize</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> vectorized loop (vectorization width: 4, interleaved count: 2) </span></td>
+<td class="column-entry-yellow">TestH</td>
+</tr>
+
+<tr>
+<td><a name="L6">6</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>    res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L7">7</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  }</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L8">8</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L9">9</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  for (i = 0; i < 16; i++) {</pre></div></td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-green">loop-unroll</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> completely unrolled loop with 16 iterations </span></td>
+<td class="column-entry-yellow">TestH</td>
+</tr>
+
+<tr>
+<td><a name="L10">10</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>    res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L11">11</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  }</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L12">12</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L13">13</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  foo();</pre></div></td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-white">inline</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> foo can be inlined into TestH with cost=30 (threshold=412) </span></td>
+<td class="column-entry-yellow">TestH</td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-green">inline</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> foo inlined into TestH </span></td>
+<td class="column-entry-yellow">TestH</td>
+</tr>
+
+<tr>
+<td><a name="L14">14</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L15">15</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>  foo(); bar(); foo();</pre></div></td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-red">inline</td>
+<td><pre style="display:inline">         </pre><span class="column-entry-yellow"> bar will not be inlined into TestH because its definition is unavailable </span></td>
+<td class="column-entry-yellow">TestH</td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-white">inline</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> foo can be inlined into TestH with cost=30 (threshold=412) </span></td>
+<td class="column-entry-yellow">TestH</td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-green">inline</td>
+<td><pre style="display:inline">  </pre><span class="column-entry-yellow"> foo inlined into TestH </span></td>
+<td class="column-entry-yellow">TestH</td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-white">inline</td>
+<td><pre style="display:inline">                </pre><span class="column-entry-yellow"> foo can be inlined into TestH with cost=30 (threshold=412) </span></td>
+<td class="column-entry-yellow">TestH</td>
+</tr>
+
+<tr>
+<td></td>
+<td></td>
+<td class="column-entry-green">inline</td>
+<td><pre style="display:inline">                </pre><span class="column-entry-yellow"> foo inlined into TestH </span></td>
+<td class="column-entry-yellow">TestH</td>
+</tr>
+
+<tr>
+<td><a name="L16">16</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre>}</pre></div></td>
+</tr>
+
+<tr>
+<td><a name="L17">17</a></td>
+<td></td>
+<td></td>
+<td><div class="highlight"><pre></pre></div></td>
+</tr>
+
+</tbody>
+</table>
+</body>
+</html>

Added: llvm/trunk/test/tools/opt-viewer/Outputs/basic/index.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/opt-viewer/Outputs/basic/index.html?rev=319324&view=auto
==============================================================================
--- llvm/trunk/test/tools/opt-viewer/Outputs/basic/index.html (added)
+++ llvm/trunk/test/tools/opt-viewer/Outputs/basic/index.html Wed Nov 29 09:07:41 2017
@@ -0,0 +1,151 @@
+
+<html>
+<head>
+<link rel='stylesheet' type='text/css' href='style.css'>
+</head>
+<body>
+<div class="centered">
+<table>
+<tr>
+<td>Source Location</td>
+<td>Hotness</td>
+<td>Function</td>
+<td>Pass</td>
+</tr>
+
+<tr>
+<td class="column-entry-0"><a href="basic_or.c.html#L2">basic/or.c:2:14</a></td>
+<td class="column-entry-0"></td>
+<td class="column-entry-0">foo</td>
+<td class="column-entry-red">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-1"><a href="basic_or.c.html#L10">basic/or.c:10:3</a></td>
+<td class="column-entry-1"></td>
+<td class="column-entry-1">Test</td>
+<td class="column-entry-green">loop-vectorize</td>
+</tr>
+
+<tr>
+<td class="column-entry-0"><a href="basic_or.c.html#L14">basic/or.c:14:3</a></td>
+<td class="column-entry-0"></td>
+<td class="column-entry-0">Test</td>
+<td class="column-entry-green">loop-unroll</td>
+</tr>
+
+<tr>
+<td class="column-entry-1"><a href="basic_or.c.html#L18">basic/or.c:18:3</a></td>
+<td class="column-entry-1"></td>
+<td class="column-entry-1">Test</td>
+<td class="column-entry-white">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-0"><a href="basic_or.c.html#L18">basic/or.c:18:3</a></td>
+<td class="column-entry-0"></td>
+<td class="column-entry-0">Test</td>
+<td class="column-entry-green">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-1"><a href="basic_or.c.html#L20">basic/or.c:20:3</a></td>
+<td class="column-entry-1"></td>
+<td class="column-entry-1">Test</td>
+<td class="column-entry-white">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-0"><a href="basic_or.c.html#L20">basic/or.c:20:3</a></td>
+<td class="column-entry-0"></td>
+<td class="column-entry-0">Test</td>
+<td class="column-entry-green">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-1"><a href="basic_or.c.html#L20">basic/or.c:20:10</a></td>
+<td class="column-entry-1"></td>
+<td class="column-entry-1">Test</td>
+<td class="column-entry-red">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-0"><a href="basic_or.c.html#L20">basic/or.c:20:17</a></td>
+<td class="column-entry-0"></td>
+<td class="column-entry-0">Test</td>
+<td class="column-entry-white">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-1"><a href="basic_or.c.html#L20">basic/or.c:20:17</a></td>
+<td class="column-entry-1"></td>
+<td class="column-entry-1">Test</td>
+<td class="column-entry-green">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-0"><a href="basic_or.h.html#L5">basic/or.h:5:3</a></td>
+<td class="column-entry-0"></td>
+<td class="column-entry-0">TestH</td>
+<td class="column-entry-green">loop-vectorize</td>
+</tr>
+
+<tr>
+<td class="column-entry-1"><a href="basic_or.h.html#L9">basic/or.h:9:3</a></td>
+<td class="column-entry-1"></td>
+<td class="column-entry-1">TestH</td>
+<td class="column-entry-green">loop-unroll</td>
+</tr>
+
+<tr>
+<td class="column-entry-0"><a href="basic_or.h.html#L13">basic/or.h:13:3</a></td>
+<td class="column-entry-0"></td>
+<td class="column-entry-0">TestH</td>
+<td class="column-entry-white">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-1"><a href="basic_or.h.html#L13">basic/or.h:13:3</a></td>
+<td class="column-entry-1"></td>
+<td class="column-entry-1">TestH</td>
+<td class="column-entry-green">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-0"><a href="basic_or.h.html#L15">basic/or.h:15:3</a></td>
+<td class="column-entry-0"></td>
+<td class="column-entry-0">TestH</td>
+<td class="column-entry-white">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-1"><a href="basic_or.h.html#L15">basic/or.h:15:3</a></td>
+<td class="column-entry-1"></td>
+<td class="column-entry-1">TestH</td>
+<td class="column-entry-green">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-0"><a href="basic_or.h.html#L15">basic/or.h:15:10</a></td>
+<td class="column-entry-0"></td>
+<td class="column-entry-0">TestH</td>
+<td class="column-entry-red">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-1"><a href="basic_or.h.html#L15">basic/or.h:15:17</a></td>
+<td class="column-entry-1"></td>
+<td class="column-entry-1">TestH</td>
+<td class="column-entry-white">inline</td>
+</tr>
+
+<tr>
+<td class="column-entry-0"><a href="basic_or.h.html#L15">basic/or.h:15:17</a></td>
+<td class="column-entry-0"></td>
+<td class="column-entry-0">TestH</td>
+<td class="column-entry-green">inline</td>
+</tr>
+
+</table>
+</body>
+</html>

Added: llvm/trunk/test/tools/opt-viewer/Outputs/basic/style.css
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/opt-viewer/Outputs/basic/style.css?rev=319324&view=auto
==============================================================================
--- llvm/trunk/test/tools/opt-viewer/Outputs/basic/style.css (added)
+++ llvm/trunk/test/tools/opt-viewer/Outputs/basic/style.css Wed Nov 29 09:07:41 2017
@@ -0,0 +1,208 @@
+.source {
+  table-layout: fixed;
+  width: 100%;
+  white-space: nowrap;
+}
+.source td {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.red {
+  background-color: #ffd0d0;
+}
+.cyan {
+  background-color: cyan;
+}
+body {
+  font-family: -apple-system, sans-serif;
+}
+pre {
+  margin-top: 0px !important;
+  margin-bottom: 0px !important;
+}
+.source-name-title {
+  padding: 5px 10px;
+  border-bottom: 1px solid #dbdbdb;
+  background-color: #eee;
+  line-height: 35px;
+}
+.centered {
+  display: table;
+  margin-left: left;
+  margin-right: auto;
+  border: 1px solid #dbdbdb;
+  border-radius: 3px;
+}
+.expansion-view {
+  background-color: rgba(0, 0, 0, 0);
+  margin-left: 0px;
+  margin-top: 5px;
+  margin-right: 5px;
+  margin-bottom: 5px;
+  border: 1px solid #dbdbdb;
+  border-radius: 3px;
+}
+table {
+  border-collapse: collapse;
+}
+.light-row {
+  background: #ffffff;
+  border: 1px solid #dbdbdb;
+}
+.column-entry {
+  text-align: right;
+}
+.column-entry-left {
+  text-align: left;
+}
+.column-entry-white {
+  text-align: right;
+  background-color: #ffffff;
+}
+.column-entry-red {
+  text-align: right;
+  background-color: #ffd0d0;
+}
+.column-entry-green {
+  text-align: right;
+  background-color: #d0ffd0;
+}
+.column-entry-yellow {
+  text-align: left;
+  background-color: #ffe1a6;
+}
+.column-entry-0 {
+  background-color: #ffffff;
+}
+.column-entry-1 {
+  background-color: #eeeeee;
+}
+.line-number {
+  text-align: right;
+  color: #aaa;
+}
+.covered-line {
+  text-align: right;
+  color: #0080ff;
+}
+.uncovered-line {
+  text-align: right;
+  color: #ff3300;
+}
+.tooltip {
+  position: relative;
+  display: inline;
+  background-color: #b3e6ff;
+  text-decoration: none;
+}
+.tooltip span.tooltip-content {
+  position: absolute;
+  width: 100px;
+  margin-left: -50px;
+  color: #FFFFFF;
+  background: #000000;
+  height: 30px;
+  line-height: 30px;
+  text-align: center;
+  visibility: hidden;
+  border-radius: 6px;
+}
+.tooltip span.tooltip-content:after {
+  content: '';
+  position: absolute;
+  top: 100%;
+  left: 50%;
+  margin-left: -8px;
+  width: 0; height: 0;
+  border-top: 8px solid #000000;
+  border-right: 8px solid transparent;
+  border-left: 8px solid transparent;
+}
+:hover.tooltip span.tooltip-content {
+  visibility: visible;
+  opacity: 0.8;
+  bottom: 30px;
+  left: 50%;
+  z-index: 999;
+}
+th, td {
+  vertical-align: top;
+  padding: 2px 5px;
+  border-collapse: collapse;
+  border-right: solid 1px #eee;
+  border-left: solid 1px #eee;
+}
+td:first-child {
+  border-left: none;
+}
+td:last-child {
+  border-right: none;
+}
+
+/* Generated with pygmentize -S colorful -f html >> style.css */
+
+.hll { background-color: #ffffcc }
+.c { color: #888888 } /* Comment */
+.err { color: #FF0000; background-color: #FFAAAA } /* Error */
+.k { color: #008800; font-weight: bold } /* Keyword */
+.o { color: #333333 } /* Operator */
+.ch { color: #888888 } /* Comment.Hashbang */
+.cm { color: #888888 } /* Comment.Multiline */
+.cp { color: #557799 } /* Comment.Preproc */
+.cpf { color: #888888 } /* Comment.PreprocFile */
+.c1 { color: #888888 } /* Comment.Single */
+.cs { color: #cc0000; font-weight: bold } /* Comment.Special */
+.gd { color: #A00000 } /* Generic.Deleted */
+.ge { font-style: italic } /* Generic.Emph */
+.gr { color: #FF0000 } /* Generic.Error */
+.gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.gi { color: #00A000 } /* Generic.Inserted */
+.go { color: #888888 } /* Generic.Output */
+.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
+.gs { font-weight: bold } /* Generic.Strong */
+.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.gt { color: #0044DD } /* Generic.Traceback */
+.kc { color: #008800; font-weight: bold } /* Keyword.Constant */
+.kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
+.kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
+.kp { color: #003388; font-weight: bold } /* Keyword.Pseudo */
+.kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
+.kt { color: #333399; font-weight: bold } /* Keyword.Type */
+.m { color: #6600EE; font-weight: bold } /* Literal.Number */
+.s { background-color: #fff0f0 } /* Literal.String */
+.na { color: #0000CC } /* Name.Attribute */
+.nb { color: #007020 } /* Name.Builtin */
+.nc { color: #BB0066; font-weight: bold } /* Name.Class */
+.no { color: #003366; font-weight: bold } /* Name.Constant */
+.nd { color: #555555; font-weight: bold } /* Name.Decorator */
+.ni { color: #880000; font-weight: bold } /* Name.Entity */
+.ne { color: #FF0000; font-weight: bold } /* Name.Exception */
+.nf { color: #0066BB; font-weight: bold } /* Name.Function */
+.nl { color: #997700; font-weight: bold } /* Name.Label */
+.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
+.nt { color: #007700 } /* Name.Tag */
+.nv { color: #996633 } /* Name.Variable */
+.ow { color: #000000; font-weight: bold } /* Operator.Word */
+.w { color: #bbbbbb } /* Text.Whitespace */
+.mb { color: #6600EE; font-weight: bold } /* Literal.Number.Bin */
+.mf { color: #6600EE; font-weight: bold } /* Literal.Number.Float */
+.mh { color: #005588; font-weight: bold } /* Literal.Number.Hex */
+.mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
+.mo { color: #4400EE; font-weight: bold } /* Literal.Number.Oct */
+.sb { background-color: #fff0f0 } /* Literal.String.Backtick */
+.sc { color: #0044DD } /* Literal.String.Char */
+.sd { color: #DD4422 } /* Literal.String.Doc */
+.s2 { background-color: #fff0f0 } /* Literal.String.Double */
+.se { color: #666666; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */
+.sh { background-color: #fff0f0 } /* Literal.String.Heredoc */
+.si { background-color: #eeeeee } /* Literal.String.Interpol */
+.sx { color: #DD2200; background-color: #fff0f0 } /* Literal.String.Other */
+.sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */
+.s1 { background-color: #fff0f0 } /* Literal.String.Single */
+.ss { color: #AA6600 } /* Literal.String.Symbol */
+.bp { color: #007020 } /* Name.Builtin.Pseudo */
+.vc { color: #336699 } /* Name.Variable.Class */
+.vg { color: #dd7700; font-weight: bold } /* Name.Variable.Global */
+.vi { color: #3333BB } /* Name.Variable.Instance */
+.il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */

Added: llvm/trunk/test/tools/opt-viewer/basic.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/opt-viewer/basic.test?rev=319324&view=auto
==============================================================================
--- llvm/trunk/test/tools/opt-viewer/basic.test (added)
+++ llvm/trunk/test/tools/opt-viewer/basic.test Wed Nov 29 09:07:41 2017
@@ -0,0 +1,9 @@
+# Since we're performing a full compare of the generate HTML files disable
+# syntax highlighting; pygments generates slightly different code with
+# different versions.
+
+RUN: %opt-viewer -s %p/Inputs -o %t %p/Inputs/basic/or.yaml --no-highlight --demangler=llvm-cxxfilt
+RUN: diff %p/Outputs/basic/index.html %t/index.html
+RUN: diff %p/Outputs/basic/basic_or.h.html %t/basic_or.h.html
+RUN: diff %p/Outputs/basic/basic_or.c.html %t/basic_or.c.html
+RUN: ls %t/style.css

Added: llvm/trunk/test/tools/opt-viewer/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/opt-viewer/lit.local.cfg?rev=319324&view=auto
==============================================================================
--- llvm/trunk/test/tools/opt-viewer/lit.local.cfg (added)
+++ llvm/trunk/test/tools/opt-viewer/lit.local.cfg Wed Nov 29 09:07:41 2017
@@ -0,0 +1,2 @@
+if 'have_opt_viewer_modules' not in config.available_features:
+    config.unsupported = True

Modified: llvm/trunk/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cxxfilt/llvm-cxxfilt.cpp?rev=319324&r1=319323&r2=319324&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cxxfilt/llvm-cxxfilt.cpp (original)
+++ llvm/trunk/tools/llvm-cxxfilt/llvm-cxxfilt.cpp Wed Nov 29 09:07:41 2017
@@ -75,6 +75,7 @@ static void demangle(llvm::raw_ostream &
   }
 
   OS << (Undecorated ? Undecorated : Mangled) << '\n';
+  OS.flush();
 
   free(Undecorated);
 }

Modified: llvm/trunk/tools/opt-viewer/opt-viewer.py
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt-viewer/opt-viewer.py?rev=319324&r1=319323&r2=319324&view=diff
==============================================================================
--- llvm/trunk/tools/opt-viewer/opt-viewer.py (original)
+++ llvm/trunk/tools/opt-viewer/opt-viewer.py Wed Nov 29 09:07:41 2017
@@ -60,19 +60,23 @@ class SourceFileRenderer:
 
     def render_source_lines(self, stream, line_remarks):
         file_text = stream.read()
-        html_highlighted = highlight(
+
+        if args.no_highlight:
+            html_highlighted = file_text
+        else:
+            html_highlighted = highlight(
             file_text,
-            self.cpp_lexer,
-            self.html_formatter)
+                self.cpp_lexer,
+                self.html_formatter)
 
-        # On Python 3, pygments.highlight() returns a bytes object, not a str.
-        if sys.version_info >= (3, 0):
-          html_highlighted = html_highlighted.decode('utf-8')
-
-        # Take off the header and footer, these must be
-        #   reapplied line-wise, within the page structure
-        html_highlighted = html_highlighted.replace('<div class="highlight"><pre>', '')
-        html_highlighted = html_highlighted.replace('</pre></div>', '')
+            # On Python 3, pygments.highlight() returns a bytes object, not a str.
+            if sys.version_info >= (3, 0):
+              html_highlighted = html_highlighted.decode('utf-8')
+
+            # Take off the header and footer, these must be
+            #   reapplied line-wise, within the page structure
+            html_highlighted = html_highlighted.replace('<div class="highlight"><pre>', '')
+            html_highlighted = html_highlighted.replace('</pre></div>', '')
 
         for (linenum, html_line) in enumerate(html_highlighted.split('\n'), start=1):
             print('''
@@ -274,9 +278,19 @@ if __name__ == '__main__':
         default=1000,
         type=int,
         help='Maximum number of the hottest remarks to appear on the index page')
+    parser.add_argument(
+        '--no-highlight',
+        action='store_true',
+        default=False,
+        help='Do not use a syntax highlighter when rendering the source code')
+    parser.add_argument(
+        '--demangler',
+        help='Set the demangler to be used (defaults to %s)' % optrecord.Remark.default_demangler)
     args = parser.parse_args()
 
     print_progress = not args.no_progress_indicator
+    if args.demangler:
+        optrecord.Remark.set_demangler(args.demangler)
 
     files = optrecord.find_opt_files(*args.yaml_dirs_or_files)
     if not files:

Modified: llvm/trunk/tools/opt-viewer/optrecord.py
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt-viewer/optrecord.py?rev=319324&r1=319323&r2=319324&view=diff
==============================================================================
--- llvm/trunk/tools/opt-viewer/optrecord.py (original)
+++ llvm/trunk/tools/opt-viewer/optrecord.py Wed Nov 29 09:07:41 2017
@@ -26,11 +26,6 @@ except:
 
 import optpmap
 
-
-p = subprocess.Popen(['c++filt', '-n'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
-p_lock = Lock()
-
-
 try:
     dict.iteritems
 except AttributeError:
@@ -47,13 +42,6 @@ else:
         return d.iteritems()
 
 
-def demangle(name):
-    with p_lock:
-        p.stdin.write((name + '\n').encode('utf-8'))
-        p.stdin.flush()
-        return p.stdout.readline().rstrip().decode('utf-8')
-
-
 def html_file_name(filename):
     return filename.replace('/', '_').replace('#', '_') + ".html"
 
@@ -66,6 +54,21 @@ class Remark(yaml.YAMLObject):
     # Work-around for http://pyyaml.org/ticket/154.
     yaml_loader = Loader
 
+    default_demangler = 'c++filt -n'
+    demangler_proc = None
+
+    @classmethod
+    def set_demangler(cls, demangler):
+        cls.demangler_proc = subprocess.Popen(demangler.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+        cls.demangler_lock = Lock()
+
+    @classmethod
+    def demangle(cls, name):
+        with cls.demangler_lock:
+            cls.demangler_proc.stdin.write((name + '\n').encode('utf-8'))
+            cls.demangler_proc.stdin.flush()
+            return cls.demangler_proc.stdout.readline().rstrip().decode('utf-8')
+
     # Intern all strings since we have lot of duplication across filenames,
     # remark text.
     #
@@ -133,7 +136,7 @@ class Remark(yaml.YAMLObject):
 
     @property
     def DemangledFunctionName(self):
-        return demangle(self.Function)
+        return self.demangle(self.Function)
 
     @property
     def Link(self):
@@ -149,7 +152,7 @@ class Remark(yaml.YAMLObject):
         (key, value) = list(mapping.items())[0]
 
         if key == 'Caller' or key == 'Callee':
-            value = cgi.escape(demangle(value))
+            value = cgi.escape(self.demangle(value))
 
         if dl and key != 'Caller':
             dl_dict = dict(list(dl))
@@ -259,6 +262,8 @@ def get_remarks(input_file):
 def gather_results(filenames, num_jobs, should_print_progress):
     if should_print_progress:
         print('Reading YAML files...')
+    if not Remark.demangler_proc:
+        Remark.set_demangler(Remark.default_demangler)
     remarks = optpmap.pmap(
         get_remarks, filenames, num_jobs, should_print_progress)
     max_hotness = max(entry[0] for entry in remarks)




More information about the llvm-commits mailing list