llvm.org GIT mirror llvm / 0837bf4
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283402 91177308-0d34-0410-b5e6-96231b3b80d8 Hal Finkel 2 years ago
11 changed file(s) with 682 addition(s) and 77 deletion(s). Raw diff Collapse all Expand all
0 void bar();
1 void foo(int n) {
2 for (int i = 0; i < n; ++i)
3 bar();
4 }
5
6 void quack() {
7 foo(4);
8 }
9
10 void quack2() {
11 foo(4);
12 }
13
0 void bar();
1 void foo(int n) {
2 for (int i = 0; i < n; ++i)
3 bar();
4 }
5
6 void quack() {
7 foo(4);
8 }
9
10 void quack2() {
11 foo(4);
12 }
13
0 --- !Missed
1 Pass: inline
2 Name: NoDefinition
3 DebugLoc: { File: Inputs/q.c, Line: 4, Column: 5 }
4 Function: foo
5 Args:
6 - Callee: bar
7 - String: ' will not be inlined into '
8 - Caller: foo
9 - String: ' because its definition is unavailable'
10 ...
11 --- !Analysis
12 Pass: inline
13 Name: CanBeInlined
14 DebugLoc: { File: Inputs/q.c, Line: 8, Column: 3 }
15 Function: quack
16 Args:
17 - Callee: foo
18 - String: ' can be inlined into '
19 - Caller: quack
20 - String: ' with cost='
21 - Cost: '40'
22 - String: ' (threshold='
23 - Threshold: '275'
24 - String: ')'
25 ...
26 --- !Passed
27 Pass: inline
28 Name: Inlined
29 DebugLoc: { File: Inputs/q.c, Line: 8, Column: 3 }
30 Function: quack
31 Args:
32 - Callee: foo
33 - String: ' inlined into '
34 - Caller: quack
35 ...
36 --- !Passed
37 Pass: loop-unroll
38 Name: FullyUnrolled
39 DebugLoc: { File: Inputs/q.c, Line: 3, Column: 3 }
40 Function: quack
41 Args:
42 - String: 'completely unrolled loop with '
43 - UnrollCount: '4'
44 - String: ' iterations'
45 ...
46 --- !Analysis
47 Pass: inline
48 Name: CanBeInlined
49 DebugLoc: { File: Inputs/q.c, Line: 12, Column: 3 }
50 Function: quack2
51 Args:
52 - Callee: foo
53 - String: ' can be inlined into '
54 - Caller: quack2
55 - String: ' with cost='
56 - Cost: '40'
57 - String: ' (threshold='
58 - Threshold: '275'
59 - String: ')'
60 ...
61 --- !Passed
62 Pass: inline
63 Name: Inlined
64 DebugLoc: { File: Inputs/q.c, Line: 12, Column: 3 }
65 Function: quack2
66 Args:
67 - Callee: foo
68 - String: ' inlined into '
69 - Caller: quack2
70 ...
71 --- !Passed
72 Pass: loop-unroll
73 Name: FullyUnrolled
74 DebugLoc: { File: Inputs/q.c, Line: 3, Column: 3 }
75 Function: quack2
76 Args:
77 - String: 'completely unrolled loop with '
78 - UnrollCount: '4'
79 - String: ' iterations'
80 ...
81 --- !Analysis
82 Pass: loop-vectorize
83 Name: CantVectorizeCall
84 DebugLoc: { File: Inputs/q.c, Line: 4, Column: 5 }
85 Function: foo
86 Args:
87 - String: 'loop not vectorized: '
88 - String: call instruction cannot be vectorized
89 ...
90 --- !Missed
91 Pass: loop-vectorize
92 Name: MissedDetails
93 DebugLoc: { File: Inputs/q.c, Line: 3, Column: 3 }
94 Function: foo
95 Args:
96 - String: 'loop not vectorized: use -Rpass-analysis=loop-vectorize for more info'
97 ...
0 void bar();
1 void foo(int n) {
2 for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)
3 bar();
4 }
5
6 void quack() {
7 foo(4);
8 }
9
10 void quack2() {
11 foo(4);
12 }
13
0 --- !Missed
1 Pass: inline
2 Name: NoDefinition
3 DebugLoc: { File: Inputs/q2.c, Line: 4, Column: 5 }
4 Function: foo
5 Args:
6 - Callee: bar
7 - String: ' will not be inlined into '
8 - Caller: foo
9 - String: ' because its definition is unavailable'
10 ...
11 --- !Analysis
12 Pass: inline
13 Name: CanBeInlined
14 DebugLoc: { File: Inputs/q2.c, Line: 8, Column: 3 }
15 Function: quack
16 Args:
17 - Callee: foo
18 - String: ' can be inlined into '
19 - Caller: quack
20 - String: ' with cost='
21 - Cost: '55'
22 - String: ' (threshold='
23 - Threshold: '275'
24 - String: ')'
25 ...
26 --- !Passed
27 Pass: inline
28 Name: Inlined
29 DebugLoc: { File: Inputs/q2.c, Line: 8, Column: 3 }
30 Function: quack
31 Args:
32 - Callee: foo
33 - String: ' inlined into '
34 - Caller: quack
35 ...
36 --- !Passed
37 Pass: loop-unroll
38 Name: FullyUnrolled
39 DebugLoc: { File: Inputs/q2.c, Line: 3, Column: 31 }
40 Function: quack
41 Args:
42 - String: 'completely unrolled loop with '
43 - UnrollCount: '4'
44 - String: ' iterations'
45 ...
46 --- !Passed
47 Pass: loop-unroll
48 Name: FullyUnrolled
49 DebugLoc: { File: Inputs/q2.c, Line: 3, Column: 3 }
50 Function: quack
51 Args:
52 - String: 'completely unrolled loop with '
53 - UnrollCount: '4'
54 - String: ' iterations'
55 ...
56 --- !Analysis
57 Pass: inline
58 Name: CanBeInlined
59 DebugLoc: { File: Inputs/q2.c, Line: 12, Column: 3 }
60 Function: quack2
61 Args:
62 - Callee: foo
63 - String: ' can be inlined into '
64 - Caller: quack2
65 - String: ' with cost='
66 - Cost: '55'
67 - String: ' (threshold='
68 - Threshold: '275'
69 - String: ')'
70 ...
71 --- !Passed
72 Pass: inline
73 Name: Inlined
74 DebugLoc: { File: Inputs/q2.c, Line: 12, Column: 3 }
75 Function: quack2
76 Args:
77 - Callee: foo
78 - String: ' inlined into '
79 - Caller: quack2
80 ...
81 --- !Passed
82 Pass: loop-unroll
83 Name: FullyUnrolled
84 DebugLoc: { File: Inputs/q2.c, Line: 3, Column: 31 }
85 Function: quack2
86 Args:
87 - String: 'completely unrolled loop with '
88 - UnrollCount: '4'
89 - String: ' iterations'
90 ...
91 --- !Passed
92 Pass: loop-unroll
93 Name: FullyUnrolled
94 DebugLoc: { File: Inputs/q2.c, Line: 3, Column: 3 }
95 Function: quack2
96 Args:
97 - String: 'completely unrolled loop with '
98 - UnrollCount: '4'
99 - String: ' iterations'
100 ...
101 --- !Analysis
102 Pass: loop-vectorize
103 Name: CantVectorizeCall
104 DebugLoc: { File: Inputs/q2.c, Line: 4, Column: 5 }
105 Function: foo
106 Args:
107 - String: 'loop not vectorized: '
108 - String: call instruction cannot be vectorized
109 ...
110 --- !Missed
111 Pass: loop-vectorize
112 Name: MissedDetails
113 DebugLoc: { File: Inputs/q2.c, Line: 3, Column: 31 }
114 Function: foo
115 Args:
116 - String: 'loop not vectorized: use -Rpass-analysis=loop-vectorize for more info'
117 ...
0 --- !Missed
1 Pass: inline
2 Name: NoDefinition
3 DebugLoc: { File: Inputs/q.cpp, Line: 4, Column: 5 }
4 Function: _Z3fooi
5 Args:
6 - Callee: _Z3barv
7 - String: ' will not be inlined into '
8 - Caller: _Z3fooi
9 - String: ' because its definition is unavailable'
10 ...
11 --- !Analysis
12 Pass: inline
13 Name: CanBeInlined
14 DebugLoc: { File: Inputs/q.cpp, Line: 8, Column: 3 }
15 Function: _Z5quackv
16 Args:
17 - Callee: _Z3fooi
18 - String: ' can be inlined into '
19 - Caller: _Z5quackv
20 - String: ' with cost='
21 - Cost: '40'
22 - String: ' (threshold='
23 - Threshold: '275'
24 - String: ')'
25 ...
26 --- !Passed
27 Pass: inline
28 Name: Inlined
29 DebugLoc: { File: Inputs/q.cpp, Line: 8, Column: 3 }
30 Function: _Z5quackv
31 Args:
32 - Callee: _Z3fooi
33 - String: ' inlined into '
34 - Caller: _Z5quackv
35 ...
36 --- !Passed
37 Pass: loop-unroll
38 Name: FullyUnrolled
39 DebugLoc: { File: Inputs/q.cpp, Line: 3, Column: 3 }
40 Function: _Z5quackv
41 Args:
42 - String: 'completely unrolled loop with '
43 - UnrollCount: '4'
44 - String: ' iterations'
45 ...
46 --- !Analysis
47 Pass: inline
48 Name: CanBeInlined
49 DebugLoc: { File: Inputs/q.cpp, Line: 12, Column: 3 }
50 Function: _Z6quack2v
51 Args:
52 - Callee: _Z3fooi
53 - String: ' can be inlined into '
54 - Caller: _Z6quack2v
55 - String: ' with cost='
56 - Cost: '40'
57 - String: ' (threshold='
58 - Threshold: '275'
59 - String: ')'
60 ...
61 --- !Passed
62 Pass: inline
63 Name: Inlined
64 DebugLoc: { File: Inputs/q.cpp, Line: 12, Column: 3 }
65 Function: _Z6quack2v
66 Args:
67 - Callee: _Z3fooi
68 - String: ' inlined into '
69 - Caller: _Z6quack2v
70 ...
71 --- !Passed
72 Pass: loop-unroll
73 Name: FullyUnrolled
74 DebugLoc: { File: Inputs/q.cpp, Line: 3, Column: 3 }
75 Function: _Z6quack2v
76 Args:
77 - String: 'completely unrolled loop with '
78 - UnrollCount: '4'
79 - String: ' iterations'
80 ...
81 --- !Analysis
82 Pass: loop-vectorize
83 Name: CantVectorizeCall
84 DebugLoc: { File: Inputs/q.cpp, Line: 4, Column: 5 }
85 Function: _Z3fooi
86 Args:
87 - String: 'loop not vectorized: '
88 - String: call instruction cannot be vectorized
89 ...
90 --- !Missed
91 Pass: loop-vectorize
92 Name: MissedDetails
93 DebugLoc: { File: Inputs/q.cpp, Line: 3, Column: 3 }
94 Function: _Z3fooi
95 Args:
96 - String: 'loop not vectorized: use -Rpass-analysis=loop-vectorize for more info'
97 ...
0 RUN: llvm-opt-report -r %p %p/Inputs/q2.yaml | FileCheck -strict-whitespace %s
1 RUN: llvm-opt-report -s -r %p %p/Inputs/q2.yaml | FileCheck -strict-whitespace -check-prefix=CHECK-SUCCINCT %s
2
3 ; CHECK: < {{.*}}/Inputs/q2.c
4 ; CHECK-NEXT: 2 | void bar();
5 ; CHECK-NEXT: 3 | void foo(int n) {
6 ; CHECK-NEXT: {{\[\[}}
7 ; CHECK-NEXT: > quack, quack2:
8 ; CHECK-NEXT: 4 | for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)
9 ; CHECK-NEXT: U4 | ^
10 ; CHECK-NEXT: U4 | ^
11 ; CHECK-NEXT: > foo:
12 ; CHECK-NEXT: 4 | for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)
13 ; CHECK-NEXT: {{\]\]}}
14 ; CHECK-NEXT: 5 | bar();
15 ; CHECK-NEXT: 6 | }
16 ; CHECK-NEXT: 7 |
17 ; CHECK-NEXT: 8 | void quack() {
18 ; CHECK-NEXT: 9 I | foo(4);
19 ; CHECK-NEXT: 10 | }
20 ; CHECK-NEXT: 11 |
21 ; CHECK-NEXT: 12 | void quack2() {
22 ; CHECK-NEXT: 13 I | foo(4);
23 ; CHECK-NEXT: 14 | }
24 ; CHECK-NEXT: 15 |
25
26 ; CHECK-SUCCINCT: < {{.*}}/Inputs/q2.c
27 ; CHECK-SUCCINCT-NEXT: 2 | void bar();
28 ; CHECK-SUCCINCT-NEXT: 3 | void foo(int n) {
29 ; CHECK-SUCCINCT-NEXT: {{\[\[}}
30 ; CHECK-SUCCINCT-NEXT: > quack, quack2:
31 ; CHECK-SUCCINCT-NEXT: 4 | for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)
32 ; CHECK-SUCCINCT-NEXT: U | ^
33 ; CHECK-SUCCINCT-NEXT: U | ^
34 ; CHECK-SUCCINCT-NEXT: > foo:
35 ; CHECK-SUCCINCT-NEXT: 4 | for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)
36 ; CHECK-SUCCINCT-NEXT: {{\]\]}}
37 ; CHECK-SUCCINCT-NEXT: 5 | bar();
38 ; CHECK-SUCCINCT-NEXT: 6 | }
39 ; CHECK-SUCCINCT-NEXT: 7 |
40 ; CHECK-SUCCINCT-NEXT: 8 | void quack() {
41 ; CHECK-SUCCINCT-NEXT: 9 I | foo(4);
42 ; CHECK-SUCCINCT-NEXT: 10 | }
43 ; CHECK-SUCCINCT-NEXT: 11 |
44 ; CHECK-SUCCINCT-NEXT: 12 | void quack2() {
45 ; CHECK-SUCCINCT-NEXT: 13 I | foo(4);
46 ; CHECK-SUCCINCT-NEXT: 14 | }
47 ; CHECK-SUCCINCT-NEXT: 15 |
48
0 RUN: llvm-opt-report -r %p %p/Inputs/qx.yaml | FileCheck -strict-whitespace %s
1 RUN: llvm-opt-report -s -r %p %p/Inputs/qx.yaml | FileCheck -strict-whitespace -check-prefix=CHECK-SUCCINCT %s
2
3 ; CHECK: < {{.*}}/Inputs/q.cpp
4 ; CHECK-NEXT: 2 | void bar();
5 ; CHECK-NEXT: 3 | void foo(int n) {
6 ; CHECK-NEXT: {{\[\[}}
7 ; CHECK-NEXT: > foo(int):
8 ; CHECK-NEXT: 4 | for (int i = 0; i < n; ++i)
9 ; CHECK-NEXT: > quack(), quack2():
10 ; CHECK-NEXT: 4 U4 | for (int i = 0; i < n; ++i)
11 ; CHECK-NEXT: {{\]\]}}
12 ; CHECK-NEXT: 5 | bar();
13 ; CHECK-NEXT: 6 | }
14 ; CHECK-NEXT: 7 |
15 ; CHECK-NEXT: 8 | void quack() {
16 ; CHECK-NEXT: 9 I | foo(4);
17 ; CHECK-NEXT: 10 | }
18 ; CHECK-NEXT: 11 |
19 ; CHECK-NEXT: 12 | void quack2() {
20 ; CHECK-NEXT: 13 I | foo(4);
21 ; CHECK-NEXT: 14 | }
22 ; CHECK-NEXT: 15 |
23
24 ; CHECK-SUCCINCT: < {{.*}}/Inputs/q.cpp
25 ; CHECK-SUCCINCT-NEXT: 2 | void bar();
26 ; CHECK-SUCCINCT-NEXT: 3 | void foo(int n) {
27 ; CHECK-SUCCINCT-NEXT: {{\[\[}}
28 ; CHECK-SUCCINCT-NEXT: > foo(int):
29 ; CHECK-SUCCINCT-NEXT: 4 | for (int i = 0; i < n; ++i)
30 ; CHECK-SUCCINCT-NEXT: > quack(), quack2():
31 ; CHECK-SUCCINCT-NEXT: 4 U | for (int i = 0; i < n; ++i)
32 ; CHECK-SUCCINCT-NEXT: {{\]\]}}
33 ; CHECK-SUCCINCT-NEXT: 5 | bar();
34 ; CHECK-SUCCINCT-NEXT: 6 | }
35 ; CHECK-SUCCINCT-NEXT: 7 |
36 ; CHECK-SUCCINCT-NEXT: 8 | void quack() {
37 ; CHECK-SUCCINCT-NEXT: 9 I | foo(4);
38 ; CHECK-SUCCINCT-NEXT: 10 | }
39 ; CHECK-SUCCINCT-NEXT: 11 |
40 ; CHECK-SUCCINCT-NEXT: 12 | void quack2() {
41 ; CHECK-SUCCINCT-NEXT: 13 I | foo(4);
42 ; CHECK-SUCCINCT-NEXT: 14 | }
43 ; CHECK-SUCCINCT-NEXT: 15 |
44
0 RUN: llvm-opt-report -r %p %p/Inputs/q.yaml | FileCheck -strict-whitespace %s
1 RUN: llvm-opt-report -s -r %p %p/Inputs/q.yaml | FileCheck -strict-whitespace -check-prefix=CHECK-SUCCINCT %s
2
3 ; CHECK: < {{.*}}/Inputs/q.c
4 ; CHECK-NEXT: 2 | void bar();
5 ; CHECK-NEXT: 3 | void foo(int n) {
6 ; CHECK-NEXT: {{\[\[}}
7 ; CHECK-NEXT: > foo:
8 ; CHECK-NEXT: 4 | for (int i = 0; i < n; ++i)
9 ; CHECK-NEXT: > quack, quack2:
10 ; CHECK-NEXT: 4 U4 | for (int i = 0; i < n; ++i)
11 ; CHECK-NEXT: {{\]\]}}
12 ; CHECK-NEXT: 5 | bar();
13 ; CHECK-NEXT: 6 | }
14 ; CHECK-NEXT: 7 |
15 ; CHECK-NEXT: 8 | void quack() {
16 ; CHECK-NEXT: 9 I | foo(4);
17 ; CHECK-NEXT: 10 | }
18 ; CHECK-NEXT: 11 |
19 ; CHECK-NEXT: 12 | void quack2() {
20 ; CHECK-NEXT: 13 I | foo(4);
21 ; CHECK-NEXT: 14 | }
22 ; CHECK-NEXT: 15 |
23
24 ; CHECK-SUCCINCT: < {{.*}}/Inputs/q.c
25 ; CHECK-SUCCINCT-NEXT: 2 | void bar();
26 ; CHECK-SUCCINCT-NEXT: 3 | void foo(int n) {
27 ; CHECK-SUCCINCT-NEXT: {{\[\[}}
28 ; CHECK-SUCCINCT-NEXT: > foo:
29 ; CHECK-SUCCINCT-NEXT: 4 | for (int i = 0; i < n; ++i)
30 ; CHECK-SUCCINCT-NEXT: > quack, quack2:
31 ; CHECK-SUCCINCT-NEXT: 4 U | for (int i = 0; i < n; ++i)
32 ; CHECK-SUCCINCT-NEXT: {{\]\]}}
33 ; CHECK-SUCCINCT-NEXT: 5 | bar();
34 ; CHECK-SUCCINCT-NEXT: 6 | }
35 ; CHECK-SUCCINCT-NEXT: 7 |
36 ; CHECK-SUCCINCT-NEXT: 8 | void quack() {
37 ; CHECK-SUCCINCT-NEXT: 9 I | foo(4);
38 ; CHECK-SUCCINCT-NEXT: 10 | }
39 ; CHECK-SUCCINCT-NEXT: 11 |
40 ; CHECK-SUCCINCT-NEXT: 12 | void quack2() {
41 ; CHECK-SUCCINCT-NEXT: 13 I | foo(4);
42 ; CHECK-SUCCINCT-NEXT: 14 | }
43 ; CHECK-SUCCINCT-NEXT: 15 |
44
None set(LLVM_LINK_COMPONENTS Core Object Support)
0 set(LLVM_LINK_COMPONENTS Core Demangle Object Support)
11
22 add_llvm_tool(llvm-opt-report
33 OptReport.cpp
1414 //===----------------------------------------------------------------------===//
1515
1616 #include "llvm/Support/CommandLine.h"
17 #include "llvm/Demangle/Demangle.h"
1718 #include "llvm/Support/Error.h"
1819 #include "llvm/Support/ErrorOr.h"
1920 #include "llvm/Support/FileSystem.h"
2627 #include "llvm/Support/raw_ostream.h"
2728 #include "llvm/Support/Signals.h"
2829 #include "llvm/Support/YAMLTraits.h"
30 #include
31 #include
32 #include
2933
3034 using namespace llvm;
3135 using namespace llvm::yaml;
5256 static cl::opt
5357 Succinct("s", cl::desc("Don't include vectorization factors, etc."),
5458 cl::init(false), cl::cat(OptReportCategory));
59
60 static cl::opt
61 Demangle("demangle", cl::desc("Demangle function names"), cl::init(true),
62 cl::cat(OptReportCategory));
5563
5664 namespace {
5765 // For each location in the source file, the common per-transformation state
6775
6876 return *this;
6977 }
78
79 bool operator < (const OptReportLocationItemInfo &RHS) const {
80 if (Analyzed < RHS.Analyzed)
81 return true;
82 else if (Analyzed > RHS.Analyzed)
83 return false;
84 else if (Transformed < RHS.Transformed)
85 return true;
86 return false;
87 }
7088 };
7189
7290 // The per-location information collected for producing an optimization report.
91109
92110 return *this;
93111 }
112
113 bool operator < (const OptReportLocationInfo &RHS) const {
114 if (Inlined < RHS.Inlined)
115 return true;
116 else if (RHS.Inlined < Inlined)
117 return false;
118 else if (Unrolled < RHS.Unrolled)
119 return true;
120 else if (RHS.Unrolled < Unrolled)
121 return false;
122 else if (Vectorized < RHS.Vectorized)
123 return true;
124 else if (RHS.Vectorized < Vectorized || Succinct)
125 return false;
126 else if (VectorizationFactor < RHS.VectorizationFactor)
127 return true;
128 else if (VectorizationFactor > RHS.VectorizationFactor)
129 return false;
130 else if (InterleaveCount < RHS.InterleaveCount)
131 return true;
132 else if (InterleaveCount > RHS.InterleaveCount)
133 return false;
134 else if (InterleaveCount < RHS.InterleaveCount)
135 return true;
136 return false;
137 }
94138 };
95139
96 typedef std::map
97 OptReportLocationInfo>>> LocationInfoTy;
140 typedef std::map
141 OptReportLocationInfo>>>> LocationInfoTy;
98142 } // anonymous namespace
99143
100144 static void collectLocationInfo(yaml::Stream &Stream,
114158 continue;
115159
116160 bool Transformed = Root->getRawTag() == "!Passed";
117 std::string Pass, File;
161 std::string Pass, File, Function;
118162 int Line = 0, Column = 1;
119163
120164 int VectorizationFactor = 1;
131175 if (!Value)
132176 continue;
133177 Pass = Value->getValue(Tmp);
178 } else if (KeyName == "Function") {
179 auto *Value = dyn_cast(RootChild.getValue());
180 if (!Value)
181 continue;
182 Function = Value->getValue(Tmp);
134183 } else if (KeyName == "DebugLoc") {
135184 auto *DebugLoc = dyn_cast(RootChild.getValue());
136185 if (!DebugLoc)
213262 };
214263
215264 if (Pass == "inline") {
216 auto &LI = LocationInfo[File][Line][Column];
265 auto &LI = LocationInfo[File][Line][Function][Column];
217266 UpdateLLII(LI, LI.Inlined);
218267 } else if (Pass == "loop-unroll") {
219 auto &LI = LocationInfo[File][Line][Column];
268 auto &LI = LocationInfo[File][Line][Function][Column];
220269 UpdateLLII(LI, LI.Unrolled);
221270 } else if (Pass == "loop-vectorize") {
222 auto &LI = LocationInfo[File][Line][Column];
271 auto &LI = LocationInfo[File][Line][Function][Column];
223272 UpdateLLII(LI, LI.Vectorized);
224273 }
225274 }
282331 // Figure out how many characters we need for the vectorization factors
283332 // and similar.
284333 OptReportLocationInfo MaxLI;
285 for (auto &FI : FileInfo)
286 for (auto &LI : FI.second)
287 MaxLI |= LI.second;
334 for (auto &FLI : FileInfo)
335 for (auto &FI : FLI.second)
336 for (auto &LI : FI.second)
337 MaxLI |= LI.second;
288338
289339 unsigned VFDigits = llvm::utostr(MaxLI.VectorizationFactor).size();
290340 unsigned ICDigits = llvm::utostr(MaxLI.InterleaveCount).size();
299349
300350 for (line_iterator LI(*Buf.get(), false); LI != line_iterator(); ++LI) {
301351 int64_t L = LI.line_number();
302 OptReportLocationInfo LLI;
303
304 std::map ColsInfo;
305 unsigned InlinedCols = 0, UnrolledCols = 0, VectorizedCols = 0;
306
307352 auto LII = FileInfo.find(L);
353
354 auto PrintLine = [&](bool PrintFuncName,
355 const std::set &FuncNameSet) {
356 OptReportLocationInfo LLI;
357
358 std::map ColsInfo;
359 unsigned InlinedCols = 0, UnrolledCols = 0, VectorizedCols = 0;
360
361 if (LII != FileInfo.end()) {
362 const auto &LineInfo = LII->second;
363
364 for (auto &CI : LineInfo.find(*FuncNameSet.begin())->second) {
365 int Col = CI.first;
366 ColsInfo[Col] = CI.second;
367 InlinedCols += CI.second.Inlined.Analyzed;
368 UnrolledCols += CI.second.Unrolled.Analyzed;
369 VectorizedCols += CI.second.Vectorized.Analyzed;
370 LLI |= CI.second;
371 }
372 }
373
374 if (PrintFuncName) {
375 OS << " > ";
376
377 bool FirstFunc = true;
378 for (const auto &FuncName : FuncNameSet) {
379 if (FirstFunc)
380 FirstFunc = false;
381 else
382 OS << ", ";
383
384 bool Printed = false;
385 if (Demangle) {
386 int Status = 0;
387 char *Demangled =
388 itaniumDemangle(FuncName.c_str(), nullptr, nullptr, &Status);
389 if (Demangled && Status == 0) {
390 OS << Demangled;
391 Printed = true;
392 }
393
394 if (Demangled)
395 std::free(Demangled);
396 }
397
398 if (!Printed)
399 OS << FuncName;
400 }
401
402 OS << ":\n";
403 }
404
405 // We try to keep the output as concise as possible. If only one thing on
406 // a given line could have been inlined, vectorized, etc. then we can put
407 // the marker on the source line itself. If there are multiple options
408 // then we want to distinguish them by placing the marker for each
409 // transformation on a separate line following the source line. When we
410 // do this, we use a '^' character to point to the appropriate column in
411 // the source line.
412
413 std::string USpaces(Succinct ? 0 : UCDigits, ' ');
414 std::string VSpaces(Succinct ? 0 : VFDigits + ICDigits + 1, ' ');
415
416 auto UStr = [UCDigits](OptReportLocationInfo &LLI) {
417 std::string R;
418 raw_string_ostream RS(R);
419 if (!Succinct)
420 RS << llvm::format_decimal(LLI.UnrollCount, UCDigits);
421 return RS.str();
422 };
423
424 auto VStr = [VFDigits,
425 ICDigits](OptReportLocationInfo &LLI) -> std::string {
426 std::string R;
427 raw_string_ostream RS(R);
428 if (!Succinct)
429 RS << llvm::format_decimal(LLI.VectorizationFactor, VFDigits) <<
430 "," << llvm::format_decimal(LLI.InterleaveCount, ICDigits);
431 return RS.str();
432 };
433
434 OS << llvm::format_decimal(L + 1, LNDigits) << " ";
435 OS << (LLI.Inlined.Transformed && InlinedCols < 2 ? "I" : " ");
436 OS << (LLI.Unrolled.Transformed && UnrolledCols < 2 ?
437 "U" + UStr(LLI) : " " + USpaces);
438 OS << (LLI.Vectorized.Transformed && VectorizedCols < 2 ?
439 "V" + VStr(LLI) : " " + VSpaces);
440
441 OS << " | " << *LI << "\n";
442
443 for (auto &J : ColsInfo) {
444 if ((J.second.Inlined.Transformed && InlinedCols > 1) ||
445 (J.second.Unrolled.Transformed && UnrolledCols > 1) ||
446 (J.second.Vectorized.Transformed && VectorizedCols > 1)) {
447 OS << std::string(LNDigits + 1, ' ');
448 OS << (J.second.Inlined.Transformed &&
449 InlinedCols > 1 ? "I" : " ");
450 OS << (J.second.Unrolled.Transformed &&
451 UnrolledCols > 1 ? "U" + UStr(J.second) : " " + USpaces);
452 OS << (J.second.Vectorized.Transformed &&
453 VectorizedCols > 1 ? "V" + VStr(J.second) : " " + VSpaces);
454
455 OS << " | " << std::string(J.first - 1, ' ') << "^\n";
456 }
457 }
458 };
459
460 // We need to figure out if the optimizations for this line were the same
461 // in each function context. If not, then we want to group the similar
462 // function contexts together and display each group separately. If
463 // they're all the same, then we only display the line once without any
464 // additional markings.
465 std::map,
466 std::set> UniqueLIs;
467
308468 if (LII != FileInfo.end()) {
309 const auto &LineInfo = LII->second;
310
311 for (auto &CI : LineInfo) {
312 int Col = CI.first;
313 ColsInfo[Col] = CI.second;
314 InlinedCols += CI.second.Inlined.Analyzed;
315 UnrolledCols += CI.second.Unrolled.Analyzed;
316 VectorizedCols += CI.second.Vectorized.Analyzed;
317 LLI |= CI.second;
318 }
469 const auto &FuncLineInfo = LII->second;
470 for (const auto &FLII : FuncLineInfo)
471 UniqueLIs[FLII.second].insert(FLII.first);
319472 }
320473
321 // We try to keep the output as concise as possible. If only one thing on
322 // a given line could have been inlined, vectorized, etc. then we can put
323 // the marker on the source line itself. If there are multiple options
324 // then we want to distinguish them by placing the marker for each
325 // transformation on a separate line following the source line. When we
326 // do this, we use a '^' character to point to the appropriate column in
327 // the source line.
328
329 std::string USpaces(Succinct ? 0 : UCDigits, ' ');
330 std::string VSpaces(Succinct ? 0 : VFDigits + ICDigits + 1, ' ');
331
332 auto UStr = [UCDigits](OptReportLocationInfo &LLI) {
333 std::string R;
334 raw_string_ostream RS(R);
335 if (!Succinct)
336 RS << llvm::format_decimal(LLI.UnrollCount, UCDigits);
337 return RS.str();
338 };
339
340 auto VStr = [VFDigits,
341 ICDigits](OptReportLocationInfo &LLI) -> std::string {
342 std::string R;
343 raw_string_ostream RS(R);
344 if (!Succinct)
345 RS << llvm::format_decimal(LLI.VectorizationFactor, VFDigits) <<
346 "," << llvm::format_decimal(LLI.InterleaveCount, ICDigits);
347 return RS.str();
348 };
349
350 OS << llvm::format_decimal(L + 1, LNDigits) << " ";
351 OS << (LLI.Inlined.Transformed && InlinedCols < 2 ? "I" : " ");
352 OS << (LLI.Unrolled.Transformed && UnrolledCols < 2 ?
353 "U" + UStr(LLI) : " " + USpaces);
354 OS << (LLI.Vectorized.Transformed && VectorizedCols < 2 ?
355 "V" + VStr(LLI) : " " + VSpaces);
356
357 OS << " | " << *LI << "\n";
358
359 for (auto &J : ColsInfo) {
360 if ((J.second.Inlined.Transformed && InlinedCols > 1) ||
361 (J.second.Unrolled.Transformed && UnrolledCols > 1) ||
362 (J.second.Vectorized.Transformed && VectorizedCols > 1)) {
363 OS << std::string(LNDigits + 1, ' ');
364 OS << (J.second.Inlined.Transformed &&
365 InlinedCols > 1 ? "I" : " ");
366 OS << (J.second.Unrolled.Transformed &&
367 UnrolledCols > 1 ? "U" + UStr(J.second) : " " + USpaces);
368 OS << (J.second.Vectorized.Transformed &&
369 VectorizedCols > 1 ? "V" + VStr(J.second) : " " + VSpaces);
370
371 OS << " | " << std::string(J.first - 1, ' ') << "^\n";
372 }
474 if (UniqueLIs.size() > 1) {
475 OS << " [[\n";
476 for (const auto &FSLI : UniqueLIs)
477 PrintLine(true, FSLI.second);
478 OS << " ]]\n";
479 } else if (UniqueLIs.size() == 1) {
480 PrintLine(false, UniqueLIs.begin()->second);
481 } else {
482 PrintLine(false, std::set());
373483 }
374484 }
375485 }