GCC Middle and Back End API Reference
opt_problem Class Reference

#include <opt-problem.h>

Collaboration diagram for opt_problem:

Public Member Functions

 opt_problem (const dump_location_t &loc, const char *fmt, va_list *ap) ATTRIBUTE_GCC_DUMP_PRINTF(3
 
const dump_location_tget_dump_location () const
 
const optinfoget_optinfo () const
 
void emit_and_clear ()
 

Static Public Member Functions

static opt_problemget_singleton ()
 

Private Attributes

optinfo m_optinfo
 

Static Private Attributes

static opt_problems_the_problem
 

Detailed Description

Rich information on why an optimization wasn't possible.
   Copyright (C) 2018-2024 Free Software Foundation, Inc.
   Contributed by David Malcolm <dmalcolm@redhat.com>.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.   
This header declares a family of wrapper classes for tracking a
success/failure value, while optionally supporting propagating an
opt_problem * describing any failure back up the call stack.

For instance, at the deepest point of the callstack where the failure
happens, rather than:

  if (!check_something ())
    {
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                         "foo is unsupported.\n");
      return false;
    }
  // [...more checks...]

  // All checks passed:
  return true;

we can capture the cause of the failure via:

  if (!check_something ())
    return opt_result::failure_at (stmt, "foo is unsupported");
  // [...more checks...]

  // All checks passed:
  return opt_result::success ();

which effectively returns true or false, whilst recording any problem.

opt_result::success and opt_result::failure return opt_result values
which "looks like" true/false respectively, via operator bool().
If dump_enabled_p, then opt_result::failure also creates an opt_problem *,
capturing the pertinent data (here, "foo is unsupported " and "stmt").
If dumps are disabled, then opt_problem instances aren't
created, and it's equivalent to just returning a bool.

The opt_problem can be propagated via opt_result values back up
the call stack to where it makes most sense to the user.
For instance, rather than:

  bool ok = try_something_that_might_fail ();
  if (!ok)
    {
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                         "some message.\n");
      return false;
    }

we can replace the bool with an opt_result, so if dump_enabled_p, we
assume that if try_something_that_might_fail, an opt_problem * will be
created, and we can propagate it up the call chain:

  opt_result ok = try_something_that_might_fail ();
  if (!ok)
    {
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                         "some message.\n");
      return ok; // propagating the opt_result
    }

opt_result is an opt_wrapper<bool>, where opt_wrapper<T> is a base
class for wrapping a T, optionally propagating an opt_problem in
case of failure_at (when dumps are enabled).  Similarly,
opt_pointer_wrapper<T> can be used to wrap pointer types (where non-NULL
signifies success, NULL signifies failure).

In all cases, opt_wrapper<T> acts as if the opt_problem were one of its
fields, but the opt_problem is actually stored in a global, so that when
compiled, an opt_wrapper<T> is effectively just a T, so that we're
still just passing e.g. a bool around; the opt_wrapper<T> classes
simply provide type-checking and an API to ensure that we provide
error-messages deep in the callstack at the places where problems
occur, and that we propagate them.  This also avoids having
to manage the ownership of the opt_problem instances.

Using opt_result and opt_wrapper<T> documents the intent of the code
for the places where we represent success values, and allows the C++ type
system to track where the deepest points in the callstack are where we
need to emit the failure messages from.   
A bundle of information about why an optimization failed (e.g.
vectorization), and the location in both the user's code and
in GCC itself where the problem occurred.

Instances are created by static member functions in opt_wrapper
subclasses, such as opt_result::failure.

Instances are only created when dump_enabled_p ().   

Constructor & Destructor Documentation

◆ opt_problem()

opt_problem::opt_problem ( const dump_location_t & loc,
const char * fmt,
va_list * ap )
Rich optional information on why an optimization wasn't possible.
   Copyright (C) 2018-2024 Free Software Foundation, Inc.
   Contributed by David Malcolm <dmalcolm@redhat.com>.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.   
opt_problem's ctor.

Use FMT and AP to emit a message to the "immediate" dump destinations
as if via:
  dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, ...)

The optinfo_item instances are not emitted yet.  Instead, they
are retained internally so that the message can be replayed and
emitted when this problem is handled, higher up the call stack.   

References ap, dump_enabled_p(), dump_context::dump_loc(), dump_pretty_printer::emit_items(), errno, gcc_assert, dump_context::get(), dump_location_t::get_user_location(), ggc_alloc(), m_optinfo, MSG_MISSED_OPTIMIZATION, pp_format(), and s_the_problem.

Member Function Documentation

◆ emit_and_clear()

void opt_problem::emit_and_clear ( )
Emit this problem and delete it, clearing the current opt_problem.   

References optinfo::emit_for_opt_problem(), gcc_assert, m_optinfo, NULL, and s_the_problem.

◆ get_dump_location()

const dump_location_t & opt_problem::get_dump_location ( ) const
inline

◆ get_optinfo()

const optinfo & opt_problem::get_optinfo ( ) const
inline

References m_optinfo.

◆ get_singleton()

static opt_problem * opt_problem::get_singleton ( )
inlinestatic

References s_the_problem.

Referenced by opt_wrapper< T >::get_problem().

Field Documentation

◆ m_optinfo

optinfo opt_problem::m_optinfo
private

◆ s_the_problem

opt_problem * opt_problem::s_the_problem
staticprivate
The singleton opt_problem *.   

Referenced by emit_and_clear(), get_singleton(), and opt_problem().


The documentation for this class was generated from the following files: