diff options
author | Adam Nemet <anemet@apple.com> | 2017-11-29 17:07:41 +0000 |
---|---|---|
committer | Adam Nemet <anemet@apple.com> | 2017-11-29 17:07:41 +0000 |
commit | 95e0c5fc6cebc2ced6eaac6dddd7858dc053cf4e (patch) | |
tree | f0db50aa4c55e4ddd03b9b0499ec93bfb3aaaa80 | |
parent | 5360f9404e5bc4b0a55cf1ca7c3449bb64034ff5 (diff) | |
download | bcm5719-llvm-95e0c5fc6cebc2ced6eaac6dddd7858dc053cf4e.tar.gz bcm5719-llvm-95e0c5fc6cebc2ced6eaac6dddd7858dc053cf4e.zip |
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
llvm-svn: 319324
-rw-r--r-- | llvm/cmake/config-ix.cmake | 31 | ||||
-rw-r--r-- | llvm/test/lit.cfg.py | 5 | ||||
-rw-r--r-- | llvm/test/lit.site.cfg.py.in | 1 | ||||
-rw-r--r-- | llvm/test/tools/opt-viewer/Inputs/basic/or.c | 21 | ||||
-rw-r--r-- | llvm/test/tools/opt-viewer/Inputs/basic/or.h | 16 | ||||
-rw-r--r-- | llvm/test/tools/opt-viewer/Inputs/basic/or.yaml | 227 | ||||
-rw-r--r-- | llvm/test/tools/opt-viewer/Outputs/basic/basic_or.c.html | 257 | ||||
-rw-r--r-- | llvm/test/tools/opt-viewer/Outputs/basic/basic_or.h.html | 214 | ||||
-rw-r--r-- | llvm/test/tools/opt-viewer/Outputs/basic/index.html | 151 | ||||
-rw-r--r-- | llvm/test/tools/opt-viewer/Outputs/basic/style.css | 208 | ||||
-rw-r--r-- | llvm/test/tools/opt-viewer/basic.test | 9 | ||||
-rw-r--r-- | llvm/test/tools/opt-viewer/lit.local.cfg | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp | 1 | ||||
-rwxr-xr-x | llvm/tools/opt-viewer/opt-viewer.py | 34 | ||||
-rw-r--r-- | llvm/tools/opt-viewer/optrecord.py | 33 |
15 files changed, 1186 insertions, 24 deletions
diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake index 23494fb96c6..caa538082fc 100644 --- a/llvm/cmake/config-ix.cmake +++ b/llvm/cmake/config-ix.cmake @@ -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() diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py index e956bb74f5a..06a23536a8c 100644 --- a/llvm/test/lit.cfg.py +++ b/llvm/test/lit.cfg.py @@ -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') diff --git a/llvm/test/lit.site.cfg.py.in b/llvm/test/lit.site.cfg.py.in index dff46dcff32..117af7336d0 100644 --- a/llvm/test/lit.site.cfg.py.in +++ b/llvm/test/lit.site.cfg.py.in @@ -43,6 +43,7 @@ config.link_llvm_dylib = @LLVM_LINK_LLVM_DYLIB@ 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. diff --git a/llvm/test/tools/opt-viewer/Inputs/basic/or.c b/llvm/test/tools/opt-viewer/Inputs/basic/or.c new file mode 100644 index 00000000000..6b1c4744cda --- /dev/null +++ b/llvm/test/tools/opt-viewer/Inputs/basic/or.c @@ -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(); +} diff --git a/llvm/test/tools/opt-viewer/Inputs/basic/or.h b/llvm/test/tools/opt-viewer/Inputs/basic/or.h new file mode 100644 index 00000000000..a1c47edb3d1 --- /dev/null +++ b/llvm/test/tools/opt-viewer/Inputs/basic/or.h @@ -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(); +} diff --git a/llvm/test/tools/opt-viewer/Inputs/basic/or.yaml b/llvm/test/tools/opt-viewer/Inputs/basic/or.yaml new file mode 100644 index 00000000000..11c5528b43f --- /dev/null +++ b/llvm/test/tools/opt-viewer/Inputs/basic/or.yaml @@ -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: ')' +... diff --git a/llvm/test/tools/opt-viewer/Outputs/basic/basic_or.c.html b/llvm/test/tools/opt-viewer/Outputs/basic/basic_or.c.html new file mode 100644 index 00000000000..a97b12855bc --- /dev/null +++ b/llvm/test/tools/opt-viewer/Outputs/basic/basic_or.c.html @@ -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> diff --git a/llvm/test/tools/opt-viewer/Outputs/basic/basic_or.h.html b/llvm/test/tools/opt-viewer/Outputs/basic/basic_or.h.html new file mode 100644 index 00000000000..171bb835563 --- /dev/null +++ b/llvm/test/tools/opt-viewer/Outputs/basic/basic_or.h.html @@ -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> diff --git a/llvm/test/tools/opt-viewer/Outputs/basic/index.html b/llvm/test/tools/opt-viewer/Outputs/basic/index.html new file mode 100644 index 00000000000..9fe9a4a7adf --- /dev/null +++ b/llvm/test/tools/opt-viewer/Outputs/basic/index.html @@ -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> diff --git a/llvm/test/tools/opt-viewer/Outputs/basic/style.css b/llvm/test/tools/opt-viewer/Outputs/basic/style.css new file mode 100644 index 00000000000..0d3347c1578 --- /dev/null +++ b/llvm/test/tools/opt-viewer/Outputs/basic/style.css @@ -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 */ diff --git a/llvm/test/tools/opt-viewer/basic.test b/llvm/test/tools/opt-viewer/basic.test new file mode 100644 index 00000000000..f0e8fa3ad1b --- /dev/null +++ b/llvm/test/tools/opt-viewer/basic.test @@ -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 diff --git a/llvm/test/tools/opt-viewer/lit.local.cfg b/llvm/test/tools/opt-viewer/lit.local.cfg new file mode 100644 index 00000000000..84dda078f97 --- /dev/null +++ b/llvm/test/tools/opt-viewer/lit.local.cfg @@ -0,0 +1,2 @@ +if 'have_opt_viewer_modules' not in config.available_features: + config.unsupported = True diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp index 13024fbeaea..9c6a1612fa0 100644 --- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp +++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp @@ -75,6 +75,7 @@ static void demangle(llvm::raw_ostream &OS, const std::string &Mangled) { } OS << (Undecorated ? Undecorated : Mangled) << '\n'; + OS.flush(); free(Undecorated); } diff --git a/llvm/tools/opt-viewer/opt-viewer.py b/llvm/tools/opt-viewer/opt-viewer.py index 7253d7c13ee..3000fb12f0b 100755 --- a/llvm/tools/opt-viewer/opt-viewer.py +++ b/llvm/tools/opt-viewer/opt-viewer.py @@ -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') + # 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>', '') + # 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: diff --git a/llvm/tools/opt-viewer/optrecord.py b/llvm/tools/opt-viewer/optrecord.py index e68bcb870c6..ce665299e17 100644 --- a/llvm/tools/opt-viewer/optrecord.py +++ b/llvm/tools/opt-viewer/optrecord.py @@ -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) |