GCC Middle and Back End API Reference
tree-stdarg.c File Reference

Functions

static bool reachable_at_most_once ()
static unsigned HOST_WIDE_INT va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, bool gpr_p)
static tree find_va_list_reference (tree *tp, int *walk_subtrees, void *data)
static void va_list_counter_op (struct stdarg_info *si, tree ap, tree var, bool gpr_p, bool write_p)
static bool va_list_counter_struct_op (struct stdarg_info *si, tree ap, tree var, bool write_p)
static bool va_list_ptr_read ()
static bool va_list_ptr_write ()
static void check_va_list_escapes ()
static bool check_all_va_list_escapes ()
static bool gate_optimize_stdarg ()
static unsigned int execute_optimize_stdarg ()
gimple_opt_passmake_pass_stdarg ()

Function Documentation

static bool check_all_va_list_escapes ( )
static
   Check all uses of temporaries from si->va_list_escape_vars bitmap.
   Return true if va_list might be escaping.  
                     x = *ap_temp;  
                     va_arg sequences may contain
                     other_ap_temp = ap_temp;
                     other_ap_temp = ap_temp + constant;
                     other_ap_temp = (some_type *) ap_temp;
                     ap = ap_temp;
                     statements.  
static void check_va_list_escapes ( )
static
   If RHS is X, (some type *) X or X + CST for X a temporary variable
   containing value of some va_list variable plus optionally some constant,
   either set si->va_list_escapes or add LHS to si->va_list_escape_vars,
   depending whether LHS is a function local temporary.  
     For void * or char * va_list types, there is just one counter.
     If va_arg is used in a loop, we don't know how many registers need
     saving.  

References bitmap_bit_p(), and stdarg_info::va_list_escape_vars.

static unsigned int execute_optimize_stdarg ( )
static
   Entry point to the stdarg optimization pass.  
                 If old style builtins are used, don't optimize anything.  
             VA_START_BB and VA_START_AP will be only used if there is just
             one va_start in the function.  
     If there were no va_start uses in the function, there is no need to
     save anything.  
     If some va_list arguments weren't local, we can't optimize.  
     For void * or char * va_list, something useful can be done only
     if there is just one va_start.  
     For struct * va_list, if the backend didn't tell us what the counter fields
     are, there is nothing more we can do.  
     For void * or char * va_list there is just one counter
     (va_list itself).  Use VA_LIST_GPR_SIZE for it.  
         For va_list_simple_ptr, we have to check PHI nodes too.  We treat
         them as assignments for the purpose of escape analysis.  This is
         not needed for non-simple va_list because virtual phis don't perform
         any real data movement.  
             Don't look at __builtin_va_{start,end}, they are ok.  
                         Check for ap ={v} {}.  
                         Check for tem = ap.  
                         Check for the last insn in:
                         tem1 = ap;
                         tem2 = tem1 + CST;
                         ap = tem2;
                         sequence.  
                         Check for ap ={v} {}.  
                         Check for ap[0].field = temp.  
                         Check for temp = ap[0].field.  
                     Do any architecture specific checking.  
             All other uses of va_list are either va_copy (that is not handled
             in this optimization), taking address of va_list variable or
             passing va_list to other functions (in that case va_list might
             escape the function and therefore va_start needs to set it up
             fully), or some unexpected use of va_list.  None of these should
             happen in a gimplified VA_ARG_EXPR.  
static tree find_va_list_reference ( tree tp,
int *  walk_subtrees,
void *  data 
)
static
   Called by walk_tree to look for references to va_list variables.  

References bitmap_bit_p().

static bool gate_optimize_stdarg ( )
static
   Return true if this optimization pass should be done.
   It makes only sense for stdarg functions.  
     This optimization is only for stdarg functions.  

References targetm.

gimple_opt_pass* make_pass_stdarg ( )
static bool reachable_at_most_once ( )
static
@verbatim 

Pass computing data for optimizing stdarg functions. Copyright (C) 2004-2013 Free Software Foundation, Inc. Contributed by Jakub Jelinek jakub.nosp@m.@red.nosp@m.hat.c.nosp@m.om

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/.

   A simple pass that attempts to optimize stdarg functions on architectures
   that need to save register arguments to stack on entry to stdarg functions.
   If the function doesn't use any va_start macros, no registers need to
   be saved.  If va_start macros are used, the va_list variables don't escape
   the function, it is only necessary to save registers that will be used
   in va_arg macros.  E.g. if va_arg is only used with integral types
   in the function, floating point registers don't need to be saved, etc.  
   Return true if basic block VA_ARG_BB is dominated by VA_START_BB and
   is executed at most as many times as VA_START_BB.  
         va_arg_bb can be executed more times than va_start_bb.  

Referenced by va_list_ptr_read().

static unsigned HOST_WIDE_INT va_list_counter_bump ( struct stdarg_info si,
tree  counter,
tree  rhs,
bool  gpr_p 
)
static
   For statement COUNTER = RHS, if RHS is COUNTER + constant,
   return constant, otherwise return HOST_WIDE_INT_M1U.
   GPR_P is true if this is GPR counter.  
static void va_list_counter_op ( struct stdarg_info si,
tree  ap,
tree  var,
bool  gpr_p,
bool  write_p 
)
static
   Helper function of va_list_counter_struct_op.  Compute
   cfun->va_list_{g,f}pr_size.  AP is a va_list GPR/FPR counter,
   if WRITE_P is true, seen in AP = VAR, otherwise seen in VAR = AP
   statement.  GPR_P is true if AP is a GPR counter, false if it is
   a FPR counter.  
static bool va_list_counter_struct_op ( struct stdarg_info si,
tree  ap,
tree  var,
bool  write_p 
)
static
   If AP is a va_list GPR/FPR counter, compute cfun->va_list_{g,f}pr_size.
   If WRITE_P is true, AP has been seen in AP = VAR assignment, if WRITE_P
   is false, AP has been seen in VAR = AP assignment.
   Return true if the AP = VAR (resp. VAR = AP) statement is a recognized
   va_arg operation that doesn't cause the va_list variable to escape
   current function.  
static bool va_list_ptr_read ( )
static
   Check for TEM = AP.  Return true if found and the caller shouldn't
   search for va_list references in the statement.  
     For void * or char * va_list types, there is just one counter.
     If va_arg is used in a loop, we don't know how many registers need
     saving.  
     Note the temporary, as we need to track whether it doesn't escape
     the current function.  

References stdarg_info::bb, stdarg_info::compute_sizes, dump_file, dump_flags, basic_block_def::index, reachable_at_most_once(), stdarg_info::va_start_bb, and stdarg_info::va_start_count.

static bool va_list_ptr_write ( )
static
   Check for:
     tem1 = AP;
     TEM2 = tem1 + CST;
     AP = TEM2;
   sequence and update cfun->va_list_gpr_size.  Return true if found.