diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-03-19 07:34:27 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-03-19 07:34:27 +0000 |
commit | 3b8f34f9b9122c1624a769815096ecab84be64ae (patch) | |
tree | c2285aa68ac7868c79874c1f3812b1c43f91f036 /gcc | |
parent | 8e013e9df091655c14069b3d90b78aed1396cbb9 (diff) | |
download | gcc-3b8f34f9b9122c1624a769815096ecab84be64ae.tar.gz |
2010-03-19 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 157557
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@157559 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
80 files changed, 2201 insertions, 725 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 866ad6dee3b..45a4634bca8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,305 @@ +2010-03-19 David S. Miller <davem@davemloft.net> + + With help from Eric Botcazou. + * config/sparc/sparc.c: Include dwarf2out.h. + (emit_pic_helper): Delete. + (pic_helper_symbol_name): Delete. + (pic_helper_emitted_p): Delete. + (pic_helper_needed): New. + (USE_HIDDEN_LINKONCE): Define to '1' if HAVE_GAS_HIDDEN else '0'. + (get_pc_thunk_name): New. + (load_pic_register): Remove 'delay_pic_helper' arg. Use + get_thunk_pc_name and ggc_strdup to generate PIC thunk symbol. + Set pic_helper_needed to true. Don't call emit_pic_helper. + (sparc_expand_prologue): Update load_pic_register call. + (sparc_output_mi_thunk): Likewise. + (sparc_file_end): Emit a hidden comdat symbol for the PIC + thunk if possible. Output CFI information as needed. + +2010-03-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + Jack Howarth <howarth@bromo.med.uc.edu> + + PR target/36399 + * gcc/config/i386/i386.h: Fix ABI on darwin x86-32. + +2010-03-18 Aldy Hernandez <aldyh@redhat.com> + + * tree.h: Declare make_decl_rtl_for_debug. + * varasm.c (make_decl_rtl_for_debug): New. + * dwarf2out.c (rtl_for_decl_location): Call it. + * cfgexpand.c (expand_debug_expr): Call it. + +2010-03-18 Jakub Jelinek <jakub@redhat.com> + + PR bootstrap/43399 + * var-tracking.c (adjust_mems) <case POST_MODIFY>: Allow BLKmode + mem_mode. + + PR bootstrap/43403 + * var-tracking.c (vt_init_cfa_base): Do nothing if + cfa_base_rtx would be hard_frame_pointer_rtx or non-fixed + register. + +2010-03-18 Alexandre Oliva <aoliva@redhat.com> + + PR debug/42873 + * var-tracking.c (canonicalize_vars_star): New. + (dataflow_post_merge_adjust): Use it. + +2010-03-18 Jakub Jelinek <jakub@redhat.com> + + PR debug/43058 + * var-tracking.c (non_suitable_const): New function. + (add_uses): For DEBUG_INSNs with constants, don't record any + value, instead just the constant value itself. + (compute_bb_dataflow) <case MO_VAL_LOC>: If PAT_VAR_LOCATION_LOC + is not VAR_LOC_UNKNOWN_P, set var to the constant. + (emit_notes_in_bb): Likewise. + (emit_note_insn_var_location): For onepart variables if + cur_loc is a VOIDmode constant, use DECL_MODE. + +2010-03-18 Martin Jambor <mjambor@suse.cz> + + PR middle-end/42450 + * cgraph.h (cgraph_redirect_edge_call_stmt_to_callee): Declare. + * cgraphunit.c (cgraph_materialize_all_clones): Update calls in + all non-clones. Moved call redirection... + (cgraph_redirect_edge_call_stmt_to_callee): ...to this new + function. + (cgraph_materialize_all_clones): Dispose of all + combined_args_to_skip bitmaps. + (verify_cgraph_node): Do not check for edges pointing to wrong + nodes in inline clones. + * tree-inline.c (copy_bb): Call + cgraph_redirect_edge_call_stmt_to_callee. + * ipa.c (cgraph_remove_unreachable_nodes): Call + cgraph_node_remove_callees even when there are used clones. + +2010-03-18 H.J. Lu <hongjiu.lu@intel.com> + + * config/i386/libgcc-glibc.ver: Make GCC_4.5.0 inherit GCC_4.4.0. + +2010-03-18 H.J. Lu <hongjiu.lu@intel.com> + + PR target/43383 + * config/i386/libgcc-glibc.ver: Add __extendxftf2 to GCC_4.5.0 + for 32bit. + +2010-03-18 Michael Matz <matz@suse.de> + + PR middle-end/43419 + * builtins.c (expand_builtin_pow): Don't transform pow(x, 0.5) + into sqrt(x) if we need to preserve signed zeros. + +2010-03-18 Steven Bosscher <steven@gcc.gnu.org> + Eric Botcazou <ebotcazou@adacore.com> + + PR rtl-optimization/43360 + * loop-invariant.c (move_invariant_reg): Remove the REG_EQUAL + note if we don't know its invariant status. + +2010-03-18 Michael Matz <matz@suse.de> + + PR tree-optimization/43402 + * tree-cfgcleanup.c (cleanup_control_expr_graph): Don't follow + PHI chains of ssa names registered for update. + +2010-03-17 Peter Bergner <bergner@vnet.ibm.com> + + PR target/42427 + * config/rs6000/rs6000.c (rs6000_split_multireg_move): Add support for + non-offsettable and pre_modify update addressing. + * config/rs6000/dfp.md (*movdd_hardfloat32): Make the "0", "1" + and "2" alternatives "#". + (*movdd_softfloat32): Make all alternatives "#"; + * config/rs6000/rs6000.md (DIFD): New define_mode_iterator. + (*movdf_hardfloat32): Make the "0", "1" and "2" alternatives "#". + (*movdf_softfloat32): Make all alternatives "#"; + (movdi): Use the new DIFD mode iterator to create a common splitter + for movdi, movdf and movdd patterns. + +2010-03-18 Shujing Zhao <pearly.zhao@oracle.com> + + * common.opt (dumpdir): Remove redundant tab. + +2010-03-17 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/43347 + * tree-sra.c (create_access_replacement): Set TREE_NO_WARNING when the + original base is DECL_ARTIFICIAL or DECL_IGNORED_P. + +2010-03-17 Bernd Schmidt <bernd.schmidt@analog.com> + + PR rtl-optimization/42216 + * regrename.c (create_new_chain): New function, broken out from... + (scan_rtx_reg): ... here. Call it. Handle the case where we are + appending a use to an empty chain. + (build_def_use): Remove previous changes that convert OP_INOUT to + OP_OUT operands; instead detect the case where an OP_INOUT operand + uses a previously untracked register and create an empty chain for + it. + +2010-03-17 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * doc/extend.texi (Function Attributes): Rewrite unfinished + sentence in ms_abi documentation. + +2010-03-17 Alan Modra <amodra@gmail.com> + + * config/rs6000/linux64.opt (mprofile-kernel): Use profile_kernel var. + * config/rs6000/linux64.h (TARGET_PROFILE_KERNEL): Define. + (SUBSUBTARGET_OVERRIDE_OPTIONS): Don't use SET_PROFILE_KERNEL. + * config/rs6000/rs6000.c (SET_PROFILE_KERNEL): Don't define. + +2010-03-16 Richard Henderson <rth@redhat.com> + + PR middle-end/43365 + * tree-eh.c (replace_goto_queue): Also replace in the eh_seq. + (lower_try_finally): Save and restore eh_seq around the expansion + of the try-finally. + +2010-03-16 Aldy Hernandez <aldyh@redhat.com> + + * graphite-sese-to-poly.c (split_reduction_stmt): Skip debug + statements before splitting block. + +2010-03-16 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * doc/sourcebuild.texi (Testsuites): Fix markup. + Use pathnames relative to gcc/testsuite. + (Test Directives): Move description of how timeout is determined. + (Ada Tests): Favor gnat.exp over ada/acats/tests/gcc. + (C Tests): Correct gcc.misc-tests directory. + Framework tests now live in gcc.test-framework. + +2010-03-16 Richard Guenther <rguenther@suse.de> + + PR middle-end/43379 + * tree-cfg.c (gimple_merge_blocks): When propagating virtual + PHI operands make sure to merge SSA_NAME_OCCURS_IN_ABNORMAL_PHI + properly. + +2010-03-16 Aldy Hernandez <aldyh@redhat.com> + Alexandre Oliva <aoliva@redhat.com> + + PR tree-optimization/42917 + * lambda-code.c (remove_iv): Skip debug statements. + (lambda_loopnest_to_gcc_loopnest): Likewise. + (not_interesting_stmt): Debug statements are not interesting. + +2010-03-16 Jakub Jelinek <jakub@redhat.com> + + PR debug/43051 + PR debug/43092 + * cselib.c (cselib_preserve_constants, + cfa_base_preserved_val): New static variables. + (preserve_only_constants): New function. + (cselib_reset_table): If cfa_base_preserved_val is non-NULL, don't + clear its REG_VALUES. If cselib_preserve_constants, don't + empty the whole hash table, but preserve there VALUEs with constants, + cfa_base_preserved_val and cfa_base_preserved_val plus constant. + (cselib_preserve_cfa_base_value): New function. + (cselib_invalidate_regno): Don't invalidate cfa_base_preserved_val. + (cselib_init): Change argument to int bitfield. Set + cselib_preserve_constants to whether CSELIB_PRESERVE_CONSTANTS + is in it. + (cselib_finish): Clear cselib_preserve_constants and + cfa_base_preserved_val. + * cselib.h (enum cselib_record_what): New enum. + (cselib_init): Change argument to int. + (cselib_preserve_cfa_base_value): New prototype. + * postreload.c (reload_cse_regs_1): Adjust cselib_init caller. + * dse.c (dse_step1): Likewise. + * cfgcleanup.c (thread_jump): Likewise. + * sched-deps.c (sched_analyze): Likewise. + * gcse.c (local_cprop_pass): Likewise. + * simplify-rtx.c (simplify_replace_fn_rtx): Add argument to callback. + If FN is non-NULL, call the callback always and whenever it returns + non-NULL just return that. Only do rtx_equal_p if FN is NULL. + * rtl.h (simplify_replace_fn_rtx): Add argument to callback. + * combine.c (propagate_for_debug_subst): Add old_rtx argument, + compare from with old_rtx and if it isn't rtx_equal_p, return NULL. + * Makefile.in (var-tracking.o): Depend on $(RECOG_H). + * var-tracking.c: Include recog.h. + (bb_stack_adjust_offset): Remove. + (vt_stack_adjustments): Don't call it, instead just gather the + adjustments using insn_stack_adjust_offset_pre_post on each bb insn. + (adjust_stack_reference): Remove. + (compute_cfa_pointer): New function. + (hard_frame_pointer_adjustment, cfa_base_rtx): New static variables. + (struct adjust_mem_data): New type. + (adjust_mems, adjust_mem_uses, adjust_mem_stores, adjust_insn): New + functions. + (get_address_mode): New function. + (replace_expr_with_values): Use it. + (use_type): Don't do cselib_lookup for VAR_LOC_UNKNOWN_P. + Use get_address_mode. For cfa_base_rtx return MO_CLOBBER. + (adjust_sets): Remove. + (add_uses): Don't add extra MO_VAL_USE for cfa_base_rtx plus constant. + Use get_address_mode. + (get_adjusted_src): Remove. + (add_stores): Don't call it. Never reuse expr SET. Don't add extra + MO_VAL_USE for cfa_base_rtx plus constant. Use get_address_mode. + (add_with_sets): Don't call adjust_sets. + (fp_setter, vt_init_cfa_base): New functions. + (vt_initialize): Change return type to bool. Move most of pool etc. + initialization to the beginning of the function from end. Pass + CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS to cselib_init. + If !frame_pointer_needed, call vt_stack_adjustment before mos + vector is filled, call vt_init_cfa_base if argp/framep has been + eliminated to sp. If frame_pointer_needed and argp/framep has + been eliminated to hard frame pointer, set + hard_frame_pointer_adjustment and call vt_init_cfa_base after + encountering fp setter in the prologue. For MO_ADJUST, call + log_op_type before pusing the op into mos vector, not afterwards. + Call adjust_insn before cselib_process_insn/add_with_sets, + call cancel_changes (0) afterwards. + (variable_tracking_main_1): Adjust for vt_initialize calling + vt_stack_adjustments and returning whether it succeeded or not. + +2010-03-15 Aldy Hernandez <aldyh@redhat.com> + + * graphite-sese-to-poly.c (rewrite_cross_bb_scalar_deps): Skip + debug statements. + +2010-03-15 Jakub Jelinek <jakub@redhat.com> + + * dwarf2out.c (dwarf2out_frame_debug): Don't assert drap_reg + has been set. + (based_loc_descr): Use DW_OP_fbreg for vdrap_reg even when + drap_reg has not been set. + +2010-03-15 Michael Matz <matz@suse.de> + + PR middle-end/43300 + * tree-outof-ssa.c (emit_partition_copy): New argument sizeexp, + use it to expand block copies. + (insert_partition_copy_on_edge, insert_rtx_to_part_on_edge, + insert_part_to_rtx_on_edge): Adjust callers of emit_partition_copy. + (insert_value_copy_on_edge): Use store_expr for BLKmode values. + +2010-03-15 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/43367 + * tree-cfg.c (gimple_can_merge_blocks_p): Simplify PHI + elimination check. + +2010-03-15 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/43317 + * ipa-struct-reorg.c (create_new_general_access): Update stmt. + +2010-03-15 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/43141 + * tree-sra.c (create_abstract_origin): New function. + (modify_function): Call create_abstract_origin. + +2010-03-15 Chris Demetriou <cgd@google.com> + + * Makefile.in (stmp-int-hdrs): Don't chmod include/stdint.h if it + wasn't copied. + 2010-03-13 Sebastian Pop <sebastian.pop@amd.com> PR middle-end/43354 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7045fdbbfaf..b84b20bd6db 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20100315 +20100319 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index b1362982f0b..c5803ced5e7 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3072,7 +3072,8 @@ var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h $(FLAGS_H) \ $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \ $(REGS_H) $(EXPR_H) $(TIMEVAR_H) $(TREE_PASS_H) $(TREE_FLOW_H) \ - cselib.h $(TARGET_H) $(TOPLEV_H) $(PARAMS_H) $(DIAGNOSTIC_H) pointer-set.h + cselib.h $(TARGET_H) $(TOPLEV_H) $(PARAMS_H) $(DIAGNOSTIC_H) pointer-set.h \ + $(RECOG_H) profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) $(FUNCTION_H) \ $(TOPLEV_H) $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h cfghooks.h \ @@ -3901,10 +3902,11 @@ stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) $(UNWIND_H) fixinc_list cp $(srcdir)/ginclude/stdint-gcc.h include/stdint-gcc.h; \ chmod a+r include/stdint-gcc.h; \ cp $(srcdir)/ginclude/stdint-wrap.h include/stdint.h; \ + chmod a+r include/stdint.h; \ elif [ $(USE_GCC_STDINT) = provide ]; then \ cp $(srcdir)/ginclude/stdint-gcc.h include/stdint.h; \ + chmod a+r include/stdint.h; \ fi - chmod a+r include/stdint.h set -e; for ml in `cat fixinc_list`; do \ sysroot_headers_suffix=`echo $${ml} | sed -e 's/;.*$$//'`; \ multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \ diff --git a/gcc/builtins.c b/gcc/builtins.c index 1e089ef99c4..705a25598b0 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -2980,7 +2980,10 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget) && ((flag_unsafe_math_optimizations && optimize_insn_for_speed_p () && powi_cost (n/2) <= POWI_MAX_MULTS) - || n == 1)) + /* Even the c==0.5 case cannot be done unconditionally + when we need to preserve signed zeros, as + pow (-0, 0.5) is +0, while sqrt(-0) is -0. */ + || (!HONOR_SIGNED_ZEROS (mode) && n == 1))) { tree call_expr = build_call_nofold (fn, 1, narg0); /* Use expand_expr in case the newly built call expression diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index ffe36e45a9e..01b165a701a 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -1,6 +1,6 @@ /* Control flow optimization code for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -337,7 +337,7 @@ thread_jump (edge e, basic_block b) return NULL; } - cselib_init (false); + cselib_init (0); /* First process all values computed in the source basic block. */ for (insn = NEXT_INSN (BB_HEAD (e->src)); diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index ee145993404..fcae897a392 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -2339,8 +2339,7 @@ expand_debug_expr (tree exp) || mode == VOIDmode) return NULL; - op0 = DECL_RTL (exp); - SET_DECL_RTL (exp, NULL); + op0 = make_decl_rtl_for_debug (exp); if (!MEM_P (op0) || GET_CODE (XEXP (op0, 0)) != SYMBOL_REF || SYMBOL_REF_DECL (XEXP (op0, 0)) != exp) diff --git a/gcc/cgraph.h b/gcc/cgraph.h index f8d52ebc560..4f0c333a3f4 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -534,7 +534,7 @@ void cgraph_remove_edge_duplication_hook (struct cgraph_2edge_hook_list *); struct cgraph_2node_hook_list *cgraph_add_node_duplication_hook (cgraph_2node_hook, void *); void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *); void cgraph_materialize_all_clones (void); - +gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *); /* In cgraphbuild.c */ unsigned int rebuild_cgraph_edges (void); void reset_inline_failed (struct cgraph_node *); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index f4580adbd75..c41477bede3 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -751,8 +751,9 @@ verify_cgraph_node (struct cgraph_node *node) debug_tree (e->callee->decl); error_found = true; } - else if (!clone_of_p (cgraph_node (decl), e->callee) - && !e->callee->global.inlined_to) + else if (!node->global.inlined_to + && !e->callee->global.inlined_to + && !clone_of_p (cgraph_node (decl), e->callee)) { error ("edge points to wrong declaration:"); debug_tree (e->callee->decl); @@ -2222,11 +2223,60 @@ cgraph_materialize_clone (struct cgraph_node *node) bitmap_obstack_release (NULL); } +/* If necessary, change the function declaration in the call statement + associated with E so that it corresponds to the edge callee. */ + +gimple +cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) +{ + tree decl = gimple_call_fndecl (e->call_stmt); + gimple new_stmt; + gimple_stmt_iterator gsi; + + if (!decl || decl == e->callee->decl + /* Don't update call from same body alias to the real function. */ + || cgraph_get_node (decl) == cgraph_get_node (e->callee->decl)) + return e->call_stmt; + + if (cgraph_dump_file) + { + fprintf (cgraph_dump_file, "updating call of %s/%i -> %s/%i: ", + cgraph_node_name (e->caller), e->caller->uid, + cgraph_node_name (e->callee), e->callee->uid); + print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags); + } + + if (e->callee->clone.combined_args_to_skip) + new_stmt = gimple_call_copy_skip_args (e->call_stmt, + e->callee->clone.combined_args_to_skip); + else + new_stmt = e->call_stmt; + if (gimple_vdef (new_stmt) + && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME) + SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; + gimple_call_set_fndecl (new_stmt, e->callee->decl); + + gsi = gsi_for_stmt (e->call_stmt); + gsi_replace (&gsi, new_stmt, true); + + /* Update EH information too, just in case. */ + maybe_clean_or_replace_eh_stmt (e->call_stmt, new_stmt); + + cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt); + + if (cgraph_dump_file) + { + fprintf (cgraph_dump_file, " updated to:"); + print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags); + } + return new_stmt; +} + /* Once all functions from compilation unit are in memory, produce all clones - and update all calls. - We might also do this on demand if we don't want to bring all functions to - memory prior compilation, but current WHOPR implementation does that and it is - is bit easier to keep everything right in this order. */ + and update all calls. We might also do this on demand if we don't want to + bring all functions to memory prior compilation, but current WHOPR + implementation does that and it is is bit easier to keep everything right in + this order. */ void cgraph_materialize_all_clones (void) { @@ -2302,69 +2352,28 @@ cgraph_materialize_all_clones (void) if (cgraph_dump_file) fprintf (cgraph_dump_file, "Updating call sites\n"); for (node = cgraph_nodes; node; node = node->next) - if (node->analyzed && gimple_has_body_p (node->decl) - && (!node->clone_of || node->clone_of->decl != node->decl)) + if (node->analyzed && !node->clone_of + && gimple_has_body_p (node->decl)) { struct cgraph_edge *e; current_function_decl = node->decl; push_cfun (DECL_STRUCT_FUNCTION (node->decl)); for (e = node->callees; e; e = e->next_callee) - { - tree decl = gimple_call_fndecl (e->call_stmt); - /* When function gets inlined, indirect inlining might've invented - new edge for orginally indirect stmt. Since we are not - preserving clones in the original form, we must not update here - since other inline clones don't need to contain call to the same - call. Inliner will do the substitution for us later. */ - if (decl && decl != e->callee->decl) - { - gimple new_stmt; - gimple_stmt_iterator gsi; - - if (cgraph_get_node (decl) == cgraph_get_node (e->callee->decl)) - /* Don't update call from same body alias to the real function. */ - continue; - - if (cgraph_dump_file) - { - fprintf (cgraph_dump_file, "updating call of %s in %s:", - cgraph_node_name (node), - cgraph_node_name (e->callee)); - print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags); - } - - if (e->callee->clone.combined_args_to_skip) - new_stmt = gimple_call_copy_skip_args (e->call_stmt, - e->callee->clone.combined_args_to_skip); - else - new_stmt = e->call_stmt; - if (gimple_vdef (new_stmt) - && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME) - SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; - gimple_call_set_fndecl (new_stmt, e->callee->decl); - - gsi = gsi_for_stmt (e->call_stmt); - gsi_replace (&gsi, new_stmt, true); - - /* Update EH information too, just in case. */ - maybe_clean_or_replace_eh_stmt (e->call_stmt, new_stmt); - - cgraph_set_call_stmt_including_clones (node, e->call_stmt, new_stmt); - - if (cgraph_dump_file) - { - fprintf (cgraph_dump_file, " updated to:"); - print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags); - } - } - } + cgraph_redirect_edge_call_stmt_to_callee (e); pop_cfun (); current_function_decl = NULL; #ifdef ENABLE_CHECKING verify_cgraph_node (node); #endif } + if (cgraph_dump_file) + fprintf (cgraph_dump_file, "Materialization Call site updates done.\n"); + /* All changes to parameters have been performed. In order not to + incorrectly repeat them, we simply dispose of the bitmaps that drive the + changes. */ + for (node = cgraph_nodes; node; node = node->next) + node->clone.combined_args_to_skip = NULL; #ifdef ENABLE_CHECKING verify_cgraph (); #endif diff --git a/gcc/combine.c b/gcc/combine.c index e5d4c5aafc2..f4f2fa06fdb 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1,6 +1,6 @@ /* Optimize by combining instructions for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -2286,10 +2286,12 @@ struct rtx_subst_pair substituted. */ static rtx -propagate_for_debug_subst (rtx from ATTRIBUTE_UNUSED, void *data) +propagate_for_debug_subst (rtx from, const_rtx old_rtx, void *data) { struct rtx_subst_pair *pair = (struct rtx_subst_pair *)data; + if (!rtx_equal_p (from, old_rtx)) + return NULL_RTX; if (!pair->adjusted) { pair->adjusted = true; diff --git a/gcc/common.opt b/gcc/common.opt index 75e564f5e04..13c7a76f3d1 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -255,7 +255,7 @@ Common Separate dumpdir Common Separate --dumpdir <dir> Set the directory name to be used for dumps +-dumpdir <dir> Set the directory name to be used for dumps ; The version of the C++ ABI in use. The following values are allowed: ; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 962a14c8005..fa94091930e 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1810,7 +1810,7 @@ typedef struct ix86_args { #define X86_64_SSE_REGPARM_MAX 8 #define X86_64_MS_SSE_REGPARM_MAX 4 -#define X86_32_SSE_REGPARM_MAX (TARGET_SSE ? 3 : 0) +#define X86_32_SSE_REGPARM_MAX (TARGET_SSE ? (TARGET_MACHO ? 4 : 3) : 0) #define SSE_REGPARM_MAX \ (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? X86_64_MS_SSE_REGPARM_MAX \ diff --git a/gcc/config/i386/libgcc-glibc.ver b/gcc/config/i386/libgcc-glibc.ver index 5565fe31893..2a2ddcd1df8 100644 --- a/gcc/config/i386/libgcc-glibc.ver +++ b/gcc/config/i386/libgcc-glibc.ver @@ -180,4 +180,10 @@ GCC_4.4.0 { __trunctfxf2 __unordtf2 } +# It is OK to have a duplicate of %inherit in libgcc-std.ver since +# mkmap-symver.awk always takes the last %inherit statement. +%inherit GCC_4.5.0 GCC_4.4.0 +GCC_4.5.0 { + __extendxftf2 +} %endif diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md index 96da57c319c..8326d6be0a6 100644 --- a/gcc/config/rs6000/dfp.md +++ b/gcc/config/rs6000/dfp.md @@ -293,71 +293,9 @@ default: gcc_unreachable (); case 0: - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register - of operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\"; case 1: - if (rs6000_offsettable_memref_p (operands[1]) - || (GET_CODE (operands[1]) == MEM - && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM - || GET_CODE (XEXP (operands[1], 0)) == PRE_INC - || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC))) - { - /* If the low-address word is used in the address, we must load - it last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is - known to be dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; - else - return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\"; - } - else - { - rtx addreg; - - addreg = find_addr_reg (XEXP (operands[1], 0)); - if (refers_to_regno_p (REGNO (operands[0]), - REGNO (operands[0]) + 1, - operands[1], 0)) - { - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{lx|lwzx} %L0,%1\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"{lx|lwzx} %0,%1\"; - } - else - { - output_asm_insn (\"{lx|lwzx} %0,%1\", operands); - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{lx|lwzx} %L0,%1\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"\"; - } - } case 2: - if (rs6000_offsettable_memref_p (operands[0]) - || (GET_CODE (operands[0]) == MEM - && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM - || GET_CODE (XEXP (operands[0], 0)) == PRE_INC - || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))) - return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\"; - else - { - rtx addreg; - - addreg = find_addr_reg (XEXP (operands[0], 0)); - output_asm_insn (\"{stx|stwx} %1,%0\", operands); - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{stx|stwx} %L1,%0\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"\"; - } + return \"#\"; case 3: return \"fmr %0,%1\"; case 4: @@ -379,38 +317,7 @@ "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS) && (gpc_reg_operand (operands[0], DDmode) || gpc_reg_operand (operands[1], DDmode))" - "* -{ - switch (which_alternative) - { - default: - gcc_unreachable (); - case 0: - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register of - operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\"; - case 1: - /* If the low-address word is used in the address, we must load - it last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is - known to be dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; - else - return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\"; - case 2: - return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\"; - case 3: - case 4: - case 5: - return \"#\"; - } -}" + "#" [(set_attr "type" "two,load,store,*,*,*") (set_attr "length" "8,8,8,8,12,16")]) diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index 37148c6aec6..da7bca3037c 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -1,7 +1,7 @@ /* Definitions of target machine for GNU compiler, for 64 bit PowerPC linux. Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009 Free Software Foundation, Inc. + 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -61,6 +61,8 @@ extern int dot_symbols; #define DOT_SYMBOLS dot_symbols #endif +#define TARGET_PROFILE_KERNEL profile_kernel + #undef PROCESSOR_DEFAULT #define PROCESSOR_DEFAULT PROCESSOR_POWER6 #undef PROCESSOR_DEFAULT64 @@ -119,7 +121,7 @@ extern int dot_symbols; error (INVALID_32BIT, "32"); \ if (TARGET_PROFILE_KERNEL) \ { \ - SET_PROFILE_KERNEL (0); \ + TARGET_PROFILE_KERNEL = 0; \ error (INVALID_32BIT, "profile-kernel"); \ } \ } \ diff --git a/gcc/config/rs6000/linux64.opt b/gcc/config/rs6000/linux64.opt index 1eac7382aa0..0d52820691c 100644 --- a/gcc/config/rs6000/linux64.opt +++ b/gcc/config/rs6000/linux64.opt @@ -1,6 +1,6 @@ ; Options for 64-bit PowerPC Linux. ; -; Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc. +; Copyright (C) 2005, 2007, 2009, 2010 Free Software Foundation, Inc. ; Contributed by Aldy Hernandez <aldy@quesejoda.com>. ; ; This file is part of GCC. @@ -20,5 +20,5 @@ ; <http://www.gnu.org/licenses/>. mprofile-kernel -Target Report Var(TARGET_PROFILE_KERNEL) +Target Report Var(profile_kernel) Call mcount for profiling before a function prologue diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index ce38a8a9d9a..dea0271b91a 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1269,9 +1269,6 @@ static const struct attribute_spec rs6000_attribute_table[] = #endif #ifndef TARGET_PROFILE_KERNEL #define TARGET_PROFILE_KERNEL 0 -#define SET_PROFILE_KERNEL(N) -#else -#define SET_PROFILE_KERNEL(N) TARGET_PROFILE_KERNEL = (N) #endif /* The VRSAVE bitmask puts bit %v0 as the most significant bit. */ @@ -16727,6 +16724,7 @@ rs6000_split_multireg_move (rtx dst, rtx src) int i; int j = -1; bool used_update = false; + rtx restore_basereg = NULL_RTX; if (MEM_P (src) && INT_REGNO_P (reg)) { @@ -16745,10 +16743,27 @@ rs6000_split_multireg_move (rtx dst, rtx src) } else if (! rs6000_offsettable_memref_p (src)) { - rtx basereg; - basereg = gen_rtx_REG (Pmode, reg); - emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0))); - src = replace_equiv_address (src, basereg); + if (GET_CODE (XEXP (src, 0)) == PRE_MODIFY) + { + rtx basereg = XEXP (XEXP (src, 0), 0); + if (TARGET_UPDATE) + { + rtx ndst = simplify_gen_subreg (reg_mode, dst, mode, 0); + emit_insn (gen_rtx_SET (VOIDmode, ndst, + gen_rtx_MEM (reg_mode, XEXP (src, 0)))); + used_update = true; + } + else + emit_insn (gen_rtx_SET (VOIDmode, basereg, + XEXP (XEXP (src, 0), 1))); + src = replace_equiv_address (src, basereg); + } + else + { + rtx basereg = gen_rtx_REG (Pmode, reg); + emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0))); + src = replace_equiv_address (src, basereg); + } } breg = XEXP (src, 0); @@ -16762,8 +16777,7 @@ rs6000_split_multireg_move (rtx dst, rtx src) && REGNO (breg) < REGNO (dst) + nregs) j = REGNO (breg) - REGNO (dst); } - - if (GET_CODE (dst) == MEM && INT_REGNO_P (reg)) + else if (MEM_P (dst) && INT_REGNO_P (reg)) { rtx breg; @@ -16793,7 +16807,34 @@ rs6000_split_multireg_move (rtx dst, rtx src) emit_insn (gen_add3_insn (breg, breg, delta_rtx)); dst = replace_equiv_address (dst, breg); } - else + else if (!rs6000_offsettable_memref_p (dst) + && GET_CODE (XEXP (dst, 0)) != LO_SUM) + { + if (GET_CODE (XEXP (dst, 0)) == PRE_MODIFY) + { + rtx basereg = XEXP (XEXP (dst, 0), 0); + if (TARGET_UPDATE) + { + rtx nsrc = simplify_gen_subreg (reg_mode, src, mode, 0); + emit_insn (gen_rtx_SET (VOIDmode, + gen_rtx_MEM (reg_mode, XEXP (dst, 0)), nsrc)); + used_update = true; + } + else + emit_insn (gen_rtx_SET (VOIDmode, basereg, + XEXP (XEXP (dst, 0), 1))); + dst = replace_equiv_address (dst, basereg); + } + else + { + rtx basereg = XEXP (XEXP (dst, 0), 0); + rtx offsetreg = XEXP (XEXP (dst, 0), 1); + emit_insn (gen_add3_insn (basereg, basereg, offsetreg)); + restore_basereg = gen_sub3_insn (basereg, basereg, offsetreg); + dst = replace_equiv_address (dst, basereg); + } + } + else if (GET_CODE (XEXP (dst, 0)) != LO_SUM) gcc_assert (rs6000_offsettable_memref_p (dst)); } @@ -16815,6 +16856,8 @@ rs6000_split_multireg_move (rtx dst, rtx src) simplify_gen_subreg (reg_mode, src, mode, j * reg_mode_size))); } + if (restore_basereg != NULL_RTX) + emit_insn (restore_basereg); } } diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 08475b65e54..50c4d618053 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -217,6 +217,9 @@ (DD "TARGET_DFP") (TD "TARGET_DFP")]) +; These modes do not fit in integer registers in 32-bit mode. +(define_mode_iterator DIFD [DI DF DD]) + ; Various instructions that come in SI and DI forms. ; A generic w/d attribute, for things like cmpw/cmpd. (define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")]) @@ -9148,73 +9151,9 @@ default: gcc_unreachable (); case 0: - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register - of operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\"; case 1: - if (rs6000_offsettable_memref_p (operands[1]) - || (GET_CODE (operands[1]) == MEM - && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM - || GET_CODE (XEXP (operands[1], 0)) == PRE_INC - || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC - || GET_CODE (XEXP (operands[1], 0)) == PRE_MODIFY))) - { - /* If the low-address word is used in the address, we must load - it last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is - known to be dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; - else - return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\"; - } - else - { - rtx addreg; - - addreg = find_addr_reg (XEXP (operands[1], 0)); - if (refers_to_regno_p (REGNO (operands[0]), - REGNO (operands[0]) + 1, - operands[1], 0)) - { - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"{l%X1|lwz%X1} %0,%1\"; - } - else - { - output_asm_insn (\"{l%X1|lwz%X1} %0,%1\", operands); - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"\"; - } - } case 2: - if (rs6000_offsettable_memref_p (operands[0]) - || (GET_CODE (operands[0]) == MEM - && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM - || GET_CODE (XEXP (operands[0], 0)) == PRE_INC - || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC - || GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY))) - return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\"; - else - { - rtx addreg; - - addreg = find_addr_reg (XEXP (operands[0], 0)); - output_asm_insn (\"{st%X0|stw%X0} %1,%0\", operands); - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{st%X0|stw%X0} %L1,%0\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"\"; - } + return \"#\"; case 3: case 4: return \"xxlor %x0,%x1,%x1\"; @@ -9249,38 +9188,7 @@ || TARGET_SOFT_FLOAT || TARGET_E500_SINGLE) && (gpc_reg_operand (operands[0], DFmode) || gpc_reg_operand (operands[1], DFmode))" - "* -{ - switch (which_alternative) - { - default: - gcc_unreachable (); - case 0: - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register of - operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\"; - case 1: - /* If the low-address word is used in the address, we must load - it last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is - known to be dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; - else - return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\"; - case 2: - return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\"; - case 3: - case 4: - case 5: - return \"#\"; - } -}" + "#" [(set_attr "type" "two,load,store,*,*,*") (set_attr "length" "8,8,8,8,12,16")]) @@ -9729,8 +9637,8 @@ }") (define_split - [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "") - (match_operand:DI 1 "input_operand" ""))] + [(set (match_operand:DIFD 0 "rs6000_nonimmediate_operand" "") + (match_operand:DIFD 1 "input_operand" ""))] "reload_completed && !TARGET_POWERPC64 && gpr_or_gpr_p (operands[0], operands[1])" [(pc)] diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index e4ef862c96d..38711d3d72e 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "params.h" #include "df.h" +#include "dwarf2out.h" /* Processor costs */ static const @@ -362,8 +363,7 @@ static rtx sparc_builtin_saveregs (void); static int epilogue_renumber (rtx *, int); static bool sparc_assemble_integer (rtx, unsigned int, int); static int set_extends (rtx); -static void emit_pic_helper (void); -static void load_pic_register (bool); +static void load_pic_register (void); static int save_or_restore_regs (int, int, rtx, int, int); static void emit_save_or_restore_regs (int); static void sparc_asm_function_prologue (FILE *, HOST_WIDE_INT); @@ -2908,9 +2908,8 @@ sparc_cannot_force_const_mem (rtx x) } /* PIC support. */ -static GTY(()) char pic_helper_symbol_name[256]; +static GTY(()) bool pic_helper_needed = false; static GTY(()) rtx pic_helper_symbol; -static GTY(()) bool pic_helper_emitted_p = false; static GTY(()) rtx global_offset_table; /* Ensure that we are not using patterns that are not OK with PIC. */ @@ -3521,34 +3520,31 @@ sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, return x; } -/* Emit the special PIC helper function. */ +#ifdef HAVE_GAS_HIDDEN +# define USE_HIDDEN_LINKONCE 1 +#else +# define USE_HIDDEN_LINKONCE 0 +#endif static void -emit_pic_helper (void) +get_pc_thunk_name (char name[32], unsigned int regno) { - const char *pic_name = reg_names[REGNO (pic_offset_table_rtx)]; - int align; + const char *pic_name = reg_names[regno]; - switch_to_section (text_section); + /* Skip the leading '%' as that cannot be used in a + symbol name. */ + pic_name += 1; - align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); - if (align > 0) - ASM_OUTPUT_ALIGN (asm_out_file, align); - ASM_OUTPUT_LABEL (asm_out_file, pic_helper_symbol_name); - if (flag_delayed_branch) - fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n", - pic_name, pic_name); + if (USE_HIDDEN_LINKONCE) + sprintf (name, "__sparc_get_pc_thunk.%s", pic_name); else - fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n", - pic_name, pic_name); - - pic_helper_emitted_p = true; + ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC", regno); } /* Emit code to load the PIC register. */ static void -load_pic_register (bool delay_pic_helper) +load_pic_register (void) { int orig_flag_pic = flag_pic; @@ -3560,18 +3556,18 @@ load_pic_register (bool delay_pic_helper) } /* If we haven't initialized the special PIC symbols, do so now. */ - if (!pic_helper_symbol_name[0]) + if (!pic_helper_needed) { - ASM_GENERATE_INTERNAL_LABEL (pic_helper_symbol_name, "LADDPC", 0); - pic_helper_symbol = gen_rtx_SYMBOL_REF (Pmode, pic_helper_symbol_name); + char name[32]; + + pic_helper_needed = true; + + get_pc_thunk_name (name, REGNO (pic_offset_table_rtx)); + pic_helper_symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name)); + global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); } - /* If we haven't emitted the special PIC helper function, do so now unless - we are requested to delay it. */ - if (!delay_pic_helper && !pic_helper_emitted_p) - emit_pic_helper (); - flag_pic = 0; if (TARGET_ARCH64) emit_insn (gen_load_pcrel_symdi (pic_offset_table_rtx, global_offset_table, @@ -4221,7 +4217,7 @@ sparc_expand_prologue (void) /* Load the PIC register if needed. */ if (flag_pic && crtl->uses_pic_offset_table) - load_pic_register (false); + load_pic_register (); } /* This function generates the assembly code for function entry, which boils @@ -8882,7 +8878,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, start_sequence (); /* Delay emitting the PIC helper function because it needs to change the section and we are emitting assembly code. */ - load_pic_register (true); /* clobbers %o7 */ + load_pic_register (); /* clobbers %o7 */ scratch = legitimize_pic_address (funexp, scratch); seq = get_insns (); end_sequence (); @@ -9037,9 +9033,59 @@ sparc_output_dwarf_dtprel (FILE *file, int size, rtx x) static void sparc_file_end (void) { - /* If we haven't emitted the special PIC helper function, do so now. */ - if (pic_helper_symbol_name[0] && !pic_helper_emitted_p) - emit_pic_helper (); + /* If need to emit the special PIC helper function, do so now. */ + if (pic_helper_needed) + { + unsigned int regno = REGNO (pic_offset_table_rtx); + const char *pic_name = reg_names[regno]; + char name[32]; +#ifdef DWARF2_UNWIND_INFO + bool do_cfi; +#endif + + get_pc_thunk_name (name, regno); + if (USE_HIDDEN_LINKONCE) + { + tree decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, + get_identifier (name), + build_function_type (void_type_node, + void_list_node)); + DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL, + NULL_TREE, void_type_node); + TREE_STATIC (decl) = 1; + make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl)); + DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; + DECL_VISIBILITY_SPECIFIED (decl) = 1; + allocate_struct_function (decl, true); + current_function_decl = decl; + init_varasm_status (); + assemble_start_function (decl, name); + } + else + { + const int align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); + switch_to_section (text_section); + if (align > 0) + ASM_OUTPUT_ALIGN (asm_out_file, align); + ASM_OUTPUT_LABEL (asm_out_file, name); + } + +#ifdef DWARF2_UNWIND_INFO + do_cfi = dwarf2out_do_cfi_asm (); + if (do_cfi) + fprintf (asm_out_file, "\t.cfi_startproc\n"); +#endif + if (flag_delayed_branch) + fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n", + pic_name, pic_name); + else + fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n", + pic_name, pic_name); +#ifdef DWARF2_UNWIND_INFO + if (do_cfi) + fprintf (asm_out_file, "\t.cfi_endproc\n"); +#endif + } if (NEED_INDICATE_EXEC_STACK) file_end_indicate_exec_stack (); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 214f36f2405..eecdd1a1941 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2010-03-18 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/43418 + * parser.c (cp_parser_for_init_statement): Use NULL_TREE, not + false, in the cp_parser_expression_statement call. + 2010-03-05 Jason Merrill <jason@redhat.com> * mangle.c (mangle_decl): Give name collision error even without @@ -11,6 +17,11 @@ 2010-03-03 Jason Merrill <jason@redhat.com> PR c++/12909 + * mangle.c (mangle_decl): Handle VAR_DECL, too. + +2010-03-03 Jason Merrill <jason@redhat.com> + + PR c++/12909 * mangle.c: Include cgraph.h. (mangle_decl): If the mangled name will change in a later ABI version, make the later mangled name an alias. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 55d05174eee..d27d12254ca 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -8352,7 +8352,7 @@ cp_parser_for_init_statement (cp_parser* parser) return; } - cp_parser_expression_statement (parser, false); + cp_parser_expression_statement (parser, NULL_TREE); } /* Parse a jump-statement. diff --git a/gcc/cselib.c b/gcc/cselib.c index f63ea3f5f1c..9073b9928be 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "target.h" static bool cselib_record_memory; +static bool cselib_preserve_constants; static int entry_and_rtx_equal_p (const void *, const void *); static hashval_t get_value_hash (const void *); static struct elt_list *new_elt_list (struct elt_list *, cselib_val *); @@ -135,6 +136,11 @@ static int values_became_useless; presence in the list by checking the next pointer. */ static cselib_val dummy_val; +/* If non-NULL, value of the eliminated arg_pointer_rtx or frame_pointer_rtx + that is constant through the whole function and should never be + eliminated. */ +static cselib_val *cfa_base_preserved_val; + /* Used to list all values that contain memory reference. May or may not contain the useless values - the list is compacted each time memory is invalidated. */ @@ -229,6 +235,35 @@ cselib_clear_table (void) cselib_reset_table (1); } +/* Remove from hash table all VALUEs except constants. */ + +static int +preserve_only_constants (void **x, void *info ATTRIBUTE_UNUSED) +{ + cselib_val *v = (cselib_val *)*x; + + if (v->locs != NULL + && v->locs->next == NULL) + { + if (CONSTANT_P (v->locs->loc) + && (GET_CODE (v->locs->loc) != CONST + || !references_value_p (v->locs->loc, 0))) + return 1; + if (cfa_base_preserved_val) + { + if (v == cfa_base_preserved_val) + return 1; + if (GET_CODE (v->locs->loc) == PLUS + && CONST_INT_P (XEXP (v->locs->loc, 1)) + && XEXP (v->locs->loc, 0) == cfa_base_preserved_val->val_rtx) + return 1; + } + } + + htab_clear_slot (cselib_hash_table, x); + return 1; +} + /* Remove all entries from the hash table, arranging for the next value to be numbered NUM. */ @@ -237,15 +272,37 @@ cselib_reset_table (unsigned int num) { unsigned int i; - for (i = 0; i < n_used_regs; i++) - REG_VALUES (used_regs[i]) = 0; - max_value_regs = 0; - n_used_regs = 0; + if (cfa_base_preserved_val) + { + unsigned int regno = REGNO (cfa_base_preserved_val->locs->loc); + unsigned int new_used_regs = 0; + for (i = 0; i < n_used_regs; i++) + if (used_regs[i] == regno) + { + new_used_regs = 1; + continue; + } + else + REG_VALUES (used_regs[i]) = 0; + gcc_assert (new_used_regs == 1); + n_used_regs = new_used_regs; + used_regs[0] = regno; + max_value_regs + = hard_regno_nregs[regno][GET_MODE (cfa_base_preserved_val->locs->loc)]; + } + else + { + for (i = 0; i < n_used_regs; i++) + REG_VALUES (used_regs[i]) = 0; + n_used_regs = 0; + } - /* ??? Preserve constants? */ - htab_empty (cselib_hash_table); + if (cselib_preserve_constants) + htab_traverse (cselib_hash_table, preserve_only_constants, NULL); + else + htab_empty (cselib_hash_table); n_useless_values = 0; @@ -434,6 +491,18 @@ cselib_preserved_value_p (cselib_val *v) return PRESERVED_VALUE_P (v->val_rtx); } +/* Arrange for a REG value to be assumed constant through the whole function, + never invalidated and preserved across cselib_reset_table calls. */ + +void +cselib_preserve_cfa_base_value (cselib_val *v) +{ + if (cselib_preserve_constants + && v->locs + && REG_P (v->locs->loc)) + cfa_base_preserved_val = v; +} + /* Clean all non-constant expressions in the hash table, but retain their values. */ @@ -1600,7 +1669,7 @@ cselib_invalidate_regno (unsigned int regno, enum machine_mode mode) if (i < FIRST_PSEUDO_REGISTER && v != NULL) this_last = end_hard_regno (GET_MODE (v->val_rtx), i) - 1; - if (this_last < regno || v == NULL) + if (this_last < regno || v == NULL || v == cfa_base_preserved_val) { l = &(*l)->next; continue; @@ -2018,7 +2087,7 @@ cselib_process_insn (rtx insn) init_alias_analysis. */ void -cselib_init (bool record_memory) +cselib_init (int record_what) { elt_list_pool = create_alloc_pool ("elt_list", sizeof (struct elt_list), 10); @@ -2027,7 +2096,8 @@ cselib_init (bool record_memory) cselib_val_pool = create_alloc_pool ("cselib_val_list", sizeof (cselib_val), 10); value_pool = create_alloc_pool ("value", RTX_CODE_SIZE (VALUE), 100); - cselib_record_memory = record_memory; + cselib_record_memory = record_what & CSELIB_RECORD_MEMORY; + cselib_preserve_constants = record_what & CSELIB_PRESERVE_CONSTANTS; /* (mem:BLK (scratch)) is a special mechanism to conflict with everything, see canon_true_dependence. This is only created once. */ @@ -2061,6 +2131,8 @@ void cselib_finish (void) { cselib_discard_hook = NULL; + cselib_preserve_constants = false; + cfa_base_preserved_val = NULL; free_alloc_pool (elt_list_pool); free_alloc_pool (elt_loc_list_pool); free_alloc_pool (cselib_val_pool); diff --git a/gcc/cselib.h b/gcc/cselib.h index 67e59920254..015d628bf9e 100644 --- a/gcc/cselib.h +++ b/gcc/cselib.h @@ -66,12 +66,18 @@ struct cselib_set cselib_val *dest_addr_elt; }; +enum cselib_record_what +{ + CSELIB_RECORD_MEMORY = 1, + CSELIB_PRESERVE_CONSTANTS = 2 +}; + extern void (*cselib_discard_hook) (cselib_val *); extern void (*cselib_record_sets_hook) (rtx insn, struct cselib_set *sets, int n_sets); extern cselib_val *cselib_lookup (rtx, enum machine_mode, int); -extern void cselib_init (bool record_memory); +extern void cselib_init (int); extern void cselib_clear_table (void); extern void cselib_finish (void); extern void cselib_process_insn (rtx); @@ -92,5 +98,6 @@ extern unsigned int cselib_get_next_uid (void); extern void cselib_preserve_value (cselib_val *); extern bool cselib_preserved_value_p (cselib_val *); extern void cselib_preserve_only_values (void); +extern void cselib_preserve_cfa_base_value (cselib_val *); extern void dump_cselib_table (FILE *); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 62a57a92b0a..6e4a71841ea 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2706,7 +2706,8 @@ attribute tells the compiler to use the Microsoft ABI, while the GNU/Linux and other systems. The default is to use the Microsoft ABI when targeting Windows. On all other systems, the default is the AMD ABI. -Note, This feature is currently sorried out for Windows targets trying to +Note, the @code{ms_abi} attribute for Windows targets currently requires +the @option{-maccumulate-outgoing-args} option. @item ms_hook_prologue @cindex @code{ms_hook_prologue} attribute diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index ee5545850ea..100b5206e12 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -1,4 +1,4 @@ -@c Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009 +@c Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 @c Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -930,7 +930,7 @@ effective-target keyword; or a logical expression. Depending on the context, the selector specifies whether a test is skipped and reported as unsupported or is expected to fail. Use @samp{*-*-*} to match any target. -Effective-target keywords are defined in @file{target-supports.exp} in +Effective-target keywords are defined in @file{lib/target-supports.exp} in the GCC testsuite. A selector expression appears within curly braces and uses a single @@ -972,10 +972,10 @@ If the directive includes the optional @samp{@{ target @var{selector} @}} then the test is skipped unless the target system is included in the list of target triplets or matches the effective-target keyword. -If @samp{do-what-keyword} is @code{run} and the directive includes +If @var{do-what-keyword} is @code{run} and the directive includes the optional @samp{@{ xfail @var{selector} @}} and the selector is met then the test is expected to fail. The @code{xfail} clause is ignored -for other values of @samp{do-what-keyword}; those tests can use +for other values of @var{do-what-keyword}; those tests can use directive @code{dg-xfail-if}. @item @{ dg-options @var{options} [@{ target @var{selector} @}] @} @@ -1001,11 +1001,7 @@ and only then in certain modes. @item @{ dg-timeout @var{n} [@{target @var{selector} @}] @} Set the time limit for the compilation and for the execution of the test -to the specified number of seconds. - -@item @{ dg-timeout-factor @var{x} [@{ target @var{selector} @}] @} -Multiply the normal time limit for compilation and execution of the test -by the specified floating-point factor. The normal timeout limit, in +to the specified number of seconds. The normal timeout limit, in seconds, is found by searching the following in order: @itemize @bullet @@ -1019,6 +1015,10 @@ the test @item 300 @end itemize +@item @{ dg-timeout-factor @var{x} [@{ target @var{selector} @}] @} +Multiply the normal time limit for compilation and execution of the test +by the specified floating-point factor. + @item @{ dg-skip-if @var{comment} @{ @var{selector} @} [@{ @var{include-opts} @} [@{ @var{exclude-opts} @}]] @} Arguments @var{include-opts} and @var{exclude-opts} are lists in which each element is a string of zero or more GCC options. @@ -1075,11 +1075,11 @@ Expect the test to fail if the conditions (which are the same as for @item @{ dg-xfail-run-if @var{comment} @{ @var{selector} @} [@{ @var{include-opts} @} [@{ @var{exclude-opts} @}]] @} Expect the execute step of a test to fail if the conditions (which are -the same as for @code{dg-skip-if}) and @code{dg-xfail-if}) are met. +the same as for @code{dg-skip-if} and @code{dg-xfail-if}) are met. @item @{ dg-require-@var{support} args @} Skip the test if the target does not provide the required support; -see @file{gcc-dg.exp} in the GCC testsuite for the actual directives. +see @file{lib/gcc-dg.exp} in the GCC testsuite for the actual directives. These directives must appear after any @code{dg-do} directive in the test and before any @code{dg-additional-sources} directive. They require at least one argument, which can be an empty string if the @@ -1241,7 +1241,7 @@ Check branch and/or call counts, in addition to line counts, in The Ada testsuite includes executable tests from the ACATS 2.5 testsuite, publicly available at -@uref{http://www.adaic.org/compilers/acats/2.5} +@uref{http://www.adaic.org/compilers/acats/2.5}. These tests are integrated in the GCC testsuite in the @file{gcc/testsuite/ada/acats} directory, and @@ -1257,11 +1257,12 @@ $ make check-ada CHAPTERS="c3 c9" @end smallexample The tests are organized by directory, each directory corresponding to -a chapter of the Ada Reference Manual. So for example, c9 corresponds +a chapter of the Ada Reference Manual. So for example, @file{c9} corresponds to chapter 9, which deals with tasking features of the language. There is also an extra chapter called @file{gcc} containing a template for -creating new executable tests. +creating new executable tests, although this is deprecated in favor of +the @file{gnat.dg} testsuite. The tests are run using two @command{sh} scripts: @file{run_acats} and @file{run_all.sh}. To run the tests using a simulator or a cross @@ -1291,7 +1292,7 @@ unless other options are given in the test. Except as noted below they are not run with multiple optimization options. @item gcc.dg/compat This subdirectory contains tests for binary compatibility using -@file{compat.exp}, which in turn uses the language-independent support +@file{lib/compat.exp}, which in turn uses the language-independent support (@pxref{compat Testing, , Support for testing binary compatibility}). @item gcc.dg/cpp This subdirectory contains tests of the preprocessor. @@ -1341,21 +1342,19 @@ This contains tests which are specific to IEEE floating point. FIXME: describe this. This directory should probably not be used for new tests. -@item gcc.c-torture/misc-tests +@item gcc.misc-tests This directory contains C tests that require special handling. Some of these tests have individual expect files, and others share special-purpose expect files: @table @file @item @code{bprob*.c} -Test @option{-fbranch-probabilities} using @file{bprob.exp}, which +Test @option{-fbranch-probabilities} using +@file{gcc.misc-tests/bprob.exp}, which in turn uses the generic, language-independent framework (@pxref{profopt Testing, , Support for testing profile-directed optimizations}). -@item @code{dg-*.c} -Test the testsuite itself using @file{dg-test.exp}. - @item @code{gcov*.c} Test @command{gcov} output using @file{gcov.exp}, which in turn uses the language-independent support (@pxref{gcov Testing, , Support for testing gcov}). @@ -1364,6 +1363,12 @@ language-independent support (@pxref{gcov Testing, , Support for testing gcov}). Test i386-specific support for data prefetch using @file{i386-prefetch.exp}. @end table +@item gcc.test-framework +@table @file +@item @code{dg-*.c} +Test the testsuite itself using @file{gcc.test-framework/test-framework.exp}. +@end table + @end table FIXME: merge in @file{testsuite/README.gcc} and discuss the format of @@ -1433,8 +1438,8 @@ each of these sets of options. Language-independent support for testing @command{gcov}, and for checking that branch profiling produces expected values, is provided by the -expect file @file{gcov.exp}. @command{gcov} tests also rely on procedures -in @file{gcc.dg.exp} to compile and run the test program. A typical +expect file @file{lib/gcov.exp}. @command{gcov} tests also rely on procedures +in @file{lib/gcc-dg.exp} to compile and run the test program. A typical @command{gcov} test contains the following DejaGnu commands within comments: @smallexample @@ -1607,7 +1612,7 @@ following from @file{@var{objdir}/gcc}: rm site.exp make -k \ ALT_CXX_UNDER_TEST=$@{alt_prefix@}/bin/g++ \ - COMPAT_OPTIONS="lists as shown above" \ + COMPAT_OPTIONS="@var{lists as shown above}" \ check-c++ \ RUNTESTFLAGS="compat.exp" @end smallexample @@ -1646,7 +1651,7 @@ targets. Throughout the compiler testsuite there are several directories whose tests are run multiple times, each with a different set of options. These are known as torture tests. -@file{gcc/testsuite/lib/torture-options.exp} defines procedures to +@file{lib/torture-options.exp} defines procedures to set up these lists: @table @code diff --git a/gcc/dse.c b/gcc/dse.c index 239d0fbe1ab..2be8a942c75 100644 --- a/gcc/dse.c +++ b/gcc/dse.c @@ -1,5 +1,6 @@ /* RTL dead store elimination. - Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. Contributed by Richard Sandiford <rsandifor@codesourcery.com> and Kenneth Zadeck <zadeck@naturalbridge.com> @@ -2616,7 +2617,7 @@ dse_step1 (void) basic_block bb; bitmap regs_live = BITMAP_ALLOC (NULL); - cselib_init (false); + cselib_init (0); all_blocks = BITMAP_ALLOC (NULL); bitmap_set_bit (all_blocks, ENTRY_BLOCK); bitmap_set_bit (all_blocks, EXIT_BLOCK); diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index c76d54f39c2..540d75fd9f9 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2760,11 +2760,12 @@ dwarf2out_frame_debug (rtx insn, bool after_p) if (REG_P (n)) { dw_fde_ref fde = current_fde (); - gcc_assert (fde - && fde->drap_reg != INVALID_REGNUM - && fde->vdrap_reg == INVALID_REGNUM); - if (REG_P (n)) - fde->vdrap_reg = REGNO (n); + if (fde) + { + gcc_assert (fde->vdrap_reg == INVALID_REGNUM); + if (REG_P (n)) + fde->vdrap_reg = REGNO (n); + } } handled_one = true; break; @@ -12726,7 +12727,6 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset, } else if (!optimize && fde - && fde->drap_reg != INVALID_REGNUM && (fde->drap_reg == REGNO (reg) || fde->vdrap_reg == REGNO (reg))) { @@ -15770,10 +15770,7 @@ rtl_for_decl_location (tree decl) && !DECL_HARD_REGISTER (decl) && DECL_MODE (decl) != VOIDmode) { - rtl = DECL_RTL (decl); - /* Reset DECL_RTL back, as various parts of the compiler expects - DECL_RTL set meaning it is actually going to be output. */ - SET_DECL_RTL (decl, NULL); + rtl = make_decl_rtl_for_debug (decl); if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF || SYMBOL_REF_DECL (XEXP (rtl, 0)) != decl) diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index dd809d9c23d..dc155fa1574 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,39 @@ +2010-03-18 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/43039 + * trans-expr.c (conv_parent_component_references): Ensure that + 'dt' has a backend_decl. + + PR fortran/43043 + * trans-expr.c (gfc_conv_structure): Ensure that the derived + type has a backend_decl. + + PR fortran/43044 + * resolve.c (resolve_global_procedure): Check that the 'cl' + structure is not NULL. + +2010-03-18 Shujing Zhao <pearly.zhao@oracle.com> + + * lang.opt (-ffixed-line-length-, ffree-line-length-): Remove + redundant tab. + +2010-03-17 Tobias Burnus <burnus@net-b.de> + + PR fortran/43331 + * trans-array.c (gfc_conv_array_index_offset,gfc_conv_array_ref, + gfc_conv_ss_startstride): Remove no-longer-needed cp_was_assumed + check. + * decl.c (gfc_match_derived_decl): Don't mark assumed-size Cray + pointees as having explizit size. + * expr.c (gfc_check_assign): Remove now unreachable Cray pointee + check. + * trans-types.c (gfc_is_nodesc_array): Add cp_was_assumed to assert. + (gfc_sym_type): Don't mark Cray pointees as restricted pointers. + * resolve.c (resolve_symbol): Handle cp_was_assumed. + * trans-decl.c (gfc_trans_deferred_vars): Ditto. + (gfc_finish_var_decl): Don't mark Cray pointees as restricted + pointers. + 2010-03-14 Tobias Burnus <burnus@net-b.de> PR fortran/43362 diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 04669061bf8..692078a11d4 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -6969,22 +6969,14 @@ gfc_match_derived_decl (void) /* Cray Pointees can be declared as: - pointer (ipt, a (n,m,...,*)) - By default, this is treated as an AS_ASSUMED_SIZE array. We'll - cheat and set a constant bound of 1 for the last dimension, if this - is the case. Since there is no bounds-checking for Cray Pointees, - this will be okay. */ + pointer (ipt, a (n,m,...,*)) */ match gfc_mod_pointee_as (gfc_array_spec *as) { as->cray_pointee = true; /* This will be useful to know later. */ if (as->type == AS_ASSUMED_SIZE) - { - as->type = AS_EXPLICIT; - as->upper[as->rank - 1] = gfc_int_expr (1); - as->cp_was_assumed = true; - } + as->cp_was_assumed = true; else if (as->type == AS_ASSUMED_SHAPE) { gfc_error ("Cray Pointee at %C cannot be assumed shape array"); diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 6d3ca8476b8..58c906375ea 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -3010,16 +3010,6 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform) } } - if (sym->attr.cray_pointee - && lvalue->ref != NULL - && lvalue->ref->u.ar.type == AR_FULL - && lvalue->ref->u.ar.as->cp_was_assumed) - { - gfc_error ("Vector assignment to assumed-size Cray Pointee at %L " - "is illegal", &lvalue->where); - return FAILURE; - } - /* This is possibly a typo: x = f() instead of x => f(). */ if (gfc_option.warn_surprising && rvalue->expr_type == EXPR_FUNCTION diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt index a52e643c9b3..7ea06c2838f 100644 --- a/gcc/fortran/lang.opt +++ b/gcc/fortran/lang.opt @@ -246,7 +246,7 @@ Allow arbitrary character line width in fixed mode ffixed-line-length- Fortran RejectNegative Joined UInteger --ffixed-line-length-<n> Use n as character line width in fixed mode +-ffixed-line-length-<n> Use n as character line width in fixed mode ffpe-trap= Fortran RejectNegative JoinedOrMissing @@ -262,7 +262,7 @@ Allow arbitrary character line width in free mode ffree-line-length- Fortran RejectNegative Joined UInteger --ffree-line-length-<n> Use n as character line width in free mode +-ffree-line-length-<n> Use n as character line width in free mode fimplicit-none Fortran diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 774dfe4f2ea..24ec7a8a1de 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -1851,12 +1851,13 @@ resolve_global_procedure (gfc_symbol *sym, locus *where, /* Non-assumed length character functions. */ if (sym->attr.function && sym->ts.type == BT_CHARACTER - && gsym->ns->proc_name->ts.u.cl->length != NULL) + && gsym->ns->proc_name->ts.u.cl != NULL + && gsym->ns->proc_name->ts.u.cl->length != NULL) { gfc_charlen *cl = sym->ts.u.cl; if (!sym->attr.entry_master && sym->attr.if_source == IFSRC_UNKNOWN - && cl && cl->length && cl->length->expr_type != EXPR_CONSTANT) + && cl && cl->length && cl->length->expr_type != EXPR_CONSTANT) { gfc_error ("Nonconstant character-length function '%s' at %L " "must have an explicit interface", sym->name, @@ -11010,7 +11011,7 @@ resolve_symbol (gfc_symbol *sym) arguments. */ if (sym->as != NULL - && (sym->as->type == AS_ASSUMED_SIZE + && ((sym->as->type == AS_ASSUMED_SIZE && !sym->as->cp_was_assumed) || sym->as->type == AS_ASSUMED_SHAPE) && sym->attr.dummy == 0) { diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 8eea3aca716..5eeead831c4 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -2404,8 +2404,8 @@ gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i, index = gfc_trans_array_bound_check (se, info->descriptor, index, dim, &ar->where, - (ar->as->type != AS_ASSUMED_SIZE - && !ar->as->cp_was_assumed) || dim < ar->dimen - 1); + ar->as->type != AS_ASSUMED_SIZE + || dim < ar->dimen - 1); break; case DIMEN_VECTOR: @@ -2431,8 +2431,8 @@ gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i, /* Do any bounds checking on the final info->descriptor index. */ index = gfc_trans_array_bound_check (se, info->descriptor, index, dim, &ar->where, - (ar->as->type != AS_ASSUMED_SIZE - && !ar->as->cp_was_assumed) || dim < ar->dimen - 1); + ar->as->type != AS_ASSUMED_SIZE + || dim < ar->dimen - 1); break; case DIMEN_RANGE: @@ -2581,8 +2581,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym, /* Upper bound, but not for the last dimension of assumed-size arrays. */ - if (n < ar->dimen - 1 - || (ar->as->type != AS_ASSUMED_SIZE && !ar->as->cp_was_assumed)) + if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE) { tmp = gfc_conv_array_ubound (se->expr, n); if (sym->attr.temporary) @@ -3207,8 +3206,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) continue; if (dim == info->ref->u.ar.dimen - 1 - && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE - || info->ref->u.ar.as->cp_was_assumed)) + && info->ref->u.ar.as->type == AS_ASSUMED_SIZE) check_upper = false; else check_upper = true; diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 34e153ae77b..6f5f7796da8 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -598,6 +598,7 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym) if (!sym->attr.target && !sym->attr.pointer + && !sym->attr.cray_pointee && !sym->attr.proc_pointer) DECL_RESTRICTED_P (decl) = 1; } @@ -3159,10 +3160,11 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody) case AS_ASSUMED_SIZE: /* Must be a dummy parameter. */ - gcc_assert (sym->attr.dummy); + gcc_assert (sym->attr.dummy || sym->as->cp_was_assumed); /* We should always pass assumed size arrays the g77 way. */ - fnbody = gfc_trans_g77_array (sym, fnbody); + if (sym->attr.dummy) + fnbody = gfc_trans_g77_array (sym, fnbody); break; case AS_ASSUMED_SHAPE: diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index abc2a24318a..b9ea5579ac8 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -507,6 +507,9 @@ conv_parent_component_references (gfc_se * se, gfc_ref * ref) parent.u.c.sym = dt; parent.u.c.component = dt->components; + if (dt->backend_decl == NULL) + gfc_get_derived_type (dt); + if (dt->attr.extension && dt->components) { if (dt->attr.is_class) @@ -4454,6 +4457,8 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init) { gfc_component *data; data = gfc_find_component (cm->ts.u.derived, "$data", true, true); + if (!data->backend_decl) + gfc_get_derived_type (cm->ts.u.derived); val = gfc_conv_initializer (c->expr, &cm->ts, TREE_TYPE (data->backend_decl), data->attr.dimension, diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index 278ae27a458..ebe4c2f832b 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -1193,7 +1193,7 @@ gfc_is_nodesc_array (gfc_symbol * sym) if (sym->attr.result || sym->attr.function) return 0; - gcc_assert (sym->as->type == AS_EXPLICIT); + gcc_assert (sym->as->type == AS_EXPLICIT || sym->as->cp_was_assumed); return 1; } @@ -1775,7 +1775,7 @@ gfc_sym_type (gfc_symbol * sym) byref = 0; restricted = !sym->attr.target && !sym->attr.pointer - && !sym->attr.proc_pointer; + && !sym->attr.proc_pointer && !sym->attr.cray_pointee; if (sym->attr.dimension) { if (gfc_is_nodesc_array (sym)) diff --git a/gcc/gcse.c b/gcc/gcse.c index 432e34d478e..8e31ee11a58 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -1,7 +1,7 @@ /* Global common subexpression elimination/Partial redundancy elimination and global constant/copy propagation for GNU compiler. Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -2724,7 +2724,7 @@ local_cprop_pass (void) struct reg_use *reg_used; bool changed = false; - cselib_init (false); + cselib_init (0); FOR_EACH_BB (bb) { FOR_BB_INSNS (bb, insn) diff --git a/gcc/graphite-sese-to-poly.c b/gcc/graphite-sese-to-poly.c index b0bc3481cd2..83eff2a341c 100644 --- a/gcc/graphite-sese-to-poly.c +++ b/gcc/graphite-sese-to-poly.c @@ -2366,7 +2366,8 @@ rewrite_cross_bb_scalar_deps (sese region, gimple_stmt_iterator *gsi) FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def) if (def_bb != gimple_bb (use_stmt) - && gimple_code (use_stmt) != GIMPLE_PHI) + && gimple_code (use_stmt) != GIMPLE_PHI + && !is_gimple_debug (use_stmt)) { if (!zero_dim_array) { @@ -2465,7 +2466,7 @@ split_reduction_stmt (gimple stmt) split_block (bb, stmt); - if (gsi_one_before_end_p (gsi_start_bb (bb))) + if (gsi_one_before_end_p (gsi_start_nondebug_bb (bb))) return bb; gsi = gsi_last_bb (bb); diff --git a/gcc/ipa-struct-reorg.c b/gcc/ipa-struct-reorg.c index e0336aa1a13..24b42e3ed03 100644 --- a/gcc/ipa-struct-reorg.c +++ b/gcc/ipa-struct-reorg.c @@ -1389,6 +1389,7 @@ create_new_general_access (struct access_site *acc, d_str str) for now just reset all debug stmts referencing objects that have been peeled. */ gimple_debug_bind_reset_value (stmt); + update_stmt (stmt); break; default: diff --git a/gcc/ipa.c b/gcc/ipa.c index f81d41a4a28..c789a29372d 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -262,10 +262,10 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) if (!clone) { cgraph_release_function_body (node); - cgraph_node_remove_callees (node); node->analyzed = false; node->local.inlinable = false; } + cgraph_node_remove_callees (node); if (node->prev_sibling_clone) node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone; else if (node->clone_of) diff --git a/gcc/lambda-code.c b/gcc/lambda-code.c index e5fe6299f28..50f7d475665 100644 --- a/gcc/lambda-code.c +++ b/gcc/lambda-code.c @@ -1657,7 +1657,7 @@ remove_iv (gimple iv_stmt) continue; FOR_EACH_IMM_USE_STMT (stmt, imm_iter, arg) - if (stmt != iv_stmt) + if (stmt != iv_stmt && !is_gimple_debug (stmt)) used = true; if (!used) @@ -1839,6 +1839,9 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest, gimple_seq stmts; lambda_body_vector lbv, newlbv; + if (is_gimple_debug (stmt)) + continue; + /* Compute the new expression for the induction variable. */ depth = VEC_length (tree, new_ivs); @@ -1885,7 +1888,8 @@ not_interesting_stmt (gimple stmt) loop, we would have already failed the number of exits tests. */ if (gimple_code (stmt) == GIMPLE_LABEL || gimple_code (stmt) == GIMPLE_GOTO - || gimple_code (stmt) == GIMPLE_COND) + || gimple_code (stmt) == GIMPLE_COND + || is_gimple_debug (stmt)) return true; return false; } diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c index 03f0a13baa0..57973c19523 100644 --- a/gcc/loop-invariant.c +++ b/gcc/loop-invariant.c @@ -1423,14 +1423,16 @@ move_invariant_reg (struct loop *loop, unsigned invno) emit_insn_after (gen_move_insn (dest, reg), inv->insn); reorder_insns (inv->insn, inv->insn, BB_END (preheader)); - /* If there is a REG_EQUAL note on the insn we just moved, and - insn is in a basic block that is not always executed, the note - may no longer be valid after we move the insn. - Note that uses in REG_EQUAL notes are taken into account in - the computation of invariants. Hence it is safe to retain the - note even if the note contains register references. */ - if (! inv->always_executed - && (note = find_reg_note (inv->insn, REG_EQUAL, NULL_RTX))) + /* If there is a REG_EQUAL note on the insn we just moved, and the + insn is in a basic block that is not always executed or the note + contains something for which we don't know the invariant status, + the note may no longer be valid after we move the insn. Note that + uses in REG_EQUAL notes are taken into account in the computation + of invariants, so it is safe to retain the note even if it contains + register references for which we know the invariant status. */ + if ((note = find_reg_note (inv->insn, REG_EQUAL, NULL_RTX)) + && (!inv->always_executed + || !check_maybe_invariant (XEXP (note, 0)))) remove_note (inv->insn, note); } else diff --git a/gcc/postreload.c b/gcc/postreload.c index f8785821f63..8b622a7365a 100644 --- a/gcc/postreload.c +++ b/gcc/postreload.c @@ -1,7 +1,7 @@ /* Perform simple optimizations to clean up the result of reload. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - Free Software Foundation, Inc. + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -198,7 +198,7 @@ reload_cse_regs_1 (rtx first) rtx insn; rtx testreg = gen_rtx_REG (VOIDmode, -1); - cselib_init (true); + cselib_init (CSELIB_RECORD_MEMORY); init_alias_analysis (); for (insn = first; insn; insn = NEXT_INSN (insn)) diff --git a/gcc/regrename.c b/gcc/regrename.c index f7891d1b017..d6063a83a52 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -509,6 +509,72 @@ note_sets_clobbers (rtx x, const_rtx set, void *data) add_to_hard_reg_set (&chain->hard_conflicts, GET_MODE (x), REGNO (x)); } +/* Create a new chain for THIS_NREGS registers starting at THIS_REGNO, + and record its occurrence in *LOC, which is being written to in INSN. + This access requires a register of class CL. */ + +static void +create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc, + rtx insn, enum reg_class cl) +{ + struct du_head *head = XOBNEW (&rename_obstack, struct du_head); + struct du_chain *this_du; + int nregs; + + head->next_chain = open_chains; + open_chains = head; + head->regno = this_regno; + head->nregs = this_nregs; + head->need_caller_save_reg = 0; + head->cannot_rename = 0; + head->terminated = 0; + + VEC_safe_push (du_head_p, heap, id_to_chain, head); + head->id = current_id++; + + bitmap_initialize (&head->conflicts, &bitmap_default_obstack); + bitmap_copy (&head->conflicts, &open_chains_set); + mark_conflict (open_chains, head->id); + + /* Since we're tracking this as a chain now, remove it from the + list of conflicting live hard registers and track it in + live_in_chains instead. */ + nregs = head->nregs; + while (nregs-- > 0) + { + SET_HARD_REG_BIT (live_in_chains, head->regno + nregs); + CLEAR_HARD_REG_BIT (live_hard_regs, head->regno + nregs); + } + + COPY_HARD_REG_SET (head->hard_conflicts, live_hard_regs); + bitmap_set_bit (&open_chains_set, head->id); + + open_chains = head; + + if (dump_file) + { + fprintf (dump_file, "Creating chain %s (%d)", + reg_names[head->regno], head->id); + if (insn != NULL_RTX) + fprintf (dump_file, " at insn %d", INSN_UID (insn)); + fprintf (dump_file, "\n"); + } + + if (insn == NULL_RTX) + { + head->first = head->last = NULL; + return; + } + + this_du = XOBNEW (&rename_obstack, struct du_chain); + head->first = head->last = this_du; + + this_du->next_use = 0; + this_du->loc = loc; + this_du->insn = insn; + this_du->cl = cl; +} + static void scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action, enum op_type type) @@ -522,53 +588,7 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action, if (action == mark_write) { if (type == OP_OUT) - { - struct du_head *head = XOBNEW (&rename_obstack, struct du_head); - struct du_chain *this_du = XOBNEW (&rename_obstack, struct du_chain); - int nregs; - - head->next_chain = open_chains; - open_chains = head; - head->first = head->last = this_du; - head->regno = this_regno; - head->nregs = this_nregs; - head->need_caller_save_reg = 0; - head->cannot_rename = 0; - head->terminated = 0; - - VEC_safe_push (du_head_p, heap, id_to_chain, head); - head->id = current_id++; - - bitmap_initialize (&head->conflicts, &bitmap_default_obstack); - bitmap_copy (&head->conflicts, &open_chains_set); - mark_conflict (open_chains, head->id); - - /* Since we're tracking this as a chain now, remove it from the - list of conflicting live hard registers and track it in - live_in_chains instead. */ - nregs = head->nregs; - while (nregs-- > 0) - { - SET_HARD_REG_BIT (live_in_chains, head->regno + nregs); - CLEAR_HARD_REG_BIT (live_hard_regs, head->regno + nregs); - } - - COPY_HARD_REG_SET (head->hard_conflicts, live_hard_regs); - bitmap_set_bit (&open_chains_set, head->id); - - open_chains = head; - - this_du->next_use = 0; - this_du->loc = loc; - this_du->insn = insn; - this_du->cl = cl; - - if (dump_file) - fprintf (dump_file, - "Creating chain %s (%d) at insn %d (%s)\n", - reg_names[head->regno], head->id, INSN_UID (insn), - scan_actions_name[(int) action]); - } + create_new_chain (this_regno, this_nregs, loc, insn, cl); return; } @@ -636,7 +656,10 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action, this_du->loc = loc; this_du->insn = insn; this_du->cl = cl; - head->last->next_use = this_du; + if (head->first == NULL) + head->first = this_du; + else + head->last->next_use = this_du; head->last = this_du; } @@ -1069,7 +1092,6 @@ build_def_use (basic_block bb) int n_ops; rtx note; rtx old_operands[MAX_RECOG_OPERANDS]; - bool has_dup[MAX_RECOG_OPERANDS]; rtx old_dups[MAX_DUP_OPERANDS]; int i; int alt; @@ -1108,10 +1130,6 @@ build_def_use (basic_block bb) n_ops = recog_data.n_operands; untracked_operands = 0; - memset (has_dup, 0, sizeof has_dup); - for (i = 0; i < recog_data.n_dups; i++) - has_dup[(int)recog_data.dup_num[i]] = true; - /* Simplify the code below by rewriting things to reflect matching constraints. Also promote OP_OUT to OP_INOUT in predicated instructions, but only for register operands @@ -1121,14 +1139,13 @@ build_def_use (basic_block bb) predicated = GET_CODE (PATTERN (insn)) == COND_EXEC; for (i = 0; i < n_ops; ++i) { + rtx op = recog_data.operand[i]; int matches = recog_op_alt[i][alt].matches; if (matches >= 0) recog_op_alt[i][alt].cl = recog_op_alt[matches][alt].cl; if (matches >= 0 || recog_op_alt[i][alt].matched >= 0 - || (predicated && recog_data.operand_type[i] == OP_OUT - && verify_reg_tracked (recog_data.operand[i]))) + || (predicated && recog_data.operand_type[i] == OP_OUT)) { - rtx op = recog_data.operand[i]; recog_data.operand_type[i] = OP_INOUT; /* A special case to deal with instruction patterns that have matching operands with different modes. If we're @@ -1145,18 +1162,17 @@ build_def_use (basic_block bb) } } /* If there's an in-out operand with a register that is not - being tracked at all yet, convert it to an earlyclobber - output operand. - This only works if the operand isn't duplicated, i.e. for - a ZERO_EXTRACT in a SET_DEST. */ + being tracked at all yet, open a chain. */ if (recog_data.operand_type[i] == OP_INOUT && !(untracked_operands & (1 << i)) - && !verify_reg_tracked (recog_data.operand[i])) + && REG_P (op) + && !verify_reg_tracked (op)) { - if (has_dup[i]) - fail_current_block = true; - recog_data.operand_type[i] = OP_OUT; - recog_op_alt[i][alt].earlyclobber = 1; + enum machine_mode mode = GET_MODE (op); + unsigned this_regno = REGNO (op); + unsigned this_nregs = hard_regno_nregs[this_regno][mode]; + create_new_chain (this_regno, this_nregs, NULL, NULL_RTX, + NO_REGS); } } diff --git a/gcc/rtl.h b/gcc/rtl.h index 1748e738527..b8563b33d16 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1778,7 +1778,7 @@ extern rtx simplify_subreg (enum machine_mode, rtx, enum machine_mode, extern rtx simplify_gen_subreg (enum machine_mode, rtx, enum machine_mode, unsigned int); extern rtx simplify_replace_fn_rtx (rtx, const_rtx, - rtx (*fn) (rtx, void *), void *); + rtx (*fn) (rtx, const_rtx, void *), void *); extern rtx simplify_replace_rtx (rtx, const_rtx, rtx); extern rtx simplify_rtx (const_rtx); extern rtx avoid_constant_pool_reference (rtx); diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index 02de5f8e820..40ebc5654de 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -1,7 +1,7 @@ /* Instruction scheduling pass. This file computes dependencies between instructions. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by, and currently maintained by, Jim Wilson (wilson@cygnus.com) @@ -3383,7 +3383,7 @@ sched_analyze (struct deps *deps, rtx head, rtx tail) rtx insn; if (sched_deps_info->use_cselib) - cselib_init (true); + cselib_init (CSELIB_RECORD_MEMORY); deps_start_bb (deps, head); diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 5ad5b1aceb9..d189d7066f2 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -350,15 +350,14 @@ simplify_gen_relational (enum rtx_code code, enum machine_mode mode, return gen_rtx_fmt_ee (code, mode, op0, op1); } -/* Replace all occurrences of OLD_RTX in X with FN (X', DATA), where X' - is an expression in X that is equal to OLD_RTX. Canonicalize and - simplify the result. - - If FN is null, assume FN (X', DATA) == copy_rtx (DATA). */ +/* If FN is NULL, replace all occurrences of OLD_RTX in X with copy_rtx (DATA) + and simplify the result. If FN is non-NULL, call this callback on each + X, if it returns non-NULL, replace X with its return value and simplify the + result. */ rtx simplify_replace_fn_rtx (rtx x, const_rtx old_rtx, - rtx (*fn) (rtx, void *), void *data) + rtx (*fn) (rtx, const_rtx, void *), void *data) { enum rtx_code code = GET_CODE (x); enum machine_mode mode = GET_MODE (x); @@ -368,17 +367,14 @@ simplify_replace_fn_rtx (rtx x, const_rtx old_rtx, rtvec vec, newvec; int i, j; - /* If X is OLD_RTX, return FN (X, DATA), with a null FN. Otherwise, - if this is an expression, try to build a new expression, substituting - recursively. If we can't do anything, return our input. */ - - if (rtx_equal_p (x, old_rtx)) + if (__builtin_expect (fn != NULL, 0)) { - if (fn) - return fn (x, data); - else - return copy_rtx ((rtx) data); + newx = fn (x, old_rtx, data); + if (newx) + return newx; } + else if (rtx_equal_p (x, old_rtx)) + return copy_rtx ((rtx) data); switch (GET_RTX_CLASS (code)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f70b5e64199..ef33f4cab91 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,103 @@ +2010-03-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + Jack Howarth <howarth@bromo.med.uc.edu> + + PR target/36399 + * gcc/testsuite/gcc.target/i386/push-1.c: Don't xfail + scan-assembler-not "movups" on darwin. + +2010-03-18 Jakub Jelinek <jakub@redhat.com> + + PR debug/43058 + * gcc.dg/pr43058.c: New test. + +2010-03-18 Martin Jambor <mjambor@suse.cz> + + PR middle-end/42450 + * g++.dg/torture/pr42450.C: New test. + +2010-03-18 Michael Matz <matz@suse.de> + + PR middle-end/43419 + * gcc.dg/pr43419.c: New testcase. + +2010-03-18 H.J. Lu <hongjiu.lu@intel.com> + + PR rtl-optimization/43360 + * gcc.dg/torture/pr43360.c: New. + +2010-03-18 Michael Matz <matz@suse.de> + + PR tree-optimization/43402 + * gcc.dg/pr43402.c: New testcase. + +2010-03-17 Peter Bergner <bergner@vnet.ibm.com> + + PR target/42427 + * gcc.dg/pr42427.c: New test. + +2010-03-17 Jerry DeLisle <jvdelisle@gcc.gnu.org> + + PR libfortran/43265 + * gfortran.dg/read_empty_file.f: New test. + * gfortran.dg/read_eof_all.f90: New test. + * gfortran.dg/namelist_27.f90: Eliminate infinite loop posibility. + * gfortran.dg/namelist_28.f90: Eliminate infinite loop posibility. + +2010-03-17 Michael Matz <matz@suse.de> + + * gcc.dg/pr43300.c: Add -w. + +2010-03-17 Richard Guenther <rguenther@suse.de> + + * gcc.dg/pr43379.c: Add -w. + +2010-03-17 Tobias Burnus <burnus@net-b.de> + + PR fortran/43331 + * gfortran.dg/cray_pointers_1.f90: Update dg-error message. + +2010-03-16 Uros Bizjak <ubizjak@gmail.com> + + * gcc.dg/graphite/block-3.c: Add dg-timeout-factor. + +2010-03-16 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * ada/acats/run_all.sh: Log start and end times. + +2010-03-16 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gnat.dg/socket1.adb: Disable on *-*-solaris2*. + +2010-03-16 Richard Guenther <rguenther@suse.de> + + PR middle-end/43379 + * gcc.dg/pr43379.c: New testcase. + +2010-03-16 Jakub Jelinek <jakub@redhat.com> + + PR debug/43051 + * gcc.dg/guality/pr43051-1.c: New test. + +2010-03-15 Janis Johnson <janis187@us.ibm.com> + + PR testsuite/43363 + * g++.dg/ext/altivec-17.C: Handle changes to error message. + +2010-03-15 Michael Matz <matz@suse.de> + + PR middle-end/43300 + * gcc.dg/pr43300.c: New testcase. + +2010-03-15 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/43367 + * gcc.c-torture/compile/pr43367.c: New testcase. + +2010-03-15 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/43317 + * gcc.dg/pr43317.c: New testcase. + 2010-03-14 Uros Bizjak <ubizjak@gmail.com> * g++.dg/abi/packed1.C: Expect warning on the alpha*-*-*. @@ -228,6 +328,11 @@ 2010-03-03 Jason Merrill <jason@redhat.com> + PR c++/12909 + * g++.dg/abi/mangle40.C: Updated. + +2010-03-03 Jason Merrill <jason@redhat.com> + * g++.dg/abi/mangle19-1.C: Adjust for default -Wabi. * g++.dg/abi/mangle23.C: Likewise. * g++.dg/eh/simd-2.C: Likewise. diff --git a/gcc/testsuite/ada/acats/run_all.sh b/gcc/testsuite/ada/acats/run_all.sh index edc76f4371d..eb30fbc3356 100755 --- a/gcc/testsuite/ada/acats/run_all.sh +++ b/gcc/testsuite/ada/acats/run_all.sh @@ -76,6 +76,8 @@ EXTERNAL_OBJECTS="" rm -f $dir/acats.sum $dir/acats.log +display "Test Run By $USER on `date`" + display " === acats configuration ===" target=`$GCC -dumpmachine` @@ -312,4 +314,6 @@ if [ $glob_countok -ne $glob_countn ]; then display "*** FAILURES: $failed" fi +display "$0 completed at `date`" + exit 0 diff --git a/gcc/testsuite/g++.dg/eh/pr43365.C b/gcc/testsuite/g++.dg/eh/pr43365.C new file mode 100644 index 00000000000..32346d5018c --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/pr43365.C @@ -0,0 +1,30 @@ +extern "C" void abort(); + +class Counter +{ +public: + static int count; + ~Counter() { count += 1; } +}; + +int Counter::count = 0; + +void func() +{ + Counter c; + + try { + throw 1; + } + catch (const int&) { + return; + } +} + +int main() +{ + func(); + if (Counter::count != 1) + abort(); + return 0; +} diff --git a/gcc/testsuite/g++.dg/ext/altivec-17.C b/gcc/testsuite/g++.dg/ext/altivec-17.C index 7db10e502b1..20c6935ecbb 100644 --- a/gcc/testsuite/g++.dg/ext/altivec-17.C +++ b/gcc/testsuite/g++.dg/ext/altivec-17.C @@ -12,5 +12,5 @@ typedef vector__ bool__ int bool_simd_type; void Foo (bool_simd_type const &a) { - simd_type const &v = a; // { dg-error "'const unsigned int __vector__&' from expression of type 'const __bool int __vector__'" } + simd_type const &v = a; // { dg-error "'const unsigned int __vector\\\[4\\\]&' from expression of type 'const __bool int __vector\\\[4\\\]'" } } diff --git a/gcc/testsuite/g++.dg/torture/pr42450.C b/gcc/testsuite/g++.dg/torture/pr42450.C new file mode 100644 index 00000000000..f630fa2b7e2 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr42450.C @@ -0,0 +1,112 @@ +/* { dg-do compile } */ + +template < typename > class basic_stringstream; + +struct basic_string { + basic_string(); +}; + +struct ios_base { + virtual ~ios_base(); +}; + +class ostream:ios_base {}; +class istream:virtual ios_base {}; + +template < typename > struct basic_iostream:public istream, ostream { + ~basic_iostream () {} +}; +extern template class basic_iostream < char >; + +template < typename > struct basic_stringstream:public basic_iostream < char > { + basic_string _M_stringbuf; + ~basic_stringstream () {} +}; +extern template class basic_stringstream < char >; + +template < typename > struct AnyMatrixBase; +template < typename, int _Rows, int _Cols, int = _Rows, int = _Cols > class Matrix; +template < typename > class CwiseNullaryOp; + +template < typename Derived > struct MatrixBase:public AnyMatrixBase < Derived > { + typedef CwiseNullaryOp < Derived > ConstantReturnType; + ConstantReturnType Constant (); + template < typename > Derived cast (); + static CwiseNullaryOp < Derived > Random (int); +}; + +template < typename Derived > struct AnyMatrixBase { + Derived derived () {} + Derived & derived () const {} +}; + +template < typename, int > struct ei_matrix_storage {}; + +template < typename _Scalar, int, int, int _MaxRows, int _MaxCols > struct Matrix:MatrixBase < Matrix < _Scalar, _MaxRows, _MaxCols > > { + typedef MatrixBase < Matrix > Base; + ei_matrix_storage < int, _MaxCols > m_storage; + Matrix operator= (const Matrix other) { + _resize_to_match (other); + lazyAssign (other.derived ()); + } + template < typename OtherDerived > Matrix lazyAssign (MatrixBase < OtherDerived > other) { + _resize_to_match (other); + return Base (other.derived ()); + } + Matrix (); + template < typename OtherDerived > Matrix (const MatrixBase < OtherDerived > &other) { + *this = other; + } + template < typename OtherDerived > void _resize_to_match (const MatrixBase < OtherDerived > &) { + throw 1; + } +}; + +template < typename MatrixType > class CwiseNullaryOp: +public MatrixBase < CwiseNullaryOp < MatrixType > > {}; + +int f() +{ + bool align_cols; + if (align_cols) { + basic_stringstream<char> sstr; + f(); + } +} + +template < typename > struct AutoDiffScalar; +template < typename Functor > struct AutoDiffJacobian:Functor { + AutoDiffJacobian (Functor); + typedef typename Functor::InputType InputType; + typedef typename Functor::ValueType ValueType; + typedef Matrix < int, Functor::InputsAtCompileTime, 1 > DerivativeType; + typedef AutoDiffScalar < DerivativeType > ActiveScalar; + typedef Matrix < ActiveScalar, Functor::InputsAtCompileTime, 1 > ActiveInput; + void operator () (InputType x, ValueType *) { + ActiveInput ax = x.template cast < ActiveScalar > (); + } +}; + +template < int NX, int NY > struct TestFunc1 { + enum { + InputsAtCompileTime = NX + }; + typedef Matrix < float, NX, 1 > InputType; + typedef Matrix < float, NY, 1 > ValueType; + typedef Matrix < float, NY, NX > JacobianType; + int inputs (); +}; + +template < typename Func > void forward_jacobian (Func f) { + typename Func::InputType x = Func::InputType::Random (f.inputs ()); + typename Func::ValueType y; + typename Func::JacobianType jref = jref.Constant (); + AutoDiffJacobian < Func > autoj (f); + autoj (x, &y); +} + +void test_autodiff_scalar () +{ + forward_jacobian (TestFunc1 < 2, 2 > ()); + forward_jacobian (TestFunc1 < 3, 2 > ()); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr43367.c b/gcc/testsuite/gcc.c-torture/compile/pr43367.c new file mode 100644 index 00000000000..5c620c13c90 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr43367.c @@ -0,0 +1,30 @@ +unsigned char g_17; + +const unsigned char func_39 (unsigned char p_40, unsigned char * p_41) +{ + return 0; +} + +void int327 (const unsigned char p_48, unsigned char p_49) +{ + unsigned l_52; + unsigned char l_58[2]; + int i, j; + if (func_39 (l_52, &p_49), p_48) { + unsigned char *l_60; + unsigned char *l = &l_58[1]; + for (j; j; j++) { +lbl_59: + break; + } + for (l = 0; 1; l += 1) { + for (p_49 = 1; p_49; p_49 += 0) { + unsigned char **l_61[1][6]; + for (j = 0; j < 1; j++) + l_61[i][j] = &l_60; + goto lbl_59; + } + } + } +} + diff --git a/gcc/testsuite/gcc.dg/graphite/block-3.c b/gcc/testsuite/gcc.dg/graphite/block-3.c index efa14599ed7..322ed8d7f89 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-3.c +++ b/gcc/testsuite/gcc.dg/graphite/block-3.c @@ -1,4 +1,5 @@ /* { dg-require-effective-target size32plus } */ +/* { dg-timeout-factor 4.0 } */ #define DEBUG 0 #if DEBUG diff --git a/gcc/testsuite/gcc.dg/guality/pr43051-1.c b/gcc/testsuite/gcc.dg/guality/pr43051-1.c new file mode 100644 index 00000000000..77325c97e26 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr43051-1.c @@ -0,0 +1,57 @@ +/* PR debug/43051 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +extern void abort (void); + +static void __attribute__ ((noinline)) +foo (const char *x, long long y, int z) +{ + asm volatile ("" : : "r" (x), "r" ((int) y), "r" (z) : "memory"); +} + +struct S +{ + struct S *n; + int v; +}; + +struct S a[10]; + +struct S * __attribute__ ((noinline)) +bar (struct S *c, int v, struct S *e) +{ +#ifdef __i386__ + register int si asm ("esi"), di asm ("edi"), bx +# if !defined (__pic__) && !defined (__APPLE__) + asm ("ebx") +# endif + ; + asm volatile ("" : "=r" (si), "=r" (di), "=r" (bx)); +#endif + while (c < e) + { + foo ("c", (__UINTPTR_TYPE__) c, 0); /* { dg-final { gdb-test 34 "c" "\&a\[0\]" } } */ + foo ("v", v, 1); /* { dg-final { gdb-test 35 "v" "1" } } */ + foo ("e", (__UINTPTR_TYPE__) e, 2); /* { dg-final { gdb-test 36 "e" "\&a\[1\]" } } */ + if (c->v == v) + return c; + foo ("c", (__UINTPTR_TYPE__) c, 3); /* { dg-final { gdb-test 39 "c" "\&a\[0\]" } } */ + foo ("v", v, 4); /* { dg-final { gdb-test 40 "v" "1" } } */ + foo ("e", (__UINTPTR_TYPE__) e, 5); /* { dg-final { gdb-test 41 "e" "\&a\[1\]" } } */ + c++; + } +#ifdef __i386__ + asm volatile ("" : : "r" (si), "r" (di), "r" (bx)); +#endif + return 0; +} + +int +main () +{ + asm volatile ("" : : "r" (&a[0]) : "memory"); + if (bar (&a[a[0].v], a[0].v + 1, &a[a[0].v + 1])) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr42427.c b/gcc/testsuite/gcc.dg/pr42427.c new file mode 100644 index 00000000000..1961313bc5f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr42427.c @@ -0,0 +1,21 @@ +/* { dg-do assemble } */ +/* { dg-options "-O2 -fexceptions -fnon-call-exceptions -fpeel-loops" } */ +/* { dg-require-effective-target ilp32 } */ + +#include <complex.h> + +extern double myabs (complex double); + +void +test (double *help, complex double *wm, long nz) +{ + long k; + double znew; + double zold; + for (k = 0; k < nz; k++) + { + znew = myabs (wm[k]); + zold = help[k]; + help[k] = znew; + } +} diff --git a/gcc/testsuite/gcc.dg/pr42917.c b/gcc/testsuite/gcc.dg/pr42917.c new file mode 100644 index 00000000000..d8db32ea2da --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr42917.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -ftree-loop-linear -fcompare-debug -fdump-tree-ltrans" } */ + +extern int A[]; + +void +foo () +{ + int i, j; + for (i = 0; i < 4; i++) + for (j = 255; j >= 0; j--) + A[j] = 0; +} + +/* { dg-final { scan-tree-dump "Successfully transformed loop" "ltrans" } } */ +/* { dg-final { cleanup-tree-dump "ltrans" } } */ diff --git a/gcc/testsuite/gcc.dg/pr43058.c b/gcc/testsuite/gcc.dg/pr43058.c new file mode 100644 index 00000000000..50d8a63bb8f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr43058.c @@ -0,0 +1,20 @@ +/* PR debug/43058 */ +/* { dg-do compile } */ +/* { dg-options "-g -O2" } */ + +extern void *f1 (void *, void *, void *); +extern void *f2 (const char *, int, int, int, void *(*) ()); +extern void *f3 (const char *); +extern void *f4 (void *s); +extern void *f5 (void *); + +void test (void) +{ +#define X1 f1 (f2 ("a", 1, 0, 0, f5), \ + f4 (({ const char *a = "b"; f3 (a); })), \ + ({ const char *a = "c"; f3 (a); })); +#define X2 X1 X1 X1 X1 X1 X1 X1 X1 X1 X1 +#define X3 X2 X2 X2 X2 X2 X2 X2 X2 X2 X2 +#define X4 X3 X3 X3 X3 X3 X3 X3 X3 X3 X3 + X4 X4 +} diff --git a/gcc/testsuite/gcc.dg/pr43300.c b/gcc/testsuite/gcc.dg/pr43300.c new file mode 100644 index 00000000000..df71dbed789 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr43300.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -w" } */ +typedef float V2SF __attribute__ ((vector_size (128))); + +V2SF +foo (int x, V2SF a) +{ + V2SF b; + if (x & 42) + b = a; + else + b = a + (V2SF) {1.0f/0.0f - 1.0f/0.0f, 1.0f/0.0f - 1.0f/0.0f}; + while (x--) + a += b; + + return a; +} diff --git a/gcc/testsuite/gcc.dg/pr43317.c b/gcc/testsuite/gcc.dg/pr43317.c new file mode 100644 index 00000000000..3ee3ed54931 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr43317.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fipa-struct-reorg -fwhole-program -fipa-type-escape -g" } */ + +extern void *malloc(__SIZE_TYPE__); + +struct S { + int i; +}; + +int main(int argc, char *argv[]) +{ + int i = argc; + struct S *p = malloc(sizeof (struct S)); + return p[i].i; +} diff --git a/gcc/testsuite/gcc.dg/pr43379.c b/gcc/testsuite/gcc.dg/pr43379.c new file mode 100644 index 00000000000..da4e6ba67ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr43379.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftracer -w" } */ + +void *foo(int i, int *p) +{ +lab: + if (p) *p = i; + goto *p; + return &&lab; +} + diff --git a/gcc/testsuite/gcc.dg/pr43402.c b/gcc/testsuite/gcc.dg/pr43402.c new file mode 100644 index 00000000000..82234c74a85 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr43402.c @@ -0,0 +1,58 @@ +/* { dg-do run } */ +/* { dg-options "-O1 -fno-inline" } */ +extern void abort (void); + +static int something; + +static int * converterData[2]={ + &something, &something, +}; + +static struct { + const char *name; + int type; +} const cnvNameType[] = { + { "bocu1", 1 }, + { "utf7", 1 }, + { "utf8", 1 } +}; + + +const int * getAlgorithmicTypeFromName(const char *realName); +const int * +getAlgorithmicTypeFromName(const char *realName) +{ + unsigned mid, start, limit; + unsigned lastMid; + int result; + start = 0; + limit = sizeof(cnvNameType)/sizeof(cnvNameType[0]); + mid = limit; + lastMid = 0xffffffff; + + for (;;) { + mid = (start + limit) / 2; + if (lastMid == mid) { /* Have we moved? */ + break; /* We haven't moved, and it wasn't found. */ + } + lastMid = mid; + result = __builtin_strcmp(realName, cnvNameType[mid].name); + + if (result < 0) { + limit = mid; + } else if (result > 0) { + start = mid; + } else { + return converterData[cnvNameType[mid].type]; + } + } + + return 0; +} + +int main (void) +{ + if (!getAlgorithmicTypeFromName ("utf8")) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr43419.c b/gcc/testsuite/gcc.dg/pr43419.c new file mode 100644 index 00000000000..a4306f04855 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr43419.c @@ -0,0 +1,19 @@ +/* { dg-do run } */ +/* { dg-options "-O1" } */ +/* { dg-add-options ieee } */ +#include <math.h> + +extern void abort (void); +void __attribute__((noinline)) f (double x) +{ + double pluszero = pow (x, 0.5); + double minuszero = sqrt (x); + if (signbit (pluszero) == signbit (minuszero)) + abort (); +} + +int main(void) +{ + f (-0.0); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr43360.c b/gcc/testsuite/gcc.dg/torture/pr43360.c new file mode 100644 index 00000000000..9ed9872db26 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr43360.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ + +int l_5_5_2 = 4; +int g_3[1][1]; + +void func_1 (void) +{ + for (g_3[0][0] = 1; g_3[0][0] < 8; g_3[0][0] += 7) { + int *l_6 = &g_3[0][0]; + *l_6 = l_5_5_2; + } +} + +int main (void) +{ + func_1 (); + if (g_3[0][0] != 11) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/push-1.c b/gcc/testsuite/gcc.target/i386/push-1.c index da9b39ec9b5..09464bf9229 100644 --- a/gcc/testsuite/gcc.target/i386/push-1.c +++ b/gcc/testsuite/gcc.target/i386/push-1.c @@ -12,4 +12,4 @@ bar (void) foo (x, x, x, x, 5); } -/* { dg-final { scan-assembler-not "movups" { xfail *-*-* } } } */ +/* { dg-final { scan-assembler-not "movups" { xfail { ! *-*-darwin* } } } } */ diff --git a/gcc/testsuite/gfortran.dg/assign-debug.f90 b/gcc/testsuite/gfortran.dg/assign-debug.f90 new file mode 100644 index 00000000000..bd441211242 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/assign-debug.f90 @@ -0,0 +1,8 @@ +! { dg-do compile } +! { dg-options "-fcompare-debug -O2" } + program test + integer i + common i + assign 2000 to i ! { dg-warning "Deleted feature: ASSIGN statement" } +2000 continue + end diff --git a/gcc/testsuite/gfortran.dg/cray_pointers_1.f90 b/gcc/testsuite/gfortran.dg/cray_pointers_1.f90 index b23a300feac..87ace6848bd 100644 --- a/gcc/testsuite/gfortran.dg/cray_pointers_1.f90 +++ b/gcc/testsuite/gfortran.dg/cray_pointers_1.f90 @@ -21,7 +21,7 @@ subroutine err3 real array(*) pointer (ipt, array) ipt = loc (target) - array = 0 ! { dg-error "Vector assignment" } + array = 0 ! { dg-error "upper bound in the last dimension" } end subroutine err3 subroutine err4 diff --git a/gcc/testsuite/gfortran.dg/namelist_27.f90 b/gcc/testsuite/gfortran.dg/namelist_27.f90 index 35fe032a62c..06381b11634 100644 --- a/gcc/testsuite/gfortran.dg/namelist_27.f90 +++ b/gcc/testsuite/gfortran.dg/namelist_27.f90 @@ -41,14 +41,14 @@ contains character(len=*), intent(in) :: name character(len=255) :: line - integer :: ios, idx + integer :: ios, idx, k logical :: first first = .true. status = 0 ios = 0 line = "" - do + do k=1,10 read (unit,'(a)',iostat=ios) line if (first) then first = .false. @@ -74,7 +74,7 @@ contains subroutine read_report (unit, status) integer :: unit, status - integer :: iuse, ios + integer :: iuse, ios, k !------------------ ! Namelist 'REPORT' !------------------ @@ -85,7 +85,7 @@ contains ! Loop to read namelist multiple times !------------------------------------- iuse = 0 - do + do k=1,5 !---------------------------------------- ! Preset namelist variables with defaults !---------------------------------------- diff --git a/gcc/testsuite/gfortran.dg/namelist_28.f90 b/gcc/testsuite/gfortran.dg/namelist_28.f90 index 53b1f0ff002..22bddf66239 100644 --- a/gcc/testsuite/gfortran.dg/namelist_28.f90 +++ b/gcc/testsuite/gfortran.dg/namelist_28.f90 @@ -27,12 +27,12 @@ contains character(len=*), intent(in) :: name character(len=255) :: line - integer :: ios, idx + integer :: ios, idx, k logical :: first first = .true. status = 0 - do + do k=1,25 line = "" read (unit,'(a)',iostat=ios) line if (ios < 0) then @@ -51,12 +51,13 @@ contains return end if end do + if (k.gt.10) call abort end subroutine position_nml subroutine read_report (unit, status) integer :: unit, status - integer :: iuse, ios + integer :: iuse, ios, k !------------------ ! Namelist 'REPORT' !------------------ @@ -66,7 +67,7 @@ contains ! Loop to read namelist multiple times !------------------------------------- iuse = 0 - do + do k=1,25 !---------------------------------------- ! Preset namelist variables with defaults !---------------------------------------- @@ -84,6 +85,7 @@ contains if (ios /= 0) exit iuse = iuse + 1 end do + if (k.gt.10) call abort status = ios end subroutine read_report diff --git a/gcc/testsuite/gfortran.dg/read_empty_file.f b/gcc/testsuite/gfortran.dg/read_empty_file.f new file mode 100644 index 00000000000..d4077481bda --- /dev/null +++ b/gcc/testsuite/gfortran.dg/read_empty_file.f @@ -0,0 +1,7 @@ +! { dg-do run } +! PR43320 Missing EOF on read from empty file. + open(8,status='scratch',form='formatted') ! Create empty file + read(8,'(a80)', end=123) ! Reading from an empty file should be an EOF + call abort +123 continue + end diff --git a/gcc/testsuite/gfortran.dg/read_eof_all.f90 b/gcc/testsuite/gfortran.dg/read_eof_all.f90 new file mode 100644 index 00000000000..db6def48716 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/read_eof_all.f90 @@ -0,0 +1,71 @@ +! { dg-do run } +! PR43265 Followup patch for miscellaneous EOF conditions. +! Eaxamples from Tobius Burnus + use iso_fortran_env + character(len=2) :: str, str2(2) + integer :: a, b, c, ios + str = '' + str2 = '' + + open(99,file='test.dat',access='stream',form='unformatted', status='replace') + write(99) ' ' + close(99) + + open(99,file='test.dat') + read(99, '(T7,i2)') i + close(99, status="delete") + if (i /= 0) call abort + + read(str(1:0), '(T7,i1)') i + if (i /= 0) call abort + + read(str,'(i2,/,i2)',end=111) a, b + call abort !stop 'ERROR: Expected EOF error (1)' + 111 continue + + read(str2,'(i2,/,i2)',end=112) a, b + + read(str2,'(i2,/,i2,/,i2)',end=113) a, b, c + call abort !stop 'ERROR: Expected EOF error (2)' + + 112 call abort !stop 'ERROR: Unexpected EOF (3)' + + 113 continue + read(str,'(i2,/,i2)',end=121,pad='no') a, b + call abort !stop 'ERROR: Expected EOF error (1)' + 121 continue + + read(str2(:),'(i2,/,i2)', end=122, pad='no') a, b + goto 125 + 122 call abort !stop 'ERROR: Expected no EOF error (2)' + 125 continue + + read(str2(:),'(i2,/,i2,/,i2)',end=123,pad='no') a, b, c + call abort !stop 'ERROR: Expected EOF error (3)' + 123 continue + + read(str(2:1),'(i2,/,i2)',end=131, pad='no') a, b + call abort !stop 'ERROR: Expected EOF error (1)' + 131 continue + + read(str2(:)(2:1),'(i2,/,i2)',end=132, pad='no') a, b + call abort !stop 'ERROR: Expected EOF error (2)' + 132 continue + + read(str2(:)(2:1),'(i2,/,i2,/,i2)',end=133,pad='no') a, b, c + call abort !stop 'ERROR: Expected EOF error (3)' + 133 continue + + read(str(2:1),'(i2,/,i2)',iostat=ios, pad='no') a, b + if (ios /= IOSTAT_END) call abort !stop 'ERROR: expected iostat /= 0 (1)' + + read(str2(:)(2:1),'(i2,/,i2)',iostat=ios, pad='no') a, b + if (ios /= IOSTAT_END) call abort !stop 'ERROR: expected iostat /= 0 (2)' + + read(str2(:)(2:1),'(i2,/,i2,/,i2)',iostat=ios,pad='no') a, b, c + if (ios /= IOSTAT_END) call abort !stop 'ERROR: expected iostat /= 0 (2)' + + ! print *, "success" + end + + diff --git a/gcc/testsuite/gnat.dg/socket1.adb b/gcc/testsuite/gnat.dg/socket1.adb index f1adf7a1f2c..a6bdade304b 100644 --- a/gcc/testsuite/gnat.dg/socket1.adb +++ b/gcc/testsuite/gnat.dg/socket1.adb @@ -1,4 +1,4 @@ --- { dg-do run } +-- { dg-do run { target { ! "*-*-solaris2*" } } } with GNAT.Sockets; use GNAT.Sockets; procedure socket1 is diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index e5ed9ec7006..01fefc306ef 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -1438,27 +1438,12 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b) return false; /* It must be possible to eliminate all phi nodes in B. If ssa form - is not up-to-date, we cannot eliminate any phis; however, if only - some symbols as whole are marked for renaming, this is not a problem, - as phi nodes for those symbols are irrelevant in updating anyway. */ + is not up-to-date and a name-mapping is registered, we cannot eliminate + any phis. Symbols marked for renaming are never a problem though. */ phis = phi_nodes (b); - if (!gimple_seq_empty_p (phis)) - { - gimple_stmt_iterator i; - - if (name_mappings_registered_p ()) - return false; - - for (i = gsi_start (phis); !gsi_end_p (i); gsi_next (&i)) - { - gimple phi = gsi_stmt (i); - - if (!is_gimple_reg (gimple_phi_result (phi)) - && !may_propagate_copy (gimple_phi_result (phi), - gimple_phi_arg_def (phi, 0))) - return false; - } - } + if (!gimple_seq_empty_p (phis) + && name_mappings_registered_p ()) + return false; return true; } @@ -1632,6 +1617,9 @@ gimple_merge_blocks (basic_block a, basic_block b) FOR_EACH_IMM_USE_STMT (stmt, iter, def) FOR_EACH_IMM_USE_ON_STMT (use_p, iter) SET_USE (use_p, use); + + if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def)) + SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use) = 1; } else replace_uses_by (def, use); diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index eae0c84cef5..326bf80ec9a 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -103,20 +103,28 @@ cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi) /* For conditions try harder and lookup single-argument PHI nodes. Only do so from the same basic-block though as other basic-blocks may be dead already. */ - if (TREE_CODE (lhs) == SSA_NAME) + if (TREE_CODE (lhs) == SSA_NAME + && !name_registered_for_update_p (lhs)) { gimple def_stmt = SSA_NAME_DEF_STMT (lhs); if (gimple_code (def_stmt) == GIMPLE_PHI && gimple_phi_num_args (def_stmt) == 1 - && gimple_bb (def_stmt) == gimple_bb (stmt)) + && gimple_bb (def_stmt) == gimple_bb (stmt) + && (TREE_CODE (PHI_ARG_DEF (def_stmt, 0)) != SSA_NAME + || !name_registered_for_update_p (PHI_ARG_DEF (def_stmt, + 0)))) lhs = PHI_ARG_DEF (def_stmt, 0); } - if (TREE_CODE (rhs) == SSA_NAME) + if (TREE_CODE (rhs) == SSA_NAME + && !name_registered_for_update_p (rhs)) { gimple def_stmt = SSA_NAME_DEF_STMT (rhs); if (gimple_code (def_stmt) == GIMPLE_PHI && gimple_phi_num_args (def_stmt) == 1 - && gimple_bb (def_stmt) == gimple_bb (stmt)) + && gimple_bb (def_stmt) == gimple_bb (stmt) + && (TREE_CODE (PHI_ARG_DEF (def_stmt, 0)) != SSA_NAME + || !name_registered_for_update_p (PHI_ARG_DEF (def_stmt, + 0)))) rhs = PHI_ARG_DEF (def_stmt, 0); } val = fold_binary_loc (loc, gimple_cond_code (stmt), diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 5ae47f0c10f..a1aca981d6f 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -564,6 +564,7 @@ replace_goto_queue (struct leh_tf_state *tf) if (tf->goto_queue_active == 0) return; replace_goto_queue_stmt_list (tf->top_p_seq, tf); + replace_goto_queue_stmt_list (eh_seq, tf); } /* Add a new record to the goto queue contained in TF. NEW_STMT is the @@ -644,7 +645,6 @@ record_in_goto_queue_label (struct leh_tf_state *tf, treemple stmt, tree label) labels. */ new_stmt = stmt; record_in_goto_queue (tf, new_stmt, index, true); - } /* For any GIMPLE_GOTO or GIMPLE_RETURN, decide whether it leaves a try_finally @@ -1531,6 +1531,7 @@ lower_try_finally (struct leh_state *state, gimple tp) struct leh_tf_state this_tf; struct leh_state this_state; int ndests; + gimple_seq old_eh_seq; /* Process the try block. */ @@ -1547,6 +1548,9 @@ lower_try_finally (struct leh_state *state, gimple tp) this_state.ehp_region = state->ehp_region; this_state.tf = &this_tf; + old_eh_seq = eh_seq; + eh_seq = NULL; + lower_eh_constructs_1 (&this_state, gimple_try_eval(tp)); /* Determine if the try block is escaped through the bottom. */ @@ -1602,6 +1606,20 @@ lower_try_finally (struct leh_state *state, gimple tp) if (this_tf.goto_queue_map) pointer_map_destroy (this_tf.goto_queue_map); + /* If there was an old (aka outer) eh_seq, append the current eh_seq. + If there was no old eh_seq, then the append is trivially already done. */ + if (old_eh_seq) + { + if (eh_seq == NULL) + eh_seq = old_eh_seq; + else + { + gimple_seq new_eh_seq = eh_seq; + eh_seq = old_eh_seq; + gimple_seq_add_seq(&eh_seq, new_eh_seq); + } + } + return this_tf.top_p_seq; } diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index f3c420475df..e0928b9fe03 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1650,6 +1650,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, bb->frequency, copy_basic_block->frequency); } + stmt = cgraph_redirect_edge_call_stmt_to_callee (edge); } break; diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c index 32aa464948b..ac1641fc8e8 100644 --- a/gcc/tree-outof-ssa.c +++ b/gcc/tree-outof-ssa.c @@ -140,10 +140,12 @@ set_location_for_edge (edge e) } } -/* Emit insns to copy SRC into DEST converting SRC if necessary. */ +/* Emit insns to copy SRC into DEST converting SRC if necessary. As + SRC/DEST might be BLKmode memory locations SIZEEXP is a tree from + which we deduce the size to copy in that case. */ static inline rtx -emit_partition_copy (rtx dest, rtx src, int unsignedsrcp) +emit_partition_copy (rtx dest, rtx src, int unsignedsrcp, tree sizeexp) { rtx seq; @@ -151,7 +153,13 @@ emit_partition_copy (rtx dest, rtx src, int unsignedsrcp) if (GET_MODE (src) != VOIDmode && GET_MODE (src) != GET_MODE (dest)) src = convert_to_mode (GET_MODE (dest), src, unsignedsrcp); - emit_move_insn (dest, src); + if (GET_MODE (src) == BLKmode) + { + gcc_assert (GET_MODE (dest) == BLKmode); + emit_block_move (dest, src, expr_size (sizeexp), BLOCK_OP_NORMAL); + } + else + emit_move_insn (dest, src); seq = get_insns (); end_sequence (); @@ -164,6 +172,7 @@ emit_partition_copy (rtx dest, rtx src, int unsignedsrcp) static void insert_partition_copy_on_edge (edge e, int dest, int src, source_location locus) { + tree var; rtx seq; if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -183,10 +192,11 @@ insert_partition_copy_on_edge (edge e, int dest, int src, source_location locus) if (locus) set_curr_insn_source_location (locus); + var = partition_to_var (SA.map, src); seq = emit_partition_copy (SA.partition_to_pseudo[dest], SA.partition_to_pseudo[src], - TYPE_UNSIGNED (TREE_TYPE ( - partition_to_var (SA.map, src)))); + TYPE_UNSIGNED (TREE_TYPE (var)), + var); insert_insn_on_edge (seq, e); } @@ -232,6 +242,11 @@ insert_value_copy_on_edge (edge e, int dest, tree src, source_location locus) x = expand_expr (src, NULL, src_mode, EXPAND_NORMAL); x = convert_modes (dest_mode, src_mode, x, unsignedp); } + else if (src_mode == BLKmode) + { + x = SA.partition_to_pseudo[dest]; + store_expr (src, x, 0, false); + } else x = expand_expr (src, SA.partition_to_pseudo[dest], dest_mode, EXPAND_NORMAL); @@ -269,9 +284,13 @@ insert_rtx_to_part_on_edge (edge e, int dest, rtx src, int unsignedsrcp, if (locus) set_curr_insn_source_location (locus); + /* We give the destination as sizeexp in case src/dest are BLKmode + mems. Usually we give the source. As we result from SSA names + the left and right size should be the same (and no WITH_SIZE_EXPR + involved), so it doesn't matter. */ seq = emit_partition_copy (SA.partition_to_pseudo[dest], - src, - unsignedsrcp); + src, unsignedsrcp, + partition_to_var (SA.map, dest)); insert_insn_on_edge (seq, e); } @@ -282,6 +301,7 @@ insert_rtx_to_part_on_edge (edge e, int dest, rtx src, int unsignedsrcp, static void insert_part_to_rtx_on_edge (edge e, rtx dest, int src, source_location locus) { + tree var; rtx seq; if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -300,10 +320,11 @@ insert_part_to_rtx_on_edge (edge e, rtx dest, int src, source_location locus) if (locus) set_curr_insn_source_location (locus); + var = partition_to_var (SA.map, src); seq = emit_partition_copy (dest, SA.partition_to_pseudo[src], - TYPE_UNSIGNED (TREE_TYPE ( - partition_to_var (SA.map, src)))); + TYPE_UNSIGNED (TREE_TYPE (var)), + var); insert_insn_on_edge (seq, e); } diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index d32ef387d19..e1dd0d777e3 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -1664,6 +1664,7 @@ create_access_replacement (struct access *access) DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base); DECL_ARTIFICIAL (repl) = 1; + DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base); if (DECL_NAME (access->base) && !DECL_IGNORED_P (access->base) @@ -1676,11 +1677,10 @@ create_access_replacement (struct access *access) SET_DECL_DEBUG_EXPR (repl, access->expr); DECL_DEBUG_EXPR_IS_FROM (repl) = 1; - DECL_IGNORED_P (repl) = 0; + TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base); } - - DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base); - TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base); + else + TREE_NO_WARNING (repl) = 1; if (dump_file) { @@ -4048,6 +4048,26 @@ convert_callers (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments) return; } +/* Create an abstract origin declaration for OLD_DECL and make it an abstract + origin of the provided decl so that there are preserved parameters for debug + information. */ + +static void +create_abstract_origin (tree old_decl) +{ + if (!DECL_ABSTRACT_ORIGIN (old_decl)) + { + tree new_decl = copy_node (old_decl); + + DECL_ABSTRACT (new_decl) = 1; + SET_DECL_ASSEMBLER_NAME (new_decl, NULL_TREE); + SET_DECL_RTL (new_decl, NULL); + DECL_STRUCT_FUNCTION (new_decl) = NULL; + DECL_ARTIFICIAL (old_decl) = 1; + DECL_ABSTRACT_ORIGIN (old_decl) = new_decl; + } +} + /* Perform all the modification required in IPA-SRA for NODE to have parameters as given in ADJUSTMENTS. */ @@ -4059,6 +4079,7 @@ modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments) ipa_modify_formal_parameters (alias->decl, adjustments, "ISRA"); /* current_function_decl must be handled last, after same_body aliases, as following functions will use what it computed. */ + create_abstract_origin (current_function_decl); ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA"); scan_function (sra_ipa_modify_expr, sra_ipa_modify_assign, replace_removed_params_ssa_names, false, adjustments); diff --git a/gcc/tree.h b/gcc/tree.h index 7e51ea624ae..bc3cd29453e 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5131,6 +5131,7 @@ extern unsigned int update_alignment_for_field (record_layout_info, tree, unsigned int); /* varasm.c */ extern void make_decl_rtl (tree); +extern rtx make_decl_rtl_for_debug (tree); extern void make_decl_one_only (tree, tree); extern int supports_one_only (void); extern void resolve_unique_section (tree, int, int); diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 430e16830a8..c11d11953f4 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -113,6 +113,7 @@ #include "params.h" #include "diagnostic.h" #include "pointer-set.h" +#include "recog.h" /* var-tracking.c assumes that tree code with the same value as VALUE rtx code has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl. @@ -405,9 +406,8 @@ static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, HOST_WIDE_INT *); static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, HOST_WIDE_INT *); -static void bb_stack_adjust_offset (basic_block); static bool vt_stack_adjustments (void); -static rtx adjust_stack_reference (rtx, HOST_WIDE_INT); +static rtx compute_cfa_pointer (HOST_WIDE_INT); static hashval_t variable_htab_hash (const void *); static int variable_htab_eq (const void *, const void *); static void variable_htab_free (void *); @@ -490,7 +490,7 @@ static void vt_emit_notes (void); static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *); static void vt_add_function_parameters (void); -static void vt_initialize (void); +static bool vt_initialize (void); static void vt_finalize (void); /* Given a SET, calculate the amount of stack adjustment it contains @@ -617,29 +617,6 @@ insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre, } } -/* Compute stack adjustment in basic block BB. */ - -static void -bb_stack_adjust_offset (basic_block bb) -{ - HOST_WIDE_INT offset; - unsigned int i; - micro_operation *mo; - - offset = VTI (bb)->in.stack_adjust; - for (i = 0; VEC_iterate (micro_operation, VTI (bb)->mos, i, mo); i++) - { - if (mo->type == MO_ADJUST) - offset += mo->u.adjust; - else if (mo->type != MO_CALL) - { - if (MEM_P (mo->u.loc)) - mo->u.loc = adjust_stack_reference (mo->u.loc, -offset); - } - } - VTI (bb)->out.stack_adjust = offset; -} - /* Compute stack adjustments for all blocks by traversing DFS tree. Return true when the adjustments on all incoming edges are consistent. Heavily borrowed from pre_and_rev_post_order_compute. */ @@ -652,6 +629,7 @@ vt_stack_adjustments (void) /* Initialize entry block. */ VTI (ENTRY_BLOCK_PTR)->visited = true; + VTI (ENTRY_BLOCK_PTR)->in.stack_adjust = INCOMING_FRAME_SP_OFFSET; VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET; /* Allocate stack for back-tracking up CFG. */ @@ -675,9 +653,22 @@ vt_stack_adjustments (void) /* Check if the edge destination has been visited yet. */ if (!VTI (dest)->visited) { + rtx insn; + HOST_WIDE_INT pre, post, offset; VTI (dest)->visited = true; - VTI (dest)->in.stack_adjust = VTI (src)->out.stack_adjust; - bb_stack_adjust_offset (dest); + VTI (dest)->in.stack_adjust = offset = VTI (src)->out.stack_adjust; + + if (dest != EXIT_BLOCK_PTR) + for (insn = BB_HEAD (dest); + insn != NEXT_INSN (BB_END (dest)); + insn = NEXT_INSN (insn)) + if (INSN_P (insn)) + { + insn_stack_adjust_offset_pre_post (insn, &pre, &post); + offset += pre + post; + } + + VTI (dest)->out.stack_adjust = offset; if (EDGE_COUNT (dest->succs) > 0) /* Since the DEST node has been visited for the first @@ -706,13 +697,12 @@ vt_stack_adjustments (void) return true; } -/* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative - to the argument pointer. Return the new rtx. */ +/* Compute a CFA-based value for the stack pointer. */ static rtx -adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment) +compute_cfa_pointer (HOST_WIDE_INT adjustment) { - rtx addr, cfa, tmp; + rtx cfa; #ifdef FRAME_POINTER_CFA_OFFSET adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl); @@ -722,12 +712,216 @@ adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment) cfa = plus_constant (arg_pointer_rtx, adjustment); #endif - addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa); - tmp = simplify_rtx (addr); - if (tmp) - addr = tmp; + return cfa; +} + +/* Adjustment for hard_frame_pointer_rtx to cfa base reg, + or -1 if the replacement shouldn't be done. */ +static HOST_WIDE_INT hard_frame_pointer_adjustment = -1; + +/* Data for adjust_mems callback. */ + +struct adjust_mem_data +{ + bool store; + enum machine_mode mem_mode; + HOST_WIDE_INT stack_adjust; + rtx side_effects; +}; + +/* Helper function for adjusting used MEMs. */ + +static rtx +adjust_mems (rtx loc, const_rtx old_rtx, void *data) +{ + struct adjust_mem_data *amd = (struct adjust_mem_data *) data; + rtx mem, addr = loc, tem; + enum machine_mode mem_mode_save; + bool store_save; + switch (GET_CODE (loc)) + { + case REG: + /* Don't do any sp or fp replacements outside of MEM addresses. */ + if (amd->mem_mode == VOIDmode) + return loc; + if (loc == stack_pointer_rtx + && !frame_pointer_needed) + return compute_cfa_pointer (amd->stack_adjust); + else if (loc == hard_frame_pointer_rtx + && frame_pointer_needed + && hard_frame_pointer_adjustment != -1) + return compute_cfa_pointer (hard_frame_pointer_adjustment); + return loc; + case MEM: + mem = loc; + if (!amd->store) + { + mem = targetm.delegitimize_address (mem); + if (mem != loc && !MEM_P (mem)) + return simplify_replace_fn_rtx (mem, old_rtx, adjust_mems, data); + } + + addr = XEXP (mem, 0); + mem_mode_save = amd->mem_mode; + amd->mem_mode = GET_MODE (mem); + store_save = amd->store; + amd->store = false; + addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data); + amd->store = store_save; + amd->mem_mode = mem_mode_save; + if (mem == loc) + addr = targetm.delegitimize_address (addr); + if (addr != XEXP (mem, 0)) + mem = replace_equiv_address_nv (mem, addr); + if (!amd->store) + mem = avoid_constant_pool_reference (mem); + return mem; + case PRE_INC: + case PRE_DEC: + addr = gen_rtx_PLUS (GET_MODE (loc), XEXP (loc, 0), + GEN_INT (GET_CODE (loc) == PRE_INC + ? GET_MODE_SIZE (amd->mem_mode) + : -GET_MODE_SIZE (amd->mem_mode))); + case POST_INC: + case POST_DEC: + if (addr == loc) + addr = XEXP (loc, 0); + gcc_assert (amd->mem_mode != VOIDmode && amd->mem_mode != BLKmode); + addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data); + tem = gen_rtx_PLUS (GET_MODE (loc), XEXP (loc, 0), + GEN_INT ((GET_CODE (loc) == PRE_INC + || GET_CODE (loc) == POST_INC) + ? GET_MODE_SIZE (amd->mem_mode) + : -GET_MODE_SIZE (amd->mem_mode))); + amd->side_effects = alloc_EXPR_LIST (0, + gen_rtx_SET (VOIDmode, + XEXP (loc, 0), + tem), + amd->side_effects); + return addr; + case PRE_MODIFY: + addr = XEXP (loc, 1); + case POST_MODIFY: + if (addr == loc) + addr = XEXP (loc, 0); + gcc_assert (amd->mem_mode != VOIDmode); + addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data); + amd->side_effects = alloc_EXPR_LIST (0, + gen_rtx_SET (VOIDmode, + XEXP (loc, 0), + XEXP (loc, 1)), + amd->side_effects); + return addr; + case SUBREG: + /* First try without delegitimization of whole MEMs and + avoid_constant_pool_reference, which is more likely to succeed. */ + store_save = amd->store; + amd->store = true; + addr = simplify_replace_fn_rtx (SUBREG_REG (loc), old_rtx, adjust_mems, + data); + amd->store = store_save; + mem = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data); + if (mem == SUBREG_REG (loc)) + return loc; + tem = simplify_gen_subreg (GET_MODE (loc), mem, + GET_MODE (SUBREG_REG (loc)), + SUBREG_BYTE (loc)); + if (tem) + return tem; + tem = simplify_gen_subreg (GET_MODE (loc), addr, + GET_MODE (SUBREG_REG (loc)), + SUBREG_BYTE (loc)); + if (tem) + return tem; + return gen_rtx_raw_SUBREG (GET_MODE (loc), addr, SUBREG_BYTE (loc)); + default: + break; + } + return NULL_RTX; +} + +/* Helper function for replacement of uses. */ - return replace_equiv_address_nv (mem, addr); +static void +adjust_mem_uses (rtx *x, void *data) +{ + rtx new_x = simplify_replace_fn_rtx (*x, NULL_RTX, adjust_mems, data); + if (new_x != *x) + validate_change (NULL_RTX, x, new_x, true); +} + +/* Helper function for replacement of stores. */ + +static void +adjust_mem_stores (rtx loc, const_rtx expr, void *data) +{ + if (MEM_P (loc)) + { + rtx new_dest = simplify_replace_fn_rtx (SET_DEST (expr), NULL_RTX, + adjust_mems, data); + if (new_dest != SET_DEST (expr)) + { + rtx xexpr = CONST_CAST_RTX (expr); + validate_change (NULL_RTX, &SET_DEST (xexpr), new_dest, true); + } + } +} + +/* Simplify INSN. Remove all {PRE,POST}_{INC,DEC,MODIFY} rtxes, + replace them with their value in the insn and add the side-effects + as other sets to the insn. */ + +static void +adjust_insn (basic_block bb, rtx insn) +{ + struct adjust_mem_data amd; + rtx set; + amd.mem_mode = VOIDmode; + amd.stack_adjust = -VTI (bb)->out.stack_adjust; + amd.side_effects = NULL_RTX; + + amd.store = true; + note_stores (PATTERN (insn), adjust_mem_stores, &amd); + + amd.store = false; + note_uses (&PATTERN (insn), adjust_mem_uses, &amd); + + /* For read-only MEMs containing some constant, prefer those + constants. */ + set = single_set (insn); + if (set && MEM_P (SET_SRC (set)) && MEM_READONLY_P (SET_SRC (set))) + { + rtx note = find_reg_equal_equiv_note (insn); + + if (note && CONSTANT_P (XEXP (note, 0))) + validate_change (NULL_RTX, &SET_SRC (set), XEXP (note, 0), true); + } + + if (amd.side_effects) + { + rtx *pat, new_pat, s; + int i, oldn, newn; + + pat = &PATTERN (insn); + if (GET_CODE (*pat) == COND_EXEC) + pat = &COND_EXEC_CODE (*pat); + if (GET_CODE (*pat) == PARALLEL) + oldn = XVECLEN (*pat, 0); + else + oldn = 1; + for (s = amd.side_effects, newn = 0; s; newn++) + s = XEXP (s, 1); + new_pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (oldn + newn)); + if (GET_CODE (*pat) == PARALLEL) + for (i = 0; i < oldn; i++) + XVECEXP (new_pat, 0, i) = XVECEXP (*pat, 0, i); + else + XVECEXP (new_pat, 0, 0) = *pat; + for (s = amd.side_effects, i = oldn; i < oldn + newn; i++, s = XEXP (s, 1)) + XVECEXP (new_pat, 0, i) = XEXP (s, 0); + free_EXPR_LIST_list (&amd.side_effects); + validate_change (NULL_RTX, pat, new_pat, true); + } } /* Return true if a decl_or_value DV is a DECL or NULL. */ @@ -2974,6 +3168,67 @@ canonicalize_values_star (void **slot, void *data) return 1; } +/* Bind one-part variables to the canonical value in an equivalence + set. Not doing this causes dataflow convergence failure in rare + circumstances, see PR42873. Unfortunately we can't do this + efficiently as part of canonicalize_values_star, since we may not + have determined or even seen the canonical value of a set when we + get to a variable that references another member of the set. */ + +static int +canonicalize_vars_star (void **slot, void *data) +{ + dataflow_set *set = (dataflow_set *)data; + variable var = (variable) *slot; + decl_or_value dv = var->dv; + location_chain node; + rtx cval; + decl_or_value cdv; + void **cslot; + variable cvar; + location_chain cnode; + + if (!dv_onepart_p (dv) || dv_is_value_p (dv)) + return 1; + + gcc_assert (var->n_var_parts == 1); + + node = var->var_part[0].loc_chain; + + if (GET_CODE (node->loc) != VALUE) + return 1; + + gcc_assert (!node->next); + cval = node->loc; + + /* Push values to the canonical one. */ + cdv = dv_from_value (cval); + cslot = shared_hash_find_slot_noinsert (set->vars, cdv); + if (!cslot) + return 1; + cvar = (variable)*cslot; + gcc_assert (cvar->n_var_parts == 1); + + cnode = cvar->var_part[0].loc_chain; + + /* CVAL is canonical if its value list contains non-VALUEs or VALUEs + that are not “more canonical” than it. */ + if (GET_CODE (cnode->loc) != VALUE + || !canon_value_cmp (cnode->loc, cval)) + return 1; + + /* CVAL was found to be non-canonical. Change the variable to point + to the canonical VALUE. */ + gcc_assert (!cnode->next); + cval = cnode->loc; + + slot = set_slot_part (set, cval, slot, dv, 0, + node->init, node->set_src); + slot = clobber_slot_part (set, cval, slot, 0, node->set_src); + + return 1; +} + /* Combine variable or value in *S1SLOT (in DSM->cur) with the corresponding entry in DSM->src. Multi-part variables are combined with variable_union, whereas onepart dvs are combined with @@ -3636,6 +3891,7 @@ dataflow_post_merge_adjust (dataflow_set *set, dataflow_set **permp) htab_traverse (shared_hash_htab ((*permp)->vars), variable_post_merge_perm_vals, &dfpm); htab_traverse (shared_hash_htab (set->vars), canonicalize_values_star, set); + htab_traverse (shared_hash_htab (set->vars), canonicalize_vars_star, set); } /* Return a node whose loc is a MEM that refers to EXPR in the @@ -4326,6 +4582,10 @@ var_lowpart (enum machine_mode mode, rtx loc) return gen_rtx_REG_offset (loc, mode, regno, offset); } +/* arg_pointer_rtx resp. frame_pointer_rtx if stack_pointer_rtx or + hard_frame_pointer_rtx is being mapped to it. */ +static rtx cfa_base_rtx; + /* Carry information about uses and stores while walking rtx. */ struct count_use_info @@ -4371,6 +4631,17 @@ find_use_val (rtx x, enum machine_mode mode, struct count_use_info *cui) return NULL; } +/* Helper function to get mode of MEM's address. */ + +static inline enum machine_mode +get_address_mode (rtx mem) +{ + enum machine_mode mode = GET_MODE (XEXP (mem, 0)); + if (mode != VOIDmode) + return mode; + return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem)); +} + /* Replace all registers and addresses in an expression with VALUE expressions that map back to them, unless the expression is a register. If no mapping is or can be performed, returns NULL. */ @@ -4382,9 +4653,8 @@ replace_expr_with_values (rtx loc) return NULL; else if (MEM_P (loc)) { - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (loc)); - cselib_val *addr = cselib_lookup (XEXP (loc, 0), address_mode, 0); + cselib_val *addr = cselib_lookup (XEXP (loc, 0), + get_address_mode (loc), 0); if (addr) return replace_equiv_address_nv (loc, addr->val_rtx); else @@ -4409,12 +4679,15 @@ use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep) if (track_expr_p (PAT_VAR_LOCATION_DECL (loc), false)) { rtx ploc = PAT_VAR_LOCATION_LOC (loc); - cselib_val *val = cselib_lookup (ploc, GET_MODE (loc), 1); + if (! VAR_LOC_UNKNOWN_P (ploc)) + { + cselib_val *val = cselib_lookup (ploc, GET_MODE (loc), 1); - /* ??? flag_float_store and volatile mems are never - given values, but we could in theory use them for - locations. */ - gcc_assert (val || 1); + /* ??? flag_float_store and volatile mems are never + given values, but we could in theory use them for + locations. */ + gcc_assert (val || 1); + } return MO_VAL_LOC; } else @@ -4429,7 +4702,8 @@ use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep) { if (REG_P (loc) || (find_use_val (loc, GET_MODE (loc), cui) - && cselib_lookup (XEXP (loc, 0), GET_MODE (loc), 0))) + && cselib_lookup (XEXP (loc, 0), + get_address_mode (loc), 0))) return MO_VAL_SET; } else @@ -4446,6 +4720,8 @@ use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep) { gcc_assert (REGNO (loc) < FIRST_PSEUDO_REGISTER); + if (loc == cfa_base_rtx) + return MO_CLOBBER; expr = REG_EXPR (loc); if (!expr) @@ -4490,30 +4766,6 @@ log_op_type (rtx x, basic_block bb, rtx insn, fputc ('\n', out); } -/* Adjust sets if needed. Currently this optimizes read-only MEM loads - if REG_EQUAL/REG_EQUIV note is present. */ - -static void -adjust_sets (rtx insn, struct cselib_set *sets, int n_sets) -{ - if (n_sets == 1 && MEM_P (sets[0].src) && MEM_READONLY_P (sets[0].src)) - { - /* For read-only MEMs containing some constant, prefer those - constants. */ - rtx note = find_reg_equal_equiv_note (insn), src; - - if (note && CONSTANT_P (XEXP (note, 0))) - { - sets[0].src = src = XEXP (note, 0); - if (GET_CODE (PATTERN (insn)) == COND_EXEC) - src = gen_rtx_IF_THEN_ELSE (GET_MODE (sets[0].dest), - COND_EXEC_TEST (PATTERN (insn)), - src, sets[0].dest); - sets[0].src_elt = cselib_lookup (src, GET_MODE (sets[0].dest), 1); - } - } -} - /* Tell whether the CONCAT used to holds a VALUE and its location needs value resolution, i.e., an attempt of mapping the location back to other incoming values. */ @@ -4548,6 +4800,33 @@ preserve_value (cselib_val *val) VEC_safe_push (rtx, heap, preserved_values, val->val_rtx); } +/* Helper function for MO_VAL_LOC handling. Return non-zero if + any rtxes not suitable for CONST use not replaced by VALUEs + are discovered. */ + +static int +non_suitable_const (rtx *x, void *data ATTRIBUTE_UNUSED) +{ + if (*x == NULL_RTX) + return 0; + + switch (GET_CODE (*x)) + { + case REG: + case DEBUG_EXPR: + case PC: + case SCRATCH: + case CC0: + case ASM_INPUT: + case ASM_OPERANDS: + return 1; + case MEM: + return !MEM_READONLY_P (*x); + default: + return 0; + } +} + /* Add uses (register and memory references) LOC which will be tracked to VTI (bb)->mos. INSN is instruction which the LOC is part of. */ @@ -4577,11 +4856,14 @@ add_uses (rtx *ploc, void *data) gcc_assert (cui->sets); if (MEM_P (vloc) - && !REG_P (XEXP (vloc, 0)) && !MEM_P (XEXP (vloc, 0))) + && !REG_P (XEXP (vloc, 0)) + && !MEM_P (XEXP (vloc, 0)) + && (GET_CODE (XEXP (vloc, 0)) != PLUS + || XEXP (XEXP (vloc, 0), 0) != cfa_base_rtx + || !CONST_INT_P (XEXP (XEXP (vloc, 0), 1)))) { rtx mloc = vloc; - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc)); + enum machine_mode address_mode = get_address_mode (mloc); cselib_val *val = cselib_lookup (XEXP (mloc, 0), address_mode, 0); @@ -4601,8 +4883,12 @@ add_uses (rtx *ploc, void *data) } } - if (!VAR_LOC_UNKNOWN_P (vloc) - && (val = find_use_val (vloc, GET_MODE (oloc), cui))) + if (CONSTANT_P (vloc) + && (GET_CODE (vloc) != CONST + || for_each_rtx (&vloc, non_suitable_const, NULL))) + /* For constants don't look up any value. */; + else if (!VAR_LOC_UNKNOWN_P (vloc) + && (val = find_use_val (vloc, GET_MODE (oloc), cui))) { enum machine_mode mode2; enum micro_operation_type type2; @@ -4646,11 +4932,14 @@ add_uses (rtx *ploc, void *data) gcc_assert (cui->sets); if (MEM_P (oloc) - && !REG_P (XEXP (oloc, 0)) && !MEM_P (XEXP (oloc, 0))) + && !REG_P (XEXP (oloc, 0)) + && !MEM_P (XEXP (oloc, 0)) + && (GET_CODE (XEXP (oloc, 0)) != PLUS + || XEXP (XEXP (oloc, 0), 0) != cfa_base_rtx + || !CONST_INT_P (XEXP (XEXP (oloc, 0), 1)))) { rtx mloc = oloc; - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc)); + enum machine_mode address_mode = get_address_mode (mloc); cselib_val *val = cselib_lookup (XEXP (mloc, 0), address_mode, 0); @@ -4814,21 +5103,6 @@ reverse_op (rtx val, const_rtx expr) return gen_rtx_CONCAT (GET_MODE (v->val_rtx), v->val_rtx, ret); } -/* Return SRC, or, if it is a read-only MEM for which adjust_sets - replated it with a constant from REG_EQUIV/REG_EQUAL note, - that constant. */ - -static inline rtx -get_adjusted_src (struct count_use_info *cui, rtx src) -{ - if (cui->n_sets == 1 - && MEM_P (src) - && MEM_READONLY_P (src) - && CONSTANT_P (cui->sets[0].src)) - return cui->sets[0].src; - return src; -} - /* Add stores (register and memory references) LOC which will be tracked to VTI (bb)->mos. EXPR is the RTL expression containing the store. CUIP->insn is instruction which the LOC is part of. */ @@ -4854,6 +5128,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip) if (REG_P (loc)) { + gcc_assert (loc != cfa_base_rtx); if ((GET_CODE (expr) == CLOBBER && type != MO_VAL_SET) || !(track_p = use_type (loc, NULL, &mode2) == MO_USE) || GET_CODE (expr) == CLOBBER) @@ -4864,10 +5139,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip) else { if (GET_CODE (expr) == SET && SET_DEST (expr) == loc) - { - src = get_adjusted_src (cui, SET_SRC (expr)); - src = var_lowpart (mode2, src); - } + src = var_lowpart (mode2, SET_SRC (expr)); loc = var_lowpart (mode2, loc); if (src == NULL) @@ -4877,10 +5149,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip) } else { - rtx xexpr = CONST_CAST_RTX (expr); - - if (SET_SRC (expr) != src) - xexpr = gen_rtx_SET (VOIDmode, loc, src); + rtx xexpr = gen_rtx_SET (VOIDmode, loc, src); if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc))) mo.type = MO_COPY; else @@ -4895,12 +5164,16 @@ add_stores (rtx loc, const_rtx expr, void *cuip) || cui->sets)) { if (MEM_P (loc) && type == MO_VAL_SET - && !REG_P (XEXP (loc, 0)) && !MEM_P (XEXP (loc, 0))) + && !REG_P (XEXP (loc, 0)) + && !MEM_P (XEXP (loc, 0)) + && (GET_CODE (XEXP (loc, 0)) != PLUS + || XEXP (XEXP (loc, 0), 0) != cfa_base_rtx + || !CONST_INT_P (XEXP (XEXP (loc, 0), 1)))) { rtx mloc = loc; - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc)); - cselib_val *val = cselib_lookup (XEXP (mloc, 0), address_mode, 0); + enum machine_mode address_mode = get_address_mode (mloc); + cselib_val *val = cselib_lookup (XEXP (mloc, 0), + address_mode, 0); if (val && !cselib_preserved_value_p (val)) { @@ -4924,10 +5197,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip) else { if (GET_CODE (expr) == SET && SET_DEST (expr) == loc) - { - src = get_adjusted_src (cui, SET_SRC (expr)); - src = var_lowpart (mode2, src); - } + src = var_lowpart (mode2, SET_SRC (expr)); loc = var_lowpart (mode2, loc); if (src == NULL) @@ -4937,10 +5207,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip) } else { - rtx xexpr = CONST_CAST_RTX (expr); - - if (SET_SRC (expr) != src) - xexpr = gen_rtx_SET (VOIDmode, loc, src); + rtx xexpr = gen_rtx_SET (VOIDmode, loc, src); if (same_variable_part_p (SET_SRC (xexpr), MEM_EXPR (loc), INT_MEM_OFFSET (loc))) @@ -4997,13 +5264,12 @@ add_stores (rtx loc, const_rtx expr, void *cuip) } else if (resolve && GET_CODE (mo.u.loc) == SET) { - src = get_adjusted_src (cui, SET_SRC (expr)); - nloc = replace_expr_with_values (src); + nloc = replace_expr_with_values (SET_SRC (expr)); /* Avoid the mode mismatch between oexpr and expr. */ if (!nloc && mode != mode2) { - nloc = src; + nloc = SET_SRC (expr); gcc_assert (oloc == SET_DEST (expr)); } @@ -5102,8 +5368,6 @@ add_with_sets (rtx insn, struct cselib_set *sets, int n_sets) cselib_hook_called = true; - adjust_sets (insn, sets, n_sets); - cui.insn = insn; cui.bb = bb; cui.sets = sets; @@ -5337,6 +5601,11 @@ compute_bb_dataflow (basic_block bb) VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT); } + else if (!VAR_LOC_UNKNOWN_P (PAT_VAR_LOCATION_LOC (vloc))) + set_variable_part (out, PAT_VAR_LOCATION_LOC (vloc), + dv_from_decl (var), 0, + VAR_INIT_STATUS_INITIALIZED, NULL_RTX, + INSERT); } break; @@ -6690,7 +6959,7 @@ emit_note_insn_var_location (void **varp, void *data) complete = true; last_limit = 0; n_var_parts = 0; - if (!MAY_HAVE_DEBUG_STMTS) + if (!MAY_HAVE_DEBUG_INSNS) { for (i = 0; i < var->n_var_parts; i++) if (var->var_part[i].cur_loc == NULL && var->var_part[i].loc_chain) @@ -6731,6 +7000,8 @@ emit_note_insn_var_location (void **varp, void *data) } loc[n_var_parts] = loc2; mode = GET_MODE (var->var_part[i].cur_loc); + if (mode == VOIDmode && dv_onepart_p (var->dv)) + mode = DECL_MODE (decl); for (lc = var->var_part[i].loc_chain; lc; lc = lc->next) if (var->var_part[i].cur_loc == lc->loc) { @@ -7252,6 +7523,11 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set) VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT); } + else if (!VAR_LOC_UNKNOWN_P (PAT_VAR_LOCATION_LOC (vloc))) + set_variable_part (set, PAT_VAR_LOCATION_LOC (vloc), + dv_from_decl (var), 0, + VAR_INIT_STATUS_INITIALIZED, NULL_RTX, + INSERT); emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars); } @@ -7688,19 +7964,115 @@ vt_add_function_parameters (void) } +/* Return true if INSN in the prologue initializes hard_frame_pointer_rtx. */ + +static bool +fp_setter (rtx insn) +{ + rtx pat = PATTERN (insn); + if (RTX_FRAME_RELATED_P (insn)) + { + rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); + if (expr) + pat = XEXP (expr, 0); + } + if (GET_CODE (pat) == SET) + return SET_DEST (pat) == hard_frame_pointer_rtx; + else if (GET_CODE (pat) == PARALLEL) + { + int i; + for (i = XVECLEN (pat, 0) - 1; i >= 0; i--) + if (GET_CODE (XVECEXP (pat, 0, i)) == SET + && SET_DEST (XVECEXP (pat, 0, i)) == hard_frame_pointer_rtx) + return true; + } + return false; +} + +/* Initialize cfa_base_rtx, create a preserved VALUE for it and + ensure it isn't flushed during cselib_reset_table. + Can be called only if frame_pointer_rtx resp. arg_pointer_rtx + has been eliminated. */ + +static void +vt_init_cfa_base (void) +{ + cselib_val *val; + +#ifdef FRAME_POINTER_CFA_OFFSET + cfa_base_rtx = frame_pointer_rtx; +#else + cfa_base_rtx = arg_pointer_rtx; +#endif + if (cfa_base_rtx == hard_frame_pointer_rtx + || !fixed_regs[REGNO (cfa_base_rtx)]) + { + cfa_base_rtx = NULL_RTX; + return; + } + if (!MAY_HAVE_DEBUG_INSNS) + return; + + val = cselib_lookup (cfa_base_rtx, GET_MODE (cfa_base_rtx), 1); + preserve_value (val); + cselib_preserve_cfa_base_value (val); + val->locs->setting_insn = get_insns (); + var_reg_decl_set (&VTI (ENTRY_BLOCK_PTR)->out, cfa_base_rtx, + VAR_INIT_STATUS_INITIALIZED, dv_from_value (val->val_rtx), + 0, NULL_RTX, INSERT); +} + /* Allocate and initialize the data structures for variable tracking and parse the RTL to get the micro operations. */ -static void +static bool vt_initialize (void) { - basic_block bb; + basic_block bb, prologue_bb = NULL; + HOST_WIDE_INT fp_cfa_offset = -1; alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def)); + attrs_pool = create_alloc_pool ("attrs_def pool", + sizeof (struct attrs_def), 1024); + var_pool = create_alloc_pool ("variable_def pool", + sizeof (struct variable_def) + + (MAX_VAR_PARTS - 1) + * sizeof (((variable)NULL)->var_part[0]), 64); + loc_chain_pool = create_alloc_pool ("location_chain_def pool", + sizeof (struct location_chain_def), + 1024); + shared_hash_pool = create_alloc_pool ("shared_hash_def pool", + sizeof (struct shared_hash_def), 256); + empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool); + empty_shared_hash->refcount = 1; + empty_shared_hash->htab + = htab_create (1, variable_htab_hash, variable_htab_eq, + variable_htab_free); + changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq, + variable_htab_free); + if (MAY_HAVE_DEBUG_INSNS) + { + value_chain_pool = create_alloc_pool ("value_chain_def pool", + sizeof (struct value_chain_def), + 1024); + value_chains = htab_create (32, value_chain_htab_hash, + value_chain_htab_eq, NULL); + } + + /* Init the IN and OUT sets. */ + FOR_ALL_BB (bb) + { + VTI (bb)->visited = false; + VTI (bb)->flooded = false; + dataflow_set_init (&VTI (bb)->in); + dataflow_set_init (&VTI (bb)->out); + VTI (bb)->permp = NULL; + } + if (MAY_HAVE_DEBUG_INSNS) { - cselib_init (true); + cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS); scratch_regs = BITMAP_ALLOC (NULL); valvar_pool = create_alloc_pool ("small variable_def pool", sizeof (struct variable_def), 256); @@ -7712,6 +8084,55 @@ vt_initialize (void) valvar_pool = NULL; } + if (!frame_pointer_needed) + { + rtx reg, elim; + + if (!vt_stack_adjustments ()) + return false; + +#ifdef FRAME_POINTER_CFA_OFFSET + reg = frame_pointer_rtx; +#else + reg = arg_pointer_rtx; +#endif + elim = eliminate_regs (reg, VOIDmode, NULL_RTX); + if (elim != reg) + { + if (GET_CODE (elim) == PLUS) + elim = XEXP (elim, 0); + if (elim == stack_pointer_rtx) + vt_init_cfa_base (); + } + } + else if (!crtl->stack_realign_tried) + { + rtx reg, elim; + +#ifdef FRAME_POINTER_CFA_OFFSET + reg = frame_pointer_rtx; + fp_cfa_offset = FRAME_POINTER_CFA_OFFSET (current_function_decl); +#else + reg = arg_pointer_rtx; + fp_cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl); +#endif + elim = eliminate_regs (reg, VOIDmode, NULL_RTX); + if (elim != reg) + { + if (GET_CODE (elim) == PLUS) + { + fp_cfa_offset -= INTVAL (XEXP (elim, 1)); + elim = XEXP (elim, 0); + } + if (elim != hard_frame_pointer_rtx) + fp_cfa_offset = -1; + else + prologue_bb = single_succ (ENTRY_BLOCK_PTR); + } + } + + hard_frame_pointer_adjustment = -1; + FOR_EACH_BB (bb) { rtx insn; @@ -7743,6 +8164,8 @@ vt_initialize (void) /* Add the micro-operations to the vector. */ FOR_BB_BETWEEN (bb, first_bb, last_bb->next_bb, next_bb) { + HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust; + VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust; for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); insn = NEXT_INSN (insn)) { @@ -7757,16 +8180,17 @@ vt_initialize (void) mo.type = MO_ADJUST; mo.u.adjust = pre; mo.insn = insn; - VEC_safe_push (micro_operation, heap, VTI (bb)->mos, - &mo); - if (dump_file && (dump_flags & TDF_DETAILS)) log_op_type (PATTERN (insn), bb, insn, MO_ADJUST, dump_file); + VEC_safe_push (micro_operation, heap, VTI (bb)->mos, + &mo); + VTI (bb)->out.stack_adjust += pre; } } cselib_hook_called = false; + adjust_insn (bb, insn); if (MAY_HAVE_DEBUG_INSNS) { cselib_process_insn (insn); @@ -7778,6 +8202,7 @@ vt_initialize (void) } if (!cselib_hook_called) add_with_sets (insn, 0, 0); + cancel_changes (0); if (!frame_pointer_needed && post) { @@ -7785,15 +8210,25 @@ vt_initialize (void) mo.type = MO_ADJUST; mo.u.adjust = post; mo.insn = insn; - VEC_safe_push (micro_operation, heap, VTI (bb)->mos, - &mo); - if (dump_file && (dump_flags & TDF_DETAILS)) log_op_type (PATTERN (insn), bb, insn, MO_ADJUST, dump_file); + VEC_safe_push (micro_operation, heap, VTI (bb)->mos, + &mo); + VTI (bb)->out.stack_adjust += post; + } + + if (bb == prologue_bb + && hard_frame_pointer_adjustment == -1 + && RTX_FRAME_RELATED_P (insn) + && fp_setter (insn)) + { + vt_init_cfa_base (); + hard_frame_pointer_adjustment = fp_cfa_offset; } } } + gcc_assert (offset == VTI (bb)->out.stack_adjust); } bb = last_bb; @@ -7806,45 +8241,11 @@ vt_initialize (void) } } - attrs_pool = create_alloc_pool ("attrs_def pool", - sizeof (struct attrs_def), 1024); - var_pool = create_alloc_pool ("variable_def pool", - sizeof (struct variable_def) - + (MAX_VAR_PARTS - 1) - * sizeof (((variable)NULL)->var_part[0]), 64); - loc_chain_pool = create_alloc_pool ("location_chain_def pool", - sizeof (struct location_chain_def), - 1024); - shared_hash_pool = create_alloc_pool ("shared_hash_def pool", - sizeof (struct shared_hash_def), 256); - empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool); - empty_shared_hash->refcount = 1; - empty_shared_hash->htab - = htab_create (1, variable_htab_hash, variable_htab_eq, - variable_htab_free); - changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq, - variable_htab_free); - if (MAY_HAVE_DEBUG_INSNS) - { - value_chain_pool = create_alloc_pool ("value_chain_def pool", - sizeof (struct value_chain_def), - 1024); - value_chains = htab_create (32, value_chain_htab_hash, - value_chain_htab_eq, NULL); - } - - /* Init the IN and OUT sets. */ - FOR_ALL_BB (bb) - { - VTI (bb)->visited = false; - VTI (bb)->flooded = false; - dataflow_set_init (&VTI (bb)->in); - dataflow_set_init (&VTI (bb)->out); - VTI (bb)->permp = NULL; - } - + hard_frame_pointer_adjustment = -1; VTI (ENTRY_BLOCK_PTR)->flooded = true; vt_add_function_parameters (); + cfa_base_rtx = NULL_RTX; + return true; } /* Get rid of all debug insns from the insn stream. */ @@ -7946,15 +8347,11 @@ variable_tracking_main_1 (void) } mark_dfs_back_edges (); - vt_initialize (); - if (!frame_pointer_needed) + if (!vt_initialize ()) { - if (!vt_stack_adjustments ()) - { - vt_finalize (); - vt_debug_insns_local (true); - return 0; - } + vt_finalize (); + vt_debug_insns_local (true); + return 0; } success = vt_find_locations (); @@ -7968,10 +8365,8 @@ variable_tracking_main_1 (void) /* This is later restored by our caller. */ flag_var_tracking_assignments = 0; - vt_initialize (); - - if (!frame_pointer_needed && !vt_stack_adjustments ()) - gcc_unreachable (); + success = vt_initialize (); + gcc_assert (success); success = vt_find_locations (); } diff --git a/gcc/varasm.c b/gcc/varasm.c index 6b8222f8e9a..31007b8af86 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1476,6 +1476,38 @@ make_decl_rtl (tree decl) if (flag_mudflap && TREE_CODE (decl) == VAR_DECL) mudflap_enqueue_decl (decl); } + +/* Like make_decl_rtl, but inhibit creation of new alias sets when + calling make_decl_rtl. Also, reset DECL_RTL before returning the + rtl. */ + +rtx +make_decl_rtl_for_debug (tree decl) +{ + unsigned int save_aliasing_flag; + rtx rtl; + + if (DECL_RTL_SET_P (decl)) + return DECL_RTL (decl); + + /* Kludge alert! Somewhere down the call chain, make_decl_rtl will + call new_alias_set. If running with -fcompare-debug, sometimes + we do not want to create alias sets that will throw the alias + numbers off in the comparison dumps. So... clearing + flag_strict_aliasing will keep new_alias_set() from creating a + new set. */ + save_aliasing_flag = flag_strict_aliasing; + flag_strict_aliasing = 0; + + rtl = DECL_RTL (decl); + /* Reset DECL_RTL back, as various parts of the compiler expects + DECL_RTL set meaning it is actually going to be output. */ + SET_DECL_RTL (decl, NULL); + + flag_strict_aliasing = save_aliasing_flag; + + return rtl; +} /* Output a string of literal assembler code for an `asm' keyword used between functions. */ |