diff options
Diffstat (limited to 'gcc/tree-promote-statics.c')
-rw-r--r-- | gcc/tree-promote-statics.c | 597 |
1 files changed, 0 insertions, 597 deletions
diff --git a/gcc/tree-promote-statics.c b/gcc/tree-promote-statics.c deleted file mode 100644 index a4ac8b7..0000000 --- a/gcc/tree-promote-statics.c +++ /dev/null @@ -1,597 +0,0 @@ -/* Promotion of static variables to ssa registers - Copyright (C) 2004-2005 Free Software Foundation, Inc. - Contributed by Kenneth Zadeck <zadeck@naturalbridge.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 2, 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 COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "tree.h" -#include "basic-block.h" -#include "tree-flow.h" -#include "ipa-utils.h" -#include "ipa-reference.h" -#include "bitmap.h" -#include "tree-pass.h" -#include "flags.h" -#include "timevar.h" -#include "langhooks.h" - -/* -The main idea is to promote some static variables from memory to SSA -registers. This transformation is only applied to those static -variables for which the effects of subroutine calls can be understood. -Such infomation is provided by functions in cgraphunit.c. - -The following table shows the actions that are taken to promote -variables. The analysis in cgraphunit constructs information about -both local usage and the effect of any particular call. Variables are -broken into 4 categories: only-read, only-write, read-write, and no -information. (No information variables are never promoted.) - -All information is of the "may" variety: if a function is marked read, -it means the call may read the variable, but it also may not read the -variable. - -There are two possible ways to perform the promotion: assume that the -static is live everywhere or compute the minimal live range for the -static variable. - -The minimal live range path has a lot of problems: - -1) live variables and upwards exposed uses must be first comuputed. -2) new machiney must be invented to prevent code motion algorithms -from floating a use of the surrogate register across a register -function call that clobbers the variable, but was not in any minimal -live range at the time of this analysis. - -While the first problem is simply a lot of code, the second problem -requires a new mechanism for pinning code and teaching all passes that -can move code to obey this new fenceposts. - -The maximum live range path has the problem that this technique can -create many false live ranges where the register is loaded after on -call only to be stored back right before the next call. This will eat -a certain amount of space and requires special smarts to get rid of them. - -There are really 7 situations to cover in the following table. - -action read write read-write - - -+--------------------------------------------------------------- - -entry | load load load - | -load | getfromreg xxxxx getfromreg - | -store | xxxx puttoreg puttoreg - | -call-read | noaction store before store before - | -call-write | load after store before store before - | load after load after -call-readwrite| load after store before store before - | load after load after - | -return | no action store store - - -l-r l-w c-r c-w store-b load-a - -0 0 0 0 | 0 0 -0 0 0 1 | 0 0 -0 0 1 0 | 0 0 -0 0 1 1 | 0 0 -0 1 0 0 | 0 0 -0 1 0 1 | 1 1 -0 1 1 0 | 1 0 -0 1 1 1 | 1 1 -1 0 0 0 | 0 0 -1 0 0 1 | 0 1 -1 0 1 0 | 0 0 -1 0 1 1 | 0 1 -1 1 0 0 | 0 0 -1 1 0 1 | 1 1 -1 1 1 0 | 1 0 -1 1 1 1 | 1 1 - -store_before = local_written & (callee_read | callee_written) -load_after = (local_read | local_written) & callee_written -*/ - -static bitmap_obstack promote_obstack; - -/* All of the static variables under consideration by this pass that - do reads or writes withing this function. */ -static bitmap local_read; -static bitmap local_written; -static bitmap local_all; - -/* Return true if the asm STMT clobbers memory. */ - -static bool -asm_clobbers_mem (tree stmt) -{ - tree link; - for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link)) - if (simple_cst_equal(TREE_VALUE (link), memory_identifier_string) == 1) - return true; - - return false; -} - -/* Return a INPUT_BITMAP for the asm inputs and OUTPUT_BITMAP for the - asm outputs of variables written by the asm STMT. */ - -static void -get_asm_read_and_write (bitmap input_bitmap, bitmap output_bitmap, tree stmt) -{ - int noutputs = list_length (ASM_OUTPUTS (stmt)); - const char **oconstraints - = (const char **) alloca ((noutputs) * sizeof (const char *)); - int i; - tree link; - const char *constraint; - bool allows_mem, allows_reg, is_inout; - - for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link)) - { - oconstraints[i] = constraint - = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link))); - parse_output_constraint (&constraint, i, 0, 0, - &allows_mem, &allows_reg, &is_inout); - - /* The variable is only added to the bitmap if there is an aux - field, ie.this is a variable we care about. */ - if (!allows_reg && allows_mem) - { - tree var = TREE_VALUE (link); - var = get_base_address (var); - if (TREE_CODE (var) == VAR_DECL) - { - var_ann_t va = var_ann (var); - if (va && va->common.aux) - bitmap_set_bit(output_bitmap, DECL_UID (var)); - } - } - } - - for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link)) - { - constraint - = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link))); - parse_input_constraint (&constraint, 0, 0, noutputs, 0, - oconstraints, &allows_mem, &allows_reg); - - /* The variable is only added to the bitmap if there is an aux - field, ie.this is a variable we care about. */ - if (!allows_reg && allows_mem) - { - tree var = TREE_VALUE (link); - var = get_base_address (var); - if (TREE_CODE (var) == VAR_DECL) - { - var_ann_t va = var_ann (var); - if (va && va->common.aux) - bitmap_set_bit(input_bitmap, DECL_UID (var)); - } - } - } -} - -/* Generate a series of loads from the static variables pointed to by - B1 && B2 or just B1 (if B2 is NULL) and insert them after - BSI). */ - -static void -gen_loads (bitmap b1, bitmap b2, block_stmt_iterator *bsi) -{ - bitmap result; - bitmap_iterator bi; - unsigned int index; - tree list = NULL; - - if (b2) - { - result = BITMAP_ALLOC (&promote_obstack); - bitmap_and (result, b1, b2); - } - else - result = b1; - - EXECUTE_IF_SET_IN_BITMAP(result, 0, index, bi) - { - tree src = referenced_var (index); - tree dest = (tree) (var_ann (src)->common.aux); - tree stmt = build (MODIFY_EXPR, TREE_TYPE (src), dest, src); - append_to_statement_list (stmt, &list); - } - - if (list) - sra_insert_after (bsi, list); - - if (b2) - BITMAP_FREE (result); -} - -/* Generate a series of stores to the static variables pointed to by - B1 && B2 or just B1 (if B2 is NULL) and insert them before - BSI). */ - -static void -gen_stores (bitmap b1, bitmap b2, block_stmt_iterator *bsi) -{ - bitmap result; - bitmap_iterator bi; - unsigned int index; - tree list = NULL; - - if (b2) - { - result = BITMAP_ALLOC (&promote_obstack); - bitmap_and (result, b1, b2); - } - else - result = b1; - - EXECUTE_IF_SET_IN_BITMAP(result, 0, index, bi) - { - tree dest = referenced_var (index); - tree src = (tree) (var_ann (dest)->common.aux); - tree stmt = build (MODIFY_EXPR, TREE_TYPE (src), dest, src); - append_to_statement_list (stmt, &list); - } - - if (list) - sra_insert_before (bsi, list); - - if (b2) - BITMAP_FREE (result); -} - -/* Replace the static references if it exists in the TPTR. */ - -static void -try_replace_operand(tree * tptr) -{ - tree t = *tptr; - if (TREE_CODE (t) == VAR_DECL) - { - var_ann_t va = var_ann (t); - tree replacement = (tree) (va->common.aux); - if (replacement) - *tptr = replacement; - } -} - -/* Walk an expression TPTR replacing all of the static references. */ - -static void -try_replace (tree *tptr) -{ - tree t = *tptr; - if ((TREE_CODE (t) == EXC_PTR_EXPR) || (TREE_CODE (t) == FILTER_EXPR)) - return; - - /* The INTEGER_CST is because some people use cute things like &0->a - for offsetof. */ - while (t && !SSA_VAR_P (t) - && (!CONSTANT_CLASS_P (t)) - && TREE_CODE (t) != LABEL_DECL - && TREE_CODE (t) != CONST_DECL - && TREE_CODE (t) != FUNCTION_DECL - && TREE_CODE (t) != EXC_PTR_EXPR) - { - if (TREE_CODE (t) == ARRAY_REF) - try_replace_operand (&TREE_OPERAND (t, 1)); - - tptr = &TREE_OPERAND (t, 0); - t = *tptr; - } - if (t) - try_replace_operand (tptr); -} - -/* Repalce the static references that exist in a constructor. */ - -static void -try_replace_constructor (tree ctor) -{ - tree t; - for (t = TREE_OPERAND (ctor, 0); t; t = TREE_CHAIN (t)) - { - try_replace (&TREE_VALUE (t)); - } -} - -/* Replace all the static references in the operand list of - CALL_EXPR. */ - -static void -try_replace_call_operands (tree call_expr) -{ - tree operandList = TREE_OPERAND (call_expr, 1); - tree operand; - - for (operand = operandList; - operand != NULL_TREE; - operand = TREE_CHAIN (operand)) - - if (TREE_CODE(TREE_VALUE (operand)) != FUNCTION_DECL) - try_replace (&TREE_VALUE (operand)); -} - -/* Generate loads and stores and replace all the static references in - function FN using statement iterator SI. This form is used when - there is not info available about the caller. */ - -static void -gen_dumb_call (tree fn, block_stmt_iterator si) -{ - gen_stores (local_written, NULL, &si); - try_replace (&TREE_OPERAND (fn, 0)); - try_replace_call_operands (fn); - gen_loads (local_all, NULL, &si); -} - - -/* Generate loads and stores and replace all the static references in - function FN using statement iterator SI. */ - -static void -try_replace_call (tree fn, block_stmt_iterator si) -{ - /* Store intersection of call_read and local_written - registers back to memory before calling. */ - /* int call_flags = call_expr_flags (fn); */ - tree callee = get_callee_fndecl (fn); - if (callee) - { - bitmap callee_all = BITMAP_ALLOC (&promote_obstack); - bitmap callee_written = ipa_reference_get_written_global (callee); - if (callee_written) - { - bitmap_ior (callee_all, - ipa_reference_get_read_global (callee), - callee_written); - - gen_stores (local_written, callee_all, &si); - - if (TREE_CODE (callee) != FUNCTION_DECL) - try_replace (&TREE_OPERAND (fn, 0)); - try_replace_call_operands (fn); - - /* This is a hack required because the call_flags are set on a - function by function basis during compilation. Thus these - flags are only set if the callee has already been compiled. */ - /* if (!(call_flags & (ECF_PURE | ECF_CONST | ECF_NORETURN))) */ - gen_loads (local_all, callee_written, &si); - BITMAP_FREE (callee_all); - } - else - gen_dumb_call (fn, si); - } - else - gen_dumb_call (fn, si); -} - - -/* Walk the entire function looking uses or stores to global variables - and changing them to use ssa shadow registers. */ - -static void -walk_function (void) -{ - basic_block bb; - block_stmt_iterator si, ni; - - FOR_EACH_BB (bb) - for (si = bsi_start (bb); !bsi_end_p (si); si = ni) - { - tree stmt = bsi_stmt (si); - - ni = si; - bsi_next (&ni); - - switch (TREE_CODE (stmt)) - { - case RETURN_EXPR: - /* Store all of the local_written registers back to memory - before returning. */ - gen_stores (local_written, NULL, &si); - break; - - case MODIFY_EXPR: - /* Change load of static to use of reg. Change store of - static to store of reg. */ - { - tree rhs = TREE_OPERAND (stmt, 1); - tree *rhsp = &TREE_OPERAND (stmt, 1); - tree *lhsp = &TREE_OPERAND (stmt, 0); - - /* If we have a call on the rhs, try to replace the arguments. - Otherwise, try to replace the operand on the LHS and the operand on - the RHS. */ - if (TREE_CODE (rhs) == CALL_EXPR) - try_replace_call (rhs, si); - else if (TREE_CODE (rhs) == CONSTRUCTOR) - try_replace_constructor (rhs); - else - try_replace (rhsp); - try_replace (lhsp); - } - break; - case CALL_EXPR: - try_replace_call (stmt, si); - - break; - case ASM_EXPR: - /* If the asm clobbers memory, just store everything and - load it back. */ - if (asm_clobbers_mem (stmt)) - { - gen_stores (local_written, NULL, &si); - gen_loads (local_all, NULL, &si); - } - else - { - bitmap store_bitmap = BITMAP_ALLOC (&promote_obstack); - bitmap load_bitmap = BITMAP_ALLOC (&promote_obstack); - bitmap all_bitmap = BITMAP_ALLOC (&promote_obstack); - /* The asm read generates a stores before, and the asm - write generates loads after. */ - get_asm_read_and_write (store_bitmap, load_bitmap, stmt); - bitmap_ior (all_bitmap, store_bitmap, load_bitmap); - - gen_stores (local_written, all_bitmap , &si); - gen_loads (local_all, load_bitmap, &si); - - BITMAP_FREE (store_bitmap); - BITMAP_FREE (load_bitmap); - BITMAP_FREE (all_bitmap); - } - break; - - default: - break; - } - } -} - -/* Main entry point for the promotion of statics to ssa regsisters. */ - -static void -execute_promote_statics (void) -{ - unsigned int index; - bitmap_iterator bi; - bitmap tb = ipa_reference_get_read_local (current_function_decl); - - - /* There are some options that cause this pass to run even if file - at a time is not set. */ - if (!tb) - return; - - bitmap_obstack_initialize (&promote_obstack); - sra_init_cache (); - - local_read = BITMAP_ALLOC (&promote_obstack); - bitmap_copy (local_read, tb); - tb = ipa_reference_get_written_local (current_function_decl); - local_written = BITMAP_ALLOC (&promote_obstack); - bitmap_copy (local_written, tb); - - local_all = BITMAP_ALLOC (&promote_obstack); - tb = BITMAP_ALLOC (&promote_obstack); - bitmap_ior (local_all, local_read, local_written); - - if (dump_file) - fprintf (dump_file, "promoting in %s\n", - lang_hooks.decl_printable_name (current_function_decl, 2)); - - EXECUTE_IF_SET_IN_BITMAP (local_all, 0, index, bi) - { - tree svar = referenced_var_lookup_if_exists (index); - if (svar) - { - tree type = TREE_TYPE (svar); - /* We only promote variables that are either scalars or if - they are aggregrates, they must be a type that sra is - willing to scalarize. Otherwise there is no reason to - promote it a register. - - We also do not promote anything that is marked READONLY - since there is little gain. The optimizations should - generally be able to look thru the operations and find the - constants. */ - if ((!TREE_READONLY(svar)) - && (TREE_CODE (type) != ARRAY_TYPE) - && ((!AGGREGATE_TYPE_P (type)) - || (sra_type_can_be_decomposed_p (type)))) - { - tree tmp = create_tmp_var (type, get_name (svar)); - add_referenced_tmp_var (tmp); - var_ann (svar)->common.aux = tmp; - - /* Insert loads from all read statics in the entry - block. */ - insert_edge_copies (build (MODIFY_EXPR, TREE_TYPE (svar), - tmp, svar), - ENTRY_BLOCK_PTR); - if (dump_file) - fprintf (dump_file, " var=%s, read=%d,write=%d\n", - get_name (svar), - bitmap_bit_p (local_read, index), - bitmap_bit_p (local_written, index)); - } - else - /* There is nothing to be done with this variable. */ - bitmap_set_bit (tb, index); - } - else - /* There is nothing to be done with this variable because the - reference was optimized out before we got here. */ - bitmap_set_bit (tb, index); - } - - /* Clear the to be ignored variables from the local maps. */ - bitmap_and_compl_into (local_read, tb); - bitmap_and_compl_into (local_written, tb); - bitmap_and_compl_into (local_all, tb); - - walk_function (); - bsi_commit_edge_inserts (); - - EXECUTE_IF_SET_IN_BITMAP (local_all, 0, index, bi) - { - tree svar = referenced_var (index); - var_ann (svar)->common.aux = NULL; - } - - bitmap_obstack_release (&promote_obstack); -} - -static bool -gate_promote_statics (void) -{ - return flag_unit_at_a_time != 0 - && flag_ipa_reference - && flag_tree_promote_statics; -} - -struct tree_opt_pass pass_promote_statics = -{ - "promote-statics", /* name */ - gate_promote_statics, /* gate */ - execute_promote_statics, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_TREE_PROMOTE_STATICS, /* tv_id */ - PROP_cfg, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_dump_func, /* todo_flags_finish */ - 0 /* letter */ -}; - - |