mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[llvm-opt-report] Distinguish inlined contexts when optimizations differ
How code is optimized sometimes, perhaps often, depends on the context into which it was inlined. This change allows llvm-opt-report to track the differences between the optimizations performed, or not, in different contexts, and when these differ, display those differences. For example, this code: $ cat /tmp/q.cpp void bar(); void foo(int n) { for (int i = 0; i < n; ++i) bar(); } void quack() { foo(4); } void quack2() { foo(4); } will now produce this report: < /home/hfinkel/src/llvm/test/tools/llvm-opt-report/Inputs/q.cpp 2 | void bar(); 3 | void foo(int n) { [[ > foo(int): 4 | for (int i = 0; i < n; ++i) > quack(), quack2(): 4 U4 | for (int i = 0; i < n; ++i) ]] 5 | bar(); 6 | } 7 | 8 | void quack() { 9 I | foo(4); 10 | } 11 | 12 | void quack2() { 13 I | foo(4); 14 | } 15 | Note that the tool has demangled the function names, and grouped the reports associated with line 4. This shows that the loop on line 4 was unrolled by a factor of 4 when inlined into the functions quack() and quack2(), but not in the function foo(int) itself. llvm-svn: 283402
This commit is contained in:
parent
77c7c501d3
commit
989b264cc2
14
test/tools/llvm-opt-report/Inputs/q.c
Normal file
14
test/tools/llvm-opt-report/Inputs/q.c
Normal file
@ -0,0 +1,14 @@
|
||||
void bar();
|
||||
void foo(int n) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
bar();
|
||||
}
|
||||
|
||||
void quack() {
|
||||
foo(4);
|
||||
}
|
||||
|
||||
void quack2() {
|
||||
foo(4);
|
||||
}
|
||||
|
14
test/tools/llvm-opt-report/Inputs/q.cpp
Normal file
14
test/tools/llvm-opt-report/Inputs/q.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
void bar();
|
||||
void foo(int n) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
bar();
|
||||
}
|
||||
|
||||
void quack() {
|
||||
foo(4);
|
||||
}
|
||||
|
||||
void quack2() {
|
||||
foo(4);
|
||||
}
|
||||
|
98
test/tools/llvm-opt-report/Inputs/q.yaml
Normal file
98
test/tools/llvm-opt-report/Inputs/q.yaml
Normal file
@ -0,0 +1,98 @@
|
||||
--- !Missed
|
||||
Pass: inline
|
||||
Name: NoDefinition
|
||||
DebugLoc: { File: Inputs/q.c, Line: 4, Column: 5 }
|
||||
Function: foo
|
||||
Args:
|
||||
- Callee: bar
|
||||
- String: ' will not be inlined into '
|
||||
- Caller: foo
|
||||
- String: ' because its definition is unavailable'
|
||||
...
|
||||
--- !Analysis
|
||||
Pass: inline
|
||||
Name: CanBeInlined
|
||||
DebugLoc: { File: Inputs/q.c, Line: 8, Column: 3 }
|
||||
Function: quack
|
||||
Args:
|
||||
- Callee: foo
|
||||
- String: ' can be inlined into '
|
||||
- Caller: quack
|
||||
- String: ' with cost='
|
||||
- Cost: '40'
|
||||
- String: ' (threshold='
|
||||
- Threshold: '275'
|
||||
- String: ')'
|
||||
...
|
||||
--- !Passed
|
||||
Pass: inline
|
||||
Name: Inlined
|
||||
DebugLoc: { File: Inputs/q.c, Line: 8, Column: 3 }
|
||||
Function: quack
|
||||
Args:
|
||||
- Callee: foo
|
||||
- String: ' inlined into '
|
||||
- Caller: quack
|
||||
...
|
||||
--- !Passed
|
||||
Pass: loop-unroll
|
||||
Name: FullyUnrolled
|
||||
DebugLoc: { File: Inputs/q.c, Line: 3, Column: 3 }
|
||||
Function: quack
|
||||
Args:
|
||||
- String: 'completely unrolled loop with '
|
||||
- UnrollCount: '4'
|
||||
- String: ' iterations'
|
||||
...
|
||||
--- !Analysis
|
||||
Pass: inline
|
||||
Name: CanBeInlined
|
||||
DebugLoc: { File: Inputs/q.c, Line: 12, Column: 3 }
|
||||
Function: quack2
|
||||
Args:
|
||||
- Callee: foo
|
||||
- String: ' can be inlined into '
|
||||
- Caller: quack2
|
||||
- String: ' with cost='
|
||||
- Cost: '40'
|
||||
- String: ' (threshold='
|
||||
- Threshold: '275'
|
||||
- String: ')'
|
||||
...
|
||||
--- !Passed
|
||||
Pass: inline
|
||||
Name: Inlined
|
||||
DebugLoc: { File: Inputs/q.c, Line: 12, Column: 3 }
|
||||
Function: quack2
|
||||
Args:
|
||||
- Callee: foo
|
||||
- String: ' inlined into '
|
||||
- Caller: quack2
|
||||
...
|
||||
--- !Passed
|
||||
Pass: loop-unroll
|
||||
Name: FullyUnrolled
|
||||
DebugLoc: { File: Inputs/q.c, Line: 3, Column: 3 }
|
||||
Function: quack2
|
||||
Args:
|
||||
- String: 'completely unrolled loop with '
|
||||
- UnrollCount: '4'
|
||||
- String: ' iterations'
|
||||
...
|
||||
--- !Analysis
|
||||
Pass: loop-vectorize
|
||||
Name: CantVectorizeCall
|
||||
DebugLoc: { File: Inputs/q.c, Line: 4, Column: 5 }
|
||||
Function: foo
|
||||
Args:
|
||||
- String: 'loop not vectorized: '
|
||||
- String: call instruction cannot be vectorized
|
||||
...
|
||||
--- !Missed
|
||||
Pass: loop-vectorize
|
||||
Name: MissedDetails
|
||||
DebugLoc: { File: Inputs/q.c, Line: 3, Column: 3 }
|
||||
Function: foo
|
||||
Args:
|
||||
- String: 'loop not vectorized: use -Rpass-analysis=loop-vectorize for more info'
|
||||
...
|
14
test/tools/llvm-opt-report/Inputs/q2.c
Normal file
14
test/tools/llvm-opt-report/Inputs/q2.c
Normal file
@ -0,0 +1,14 @@
|
||||
void bar();
|
||||
void foo(int n) {
|
||||
for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)
|
||||
bar();
|
||||
}
|
||||
|
||||
void quack() {
|
||||
foo(4);
|
||||
}
|
||||
|
||||
void quack2() {
|
||||
foo(4);
|
||||
}
|
||||
|
118
test/tools/llvm-opt-report/Inputs/q2.yaml
Normal file
118
test/tools/llvm-opt-report/Inputs/q2.yaml
Normal file
@ -0,0 +1,118 @@
|
||||
--- !Missed
|
||||
Pass: inline
|
||||
Name: NoDefinition
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 4, Column: 5 }
|
||||
Function: foo
|
||||
Args:
|
||||
- Callee: bar
|
||||
- String: ' will not be inlined into '
|
||||
- Caller: foo
|
||||
- String: ' because its definition is unavailable'
|
||||
...
|
||||
--- !Analysis
|
||||
Pass: inline
|
||||
Name: CanBeInlined
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 8, Column: 3 }
|
||||
Function: quack
|
||||
Args:
|
||||
- Callee: foo
|
||||
- String: ' can be inlined into '
|
||||
- Caller: quack
|
||||
- String: ' with cost='
|
||||
- Cost: '55'
|
||||
- String: ' (threshold='
|
||||
- Threshold: '275'
|
||||
- String: ')'
|
||||
...
|
||||
--- !Passed
|
||||
Pass: inline
|
||||
Name: Inlined
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 8, Column: 3 }
|
||||
Function: quack
|
||||
Args:
|
||||
- Callee: foo
|
||||
- String: ' inlined into '
|
||||
- Caller: quack
|
||||
...
|
||||
--- !Passed
|
||||
Pass: loop-unroll
|
||||
Name: FullyUnrolled
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 3, Column: 31 }
|
||||
Function: quack
|
||||
Args:
|
||||
- String: 'completely unrolled loop with '
|
||||
- UnrollCount: '4'
|
||||
- String: ' iterations'
|
||||
...
|
||||
--- !Passed
|
||||
Pass: loop-unroll
|
||||
Name: FullyUnrolled
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 3, Column: 3 }
|
||||
Function: quack
|
||||
Args:
|
||||
- String: 'completely unrolled loop with '
|
||||
- UnrollCount: '4'
|
||||
- String: ' iterations'
|
||||
...
|
||||
--- !Analysis
|
||||
Pass: inline
|
||||
Name: CanBeInlined
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 12, Column: 3 }
|
||||
Function: quack2
|
||||
Args:
|
||||
- Callee: foo
|
||||
- String: ' can be inlined into '
|
||||
- Caller: quack2
|
||||
- String: ' with cost='
|
||||
- Cost: '55'
|
||||
- String: ' (threshold='
|
||||
- Threshold: '275'
|
||||
- String: ')'
|
||||
...
|
||||
--- !Passed
|
||||
Pass: inline
|
||||
Name: Inlined
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 12, Column: 3 }
|
||||
Function: quack2
|
||||
Args:
|
||||
- Callee: foo
|
||||
- String: ' inlined into '
|
||||
- Caller: quack2
|
||||
...
|
||||
--- !Passed
|
||||
Pass: loop-unroll
|
||||
Name: FullyUnrolled
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 3, Column: 31 }
|
||||
Function: quack2
|
||||
Args:
|
||||
- String: 'completely unrolled loop with '
|
||||
- UnrollCount: '4'
|
||||
- String: ' iterations'
|
||||
...
|
||||
--- !Passed
|
||||
Pass: loop-unroll
|
||||
Name: FullyUnrolled
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 3, Column: 3 }
|
||||
Function: quack2
|
||||
Args:
|
||||
- String: 'completely unrolled loop with '
|
||||
- UnrollCount: '4'
|
||||
- String: ' iterations'
|
||||
...
|
||||
--- !Analysis
|
||||
Pass: loop-vectorize
|
||||
Name: CantVectorizeCall
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 4, Column: 5 }
|
||||
Function: foo
|
||||
Args:
|
||||
- String: 'loop not vectorized: '
|
||||
- String: call instruction cannot be vectorized
|
||||
...
|
||||
--- !Missed
|
||||
Pass: loop-vectorize
|
||||
Name: MissedDetails
|
||||
DebugLoc: { File: Inputs/q2.c, Line: 3, Column: 31 }
|
||||
Function: foo
|
||||
Args:
|
||||
- String: 'loop not vectorized: use -Rpass-analysis=loop-vectorize for more info'
|
||||
...
|
98
test/tools/llvm-opt-report/Inputs/qx.yaml
Normal file
98
test/tools/llvm-opt-report/Inputs/qx.yaml
Normal file
@ -0,0 +1,98 @@
|
||||
--- !Missed
|
||||
Pass: inline
|
||||
Name: NoDefinition
|
||||
DebugLoc: { File: Inputs/q.cpp, Line: 4, Column: 5 }
|
||||
Function: _Z3fooi
|
||||
Args:
|
||||
- Callee: _Z3barv
|
||||
- String: ' will not be inlined into '
|
||||
- Caller: _Z3fooi
|
||||
- String: ' because its definition is unavailable'
|
||||
...
|
||||
--- !Analysis
|
||||
Pass: inline
|
||||
Name: CanBeInlined
|
||||
DebugLoc: { File: Inputs/q.cpp, Line: 8, Column: 3 }
|
||||
Function: _Z5quackv
|
||||
Args:
|
||||
- Callee: _Z3fooi
|
||||
- String: ' can be inlined into '
|
||||
- Caller: _Z5quackv
|
||||
- String: ' with cost='
|
||||
- Cost: '40'
|
||||
- String: ' (threshold='
|
||||
- Threshold: '275'
|
||||
- String: ')'
|
||||
...
|
||||
--- !Passed
|
||||
Pass: inline
|
||||
Name: Inlined
|
||||
DebugLoc: { File: Inputs/q.cpp, Line: 8, Column: 3 }
|
||||
Function: _Z5quackv
|
||||
Args:
|
||||
- Callee: _Z3fooi
|
||||
- String: ' inlined into '
|
||||
- Caller: _Z5quackv
|
||||
...
|
||||
--- !Passed
|
||||
Pass: loop-unroll
|
||||
Name: FullyUnrolled
|
||||
DebugLoc: { File: Inputs/q.cpp, Line: 3, Column: 3 }
|
||||
Function: _Z5quackv
|
||||
Args:
|
||||
- String: 'completely unrolled loop with '
|
||||
- UnrollCount: '4'
|
||||
- String: ' iterations'
|
||||
...
|
||||
--- !Analysis
|
||||
Pass: inline
|
||||
Name: CanBeInlined
|
||||
DebugLoc: { File: Inputs/q.cpp, Line: 12, Column: 3 }
|
||||
Function: _Z6quack2v
|
||||
Args:
|
||||
- Callee: _Z3fooi
|
||||
- String: ' can be inlined into '
|
||||
- Caller: _Z6quack2v
|
||||
- String: ' with cost='
|
||||
- Cost: '40'
|
||||
- String: ' (threshold='
|
||||
- Threshold: '275'
|
||||
- String: ')'
|
||||
...
|
||||
--- !Passed
|
||||
Pass: inline
|
||||
Name: Inlined
|
||||
DebugLoc: { File: Inputs/q.cpp, Line: 12, Column: 3 }
|
||||
Function: _Z6quack2v
|
||||
Args:
|
||||
- Callee: _Z3fooi
|
||||
- String: ' inlined into '
|
||||
- Caller: _Z6quack2v
|
||||
...
|
||||
--- !Passed
|
||||
Pass: loop-unroll
|
||||
Name: FullyUnrolled
|
||||
DebugLoc: { File: Inputs/q.cpp, Line: 3, Column: 3 }
|
||||
Function: _Z6quack2v
|
||||
Args:
|
||||
- String: 'completely unrolled loop with '
|
||||
- UnrollCount: '4'
|
||||
- String: ' iterations'
|
||||
...
|
||||
--- !Analysis
|
||||
Pass: loop-vectorize
|
||||
Name: CantVectorizeCall
|
||||
DebugLoc: { File: Inputs/q.cpp, Line: 4, Column: 5 }
|
||||
Function: _Z3fooi
|
||||
Args:
|
||||
- String: 'loop not vectorized: '
|
||||
- String: call instruction cannot be vectorized
|
||||
...
|
||||
--- !Missed
|
||||
Pass: loop-vectorize
|
||||
Name: MissedDetails
|
||||
DebugLoc: { File: Inputs/q.cpp, Line: 3, Column: 3 }
|
||||
Function: _Z3fooi
|
||||
Args:
|
||||
- String: 'loop not vectorized: use -Rpass-analysis=loop-vectorize for more info'
|
||||
...
|
49
test/tools/llvm-opt-report/func-2.test
Normal file
49
test/tools/llvm-opt-report/func-2.test
Normal file
@ -0,0 +1,49 @@
|
||||
RUN: llvm-opt-report -r %p %p/Inputs/q2.yaml | FileCheck -strict-whitespace %s
|
||||
RUN: llvm-opt-report -s -r %p %p/Inputs/q2.yaml | FileCheck -strict-whitespace -check-prefix=CHECK-SUCCINCT %s
|
||||
|
||||
; CHECK: < {{.*}}/Inputs/q2.c
|
||||
; CHECK-NEXT: 2 | void bar();
|
||||
; CHECK-NEXT: 3 | void foo(int n) {
|
||||
; CHECK-NEXT: {{\[\[}}
|
||||
; CHECK-NEXT: > quack, quack2:
|
||||
; CHECK-NEXT: 4 | for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)
|
||||
; CHECK-NEXT: U4 | ^
|
||||
; CHECK-NEXT: U4 | ^
|
||||
; CHECK-NEXT: > foo:
|
||||
; CHECK-NEXT: 4 | for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)
|
||||
; CHECK-NEXT: {{\]\]}}
|
||||
; CHECK-NEXT: 5 | bar();
|
||||
; CHECK-NEXT: 6 | }
|
||||
; CHECK-NEXT: 7 |
|
||||
; CHECK-NEXT: 8 | void quack() {
|
||||
; CHECK-NEXT: 9 I | foo(4);
|
||||
; CHECK-NEXT: 10 | }
|
||||
; CHECK-NEXT: 11 |
|
||||
; CHECK-NEXT: 12 | void quack2() {
|
||||
; CHECK-NEXT: 13 I | foo(4);
|
||||
; CHECK-NEXT: 14 | }
|
||||
; CHECK-NEXT: 15 |
|
||||
|
||||
; CHECK-SUCCINCT: < {{.*}}/Inputs/q2.c
|
||||
; CHECK-SUCCINCT-NEXT: 2 | void bar();
|
||||
; CHECK-SUCCINCT-NEXT: 3 | void foo(int n) {
|
||||
; CHECK-SUCCINCT-NEXT: {{\[\[}}
|
||||
; CHECK-SUCCINCT-NEXT: > quack, quack2:
|
||||
; CHECK-SUCCINCT-NEXT: 4 | for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)
|
||||
; CHECK-SUCCINCT-NEXT: U | ^
|
||||
; CHECK-SUCCINCT-NEXT: U | ^
|
||||
; CHECK-SUCCINCT-NEXT: > foo:
|
||||
; CHECK-SUCCINCT-NEXT: 4 | for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)
|
||||
; CHECK-SUCCINCT-NEXT: {{\]\]}}
|
||||
; CHECK-SUCCINCT-NEXT: 5 | bar();
|
||||
; CHECK-SUCCINCT-NEXT: 6 | }
|
||||
; CHECK-SUCCINCT-NEXT: 7 |
|
||||
; CHECK-SUCCINCT-NEXT: 8 | void quack() {
|
||||
; CHECK-SUCCINCT-NEXT: 9 I | foo(4);
|
||||
; CHECK-SUCCINCT-NEXT: 10 | }
|
||||
; CHECK-SUCCINCT-NEXT: 11 |
|
||||
; CHECK-SUCCINCT-NEXT: 12 | void quack2() {
|
||||
; CHECK-SUCCINCT-NEXT: 13 I | foo(4);
|
||||
; CHECK-SUCCINCT-NEXT: 14 | }
|
||||
; CHECK-SUCCINCT-NEXT: 15 |
|
||||
|
45
test/tools/llvm-opt-report/func-x.test
Normal file
45
test/tools/llvm-opt-report/func-x.test
Normal file
@ -0,0 +1,45 @@
|
||||
RUN: llvm-opt-report -r %p %p/Inputs/qx.yaml | FileCheck -strict-whitespace %s
|
||||
RUN: llvm-opt-report -s -r %p %p/Inputs/qx.yaml | FileCheck -strict-whitespace -check-prefix=CHECK-SUCCINCT %s
|
||||
|
||||
; CHECK: < {{.*}}/Inputs/q.cpp
|
||||
; CHECK-NEXT: 2 | void bar();
|
||||
; CHECK-NEXT: 3 | void foo(int n) {
|
||||
; CHECK-NEXT: {{\[\[}}
|
||||
; CHECK-NEXT: > foo(int):
|
||||
; CHECK-NEXT: 4 | for (int i = 0; i < n; ++i)
|
||||
; CHECK-NEXT: > quack(), quack2():
|
||||
; CHECK-NEXT: 4 U4 | for (int i = 0; i < n; ++i)
|
||||
; CHECK-NEXT: {{\]\]}}
|
||||
; CHECK-NEXT: 5 | bar();
|
||||
; CHECK-NEXT: 6 | }
|
||||
; CHECK-NEXT: 7 |
|
||||
; CHECK-NEXT: 8 | void quack() {
|
||||
; CHECK-NEXT: 9 I | foo(4);
|
||||
; CHECK-NEXT: 10 | }
|
||||
; CHECK-NEXT: 11 |
|
||||
; CHECK-NEXT: 12 | void quack2() {
|
||||
; CHECK-NEXT: 13 I | foo(4);
|
||||
; CHECK-NEXT: 14 | }
|
||||
; CHECK-NEXT: 15 |
|
||||
|
||||
; CHECK-SUCCINCT: < {{.*}}/Inputs/q.cpp
|
||||
; CHECK-SUCCINCT-NEXT: 2 | void bar();
|
||||
; CHECK-SUCCINCT-NEXT: 3 | void foo(int n) {
|
||||
; CHECK-SUCCINCT-NEXT: {{\[\[}}
|
||||
; CHECK-SUCCINCT-NEXT: > foo(int):
|
||||
; CHECK-SUCCINCT-NEXT: 4 | for (int i = 0; i < n; ++i)
|
||||
; CHECK-SUCCINCT-NEXT: > quack(), quack2():
|
||||
; CHECK-SUCCINCT-NEXT: 4 U | for (int i = 0; i < n; ++i)
|
||||
; CHECK-SUCCINCT-NEXT: {{\]\]}}
|
||||
; CHECK-SUCCINCT-NEXT: 5 | bar();
|
||||
; CHECK-SUCCINCT-NEXT: 6 | }
|
||||
; CHECK-SUCCINCT-NEXT: 7 |
|
||||
; CHECK-SUCCINCT-NEXT: 8 | void quack() {
|
||||
; CHECK-SUCCINCT-NEXT: 9 I | foo(4);
|
||||
; CHECK-SUCCINCT-NEXT: 10 | }
|
||||
; CHECK-SUCCINCT-NEXT: 11 |
|
||||
; CHECK-SUCCINCT-NEXT: 12 | void quack2() {
|
||||
; CHECK-SUCCINCT-NEXT: 13 I | foo(4);
|
||||
; CHECK-SUCCINCT-NEXT: 14 | }
|
||||
; CHECK-SUCCINCT-NEXT: 15 |
|
||||
|
45
test/tools/llvm-opt-report/func.test
Normal file
45
test/tools/llvm-opt-report/func.test
Normal file
@ -0,0 +1,45 @@
|
||||
RUN: llvm-opt-report -r %p %p/Inputs/q.yaml | FileCheck -strict-whitespace %s
|
||||
RUN: llvm-opt-report -s -r %p %p/Inputs/q.yaml | FileCheck -strict-whitespace -check-prefix=CHECK-SUCCINCT %s
|
||||
|
||||
; CHECK: < {{.*}}/Inputs/q.c
|
||||
; CHECK-NEXT: 2 | void bar();
|
||||
; CHECK-NEXT: 3 | void foo(int n) {
|
||||
; CHECK-NEXT: {{\[\[}}
|
||||
; CHECK-NEXT: > foo:
|
||||
; CHECK-NEXT: 4 | for (int i = 0; i < n; ++i)
|
||||
; CHECK-NEXT: > quack, quack2:
|
||||
; CHECK-NEXT: 4 U4 | for (int i = 0; i < n; ++i)
|
||||
; CHECK-NEXT: {{\]\]}}
|
||||
; CHECK-NEXT: 5 | bar();
|
||||
; CHECK-NEXT: 6 | }
|
||||
; CHECK-NEXT: 7 |
|
||||
; CHECK-NEXT: 8 | void quack() {
|
||||
; CHECK-NEXT: 9 I | foo(4);
|
||||
; CHECK-NEXT: 10 | }
|
||||
; CHECK-NEXT: 11 |
|
||||
; CHECK-NEXT: 12 | void quack2() {
|
||||
; CHECK-NEXT: 13 I | foo(4);
|
||||
; CHECK-NEXT: 14 | }
|
||||
; CHECK-NEXT: 15 |
|
||||
|
||||
; CHECK-SUCCINCT: < {{.*}}/Inputs/q.c
|
||||
; CHECK-SUCCINCT-NEXT: 2 | void bar();
|
||||
; CHECK-SUCCINCT-NEXT: 3 | void foo(int n) {
|
||||
; CHECK-SUCCINCT-NEXT: {{\[\[}}
|
||||
; CHECK-SUCCINCT-NEXT: > foo:
|
||||
; CHECK-SUCCINCT-NEXT: 4 | for (int i = 0; i < n; ++i)
|
||||
; CHECK-SUCCINCT-NEXT: > quack, quack2:
|
||||
; CHECK-SUCCINCT-NEXT: 4 U | for (int i = 0; i < n; ++i)
|
||||
; CHECK-SUCCINCT-NEXT: {{\]\]}}
|
||||
; CHECK-SUCCINCT-NEXT: 5 | bar();
|
||||
; CHECK-SUCCINCT-NEXT: 6 | }
|
||||
; CHECK-SUCCINCT-NEXT: 7 |
|
||||
; CHECK-SUCCINCT-NEXT: 8 | void quack() {
|
||||
; CHECK-SUCCINCT-NEXT: 9 I | foo(4);
|
||||
; CHECK-SUCCINCT-NEXT: 10 | }
|
||||
; CHECK-SUCCINCT-NEXT: 11 |
|
||||
; CHECK-SUCCINCT-NEXT: 12 | void quack2() {
|
||||
; CHECK-SUCCINCT-NEXT: 13 I | foo(4);
|
||||
; CHECK-SUCCINCT-NEXT: 14 | }
|
||||
; CHECK-SUCCINCT-NEXT: 15 |
|
||||
|
@ -1,4 +1,4 @@
|
||||
set(LLVM_LINK_COMPONENTS Core Object Support)
|
||||
set(LLVM_LINK_COMPONENTS Core Demangle Object Support)
|
||||
|
||||
add_llvm_tool(llvm-opt-report
|
||||
OptReport.cpp
|
||||
|
@ -15,6 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Demangle/Demangle.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
@ -27,6 +28,9 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::yaml;
|
||||
@ -54,6 +58,10 @@ static cl::opt<bool>
|
||||
Succinct("s", cl::desc("Don't include vectorization factors, etc."),
|
||||
cl::init(false), cl::cat(OptReportCategory));
|
||||
|
||||
static cl::opt<bool>
|
||||
Demangle("demangle", cl::desc("Demangle function names"), cl::init(true),
|
||||
cl::cat(OptReportCategory));
|
||||
|
||||
namespace {
|
||||
// For each location in the source file, the common per-transformation state
|
||||
// collected.
|
||||
@ -68,6 +76,16 @@ struct OptReportLocationItemInfo {
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator < (const OptReportLocationItemInfo &RHS) const {
|
||||
if (Analyzed < RHS.Analyzed)
|
||||
return true;
|
||||
else if (Analyzed > RHS.Analyzed)
|
||||
return false;
|
||||
else if (Transformed < RHS.Transformed)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// The per-location information collected for producing an optimization report.
|
||||
@ -92,10 +110,36 @@ struct OptReportLocationInfo {
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator < (const OptReportLocationInfo &RHS) const {
|
||||
if (Inlined < RHS.Inlined)
|
||||
return true;
|
||||
else if (RHS.Inlined < Inlined)
|
||||
return false;
|
||||
else if (Unrolled < RHS.Unrolled)
|
||||
return true;
|
||||
else if (RHS.Unrolled < Unrolled)
|
||||
return false;
|
||||
else if (Vectorized < RHS.Vectorized)
|
||||
return true;
|
||||
else if (RHS.Vectorized < Vectorized || Succinct)
|
||||
return false;
|
||||
else if (VectorizationFactor < RHS.VectorizationFactor)
|
||||
return true;
|
||||
else if (VectorizationFactor > RHS.VectorizationFactor)
|
||||
return false;
|
||||
else if (InterleaveCount < RHS.InterleaveCount)
|
||||
return true;
|
||||
else if (InterleaveCount > RHS.InterleaveCount)
|
||||
return false;
|
||||
else if (InterleaveCount < RHS.InterleaveCount)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<std::string, std::map<int, std::map<int,
|
||||
OptReportLocationInfo>>> LocationInfoTy;
|
||||
typedef std::map<std::string, std::map<int, std::map<std::string, std::map<int,
|
||||
OptReportLocationInfo>>>> LocationInfoTy;
|
||||
} // anonymous namespace
|
||||
|
||||
static void collectLocationInfo(yaml::Stream &Stream,
|
||||
@ -115,7 +159,7 @@ static void collectLocationInfo(yaml::Stream &Stream,
|
||||
continue;
|
||||
|
||||
bool Transformed = Root->getRawTag() == "!Passed";
|
||||
std::string Pass, File;
|
||||
std::string Pass, File, Function;
|
||||
int Line = 0, Column = 1;
|
||||
|
||||
int VectorizationFactor = 1;
|
||||
@ -132,6 +176,11 @@ static void collectLocationInfo(yaml::Stream &Stream,
|
||||
if (!Value)
|
||||
continue;
|
||||
Pass = Value->getValue(Tmp);
|
||||
} else if (KeyName == "Function") {
|
||||
auto *Value = dyn_cast<yaml::ScalarNode>(RootChild.getValue());
|
||||
if (!Value)
|
||||
continue;
|
||||
Function = Value->getValue(Tmp);
|
||||
} else if (KeyName == "DebugLoc") {
|
||||
auto *DebugLoc = dyn_cast<yaml::MappingNode>(RootChild.getValue());
|
||||
if (!DebugLoc)
|
||||
@ -214,13 +263,13 @@ static void collectLocationInfo(yaml::Stream &Stream,
|
||||
};
|
||||
|
||||
if (Pass == "inline") {
|
||||
auto &LI = LocationInfo[File][Line][Column];
|
||||
auto &LI = LocationInfo[File][Line][Function][Column];
|
||||
UpdateLLII(LI, LI.Inlined);
|
||||
} else if (Pass == "loop-unroll") {
|
||||
auto &LI = LocationInfo[File][Line][Column];
|
||||
auto &LI = LocationInfo[File][Line][Function][Column];
|
||||
UpdateLLII(LI, LI.Unrolled);
|
||||
} else if (Pass == "loop-vectorize") {
|
||||
auto &LI = LocationInfo[File][Line][Column];
|
||||
auto &LI = LocationInfo[File][Line][Function][Column];
|
||||
UpdateLLII(LI, LI.Vectorized);
|
||||
}
|
||||
}
|
||||
@ -283,7 +332,8 @@ static bool writeReport(LocationInfoTy &LocationInfo) {
|
||||
// Figure out how many characters we need for the vectorization factors
|
||||
// and similar.
|
||||
OptReportLocationInfo MaxLI;
|
||||
for (auto &FI : FileInfo)
|
||||
for (auto &FLI : FileInfo)
|
||||
for (auto &FI : FLI.second)
|
||||
for (auto &LI : FI.second)
|
||||
MaxLI |= LI.second;
|
||||
|
||||
@ -300,16 +350,19 @@ static bool writeReport(LocationInfoTy &LocationInfo) {
|
||||
|
||||
for (line_iterator LI(*Buf.get(), false); LI != line_iterator(); ++LI) {
|
||||
int64_t L = LI.line_number();
|
||||
auto LII = FileInfo.find(L);
|
||||
|
||||
auto PrintLine = [&](bool PrintFuncName,
|
||||
const std::set<std::string> &FuncNameSet) {
|
||||
OptReportLocationInfo LLI;
|
||||
|
||||
std::map<int, OptReportLocationInfo> ColsInfo;
|
||||
unsigned InlinedCols = 0, UnrolledCols = 0, VectorizedCols = 0;
|
||||
|
||||
auto LII = FileInfo.find(L);
|
||||
if (LII != FileInfo.end()) {
|
||||
const auto &LineInfo = LII->second;
|
||||
|
||||
for (auto &CI : LineInfo) {
|
||||
for (auto &CI : LineInfo.find(*FuncNameSet.begin())->second) {
|
||||
int Col = CI.first;
|
||||
ColsInfo[Col] = CI.second;
|
||||
InlinedCols += CI.second.Inlined.Analyzed;
|
||||
@ -319,6 +372,37 @@ static bool writeReport(LocationInfoTy &LocationInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
if (PrintFuncName) {
|
||||
OS << " > ";
|
||||
|
||||
bool FirstFunc = true;
|
||||
for (const auto &FuncName : FuncNameSet) {
|
||||
if (FirstFunc)
|
||||
FirstFunc = false;
|
||||
else
|
||||
OS << ", ";
|
||||
|
||||
bool Printed = false;
|
||||
if (Demangle) {
|
||||
int Status = 0;
|
||||
char *Demangled =
|
||||
itaniumDemangle(FuncName.c_str(), nullptr, nullptr, &Status);
|
||||
if (Demangled && Status == 0) {
|
||||
OS << Demangled;
|
||||
Printed = true;
|
||||
}
|
||||
|
||||
if (Demangled)
|
||||
std::free(Demangled);
|
||||
}
|
||||
|
||||
if (!Printed)
|
||||
OS << FuncName;
|
||||
}
|
||||
|
||||
OS << ":\n";
|
||||
}
|
||||
|
||||
// We try to keep the output as concise as possible. If only one thing on
|
||||
// a given line could have been inlined, vectorized, etc. then we can put
|
||||
// the marker on the source line itself. If there are multiple options
|
||||
@ -372,6 +456,32 @@ static bool writeReport(LocationInfoTy &LocationInfo) {
|
||||
OS << " | " << std::string(J.first - 1, ' ') << "^\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// We need to figure out if the optimizations for this line were the same
|
||||
// in each function context. If not, then we want to group the similar
|
||||
// function contexts together and display each group separately. If
|
||||
// they're all the same, then we only display the line once without any
|
||||
// additional markings.
|
||||
std::map<std::map<int, OptReportLocationInfo>,
|
||||
std::set<std::string>> UniqueLIs;
|
||||
|
||||
if (LII != FileInfo.end()) {
|
||||
const auto &FuncLineInfo = LII->second;
|
||||
for (const auto &FLII : FuncLineInfo)
|
||||
UniqueLIs[FLII.second].insert(FLII.first);
|
||||
}
|
||||
|
||||
if (UniqueLIs.size() > 1) {
|
||||
OS << " [[\n";
|
||||
for (const auto &FSLI : UniqueLIs)
|
||||
PrintLine(true, FSLI.second);
|
||||
OS << " ]]\n";
|
||||
} else if (UniqueLIs.size() == 1) {
|
||||
PrintLine(false, UniqueLIs.begin()->second);
|
||||
} else {
|
||||
PrintLine(false, std::set<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user