GCC Middle and Back End API Reference
tree-stdarg.c File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "function.h"
#include "langhooks.h"
#include "gimple-pretty-print.h"
#include "target.h"
#include "bitmap.h"
#include "gimple.h"
#include "gimple-ssa.h"
#include "tree-phinodes.h"
#include "ssa-iterators.h"
#include "tree-ssanames.h"
#include "sbitmap.h"
#include "tree-pass.h"
#include "tree-stdarg.h"
Include dependency graph for tree-stdarg.c:

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, SSA_NAME_VERSION, TREE_OPERAND, 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, and SSA_NAME_VERSION.

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

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.

References num_ssa_names.

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(), TDF_DETAILS, 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.