GCC Middle and Back End API Reference
inp_domain Struct Reference

Data Fields

int lb
 
int ub
 
bool has_lb
 
bool has_ub
 
bool is_lb_inclusive
 
bool is_ub_inclusive
 

Detailed Description

Conditional Dead Call Elimination pass for the GNU compiler.
   Copyright (C) 2008-2024 Free Software Foundation, Inc.
   Contributed by Xinliang David Li <davidxl@google.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 pass serves two closely-related purposes:

1. It conditionally executes calls that set errno if (a) the result of
   the call is unused and (b) a simple range check on the arguments can
   detect most cases where errno does not need to be set.

   This is the "conditional dead-code elimination" that gave the pass
   its original name, since the call is dead for most argument values.
   The calls for which it helps are usually part of the C++ abstraction
   penalty exposed after inlining.

2. It looks for calls to built-in functions that set errno and whose
   result is used.  It checks whether there is an associated internal
   function that doesn't set errno and whether the target supports
   that internal function.  If so, the pass uses the internal function
   to compute the result of the built-in function but still arranges
   for errno to be set when necessary.  There are two ways of setting
   errno:

   a. by protecting the original call with the same argument checks as (1)

   b. by protecting the original call with a check that the result
      of the internal function is not equal to itself (i.e. is NaN).

   (b) requires that NaNs are the only erroneous results.  It is not
   appropriate for functions like log, which returns ERANGE for zero
   arguments.  (b) is also likely to perform worse than (a) because it
   requires the result to be calculated first.  The pass therefore uses
   (a) when it can and uses (b) as a fallback.

   For (b) the pass can replace the original call with a call to
   IFN_SET_EDOM, if the target supports direct assignments to errno.

In both cases, arguments that require errno to be set should occur
rarely in practice.  Checks of the errno result should also be rare,
but the compiler would need powerful interprocedural analysis to
prove that errno is not checked.  It's much easier to add argument
checks or result checks instead.

  An example of (1) is:

      log (x);   // Mostly dead call
  ==>
      if (__builtin_islessequal (x, 0))
          log (x);

  With this change, call to log (x) is effectively eliminated, as
  in the majority of the cases, log won't be called with x out of
  range.  The branch is totally predictable, so the branch cost
  is low.

  An example of (2) is:

     y = sqrt (x);
  ==>
     if (__builtin_isless (x, 0))
       y =  sqrt (x);
     else
       y = IFN_SQRT (x);
  In the vast majority of cases we should then never need to call sqrt.

Note that library functions are not supposed to clear errno to zero without
error.  See IEEE Std 1003.1, section 2.3 Error Numbers, and section 7.5:3 of
ISO/IEC 9899 (C99).

The condition wrapping the builtin call is conservatively set to avoid too
aggressive (wrong) shrink wrapping.   
A structure for representing input domain of
a function argument in integer.  If the lower
bound is -inf, has_lb is set to false.  If the
upper bound is +inf, has_ub is false.
is_lb_inclusive and is_ub_inclusive are flags
to indicate if lb and ub value are inclusive
respectively.   

Field Documentation

◆ has_lb

bool inp_domain::has_lb

◆ has_ub

bool inp_domain::has_ub

◆ is_lb_inclusive

bool inp_domain::is_lb_inclusive

◆ is_ub_inclusive

bool inp_domain::is_ub_inclusive

◆ lb

int inp_domain::lb

◆ ub

int inp_domain::ub

The documentation for this struct was generated from the following file: