comparison gcc/opt-problem.cc @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
1 /* Rich optional information on why an optimization wasn't possible.
2 Copyright (C) 2018 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "tree.h"
26 #include "gimple.h"
27 #include "pretty-print.h"
28 #include "opt-problem.h"
29 #include "dump-context.h"
30 #include "tree-pass.h"
31 #include "selftest.h"
32
33 /* opt_problem's ctor.
34
35 Use FMT and AP to emit a message to the "immediate" dump destinations
36 as if via:
37 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, ...)
38
39 The optinfo_item instances are not emitted yet. Instead, they
40 are retained internally so that the message can be replayed and
41 emitted when this problem is handled, higher up the call stack. */
42
43 opt_problem::opt_problem (const dump_location_t &loc,
44 const char *fmt, va_list *ap)
45 : m_optinfo (loc, OPTINFO_KIND_FAILURE, current_pass)
46 {
47 /* We shouldn't be bothering to construct these objects if
48 dumping isn't enabled. */
49 gcc_assert (dump_enabled_p ());
50
51 /* Update the singleton. */
52 delete s_the_problem;
53 s_the_problem = this;
54
55 /* Print the location to the "immediate" dump destinations. */
56 dump_context &dc = dump_context::get ();
57 dc.dump_loc (MSG_MISSED_OPTIMIZATION, loc);
58
59 /* Print the formatted string to this opt_problem's optinfo, dumping
60 the items to the "immediate" dump destinations, and storing items
61 for later retrieval. */
62 {
63 dump_pretty_printer pp (&dump_context::get (), MSG_MISSED_OPTIMIZATION);
64
65 text_info text;
66 text.err_no = errno;
67 text.args_ptr = ap;
68 text.format_spec = fmt; /* No i18n is performed. */
69
70 /* Phases 1 and 2, using pp_format. */
71 pp_format (&pp, &text);
72
73 /* Phase 3: dump the items to the "immediate" dump destinations,
74 and storing them into m_optinfo for later retrieval. */
75 pp.emit_items (&m_optinfo);
76 }
77 }
78
79 /* Emit this problem and delete it, clearing the current opt_problem. */
80
81 void
82 opt_problem::emit_and_clear ()
83 {
84 gcc_assert (this == s_the_problem);
85
86 m_optinfo.emit_for_opt_problem ();
87
88 delete this;
89 s_the_problem = NULL;
90 }
91
92 /* The singleton opt_problem *. */
93
94 opt_problem *opt_problem::s_the_problem;
95
96 #if CHECKING_P
97
98 namespace selftest {
99
100 static opt_result
101 function_that_succeeds ()
102 {
103 return opt_result::success ();
104 }
105
106 /* Verify that opt_result::success works. */
107
108 static void
109 test_opt_result_success ()
110 {
111 /* Run all tests twice, with and then without dumping enabled. */
112 for (int i = 0 ; i < 2; i++)
113 {
114 bool with_dumping = (i == 0);
115
116 temp_dump_context tmp (with_dumping, with_dumping,
117 MSG_ALL_KINDS | MSG_ALL_PRIORITIES);
118
119 if (with_dumping)
120 gcc_assert (dump_enabled_p ());
121 else
122 gcc_assert (!dump_enabled_p ());
123
124 opt_result res = function_that_succeeds ();
125
126 /* Verify that "success" can be used as a "true" boolean. */
127 ASSERT_TRUE (res);
128
129 /* Verify the underlying opt_wrapper<bool>. */
130 ASSERT_TRUE (res.get_result ());
131 ASSERT_EQ (res.get_problem (), NULL);
132
133 /* Nothing should have been dumped. */
134 ASSERT_DUMPED_TEXT_EQ (tmp, "");
135 optinfo *info = tmp.get_pending_optinfo ();
136 ASSERT_EQ (info, NULL);
137 }
138 }
139
140 /* Example of a function that fails, with a non-trivial
141 pre-canned error message. */
142
143 static opt_result
144 function_that_fails (const greturn *stmt)
145 {
146 gcc_assert (stmt);
147 gcc_assert (gimple_return_retval (stmt));
148
149 AUTO_DUMP_SCOPE ("function_that_fails", stmt);
150
151 return opt_result::failure_at (stmt,
152 "can't handle return type: %T for stmt: %G",
153 TREE_TYPE (gimple_return_retval (stmt)),
154 static_cast <const gimple *> (stmt));
155 }
156
157 /* Example of a function that indirectly fails. */
158
159 static opt_result
160 function_that_indirectly_fails (const greturn *stmt)
161 {
162 AUTO_DUMP_SCOPE ("function_that_indirectly_fails", stmt);
163
164 opt_result res = function_that_fails (stmt);
165 if (!res)
166 return res;
167 return opt_result::success ();
168 }
169
170 /* Verify that opt_result::failure_at works.
171 Simulate a failure handling a stmt at one location whilst considering
172 an optimization that's notionally at another location (as a microcosm
173 of e.g. a problematic statement within a loop that prevents loop
174 vectorization). */
175
176 static void
177 test_opt_result_failure_at (const line_table_case &case_)
178 {
179 /* Generate a location_t for testing. */
180 line_table_test ltt (case_);
181 const line_map_ordinary *ord_map
182 = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
183 "test.c", 0));
184 linemap_line_start (line_table, 5, 100);
185
186 /* A test location: "test.c:5:10". */
187 const location_t line_5 = linemap_position_for_column (line_table, 10);
188
189 /* Another test location: "test.c:6:12". */
190 const location_t line_6
191 = linemap_position_for_line_and_column (line_table, ord_map, 6, 12);
192
193 if (line_6 > LINE_MAP_MAX_LOCATION_WITH_COLS)
194 return;
195
196 /* Generate statements using "line_5" and "line_6" for testing. */
197 greturn *stmt_at_5 = gimple_build_return (integer_one_node);
198 gimple_set_location (stmt_at_5, line_5);
199
200 greturn *stmt_at_6 = gimple_build_return (integer_zero_node);
201 gimple_set_location (stmt_at_6, line_6);
202
203 /* Run with and then without dumping enabled. */
204 for (int i = 0; i < 2; i++)
205 {
206 bool with_dumping = (i == 0);
207
208 /* Run with all 4 combinations of
209 with and without MSG_PRIORITY_INTERNALS and
210 with and without MSG_PRIORITY_REEMITTED. */
211 for (int j = 0; j < 4; j++)
212 {
213 dump_flags_t filter = MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING;
214 if (j / 2)
215 filter |= MSG_PRIORITY_INTERNALS;
216 if (j % 2)
217 filter |= MSG_PRIORITY_REEMITTED;
218
219 temp_dump_context tmp (with_dumping, with_dumping, filter);
220
221 if (with_dumping)
222 gcc_assert (dump_enabled_p ());
223 else
224 gcc_assert (!dump_enabled_p ());
225
226 /* Simulate attempting to optimize "stmt_at_6". */
227 opt_result res = function_that_indirectly_fails (stmt_at_6);
228
229 /* Verify that "failure" can be used as a "false" boolean. */
230 ASSERT_FALSE (res);
231
232 /* Verify the underlying opt_wrapper<bool>. */
233 ASSERT_FALSE (res.get_result ());
234 opt_problem *problem = res.get_problem ();
235
236 if (with_dumping)
237 {
238 ASSERT_NE (problem, NULL);
239 ASSERT_EQ (problem->get_dump_location ().get_location_t (),
240 line_6);
241 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
242 /* Verify that the problem captures the implementation location
243 it was emitted from. */
244 const dump_impl_location_t &impl_location
245 = problem->get_dump_location ().get_impl_location ();
246 ASSERT_STR_CONTAINS (impl_location.m_function,
247 "function_that_fails");
248 #endif
249
250 /* Verify that the underlying dump items are retained in the
251 opt_problem. */
252 const optinfo &info = problem->get_optinfo ();
253 ASSERT_EQ (info.get_dump_location ().get_location_t (), line_6);
254 ASSERT_EQ (info.num_items (), 4);
255 ASSERT_IS_TEXT (info.get_item (0), "can't handle return type: ");
256 ASSERT_IS_TREE (info.get_item (1), UNKNOWN_LOCATION, "int");
257 ASSERT_IS_TEXT (info.get_item (2), " for stmt: ");
258 ASSERT_IS_GIMPLE (info.get_item (3), line_6, "return 0;\n");
259
260 /* ...but not in the dump_context's pending_optinfo. */
261 ASSERT_EQ (tmp.get_pending_optinfo (), NULL);
262
263 /* Simulate emitting a high-level summary message, followed
264 by the problem. */
265 dump_printf_loc (MSG_MISSED_OPTIMIZATION, stmt_at_5,
266 "can't optimize loop\n");
267 problem->emit_and_clear ();
268 ASSERT_EQ (res.get_problem (), NULL);
269
270 /* Verify that the error message was dumped (when the failure
271 occurred). We can't use a switch here as not all of the
272 values are const expressions (using C++98). */
273 dump_flags_t effective_filter
274 = filter & (MSG_PRIORITY_INTERNALS | MSG_PRIORITY_REEMITTED);
275 if (effective_filter
276 == (MSG_PRIORITY_INTERNALS | MSG_PRIORITY_REEMITTED))
277 /* The -fopt-info-internals case. */
278 ASSERT_DUMPED_TEXT_EQ
279 (tmp,
280 "test.c:6:12: note: === function_that_indirectly_fails"
281 " ===\n"
282 "test.c:6:12: note: === function_that_fails ===\n"
283 "test.c:6:12: missed: can't handle return type: int"
284 " for stmt: return 0;\n"
285 "test.c:5:10: missed: can't optimize loop\n"
286 "test.c:6:12: missed: can't handle return type: int"
287 " for stmt: return 0;\n");
288 else if (effective_filter == MSG_PRIORITY_INTERNALS)
289 /* The default for dump files. */
290 ASSERT_DUMPED_TEXT_EQ
291 (tmp,
292 "test.c:6:12: note: === function_that_indirectly_fails"
293 " ===\n"
294 "test.c:6:12: note: === function_that_fails ===\n"
295 "test.c:6:12: missed: can't handle return type: int"
296 " for stmt: return 0;\n"
297 "test.c:5:10: missed: can't optimize loop\n");
298 else if (effective_filter == MSG_PRIORITY_REEMITTED)
299 /* The default when -fopt-info is enabled. */
300 ASSERT_DUMPED_TEXT_EQ
301 (tmp,
302 "test.c:5:10: missed: can't optimize loop\n"
303 "test.c:6:12: missed: can't handle return type: int"
304 " for stmt: return 0;\n");
305 else
306 {
307 gcc_assert (effective_filter == 0);
308 ASSERT_DUMPED_TEXT_EQ
309 (tmp,
310 "test.c:5:10: missed: can't optimize loop\n");
311 }
312 }
313 else
314 {
315 /* If dumping was disabled, then no problem should have been
316 created, and nothing should have been dumped. */
317 ASSERT_EQ (problem, NULL);
318 ASSERT_DUMPED_TEXT_EQ (tmp, "");
319 }
320 }
321 }
322 }
323
324 /* Run all of the selftests within this file. */
325
326 void
327 opt_problem_cc_tests ()
328 {
329 test_opt_result_success ();
330 for_each_line_table_case (test_opt_result_failure_at);
331 }
332
333 } // namespace selftest
334
335 #endif /* CHECKING_P */