On Fri, 29 Nov 2013, Richard Biener wrote: > > The following re-org allows a cheaper fix to PR59208 than > a push/pop_cfun pair around a single update_stmt call. > > It's simple to make the SSA operand machinery cfun-agnostic > as it has few direct uses and does not use any APIs that > implicitely use cfun. > > Thus the patch adds and uses a new update_stmt_fn function. > > Bootstrap and regtest running on x86_64-unknown-linux-gnu.
This is what I have committed. Richard. 2013-11-29 Richard Biener <rguent...@suse.de> PR middle-end/59208 * tree-ssa-operands.h (fini_ssa_operands, verify_ssa_operands, free_stmt_operands, update_stmt_operands): Add struct function argument. * tree-ssa-operands.c: Remove uses of cfun, propagate struct function argument from fini_ssa_operands, verify_ssa_operands, free_stmt_operands and update_stmt_operands everywhere. * tree-ssanames.h (release_ssa_name_fn): New. (release_ssa_name): Inline wrapper around release_ssa_name_fn. * tree-ssanames.c (release_ssa_name): Rename to ... (release_ssa_name_fn): ... this and add struct function argument. * gimple-ssa.h (update_stmt, update_stmt_if_modified): Adjust. (update_stmt_fn): New function. * tree-cfg.c (move_block_to_fn): Adjust. * tree-if-conv.c (free_bb_predicate): Likewise. * tree-ssa.c (verify_ssa): Likewise. (delete_tree_ssa): Likewise. * gimple-pretty-print.c (dump_gimple_mem_ops): Remove guard. * cgraph.c (cgraph_redirect_edge_call_stmt_to_callee): Call update_stmt_fn instead of update_stmt. * g++.dg/torture/pr59208.C: New testcase. Index: gcc/tree-ssa-operands.h =================================================================== *** gcc/tree-ssa-operands.h.orig 2013-11-29 11:45:49.000000000 +0100 --- gcc/tree-ssa-operands.h 2013-11-29 13:10:18.072553361 +0100 *************** struct GTY(()) ssa_operands { *** 91,100 **** extern bool ssa_operands_active (struct function *); extern void init_ssa_operands (struct function *fn); ! extern void fini_ssa_operands (void); ! extern bool verify_ssa_operands (gimple stmt); ! extern void free_stmt_operands (gimple); ! extern void update_stmt_operands (gimple); extern void swap_ssa_operands (gimple, tree *, tree *); extern bool verify_imm_links (FILE *f, tree var); --- 91,100 ---- extern bool ssa_operands_active (struct function *); extern void init_ssa_operands (struct function *fn); ! extern void fini_ssa_operands (struct function *); ! extern bool verify_ssa_operands (struct function *, gimple stmt); ! extern void free_stmt_operands (struct function *, gimple); ! extern void update_stmt_operands (struct function *, gimple); extern void swap_ssa_operands (gimple, tree *, tree *); extern bool verify_imm_links (FILE *f, tree var); Index: gcc/tree-ssa-operands.c =================================================================== *** gcc/tree-ssa-operands.c.orig 2013-11-29 11:45:49.000000000 +0100 --- gcc/tree-ssa-operands.c 2013-11-29 13:23:30.781756355 +0100 *************** static tree build_vuse; *** 129,135 **** compilations of multiple functions. */ static bitmap_obstack operands_bitmap_obstack; ! static void get_expr_operands (gimple, tree *, int); /* Number of functions with initialized ssa_operands. */ static int n_initialized = 0; --- 129,135 ---- compilations of multiple functions. */ static bitmap_obstack operands_bitmap_obstack; ! static void get_expr_operands (struct function *, gimple, tree *, int); /* Number of functions with initialized ssa_operands. */ static int n_initialized = 0; *************** init_ssa_operands (struct function *fn) *** 217,223 **** /* Dispose of anything required by the operand routines. */ void ! fini_ssa_operands (void) { struct ssa_operand_memory_d *ptr; --- 217,223 ---- /* Dispose of anything required by the operand routines. */ void ! fini_ssa_operands (struct function *fn) { struct ssa_operand_memory_d *ptr; *************** fini_ssa_operands (void) *** 228,276 **** build_vuse = NULL_TREE; } ! gimple_ssa_operands (cfun)->free_uses = NULL; ! while ((ptr = gimple_ssa_operands (cfun)->operand_memory) != NULL) { ! gimple_ssa_operands (cfun)->operand_memory ! = gimple_ssa_operands (cfun)->operand_memory->next; ggc_free (ptr); } ! gimple_ssa_operands (cfun)->ops_active = false; if (!n_initialized) bitmap_obstack_release (&operands_bitmap_obstack); ! cfun->gimple_df->vop = NULL_TREE; } /* Return memory for an operand of size SIZE. */ static inline void * ! ssa_operand_alloc (unsigned size) { char *ptr; gcc_assert (size == sizeof (struct use_optype_d)); ! if (gimple_ssa_operands (cfun)->operand_memory_index + size ! >= gimple_ssa_operands (cfun)->ssa_operand_mem_size) { struct ssa_operand_memory_d *ptr; ! switch (gimple_ssa_operands (cfun)->ssa_operand_mem_size) { case OP_SIZE_INIT: ! gimple_ssa_operands (cfun)->ssa_operand_mem_size = OP_SIZE_1; break; case OP_SIZE_1: ! gimple_ssa_operands (cfun)->ssa_operand_mem_size = OP_SIZE_2; break; case OP_SIZE_2: case OP_SIZE_3: ! gimple_ssa_operands (cfun)->ssa_operand_mem_size = OP_SIZE_3; break; default: gcc_unreachable (); --- 228,276 ---- build_vuse = NULL_TREE; } ! gimple_ssa_operands (fn)->free_uses = NULL; ! while ((ptr = gimple_ssa_operands (fn)->operand_memory) != NULL) { ! gimple_ssa_operands (fn)->operand_memory ! = gimple_ssa_operands (fn)->operand_memory->next; ggc_free (ptr); } ! gimple_ssa_operands (fn)->ops_active = false; if (!n_initialized) bitmap_obstack_release (&operands_bitmap_obstack); ! fn->gimple_df->vop = NULL_TREE; } /* Return memory for an operand of size SIZE. */ static inline void * ! ssa_operand_alloc (struct function *fn, unsigned size) { char *ptr; gcc_assert (size == sizeof (struct use_optype_d)); ! if (gimple_ssa_operands (fn)->operand_memory_index + size ! >= gimple_ssa_operands (fn)->ssa_operand_mem_size) { struct ssa_operand_memory_d *ptr; ! switch (gimple_ssa_operands (fn)->ssa_operand_mem_size) { case OP_SIZE_INIT: ! gimple_ssa_operands (fn)->ssa_operand_mem_size = OP_SIZE_1; break; case OP_SIZE_1: ! gimple_ssa_operands (fn)->ssa_operand_mem_size = OP_SIZE_2; break; case OP_SIZE_2: case OP_SIZE_3: ! gimple_ssa_operands (fn)->ssa_operand_mem_size = OP_SIZE_3; break; default: gcc_unreachable (); *************** ssa_operand_alloc (unsigned size) *** 278,293 **** 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; } ! ptr = &(gimple_ssa_operands (cfun)->operand_memory ! ->mem[gimple_ssa_operands (cfun)->operand_memory_index]); ! gimple_ssa_operands (cfun)->operand_memory_index += size; return ptr; } --- 278,293 ---- ptr = ggc_alloc_ssa_operand_memory_d (sizeof (void *) ! + gimple_ssa_operands (fn)->ssa_operand_mem_size); ! ptr->next = gimple_ssa_operands (fn)->operand_memory; ! gimple_ssa_operands (fn)->operand_memory = ptr; ! gimple_ssa_operands (fn)->operand_memory_index = 0; } ! ptr = &(gimple_ssa_operands (fn)->operand_memory ! ->mem[gimple_ssa_operands (fn)->operand_memory_index]); ! gimple_ssa_operands (fn)->operand_memory_index += size; return ptr; } *************** ssa_operand_alloc (unsigned size) *** 295,312 **** /* Allocate a USE operand. */ static inline struct use_optype_d * ! alloc_use (void) { struct use_optype_d *ret; ! if (gimple_ssa_operands (cfun)->free_uses) { ! ret = gimple_ssa_operands (cfun)->free_uses; ! gimple_ssa_operands (cfun)->free_uses ! = gimple_ssa_operands (cfun)->free_uses->next; } else ret = (struct use_optype_d *) ! ssa_operand_alloc (sizeof (struct use_optype_d)); return ret; } --- 295,312 ---- /* Allocate a USE operand. */ static inline struct use_optype_d * ! alloc_use (struct function *fn) { struct use_optype_d *ret; ! if (gimple_ssa_operands (fn)->free_uses) { ! ret = gimple_ssa_operands (fn)->free_uses; ! gimple_ssa_operands (fn)->free_uses ! = gimple_ssa_operands (fn)->free_uses->next; } else ret = (struct use_optype_d *) ! ssa_operand_alloc (fn, sizeof (struct use_optype_d)); return ret; } *************** alloc_use (void) *** 314,324 **** /* Adds OP to the list of uses of statement STMT after LAST. */ static inline use_optype_p ! add_use_op (gimple stmt, tree *op, use_optype_p last) { use_optype_p new_use; ! new_use = alloc_use (); USE_OP_PTR (new_use)->use = op; link_imm_use_stmt (USE_OP_PTR (new_use), *op, stmt); last->next = new_use; --- 314,324 ---- /* Adds OP to the list of uses of statement STMT after LAST. */ static inline use_optype_p ! add_use_op (struct function *fn, gimple stmt, tree *op, use_optype_p last) { use_optype_p new_use; ! new_use = alloc_use (fn); USE_OP_PTR (new_use)->use = op; link_imm_use_stmt (USE_OP_PTR (new_use), *op, stmt); last->next = new_use; *************** add_use_op (gimple stmt, tree *op, use_o *** 332,338 **** TODO -- Make build_defs vec of tree *. */ static inline void ! finalize_ssa_defs (gimple stmt) { /* Pre-pend the vdef we may have built. */ if (build_vdef != NULL_TREE) --- 332,338 ---- TODO -- Make build_defs vec of tree *. */ static inline void ! finalize_ssa_defs (struct function *fn, gimple stmt) { /* Pre-pend the vdef we may have built. */ if (build_vdef != NULL_TREE) *************** finalize_ssa_defs (gimple stmt) *** 352,358 **** if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME) { unlink_stmt_vdef (stmt); ! release_ssa_name (gimple_vdef (stmt)); } gimple_set_vdef (stmt, NULL_TREE); } --- 352,358 ---- if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME) { unlink_stmt_vdef (stmt); ! release_ssa_name_fn (fn, gimple_vdef (stmt)); } gimple_set_vdef (stmt, NULL_TREE); } *************** finalize_ssa_defs (gimple stmt) *** 361,368 **** if (gimple_vdef (stmt) && TREE_CODE (gimple_vdef (stmt)) != SSA_NAME) { ! cfun->gimple_df->rename_vops = 1; ! cfun->gimple_df->ssa_renaming_needed = 1; } } --- 361,368 ---- if (gimple_vdef (stmt) && TREE_CODE (gimple_vdef (stmt)) != SSA_NAME) { ! fn->gimple_df->rename_vops = 1; ! fn->gimple_df->ssa_renaming_needed = 1; } } *************** finalize_ssa_defs (gimple stmt) *** 371,377 **** TODO -- Make build_uses vec of tree *. */ static inline void ! finalize_ssa_uses (gimple stmt) { unsigned new_i; struct use_optype_d new_list; --- 371,377 ---- TODO -- Make build_uses vec of tree *. */ static inline void ! finalize_ssa_uses (struct function *fn, gimple stmt) { unsigned new_i; struct use_optype_d new_list; *************** finalize_ssa_uses (gimple stmt) *** 405,412 **** { for (ptr = old_ops; ptr; ptr = ptr->next) delink_imm_use (USE_OP_PTR (ptr)); ! old_ops->next = gimple_ssa_operands (cfun)->free_uses; ! gimple_ssa_operands (cfun)->free_uses = old_ops; } /* If we added a VUSE, make sure to set the operand if it is not already --- 405,412 ---- { for (ptr = old_ops; ptr; ptr = ptr->next) delink_imm_use (USE_OP_PTR (ptr)); ! old_ops->next = gimple_ssa_operands (fn)->free_uses; ! gimple_ssa_operands (fn)->free_uses = old_ops; } /* If we added a VUSE, make sure to set the operand if it is not already *************** finalize_ssa_uses (gimple stmt) *** 414,429 **** if (build_vuse != NULL_TREE && gimple_vuse (stmt) == NULL_TREE) { ! gimple_set_vuse (stmt, gimple_vop (cfun)); ! cfun->gimple_df->rename_vops = 1; ! cfun->gimple_df->ssa_renaming_needed = 1; } /* Now create nodes for all the new nodes. */ for (new_i = 0; new_i < build_uses.length (); new_i++) { tree *op = (tree *) build_uses[new_i]; ! last = add_use_op (stmt, op, last); } /* Now set the stmt's operands. */ --- 414,429 ---- if (build_vuse != NULL_TREE && gimple_vuse (stmt) == NULL_TREE) { ! gimple_set_vuse (stmt, gimple_vop (fn)); ! fn->gimple_df->rename_vops = 1; ! fn->gimple_df->ssa_renaming_needed = 1; } /* Now create nodes for all the new nodes. */ for (new_i = 0; new_i < build_uses.length (); new_i++) { tree *op = (tree *) build_uses[new_i]; ! last = add_use_op (fn, stmt, op, last); } /* Now set the stmt's operands. */ *************** cleanup_build_arrays (void) *** 446,455 **** /* Finalize all the build vectors, fill the new ones into INFO. */ static inline void ! finalize_ssa_stmt_operands (gimple stmt) { ! finalize_ssa_defs (stmt); ! finalize_ssa_uses (stmt); cleanup_build_arrays (); } --- 446,455 ---- /* Finalize all the build vectors, fill the new ones into INFO. */ static inline void ! finalize_ssa_stmt_operands (struct function *fn, gimple stmt) { ! finalize_ssa_defs (fn, stmt); ! finalize_ssa_uses (fn, stmt); cleanup_build_arrays (); } *************** append_vuse (tree var) *** 509,515 **** /* Add virtual operands for STMT. FLAGS is as in get_expr_operands. */ static void ! add_virtual_operand (gimple stmt ATTRIBUTE_UNUSED, int flags) { /* Add virtual operands to the stmt, unless the caller has specifically requested not to do that (used when adding operands inside an --- 509,516 ---- /* Add virtual operands for STMT. FLAGS is as in get_expr_operands. */ static void ! add_virtual_operand (struct function *fn, ! gimple stmt ATTRIBUTE_UNUSED, int flags) { /* Add virtual operands to the stmt, unless the caller has specifically requested not to do that (used when adding operands inside an *************** add_virtual_operand (gimple stmt ATTRIBU *** 520,528 **** gcc_assert (!is_gimple_debug (stmt)); if (flags & opf_def) ! append_vdef (gimple_vop (cfun)); else ! append_vuse (gimple_vop (cfun)); } --- 521,529 ---- gcc_assert (!is_gimple_debug (stmt)); if (flags & opf_def) ! append_vdef (gimple_vop (fn)); else ! append_vuse (gimple_vop (fn)); } *************** add_virtual_operand (gimple stmt ATTRIBU *** 532,538 **** added to virtual operands. */ static void ! add_stmt_operand (tree *var_p, gimple stmt, int flags) { tree var = *var_p; --- 533,539 ---- added to virtual operands. */ static void ! add_stmt_operand (struct function *fn, tree *var_p, gimple stmt, int flags) { tree var = *var_p; *************** add_stmt_operand (tree *var_p, gimple st *** 546,552 **** else append_use (var_p); if (DECL_P (*var_p)) ! cfun->gimple_df->ssa_renaming_needed = 1; } else { --- 547,553 ---- else append_use (var_p); if (DECL_P (*var_p)) ! fn->gimple_df->ssa_renaming_needed = 1; } else { *************** add_stmt_operand (tree *var_p, gimple st *** 556,562 **** gimple_set_has_volatile_ops (stmt, true); /* The variable is a memory access. Add virtual operands. */ ! add_virtual_operand (stmt, flags); } } --- 557,563 ---- gimple_set_has_volatile_ops (stmt, true); /* The variable is a memory access. Add virtual operands. */ ! add_virtual_operand (fn, stmt, flags); } } *************** mark_address_taken (tree ref) *** 596,602 **** FLAGS is as in get_expr_operands. */ static void ! get_indirect_ref_operands (gimple stmt, tree expr, int flags) { tree *pptr = &TREE_OPERAND (expr, 0); --- 597,604 ---- FLAGS is as in get_expr_operands. */ static void ! get_indirect_ref_operands (struct function *fn, ! gimple stmt, tree expr, int flags) { tree *pptr = &TREE_OPERAND (expr, 0); *************** get_indirect_ref_operands (gimple stmt, *** 605,614 **** gimple_set_has_volatile_ops (stmt, true); /* Add the VOP. */ ! add_virtual_operand (stmt, flags); /* If requested, add a USE operand for the base pointer. */ ! get_expr_operands (stmt, pptr, opf_non_addressable | opf_use | (flags & (opf_no_vops|opf_not_non_addressable))); } --- 607,616 ---- gimple_set_has_volatile_ops (stmt, true); /* Add the VOP. */ ! add_virtual_operand (fn, stmt, flags); /* If requested, add a USE operand for the base pointer. */ ! get_expr_operands (fn, stmt, pptr, opf_non_addressable | opf_use | (flags & (opf_no_vops|opf_not_non_addressable))); } *************** get_indirect_ref_operands (gimple stmt, *** 617,634 **** /* A subroutine of get_expr_operands to handle TARGET_MEM_REF. */ static void ! get_tmr_operands (gimple stmt, tree expr, int flags) { if (!(flags & opf_no_vops) && TREE_THIS_VOLATILE (expr)) gimple_set_has_volatile_ops (stmt, true); /* 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); } --- 619,639 ---- /* A subroutine of get_expr_operands to handle TARGET_MEM_REF. */ static void ! get_tmr_operands (struct function *fn, gimple stmt, tree expr, int flags) { if (!(flags & opf_no_vops) && TREE_THIS_VOLATILE (expr)) gimple_set_has_volatile_ops (stmt, true); /* First record the real operands. */ ! get_expr_operands (fn, stmt, ! &TMR_BASE (expr), opf_use | (flags & opf_no_vops)); ! get_expr_operands (fn, stmt, ! &TMR_INDEX (expr), opf_use | (flags & opf_no_vops)); ! get_expr_operands (fn, stmt, ! &TMR_INDEX2 (expr), opf_use | (flags & opf_no_vops)); ! add_virtual_operand (fn, stmt, flags); } *************** get_tmr_operands (gimple stmt, tree expr *** 636,642 **** escape, add them to the VDEF/VUSE lists for it. */ static void ! maybe_add_call_vops (gimple stmt) { int call_flags = gimple_call_flags (stmt); --- 641,647 ---- escape, add them to the VDEF/VUSE lists for it. */ static void ! maybe_add_call_vops (struct function *fn, gimple stmt) { int call_flags = gimple_call_flags (stmt); *************** maybe_add_call_vops (gimple stmt) *** 649,657 **** 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)) ! add_virtual_operand (stmt, opf_use); } } --- 654,662 ---- 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 (fn, stmt, opf_def); else if (!(call_flags & ECF_CONST)) ! add_virtual_operand (fn, stmt, opf_use); } } *************** maybe_add_call_vops (gimple stmt) *** 659,665 **** /* Scan operands in the ASM_EXPR stmt referred to in INFO. */ static void ! get_asm_expr_operands (gimple stmt) { size_t i, noutputs; const char **oconstraints; --- 664,670 ---- /* Scan operands in the ASM_EXPR stmt referred to in INFO. */ static void ! get_asm_expr_operands (struct function *fn, gimple stmt) { size_t i, noutputs; const char **oconstraints; *************** get_asm_expr_operands (gimple stmt) *** 686,692 **** if (!allows_reg && allows_mem) mark_address_taken (TREE_VALUE (link)); ! get_expr_operands (stmt, &TREE_VALUE (link), opf_def | opf_not_non_addressable); } /* Gather all input operands. */ --- 691,698 ---- if (!allows_reg && allows_mem) mark_address_taken (TREE_VALUE (link)); ! get_expr_operands (fn, stmt, ! &TREE_VALUE (link), opf_def | opf_not_non_addressable); } /* Gather all input operands. */ *************** get_asm_expr_operands (gimple stmt) *** 702,713 **** if (!allows_reg && allows_mem) mark_address_taken (TREE_VALUE (link)); ! get_expr_operands (stmt, &TREE_VALUE (link), opf_not_non_addressable); } /* Clobber all memory and addressable symbols for asm ("" : : : "memory"); */ if (gimple_asm_clobbers_memory_p (stmt)) ! add_virtual_operand (stmt, opf_def); } --- 708,719 ---- if (!allows_reg && allows_mem) mark_address_taken (TREE_VALUE (link)); ! get_expr_operands (fn, stmt, &TREE_VALUE (link), opf_not_non_addressable); } /* Clobber all memory and addressable symbols for asm ("" : : : "memory"); */ if (gimple_asm_clobbers_memory_p (stmt)) ! add_virtual_operand (fn, stmt, opf_def); } *************** get_asm_expr_operands (gimple stmt) *** 716,722 **** interpret the operands found. */ static void ! get_expr_operands (gimple stmt, tree *expr_p, int flags) { enum tree_code code; enum tree_code_class codeclass; --- 722,728 ---- interpret the operands found. */ static void ! get_expr_operands (struct function *fn, gimple stmt, tree *expr_p, int flags) { enum tree_code code; enum tree_code_class codeclass; *************** get_expr_operands (gimple stmt, tree *ex *** 755,761 **** 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 | opf_not_non_addressable); return; --- 761,767 ---- 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 (fn, stmt, &TREE_OPERAND (expr, 0), flags | opf_not_non_addressable); return; *************** get_expr_operands (gimple stmt, tree *ex *** 763,769 **** case VAR_DECL: case PARM_DECL: case RESULT_DECL: ! add_stmt_operand (expr_p, stmt, flags); return; case DEBUG_EXPR_DECL: --- 769,775 ---- case VAR_DECL: case PARM_DECL: case RESULT_DECL: ! add_stmt_operand (fn, expr_p, stmt, flags); return; case DEBUG_EXPR_DECL: *************** get_expr_operands (gimple stmt, tree *ex *** 771,781 **** return; case MEM_REF: ! get_indirect_ref_operands (stmt, expr, flags); return; case TARGET_MEM_REF: ! get_tmr_operands (stmt, expr, flags); return; case ARRAY_REF: --- 777,787 ---- return; case MEM_REF: ! get_indirect_ref_operands (fn, stmt, expr, flags); return; case TARGET_MEM_REF: ! get_tmr_operands (fn, stmt, expr, flags); return; case ARRAY_REF: *************** get_expr_operands (gimple stmt, tree *ex *** 788,807 **** && TREE_THIS_VOLATILE (expr)) gimple_set_has_volatile_ops (stmt, true); ! get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); if (code == COMPONENT_REF) { 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), uflags); } else if (code == ARRAY_REF || code == ARRAY_RANGE_REF) { ! 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; --- 794,813 ---- && TREE_THIS_VOLATILE (expr)) gimple_set_has_volatile_ops (stmt, true); ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); if (code == COMPONENT_REF) { if (!(flags & opf_no_vops) && TREE_THIS_VOLATILE (TREE_OPERAND (expr, 1))) gimple_set_has_volatile_ops (stmt, true); ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), uflags); } else if (code == ARRAY_REF || code == ARRAY_RANGE_REF) { ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), uflags); ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), uflags); ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 3), uflags); } return; *************** get_expr_operands (gimple stmt, tree *ex *** 810,825 **** 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), uflags); ! get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); return; case COND_EXPR: case VEC_COND_EXPR: 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: --- 816,831 ---- 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 (fn, stmt, &TREE_OPERAND (expr, 1), uflags); ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); return; case COND_EXPR: case VEC_COND_EXPR: case VEC_PERM_EXPR: ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), uflags); ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), uflags); ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), uflags); return; case CONSTRUCTOR: *************** get_expr_operands (gimple stmt, tree *ex *** 839,845 **** for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (expr), idx, &ce); idx++) ! get_expr_operands (stmt, &ce->value, uflags); return; } --- 845,851 ---- for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (expr), idx, &ce); idx++) ! get_expr_operands (fn, stmt, &ce->value, uflags); return; } *************** get_expr_operands (gimple stmt, tree *ex *** 852,858 **** case VIEW_CONVERT_EXPR: do_unary: ! get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); return; case COMPOUND_EXPR: --- 858,864 ---- case VIEW_CONVERT_EXPR: do_unary: ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); return; case COMPOUND_EXPR: *************** get_expr_operands (gimple stmt, tree *ex *** 860,867 **** case ASSERT_EXPR: do_binary: { ! get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); ! get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); return; } --- 866,873 ---- case ASSERT_EXPR: do_binary: { ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), flags); return; } *************** get_expr_operands (gimple stmt, tree *ex *** 871,879 **** 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; } --- 877,885 ---- case WIDEN_MULT_MINUS_EXPR: case FMA_EXPR: { ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), flags); ! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), flags); return; } *************** get_expr_operands (gimple stmt, tree *ex *** 907,913 **** build_* operand vectors will have potential operands in them. */ static void ! parse_ssa_operands (gimple stmt) { enum gimple_code code = gimple_code (stmt); size_t i, n, start = 0; --- 913,919 ---- build_* operand vectors will have potential operands in them. */ static void ! parse_ssa_operands (struct function *fn, gimple stmt) { enum gimple_code code = gimple_code (stmt); size_t i, n, start = 0; *************** parse_ssa_operands (gimple stmt) *** 915,946 **** switch (code) { 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 */ case GIMPLE_ASSIGN: ! get_expr_operands (stmt, gimple_op_ptr (stmt, 0), opf_def); start = 1; /* FALLTHRU */ --- 921,952 ---- switch (code) { case GIMPLE_ASM: ! get_asm_expr_operands (fn, stmt); break; case GIMPLE_TRANSACTION: /* The start of a transaction is a memory barrier. */ ! add_virtual_operand (fn, 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 (fn, stmt, gimple_debug_bind_get_value_ptr (stmt), opf_use | opf_no_vops); break; case GIMPLE_RETURN: ! append_vuse (gimple_vop (fn)); goto do_default; case GIMPLE_CALL: /* Add call-clobbered operands, if needed. */ ! maybe_add_call_vops (fn, stmt); /* FALLTHRU */ case GIMPLE_ASSIGN: ! get_expr_operands (fn, stmt, gimple_op_ptr (stmt, 0), opf_def); start = 1; /* FALLTHRU */ *************** parse_ssa_operands (gimple stmt) *** 948,954 **** do_default: n = gimple_num_ops (stmt); for (i = start; i < n; i++) ! get_expr_operands (stmt, gimple_op_ptr (stmt, i), opf_use); break; } } --- 954,960 ---- do_default: n = gimple_num_ops (stmt); for (i = start; i < n; i++) ! get_expr_operands (fn, stmt, gimple_op_ptr (stmt, i), opf_use); break; } } *************** parse_ssa_operands (gimple stmt) *** 957,976 **** /* Create an operands cache for STMT. */ static void ! build_ssa_operands (gimple stmt) { /* Initially assume that the statement has no volatile operands. */ gimple_set_has_volatile_ops (stmt, false); 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; --- 963,982 ---- /* Create an operands cache for STMT. */ static void ! build_ssa_operands (struct function *fn, gimple stmt) { /* Initially assume that the statement has no volatile operands. */ gimple_set_has_volatile_ops (stmt, false); start_ssa_stmt_operands (); ! parse_ssa_operands (fn, stmt); ! finalize_ssa_stmt_operands (fn, stmt); } /* Verifies SSA statement operands. */ DEBUG_FUNCTION bool ! verify_ssa_operands (struct function *fn, gimple stmt) { use_operand_p use_p; def_operand_p def_p; *************** verify_ssa_operands (gimple stmt) *** 982,988 **** /* 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); --- 988,994 ---- /* build_ssa_operands w/o finalizing them. */ gimple_set_has_volatile_ops (stmt, false); start_ssa_stmt_operands (); ! parse_ssa_operands (fn, stmt); /* Now verify the built operands are the same as present in STMT. */ def = gimple_vdef (stmt); *************** verify_ssa_operands (gimple stmt) *** 1059,1065 **** the stmt operand lists. */ void ! free_stmt_operands (gimple stmt) { use_optype_p uses = gimple_use_ops (stmt), last_use; --- 1065,1071 ---- the stmt operand lists. */ void ! free_stmt_operands (struct function *fn, gimple stmt) { use_optype_p uses = gimple_use_ops (stmt), last_use; *************** free_stmt_operands (gimple stmt) *** 1068,1075 **** for (last_use = uses; last_use->next; last_use = last_use->next) delink_imm_use (USE_OP_PTR (last_use)); delink_imm_use (USE_OP_PTR (last_use)); ! last_use->next = gimple_ssa_operands (cfun)->free_uses; ! gimple_ssa_operands (cfun)->free_uses = uses; gimple_set_use_ops (stmt, NULL); } --- 1074,1081 ---- for (last_use = uses; last_use->next; last_use = last_use->next) delink_imm_use (USE_OP_PTR (last_use)); delink_imm_use (USE_OP_PTR (last_use)); ! last_use->next = gimple_ssa_operands (fn)->free_uses; ! gimple_ssa_operands (fn)->free_uses = uses; gimple_set_use_ops (stmt, NULL); } *************** free_stmt_operands (gimple stmt) *** 1084,1094 **** /* Get the operands of statement STMT. */ void ! update_stmt_operands (gimple stmt) { /* If update_stmt_operands is called before SSA is initialized, do nothing. */ ! if (!ssa_operands_active (cfun)) return; timevar_push (TV_TREE_OPS); --- 1090,1100 ---- /* Get the operands of statement STMT. */ void ! update_stmt_operands (struct function *fn, gimple stmt) { /* If update_stmt_operands is called before SSA is initialized, do nothing. */ ! if (!ssa_operands_active (fn)) return; timevar_push (TV_TREE_OPS); *************** update_stmt_operands (gimple stmt) *** 1097,1106 **** split_bbs_on_noreturn_calls during cfg cleanup. */ if (is_gimple_call (stmt) && gimple_call_noreturn_p (stmt)) ! vec_safe_push (MODIFIED_NORETURN_CALLS (cfun), stmt); gcc_assert (gimple_modified_p (stmt)); ! build_ssa_operands (stmt); gimple_set_modified (stmt, false); timevar_pop (TV_TREE_OPS); --- 1103,1112 ---- split_bbs_on_noreturn_calls during cfg cleanup. */ if (is_gimple_call (stmt) && gimple_call_noreturn_p (stmt)) ! vec_safe_push (MODIFIED_NORETURN_CALLS (fn), stmt); gcc_assert (gimple_modified_p (stmt)); ! build_ssa_operands (fn, stmt); gimple_set_modified (stmt, false); timevar_pop (TV_TREE_OPS); *************** swap_ssa_operands (gimple stmt, tree *ex *** 1117,1124 **** op0 = *exp0; op1 = *exp1; - gcc_checking_assert (ssa_operands_active (cfun)); - if (op0 != op1) { /* Attempt to preserve the relative positions of these two operands in --- 1123,1128 ---- Index: gcc/gimple-ssa.h =================================================================== *** gcc/gimple-ssa.h.orig 2013-11-29 11:45:49.000000000 +0100 --- gcc/gimple-ssa.h 2013-11-29 13:10:18.087553532 +0100 *************** update_stmt (gimple s) *** 141,147 **** if (gimple_has_ops (s)) { gimple_set_modified (s, true); ! update_stmt_operands (s); } } --- 141,147 ---- if (gimple_has_ops (s)) { gimple_set_modified (s, true); ! update_stmt_operands (cfun, s); } } *************** static inline void *** 151,157 **** update_stmt_if_modified (gimple s) { if (gimple_modified_p (s)) ! update_stmt_operands (s); } --- 151,169 ---- update_stmt_if_modified (gimple s) { if (gimple_modified_p (s)) ! update_stmt_operands (cfun, s); ! } ! ! /* Mark statement S as modified, and update it. */ ! ! static inline void ! update_stmt_fn (struct function *fn, gimple s) ! { ! if (gimple_has_ops (s)) ! { ! gimple_set_modified (s, true); ! update_stmt_operands (fn, s); ! } } Index: gcc/cgraph.c =================================================================== *** gcc/cgraph.c.orig 2013-11-29 11:45:49.000000000 +0100 --- gcc/cgraph.c 2013-11-29 13:10:18.087553532 +0100 *************** cgraph_redirect_edge_call_stmt_to_callee *** 1468,1474 **** { new_stmt = e->call_stmt; gimple_call_set_fndecl (new_stmt, e->callee->decl); ! update_stmt (new_stmt); } cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt, false); --- 1468,1474 ---- { new_stmt = e->call_stmt; gimple_call_set_fndecl (new_stmt, e->callee->decl); ! update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt); } cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt, false); Index: gcc/testsuite/g++.dg/torture/pr59208.C =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/g++.dg/torture/pr59208.C 2013-11-29 13:10:18.123553951 +0100 *************** *** 0 **** --- 1,26 ---- + // { dg-do compile } + + class A { + public: + A(); + A(int *); + }; + class B {}; + class C : B { + public: + virtual void m_fn1(); + void operator+=(int) { m_fn1(); } + }; + enum DebuggerType {}; + C a; + DebuggerType b; + void operator==(A &, const A &); + static A get_dbx_doc(A &p1) { p1 == 0; } + + void add_button() { + A c; + switch (b) + case 0: + get_dbx_doc(c); + a += 0; + } Index: gcc/tree-cfg.c =================================================================== *** gcc/tree-cfg.c.orig 2013-11-29 13:09:30.000000000 +0100 --- gcc/tree-cfg.c 2013-11-29 13:10:18.124553965 +0100 *************** move_block_to_fn (struct function *dest_ *** 6566,6572 **** /* We cannot leave any operands allocated from the operand caches of the current function. */ ! free_stmt_operands (stmt); push_cfun (dest_cfun); update_stmt (stmt); pop_cfun (); --- 6566,6572 ---- /* We cannot leave any operands allocated from the operand caches of the current function. */ ! free_stmt_operands (cfun, stmt); push_cfun (dest_cfun); update_stmt (stmt); pop_cfun (); Index: gcc/tree-if-conv.c =================================================================== *** gcc/tree-if-conv.c.orig 2013-11-29 11:45:49.000000000 +0100 --- gcc/tree-if-conv.c 2013-11-29 13:10:18.124553965 +0100 *************** free_bb_predicate (basic_block bb) *** 212,218 **** gimple_stmt_iterator i; for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i)) ! free_stmt_operands (gsi_stmt (i)); } free (bb->aux); --- 212,218 ---- gimple_stmt_iterator i; for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i)) ! free_stmt_operands (cfun, gsi_stmt (i)); } free (bb->aux); Index: gcc/tree-ssa.c =================================================================== *** gcc/tree-ssa.c.orig 2013-11-29 11:45:49.000000000 +0100 --- gcc/tree-ssa.c 2013-11-29 13:10:18.124553965 +0100 *************** verify_ssa (bool check_modified_stmt) *** 1049,1055 **** goto err; } ! if (verify_ssa_operands (stmt)) { print_gimple_stmt (stderr, stmt, 0, TDF_VOPS); goto err; --- 1049,1055 ---- goto err; } ! if (verify_ssa_operands (cfun, stmt)) { print_gimple_stmt (stderr, stmt, 0, TDF_VOPS); goto err; *************** delete_tree_ssa (void) *** 1202,1208 **** /* We no longer maintain the SSA operand cache at this point. */ if (ssa_operands_active (cfun)) ! fini_ssa_operands (); htab_delete (cfun->gimple_df->default_defs); cfun->gimple_df->default_defs = NULL; --- 1202,1208 ---- /* We no longer maintain the SSA operand cache at this point. */ if (ssa_operands_active (cfun)) ! fini_ssa_operands (cfun); htab_delete (cfun->gimple_df->default_defs); cfun->gimple_df->default_defs = NULL; Index: gcc/gimple-pretty-print.c =================================================================== *** gcc/gimple-pretty-print.c.orig 2013-11-25 10:44:30.000000000 +0100 --- gcc/gimple-pretty-print.c 2013-11-29 13:15:18.252039795 +0100 *************** dump_gimple_mem_ops (pretty_printer *buf *** 2027,2036 **** tree vdef = gimple_vdef (gs); tree vuse = gimple_vuse (gs); - if (!ssa_operands_active (DECL_STRUCT_FUNCTION (current_function_decl)) - || !gimple_references_memory_p (gs)) - return; - if (vdef != NULL_TREE) { pp_string (buffer, "# "); --- 2027,2032 ---- Index: gcc/tree-ssanames.c =================================================================== *** gcc/tree-ssanames.c.orig 2013-11-29 09:40:27.000000000 +0100 --- gcc/tree-ssanames.c 2013-11-29 13:23:19.964630855 +0100 *************** get_nonzero_bits (const_tree name) *** 301,307 **** other fields must be assumed clobbered. */ void ! release_ssa_name (tree var) { if (!var) return; --- 301,307 ---- other fields must be assumed clobbered. */ void ! release_ssa_name_fn (struct function *fn, tree var) { if (!var) return; *************** release_ssa_name (tree var) *** 341,347 **** while (imm->next != imm) delink_imm_use (imm->next); ! (*SSANAMES (cfun))[SSA_NAME_VERSION (var)] = NULL_TREE; memset (var, 0, tree_size (var)); imm->prev = imm; --- 341,347 ---- while (imm->next != imm) delink_imm_use (imm->next); ! (*SSANAMES (fn))[SSA_NAME_VERSION (var)] = NULL_TREE; memset (var, 0, tree_size (var)); imm->prev = imm; *************** release_ssa_name (tree var) *** 363,369 **** SSA_NAME_IN_FREE_LIST (var) = 1; /* And finally put it on the free list. */ ! vec_safe_push (FREE_SSANAMES (cfun), var); } } --- 363,369 ---- SSA_NAME_IN_FREE_LIST (var) = 1; /* And finally put it on the free list. */ ! vec_safe_push (FREE_SSANAMES (fn), var); } } Index: gcc/tree-ssanames.h =================================================================== *** gcc/tree-ssanames.h.orig 2013-11-29 09:40:27.000000000 +0100 --- gcc/tree-ssanames.h 2013-11-29 13:18:50.121499386 +0100 *************** extern void init_ssanames (struct functi *** 81,87 **** extern void fini_ssanames (void); extern void ssanames_print_statistics (void); extern tree make_ssa_name_fn (struct function *, tree, gimple); ! extern void release_ssa_name (tree); extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *, unsigned int *); extern void mark_ptr_info_alignment_unknown (struct ptr_info_def *); --- 81,87 ---- extern void fini_ssanames (void); extern void ssanames_print_statistics (void); extern tree make_ssa_name_fn (struct function *, tree, gimple); ! extern void release_ssa_name_fn (struct function *, tree); extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *, unsigned int *); extern void mark_ptr_info_alignment_unknown (struct ptr_info_def *); *************** duplicate_ssa_name (tree var, gimple stm *** 127,132 **** --- 127,140 ---- return duplicate_ssa_name_fn (cfun, var, stmt); } + /* Release the SSA name NAME used in function cfun. */ + + static inline void + release_ssa_name (tree name) + { + release_ssa_name_fn (cfun, name); + } + /* Return an anonymous SSA_NAME node for type TYPE defined in statement STMT in function cfun. Arrange so that it uses NAME in dumps. */