GCC Middle and Back End API 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"
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_pass * | make_pass_stdarg () |
|
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 |
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 |
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.
Called by walk_tree to look for references to va_list variables.
References bitmap_bit_p, and SSA_NAME_VERSION.
|
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 |
Pass computing data for optimizing stdarg functions. Copyright (C) 2004-2013 Free Software Foundation, Inc. Contributed by Jakub Jelinek jakub @red hat.c 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 |
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 |
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 |
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 |
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 |
Check for: tem1 = AP; TEM2 = tem1 + CST; AP = TEM2; sequence and update cfun->va_list_gpr_size. Return true if found.