GCC Middle and Back End API Reference
opt-problem.h
Go to the documentation of this file.
1/* Rich information on why an optimization wasn't possible.
2 Copyright (C) 2018-2024 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#ifndef GCC_OPT_PROBLEM_H
22#define GCC_OPT_PROBLEM_H
23
24#include "diagnostic-core.h" /* for ATTRIBUTE_GCC_DIAG. */
25#include "optinfo.h" /* for optinfo. */
26
27/* This header declares a family of wrapper classes for tracking a
28 success/failure value, while optionally supporting propagating an
29 opt_problem * describing any failure back up the call stack.
30
31 For instance, at the deepest point of the callstack where the failure
32 happens, rather than:
33
34 if (!check_something ())
35 {
36 if (dump_enabled_p ())
37 dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
38 "foo is unsupported.\n");
39 return false;
40 }
41 // [...more checks...]
42
43 // All checks passed:
44 return true;
45
46 we can capture the cause of the failure via:
47
48 if (!check_something ())
49 return opt_result::failure_at (stmt, "foo is unsupported");
50 // [...more checks...]
51
52 // All checks passed:
53 return opt_result::success ();
54
55 which effectively returns true or false, whilst recording any problem.
56
57 opt_result::success and opt_result::failure return opt_result values
58 which "looks like" true/false respectively, via operator bool().
59 If dump_enabled_p, then opt_result::failure also creates an opt_problem *,
60 capturing the pertinent data (here, "foo is unsupported " and "stmt").
61 If dumps are disabled, then opt_problem instances aren't
62 created, and it's equivalent to just returning a bool.
63
64 The opt_problem can be propagated via opt_result values back up
65 the call stack to where it makes most sense to the user.
66 For instance, rather than:
67
68 bool ok = try_something_that_might_fail ();
69 if (!ok)
70 {
71 if (dump_enabled_p ())
72 dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
73 "some message.\n");
74 return false;
75 }
76
77 we can replace the bool with an opt_result, so if dump_enabled_p, we
78 assume that if try_something_that_might_fail, an opt_problem * will be
79 created, and we can propagate it up the call chain:
80
81 opt_result ok = try_something_that_might_fail ();
82 if (!ok)
83 {
84 if (dump_enabled_p ())
85 dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
86 "some message.\n");
87 return ok; // propagating the opt_result
88 }
89
90 opt_result is an opt_wrapper<bool>, where opt_wrapper<T> is a base
91 class for wrapping a T, optionally propagating an opt_problem in
92 case of failure_at (when dumps are enabled). Similarly,
93 opt_pointer_wrapper<T> can be used to wrap pointer types (where non-NULL
94 signifies success, NULL signifies failure).
95
96 In all cases, opt_wrapper<T> acts as if the opt_problem were one of its
97 fields, but the opt_problem is actually stored in a global, so that when
98 compiled, an opt_wrapper<T> is effectively just a T, so that we're
99 still just passing e.g. a bool around; the opt_wrapper<T> classes
100 simply provide type-checking and an API to ensure that we provide
101 error-messages deep in the callstack at the places where problems
102 occur, and that we propagate them. This also avoids having
103 to manage the ownership of the opt_problem instances.
104
105 Using opt_result and opt_wrapper<T> documents the intent of the code
106 for the places where we represent success values, and allows the C++ type
107 system to track where the deepest points in the callstack are where we
108 need to emit the failure messages from. */
109
110/* A bundle of information about why an optimization failed (e.g.
111 vectorization), and the location in both the user's code and
112 in GCC itself where the problem occurred.
113
114 Instances are created by static member functions in opt_wrapper
115 subclasses, such as opt_result::failure.
116
117 Instances are only created when dump_enabled_p (). */
118
120{
121 public:
123
124 opt_problem (const dump_location_t &loc,
125 const char *fmt, va_list *ap)
127
128 const dump_location_t &
130
131 const optinfo & get_optinfo () const { return m_optinfo; }
132
133 void emit_and_clear ();
134
135 private:
137
139};
140
141/* A base class for wrapper classes that track a success/failure value, while
142 optionally supporting propagating an opt_problem * describing any
143 failure back up the call stack. */
144
145template <typename T>
147{
148 public:
149 typedef T wrapped_t;
150
151 /* Be accessible as the wrapped type. */
152 operator wrapped_t () const { return m_result; }
153
154 /* No public ctor. */
155
156 wrapped_t get_result () const { return m_result; }
158
159 protected:
160 opt_wrapper (wrapped_t result, opt_problem */*problem*/)
161 : m_result (result)
162 {
163 /* "problem" is ignored: although it looks like a field, we
164 actually just use the opt_problem singleton, so that
165 opt_wrapper<T> in memory is just a T. */
166 }
167
168 private:
170};
171
172/* Subclass of opt_wrapper<T> for bool, where
173 - true signifies "success", and
174 - false signifies "failure"
175 whilst effectively propagating an opt_problem * describing any failure
176 back up the call stack. */
177
178class opt_result : public opt_wrapper <bool>
179{
180 public:
181 /* Generate a "success" value: a wrapper around "true". */
182
183 static opt_result success () { return opt_result (true, NULL); }
184
185 /* Generate a "failure" value: a wrapper around "false", and,
186 if dump_enabled_p, an opt_problem. */
187
189 const char *fmt, ...)
191 {
192 opt_problem *problem = NULL;
194 {
195 va_list ap;
196 va_start (ap, fmt);
197 problem = new opt_problem (loc, fmt, &ap);
198 va_end (ap);
199 }
200 return opt_result (false, problem);
201 }
202
203 /* Given a failure wrapper of some other kind, make an opt_result failure
204 object, for propagating the opt_problem up the call stack. */
205
206 template <typename S>
207 static opt_result
209 {
210 return opt_result (false, other.get_problem ());
211 }
212
213 private:
214 /* Private ctor. Instances should be created by the success and failure
215 static member functions. */
217 : opt_wrapper <bool> (result, problem)
218 {}
219};
220
221/* Subclass of opt_wrapper<T> where T is a pointer type, for tracking
222 success/failure, where:
223 - a non-NULL value signifies "success", and
224 - a NULL value signifies "failure",
225 whilst effectively propagating an opt_problem * describing any failure
226 back up the call stack. */
227
228template <typename PtrType_t>
229class opt_pointer_wrapper : public opt_wrapper <PtrType_t>
230{
231 public:
233
234 /* Given a non-NULL pointer, make a success object wrapping it. */
235
241
242 /* Make a NULL pointer failure object, with the given message
243 (if dump_enabled_p). */
244
247 const char *fmt, ...)
249 {
250 opt_problem *problem = NULL;
252 {
253 va_list ap;
254 va_start (ap, fmt);
255 problem = new opt_problem (loc, fmt, &ap);
256 va_end (ap);
257 }
259 }
260
261 /* Given a failure wrapper of some other kind, make a NULL pointer
262 failure object, propagating the problem. */
263
264 template <typename S>
271
272 /* Support accessing the underlying pointer via ->. */
273
274 wrapped_pointer_t operator-> () const { return this->get_result (); }
275
276 private:
277 /* Private ctor. Instances should be built using the static member
278 functions "success" and "failure". */
279 opt_pointer_wrapper (wrapped_pointer_t result, opt_problem *problem)
280 : opt_wrapper<PtrType_t> (result, problem)
281 {}
282};
283
284/* A typedef for wrapping "tree" so that NULL_TREE can carry an
285 opt_problem describing the failure (if dump_enabled_p). */
286
288
289#endif /* #ifndef GCC_OPT_PROBLEM_H */
Definition dumpfile.h:446
Definition opt-problem.h:230
static opt_pointer_wrapper< wrapped_pointer_t > success(wrapped_pointer_t ptr)
Definition opt-problem.h:237
opt_pointer_wrapper(wrapped_pointer_t result, opt_problem *problem)
Definition opt-problem.h:279
static opt_pointer_wrapper< wrapped_pointer_t > propagate_failure(opt_wrapper< S > other)
Definition opt-problem.h:266
static opt_pointer_wrapper< wrapped_pointer_t > failure_at(const dump_location_t &loc, const char *fmt,...) ATTRIBUTE_GCC_DUMP_PRINTF(2
PtrType_t wrapped_pointer_t
Definition opt-problem.h:232
wrapped_pointer_t operator->() const
Definition opt-problem.h:274
Definition opt-problem.h:120
static opt_problem * get_singleton()
Definition opt-problem.h:122
const optinfo & get_optinfo() const
Definition opt-problem.h:131
const dump_location_t & get_dump_location() const
Definition opt-problem.h:129
optinfo m_optinfo
Definition opt-problem.h:136
static opt_problem * s_the_problem
Definition opt-problem.h:138
opt_problem(const dump_location_t &loc, const char *fmt, va_list *ap) ATTRIBUTE_GCC_DUMP_PRINTF(3
Definition opt-problem.cc:43
void emit_and_clear()
Definition opt-problem.cc:80
Definition opt-problem.h:179
static opt_result propagate_failure(opt_wrapper< S > other)
Definition opt-problem.h:208
static opt_result failure_at(const dump_location_t &loc, const char *fmt,...) ATTRIBUTE_GCC_DUMP_PRINTF(2
opt_result(wrapped_t result, opt_problem *problem)
Definition opt-problem.h:216
return opt_result(false, problem)
static opt_result success()
Definition opt-problem.h:183
Definition opt-problem.h:147
T wrapped_t
Definition opt-problem.h:149
opt_problem * get_problem() const
Definition opt-problem.h:157
opt_wrapper(wrapped_t result, opt_problem @endverbatim *)
Definition opt-problem.h:160
wrapped_t m_result
Definition opt-problem.h:169
wrapped_t get_result() const
Definition opt-problem.h:156
Definition optinfo.h:94
const dump_location_t & get_dump_location() const
Definition optinfo.h:106
#define ATTRIBUTE_GCC_DUMP_PRINTF(m, n)
Definition dumpfile.h:36
bool dump_enabled_p(void)
Definition dumpfile.h:532
T * ggc_alloc(ALONE_CXX_MEM_STAT_INFO)
Definition ggc.h:184
opt_pointer_wrapper< tree > opt_tree
Definition opt-problem.h:287
static void const char va_list ap
Definition read-md.cc:205
#define NULL
Definition system.h:50
#define bool
Definition system.h:893