X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-ssa-operands.c;h=ed0d34de2df14a8c2fd050836b96f40a1d8cb5be;hb=6956abd25f4834e2c451819a57af52874dd0aace;hp=f4df750809301a08d72a709202fad628772f1b95;hpb=17fbf1b862ec17f9e8df86643baffa2d864878ab;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index f4df7508093..ed0d34de2df 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -1,5 +1,5 @@ /* SSA operands management for trees. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -25,50 +25,51 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "flags.h" #include "function.h" -#include "diagnostic.h" +#include "tree-pretty-print.h" +#include "gimple-pretty-print.h" #include "tree-flow.h" #include "tree-inline.h" #include "tree-pass.h" #include "ggc.h" #include "timevar.h" -#include "toplev.h" #include "langhooks.h" -#include "ipa-reference.h" +#include "diagnostic-core.h" -/* This file contains the code required to manage the operands cache of the - SSA optimizer. For every stmt, we maintain an operand cache in the stmt - annotation. This cache contains operands that will be of interest to - optimizers and other passes wishing to manipulate the IL. - The operand type are broken up into REAL and VIRTUAL operands. The real - operands are represented as pointers into the stmt's operand tree. Thus +/* This file contains the code required to manage the operands cache of the + SSA optimizer. For every stmt, we maintain an operand cache in the stmt + annotation. This cache contains operands that will be of interest to + optimizers and other passes wishing to manipulate the IL. + + The operand type are broken up into REAL and VIRTUAL operands. The real + operands are represented as pointers into the stmt's operand tree. Thus any manipulation of the real operands will be reflected in the actual tree. - Virtual operands are represented solely in the cache, although the base - variable for the SSA_NAME may, or may not occur in the stmt's tree. + Virtual operands are represented solely in the cache, although the base + variable for the SSA_NAME may, or may not occur in the stmt's tree. Manipulation of the virtual operands will not be reflected in the stmt tree. - The routines in this file are concerned with creating this operand cache + The routines in this file are concerned with creating this operand cache from a stmt tree. - The operand tree is the parsed by the various get_* routines which look - through the stmt tree for the occurrence of operands which may be of - interest, and calls are made to the append_* routines whenever one is - found. There are 4 of these routines, each representing one of the + The operand tree is the parsed by the various get_* routines which look + through the stmt tree for the occurrence of operands which may be of + interest, and calls are made to the append_* routines whenever one is + found. There are 4 of these routines, each representing one of the 4 types of operands. Defs, Uses, Virtual Uses, and Virtual May Defs. - The append_* routines check for duplication, and simply keep a list of + The append_* routines check for duplication, and simply keep a list of unique objects for each operand type in the build_* extendable vectors. - Once the stmt tree is completely parsed, the finalize_ssa_operands() - routine is called, which proceeds to perform the finalization routine + Once the stmt tree is completely parsed, the finalize_ssa_operands() + routine is called, which proceeds to perform the finalization routine on each of the 4 operand vectors which have been built up. - If the stmt had a previous operand cache, the finalization routines - attempt to match up the new operands with the old ones. If it's a perfect - match, the old vector is simply reused. If it isn't a perfect match, then - a new vector is created and the new operands are placed there. For - virtual operands, if the previous cache had SSA_NAME version of a - variable, and that same variable occurs in the same operands cache, then + If the stmt had a previous operand cache, the finalization routines + attempt to match up the new operands with the old ones. If it's a perfect + match, the old vector is simply reused. If it isn't a perfect match, then + a new vector is created and the new operands are placed there. For + virtual operands, if the previous cache had SSA_NAME version of a + variable, and that same variable occurs in the same operands cache, then the new cache vector will also get the same SSA_NAME. i.e., if a stmt had a VUSE of 'a_5', and 'a' occurs in the new @@ -78,7 +79,7 @@ along with GCC; see the file COPYING3. If not see /* Structure storing statistics on how many call clobbers we have, and how many where avoided. */ -static struct +static struct { /* Number of call-clobbered ops we attempt to add to calls in add_call_clobbered_mem_symbols. */ @@ -90,7 +91,7 @@ static struct /* Number of reads (VUSEs) avoided by using not_read information. */ unsigned int static_read_clobbers_avoided; - + /* Number of write-clobbers avoided because the variable can't escape to this call. */ unsigned int unescapable_clobbers_avoided; @@ -109,7 +110,7 @@ static struct /* By default, operands are loaded. */ #define opf_use 0 -/* Operand is the target of an assignment expression or a +/* Operand is the target of an assignment expression or a call-clobbered variable. */ #define opf_def (1 << 0) @@ -126,6 +127,12 @@ static struct clobbering sites like function calls or ASM_EXPRs. */ #define opf_implicit (1 << 2) +/* Operand is in a place where address-taken does not imply addressable. */ +#define opf_non_addressable (1 << 3) + +/* Operand is in a place where opf_non_addressable does not apply. */ +#define opf_not_non_addressable (1 << 4) + /* Array for building all the def operands. */ static VEC(tree,heap) *build_defs; @@ -138,7 +145,7 @@ static tree build_vdef; /* The built VUSE operand. */ static tree build_vuse; -/* Bitmap obstack for our datastructures that needs to survive across +/* Bitmap obstack for our datastructures that needs to survive across compilations of multiple functions. */ static bitmap_obstack operands_bitmap_obstack; @@ -147,12 +154,6 @@ static void get_expr_operands (gimple, tree *, int); /* Number of functions with initialized ssa_operands. */ static int n_initialized = 0; -/* Stack of statements to change. Every call to - push_stmt_changes pushes the stmt onto the stack. Calls to - pop_stmt_changes pop a stmt off of the stack and compute the set - of changes for the popped statement. */ -static VEC(gimple_p,heap) *scb_stack; - /* Return the DECL_UID of the base variable of T. */ static inline unsigned @@ -180,7 +181,7 @@ ssa_operands_active (void) return cfun->gimple_df && gimple_ssa_operands (cfun)->ops_active; } - + /* Create the VOP variable, an artificial global variable to act as a representative of all of the virtual operands FUD chain. */ @@ -191,7 +192,8 @@ create_vop_var (void) gcc_assert (cfun->gimple_df->vop == NULL_TREE); - global_var = build_decl (VAR_DECL, get_identifier (".MEM"), + global_var = build_decl (BUILTINS_LOCATION, VAR_DECL, + get_identifier (".MEM"), void_type_node); DECL_ARTIFICIAL (global_var) = 1; TREE_READONLY (global_var) = 0; @@ -213,7 +215,7 @@ create_vop_var (void) In 1k we can fit 25 use operands (or 63 def operands) on a host with 8 byte pointers, that would be 10 statements each with 1 def and 2 uses. */ - + #define OP_SIZE_INIT 0 #define OP_SIZE_1 (1024 - sizeof (void *)) #define OP_SIZE_2 (1024 * 4 - sizeof (void *)) @@ -231,7 +233,6 @@ init_ssa_operands (void) build_vuse = NULL_TREE; build_vdef = NULL_TREE; bitmap_obstack_initialize (&operands_bitmap_obstack); - scb_stack = VEC_alloc (gimple_p, heap, 20); } gcc_assert (gimple_ssa_operands (cfun)->operand_memory == NULL); @@ -257,11 +258,6 @@ fini_ssa_operands (void) VEC_free (tree, heap, build_uses); build_vdef = NULL_TREE; build_vuse = NULL_TREE; - - /* The change buffer stack had better be empty. */ - gcc_assert (VEC_length (gimple_p, scb_stack) == 0); - VEC_free (gimple_p, heap, scb_stack); - scb_stack = NULL; } gimple_ssa_operands (cfun)->free_defs = NULL; @@ -300,7 +296,7 @@ fini_ssa_operands (void) /* Return memory for an operand of size SIZE. */ - + static inline void * ssa_operand_alloc (unsigned size) { @@ -330,9 +326,10 @@ ssa_operand_alloc (unsigned size) gcc_unreachable (); } - ptr = (struct ssa_operand_memory_d *) - ggc_alloc (sizeof (void *) - + gimple_ssa_operands (cfun)->ssa_operand_mem_size); + + ptr = ggc_alloc_ssa_operand_memory_d (sizeof (void *) + + gimple_ssa_operands (cfun)->ssa_operand_mem_size); + ptr->next = gimple_ssa_operands (cfun)->operand_memory; gimple_ssa_operands (cfun)->operand_memory = ptr; gimple_ssa_operands (cfun)->operand_memory_index = 0; @@ -385,7 +382,7 @@ alloc_use (void) /* Adds OP to the list of defs after LAST. */ -static inline def_optype_p +static inline def_optype_p add_def_op (tree *op, def_optype_p last) { def_optype_p new_def; @@ -540,8 +537,8 @@ finalize_ssa_uses (gimple stmt) /* Now create nodes for all the new nodes. */ for (new_i = 0; new_i < VEC_length (tree, build_uses); new_i++) - last = add_use_op (stmt, - (tree *) VEC_index (tree, build_uses, new_i), + last = add_use_op (stmt, + (tree *) VEC_index (tree, build_uses, new_i), last); /* Now set the stmt's operands. */ @@ -563,7 +560,7 @@ cleanup_build_arrays (void) /* Finalize all the build vectors, fill the new ones into INFO. */ - + static inline void finalize_ssa_stmt_operands (gimple stmt) { @@ -646,6 +643,8 @@ add_virtual_operand (gimple stmt ATTRIBUTE_UNUSED, int flags) if (flags & opf_no_vops) return; + gcc_assert (!is_gimple_debug (stmt)); + if (flags & opf_def) append_vdef (gimple_vop (cfun)); else @@ -662,16 +661,15 @@ static void add_stmt_operand (tree *var_p, gimple stmt, int flags) { tree var, sym; - var_ann_t v_ann; gcc_assert (SSA_VAR_P (*var_p)); var = *var_p; sym = (TREE_CODE (var) == SSA_NAME ? SSA_NAME_VAR (var) : var); - v_ann = var_ann (sym); /* Mark statements with volatile operands. */ - if (TREE_THIS_VOLATILE (sym)) + if (!(flags & opf_no_vops) + && TREE_THIS_VOLATILE (sym)) gimple_set_has_volatile_ops (stmt, true); if (is_gimple_reg (sym)) @@ -686,10 +684,13 @@ add_stmt_operand (tree *var_p, gimple stmt, int flags) add_virtual_operand (stmt, flags); } -/* Add the base address of REF to SET. */ +/* Mark the base address of REF as having its address taken. + REF may be a single variable whose address has been taken or any + other valid GIMPLE memory reference (structure reference, array, + etc). */ static void -add_to_addressable_set (tree ref, bitmap *set) +mark_address_taken (tree ref) { tree var; @@ -699,36 +700,23 @@ add_to_addressable_set (tree ref, bitmap *set) be referenced using pointer arithmetic. See PR 21407 and the ensuing mailing list discussion. */ var = get_base_address (ref); - if (var && SSA_VAR_P (var)) + if (var) { - if (*set == NULL) - *set = BITMAP_ALLOC (&operands_bitmap_obstack); - - bitmap_set_bit (*set, DECL_UID (var)); - TREE_ADDRESSABLE (var) = 1; + if (DECL_P (var)) + TREE_ADDRESSABLE (var) = 1; + else if (TREE_CODE (var) == MEM_REF + && TREE_CODE (TREE_OPERAND (var, 0)) == ADDR_EXPR + && DECL_P (TREE_OPERAND (TREE_OPERAND (var, 0), 0))) + TREE_ADDRESSABLE (TREE_OPERAND (TREE_OPERAND (var, 0), 0)) = 1; } } -/* Add the base address of REF to the set of addresses taken by STMT. - REF may be a single variable whose address has been taken or any - other valid GIMPLE memory reference (structure reference, array, - etc). If the base address of REF is a decl that has sub-variables, - also add all of its sub-variables. */ - -static void -gimple_add_to_addresses_taken (gimple stmt, tree ref) -{ - gcc_assert (gimple_has_ops (stmt)); - add_to_addressable_set (ref, gimple_addresses_taken_ptr (stmt)); -} - -/* A subroutine of get_expr_operands to handle INDIRECT_REF, - ALIGN_INDIRECT_REF and MISALIGNED_INDIRECT_REF. +/* A subroutine of get_expr_operands to handle MEM_REF. - STMT is the statement being processed, EXPR is the INDIRECT_REF + STMT is the statement being processed, EXPR is the MEM_REF that got us here. - + FLAGS is as in get_expr_operands. RECURSE_ON_BASE should be set to true if we want to continue @@ -741,7 +729,8 @@ get_indirect_ref_operands (gimple stmt, tree expr, int flags, { tree *pptr = &TREE_OPERAND (expr, 0); - if (TREE_THIS_VOLATILE (expr)) + if (!(flags & opf_no_vops) + && TREE_THIS_VOLATILE (expr)) gimple_set_has_volatile_ops (stmt, true); /* Add the VOP. */ @@ -749,7 +738,9 @@ get_indirect_ref_operands (gimple stmt, tree expr, int flags, /* If requested, add a USE operand for the base pointer. */ if (recurse_on_base) - get_expr_operands (stmt, pptr, opf_use); + get_expr_operands (stmt, pptr, + opf_non_addressable | opf_use + | (flags & (opf_no_vops|opf_not_non_addressable))); } @@ -758,12 +749,14 @@ get_indirect_ref_operands (gimple stmt, tree expr, int flags, static void get_tmr_operands (gimple stmt, tree expr, int flags) { - /* First record the real operands. */ - get_expr_operands (stmt, &TMR_BASE (expr), opf_use); - get_expr_operands (stmt, &TMR_INDEX (expr), opf_use); + if (!(flags & opf_no_vops) + && TREE_THIS_VOLATILE (expr)) + gimple_set_has_volatile_ops (stmt, true); - if (TMR_SYMBOL (expr)) - gimple_add_to_addresses_taken (stmt, TMR_SYMBOL (expr)); + /* First record the real operands. */ + get_expr_operands (stmt, &TMR_BASE (expr), opf_use | (flags & opf_no_vops)); + get_expr_operands (stmt, &TMR_INDEX (expr), opf_use | (flags & opf_no_vops)); + get_expr_operands (stmt, &TMR_INDEX2 (expr), opf_use | (flags & opf_no_vops)); add_virtual_operand (stmt, flags); } @@ -782,9 +775,9 @@ maybe_add_call_vops (gimple stmt) call-clobbered. */ if (!(call_flags & ECF_NOVOPS)) { - /* A 'pure' or a 'const' function never call-clobbers anything. - A 'noreturn' function might, but since we don't return anyway - there is no point in recording that. */ + /* A 'pure' or a 'const' function never call-clobbers anything. + A 'noreturn' function might, but since we don't return anyway + there is no point in recording that. */ if (!(call_flags & (ECF_PURE | ECF_CONST | ECF_NORETURN))) add_virtual_operand (stmt, opf_def); else if (!(call_flags & ECF_CONST)) @@ -821,13 +814,9 @@ get_asm_expr_operands (gimple stmt) /* Memory operands are addressable. Note that STMT needs the address of this operand. */ if (!allows_reg && allows_mem) - { - tree t = get_base_address (TREE_VALUE (link)); - if (t && DECL_P (t)) - gimple_add_to_addresses_taken (stmt, t); - } + mark_address_taken (TREE_VALUE (link)); - get_expr_operands (stmt, &TREE_VALUE (link), opf_def); + get_expr_operands (stmt, &TREE_VALUE (link), opf_def | opf_not_non_addressable); } /* Gather all input operands. */ @@ -841,25 +830,14 @@ get_asm_expr_operands (gimple stmt) /* Memory operands are addressable. Note that STMT needs the address of this operand. */ if (!allows_reg && allows_mem) - { - tree t = get_base_address (TREE_VALUE (link)); - if (t && DECL_P (t)) - gimple_add_to_addresses_taken (stmt, t); - } + mark_address_taken (TREE_VALUE (link)); - get_expr_operands (stmt, &TREE_VALUE (link), 0); + get_expr_operands (stmt, &TREE_VALUE (link), opf_not_non_addressable); } /* Clobber all memory and addressable symbols for asm ("" : : : "memory"); */ - for (i = 0; i < gimple_asm_nclobbers (stmt); i++) - { - tree link = gimple_asm_clobber_op (stmt, i); - if (strcmp (TREE_STRING_POINTER (TREE_VALUE (link)), "memory") == 0) - { - add_virtual_operand (stmt, opf_def); - break; - } - } + if (gimple_asm_clobbers_memory_p (stmt)) + add_virtual_operand (stmt, opf_def); } @@ -873,10 +851,14 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) enum tree_code code; enum tree_code_class codeclass; tree expr = *expr_p; + int uflags = opf_use; if (expr == NULL) return; + if (is_gimple_debug (stmt)) + uflags |= (flags & opf_no_vops); + code = TREE_CODE (expr); codeclass = TREE_CODE_CLASS (code); @@ -887,7 +869,10 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) reference to it, but the fact that the statement takes its address will be of interest to some passes (e.g. alias resolution). */ - gimple_add_to_addresses_taken (stmt, TREE_OPERAND (expr, 0)); + if ((!(flags & opf_non_addressable) + || (flags & opf_not_non_addressable)) + && !is_gimple_debug (stmt)) + mark_address_taken (TREE_OPERAND (expr, 0)); /* If the address is invariant, there may be no interesting variable references inside. */ @@ -900,7 +885,8 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) here are ARRAY_REF indices which will always be real operands (GIMPLE does not allow non-registers as array indices). */ flags |= opf_no_vops; - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), + flags | opf_not_non_addressable); return; case SSA_NAME: @@ -913,12 +899,11 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) add_stmt_operand (expr_p, stmt, flags); return; - case MISALIGNED_INDIRECT_REF: - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); - /* fall through */ + case DEBUG_EXPR_DECL: + gcc_assert (gimple_debug_bind_p (stmt)); + return; - case ALIGN_INDIRECT_REF: - case INDIRECT_REF: + case MEM_REF: get_indirect_ref_operands (stmt, expr, flags, true); return; @@ -932,32 +917,24 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) case REALPART_EXPR: case IMAGPART_EXPR: { - tree ref; - HOST_WIDE_INT offset, size, maxsize; - - if (TREE_THIS_VOLATILE (expr)) + if (!(flags & opf_no_vops) + && TREE_THIS_VOLATILE (expr)) gimple_set_has_volatile_ops (stmt, true); - ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize); - if (TREE_CODE (ref) == INDIRECT_REF) - { - get_indirect_ref_operands (stmt, ref, flags, false); - flags |= opf_no_vops; - } - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); - + if (code == COMPONENT_REF) { - if (TREE_THIS_VOLATILE (TREE_OPERAND (expr, 1))) + if (!(flags & opf_no_vops) + && TREE_THIS_VOLATILE (TREE_OPERAND (expr, 1))) gimple_set_has_volatile_ops (stmt, true); - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_use); + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags); } else if (code == ARRAY_REF || code == ARRAY_RANGE_REF) { - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use); - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_use); - get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_use); + get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 3), uflags); } return; @@ -966,15 +943,16 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) case WITH_SIZE_EXPR: /* WITH_SIZE_EXPR is a pass-through reference to its first argument, and an rvalue reference to its second argument. */ - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use); + get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags); get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); return; case COND_EXPR: case VEC_COND_EXPR: - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_use); - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use); - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_use); + case VEC_PERM_EXPR: + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags); return; case CONSTRUCTOR: @@ -984,28 +962,32 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) constructor_elt *ce; unsigned HOST_WIDE_INT idx; + /* A volatile constructor is actually TREE_CLOBBER_P, transfer + the volatility to the statement, don't use TREE_CLOBBER_P for + mirroring the other uses of THIS_VOLATILE in this file. */ + if (!(flags & opf_no_vops) + && TREE_THIS_VOLATILE (expr)) + gimple_set_has_volatile_ops (stmt, true); + for (idx = 0; VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (expr), idx, ce); idx++) - get_expr_operands (stmt, &ce->value, opf_use); + get_expr_operands (stmt, &ce->value, uflags); return; } case BIT_FIELD_REF: - if (TREE_THIS_VOLATILE (expr)) + if (!(flags & opf_no_vops) + && TREE_THIS_VOLATILE (expr)) gimple_set_has_volatile_ops (stmt, true); /* FALLTHRU */ - case TRUTH_NOT_EXPR: case VIEW_CONVERT_EXPR: do_unary: get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); return; - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_XOR_EXPR: case COMPOUND_EXPR: case OBJ_TYPE_REF: case ASSERT_EXPR: @@ -1018,22 +1000,20 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) case DOT_PROD_EXPR: case REALIGN_LOAD_EXPR: + case WIDEN_MULT_PLUS_EXPR: + case WIDEN_MULT_MINUS_EXPR: + case FMA_EXPR: { get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), flags); - return; + get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), flags); + return; } - case CHANGE_DYNAMIC_TYPE_EXPR: - gcc_unreachable (); - case FUNCTION_DECL: case LABEL_DECL: case CONST_DECL: case CASE_LABEL_EXPR: - case FILTER_EXPR: - case EXC_PTR_EXPR: /* Expressions that make no memory references. */ return; @@ -1063,25 +1043,46 @@ static void parse_ssa_operands (gimple stmt) { enum gimple_code code = gimple_code (stmt); + size_t i, n, start = 0; - if (code == GIMPLE_ASM) - get_asm_expr_operands (stmt); - else + switch (code) { - size_t i, start = 0; + case GIMPLE_ASM: + get_asm_expr_operands (stmt); + break; + + case GIMPLE_TRANSACTION: + /* The start of a transaction is a memory barrier. */ + add_virtual_operand (stmt, opf_def | opf_use); + break; + + case GIMPLE_DEBUG: + if (gimple_debug_bind_p (stmt) + && gimple_debug_bind_has_value_p (stmt)) + get_expr_operands (stmt, gimple_debug_bind_get_value_ptr (stmt), + opf_use | opf_no_vops); + break; + + case GIMPLE_RETURN: + append_vuse (gimple_vop (cfun)); + goto do_default; + + case GIMPLE_CALL: + /* Add call-clobbered operands, if needed. */ + maybe_add_call_vops (stmt); + /* FALLTHRU */ - if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL) - { - get_expr_operands (stmt, gimple_op_ptr (stmt, 0), opf_def); - start = 1; - } + case GIMPLE_ASSIGN: + get_expr_operands (stmt, gimple_op_ptr (stmt, 0), opf_def); + start = 1; + /* FALLTHRU */ - for (i = start; i < gimple_num_ops (stmt); i++) + default: + do_default: + n = gimple_num_ops (stmt); + for (i = start; i < n; i++) get_expr_operands (stmt, gimple_op_ptr (stmt, i), opf_use); - - /* Add call-clobbered operands, if needed. */ - if (code == GIMPLE_CALL) - maybe_add_call_vops (stmt); + break; } } @@ -1091,19 +1092,126 @@ parse_ssa_operands (gimple stmt) static void build_ssa_operands (gimple stmt) { - /* Initially assume that the statement has no volatile operands and - makes no memory references. */ + /* Initially assume that the statement has no volatile operands. */ gimple_set_has_volatile_ops (stmt, false); - /* Just clear the bitmap so we don't end up reallocating it over and over. */ - if (gimple_addresses_taken (stmt)) - bitmap_clear (gimple_addresses_taken (stmt)); - start_ssa_stmt_operands (); parse_ssa_operands (stmt); finalize_ssa_stmt_operands (stmt); } +/* Verifies SSA statement operands. */ + +DEBUG_FUNCTION bool +verify_ssa_operands (gimple stmt) +{ + use_operand_p use_p; + def_operand_p def_p; + ssa_op_iter iter; + unsigned i; + tree use, def; + bool volatile_p = gimple_has_volatile_ops (stmt); + + /* build_ssa_operands w/o finalizing them. */ + gimple_set_has_volatile_ops (stmt, false); + start_ssa_stmt_operands (); + parse_ssa_operands (stmt); + + /* Now verify the built operands are the same as present in STMT. */ + def = gimple_vdef (stmt); + if (def + && TREE_CODE (def) == SSA_NAME) + def = SSA_NAME_VAR (def); + if (build_vdef != def) + { + error ("virtual definition of statement not up-to-date"); + return true; + } + if (gimple_vdef (stmt) + && ((def_p = gimple_vdef_op (stmt)) == NULL_DEF_OPERAND_P + || DEF_FROM_PTR (def_p) != gimple_vdef (stmt))) + { + error ("virtual def operand missing for stmt"); + return true; + } + + use = gimple_vuse (stmt); + if (use + && TREE_CODE (use) == SSA_NAME) + use = SSA_NAME_VAR (use); + if (build_vuse != use) + { + error ("virtual use of statement not up-to-date"); + return true; + } + if (gimple_vuse (stmt) + && ((use_p = gimple_vuse_op (stmt)) == NULL_USE_OPERAND_P + || USE_FROM_PTR (use_p) != gimple_vuse (stmt))) + { + error ("virtual use operand missing for stmt"); + return true; + } + + FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE) + { + FOR_EACH_VEC_ELT (tree, build_uses, i, use) + { + if (use_p->use == (tree *)use) + { + VEC_replace (tree, build_uses, i, NULL_TREE); + break; + } + } + if (i == VEC_length (tree, build_uses)) + { + error ("excess use operand for stmt"); + debug_generic_expr (USE_FROM_PTR (use_p)); + return true; + } + } + FOR_EACH_VEC_ELT (tree, build_uses, i, use) + if (use != NULL_TREE) + { + error ("use operand missing for stmt"); + debug_generic_expr (*(tree *)use); + return true; + } + + FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF) + { + FOR_EACH_VEC_ELT (tree, build_defs, i, def) + { + if (def_p == (tree *)def) + { + VEC_replace (tree, build_defs, i, NULL_TREE); + break; + } + } + if (i == VEC_length (tree, build_defs)) + { + error ("excess def operand for stmt"); + debug_generic_expr (DEF_FROM_PTR (def_p)); + return true; + } + } + FOR_EACH_VEC_ELT (tree, build_defs, i, def) + if (def != NULL_TREE) + { + error ("def operand missing for stmt"); + debug_generic_expr (*(tree *)def); + return true; + } + + if (gimple_has_volatile_ops (stmt) != volatile_p) + { + error ("stmt volatile flag not up-to-date"); + return true; + } + + cleanup_build_arrays (); + return false; +} + /* Releases the operands of STMT back to their freelists, and clears the stmt operand lists. */ @@ -1133,9 +1241,6 @@ free_stmt_operands (gimple stmt) gimple_set_use_ops (stmt, NULL); } - if (gimple_has_ops (stmt)) - gimple_set_addresses_taken (stmt, NULL); - if (gimple_has_mem_ops (stmt)) { gimple_set_vuse (stmt, NULL_TREE); @@ -1156,6 +1261,12 @@ update_stmt_operands (gimple stmt) timevar_push (TV_TREE_OPS); + /* If the stmt is a noreturn call queue it to be processed by + split_bbs_on_noreturn_calls during cfg cleanup. */ + if (is_gimple_call (stmt) + && gimple_call_noreturn_p (stmt)) + VEC_safe_push (gimple, gc, MODIFIED_NORETURN_CALLS (cfun), stmt); + gcc_assert (gimple_modified_p (stmt)); build_ssa_operands (stmt); gimple_set_modified (stmt, false); @@ -1176,7 +1287,8 @@ swap_tree_operands (gimple stmt, tree *exp0, tree *exp1) /* If the operand cache is active, attempt to preserve the relative positions of these two operands in their respective immediate use - lists. */ + lists by adjusting their use pointer to point to the new + operand position. */ if (ssa_operands_active () && op0 != op1) { use_optype_p use0, use1, ptr; @@ -1197,14 +1309,12 @@ swap_tree_operands (gimple stmt, tree *exp0, tree *exp1) break; } - /* If both uses don't have operand entries, there isn't much we can do - at this point. Presumably we don't need to worry about it. */ - if (use0 && use1) - { - tree *tmp = USE_OP_PTR (use1)->use; - USE_OP_PTR (use1)->use = USE_OP_PTR (use0)->use; - USE_OP_PTR (use0)->use = tmp; - } + /* And adjust their location to point to the new position of the + operand. */ + if (use0) + USE_OP_PTR (use0)->use = exp1; + if (use1) + USE_OP_PTR (use1)->use = exp0; } /* Now swap the data. */ @@ -1216,7 +1326,7 @@ swap_tree_operands (gimple stmt, tree *exp0, tree *exp1) /* Scan the immediate_use list for VAR making sure its linked properly. Return TRUE if there is a problem and emit an error message to F. */ -bool +DEBUG_FUNCTION bool verify_imm_links (FILE *f, tree var) { use_operand_p ptr, prev, list; @@ -1239,7 +1349,7 @@ verify_imm_links (FILE *f, tree var) { if (prev != ptr->prev) goto error; - + if (ptr->use == NULL) goto error; /* 2 roots, or SAFE guard node. */ else if (*(ptr->use) != var) @@ -1277,7 +1387,7 @@ verify_imm_links (FILE *f, tree var) fprintf (f, " STMT MODIFIED. - <%p> ", (void *)ptr->loc.stmt); print_gimple_stmt (f, ptr->loc.stmt, 0, TDF_SLIM); } - fprintf (f, " IMM ERROR : (use_p : tree - %p:%p)", (void *)ptr, + fprintf (f, " IMM ERROR : (use_p : tree - %p:%p)", (void *)ptr, (void *)ptr->use); print_generic_expr (f, USE_FROM_PTR (ptr), TDF_SLIM); fprintf(f, "\n"); @@ -1340,7 +1450,7 @@ dump_immediate_uses (FILE *file) /* Dump def-use edges on stderr. */ -void +DEBUG_FUNCTION void debug_immediate_uses (void) { dump_immediate_uses (stderr); @@ -1349,80 +1459,13 @@ debug_immediate_uses (void) /* Dump def-use edges on stderr. */ -void +DEBUG_FUNCTION void debug_immediate_uses_for (tree var) { dump_immediate_uses_for (stderr, var); } -/* Push *STMT_P on the SCB_STACK. This function is deprecated, do not - introduce new uses of it. */ - -void -push_stmt_changes (gimple *stmt_p) -{ - gimple stmt = *stmt_p; - - /* It makes no sense to keep track of PHI nodes. */ - if (gimple_code (stmt) == GIMPLE_PHI) - return; - - VEC_safe_push (gimple_p, heap, scb_stack, stmt_p); -} - -/* Pop the top stmt from SCB_STACK and act on the differences between - what was recorded by push_stmt_changes and the current state of - the statement. This function is deprecated, do not introduce - new uses of it. */ - -void -pop_stmt_changes (gimple *stmt_p) -{ - gimple *stmt2_p, stmt = *stmt_p; - ssa_op_iter iter; - tree op; - - /* It makes no sense to keep track of PHI nodes. */ - if (gimple_code (stmt) == GIMPLE_PHI) - return; - - stmt2_p = VEC_pop (gimple_p, scb_stack); - gcc_assert (stmt_p == stmt2_p); - - /* Force an operand re-scan on the statement and mark any newly - exposed variables. This also will mark the virtual operand - for renaming if necessary. */ - update_stmt (stmt); - - /* Mark all the naked GIMPLE register operands for renaming. - ??? Especially this is considered bad behavior of the caller, - it should have updated SSA form manually. Even more so as - we do not have a way to verify that no SSA names for op are - already in use. */ - FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF|SSA_OP_USE) - if (DECL_P (op)) - mark_sym_for_renaming (op); -} - -/* Discard the topmost stmt from SCB_STACK. This is useful - when the caller realized that it did not actually modified the - statement. It avoids the expensive operand re-scan. - This function is deprecated, do not introduce new uses of it. */ - -void -discard_stmt_changes (gimple *stmt_p) -{ - gimple *stmt2_p, stmt = *stmt_p; - - /* It makes no sense to keep track of PHI nodes. */ - if (gimple_code (stmt) == GIMPLE_PHI) - return; - - stmt2_p = VEC_pop (gimple_p, scb_stack); - gcc_assert (stmt_p == stmt2_p); -} - /* Unlink STMTs virtual definition from the IL by propagating its use. */ void