diff options
-rw-r--r-- | gcc/dumpfile.c | 2 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 1 | ||||
-rw-r--r-- | gcc/gimple-low.c | 126 | ||||
-rw-r--r-- | gcc/gimple-low.h | 29 | ||||
-rw-r--r-- | gcc/sese.c | 1 | ||||
-rw-r--r-- | gcc/tree-cfgcleanup.h | 28 | ||||
-rw-r--r-- | gcc/tree-chrec.c | 1 | ||||
-rw-r--r-- | gcc/tree-data-ref.c | 1 | ||||
-rw-r--r-- | gcc/tree-dfa.h | 184 | ||||
-rw-r--r-- | gcc/tree-flow-inline.h | 191 | ||||
-rw-r--r-- | gcc/tree-flow.h | 64 | ||||
-rw-r--r-- | gcc/tree-into-ssa.c | 22 | ||||
-rw-r--r-- | gcc/tree-into-ssa.h | 50 | ||||
-rw-r--r-- | gcc/tree-pretty-print.h | 20 | ||||
-rw-r--r-- | gcc/tree-scalar-evolution.c | 1 | ||||
-rw-r--r-- | gcc/tree.c | 122 | ||||
-rw-r--r-- | gcc/tree.h | 6 |
17 files changed, 438 insertions, 411 deletions
diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c index 435d22dc8eb..4a19b6d4648 100644 --- a/gcc/dumpfile.c +++ b/gcc/dumpfile.c @@ -22,8 +22,8 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "diagnostic-core.h" #include "dumpfile.h" -#include "gimple-pretty-print.h" #include "tree.h" +#include "gimple-pretty-print.h" /* If non-NULL, return one past-the-end of the matching SUBPART of the WHOLE string. */ diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 8d865d38d0e..723317b8e6a 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -92,6 +92,7 @@ along with GCC; see the file COPYING3. If not see #include "lra.h" #include "dumpfile.h" #include "opts.h" +#include "tree-dfa.h" static void dwarf2out_source_line (unsigned int, const char *, int, bool); static rtx last_var_location_insn; diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index cf6bac2b35e..8e083aeb4d7 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -598,56 +598,9 @@ lower_try_catch (gimple_stmt_iterator *gsi, struct lower_data *data) gsi_next (gsi); } -/* Try to determine whether a TRY_CATCH expression can fall through. - This is a subroutine of block_may_fallthru. */ - -static bool -try_catch_may_fallthru (const_tree stmt) -{ - tree_stmt_iterator i; - - /* If the TRY block can fall through, the whole TRY_CATCH can - fall through. */ - if (block_may_fallthru (TREE_OPERAND (stmt, 0))) - return true; - - i = tsi_start (TREE_OPERAND (stmt, 1)); - switch (TREE_CODE (tsi_stmt (i))) - { - case CATCH_EXPR: - /* We expect to see a sequence of CATCH_EXPR trees, each with a - catch expression and a body. The whole TRY_CATCH may fall - through iff any of the catch bodies falls through. */ - for (; !tsi_end_p (i); tsi_next (&i)) - { - if (block_may_fallthru (CATCH_BODY (tsi_stmt (i)))) - return true; - } - return false; - - case EH_FILTER_EXPR: - /* The exception filter expression only matters if there is an - exception. If the exception does not match EH_FILTER_TYPES, - we will execute EH_FILTER_FAILURE, and we will fall through - if that falls through. If the exception does match - EH_FILTER_TYPES, the stack unwinder will continue up the - stack, so we will not fall through. We don't know whether we - will throw an exception which matches EH_FILTER_TYPES or not, - so we just ignore EH_FILTER_TYPES and assume that we might - throw an exception which doesn't match. */ - return block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i))); - default: - /* This case represents statements to be executed when an - exception occurs. Those statements are implicitly followed - by a RESX statement to resume execution after the exception. - So in this case the TRY_CATCH never falls through. */ - return false; - } -} - - -/* Same as above, but for a GIMPLE_TRY_CATCH. */ +/* Try to determine whether a TRY_CATCH expression can fall through. + This is a subroutine of gimple_stmt_may_fallthru. */ static bool gimple_try_catch_may_fallthru (gimple stmt) @@ -698,81 +651,6 @@ gimple_try_catch_may_fallthru (gimple stmt) } -/* Try to determine if we can fall out of the bottom of BLOCK. This guess - need not be 100% accurate; simply be conservative and return true if we - don't know. This is used only to avoid stupidly generating extra code. - If we're wrong, we'll just delete the extra code later. */ - -bool -block_may_fallthru (const_tree block) -{ - /* This CONST_CAST is okay because expr_last returns its argument - unmodified and we assign it to a const_tree. */ - const_tree stmt = expr_last (CONST_CAST_TREE (block)); - - switch (stmt ? TREE_CODE (stmt) : ERROR_MARK) - { - case GOTO_EXPR: - case RETURN_EXPR: - /* Easy cases. If the last statement of the block implies - control transfer, then we can't fall through. */ - return false; - - case SWITCH_EXPR: - /* If SWITCH_LABELS is set, this is lowered, and represents a - branch to a selected label and hence can not fall through. - Otherwise SWITCH_BODY is set, and the switch can fall - through. */ - return SWITCH_LABELS (stmt) == NULL_TREE; - - case COND_EXPR: - if (block_may_fallthru (COND_EXPR_THEN (stmt))) - return true; - return block_may_fallthru (COND_EXPR_ELSE (stmt)); - - case BIND_EXPR: - return block_may_fallthru (BIND_EXPR_BODY (stmt)); - - case TRY_CATCH_EXPR: - return try_catch_may_fallthru (stmt); - - case TRY_FINALLY_EXPR: - /* The finally clause is always executed after the try clause, - so if it does not fall through, then the try-finally will not - fall through. Otherwise, if the try clause does not fall - through, then when the finally clause falls through it will - resume execution wherever the try clause was going. So the - whole try-finally will only fall through if both the try - clause and the finally clause fall through. */ - return (block_may_fallthru (TREE_OPERAND (stmt, 0)) - && block_may_fallthru (TREE_OPERAND (stmt, 1))); - - case MODIFY_EXPR: - if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR) - stmt = TREE_OPERAND (stmt, 1); - else - return true; - /* FALLTHRU */ - - case CALL_EXPR: - /* Functions that do not return do not fall through. */ - return (call_expr_flags (stmt) & ECF_NORETURN) == 0; - - case CLEANUP_POINT_EXPR: - return block_may_fallthru (TREE_OPERAND (stmt, 0)); - - case TARGET_EXPR: - return block_may_fallthru (TREE_OPERAND (stmt, 1)); - - case ERROR_MARK: - return true; - - default: - return lang_hooks.block_may_fallthru (stmt); - } -} - - /* Try to determine if we can continue executing the statement immediately following STMT. This guess need not be 100% accurate; simply be conservative and return true if we don't know. This is diff --git a/gcc/gimple-low.h b/gcc/gimple-low.h new file mode 100644 index 00000000000..b66de2ef2c2 --- /dev/null +++ b/gcc/gimple-low.h @@ -0,0 +1,29 @@ +/* Header file for gimple lowering pass. + Copyright (C) 2013 Free Software Foundation, Inc. + +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/>. */ + +#ifndef GCC_GIMPLE_LOW_H +#define GCC_GIMPLE_LOW_H + +extern bool gimple_check_call_matching_types (gimple, tree, bool); +extern bool gimple_stmt_may_fallthru (gimple); +extern bool gimple_seq_may_fallthru (gimple_seq); +extern void record_vars_into (tree, tree); +extern void record_vars (tree); + +#endif /* GCC_GIMPLE_LOW_H */ diff --git a/gcc/sese.c b/gcc/sese.c index d5ffa25bbb9..c861b23d937 100644 --- a/gcc/sese.c +++ b/gcc/sese.c @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "hash-table.h" +#include "tree.h" #include "tree-pretty-print.h" #include "tree-ssa.h" #include "cfgloop.h" diff --git a/gcc/tree-cfgcleanup.h b/gcc/tree-cfgcleanup.h new file mode 100644 index 00000000000..6bd3c3940ec --- /dev/null +++ b/gcc/tree-cfgcleanup.h @@ -0,0 +1,28 @@ +/* Header file for CFG cleanup for trees. + Copyright (C) 2013 Free Software Foundation, Inc. + +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/>. */ + +#ifndef GCC_TREE_CFGCLEANUP_H +#define GCC_TREE_CFGCLEANUP_H + +/* In tree-cfgcleanup.c */ +extern bitmap cfgcleanup_altered_bbs; +extern bool cleanup_tree_cfg (void); +extern bool fixup_noreturn_call (gimple stmt); + +#endif /* GCC_TREE_CFGCLEANUP_H */ diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c index 16df51bbbef..64f2dcb13bf 100644 --- a/gcc/tree-chrec.c +++ b/gcc/tree-chrec.c @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" #include "tree-pretty-print.h" #include "cfgloop.h" #include "tree-ssa.h" diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 530f00d82d0..9133df4a2b7 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -76,6 +76,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" #include "gimple-pretty-print.h" #include "tree-ssa.h" #include "cfgloop.h" diff --git a/gcc/tree-dfa.h b/gcc/tree-dfa.h new file mode 100644 index 00000000000..7d0a47009f6 --- /dev/null +++ b/gcc/tree-dfa.h @@ -0,0 +1,184 @@ +/* Header file for tree data flow functions. + Copyright (C) 2013 Free Software Foundation, Inc. + +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/>. */ + +#ifndef GCC_TREE_DFA_H +#define GCC_TREE_DFA_H + +extern void renumber_gimple_stmt_uids (void); +extern void renumber_gimple_stmt_uids_in_blocks (basic_block *, int); +extern void dump_variable (FILE *, tree); +extern void debug_variable (tree); +extern void dump_dfa_stats (FILE *); +extern void debug_dfa_stats (void); +extern tree ssa_default_def (struct function *, tree); +extern void set_ssa_default_def (struct function *, tree, tree); +extern tree get_or_create_ssa_default_def (struct function *, tree); +extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *, + HOST_WIDE_INT *, HOST_WIDE_INT *); +extern tree get_addr_base_and_unit_offset (tree, HOST_WIDE_INT *); +extern bool stmt_references_abnormal_ssa_name (gimple); +extern void dump_enumerated_decls (FILE *, int); + +/* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that + denotes the starting address of the memory access EXP. + Returns NULL_TREE if the offset is not constant or any component + is not BITS_PER_UNIT-aligned. + VALUEIZE if non-NULL is used to valueize SSA names. It should return + its argument or a constant if the argument is known to be constant. */ +/* ??? This is a static inline here to avoid the overhead of the indirect calls + to VALUEIZE. But is this overhead really that significant? And should we + perhaps just rely on WHOPR to specialize the function? */ + +static inline tree +get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset, + tree (*valueize) (tree)) +{ + HOST_WIDE_INT byte_offset = 0; + + /* Compute cumulative byte-offset for nested component-refs and array-refs, + and find the ultimate containing object. */ + while (1) + { + switch (TREE_CODE (exp)) + { + case BIT_FIELD_REF: + { + HOST_WIDE_INT this_off = TREE_INT_CST_LOW (TREE_OPERAND (exp, 2)); + if (this_off % BITS_PER_UNIT) + return NULL_TREE; + byte_offset += this_off / BITS_PER_UNIT; + } + break; + + case COMPONENT_REF: + { + tree field = TREE_OPERAND (exp, 1); + tree this_offset = component_ref_field_offset (exp); + HOST_WIDE_INT hthis_offset; + + if (!this_offset + || TREE_CODE (this_offset) != INTEGER_CST + || (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)) + % BITS_PER_UNIT)) + return NULL_TREE; + + hthis_offset = TREE_INT_CST_LOW (this_offset); + hthis_offset += (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)) + / BITS_PER_UNIT); + byte_offset += hthis_offset; + } + break; + + case ARRAY_REF: + case ARRAY_RANGE_REF: + { + tree index = TREE_OPERAND (exp, 1); + tree low_bound, unit_size; + + if (valueize + && TREE_CODE (index) == SSA_NAME) + index = (*valueize) (index); + + /* If the resulting bit-offset is constant, track it. */ + if (TREE_CODE (index) == INTEGER_CST + && (low_bound = array_ref_low_bound (exp), + TREE_CODE (low_bound) == INTEGER_CST) + && (unit_size = array_ref_element_size (exp), + TREE_CODE (unit_size) == INTEGER_CST)) + { + HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index); + + hindex -= TREE_INT_CST_LOW (low_bound); + hindex *= TREE_INT_CST_LOW (unit_size); + byte_offset += hindex; + } + else + return NULL_TREE; + } + break; + + case REALPART_EXPR: + break; + + case IMAGPART_EXPR: + byte_offset += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (exp))); + break; + + case VIEW_CONVERT_EXPR: + break; + + case MEM_REF: + { + tree base = TREE_OPERAND (exp, 0); + if (valueize + && TREE_CODE (base) == SSA_NAME) + base = (*valueize) (base); + + /* Hand back the decl for MEM[&decl, off]. */ + if (TREE_CODE (base) == ADDR_EXPR) + { + if (!integer_zerop (TREE_OPERAND (exp, 1))) + { + double_int off = mem_ref_offset (exp); + gcc_assert (off.high == -1 || off.high == 0); + byte_offset += off.to_shwi (); + } + exp = TREE_OPERAND (base, 0); + } + goto done; + } + + case TARGET_MEM_REF: + { + tree base = TREE_OPERAND (exp, 0); + if (valueize + && TREE_CODE (base) == SSA_NAME) + base = (*valueize) (base); + + /* Hand back the decl for MEM[&decl, off]. */ + if (TREE_CODE (base) == ADDR_EXPR) + { + if (TMR_INDEX (exp) || TMR_INDEX2 (exp)) + return NULL_TREE; + if (!integer_zerop (TMR_OFFSET (exp))) + { + double_int off = mem_ref_offset (exp); + gcc_assert (off.high == -1 || off.high == 0); + byte_offset += off.to_shwi (); + } + exp = TREE_OPERAND (base, 0); + } + goto done; + } + + default: + goto done; + } + + exp = TREE_OPERAND (exp, 0); + } +done: + + *poffset = byte_offset; + return exp; +} + + + +#endif /* GCC_TREE_DFA_H */ diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h index b3a6d4b45c1..164df957315 100644 --- a/gcc/tree-flow-inline.h +++ b/gcc/tree-flow-inline.h @@ -42,52 +42,6 @@ gimple_vop (const struct function *fun) return fun->gimple_df->vop; } -/* Initialize the hashtable iterator HTI to point to hashtable TABLE */ - -static inline void * -first_htab_element (htab_iterator *hti, htab_t table) -{ - hti->htab = table; - hti->slot = table->entries; - hti->limit = hti->slot + htab_size (table); - do - { - PTR x = *(hti->slot); - if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY) - break; - } while (++(hti->slot) < hti->limit); - - if (hti->slot < hti->limit) - return *(hti->slot); - return NULL; -} - -/* Return current non-empty/deleted slot of the hashtable pointed to by HTI, - or NULL if we have reached the end. */ - -static inline bool -end_htab_p (const htab_iterator *hti) -{ - if (hti->slot >= hti->limit) - return true; - return false; -} - -/* Advance the hashtable iterator pointed to by HTI to the next element of the - hashtable. */ - -static inline void * -next_htab_element (htab_iterator *hti) -{ - while (++(hti->slot) < hti->limit) - { - PTR x = *(hti->slot); - if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY) - return x; - }; - return NULL; -} - /* Get the number of the next statement uid to be allocated. */ static inline unsigned int gimple_stmt_max_uid (struct function *fn) @@ -240,149 +194,4 @@ gimple_ssa_operands (const struct function *fun) return &fun->gimple_df->ssa_operands; } - -/* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that - denotes the starting address of the memory access EXP. - Returns NULL_TREE if the offset is not constant or any component - is not BITS_PER_UNIT-aligned. - VALUEIZE if non-NULL is used to valueize SSA names. It should return - its argument or a constant if the argument is known to be constant. */ -/* ??? This is a static inline here to avoid the overhead of the indirect calls - to VALUEIZE. But is this overhead really that significant? And should we - perhaps just rely on WHOPR to specialize the function? */ - -static inline tree -get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset, - tree (*valueize) (tree)) -{ - HOST_WIDE_INT byte_offset = 0; - - /* Compute cumulative byte-offset for nested component-refs and array-refs, - and find the ultimate containing object. */ - while (1) - { - switch (TREE_CODE (exp)) - { - case BIT_FIELD_REF: - { - HOST_WIDE_INT this_off = TREE_INT_CST_LOW (TREE_OPERAND (exp, 2)); - if (this_off % BITS_PER_UNIT) - return NULL_TREE; - byte_offset += this_off / BITS_PER_UNIT; - } - break; - - case COMPONENT_REF: - { - tree field = TREE_OPERAND (exp, 1); - tree this_offset = component_ref_field_offset (exp); - HOST_WIDE_INT hthis_offset; - - if (!this_offset - || TREE_CODE (this_offset) != INTEGER_CST - || (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)) - % BITS_PER_UNIT)) - return NULL_TREE; - - hthis_offset = TREE_INT_CST_LOW (this_offset); - hthis_offset += (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)) - / BITS_PER_UNIT); - byte_offset += hthis_offset; - } - break; - - case ARRAY_REF: - case ARRAY_RANGE_REF: - { - tree index = TREE_OPERAND (exp, 1); - tree low_bound, unit_size; - - if (valueize - && TREE_CODE (index) == SSA_NAME) - index = (*valueize) (index); - - /* If the resulting bit-offset is constant, track it. */ - if (TREE_CODE (index) == INTEGER_CST - && (low_bound = array_ref_low_bound (exp), - TREE_CODE (low_bound) == INTEGER_CST) - && (unit_size = array_ref_element_size (exp), - TREE_CODE (unit_size) == INTEGER_CST)) - { - HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index); - - hindex -= TREE_INT_CST_LOW (low_bound); - hindex *= TREE_INT_CST_LOW (unit_size); - byte_offset += hindex; - } - else - return NULL_TREE; - } - break; - - case REALPART_EXPR: - break; - - case IMAGPART_EXPR: - byte_offset += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (exp))); - break; - - case VIEW_CONVERT_EXPR: - break; - - case MEM_REF: - { - tree base = TREE_OPERAND (exp, 0); - if (valueize - && TREE_CODE (base) == SSA_NAME) - base = (*valueize) (base); - - /* Hand back the decl for MEM[&decl, off]. */ - if (TREE_CODE (base) == ADDR_EXPR) - { - if (!integer_zerop (TREE_OPERAND (exp, 1))) - { - double_int off = mem_ref_offset (exp); - gcc_assert (off.high == -1 || off.high == 0); - byte_offset += off.to_shwi (); - } - exp = TREE_OPERAND (base, 0); - } - goto done; - } - - case TARGET_MEM_REF: - { - tree base = TREE_OPERAND (exp, 0); - if (valueize - && TREE_CODE (base) == SSA_NAME) - base = (*valueize) (base); - - /* Hand back the decl for MEM[&decl, off]. */ - if (TREE_CODE (base) == ADDR_EXPR) - { - if (TMR_INDEX (exp) || TMR_INDEX2 (exp)) - return NULL_TREE; - if (!integer_zerop (TMR_OFFSET (exp))) - { - double_int off = mem_ref_offset (exp); - gcc_assert (off.high == -1 || off.high == 0); - byte_offset += off.to_shwi (); - } - exp = TREE_OPERAND (base, 0); - } - goto done; - } - - default: - goto done; - } - - exp = TREE_OPERAND (exp, 0); - } -done: - - *poffset = byte_offset; - return exp; -} - #endif /* _TREE_FLOW_INLINE_H */ diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 46082e29856..d3a4e33b921 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -30,7 +30,11 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "ipa-reference.h" #include "tree-ssa-alias.h" - +#include "tree-cfgcleanup.h" +#include "tree-dfa.h" +#include "tree-pretty-print.h" +#include "gimple-low.h" +#include "tree-into-ssa.h" /* This structure is used to map a gimple statement to a label, or list of labels to represent transaction restart. */ @@ -92,21 +96,6 @@ struct GTY(()) gimple_df { htab_t GTY ((param_is (struct tm_restart_node))) tm_restart; }; - -typedef struct -{ - htab_t htab; - PTR *slot; - PTR *limit; -} htab_iterator; - -/* Iterate through the elements of hashtable HTAB, using htab_iterator ITER, - storing each element in RESULT, which is of type TYPE. */ -#define FOR_EACH_HTAB_ELEMENT(HTAB, RESULT, TYPE, ITER) \ - for (RESULT = (TYPE) first_htab_element (&(ITER), (HTAB)); \ - !end_htab_p (&(ITER)); \ - RESULT = (TYPE) next_htab_element (&(ITER))) - static inline int get_lineno (const_gimple); /*--------------------------------------------------------------------------- @@ -255,48 +244,6 @@ extern basic_block move_sese_region_to_fn (struct function *, basic_block, void remove_edge_and_dominated_blocks (edge); bool tree_node_can_be_shared (tree); -/* In tree-cfgcleanup.c */ -extern bitmap cfgcleanup_altered_bbs; -extern bool cleanup_tree_cfg (void); - -/* In tree-pretty-print.c. */ -extern void dump_generic_bb (FILE *, basic_block, int, int); -extern int op_code_prio (enum tree_code); -extern int op_prio (const_tree); -extern const char *op_symbol_code (enum tree_code); - -/* In tree-dfa.c */ -extern void renumber_gimple_stmt_uids (void); -extern void renumber_gimple_stmt_uids_in_blocks (basic_block *, int); -extern void dump_dfa_stats (FILE *); -extern void debug_dfa_stats (void); -extern void dump_variable (FILE *, tree); -extern void debug_variable (tree); -extern void set_ssa_default_def (struct function *, tree, tree); -extern tree ssa_default_def (struct function *, tree); -extern tree get_or_create_ssa_default_def (struct function *, tree); -extern bool stmt_references_abnormal_ssa_name (gimple); -extern tree get_addr_base_and_unit_offset (tree, HOST_WIDE_INT *); -extern void dump_enumerated_decls (FILE *, int); - -/* In gimple-low.c */ -extern void record_vars_into (tree, tree); -extern void record_vars (tree); -extern bool gimple_seq_may_fallthru (gimple_seq); -extern bool gimple_stmt_may_fallthru (gimple); -extern bool gimple_check_call_matching_types (gimple, tree, bool); - -/* In tree-into-ssa.c */ -void update_ssa (unsigned); -void delete_update_ssa (void); -tree create_new_def_for (tree, gimple, def_operand_p); -bool need_ssa_update_p (struct function *); -bool name_registered_for_update_p (tree); -void release_ssa_name_after_update_ssa (tree); -void mark_virtual_operands_for_renaming (struct function *); -tree get_current_def (tree); -void set_current_def (tree, tree); - /* In tree-ssa-ccp.c */ tree fold_const_aggregate_ref (tree); tree gimple_fold_stmt_to_constant (gimple, tree (*)(tree)); @@ -539,7 +486,6 @@ void get_address_description (tree, struct mem_address *); tree maybe_fold_tmr (tree); unsigned int execute_fixup_cfg (void); -bool fixup_noreturn_call (gimple stmt); /* In ipa-pure-const.c */ void warn_function_noreturn (tree); diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c index c1da5e4fcbb..2f5ac69251e 100644 --- a/gcc/tree-into-ssa.c +++ b/gcc/tree-into-ssa.c @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see #include "domwalk.h" #include "params.h" #include "diagnostic-core.h" +#include "tree-into-ssa.h" /* This file builds the SSA form for a function as described in: @@ -253,27 +254,6 @@ enum rewrite_mode { REWRITE_UPDATE }; - - - -/* Prototypes for debugging functions. */ -extern void dump_tree_ssa (FILE *); -extern void debug_tree_ssa (void); -extern void debug_def_blocks (void); -extern void dump_tree_ssa_stats (FILE *); -extern void debug_tree_ssa_stats (void); -extern void dump_update_ssa (FILE *); -extern void debug_update_ssa (void); -extern void dump_names_replaced_by (FILE *, tree); -extern void debug_names_replaced_by (tree); -extern void dump_var_infos (FILE *); -extern void debug_var_infos (void); -extern void dump_defs_stack (FILE *, int); -extern void debug_defs_stack (int); -extern void dump_currdefs (FILE *); -extern void debug_currdefs (void); - - /* The set of symbols we ought to re-write into SSA form in update_ssa. */ static bitmap symbols_to_rename_set; static vec<tree> symbols_to_rename; diff --git a/gcc/tree-into-ssa.h b/gcc/tree-into-ssa.h new file mode 100644 index 00000000000..0c44f046697 --- /dev/null +++ b/gcc/tree-into-ssa.h @@ -0,0 +1,50 @@ +/* Header file for normal form into SSA. + Copyright (C) 2013 Free Software Foundation, Inc. + +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/>. */ + +#ifndef GCC_TREE_INTO_SSA_H +#define GCC_TREE_INTO_SSA_H + +extern tree get_current_def (tree); +extern void set_current_def (tree, tree); +void delete_update_ssa (void); +tree create_new_def_for (tree, gimple, def_operand_p); +void mark_virtual_operands_for_renaming (struct function *); +bool need_ssa_update_p (struct function *); +bool name_registered_for_update_p (tree); +void release_ssa_name_after_update_ssa (tree); +void update_ssa (unsigned); + +/* Prototypes for debugging functions. */ +extern void debug_decl_set (bitmap set); +extern void dump_defs_stack (FILE *, int); +extern void debug_defs_stack (int); +extern void dump_currdefs (FILE *); +extern void debug_currdefs (void); +extern void dump_tree_ssa (FILE *); +extern void debug_tree_ssa (void); +extern void dump_tree_ssa_stats (FILE *); +extern void debug_tree_ssa_stats (void); +extern void dump_var_infos (FILE *); +extern void debug_var_infos (void); +extern void dump_names_replaced_by (FILE *, tree); +extern void debug_names_replaced_by (tree); +extern void dump_update_ssa (FILE *); +extern void debug_update_ssa (void); + +#endif /* GCC_TREE_INTO_SSA_H */ diff --git a/gcc/tree-pretty-print.h b/gcc/tree-pretty-print.h index ec421fa938f..f70556db03d 100644 --- a/gcc/tree-pretty-print.h +++ b/gcc/tree-pretty-print.h @@ -31,24 +31,24 @@ along with GCC; see the file COPYING3. If not see #define pp_ti_abstract_origin(TI) ((tree *) (TI)->x_data) -extern void pp_tree_identifier (pretty_printer *, tree); -/* In tree-pretty-print.c */ -extern void print_declaration (pretty_printer *, tree, int, int); -extern int dump_generic_node (pretty_printer *, tree, int, int, bool); +extern void debug_generic_expr (tree); +extern void debug_generic_stmt (tree); +extern void debug_tree_chain (tree); +extern void print_generic_decl (FILE *, tree, int); extern void print_generic_stmt (FILE *, tree, int); extern void print_generic_stmt_indented (FILE *, tree, int, int); extern void print_generic_expr (FILE *, tree, int); -extern void print_generic_decl (FILE *, tree, int); extern void dump_omp_clauses (pretty_printer *, tree, int, int); +extern int dump_generic_node (pretty_printer *, tree, int, int, bool); +extern void print_declaration (pretty_printer *, tree, int, int); +extern int op_code_prio (enum tree_code); +extern int op_prio (const_tree); +extern const char *op_symbol_code (enum tree_code); extern void print_call_name (pretty_printer *, tree, int); -extern void debug_generic_expr (tree); -extern void debug_generic_stmt (tree); -extern void debug_tree_chain (tree); extern void percent_K_format (text_info *); +extern void pp_tree_identifier (pretty_printer *, tree); extern void dump_function_header (FILE *, tree, int); extern void pp_double_int (pretty_printer *pp, double_int d, bool uns); -/* In c-pretty-print.c */ -extern void debug_c_tree (tree); #endif /* ! GCC_TREE_PRETTY_PRINT_H */ diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index 06379024450..f85353c22bd 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -256,6 +256,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" #include "hash-table.h" #include "gimple-pretty-print.h" #include "tree-ssa.h" diff --git a/gcc/tree.c b/gcc/tree.c index ebee116f0c5..705332f878c 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -12125,4 +12125,126 @@ contains_bitfld_component_ref_p (const_tree ref) return false; } +/* Try to determine whether a TRY_CATCH expression can fall through. + This is a subroutine of block_may_fallthru. */ + +static bool +try_catch_may_fallthru (const_tree stmt) +{ + tree_stmt_iterator i; + + /* If the TRY block can fall through, the whole TRY_CATCH can + fall through. */ + if (block_may_fallthru (TREE_OPERAND (stmt, 0))) + return true; + + i = tsi_start (TREE_OPERAND (stmt, 1)); + switch (TREE_CODE (tsi_stmt (i))) + { + case CATCH_EXPR: + /* We expect to see a sequence of CATCH_EXPR trees, each with a + catch expression and a body. The whole TRY_CATCH may fall + through iff any of the catch bodies falls through. */ + for (; !tsi_end_p (i); tsi_next (&i)) + { + if (block_may_fallthru (CATCH_BODY (tsi_stmt (i)))) + return true; + } + return false; + + case EH_FILTER_EXPR: + /* The exception filter expression only matters if there is an + exception. If the exception does not match EH_FILTER_TYPES, + we will execute EH_FILTER_FAILURE, and we will fall through + if that falls through. If the exception does match + EH_FILTER_TYPES, the stack unwinder will continue up the + stack, so we will not fall through. We don't know whether we + will throw an exception which matches EH_FILTER_TYPES or not, + so we just ignore EH_FILTER_TYPES and assume that we might + throw an exception which doesn't match. */ + return block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i))); + + default: + /* This case represents statements to be executed when an + exception occurs. Those statements are implicitly followed + by a RESX statement to resume execution after the exception. + So in this case the TRY_CATCH never falls through. */ + return false; + } +} + +/* Try to determine if we can fall out of the bottom of BLOCK. This guess + need not be 100% accurate; simply be conservative and return true if we + don't know. This is used only to avoid stupidly generating extra code. + If we're wrong, we'll just delete the extra code later. */ + +bool +block_may_fallthru (const_tree block) +{ + /* This CONST_CAST is okay because expr_last returns its argument + unmodified and we assign it to a const_tree. */ + const_tree stmt = expr_last (CONST_CAST_TREE (block)); + + switch (stmt ? TREE_CODE (stmt) : ERROR_MARK) + { + case GOTO_EXPR: + case RETURN_EXPR: + /* Easy cases. If the last statement of the block implies + control transfer, then we can't fall through. */ + return false; + + case SWITCH_EXPR: + /* If SWITCH_LABELS is set, this is lowered, and represents a + branch to a selected label and hence can not fall through. + Otherwise SWITCH_BODY is set, and the switch can fall + through. */ + return SWITCH_LABELS (stmt) == NULL_TREE; + + case COND_EXPR: + if (block_may_fallthru (COND_EXPR_THEN (stmt))) + return true; + return block_may_fallthru (COND_EXPR_ELSE (stmt)); + + case BIND_EXPR: + return block_may_fallthru (BIND_EXPR_BODY (stmt)); + + case TRY_CATCH_EXPR: + return try_catch_may_fallthru (stmt); + + case TRY_FINALLY_EXPR: + /* The finally clause is always executed after the try clause, + so if it does not fall through, then the try-finally will not + fall through. Otherwise, if the try clause does not fall + through, then when the finally clause falls through it will + resume execution wherever the try clause was going. So the + whole try-finally will only fall through if both the try + clause and the finally clause fall through. */ + return (block_may_fallthru (TREE_OPERAND (stmt, 0)) + && block_may_fallthru (TREE_OPERAND (stmt, 1))); + + case MODIFY_EXPR: + if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR) + stmt = TREE_OPERAND (stmt, 1); + else + return true; + /* FALLTHRU */ + + case CALL_EXPR: + /* Functions that do not return do not fall through. */ + return (call_expr_flags (stmt) & ECF_NORETURN) == 0; + + case CLEANUP_POINT_EXPR: + return block_may_fallthru (TREE_OPERAND (stmt, 0)); + + case TARGET_EXPR: + return block_may_fallthru (TREE_OPERAND (stmt, 1)); + + case ERROR_MARK: + return true; + + default: + return lang_hooks.block_may_fallthru (stmt); + } +} + #include "gt-tree.h" diff --git a/gcc/tree.h b/gcc/tree.h index 4cd7e9e9f65..a71cd96414f 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4528,10 +4528,9 @@ extern tree get_binfo_at_offset (tree, HOST_WIDE_INT, tree); extern bool virtual_method_call_p (tree); extern tree obj_type_ref_class (tree ref); extern bool types_same_for_odr (tree type1, tree type2); -extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *, - HOST_WIDE_INT *, HOST_WIDE_INT *); extern bool contains_bitfld_component_ref_p (const_tree); extern bool type_in_anonymous_namespace_p (tree); +extern bool block_may_fallthru (const_tree); /* In tree-nested.c */ extern tree build_addr (tree, tree); @@ -4880,9 +4879,6 @@ is_lang_specific (tree t) return TREE_CODE (t) == LANG_TYPE || TREE_CODE (t) >= NUM_TREE_CODES; } -/* In gimple-low.c. */ -extern bool block_may_fallthru (const_tree); - /* In vtable-verify.c. */ extern void save_vtable_map_decl (tree); |