aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Pinski <andrew_pinski@playstation.sony.com>2007-05-11 20:46:18 +0000
committerAndrew Pinski <andrew_pinski@playstation.sony.com>2007-05-11 20:46:18 +0000
commit322f830eb13616c511cd94486bf5361cf2853f8a (patch)
treef29f6ed0338b106f5da9b42ef37f19373d5c6e0c
parent86bb2a5d2067811c919ea01703adab99e15e8616 (diff)
2007-05-10 Andrew Pinski <andrew_pinski@playstation.sony.com>
Merge mainline, revision 124602. * fold-const.c (extract_array_ref): Make sure the offset is converted to sizetype. (try_move_mult_to_index): Strip the NOPs from the offset. (fold_binary <case POINTER_PLUS_EXPR>): Convert the second operand to sizetype before calling try_move_mult_to_index. * tree-ssa-loop-niter.c (number_of_iterations_lt_to_ne): For pointer types, use sizetype when creating MINUS_EXPR/PLUS_EXPRs. * tree-ssa-ccp.c (maybe_fold_stmt_indirect): Make sure the offset is converted to sizetype. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/pointer_plus@124625 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog213
-rw-r--r--gcc/ChangeLog.ptr15
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/c-common.h2
-rw-r--r--gcc/c-cppbuiltin.c3
-rw-r--r--gcc/c-incpath.c19
-rw-r--r--gcc/c-opts.c2
-rw-r--r--gcc/collect2.c71
-rw-r--r--gcc/config.gcc4
-rw-r--r--gcc/config.in6
-rw-r--r--gcc/config/bfin/bfin-protos.h8
-rw-r--r--gcc/config/bfin/bfin.c97
-rw-r--r--gcc/config/bfin/bfin.h25
-rw-r--r--gcc/config/bfin/bfin.md6
-rw-r--r--gcc/config/i386/i386.c3
-rw-r--r--gcc/config/m32c/jump.md26
-rw-r--r--gcc/config/m32c/m32c-protos.h1
-rw-r--r--gcc/config/m32c/m32c.c118
-rw-r--r--gcc/config/m32c/muldiv.md31
-rw-r--r--gcc/config/m32c/shift.md10
-rw-r--r--gcc/config/mips/mips-dspr2.md30
-rw-r--r--gcc/config/mips/mips.c54
-rw-r--r--gcc/config/mips/mips.h14
-rw-r--r--gcc/config/mips/mips.md10
-rw-r--r--gcc/config/sparc/sparc-protos.h1
-rw-r--r--gcc/config/sparc/sparc.c74
-rw-r--r--gcc/config/sparc/sparc.h3
-rw-r--r--gcc/config/sparc/sparc.md32
-rw-r--r--gcc/config/sparc/t-vxworks5
-rw-r--r--gcc/config/sparc/vxworks.h64
-rw-r--r--gcc/config/xtensa/xtensa.c13
-rwxr-xr-xgcc/configure9
-rw-r--r--gcc/configure.ac3
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/parser.c47
-rw-r--r--gcc/doc/extend.texi36
-rw-r--r--gcc/doc/invoke.texi41
-rw-r--r--gcc/doc/md.texi19
-rw-r--r--gcc/emit-rtl.c33
-rw-r--r--gcc/expr.c41
-rw-r--r--gcc/fold-const.c11
-rw-r--r--gcc/fortran/ChangeLog57
-rw-r--r--gcc/fortran/array.c2
-rw-r--r--gcc/fortran/decl.c39
-rw-r--r--gcc/fortran/gfortran.h34
-rw-r--r--gcc/fortran/resolve.c19
-rw-r--r--gcc/fortran/simplify.c5
-rw-r--r--gcc/fortran/trans-array.c38
-rw-r--r--gcc/fortran/trans-decl.c14
-rw-r--r--gcc/fortran/trans-io.c262
-rw-r--r--gcc/fortran/trans-stmt.c89
-rw-r--r--gcc/fortran/trans.c16
-rw-r--r--gcc/fortran/trans.h3
-rw-r--r--gcc/gcc.c68
-rw-r--r--gcc/genopinit.c2
-rw-r--r--gcc/gimplify.c2
-rw-r--r--gcc/ipa-type-escape.c7
-rw-r--r--gcc/optabs.c2
-rw-r--r--gcc/optabs.h8
-rw-r--r--gcc/reload.c5
-rw-r--r--gcc/testsuite/ChangeLog116
-rw-r--r--gcc/testsuite/g++.dg/abi/forced.C25
-rw-r--r--gcc/testsuite/g++.dg/other/first-global.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/empty.C25
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/inline8.C1
-rw-r--r--gcc/testsuite/gcc.dg/20070507-1.c103
-rw-r--r--gcc/testsuite/gcc.dg/dfp/convert-bfp-fold.c31
-rw-r--r--gcc/testsuite/gcc.dg/invalid-call-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/pch.exp1
-rw-r--r--gcc/testsuite/gcc.dg/pr31847.c15
-rw-r--r--gcc/testsuite/gcc.dg/special/gcsec-1.c3
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loop-29.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/pr31854.c10
-rw-r--r--gcc/testsuite/gcc.target/mips/msub-1.c19
-rw-r--r--gcc/testsuite/gcc.target/mips/msub-2.c19
-rw-r--r--gcc/testsuite/gcc.target/mips/msub-3.c19
-rw-r--r--gcc/testsuite/gcc.target/mips/msub-4.c19
-rw-r--r--gcc/testsuite/gcc.target/mips/msubu-1.c22
-rw-r--r--gcc/testsuite/gcc.target/mips/msubu-2.c22
-rw-r--r--gcc/testsuite/gcc.target/mips/msubu-3.c22
-rw-r--r--gcc/testsuite/gcc.target/mips/msubu-4.c22
-rw-r--r--gcc/testsuite/gfortran.dg/actual_array_result_1.f9071
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_dummy_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/bounds_check_fail_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/char_initialiser_actual.f902
-rw-r--r--gcc/testsuite/gfortran.dg/do_3.F90110
-rw-r--r--gcc/testsuite/gfortran.dg/iostat_4.f909
-rw-r--r--gcc/testsuite/gfortran.dg/large_unit_1.f9017
-rw-r--r--gcc/testsuite/gfortran.dg/large_unit_2.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/nested_modules_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/new_line.f9017
-rw-r--r--gcc/testsuite/gfortran.dg/parameter_array_init_1.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/parameter_array_init_2.f9026
-rw-r--r--gcc/testsuite/gfortran.dg/shift-alloc.f902
-rw-r--r--gcc/testsuite/gfortran.dg/unf_read_corrupted_2.f9027
-rw-r--r--gcc/testsuite/gnat.dg/opt1.adb29
-rw-r--r--gcc/testsuite/gnat.dg/opt1.ads13
-rw-r--r--gcc/tree-chrec.c7
-rw-r--r--gcc/tree-chrec.h3
-rw-r--r--gcc/tree-dump.c2
-rw-r--r--gcc/tree-ssa-ccp.c3
-rw-r--r--gcc/tree-ssa-dom.c22
-rw-r--r--gcc/tree-ssa-loop-niter.c15
104 files changed, 2446 insertions, 363 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7453266e865..40867e98cdf 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,214 @@
+2007-05-10 Zdenek Dvorak <dvorakz@suse.cz>
+
+ PR tree-optimization/31885
+ * tree-chrec.c (chrec_contains_undetermined): Do not consider NULL_TREE
+ to be undetermined.
+ (automatically_generated_chrec_p): Return false for NULL.
+
+2007-05-08 Bernd Schmidt <bernd.schmidt@analog.com>
+
+ * config/bfin/bfin.h (MOVE_RATIO): Define.
+
+2007-05-10 Richard Sandiford <richard@codesourcery.com>
+
+ * config.gcc (sparc-wrs-vxworks): New target.
+ * config/sparc/vxworks.h, config/sparc/t-vxworks: New files.
+ * config/sparc/sparc-protos.h (sparc_emit_call_insn): Declare.
+ * config/sparc/sparc.h: Include vxworks-dummy.h.
+ (PRINT_OPERAND_ADDRESS): Extend SYMBOL_REF handling to
+ include LABEL_REFs too.
+ * config/sparc/sparc.c (sparc_expand_move): Don't assume that
+ _GLOBAL_OFFSET_TABLE_ - label_ref is a link-time constant on
+ VxWorks.
+ (legitimize_pic_address): Handle LABEL_REFs like SYMBOL_REFs
+ on VxWorks.
+ (load_pic_register): Use gen_vxworks_load_got for VxWorks.
+ (sparc_emit_call_insn): New function.
+ (sparc_function_ok_for_sibcall): Restrict sibcalls to locally-binding
+ functions when generating VxWorks PIC.
+ * config/sparc/sparc.md (vxworks_load_got): New pattern.
+ (call, call_value): Use sparc_emit_call_insn instead of
+ emit_call_insn.
+
+2007-05-09 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (xtensa_output_literal): Don't use #if.
+
+2007-05-09 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (xtensa_output_literal): Mask out high bits
+ for floating-point values if HOST_BITS_PER_LONG > 32. Use split_double
+ instead of operand_subword.
+
+2007-05-08 Bernd Schmidt <bernd.schmidt@analog.com>
+
+ * config/bfin/bfin.h (LOCAL_ALIGNMENT): Define.
+ * config/bfin/bfin.c (bfin_local_alignment): New function.
+ * config/bfin/bfin-protos.h (bfin_local_alignment): Declare it.
+
+2007-05-08 Chao-ying Fu <fu@mips.com>
+
+ * doc/md.texi (msub@var{m}@var{n}4, usub@var{m}@var{n}4): Document.
+ * optabs.h (OTI_smsub_widen, OTI_umsub_widen): New optab_indexes.
+ (smsub_widen_optab, umsub_widen_optab): Define.
+ * optabs.c (init_optabs): Initialize smsub_widen_optab and
+ umsub_widen_optab.
+ * genopinit.c (optabs): Fill in smsub_widen_optab and
+ umsub_widen_optab.
+ * expr.c (expand_expr_real_1): Try to use smsub_widen_optab
+ and umsub_widen_optab to implement multiply-subtract sequences.
+ * config/mips/mips.md (*msac<u>_di): Rename to...
+ (<u>msubsidi4): ...this. Extend condition to include
+ GENERATE_MADD_MSUB and TARGET_DSPR2. Change the constraint
+ of operand 0 to "ka" and use the three-operand form of msub<u>
+ for TARGET_DSPR2.
+ * config/mips/mips-dspr2.md (mips_msub, mips_msubu): Convert
+ to define_expands.
+
+2007-05-08 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ PR rtl-optimization/28011
+ * reload.c (push_reload): Set dont_share if IN appears in OUT
+ also when IN is a PLUS rtx.
+ (reg_overlap_mentioned_for_reload_p): Return true if X and IN
+ are same PLUS rtx.
+
+2007-05-08 Kazu Hirata <kazu@codesourcery.com>
+
+ * emit-rtl.c (unshare_all_rtl_1): Don't copy DECL_RTL. Don't
+ call unshare_all_decls.
+ (unshare_all_rtl): Adjust the call to unshare_all_rtl_1.
+ (unshare_all_decls): Remove.
+
+2007-05-08 Simon Martin <simartin@users.sourceforge.net>
+
+ PR 31847
+ * tree-dump.c (dump_options): Don't use TDF_DIAGNOSTIC in "*-all" tree
+ dumps.
+
+2007-05-08 Sandra Loosemore <sandra@codesourcery.com>
+ Nigel Stephens <nigel@mips.com>
+
+ * config/mips/mips.h (MAX_FPRS_PER_FMT): Renamed from FP_INC.
+ Update comments and all uses.
+ (MIN_FPRS_PER_FMT): Define.
+ * config/mips/mips.c (function_arg): Fix to correctly handle
+ the -mips32r2 -mfp64 -mabi=32 case.
+ (override_options): Enable use of odd-numbered registers for
+ SFmode values on MIPS32.
+ (mips_save_reg_p): Save whole floating-point register pair if
+ either half is used.
+ (compute_frame_size): Fix comment.
+
+2007-05-08 Jie Zhang <jie.zhang@analog.com>
+
+ * config/bfin/bfin-protos.h (bfin_expand_epilogue): Add a third
+ argument of type bool.
+ * config/bfin/bfin.c (add_to_reg): Add epilogue_p as a fourth
+ argument. Safely select temporary P register according to it.
+ (do_link): Change call site of add_to_reg accordingly.
+ (do_unlink): Add epilogue_p as a fourth argument and pass it
+ to add_to_reg.
+ (expand_interrupt_handler_epilogue): Change call of do_unlink
+ accordingly.
+ (bfin_expand_prologue): Add a third argument sibcall_p.
+ * config/bfin/bfin.md (epilogue): Change call of
+ bfin_expand_epilogue accordingly.
+ (sibcall_epilogue): Likewise.
+ (eh_return_internal): Likewise.
+
+ * config/bfin/bfin-protos.h (enum bfin_cpu): Add
+ BFIN_CPU_BF534, BFIN_CPU_BF536 and BFIN_CPU_BF561.
+ * config/bfin/bfin.c (bfin_handle_option): Handle
+ -mcpu=bf534, -mcpu=bf536 and -mcpu=bf561.
+ * config/bfin/bfin.h (TARGET_CPU_CPP_BUILTINS):
+ Support bf534, bf536 and bf561.
+ * doc/invoke.texi (Blackfin Options): Document -mcpu and -msim.
+
+2007-05-08 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/31854
+ * config/i386/i386.c (ix86_function_regparm): Process local
+ functions only when TREE_CODE (decl) equals FUNCTION_DECL.
+
+2007-05-07 Mike Stump <mrs@apple.com>
+
+ * doc/invoke.texi (Warning Options): Document that -Wempty-body
+ also checks for and while statements in C++.
+
+2007-05-07 Nathan Froyd <froydnj@codesourcery.com>
+
+ * gcc.c (at_file_supplied): New variable.
+ (main): Set it if we expanded argv.
+ (do_spec_1): Pass an @-file to the linker if we were called with
+ an @-file argument and HAVE_GNU_LD.
+ * collect2.c (at_file_supplied): New variable.
+ (response_file): New variable.
+ (collect_exit): Unlink response_file if necessary.
+ (handler): Likewise.
+ (do_wait): Likewise.
+ (main): Set at_file_supplied if we expanded argv.
+ (collect_execute): Pass an @-file to subprocesses if we were called
+ with an @-file argument.
+ * configure.ac: Add define for HAVE_GNU_LD.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+
+2007-05-07 Naveen.H.S <naveen.hs@kpitcummins.com>
+
+ * config/m32c/muldiv.md (mulhisi3_c): Limit the mode of the 2nd
+ operand to HI mode.
+ (mulsi3): New.
+ (divsi3): New.
+ (udivsi3): New.
+
+2007-05-07 Jayant Sonar <jayants@kpitcummins.com>
+
+ * config/m32c/m32c.c (SYMBOL_FLAG_FUNCVEC_FUNCTION): Define.
+ (TARGET_ENCODE_SECTION_INFO): Re-define.
+ (m32c_encode_section_info): New
+ (function_vector_handler): New
+ (current_function_special_page_vector): New
+ (m32c_special_page_vector_p): New.
+ * config/m32c/m32c-protos.h (m32c_special_page_vector_p):
+ Prototype.
+ * config/m32c/jump.md: Added instruction JSRS for functions
+ with attribute "function_vector".
+ * doc/extend.texi (function_vector): Added description
+ for M16C, M32C targets.
+
+2007-05-07 DJ Delorie <dj@redhat.com>
+
+ PR 31794
+ * config/m32c/shift.md (ashlpsi3_i, ashrpsi3_i, ashlpsi3,
+ ashrpsi3, lshrpsi3): Update shift count constraint.
+
+2007-05-07 Danny Smith <dannysmith@users.sourceforge.net>
+ Nathan Froyd <froydnj@codesourcery.com>
+
+ PR 22133
+ * c-incpath.c (add_path): Strip trailing path separators.
+
+2007-05-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * tree-ssa-dom.c (tree_ssa_dominator_optimize): Reset cfg_altered.
+ Free dominance info before purging EH edges.
+ (eliminate_degenerate_phis): Likewise.
+ (propagate_rhs_into_lhs): Set cfg_altered to true instead of 1.
+
+2007-05-07 Jan Hubicka <jh@suse.cz>
+
+ * gimplify.c (gimplify_expr): Do not crash when folding
+ (void *)(int)&a + 4.
+
+2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR driver/31694
+ * c-opts.c (lang_fortran): Make it non static.
+ * c-common.h (lang_fortran): New prototype.
+ * c-cppbuiltin.c (c_cpp_builtins): Create a __GFORTRAN__ if the
+ -lang-fortran option was passed by the driver.
+
2007-05-06 Eric Botcazou <ebotcazou@adacore.com>
* timevar.c (timevar_print): Test ENABLE_ASSERT_CHECKING instead
@@ -194,7 +405,7 @@
2007-05-03 Ian Lance Taylor <iant@google.com>
- * config/rs6000/rs6000.c (rs6000_override_options): Don't se
+ * config/rs6000/rs6000.c (rs6000_override_options): Don't set
MASK_PPC_GFXOPT for 8540 or 8548.
2007-05-03 Uros Bizjak <ubizjak@gmail.com>
diff --git a/gcc/ChangeLog.ptr b/gcc/ChangeLog.ptr
index 2e960d312cd..95d1c1a18a7 100644
--- a/gcc/ChangeLog.ptr
+++ b/gcc/ChangeLog.ptr
@@ -1,3 +1,18 @@
+2007-05-10 Andrew Pinski <andrew_pinski@playstation.sony.com>
+
+ Merge mainline, revision 124602.
+
+ * fold-const.c (extract_array_ref): Make sure the offset
+ is converted to sizetype.
+ (try_move_mult_to_index): Strip the NOPs from the offset.
+ (fold_binary <case POINTER_PLUS_EXPR>): Convert the second
+ operand to sizetype before calling try_move_mult_to_index.
+ * tree-ssa-loop-niter.c (number_of_iterations_lt_to_ne):
+ For pointer types, use sizetype when
+ creating MINUS_EXPR/PLUS_EXPRs.
+ * tree-ssa-ccp.c (maybe_fold_stmt_indirect): Make sure
+ the offset is converted to sizetype.
+
2007-05-11 Andrew Pinski <andrew_pinski@playstation.sony.com>
* config/spu/spu.c (spu_va_start): Create POINTER_PLUS_EXPR
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index f8b17cf886e..37fbc507602 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20070505
+20070510
diff --git a/gcc/c-common.h b/gcc/c-common.h
index d4afaec4535..5e97211cb17 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -254,6 +254,8 @@ extern c_language_kind c_language;
#define c_dialect_cxx() (c_language & clk_cxx)
#define c_dialect_objc() (c_language & clk_objc)
+extern bool lang_fortran;
+
/* Information about a statement tree. */
struct stmt_tree_s GTY(()) {
diff --git a/gcc/c-cppbuiltin.c b/gcc/c-cppbuiltin.c
index c36b038bc77..cc19ce5dd7d 100644
--- a/gcc/c-cppbuiltin.c
+++ b/gcc/c-cppbuiltin.c
@@ -569,6 +569,9 @@ c_cpp_builtins (cpp_reader *pfile)
if (flag_openmp)
cpp_define (pfile, "_OPENMP=200505");
+ if (lang_fortran)
+ cpp_define (pfile, "__GFORTRAN__=1");
+
builtin_define_type_sizeof ("__SIZEOF_INT__", integer_type_node);
builtin_define_type_sizeof ("__SIZEOF_LONG__", long_integer_type_node);
builtin_define_type_sizeof ("__SIZEOF_LONG_LONG__",
diff --git a/gcc/c-incpath.c b/gcc/c-incpath.c
index 3e819cec838..8b6512c8e0f 100644
--- a/gcc/c-incpath.c
+++ b/gcc/c-incpath.c
@@ -389,13 +389,18 @@ add_path (char *path, int chain, int cxx_aware, bool user_supplied_p)
cpp_dir *p;
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- /* Convert all backslashes to slashes. The native CRT stat()
- function does not recognize a directory that ends in a backslash
- (unless it is a drive root dir, such "c:\"). Forward slashes,
- trailing or otherwise, cause no problems for stat(). */
- char* c;
- for (c = path; *c; c++)
- if (*c == '\\') *c = '/';
+ /* Remove unnecessary trailing slashes. On some versions of MS
+ Windows, trailing _forward_ slashes cause no problems for stat().
+ On newer versions, stat() does not recognise a directory that ends
+ in a '\\' or '/', unless it is a drive root dir, such as "c:/",
+ where it is obligatory. */
+ int pathlen = strlen (path);
+ char* end = path + pathlen - 1;
+ /* Preserve the lead '/' or lead "c:/". */
+ char* start = path + (pathlen > 2 && path[1] == ':' ? 3 : 1);
+
+ for (; end > start && IS_DIR_SEPARATOR (*end); end--)
+ *end = 0;
#endif
p = XNEW (cpp_dir);
diff --git a/gcc/c-opts.c b/gcc/c-opts.c
index e378f377a0c..a41362a9829 100644
--- a/gcc/c-opts.c
+++ b/gcc/c-opts.c
@@ -73,7 +73,7 @@ static bool deps_seen;
static bool verbose;
/* If -lang-fortran seen. */
-static bool lang_fortran = false;
+bool lang_fortran = false;
/* Dependency output file. */
static const char *deps_file;
diff --git a/gcc/collect2.c b/gcc/collect2.c
index c6c1f3f4a2c..1ef174f534e 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -1,7 +1,7 @@
/* Collect static initialization info into data structures that can be
traversed by C++ initialization and finalization routines.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
Contributed by Chris Smith (csmith@convex.com).
Heavily modified by Michael Meissner (meissner@cygnus.com),
Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
@@ -202,6 +202,9 @@ static struct head exports; /* list of exported symbols */
#endif
static struct head frame_tables; /* list of frame unwind info tables */
+static bool at_file_supplied; /* Whether to use @file arguments */
+static char *response_file; /* Name of any current response file */
+
struct obstack temporary_obstack;
char * temporary_firstobj;
@@ -302,6 +305,9 @@ collect_exit (int status)
if (status != 0 && output_file != 0 && output_file[0])
maybe_unlink (output_file);
+ if (response_file)
+ maybe_unlink (response_file);
+
exit (status);
}
@@ -393,6 +399,9 @@ handler (int signo)
maybe_unlink (export_file);
#endif
+ if (response_file)
+ maybe_unlink (response_file);
+
signal (signo, SIG_DFL);
raise (signo);
}
@@ -793,7 +802,15 @@ main (int argc, char **argv)
char **object_lst;
const char **object;
int first_file;
- int num_c_args = argc+9;
+ int num_c_args;
+ char **old_argv;
+
+ old_argv = argv;
+ expandargv (&argc, &argv);
+ if (argv != old_argv)
+ at_file_supplied = 1;
+
+ num_c_args = argc + 9;
no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
@@ -1513,6 +1530,12 @@ do_wait (const char *prog, struct pex_obj *pex)
error ("%s returned %d exit status", prog, ret);
collect_exit (ret);
}
+
+ if (response_file)
+ {
+ unlink (response_file);
+ response_file = NULL;
+ }
}
@@ -1525,6 +1548,47 @@ collect_execute (const char *prog, char **argv, const char *outname,
struct pex_obj *pex;
const char *errmsg;
int err;
+ char *response_arg = NULL;
+ char *response_argv[3] ATTRIBUTE_UNUSED;
+
+ if (HAVE_GNU_LD && at_file_supplied && argv[0] != NULL)
+ {
+ /* If using @file arguments, create a temporary file and put the
+ contents of argv into it. Then change argv to an array corresponding
+ to a single argument @FILE, where FILE is the temporary filename. */
+
+ char **current_argv = argv + 1;
+ char *argv0 = argv[0];
+ int status;
+ FILE *f;
+
+ /* Note: we assume argv contains at least one element; this is
+ checked above. */
+
+ response_file = make_temp_file ("");
+
+ f = fopen (response_file, "w");
+
+ if (f == NULL)
+ fatal ("could not open response file %s", response_file);
+
+ status = writeargv (current_argv, f);
+
+ if (status)
+ fatal ("could not write to response file %s", response_file);
+
+ status = fclose (f);
+
+ if (EOF == status)
+ fatal ("could not close response file %s", response_file);
+
+ response_arg = concat ("@", response_file, NULL);
+ response_argv[0] = argv0;
+ response_argv[1] = response_arg;
+ response_argv[2] = NULL;
+
+ argv = response_argv;
+ }
if (vflag || debug)
{
@@ -1568,6 +1632,9 @@ collect_execute (const char *prog, char **argv, const char *outname,
fatal (errmsg);
}
+ if (response_arg)
+ free (response_arg);
+
return pex;
}
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 31b10d4b5e1..a26f3ddd933 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2370,6 +2370,10 @@ sparc-*-sysv4*)
extra_parts="crtbegin.o crtend.o"
use_fixproto=yes
;;
+sparc-wrs-vxworks)
+ tm_file="${tm_file} elfos.h svr4.h sparc/sysv4.h vx-common.h vxworks.h sparc/vxworks.h"
+ tmake_file="${tmake_file} sparc/t-vxworks"
+ ;;
sparc64-*-elf*)
tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sp64-elf.h"
extra_options="${extra_options} sparc/little-endian.opt"
diff --git a/gcc/config.in b/gcc/config.in
index 7e60a3ef347..7864d8c066f 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -869,6 +869,12 @@
#endif
+/* Define if using GNU ld. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GNU_LD
+#endif
+
+
/* Define if you have the iconv() function. */
#ifndef USED_FOR_TARGET
#undef HAVE_ICONV
diff --git a/gcc/config/bfin/bfin-protos.h b/gcc/config/bfin/bfin-protos.h
index 99151fa9bfd..525ecd32558 100644
--- a/gcc/config/bfin/bfin-protos.h
+++ b/gcc/config/bfin/bfin-protos.h
@@ -29,7 +29,10 @@ typedef enum bfin_cpu
BFIN_CPU_BF531,
BFIN_CPU_BF532,
BFIN_CPU_BF533,
- BFIN_CPU_BF537
+ BFIN_CPU_BF534,
+ BFIN_CPU_BF536,
+ BFIN_CPU_BF537,
+ BFIN_CPU_BF561
} bfin_cpu_t;
/* Value of -mcpu= */
@@ -83,13 +86,14 @@ extern void override_options (void);
extern void asm_conditional_branch (rtx, rtx *, int, int);
extern rtx bfin_gen_compare (rtx, Mmode);
+extern int bfin_local_alignment (tree, int);
extern int bfin_return_in_memory (tree);
extern void initialize_trampoline (rtx, rtx, rtx);
extern bool bfin_legitimate_address_p (Mmode, rtx, int);
extern rtx bfin_va_arg (tree, tree);
extern void bfin_expand_prologue (void);
-extern void bfin_expand_epilogue (int, int);
+extern void bfin_expand_epilogue (int, int, bool);
extern int push_multiple_operation (rtx, Mmode);
extern int pop_multiple_operation (rtx, Mmode);
extern void output_push_multiple (rtx, rtx *);
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 727f2ca9b81..94849ce225b 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -569,12 +569,14 @@ frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
RTX_FRAME_RELATED_P (insn) = 1;
}
-/* Generate efficient code to add a value to a P register. We can use
- P1 as a scratch register. Set RTX_FRAME_RELATED_P on the generated
- insns if FRAME is nonzero. */
+/* Generate efficient code to add a value to a P register.
+ Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
+ EPILOGUE_P is zero if this function is called for prologue,
+ otherwise it's nonzero. And it's less than zero if this is for
+ sibcall epilogue. */
static void
-add_to_reg (rtx reg, HOST_WIDE_INT value, int frame)
+add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
{
if (value == 0)
return;
@@ -584,9 +586,41 @@ add_to_reg (rtx reg, HOST_WIDE_INT value, int frame)
in one instruction. */
if (value > 120 || value < -120)
{
- rtx tmpreg = gen_rtx_REG (SImode, REG_P1);
+ rtx tmpreg;
+ rtx tmpreg2;
rtx insn;
+ tmpreg2 = NULL_RTX;
+
+ /* For prologue or normal epilogue, P1 can be safely used
+ as the temporary register. For sibcall epilogue, we try to find
+ a call used P register, which will be restored in epilogue.
+ If we cannot find such a P register, we have to use one I register
+ to help us. */
+
+ if (epilogue_p >= 0)
+ tmpreg = gen_rtx_REG (SImode, REG_P1);
+ else
+ {
+ int i;
+ for (i = REG_P0; i <= REG_P5; i++)
+ if ((regs_ever_live[i] && ! call_used_regs[i])
+ || (!TARGET_FDPIC
+ && i == PIC_OFFSET_TABLE_REGNUM
+ && (current_function_uses_pic_offset_table
+ || (TARGET_ID_SHARED_LIBRARY
+ && ! current_function_is_leaf))))
+ break;
+ if (i <= REG_P5)
+ tmpreg = gen_rtx_REG (SImode, i);
+ else
+ {
+ tmpreg = gen_rtx_REG (SImode, REG_P1);
+ tmpreg2 = gen_rtx_REG (SImode, REG_I0);
+ emit_move_insn (tmpreg2, tmpreg);
+ }
+ }
+
if (frame)
frame_related_constant_load (tmpreg, value, TRUE);
else
@@ -595,6 +629,9 @@ add_to_reg (rtx reg, HOST_WIDE_INT value, int frame)
insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
if (frame)
RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (tmpreg2 != NULL_RTX)
+ emit_move_insn (tmpreg, tmpreg2);
}
else
do
@@ -702,14 +739,17 @@ do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
rtx insn = emit_insn (pat);
RTX_FRAME_RELATED_P (insn) = 1;
}
- add_to_reg (spreg, -frame_size, 1);
+ add_to_reg (spreg, -frame_size, 1, 0);
}
}
-/* Like do_link, but used for epilogues to deallocate the stack frame. */
+/* Like do_link, but used for epilogues to deallocate the stack frame.
+ EPILOGUE_P is zero if this function is called for prologue,
+ otherwise it's nonzero. And it's less than zero if this is for
+ sibcall epilogue. */
static void
-do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all)
+do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
{
frame_size += arg_area_size ();
@@ -719,7 +759,7 @@ do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all)
{
rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
- add_to_reg (spreg, frame_size, 0);
+ add_to_reg (spreg, frame_size, 0, epilogue_p);
if (must_save_fp_p ())
{
rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
@@ -842,7 +882,7 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
insns. */
MEM_VOLATILE_P (postinc) = 1;
- do_unlink (spreg, get_frame_size (), all);
+ do_unlink (spreg, get_frame_size (), all, 1);
if (lookup_attribute ("nesting", attrs))
{
@@ -968,7 +1008,7 @@ bfin_expand_prologue (void)
{
if (lim != p2reg)
emit_move_insn (p2reg, lim);
- add_to_reg (p2reg, offset, 0);
+ add_to_reg (p2reg, offset, 0, 0);
lim = p2reg;
}
emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
@@ -987,13 +1027,15 @@ bfin_expand_prologue (void)
/* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
- eh_return pattern. */
+ eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
+ false otherwise. */
void
-bfin_expand_epilogue (int need_return, int eh_return)
+bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
{
rtx spreg = gen_rtx_REG (Pmode, REG_SP);
e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
+ int e = sibcall_p ? -1 : 1;
if (fkind != SUBROUTINE)
{
@@ -1001,7 +1043,7 @@ bfin_expand_epilogue (int need_return, int eh_return)
return;
}
- do_unlink (spreg, get_frame_size (), false);
+ do_unlink (spreg, get_frame_size (), false, e);
expand_epilogue_reg_restore (spreg, false, false);
@@ -2077,8 +2119,17 @@ bfin_handle_option (size_t code, const char *arg, int value)
bfin_cpu_type = BFIN_CPU_BF532;
else if (strcmp (arg, "bf533") == 0)
bfin_cpu_type = BFIN_CPU_BF533;
+ else if (strcmp (arg, "bf534") == 0)
+ bfin_cpu_type = BFIN_CPU_BF534;
+ else if (strcmp (arg, "bf536") == 0)
+ bfin_cpu_type = BFIN_CPU_BF536;
else if (strcmp (arg, "bf537") == 0)
bfin_cpu_type = BFIN_CPU_BF537;
+ else if (strcmp (arg, "bf561") == 0)
+ {
+ warning (0, "bf561 support is incomplete yet.");
+ bfin_cpu_type = BFIN_CPU_BF561;
+ }
else
return false;
return true;
@@ -2994,6 +3045,24 @@ bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
return false;
}
+/* Compute the alignment for a local variable.
+ TYPE is the data type, and ALIGN is the alignment that
+ the object would ordinarily have. The value of this macro is used
+ instead of that alignment to align the object. */
+
+int
+bfin_local_alignment (tree type, int align)
+{
+ /* Increasing alignment for (relatively) big types allows the builtin
+ memcpy can use 32 bit loads/stores. */
+ if (TYPE_SIZE (type)
+ && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+ && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8
+ || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32)
+ return 32;
+ return align;
+}
+
/* Implement TARGET_SCHED_ISSUE_RATE. */
static int
diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h
index c600af395d6..b78ecb2c84a 100644
--- a/gcc/config/bfin/bfin.h
+++ b/gcc/config/bfin/bfin.h
@@ -59,9 +59,18 @@ extern int target_flags;
case BFIN_CPU_BF533: \
builtin_define ("__ADSPBF533__"); \
break; \
+ case BFIN_CPU_BF534: \
+ builtin_define ("__ADSPBF534__"); \
+ break; \
+ case BFIN_CPU_BF536: \
+ builtin_define ("__ADSPBF536__"); \
+ break; \
case BFIN_CPU_BF537: \
builtin_define ("__ADSPBF537__"); \
break; \
+ case BFIN_CPU_BF561: \
+ builtin_define ("__ADSPBF561__"); \
+ break; \
} \
\
if (TARGET_FDPIC) \
@@ -218,6 +227,18 @@ extern const char *bfin_library_id_string;
/*#define DATA_ALIGNMENT(TYPE, BASIC-ALIGN) for arrays.. */
+/* If defined, a C expression to compute the alignment for a local
+ variable. TYPE is the data type, and ALIGN is the alignment that
+ the object would ordinarily have. The value of this macro is used
+ instead of that alignment to align the object.
+
+ If this macro is not defined, then ALIGN is used.
+
+ One use of this macro is to increase alignment of medium-size
+ data to make it all fit in fewer cache lines. */
+
+#define LOCAL_ALIGNMENT(TYPE, ALIGN) bfin_local_alignment ((TYPE), (ALIGN))
+
/* Make strings word-aligned so strcpy from constants will be faster. */
#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
(TREE_CODE (EXP) == STRING_CST \
@@ -913,6 +934,10 @@ do { \
in one reasonably fast instruction. */
#define MOVE_MAX UNITS_PER_WORD
+/* If a memory-to-memory move would take MOVE_RATIO or more simple
+ move-instruction pairs, we will do a movmem or libcall instead. */
+
+#define MOVE_RATIO 5
/* STORAGE LAYOUT: target machine storage layout
Define this macro as a C expression which is nonzero if accessing
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index 7b238c64982..630694a0f9c 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -2668,12 +2668,12 @@
(define_expand "epilogue"
[(const_int 1)]
""
- "bfin_expand_epilogue (1, 0); DONE;")
+ "bfin_expand_epilogue (1, 0, 0); DONE;")
(define_expand "sibcall_epilogue"
[(const_int 1)]
""
- "bfin_expand_epilogue (0, 0); DONE;")
+ "bfin_expand_epilogue (0, 0, 1); DONE;")
(define_expand "eh_return"
[(unspec_volatile [(match_operand:SI 0 "register_operand" "")]
@@ -2693,7 +2693,7 @@
"#"
"reload_completed"
[(const_int 1)]
- "bfin_expand_epilogue (1, 1); DONE;")
+ "bfin_expand_epilogue (1, 1, 0); DONE;")
(define_insn "link"
[(set (mem:SI (plus:SI (reg:SI REG_SP) (const_int -4))) (reg:SI REG_RETS))
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index a3936546d7b..7e2accf4625 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2792,7 +2792,8 @@ ix86_function_regparm (tree type, tree decl)
return 2;
/* Use register calling convention for local functions when possible. */
- if (decl && flag_unit_at_a_time && !profile_flag)
+ if (decl && TREE_CODE (decl) == FUNCTION_DECL
+ && flag_unit_at_a_time && !profile_flag)
{
struct cgraph_local_info *i = cgraph_local_info (decl);
if (i && i->local)
diff --git a/gcc/config/m32c/jump.md b/gcc/config/m32c/jump.md
index 4a358eac40f..f0983d1532d 100644
--- a/gcc/config/m32c/jump.md
+++ b/gcc/config/m32c/jump.md
@@ -69,7 +69,18 @@
""
"*
switch (which_alternative) {
- case 0: return \"jsr.a\t%0\";
+ case 0:
+ {
+ HOST_WIDE_INT func_vect_num =
+ current_function_special_page_vector(XEXP (operands[0], 0));
+ if (func_vect_num)
+ {
+ operands[3] = gen_rtx_CONST_INT (VOIDmode, func_vect_num);
+ return \"jsrs\t%3\";
+ }
+ else
+ return \"jsr.a\t%0\";
+ }
case 1: return TARGET_A16 ? \"push.w %a0 | jsr.a\tm32c_jsri16\" : \"jsri.a\t%a0\";
case 2: return \"jsri.a\t%a0\";
}"
@@ -84,7 +95,18 @@ switch (which_alternative) {
""
"*
switch (which_alternative) {
- case 0: return \"jsr.a\t%1\";
+ case 0:
+ {
+ HOST_WIDE_INT func_vect_num =
+ current_function_special_page_vector(XEXP (operands[1], 0));
+ if (func_vect_num)
+ {
+ operands[4] = gen_rtx_CONST_INT (VOIDmode, func_vect_num);
+ return \"jsrs\t%4\";
+ }
+ else
+ return \"jsr.a\t%1\";
+ }
case 1: return TARGET_A16 ? \"push.w %a1 | jsr.a\tm32c_jsri16\" : \"jsri.a\t%a1\";
case 2: return \"jsri.a\t%a1\";
}"
diff --git a/gcc/config/m32c/m32c-protos.h b/gcc/config/m32c/m32c-protos.h
index 5735ee75867..5bbc67cbb32 100644
--- a/gcc/config/m32c/m32c-protos.h
+++ b/gcc/config/m32c/m32c-protos.h
@@ -112,6 +112,7 @@ void m32c_function_arg_advance (CUMULATIVE_ARGS *, MM, tree, int);
tree m32c_gimplify_va_arg_expr (tree, tree, tree *, tree *);
void m32c_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
bool m32c_promote_function_return (tree);
+int m32c_special_page_vector_p (tree);
#endif
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index de7ce9d7a0f..dd0bce33299 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -61,6 +61,7 @@ typedef enum
} Push_Pop_Type;
static tree interrupt_handler (tree *, tree, tree, int, bool *);
+static tree function_vector_handler (tree *, tree, tree, int, bool *);
static int interrupt_p (tree node);
static bool m32c_asm_integer (rtx, unsigned int, int);
static int m32c_comp_type_attributes (tree, tree);
@@ -75,6 +76,9 @@ static bool m32c_strict_argument_naming (CUMULATIVE_ARGS *);
static rtx m32c_struct_value_rtx (tree, int);
static rtx m32c_subreg (enum machine_mode, rtx, enum machine_mode, int);
static int need_to_save (int);
+int current_function_special_page_vector (rtx);
+
+#define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
#define streq(a,b) (strcmp ((a), (b)) == 0)
@@ -2721,10 +2725,104 @@ interrupt_handler (tree * node ATTRIBUTE_UNUSED,
return NULL_TREE;
}
+/* Returns TRUE if given tree has the "function_vector" attribute. */
+int
+m32c_special_page_vector_p (tree func)
+{
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+
+ tree list = M32C_ATTRIBUTES (func);
+ while (list)
+ {
+ if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
+ return 1;
+ list = TREE_CHAIN (list);
+ }
+ return 0;
+}
+
+static tree
+function_vector_handler (tree * node ATTRIBUTE_UNUSED,
+ tree name ATTRIBUTE_UNUSED,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool * no_add_attrs ATTRIBUTE_UNUSED)
+{
+ if (TARGET_R8C)
+ {
+ /* The attribute is not supported for R8C target. */
+ warning (OPT_Wattributes,
+ "`%s' attribute is not supported for R8C target",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ /* The attribute must be applied to functions only. */
+ warning (OPT_Wattributes,
+ "`%s' attribute applies only to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
+ {
+ /* The argument must be a constant integer. */
+ warning (OPT_Wattributes,
+ "`%s' attribute argument not an integer constant",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (TREE_INT_CST_LOW (TREE_VALUE (args)) < 18
+ || TREE_INT_CST_LOW (TREE_VALUE (args)) > 255)
+ {
+ /* The argument value must be between 18 to 255. */
+ warning (OPT_Wattributes,
+ "`%s' attribute argument should be between 18 to 255",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
+
+/* If the function is assigned the attribute 'function_vector', it
+ returns the function vector number, otherwise returns zero. */
+int
+current_function_special_page_vector (rtx x)
+{
+ int num;
+
+ if ((GET_CODE(x) == SYMBOL_REF)
+ && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
+ {
+ tree t = SYMBOL_REF_DECL (x);
+
+ if (TREE_CODE (t) != FUNCTION_DECL)
+ return 0;
+
+ tree list = M32C_ATTRIBUTES (t);
+ while (list)
+ {
+ if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
+ {
+ num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (list)));
+ return num;
+ }
+
+ list = TREE_CHAIN (list);
+ }
+
+ return 0;
+ }
+ else
+ return 0;
+}
+
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
static const struct attribute_spec m32c_attribute_table[] = {
{"interrupt", 0, 0, false, false, false, interrupt_handler},
+ {"function_vector", 1, 1, true, false, false, function_vector_handler},
{0, 0, 0, 0, 0, 0, 0}
};
@@ -3751,6 +3849,23 @@ m32c_scc_pattern(rtx *operands, RTX_CODE code)
return buf;
}
+/* Encode symbol attributes of a SYMBOL_REF into its
+ SYMBOL_REF_FLAGS. */
+static void
+m32c_encode_section_info (tree decl, rtx rtl, int first)
+{
+ int extra_flags = 0;
+
+ default_encode_section_info (decl, rtl, first);
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && m32c_special_page_vector_p (decl))
+
+ extra_flags = SYMBOL_FLAG_FUNCVEC_FUNCTION;
+
+ if (extra_flags)
+ SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags;
+}
+
/* Returns TRUE if the current function is a leaf, and thus we can
determine which registers an interrupt function really needs to
save. The logic below is mostly about finding the insn sequence
@@ -4164,6 +4279,9 @@ m32c_output_compare (rtx insn, rtx *operands)
return template + 1;
}
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO m32c_encode_section_info
+
/* The Global `targetm' Variable. */
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/m32c/muldiv.md b/gcc/config/m32c/muldiv.md
index 6913ea9a729..b6c6565baa5 100644
--- a/gcc/config/m32c/muldiv.md
+++ b/gcc/config/m32c/muldiv.md
@@ -82,7 +82,7 @@
(define_insn "mulhisi3_c"
[(set (match_operand:SI 0 "ra_operand" "=Rsi")
(mult:SI (sign_extend:SI (match_operand:HI 1 "mra_operand" "%0"))
- (match_operand 2 "immediate_operand" "i")))]
+ (match_operand:HI 2 "immediate_operand" "i")))]
""
"mul.w\t%2,%1"
[(set_attr "flags" "o")]
@@ -159,7 +159,14 @@
}"
)
-
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "r0123_operand" "=R02,R02")
+ (mult:SI (match_operand:SI 1 "r0123_operand" "%0,0")
+ (match_operand:SI 2 "mra_operand" "RsiSd,?Rmm")))]
+ "TARGET_M32C"
+ "mul.l\t%2,%1"
+ [(set_attr "flags" "o")]
+)
(define_expand "divmodqi4"
[(set (match_dup 4)
@@ -260,3 +267,23 @@
"divu.w\t%2"
[(set_attr "flags" "o")]
)
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "r0123_operand" "=R02,R02")
+ (div:SI (match_operand:SI 1 "r0123_operand" "0,0")
+ (match_operand:SI 2 "mra_operand" "RsiSd,?Rmm")))]
+ "TARGET_M32C"
+ "div.l\t%2"
+ [(set_attr "flags" "o")]
+)
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "r0123_operand" "=R02,R02")
+ (udiv:SI (match_operand:SI 1 "r0123_operand" "0,0")
+ (match_operand:SI 2 "mra_operand" "RsiSd,?Rmm")))]
+ "TARGET_M32C"
+ "divu.l\t%2"
+ [(set_attr "flags" "o")]
+)
+
+
diff --git a/gcc/config/m32c/shift.md b/gcc/config/m32c/shift.md
index 6679f38ffe7..6b8a4835883 100644
--- a/gcc/config/m32c/shift.md
+++ b/gcc/config/m32c/shift.md
@@ -175,7 +175,7 @@
(define_insn "ashlpsi3_i"
[(set (match_operand:PSI 0 "mra_operand" "=R02RaaSd*Rmm,R02RaaSd*Rmm")
(ashift:PSI (match_operand:PSI 1 "mra_operand" "0,0")
- (match_operand:QI 2 "mrai_operand" "In4,RqiSd")))
+ (match_operand:QI 2 "shiftcount_operand" "In4,RqiSd")))
(clobber (match_scratch:HI 3 "=X,R1w"))]
"TARGET_A24"
"@
@@ -187,7 +187,7 @@
(define_insn "ashrpsi3_i"
[(set (match_operand:PSI 0 "mra_operand" "=R02RaaSd*Rmm,R02RaaSd*Rmm")
(ashiftrt:PSI (match_operand:PSI 1 "mra_operand" "0,0")
- (neg:QI (match_operand:QI 2 "mrai_operand" "In4,RqiSd"))))
+ (neg:QI (match_operand:QI 2 "shiftcount_operand" "In4,RqiSd"))))
(clobber (match_scratch:HI 3 "=X,R1w"))]
"TARGET_A24"
"@
@@ -212,7 +212,7 @@
(define_expand "ashlpsi3"
[(parallel [(set (match_operand:PSI 0 "mra_operand" "")
(ashift:PSI (match_operand:PSI 1 "mra_operand" "")
- (match_operand:QI 2 "mrai_operand" "")))
+ (match_operand:QI 2 "shiftcount_operand" "")))
(clobber (match_scratch:HI 3 ""))])]
"TARGET_A24"
"if (m32c_prepare_shift (operands, 1, ASHIFT))
@@ -222,7 +222,7 @@
(define_expand "ashrpsi3"
[(parallel [(set (match_operand:PSI 0 "mra_operand" "")
(ashiftrt:PSI (match_operand:PSI 1 "mra_operand" "")
- (neg:QI (match_operand:QI 2 "mrai_operand" ""))))
+ (neg:QI (match_operand:QI 2 "shiftcount_operand" ""))))
(clobber (match_scratch:HI 3 ""))])]
"TARGET_A24"
"if (m32c_prepare_shift (operands, -1, ASHIFTRT))
@@ -232,7 +232,7 @@
(define_expand "lshrpsi3"
[(parallel [(set (match_operand:PSI 0 "mra_operand" "")
(lshiftrt:PSI (match_operand:PSI 1 "mra_operand" "")
- (neg:QI (match_operand:QI 2 "mrai_operand" ""))))
+ (neg:QI (match_operand:QI 2 "shiftcount_operand" ""))))
(clobber (match_scratch:HI 3 ""))])]
"TARGET_A24"
"if (m32c_prepare_shift (operands, -1, LSHIFTRT))
diff --git a/gcc/config/mips/mips-dspr2.md b/gcc/config/mips/mips-dspr2.md
index dd0aab553a1..20190085177 100644
--- a/gcc/config/mips/mips-dspr2.md
+++ b/gcc/config/mips/mips-dspr2.md
@@ -162,31 +162,13 @@
(match_operand:DI 1 "register_operand")))]
"TARGET_DSPR2 && !TARGET_64BIT")
-(define_insn "mips_msub"
- [(set (match_operand:DI 0 "register_operand" "=a")
- (minus:DI
- (match_operand:DI 1 "register_operand" "0")
- (mult:DI (sign_extend:DI
- (match_operand:SI 2 "register_operand" "d"))
- (sign_extend:DI
- (match_operand:SI 3 "register_operand" "d")))))]
- "TARGET_DSPR2 && !TARGET_64BIT"
- "msub\t%q0,%2,%3"
- [(set_attr "type" "imadd")
- (set_attr "mode" "SI")])
-
-(define_insn "mips_msubu"
- [(set (match_operand:DI 0 "register_operand" "=a")
+(define_expand "mips_msub<u>"
+ [(set (match_operand:DI 0 "register_operand")
(minus:DI
- (match_operand:DI 1 "register_operand" "0")
- (mult:DI (zero_extend:DI
- (match_operand:SI 2 "register_operand" "d"))
- (zero_extend:DI
- (match_operand:SI 3 "register_operand" "d")))))]
- "TARGET_DSPR2 && !TARGET_64BIT"
- "msubu\t%q0,%2,%3"
- [(set_attr "type" "imadd")
- (set_attr "mode" "SI")])
+ (match_operand:DI 1 "register_operand")
+ (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand"))
+ (any_extend:DI (match_operand:SI 3 "register_operand")))))]
+ "TARGET_DSPR2 && !TARGET_64BIT")
(define_insn "mulv2hi3"
[(parallel
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 55bacf7bb19..a719a1020dd 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -3528,7 +3528,7 @@ mips_emit_fcc_reload (rtx dest, rtx src, rtx scratch)
src = gen_rtx_REG (SFmode, true_regnum (src));
fp1 = gen_rtx_REG (SFmode, REGNO (scratch));
- fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + FP_INC);
+ fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + MAX_FPRS_PER_FMT);
emit_move_insn (copy_rtx (fp1), src);
emit_move_insn (copy_rtx (fp2), CONST0_RTX (SFmode));
@@ -3872,7 +3872,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (mips_abi != ABI_EABI || !info.fpr_p)
cum->num_gprs = info.reg_offset + info.reg_words;
else if (info.reg_words > 0)
- cum->num_fprs += FP_INC;
+ cum->num_fprs += MAX_FPRS_PER_FMT;
if (info.stack_words > 0)
cum->stack_words = info.stack_offset + info.stack_words;
@@ -4006,10 +4006,11 @@ function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (!info.fpr_p)
return gen_rtx_REG (mode, GP_ARG_FIRST + info.reg_offset);
- else if (info.reg_offset == 1)
- /* This code handles the special o32 case in which the second word
- of the argument structure is passed in floating-point registers. */
- return gen_rtx_REG (mode, FP_ARG_FIRST + FP_INC);
+ else if (mips_abi == ABI_32 && TARGET_DOUBLE_FLOAT && info.reg_offset > 0)
+ /* In o32, the second argument is always passed in $f14
+ for TARGET_DOUBLE_FLOAT, regardless of whether the
+ first argument was a word or doubleword. */
+ return gen_rtx_REG (mode, FP_ARG_FIRST + 2);
else
return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset);
}
@@ -4150,7 +4151,8 @@ mips_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
mode = TARGET_SINGLE_FLOAT ? SFmode : DFmode;
- for (i = local_cum.num_fprs; i < MAX_ARGS_IN_REGISTERS; i += FP_INC)
+ for (i = local_cum.num_fprs; i < MAX_ARGS_IN_REGISTERS;
+ i += MAX_FPRS_PER_FMT)
{
rtx ptr, mem;
@@ -5098,7 +5100,9 @@ override_options (void)
temp = ((regno & 1) == 0 || size <= UNITS_PER_WORD);
else if (FP_REG_P (regno))
- temp = ((regno % FP_INC) == 0)
+ temp = ((((regno % MAX_FPRS_PER_FMT) == 0)
+ || (MIN_FPRS_PER_FMT == 1
+ && size <= UNITS_PER_FPREG))
&& (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT
|| class == MODE_VECTOR_FLOAT)
&& size <= UNITS_PER_FPVALUE)
@@ -5112,7 +5116,7 @@ override_options (void)
&& size >= MIN_UNITS_PER_WORD
&& size <= UNITS_PER_FPREG)
/* Allow TFmode for CCmode reloads. */
- || (ISA_HAS_8CC && mode == TFmode));
+ || (ISA_HAS_8CC && mode == TFmode)));
else if (ACC_REG_P (regno))
temp = (INTEGRAL_MODE_P (mode)
@@ -6285,6 +6289,15 @@ mips_save_reg_p (unsigned int regno)
if (regs_ever_live[regno] && !call_used_regs[regno])
return true;
+ /* Save both registers in an FPR pair if either one is used. This is
+ needed for the case when MIN_FPRS_PER_FMT == 1, which allows the odd
+ register to be used without the even register. */
+ if (FP_REG_P (regno)
+ && MAX_FPRS_PER_FMT == 2
+ && regs_ever_live[regno + 1]
+ && !call_used_regs[regno + 1])
+ return true;
+
/* We need to save the old frame pointer before setting up a new one. */
if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
return true;
@@ -6437,15 +6450,15 @@ compute_frame_size (HOST_WIDE_INT size)
}
/* This loop must iterate over the same space as its companion in
- save_restore_insns. */
- for (regno = (FP_REG_LAST - FP_INC + 1);
+ mips_for_each_saved_reg. */
+ for (regno = (FP_REG_LAST - MAX_FPRS_PER_FMT + 1);
regno >= FP_REG_FIRST;
- regno -= FP_INC)
+ regno -= MAX_FPRS_PER_FMT)
{
if (mips_save_reg_p (regno))
{
- fp_reg_size += FP_INC * UNITS_PER_FPREG;
- fmask |= ((1 << FP_INC) - 1) << (regno - FP_REG_FIRST);
+ fp_reg_size += MAX_FPRS_PER_FMT * UNITS_PER_FPREG;
+ fmask |= ((1 << MAX_FPRS_PER_FMT) - 1) << (regno - FP_REG_FIRST);
}
}
@@ -6467,7 +6480,8 @@ compute_frame_size (HOST_WIDE_INT size)
cfun->machine->frame.fmask = fmask;
cfun->machine->frame.initialized = reload_completed;
cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD;
- cfun->machine->frame.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG);
+ cfun->machine->frame.num_fp = (fp_reg_size
+ / (MAX_FPRS_PER_FMT * UNITS_PER_FPREG));
if (mask)
{
@@ -6490,7 +6504,7 @@ compute_frame_size (HOST_WIDE_INT size)
offset = (args_size + cprestore_size + var_size
+ gp_reg_rounded + fp_reg_size
- - FP_INC * UNITS_PER_FPREG);
+ - MAX_FPRS_PER_FMT * UNITS_PER_FPREG);
cfun->machine->frame.fp_sp_offset = offset;
cfun->machine->frame.fp_save_offset = offset - total_size;
}
@@ -6593,9 +6607,9 @@ mips_for_each_saved_reg (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn)
compute_frame_size. */
offset = cfun->machine->frame.fp_sp_offset - sp_offset;
fpr_mode = (TARGET_SINGLE_FLOAT ? SFmode : DFmode);
- for (regno = (FP_REG_LAST - FP_INC + 1);
+ for (regno = (FP_REG_LAST - MAX_FPRS_PER_FMT + 1);
regno >= FP_REG_FIRST;
- regno -= FP_INC)
+ regno -= MAX_FPRS_PER_FMT)
if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
{
mips_save_restore_reg (fpr_mode, regno, offset, fn);
@@ -7507,7 +7521,7 @@ mips_return_fpr_pair (enum machine_mode mode,
{
int inc;
- inc = (TARGET_NEWABI ? 2 : FP_INC);
+ inc = (TARGET_NEWABI ? 2 : MAX_FPRS_PER_FMT);
return gen_rtx_PARALLEL
(mode,
gen_rtvec (2,
@@ -7645,7 +7659,7 @@ mips_cannot_change_mode_class (enum machine_mode from,
registers, the first register always holds the low word.
We therefore can't allow FPRs to change between single-word
and multi-word modes. */
- if (FP_INC > 1 && reg_classes_intersect_p (FP_REGS, class))
+ if (MAX_FPRS_PER_FMT > 1 && reg_classes_intersect_p (FP_REGS, class))
return true;
}
else
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index e3c631e087e..fff2e660400 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -1021,13 +1021,19 @@ extern const struct mips_rtx_cost_data *mips_cost;
/* For MIPS, width of a floating point register. */
#define UNITS_PER_FPREG (TARGET_FLOAT64 ? 8 : 4)
-/* If register $f0 holds a floating-point value, $f(0 + FP_INC) is
- the next available register. */
-#define FP_INC (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT ? 1 : 2)
+/* The number of consecutive floating-point registers needed to store the
+ largest format supported by the FPU. */
+#define MAX_FPRS_PER_FMT (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT ? 1 : 2)
+
+/* The number of consecutive floating-point registers needed to store the
+ smallest format supported by the FPU. */
+#define MIN_FPRS_PER_FMT \
+ (ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 ? 1 : MAX_FPRS_PER_FMT)
/* The largest size of value that can be held in floating-point
registers and moved with a single instruction. */
-#define UNITS_PER_HWFPVALUE (TARGET_SOFT_FLOAT ? 0 : FP_INC * UNITS_PER_FPREG)
+#define UNITS_PER_HWFPVALUE \
+ (TARGET_SOFT_FLOAT ? 0 : MAX_FPRS_PER_FMT * UNITS_PER_FPREG)
/* The largest size of value that can be held in floating-point
registers. */
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index e44b919ccb9..de592b9adc7 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -1649,16 +1649,18 @@
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
-(define_insn "*msac<u>_di"
- [(set (match_operand:DI 0 "register_operand" "=x")
+(define_insn "<u>msubsidi4"
+ [(set (match_operand:DI 0 "register_operand" "=ka")
(minus:DI
(match_operand:DI 3 "register_operand" "0")
(mult:DI
(any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
- "!TARGET_64BIT && ISA_HAS_MSAC"
+ "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || TARGET_DSPR2)"
{
- if (TARGET_MIPS5500)
+ if (TARGET_DSPR2)
+ return "msub<u>\t%q0,%1,%2";
+ else if (TARGET_MIPS5500 || GENERATE_MADD_MSUB)
return "msub<u>\t%1,%2";
else
return "msac<u>\t$0,%1,%2";
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 4fb862cc908..c1b2813a3b3 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -73,6 +73,7 @@ extern int legitimate_address_p (enum machine_mode, rtx, int);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern rtx legitimize_tls_address (rtx);
extern rtx legitimize_address (rtx, rtx, enum machine_mode);
+extern void sparc_emit_call_insn (rtx, rtx);
extern void sparc_defer_case_vector (rtx, rtx, int);
extern bool sparc_expand_move (enum machine_mode, rtx *);
extern void sparc_emit_set_const32 (rtx, rtx);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index be07ce7d3d0..f94af2ac5d1 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -980,17 +980,27 @@ sparc_expand_move (enum machine_mode mode, rtx *operands)
if (pic_address_needs_scratch (operands[1]))
operands[1] = legitimize_pic_address (operands[1], mode, 0);
- if (GET_CODE (operands[1]) == LABEL_REF && mode == SImode)
- {
- emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
- return true;
- }
+ /* VxWorks does not impose a fixed gap between segments; the run-time
+ gap can be different from the object-file gap. We therefore can't
+ assume X - _GLOBAL_OFFSET_TABLE_ is a link-time constant unless we
+ are absolutely sure that X is in the same segment as the GOT.
+ Unfortunately, the flexibility of linker scripts means that we
+ can't be sure of that in general, so assume that _G_O_T_-relative
+ accesses are never valid on VxWorks. */
+ if (GET_CODE (operands[1]) == LABEL_REF && !TARGET_VXWORKS_RTP)
+ {
+ if (mode == SImode)
+ {
+ emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
+ return true;
+ }
- if (GET_CODE (operands[1]) == LABEL_REF && mode == DImode)
- {
- gcc_assert (TARGET_ARCH64);
- emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
- return true;
+ if (mode == DImode)
+ {
+ gcc_assert (TARGET_ARCH64);
+ emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
+ return true;
+ }
}
if (symbolic_operand (operands[1], mode))
@@ -3212,7 +3222,9 @@ rtx
legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
rtx reg)
{
- if (GET_CODE (orig) == SYMBOL_REF)
+ if (GET_CODE (orig) == SYMBOL_REF
+ /* See the comment in sparc_expand_move. */
+ || (TARGET_VXWORKS_RTP && GET_CODE (orig) == LABEL_REF))
{
rtx pic_ref, address;
rtx insn;
@@ -3377,6 +3389,13 @@ load_pic_register (bool delay_pic_helper)
{
int orig_flag_pic = flag_pic;
+ if (TARGET_VXWORKS_RTP)
+ {
+ emit_insn (gen_vxworks_load_got ());
+ emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
+ return;
+ }
+
/* If we haven't initialized the special PIC symbols, do so now. */
if (!pic_helper_symbol_name[0])
{
@@ -3405,6 +3424,29 @@ load_pic_register (bool delay_pic_helper)
since we may not fall out the bottom. */
emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
}
+
+/* Emit a call instruction with the pattern given by PAT. ADDR is the
+ address of the call target. */
+
+void
+sparc_emit_call_insn (rtx pat, rtx addr)
+{
+ rtx insn;
+
+ insn = emit_call_insn (pat);
+
+ /* The PIC register is live on entry to VxWorks PIC PLT entries. */
+ if (TARGET_VXWORKS_RTP
+ && flag_pic
+ && GET_CODE (addr) == SYMBOL_REF
+ && (SYMBOL_REF_DECL (addr)
+ ? !targetm.binds_local_p (SYMBOL_REF_DECL (addr))
+ : !SYMBOL_REF_LOCAL_P (addr)))
+ {
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+ current_function_uses_pic_offset_table = 1;
+ }
+}
/* Return 1 if RTX is a MEM which is known to be aligned to at
least a DESIRED byte boundary. */
@@ -7771,13 +7813,19 @@ sparc_elf_asm_named_section (const char *name, unsigned int flags,
the sibling call right? Well, in the C++ case we can end up passing
the pointer to the struct return area to a constructor (which returns
void) and then nothing else happens. Such a sibling call would look
- valid without the added check here. */
+ valid without the added check here.
+
+ VxWorks PIC PLT entries require the global pointer to be initialized
+ on entry. We therefore can't emit sibling calls to them. */
static bool
sparc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
{
return (decl
&& flag_delayed_branch
- && (TARGET_ARCH64 || ! current_function_returns_struct));
+ && (TARGET_ARCH64 || ! current_function_returns_struct)
+ && !(TARGET_VXWORKS_RTP
+ && flag_pic
+ && !targetm.binds_local_p (decl)));
}
/* libfunc renaming. */
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index db0e34e516d..1a4805bb7d3 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
+#include "config/vxworks-dummy.h"
+
/* Note that some other tm.h files include this one and then override
whatever definitions are necessary. */
@@ -2409,6 +2411,7 @@ extern int sparc_indent_opcode;
else if (GET_CODE (index) == REG) \
fprintf (FILE, "+%s", reg_names[REGNO (index)]); \
else if (GET_CODE (index) == SYMBOL_REF \
+ || GET_CODE (index) == LABEL_REF \
|| GET_CODE (index) == CONST) \
fputc ('+', FILE), output_addr_const (FILE, index); \
else gcc_unreachable (); \
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 387b3405db5..6d5797dbe2b 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -1874,6 +1874,22 @@
"flag_pic"
"or\t%1, %%lo(%a3-(%a2-.)), %0")
+;; Set up the PIC register for VxWorks.
+
+(define_expand "vxworks_load_got"
+ [(set (match_dup 0)
+ (high:SI (match_dup 1)))
+ (set (match_dup 0)
+ (mem:SI (lo_sum:SI (match_dup 0) (match_dup 1))))
+ (set (match_dup 0)
+ (mem:SI (lo_sum:SI (match_dup 0) (match_dup 2))))]
+ "TARGET_VXWORKS_RTP"
+{
+ operands[0] = pic_offset_table_rtx;
+ operands[1] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_BASE);
+ operands[2] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_INDEX);
+})
+
(define_expand "movdi"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
@@ -6676,7 +6692,7 @@
{
rtx fn_rtx;
- gcc_assert (GET_MODE (operands[0]) == FUNCTION_MODE);
+ gcc_assert (MEM_P (operands[0]) && GET_MODE (operands[0]) == FUNCTION_MODE);
gcc_assert (GET_CODE (operands[3]) == CONST_INT);
@@ -6712,18 +6728,20 @@
/* We accept negative sizes for untyped calls. */
if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
- emit_call_insn
+ sparc_emit_call_insn
(gen_rtx_PARALLEL
(VOIDmode,
gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx),
operands[3],
- gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))),
+ XEXP (fn_rtx, 0));
else
- emit_call_insn
+ sparc_emit_call_insn
(gen_rtx_PARALLEL
(VOIDmode,
gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx),
- gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))),
+ XEXP (fn_rtx, 0));
finish_call:
@@ -6840,7 +6858,7 @@
rtx fn_rtx;
rtvec vec;
- gcc_assert (GET_MODE (operands[1]) == FUNCTION_MODE);
+ gcc_assert (MEM_P (operands[1]) && GET_MODE (operands[1]) == FUNCTION_MODE);
fn_rtx = operands[1];
@@ -6849,7 +6867,7 @@
gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
- emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
+ sparc_emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec), XEXP (fn_rtx, 0));
DONE;
})
diff --git a/gcc/config/sparc/t-vxworks b/gcc/config/sparc/t-vxworks
new file mode 100644
index 00000000000..2aabf1a43cd
--- /dev/null
+++ b/gcc/config/sparc/t-vxworks
@@ -0,0 +1,5 @@
+# Multilibs for VxWorks.
+
+MULTILIB_OPTIONS = mrtp fPIC
+MULTILIB_MATCHES = fPIC=fpic
+MULTILIB_EXCEPTIONS = fPIC
diff --git a/gcc/config/sparc/vxworks.h b/gcc/config/sparc/vxworks.h
new file mode 100644
index 00000000000..7faacea53ab
--- /dev/null
+++ b/gcc/config/sparc/vxworks.h
@@ -0,0 +1,64 @@
+/* Definitions of target machine for GNU compiler,
+ for SPARC targeting the VxWorks run time environment.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__sparc"); \
+ builtin_define ("CPU=SIMSPARCSOLARIS"); \
+ VXWORKS_OS_CPP_BUILTINS (); \
+ } \
+ while (0)
+
+#undef OVERRIDE_OPTIONS
+#define OVERRIDE_OPTIONS \
+ do \
+ { \
+ VXWORKS_OVERRIDE_OPTIONS; \
+ sparc_override_options (); \
+ } \
+ while (0)
+
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC VXWORKS_ADDITIONAL_CPP_SPEC
+
+#undef LIB_SPEC
+#define LIB_SPEC VXWORKS_LIB_SPEC
+#undef LINK_SPEC
+#define LINK_SPEC VXWORKS_LINK_SPEC
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC VXWORKS_STARTFILE_SPEC
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC VXWORKS_ENDFILE_SPEC
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fputs (" (SPARC/VxWorks)", stderr);
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER VXWORKS_FUNCTION_PROFILER
+
+/* Use standard numbered ctors/dtors sections. */
+#undef CTORS_SECTION_ASM_OP
+#undef DTORS_SECTION_ASM_OP
+
+/* We cannot use PC-relative accesses for VxWorks PIC because there is no
+ fixed gap between segments. */
+#undef ASM_PREFERRED_EH_DATA_FORMAT
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 43bcc584856..c331a7f27ad 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -1939,6 +1939,7 @@ xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno)
long value_long[2];
REAL_VALUE_TYPE r;
int size;
+ rtx first, second;
fprintf (file, "\t.literal .LC%u, ", (unsigned) labelno);
@@ -1952,11 +1953,18 @@ xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno)
{
case SFmode:
REAL_VALUE_TO_TARGET_SINGLE (r, value_long[0]);
+ if (HOST_BITS_PER_LONG > 32)
+ value_long[0] &= 0xffffffff;
fprintf (file, "0x%08lx\n", value_long[0]);
break;
case DFmode:
REAL_VALUE_TO_TARGET_DOUBLE (r, value_long);
+ if (HOST_BITS_PER_LONG > 32)
+ {
+ value_long[0] &= 0xffffffff;
+ value_long[1] &= 0xffffffff;
+ }
fprintf (file, "0x%08lx, 0x%08lx\n",
value_long[0], value_long[1]);
break;
@@ -1978,9 +1986,10 @@ xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno)
break;
case 8:
- output_addr_const (file, operand_subword (x, 0, 0, DImode));
+ split_double (x, &first, &second);
+ output_addr_const (file, first);
fputs (", ", file);
- output_addr_const (file, operand_subword (x, 1, 0, DImode));
+ output_addr_const (file, second);
fputs ("\n", file);
break;
diff --git a/gcc/configure b/gcc/configure
index 17e4fdc7663..b3aa2b09ce7 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -1767,6 +1767,13 @@ _ACEOF
fi
+gnu_ld=`if test x"$gnu_ld_flag" = x"yes"; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GNU_LD $gnu_ld
+_ACEOF
+
+
echo "$as_me:$LINENO: checking whether a default linker was specified" >&5
echo $ECHO_N "checking whether a default linker was specified... $ECHO_C" >&6
if test x"${DEFAULT_LINKER+set}" = x"set"; then
@@ -7665,7 +7672,7 @@ if test "${gcc_cv_prog_makeinfo_modern+set}" = set; then
else
ac_prog_version=`$MAKEINFO --version 2>&1 |
sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'`
- echo "configure:7668: version of makeinfo is $ac_prog_version" >&5
+ echo "configure:7675: version of makeinfo is $ac_prog_version" >&5
case $ac_prog_version in
'') gcc_cv_prog_makeinfo_modern=no;;
4.[4-9]*)
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 9a7c563ec7b..708ce1681a3 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -206,6 +206,9 @@ if test x"${DEFAULT_LINKER+set}" = x"set"; then
[Define to enable the use of a default linker.])
fi
+gnu_ld=`if test x"$gnu_ld_flag" = x"yes"; then echo 1; else echo 0; fi`
+AC_DEFINE_UNQUOTED(HAVE_GNU_LD, $gnu_ld, [Define if using GNU ld.])
+
AC_MSG_CHECKING([whether a default linker was specified])
if test x"${DEFAULT_LINKER+set}" = x"set"; then
if test x"$gnu_ld_flag" = x"no"; then
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b4a1c9a1b0a..708da19eeef 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2007-05-07 Andrew Pinski <andrew_pinski@playstation.sony.com>
+
+ * typeck.c (build_unary_op): Remove code that used to
+ handle non lvalue increments/decrements.
+
+2007-05-07 Mike Stump <mrs@apple.com>
+
+ * parser.c (check_empty_body): Add.
+ (cp_parser_iteration_statement): Add call to check_empty_body.
+
2007-05-05 Geoffrey Keating <geoffk@apple.com>
PR 31775
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 63f7fec0169..4599aca0166 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7065,6 +7065,51 @@ cp_parser_condition (cp_parser* parser)
return cp_parser_expression (parser, /*cast_p=*/false);
}
+/* We check for a ) immediately followed by ; with no whitespacing
+ between. This is used to issue a warning for:
+
+ while (...);
+
+ and:
+
+ for (...);
+
+ as the semicolon is probably extraneous.
+
+ On parse errors, the next token might not be a ), so do nothing in
+ that case. */
+
+static void
+check_empty_body (cp_parser* parser, const char* type)
+{
+ cp_token *token;
+ cp_token *close_paren;
+ expanded_location close_loc;
+ expanded_location semi_loc;
+
+ close_paren = cp_lexer_peek_token (parser->lexer);
+ if (close_paren->type != CPP_CLOSE_PAREN)
+ return;
+
+ close_loc = expand_location (close_paren->location);
+ token = cp_lexer_peek_nth_token (parser->lexer, 2);
+
+ if (token->type != CPP_SEMICOLON
+ || (token->flags & PREV_WHITE))
+ return;
+
+ semi_loc = expand_location (token->location);
+ if (close_loc.line == semi_loc.line
+#ifdef USE_MAPPED_LOCATION
+ && close_loc.column+1 == semi_loc.column
+#endif
+ )
+ warning (OPT_Wempty_body,
+ "suggest a space before %<;%> or explicit braces around empty "
+ "body in %<%s%> statement",
+ type);
+}
+
/* Parse an iteration-statement.
iteration-statement:
@@ -7107,6 +7152,7 @@ cp_parser_iteration_statement (cp_parser* parser)
/* Parse the condition. */
condition = cp_parser_condition (parser);
finish_while_stmt_cond (condition, statement);
+ check_empty_body (parser, "while");
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
/* Parse the dependent statement. */
@@ -7168,6 +7214,7 @@ cp_parser_iteration_statement (cp_parser* parser)
if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
expression = cp_parser_expression (parser, /*cast_p=*/false);
finish_for_expr (expression, statement);
+ check_empty_body (parser, "for");
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 45a632493de..1069892a50c 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1972,7 +1972,7 @@ is used. @xref{C Dialect Options,,Options
Controlling C Dialect}.
@item function_vector
-@cindex calling functions through the function vector on the H8/300 processors
+@cindex calling functions through the function vector on H8/300, M16C, and M32C processors
Use this attribute on the H8/300, H8/300H, and H8S to indicate that the specified
function should be called through the function vector. Calling a
function through the function vector will reduce code size, however;
@@ -1982,6 +1982,40 @@ and 64 entries on the H8/300H and H8S) and shares space with the interrupt vecto
You must use GAS and GLD from GNU binutils version 2.7 or later for
this attribute to work correctly.
+On M16C/M32C targets, the @code{function_vector} attribute declares a
+special page subroutine call function. Use of this attribute reduces
+the code size by 2 bytes for each call generated to the
+subroutine. The argument to the attribute is the vector number entry
+from the special page vector table which contains the 16 low-order
+bits of the subroutine's entry address. Each vector table has special
+page number (18 to 255) which are used in @code{jsrs} instruction.
+Jump addresses of the routines are generated by adding 0x0F0000 (in
+case of M16C targets) or 0xFF0000 (in case of M32C targets), to the 2
+byte addresses set in the vector table. Therefore you need to ensure
+that all the special page vector routines should get mapped within the
+address range 0x0F0000 to 0x0FFFFF (for M16C) and 0xFF0000 to 0xFFFFFF
+(for M32C).
+
+In the following example 2 bytes will be saved for each call to
+function @code{foo}.
+
+@smallexample
+void foo (void) __attribute__((function_vector(0x18)));
+void foo (void)
+@{
+@}
+
+void bar (void)
+@{
+ foo();
+@}
+@end smallexample
+
+If functions are defined in one file and are called in another file,
+then be sure to write this declaration in both files.
+
+This attribute is ignored for R8C target.
+
@item interrupt
@cindex interrupt handler functions
Use this attribute on the ARM, AVR, C4x, CRX, M32C, M32R/D, MS1, and Xstormy16
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e608dbc017e..9e76394146c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -439,12 +439,13 @@ Objective-C and Objective-C++ Dialects}.
-mcall-prologues -mno-tablejump -mtiny-stack -mint8}
@emph{Blackfin Options}
-@gccoptlist{-momit-leaf-frame-pointer -mno-omit-leaf-frame-pointer @gol
--mspecld-anomaly -mno-specld-anomaly -mcsync-anomaly -mno-csync-anomaly @gol
--mlow-64k -mno-low64k -mstack-check-l1 -mid-shared-library @gol
--mno-id-shared-library -mshared-library-id=@var{n} @gol
--mleaf-id-shared-library -mno-leaf-id-shared-library @gol
--msep-data -mno-sep-data -mlong-calls -mno-long-calls}
+@gccoptlist{-mcpu=@var{cpu} -msim -momit-leaf-frame-pointer @gol
+-mno-omit-leaf-frame-pointer -mspecld-anomaly -mno-specld-anomaly @gol
+-mcsync-anomaly -mno-csync-anomaly -mlow-64k -mno-low64k @gol
+-mstack-check-l1 -mid-shared-library -mno-id-shared-library @gol
+-mshared-library-id=@var{n} -mleaf-id-shared-library @gol
+-mno-leaf-id-shared-library -msep-data -mno-sep-data -mlong-calls @gol
+-mno-long-calls}
@emph{CRIS Options}
@gccoptlist{-mcpu=@var{cpu} -march=@var{cpu} -mtune=@var{cpu} @gol
@@ -3157,6 +3158,11 @@ An empty body occurs in an @samp{if}, @samp{else} or
@samp{do while} statement. This warning can be independently
controlled by @option{-Wempty-body}.
+@item @r{(C++ only)}
+An empty body occurs in a @samp{while} or @samp{for} statement with no
+whitespacing before the semicolon. This warning can be independently
+controlled by @option{-Wempty-body}.
+
@item
A pointer is compared against integer zero with @samp{<}, @samp{<=},
@samp{>}, or @samp{>=}.
@@ -3421,8 +3427,10 @@ to them.
@item -Wempty-body
@opindex Wempty-body
-An empty body occurs in an @samp{if}, @samp{else} or @samp{do while}
-statement. This warning is also enabled by @option{-Wextra}.
+Warn if an empty body occurs in an @samp{if}, @samp{else} or @samp{do
+while} statement. Additionally, in C++, warn when an empty body occurs
+in a @samp{while} or @samp{for} statement with no whitespacing before
+the semicolon. This warning is also enabled by @option{-Wextra}.
@item -Wsign-compare
@opindex Wsign-compare
@@ -8342,6 +8350,23 @@ size.
@cindex Blackfin Options
@table @gcctabopt
+@item -mcpu=@var{cpu}
+@opindex mcpu=
+Specifies the name of the target Blackfin processor. Currently, @var{cpu}
+can be one of @samp{bf531}, @samp{bf532}, @samp{bf533},
+@samp{bf534}, @samp{bf536}, @samp{bf537}, @samp{bf561}.
+Without this option, @samp{bf532} is used as the processor by default.
+The corresponding predefined processor macros for @var{cpu} is to
+be defined. For the @samp{bfin-elf} toolchain, this causes the hardware
+BSP provided by libgloss to be linked in if @samp{-msim} is not given.
+Support for @samp{bf561} is incomplete; only the processor macro is defined.
+
+@item -msim
+@opindex msim
+Specifies that the program will be run on the simulator. This causes
+the simulator BSP provided by libgloss to be linked in. This option
+has effect only for @samp{bfin-elf} toolchain.
+
@item -momit-leaf-frame-pointer
@opindex momit-leaf-frame-pointer
Don't keep the frame pointer in a register for leaf functions. This
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 56cc60f2e1e..53c5769f788 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -3687,6 +3687,25 @@ These instructions are not allowed to @code{FAIL}.
Like @code{madd@var{m}@var{n}4}, but zero-extend the multiplication
operands instead of sign-extending them.
+@cindex @code{msub@var{m}@var{n}4} instruction pattern
+@item @samp{msub@var{m}@var{n}4}
+Multiply operands 1 and 2, sign-extend them to mode @var{n}, subtract the
+result from operand 3, and store the result in operand 0. Operands 1 and 2
+have mode @var{m} and operands 0 and 3 have mode @var{n}.
+Both modes must be integer modes and @var{n} must be twice
+the size of @var{m}.
+
+In other words, @code{msub@var{m}@var{n}4} is like
+@code{mul@var{m}@var{n}3} except that it also subtracts the result
+from operand 3.
+
+These instructions are not allowed to @code{FAIL}.
+
+@cindex @code{umsub@var{m}@var{n}4} instruction pattern
+@item @samp{umsub@var{m}@var{n}4}
+Like @code{msub@var{m}@var{n}4}, but zero-extend the multiplication
+operands instead of sign-extending them.
+
@cindex @code{divmod@var{m}4} instruction pattern
@item @samp{divmod@var{m}4}
Signed division that produces both a quotient and a remainder.
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index e816026a3d4..cd6bf24d611 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -167,7 +167,6 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
static rtx make_call_insn_raw (rtx);
static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
-static void unshare_all_decls (tree);
static void reset_used_decls (tree);
static void mark_label_nuses (rtx);
static hashval_t const_int_htab_hash (const void *);
@@ -2115,17 +2114,8 @@ set_new_first_and_last_insn (rtx first, rtx last)
structure. This routine should only be called once. */
static void
-unshare_all_rtl_1 (tree fndecl, rtx insn)
+unshare_all_rtl_1 (rtx insn)
{
- tree decl;
-
- /* Make sure that virtual parameters are not shared. */
- for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
- SET_DECL_RTL (decl, copy_rtx_if_shared (DECL_RTL (decl)));
-
- /* Make sure that virtual stack slots are not shared. */
- unshare_all_decls (DECL_INITIAL (fndecl));
-
/* Unshare just about everything else. */
unshare_all_rtl_in_chain (insn);
@@ -2166,13 +2156,13 @@ unshare_all_rtl_again (rtx insn)
reset_used_flags (stack_slot_list);
- unshare_all_rtl_1 (cfun->decl, insn);
+ unshare_all_rtl_1 (insn);
}
unsigned int
unshare_all_rtl (void)
{
- unshare_all_rtl_1 (current_function_decl, get_insns ());
+ unshare_all_rtl_1 (get_insns ());
return 0;
}
@@ -2358,23 +2348,6 @@ unshare_all_rtl_in_chain (rtx insn)
}
}
-/* Go through all virtual stack slots of a function and copy any
- shared structure. */
-static void
-unshare_all_decls (tree blk)
-{
- tree t;
-
- /* Copy shared decls. */
- for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t))
- if (DECL_RTL_SET_P (t))
- SET_DECL_RTL (t, copy_rtx_if_shared (DECL_RTL (t)));
-
- /* Now process sub-blocks. */
- for (t = BLOCK_SUBBLOCKS (blk); t; t = TREE_CHAIN (t))
- unshare_all_decls (t);
-}
-
/* Go through all virtual stack slots of a function and mark them as
not shared. */
static void
diff --git a/gcc/expr.c b/gcc/expr.c
index ed7d8d77bfe..8c18e66a5c4 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8139,6 +8139,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1));
case MINUS_EXPR:
+ /* Check if this is a case for multiplication and subtraction. */
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TREE_CODE (TREE_OPERAND (exp, 1)) == MULT_EXPR)
+ {
+ tree subsubexp0, subsubexp1;
+ enum tree_code code0, code1;
+
+ subexp1 = TREE_OPERAND (exp, 1);
+ subsubexp0 = TREE_OPERAND (subexp1, 0);
+ subsubexp1 = TREE_OPERAND (subexp1, 1);
+ code0 = TREE_CODE (subsubexp0);
+ code1 = TREE_CODE (subsubexp1);
+ if (code0 == NOP_EXPR && code1 == NOP_EXPR
+ && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+ < TYPE_PRECISION (TREE_TYPE (subsubexp0)))
+ && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))
+ && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+ == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))))
+ {
+ tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
+ enum machine_mode innermode = TYPE_MODE (op0type);
+ bool zextend_p = TYPE_UNSIGNED (op0type);
+ this_optab = zextend_p ? umsub_widen_optab : smsub_widen_optab;
+ if (mode == GET_MODE_2XWIDER_MODE (innermode)
+ && (this_optab->handlers[(int) mode].insn_code
+ != CODE_FOR_nothing))
+ {
+ expand_operands (TREE_OPERAND (subsubexp0, 0),
+ TREE_OPERAND (subsubexp1, 0),
+ NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+ op2 = expand_expr (TREE_OPERAND (exp, 0), subtarget,
+ VOIDmode, 0);
+ temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
+ target, unsignedp);
+ gcc_assert (temp);
+ return REDUCE_BIT_FIELD (temp);
+ }
+ }
+ }
+
/* For initializers, we are allowed to return a MINUS of two
symbolic constants. Here we handle all cases when both operands
are constant. */
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 1413b9eb18a..3232c93a09c 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -6008,11 +6008,10 @@ extract_array_ref (tree expr, tree *base, tree *offset)
if (extract_array_ref (op0, &inner_base, &dummy1))
{
*base = inner_base;
- if (dummy1 == NULL_TREE)
- *offset = TREE_OPERAND (expr, 1);
- else
+ *offset = fold_convert (sizetype, TREE_OPERAND (expr, 1));
+ if (dummy1 != NULL_TREE)
*offset = fold_build2 (PLUS_EXPR, sizetype,
- dummy1, TREE_OPERAND (expr, 1));
+ dummy1, *offset);
return true;
}
}
@@ -6030,6 +6029,7 @@ extract_array_ref (tree expr, tree *base, tree *offset)
*base = TREE_OPERAND (op0, 0);
*offset = fold_build2 (MULT_EXPR, TREE_TYPE (idx), idx,
array_ref_element_size (op0));
+ *offset = fold_convert (sizetype, *offset);
}
else
{
@@ -6879,6 +6879,7 @@ try_move_mult_to_index (tree addr, tree op1)
tree ret, pos;
tree itype;
bool mdim = false;
+ STRIP_NOPS (op1);
/* Canonicalize op1 into a possibly non-constant delta
and an INTEGER_CST s. */
@@ -9119,7 +9120,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
expressions. */
if (TREE_CODE (arg0) == ADDR_EXPR)
{
- tem = try_move_mult_to_index (arg0, arg1);
+ tem = try_move_mult_to_index (arg0, fold_convert (sizetype, arg1));
if (tem)
return fold_convert (type, tem);
}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 361ffcc04be..36137451ec6 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,60 @@
+2007-05-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/31630
+ * resolve.c (resolve_symbol): Remove the flagging mechanism from the
+ formal namespace resolution and instead check that the formal
+ namespace is not the current namespace.
+
+2007-05-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/31692
+ * trans-array.c (gfc_conv_array_parameter): Convert full array
+ references to the result of the procedure enclusing the call.
+
+2007-05-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/29397
+ PR fortran/29400
+ * decl.c (add_init_expr_to_sym): Expand a scalar initializer
+ for a parameter array into an array expression with the right
+ shape.
+ * array.c (spec_dimen_size): Remove static attribute.
+ * gfortran.h : Prototype for spec_dimen_size.
+
+2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/31399
+ * trans-stmt.c (gfc_trans_do): Handle large loop counts.
+
+2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/31764
+ * simplify.c (gfc_simplify_new_line): NEW_LINE can be simplified
+ even for non constant arguments.
+
+2007-05-06 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+ Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/31201
+ * gfortran.h: Add runtime error codes from libgfortran.h. Define
+ MAX_UNIT_NUMBER.
+ * trans.c (gfc_trans_runtime_check): Update the format of runtime error
+ messages to match library runtime errors. Use call to new library
+ function runtime_error_at().
+ * trans.h: Add prototype for new function gfc_trans_io_runtime_check.
+ Add declaration for library functions runtime_error_at and
+ generate_error.
+ * trans_io.c (gfc_trans_io_runtime_check): New function.
+ (set_parameter_value): Add error checking for UNIT numbers.
+ (set_parameter_ref): Initialize the users variable to zero.
+ (gfc_trans_open): Move setting of unit number to after setting of common
+ flags so that runtime error trapping can be detected.
+ (gfc_trans_close): Likewise. (build_filepos): Likewise.
+ (gfc_trans_inquire): Likewise. (build_dt): Likewise.
+ * trans-decl.c: Add declarations for runtime_error_at and
+ generate_error. (gfc_build_builtin_function_decls): Build function
+ declarations for runtime_error_at and generate_error.
+
2007-05-06 Paul Thomas <pault@gcc.gnu.org>
PR fortran/31540
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index 895bccc14d1..9359624efec 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -1714,7 +1714,7 @@ gfc_get_array_element (gfc_expr *array, int element)
/* Get the size of single dimension of an array specification. The
array is guaranteed to be one dimensional. */
-static try
+try
spec_dimen_size (gfc_array_spec *as, int dimen, mpz_t *result)
{
if (as == NULL)
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 1dcc53dd067..0071f905611 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -974,7 +974,44 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp,
/* Add initializer. Make sure we keep the ranks sane. */
if (sym->attr.dimension && init->rank == 0)
- init->rank = sym->as->rank;
+ {
+ mpz_t size;
+ gfc_expr *array;
+ gfc_constructor *c;
+ int n;
+ if (sym->attr.flavor == FL_PARAMETER
+ && init->expr_type == EXPR_CONSTANT
+ && spec_size (sym->as, &size) == SUCCESS
+ && mpz_cmp_si (size, 0) > 0)
+ {
+ array = gfc_start_constructor (init->ts.type, init->ts.kind,
+ &init->where);
+
+ array->value.constructor = c = NULL;
+ for (n = 0; n < (int)mpz_get_si (size); n++)
+ {
+ if (array->value.constructor == NULL)
+ {
+ array->value.constructor = c = gfc_get_constructor ();
+ c->expr = init;
+ }
+ else
+ {
+ c->next = gfc_get_constructor ();
+ c = c->next;
+ c->expr = gfc_copy_expr (init);
+ }
+ }
+
+ array->shape = gfc_get_shape (sym->as->rank);
+ for (n = 0; n < sym->as->rank; n++)
+ spec_dimen_size (sym->as, n, &array->shape[n]);
+
+ init = array;
+ mpz_clear (size);
+ }
+ init->rank = sym->as->rank;
+ }
sym->value = init;
*initp = NULL;
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 039c1ee9c20..2030ec29bb2 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -472,6 +472,39 @@ enum gfc_generic_isym_id
};
typedef enum gfc_generic_isym_id gfc_generic_isym_id;
+/* Runtime errors. The EOR and EOF errors are required to be negative.
+ These codes must be kept synchronized with their equivalents in
+ libgfortran/libgfortran.h . */
+
+typedef enum
+{
+ IOERROR_FIRST = -3, /* Marker for the first error. */
+ IOERROR_EOR = -2,
+ IOERROR_END = -1,
+ IOERROR_OK = 0, /* Indicates success, must be zero. */
+ IOERROR_OS = 5000, /* Operating system error, more info in errno. */
+ IOERROR_OPTION_CONFLICT,
+ IOERROR_BAD_OPTION,
+ IOERROR_MISSING_OPTION,
+ IOERROR_ALREADY_OPEN,
+ IOERROR_BAD_UNIT,
+ IOERROR_FORMAT,
+ IOERROR_BAD_ACTION,
+ IOERROR_ENDFILE,
+ IOERROR_BAD_US,
+ IOERROR_READ_VALUE,
+ IOERROR_READ_OVERFLOW,
+ IOERROR_INTERNAL,
+ IOERROR_INTERNAL_UNIT,
+ IOERROR_ALLOCATION,
+ IOERROR_DIRECT_EOR,
+ IOERROR_SHORT_RECORD,
+ IOERROR_CORRUPT_FILE,
+ IOERROR_LAST /* Not a real error, the last error # + 1. */
+}
+ioerror_codes;
+
+
/************************* Structures *****************************/
/* Used for keeping things in balanced binary trees. */
@@ -2088,6 +2121,7 @@ void gfc_insert_constructor (gfc_expr *, gfc_constructor *);
gfc_constructor *gfc_get_constructor (void);
tree gfc_conv_array_initializer (tree type, gfc_expr * expr);
try spec_size (gfc_array_spec *, mpz_t *);
+try spec_dimen_size (gfc_array_spec *, int, mpz_t *);
int gfc_is_compile_time_shape (gfc_array_spec *);
/* interface.c -- FIXME: some of these should be in symbol.c */
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 4ec9a921c4a..5c5d40bf6d5 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -6136,9 +6136,7 @@ resolve_fl_parameter (gfc_symbol *sym)
static void
resolve_symbol (gfc_symbol *sym)
{
- /* Zero if we are checking a formal namespace. */
- static int formal_ns_flag = 1;
- int formal_ns_save, check_constant, mp_flag;
+ int check_constant, mp_flag;
gfc_symtree *symtree;
gfc_symtree *this_symtree;
gfc_namespace *ns;
@@ -6345,18 +6343,9 @@ resolve_symbol (gfc_symbol *sym)
formal_arg_flag = 0;
- /* Resolve formal namespaces. The symbols in formal namespaces that
- themselves are from procedures in formal namespaces will not stand
- resolution, except when they are use associated.
- TODO: Fix the symbols in formal namespaces so that resolution can
- be done unconditionally. */
- if (formal_ns_flag && sym != NULL && sym->formal_ns != NULL)
- {
- formal_ns_save = formal_ns_flag;
- formal_ns_flag = sym->attr.use_assoc ? 1 : 0;
- gfc_resolve (sym->formal_ns);
- formal_ns_flag = formal_ns_save;
- }
+ /* Resolve formal namespaces. */
+ if (sym->formal_ns && sym->formal_ns != gfc_current_ns)
+ gfc_resolve (sym->formal_ns);
/* Check threadprivate restrictions. */
if (sym->attr.threadprivate && !sym->attr.save
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 9df2e812c1d..ed62ee34da4 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -2641,13 +2641,8 @@ gfc_simplify_new_line (gfc_expr *e)
{
gfc_expr *result;
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
result = gfc_constant_result (BT_CHARACTER, e->ts.kind, &e->where);
-
result->value.character.string = gfc_getmem (2);
-
result->value.character.length = 1;
result->value.character.string[0] = '\n';
result->value.character.string[1] = '\0'; /* For debugger */
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 92fd67cccf5..4997673904f 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -4748,14 +4748,25 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77)
tree desc;
tree tmp;
tree stmt;
+ tree parent = DECL_CONTEXT (current_function_decl);
+ bool full_array_var, this_array_result;
gfc_symbol *sym;
stmtblock_t block;
+ full_array_var = (expr->expr_type == EXPR_VARIABLE
+ && expr->ref->u.ar.type == AR_FULL);
+ sym = full_array_var ? expr->symtree->n.sym : NULL;
+
+ /* Is this the result of the enclosing procedure? */
+ this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
+ if (this_array_result
+ && (sym->backend_decl != current_function_decl)
+ && (sym->backend_decl != parent))
+ this_array_result = false;
+
/* Passing address of the array if it is not pointer or assumed-shape. */
- if (expr->expr_type == EXPR_VARIABLE
- && expr->ref->u.ar.type == AR_FULL && g77)
+ if (full_array_var && g77 && !this_array_result)
{
- sym = expr->symtree->n.sym;
tmp = gfc_get_symbol_decl (sym);
if (sym->ts.type == BT_CHARACTER)
@@ -4784,8 +4795,25 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77)
}
}
- se->want_pointer = 1;
- gfc_conv_expr_descriptor (se, expr, ss);
+ if (this_array_result)
+ {
+ /* Result of the enclosing function. */
+ gfc_conv_expr_descriptor (se, expr, ss);
+ se->expr = build_fold_addr_expr (se->expr);
+
+ if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
+ && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
+ se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr));
+
+ return;
+ }
+ else
+ {
+ /* Every other type of array. */
+ se->want_pointer = 1;
+ gfc_conv_expr_descriptor (se, expr, ss);
+ }
+
/* Deallocate the allocatable components of structures that are
not variable. */
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index ccf46852761..835e515e628 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -90,6 +90,8 @@ tree gfor_fndecl_stop_numeric;
tree gfor_fndecl_stop_string;
tree gfor_fndecl_select_string;
tree gfor_fndecl_runtime_error;
+tree gfor_fndecl_runtime_error_at;
+tree gfor_fndecl_generate_error;
tree gfor_fndecl_set_fpe;
tree gfor_fndecl_set_std;
tree gfor_fndecl_set_convert;
@@ -2335,6 +2337,18 @@ gfc_build_builtin_function_decls (void)
/* The runtime_error function does not return. */
TREE_THIS_VOLATILE (gfor_fndecl_runtime_error) = 1;
+ gfor_fndecl_runtime_error_at =
+ gfc_build_library_function_decl (get_identifier (PREFIX("runtime_error_at")),
+ void_type_node, 2, pchar_type_node,
+ pchar_type_node);
+ /* The runtime_error_at function does not return. */
+ TREE_THIS_VOLATILE (gfor_fndecl_runtime_error_at) = 1;
+
+ gfor_fndecl_generate_error =
+ gfc_build_library_function_decl (get_identifier (PREFIX("generate_error")),
+ void_type_node, 3, pvoid_type_node,
+ gfc_c_int_type_node, pchar_type_node);
+
gfor_fndecl_set_fpe =
gfc_build_library_function_decl (get_identifier (PREFIX("set_fpe")),
void_type_node, 1, gfc_c_int_type_node);
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index 856938c9fdd..4b87bcba241 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -212,6 +212,62 @@ gfc_build_st_parameter (enum ioparam_type ptype, tree *types)
st_parameter[ptype].type = t;
}
+
+/* Build code to test an error condition and call generate_error if needed.
+ Note: This builds calls to generate_error in the runtime library function.
+ The function generate_error is dependent on certain parameters in the
+ st_parameter_common flags to be set. (See libgfortran/runtime/error.c)
+ Therefore, the code to set these flags must be generated before
+ this function is used. */
+
+void
+gfc_trans_io_runtime_check (tree cond, tree var, int error_code,
+ const char * msgid, stmtblock_t * pblock)
+{
+ stmtblock_t block;
+ tree body;
+ tree tmp;
+ tree arg1, arg2, arg3;
+ char *message;
+
+ if (integer_zerop (cond))
+ return;
+
+ /* The code to generate the error. */
+ gfc_start_block (&block);
+
+ arg1 = build_fold_addr_expr (var);
+
+ arg2 = build_int_cst (integer_type_node, error_code),
+
+ asprintf (&message, "%s", _(msgid));
+ arg3 = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const(message));
+ gfc_free(message);
+
+ tmp = build_call_expr (gfor_fndecl_generate_error, 3, arg1, arg2, arg3);
+
+ gfc_add_expr_to_block (&block, tmp);
+
+ body = gfc_finish_block (&block);
+
+ if (integer_onep (cond))
+ {
+ gfc_add_expr_to_block (pblock, body);
+ }
+ else
+ {
+ /* Tell the compiler that this isn't likely. */
+ cond = fold_convert (long_integer_type_node, cond);
+ tmp = build_int_cst (long_integer_type_node, 0);
+ cond = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp);
+ cond = fold_convert (boolean_type_node, cond);
+
+ tmp = build3_v (COND_EXPR, cond, body, build_empty_stmt ());
+ gfc_add_expr_to_block (pblock, tmp);
+ }
+}
+
+
/* Create function decls for IO library functions. */
void
@@ -396,16 +452,49 @@ set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
gfc_se se;
tree tmp;
gfc_st_parameter_field *p = &st_parameter_field[type];
+ tree dest_type = TREE_TYPE (p->field);
gfc_init_se (&se, NULL);
- gfc_conv_expr_type (&se, e, TREE_TYPE (p->field));
+ gfc_conv_expr_val (&se, e);
+
+ /* If we're storing a UNIT number, we need to check it first. */
+ if (type == IOPARM_common_unit && e->ts.kind != 4)
+ {
+ tree cond, max;
+ ioerror_codes bad_unit;
+ int i;
+
+ bad_unit = IOERROR_BAD_UNIT;
+
+ /* Don't evaluate the UNIT number multiple times. */
+ se.expr = gfc_evaluate_now (se.expr, &se.pre);
+
+ /* UNIT numbers should be nonnegative. */
+ cond = fold_build2 (LT_EXPR, boolean_type_node, se.expr,
+ build_int_cst (TREE_TYPE (se.expr),0));
+ gfc_trans_io_runtime_check (cond, var, bad_unit,
+ "Negative unit number in I/O statement",
+ &se.pre);
+
+ /* UNIT numbers should be less than the max. */
+ i = gfc_validate_kind (BT_INTEGER, 4, false);
+ max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
+ cond = fold_build2 (GT_EXPR, boolean_type_node, se.expr,
+ fold_convert (TREE_TYPE (se.expr), max));
+ gfc_trans_io_runtime_check (cond, var, bad_unit,
+ "Unit number in I/O statement too large",
+ &se.pre);
+
+ }
+
+ se.expr = convert (dest_type, se.expr);
gfc_add_block_to_block (block, &se.pre);
if (p->param_type == IOPARM_ptype_common)
var = build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
- tmp = build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
- NULL_TREE);
+
+ tmp = build3 (COMPONENT_REF, dest_type, var, p->field, NULL_TREE);
gfc_add_modify_expr (block, tmp, se.expr);
return p->mask;
}
@@ -430,20 +519,42 @@ set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
if (TYPE_MODE (TREE_TYPE (se.expr))
== TYPE_MODE (TREE_TYPE (TREE_TYPE (p->field))))
- addr = convert (TREE_TYPE (p->field),
- build_fold_addr_expr (se.expr));
+ {
+ addr = convert (TREE_TYPE (p->field), build_fold_addr_expr (se.expr));
+
+ /* If this is for the iostat variable initialize the
+ user variable to IOERROR_OK which is zero. */
+ if (type == IOPARM_common_iostat)
+ {
+ ioerror_codes ok;
+ ok = IOERROR_OK;
+ gfc_add_modify_expr (block, se.expr,
+ build_int_cst (TREE_TYPE (se.expr), ok));
+ }
+ }
else
{
/* The type used by the library has different size
- from the type of the variable supplied by the user.
- Need to use a temporary. */
- tree tmpvar
- = gfc_create_var (TREE_TYPE (TREE_TYPE (p->field)),
- st_parameter_field[type].name);
+ from the type of the variable supplied by the user.
+ Need to use a temporary. */
+ tree tmpvar = gfc_create_var (TREE_TYPE (TREE_TYPE (p->field)),
+ st_parameter_field[type].name);
+
+ /* If this is for the iostat variable, initialize the
+ user variable to IOERROR_OK which is zero. */
+ if (type == IOPARM_common_iostat)
+ {
+ ioerror_codes ok;
+ ok = IOERROR_OK;
+ gfc_add_modify_expr (block, tmpvar,
+ build_int_cst (TREE_TYPE (tmpvar), ok));
+ }
+
addr = build_fold_addr_expr (tmpvar);
+ /* After the I/O operation, we set the variable from the temporary. */
tmp = convert (TREE_TYPE (se.expr), tmpvar);
gfc_add_modify_expr (postblock, se.expr, tmp);
- }
+ }
if (p->param_type == IOPARM_ptype_common)
var = build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
@@ -776,10 +887,16 @@ gfc_trans_open (gfc_code * code)
set_error_locus (&block, var, &code->loc);
p = code->ext.open;
- if (p->unit)
- set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
- else
- set_parameter_const (&block, var, IOPARM_common_unit, 0);
+ if (p->iomsg)
+ mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
+ p->iomsg);
+
+ if (p->iostat)
+ mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
+ p->iostat);
+
+ if (p->err)
+ mask |= IOPARM_common_err;
if (p->file)
mask |= set_string (&block, &post_block, var, IOPARM_open_file, p->file);
@@ -817,23 +934,17 @@ gfc_trans_open (gfc_code * code)
if (p->pad)
mask |= set_string (&block, &post_block, var, IOPARM_open_pad, p->pad);
- if (p->iomsg)
- mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
- p->iomsg);
-
- if (p->iostat)
- mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
- p->iostat);
-
- if (p->err)
- mask |= IOPARM_common_err;
-
if (p->convert)
mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
p->convert);
set_parameter_const (&block, var, IOPARM_common_flags, mask);
+ if (p->unit)
+ set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
+ else
+ set_parameter_const (&block, var, IOPARM_common_unit, 0);
+
tmp = build_fold_addr_expr (var);
tmp = build_call_expr (iocall[IOCALL_OPEN], 1, tmp);
gfc_add_expr_to_block (&block, tmp);
@@ -864,15 +975,6 @@ gfc_trans_close (gfc_code * code)
set_error_locus (&block, var, &code->loc);
p = code->ext.close;
- if (p->unit)
- set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
- else
- set_parameter_const (&block, var, IOPARM_common_unit, 0);
-
- if (p->status)
- mask |= set_string (&block, &post_block, var, IOPARM_close_status,
- p->status);
-
if (p->iomsg)
mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
p->iomsg);
@@ -884,8 +986,17 @@ gfc_trans_close (gfc_code * code)
if (p->err)
mask |= IOPARM_common_err;
+ if (p->status)
+ mask |= set_string (&block, &post_block, var, IOPARM_close_status,
+ p->status);
+
set_parameter_const (&block, var, IOPARM_common_flags, mask);
+ if (p->unit)
+ set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
+ else
+ set_parameter_const (&block, var, IOPARM_common_unit, 0);
+
tmp = build_fold_addr_expr (var);
tmp = build_call_expr (iocall[IOCALL_CLOSE], 1, tmp);
gfc_add_expr_to_block (&block, tmp);
@@ -918,11 +1029,6 @@ build_filepos (tree function, gfc_code * code)
set_error_locus (&block, var, &code->loc);
- if (p->unit)
- set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
- else
- set_parameter_const (&block, var, IOPARM_common_unit, 0);
-
if (p->iomsg)
mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
p->iomsg);
@@ -936,6 +1042,11 @@ build_filepos (tree function, gfc_code * code)
set_parameter_const (&block, var, IOPARM_common_flags, mask);
+ if (p->unit)
+ set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
+ else
+ set_parameter_const (&block, var, IOPARM_common_unit, 0);
+
tmp = build_fold_addr_expr (var);
tmp = build_call_expr (function, 1, tmp);
gfc_add_expr_to_block (&block, tmp);
@@ -1003,19 +1114,6 @@ gfc_trans_inquire (gfc_code * code)
set_error_locus (&block, var, &code->loc);
p = code->ext.inquire;
- /* Sanity check. */
- if (p->unit && p->file)
- gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc);
-
- if (p->unit)
- set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
- else
- set_parameter_const (&block, var, IOPARM_common_unit, 0);
-
- if (p->file)
- mask |= set_string (&block, &post_block, var, IOPARM_inquire_file,
- p->file);
-
if (p->iomsg)
mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
p->iomsg);
@@ -1024,6 +1122,17 @@ gfc_trans_inquire (gfc_code * code)
mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
p->iostat);
+ if (p->err)
+ mask |= IOPARM_common_err;
+
+ /* Sanity check. */
+ if (p->unit && p->file)
+ gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc);
+
+ if (p->file)
+ mask |= set_string (&block, &post_block, var, IOPARM_inquire_file,
+ p->file);
+
if (p->exist)
mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
p->exist);
@@ -1108,9 +1217,6 @@ gfc_trans_inquire (gfc_code * code)
mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
p->pad);
- if (p->err)
- mask |= IOPARM_common_err;
-
if (p->convert)
mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
p->convert);
@@ -1121,6 +1227,11 @@ gfc_trans_inquire (gfc_code * code)
set_parameter_const (&block, var, IOPARM_common_flags, mask);
+ if (p->unit)
+ set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
+ else
+ set_parameter_const (&block, var, IOPARM_common_unit, 0);
+
tmp = build_fold_addr_expr (var);
tmp = build_call_expr (iocall[IOCALL_INQUIRE], 1, tmp);
gfc_add_expr_to_block (&block, tmp);
@@ -1419,14 +1530,29 @@ build_dt (tree function, gfc_code * code)
var, dt->io_unit);
set_parameter_const (&block, var, IOPARM_common_unit, 0);
}
- else
- set_parameter_value (&block, var, IOPARM_common_unit, dt->io_unit);
}
else
set_parameter_const (&block, var, IOPARM_common_unit, 0);
if (dt)
{
+ if (dt->iomsg)
+ mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
+ dt->iomsg);
+
+ if (dt->iostat)
+ mask |= set_parameter_ref (&block, &post_end_block, var,
+ IOPARM_common_iostat, dt->iostat);
+
+ if (dt->err)
+ mask |= IOPARM_common_err;
+
+ if (dt->eor)
+ mask |= IOPARM_common_eor;
+
+ if (dt->end)
+ mask |= IOPARM_common_end;
+
if (dt->rec)
mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec);
@@ -1447,27 +1573,10 @@ build_dt (tree function, gfc_code * code)
dt->format_label->format);
}
- if (dt->iomsg)
- mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
- dt->iomsg);
-
- if (dt->iostat)
- mask |= set_parameter_ref (&block, &post_end_block, var,
- IOPARM_common_iostat, dt->iostat);
-
if (dt->size)
mask |= set_parameter_ref (&block, &post_end_block, var,
IOPARM_dt_size, dt->size);
- if (dt->err)
- mask |= IOPARM_common_err;
-
- if (dt->eor)
- mask |= IOPARM_common_eor;
-
- if (dt->end)
- mask |= IOPARM_common_end;
-
if (dt->namelist)
{
if (dt->format_expr || dt->format_label)
@@ -1491,6 +1600,9 @@ build_dt (tree function, gfc_code * code)
}
else
set_parameter_const (&block, var, IOPARM_common_flags, mask);
+
+ if (dt->io_unit && dt->io_unit->ts.type == BT_INTEGER)
+ set_parameter_value (&block, var, IOPARM_common_unit, dt->io_unit);
}
else
set_parameter_const (&block, var, IOPARM_common_flags, mask);
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index cdc8dc6c669..92462cbad75 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -809,22 +809,22 @@ gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
to:
[evaluate loop bounds and step]
- count = (to + step - from) / step;
+ empty = (step > 0 ? to < from : to > from);
+ countm1 = (to - from) / step;
dovar = from;
+ if (empty) goto exit_label;
for (;;)
{
body;
cycle_label:
dovar += step
- count--;
- if (count <=0) goto exit_label;
+ countm1--;
+ if (countm1 ==0) goto exit_label;
}
exit_label:
- TODO: Large loop counts
- The code above assumes the loop count fits into a signed integer kind,
- i.e. Does not work for loop counts > 2^31 for integer(kind=4) variables
- We must support the full range. */
+ countm1 is an unsigned integer. It is equal to the loop count minus one,
+ because the loop count itself can overflow. */
tree
gfc_trans_do (gfc_code * code)
@@ -834,13 +834,15 @@ gfc_trans_do (gfc_code * code)
tree from;
tree to;
tree step;
- tree count;
- tree count_one;
+ tree empty;
+ tree countm1;
tree type;
+ tree utype;
tree cond;
tree cycle_label;
tree exit_label;
tree tmp;
+ tree pos_step;
stmtblock_t block;
stmtblock_t body;
@@ -874,48 +876,59 @@ gfc_trans_do (gfc_code * code)
|| tree_int_cst_equal (step, integer_minus_one_node)))
return gfc_trans_simple_do (code, &block, dovar, from, to, step);
- /* Initialize loop count. This code is executed before we enter the
- loop body. We generate: count = (to + step - from) / step. */
+ /* We need a special check for empty loops:
+ empty = (step > 0 ? to < from : to > from); */
+ pos_step = fold_build2 (GT_EXPR, boolean_type_node, step,
+ fold_convert (type, integer_zero_node));
+ empty = fold_build3 (COND_EXPR, boolean_type_node, pos_step,
+ fold_build2 (LT_EXPR, boolean_type_node, to, from),
+ fold_build2 (GT_EXPR, boolean_type_node, to, from));
- tmp = fold_build2 (MINUS_EXPR, type, step, from);
- tmp = fold_build2 (PLUS_EXPR, type, to, tmp);
+ /* Initialize loop count. This code is executed before we enter the
+ loop body. We generate: countm1 = abs(to - from) / abs(step). */
if (TREE_CODE (type) == INTEGER_TYPE)
{
- tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step);
- count = gfc_create_var (type, "count");
+ tree ustep;
+
+ utype = gfc_unsigned_type (type);
+
+ /* tmp = abs(to - from) / abs(step) */
+ ustep = fold_convert (utype, fold_build1 (ABS_EXPR, type, step));
+ tmp = fold_build3 (COND_EXPR, type, pos_step,
+ fold_build2 (MINUS_EXPR, type, to, from),
+ fold_build2 (MINUS_EXPR, type, from, to));
+ tmp = fold_build2 (TRUNC_DIV_EXPR, utype, fold_convert (utype, tmp),
+ ustep);
}
else
{
/* TODO: We could use the same width as the real type.
This would probably cause more problems that it solves
when we implement "long double" types. */
+ utype = gfc_unsigned_type (gfc_array_index_type);
+ tmp = fold_build2 (MINUS_EXPR, type, to, from);
tmp = fold_build2 (RDIV_EXPR, type, tmp, step);
- tmp = fold_build1 (FIX_TRUNC_EXPR, gfc_array_index_type, tmp);
- count = gfc_create_var (gfc_array_index_type, "count");
+ tmp = fold_build1 (FIX_TRUNC_EXPR, utype, tmp);
}
- gfc_add_modify_expr (&block, count, tmp);
+ countm1 = gfc_create_var (utype, "countm1");
+ gfc_add_modify_expr (&block, countm1, tmp);
- count_one = build_int_cst (TREE_TYPE (count), 1);
+ /* Cycle and exit statements are implemented with gotos. */
+ cycle_label = gfc_build_label_decl (NULL_TREE);
+ exit_label = gfc_build_label_decl (NULL_TREE);
+ TREE_USED (exit_label) = 1;
/* Initialize the DO variable: dovar = from. */
gfc_add_modify_expr (&block, dovar, from);
+ /* If the loop is empty, go directly to the exit label. */
+ tmp = fold_build3 (COND_EXPR, void_type_node, empty,
+ build1_v (GOTO_EXPR, exit_label), build_empty_stmt ());
+ gfc_add_expr_to_block (&block, tmp);
+
/* Loop body. */
gfc_start_block (&body);
- /* Cycle and exit statements are implemented with gotos. */
- cycle_label = gfc_build_label_decl (NULL_TREE);
- exit_label = gfc_build_label_decl (NULL_TREE);
-
- /* Start with the loop condition. Loop until count <= 0. */
- cond = fold_build2 (LE_EXPR, boolean_type_node, count,
- build_int_cst (TREE_TYPE (count), 0));
- tmp = build1_v (GOTO_EXPR, exit_label);
- TREE_USED (exit_label) = 1;
- tmp = fold_build3 (COND_EXPR, void_type_node,
- cond, tmp, build_empty_stmt ());
- gfc_add_expr_to_block (&body, tmp);
-
/* Put these labels where they can be found later. We put the
labels in a TREE_LIST node (because TREE_CHAIN is already
used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
@@ -934,13 +947,21 @@ gfc_trans_do (gfc_code * code)
gfc_add_expr_to_block (&body, tmp);
}
+ /* End with the loop condition. Loop until countm1 == 0. */
+ cond = fold_build2 (EQ_EXPR, boolean_type_node, countm1,
+ build_int_cst (utype, 0));
+ tmp = build1_v (GOTO_EXPR, exit_label);
+ tmp = fold_build3 (COND_EXPR, void_type_node,
+ cond, tmp, build_empty_stmt ());
+ gfc_add_expr_to_block (&body, tmp);
+
/* Increment the loop variable. */
tmp = build2 (PLUS_EXPR, type, dovar, step);
gfc_add_modify_expr (&body, dovar, tmp);
/* Decrement the loop count. */
- tmp = build2 (MINUS_EXPR, TREE_TYPE (count), count, count_one);
- gfc_add_modify_expr (&body, count, tmp);
+ tmp = build2 (MINUS_EXPR, utype, countm1, build_int_cst (utype, 1));
+ gfc_add_modify_expr (&body, countm1, tmp);
/* End of loop body. */
tmp = gfc_finish_block (&body);
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 64dbb73a59e..5e717e4cbcf 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -318,8 +318,8 @@ gfc_trans_runtime_check (tree cond, const char * msgid, stmtblock_t * pblock,
stmtblock_t block;
tree body;
tree tmp;
- tree arg;
- char * message;
+ tree arg, arg2;
+ char *message;
int line;
if (integer_zerop (cond))
@@ -335,17 +335,21 @@ gfc_trans_runtime_check (tree cond, const char * msgid, stmtblock_t * pblock,
#else
line = where->lb->linenum;
#endif
- asprintf (&message, "%s (in file '%s', at line %d)", _(msgid),
- where->lb->file->filename, line);
+ asprintf (&message, "At line %d of file %s", line,
+ where->lb->file->filename);
}
else
- asprintf (&message, "%s (in file '%s', around line %d)", _(msgid),
+ asprintf (&message, "In file '%s', around line %d",
gfc_source_file, input_line + 1);
arg = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const(message));
gfc_free(message);
+
+ asprintf (&message, "%s", _(msgid));
+ arg2 = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const(message));
+ gfc_free(message);
- tmp = build_call_expr (gfor_fndecl_runtime_error, 1, arg);
+ tmp = build_call_expr (gfor_fndecl_runtime_error_at, 2, arg, arg2);
gfc_add_expr_to_block (&block, tmp);
body = gfc_finish_block (&block);
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 7ca396608bd..731045a2769 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -448,6 +448,7 @@ tree gfc_trans_pointer_assignment (gfc_expr *, gfc_expr *);
/* Initialize function decls for library functions. */
void gfc_build_intrinsic_lib_fndecls (void);
/* Create function decls for IO library functions. */
+void gfc_trans_io_runtime_check (tree, tree, int, const char *, stmtblock_t *);
void gfc_build_io_library_fndecls (void);
/* Build a function decl for a library function. */
tree gfc_build_library_function_decl (tree, tree, int, ...);
@@ -487,6 +488,8 @@ extern GTY(()) tree gfor_fndecl_stop_numeric;
extern GTY(()) tree gfor_fndecl_stop_string;
extern GTY(()) tree gfor_fndecl_select_string;
extern GTY(()) tree gfor_fndecl_runtime_error;
+extern GTY(()) tree gfor_fndecl_runtime_error_at;
+extern GTY(()) tree gfor_fndecl_generate_error;
extern GTY(()) tree gfor_fndecl_set_fpe;
extern GTY(()) tree gfor_fndecl_set_std;
extern GTY(()) tree gfor_fndecl_ttynam;
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 10468026939..5ed41bd66ff 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -127,6 +127,9 @@ static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
/* Flag set by cppspec.c to 1. */
int is_cpp_driver;
+/* Flag set to non-zero if an @file argument has been supplied to gcc. */
+static bool at_file_supplied;
+
/* Flag saying to pass the greatest exit code returned by a sub-process
to the calling program. */
static int pass_exit_codes;
@@ -5009,9 +5012,63 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
int max = n_infiles;
max += lang_specific_extra_outfiles;
- for (i = 0; i < max; i++)
- if (outfiles[i])
- store_arg (outfiles[i], 0, 0);
+ if (HAVE_GNU_LD && at_file_supplied)
+ {
+ /* We are going to expand `%o' to `@FILE', where FILE
+ is a newly-created temporary filename. The filenames
+ that would usually be expanded in place of %o will be
+ written to the temporary file. */
+
+ char *temp_file = make_temp_file ("");
+ char *at_argument;
+ char **argv;
+ int n_files, j, status;
+ FILE *f;
+
+ at_argument = concat ("@", temp_file, NULL);
+ store_arg (at_argument, 0, 0);
+
+ /* Convert OUTFILES into a form suitable for writeargv. */
+
+ /* Determine how many are non-NULL. */
+ for (n_files = 0, i = 0; i < max; i++)
+ n_files += outfiles[i] != NULL;
+
+ argv = alloca (sizeof (char *) * (n_files + 1));
+
+ /* Copy the strings over. */
+ for (i = 0, j = 0; i < max; i++)
+ if (outfiles[i])
+ {
+ argv[j] = (char *) outfiles[i];
+ j++;
+ }
+ argv[j] = NULL;
+
+ f = fopen (temp_file, "w");
+
+ if (f == NULL)
+ fatal ("could not open temporary response file %s",
+ temp_file);
+
+ status = writeargv (argv, f);
+
+ if (status)
+ fatal ("could not write to temporary response file %s",
+ temp_file);
+
+ status = fclose (f);
+
+ if (EOF == status)
+ fatal ("could not close temporary response file %s",
+ temp_file);
+
+ record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
+ }
+ else
+ for (i = 0; i < max; i++)
+ if (outfiles[i])
+ store_arg (outfiles[i], 0, 0);
break;
}
@@ -6093,6 +6150,7 @@ main (int argc, char **argv)
char *specs_file;
const char *p;
struct user_specs *uptr;
+ char **old_argv = argv;
p = argv[0] + strlen (argv[0]);
while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
@@ -6103,6 +6161,10 @@ main (int argc, char **argv)
expandargv (&argc, &argv);
+ /* Determine if any expansions were made. */
+ if (argv != old_argv)
+ at_file_supplied = true;
+
prune_options (&argc, &argv);
#ifdef GCC_DRIVER_HOST_INITIALIZATION
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 992981aa8c0..a137750f948 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -87,6 +87,8 @@ static const char * const optabs[] =
"usmul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(usmul$a$b3$)$N",
"smadd_widen_optab->handlers[$B].insn_code = CODE_FOR_$(madd$a$b4$)$N",
"umadd_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umadd$a$b4$)$N",
+ "smsub_widen_optab->handlers[$B].insn_code = CODE_FOR_$(msub$a$b4$)$N",
+ "umsub_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umsub$a$b4$)$N",
"sdiv_optab->handlers[$A].insn_code = CODE_FOR_$(div$a3$)",
"sdivv_optab->handlers[$A].insn_code = CODE_FOR_$(div$V$I$a3$)",
"udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)",
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 9f1b71bc47b..326d0f3e852 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -5895,6 +5895,8 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
/* Convert (void *)&a + 4 into (void *)&a[1]. */
if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == NOP_EXPR
&& TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
+ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p,
+ 0),0)))
&& (tmp = maybe_fold_offset_to_reference
(TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0),
TREE_OPERAND (*expr_p, 1),
diff --git a/gcc/ipa-type-escape.c b/gcc/ipa-type-escape.c
index 921284db667..1619c5e47c0 100644
--- a/gcc/ipa-type-escape.c
+++ b/gcc/ipa-type-escape.c
@@ -196,8 +196,9 @@ compare_type_brand (splay_tree_key sk1, splay_tree_key sk2)
/* This is a trivial algorithm for removing duplicate types. This
would not work for any language that used structural equivalence as
the basis of its type system. */
-/* Return either TYPE if this is first time TYPE has been seen an
- compatible TYPE that has already been processed. */
+/* Return TYPE if no type compatible with TYPE has been seen so far,
+ otherwise return a type compatible with TYPE that has already been
+ processed. */
static tree
discover_unique_type (tree type)
@@ -1662,7 +1663,7 @@ ipa_init (void)
/* Check out the rhs of a static or global initialization VNODE to see
if any of them contain addressof operations. Note that some of
- these variables may not even be referenced in the code in this
+ these variables may not even be referenced in the code in this
compilation unit but their right hand sides may contain references
to variables defined within this unit. */
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 55e5a7b5ced..5ec2fbee8d2 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -5443,6 +5443,8 @@ init_optabs (void)
usmul_widen_optab = init_optab (UNKNOWN);
smadd_widen_optab = init_optab (UNKNOWN);
umadd_widen_optab = init_optab (UNKNOWN);
+ smsub_widen_optab = init_optab (UNKNOWN);
+ umsub_widen_optab = init_optab (UNKNOWN);
sdiv_optab = init_optab (DIV);
sdivv_optab = init_optabv (DIV);
sdivmod_optab = init_optab (UNKNOWN);
diff --git a/gcc/optabs.h b/gcc/optabs.h
index e5bbef89e4c..60dcc159729 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -92,6 +92,12 @@ enum optab_index
/* Unigned multiply and add with the result and addend one machine mode
wider than the multiplicand and multiplier. */
OTI_umadd_widen,
+ /* Signed multiply and subtract the result and minuend one machine mode
+ wider than the multiplicand and multiplier. */
+ OTI_smsub_widen,
+ /* Unigned multiply and subtract the result and minuend one machine mode
+ wider than the multiplicand and multiplier. */
+ OTI_umsub_widen,
/* Signed divide */
OTI_sdiv,
@@ -317,6 +323,8 @@ extern GTY(()) optab optab_table[OTI_MAX];
#define usmul_widen_optab (optab_table[OTI_usmul_widen])
#define smadd_widen_optab (optab_table[OTI_smadd_widen])
#define umadd_widen_optab (optab_table[OTI_umadd_widen])
+#define smsub_widen_optab (optab_table[OTI_smsub_widen])
+#define umsub_widen_optab (optab_table[OTI_umsub_widen])
#define sdiv_optab (optab_table[OTI_sdiv])
#define smulv_optab (optab_table[OTI_smulv])
#define sdivv_optab (optab_table[OTI_sdivv])
diff --git a/gcc/reload.c b/gcc/reload.c
index 8ed2f4b3880..bf220ef6bc0 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -1180,7 +1180,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
/* If IN appears in OUT, we can't share any input-only reload for IN. */
if (in != 0 && out != 0 && MEM_P (out)
- && (REG_P (in) || MEM_P (in))
+ && (REG_P (in) || MEM_P (in) || GET_CODE (in) == PLUS)
&& reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0)))
dont_share = 1;
@@ -6516,7 +6516,8 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
if (REG_P (in))
return 0;
else if (GET_CODE (in) == PLUS)
- return (reg_overlap_mentioned_for_reload_p (x, XEXP (in, 0))
+ return (rtx_equal_p (x, in)
+ || reg_overlap_mentioned_for_reload_p (x, XEXP (in, 0))
|| reg_overlap_mentioned_for_reload_p (x, XEXP (in, 1)));
else return (reg_overlap_mentioned_for_reload_p (XEXP (x, 0), in)
|| reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2b74f7cc8f8..c0e3d1e2327 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,10 +1,114 @@
+2007-05-10 Zdenek Dvorak <dvorakz@suse.cz>
+
+ PR tree-optimization/31885
+ * gcc.dg/tree-ssa/loop-29.c: New test.
+
+2007-05-10 Dominique d'Humières <dominiq@lps.ens.fr>
+
+ * assumed_dummy_1.f90: Fix dg directive.
+ * char_initialiser_actual.f90: Likewise.
+ * nested_modules_2.f90: Likewise.
+ * shift-alloc.f90: Likewise.
+
+2007-05-10 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * gcc.dg/20070507-1.c: Disable for non-pic targets.
+
+2007-05-09 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/31880
+ * gfortran.dg/unf_read_corrupted_2.f90: New test.
+
+2007-05-09 Mike Stump <mrs@apple.com>
+
+ * g++.dg/other/first-global.C: Add -fpie for darwin.
+ * g++.dg/parse/attr-externally-visible-1.C: Likewise.
+
+2007-05-09 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * gcc.dg/20070507-1.c: New testcase.
+
+2007-05-08 Chao-ying Fu <fu@mips.com>
+
+ * gcc.target/mips/msub-1.c, gcc.target/mips/msub-2.c,
+ * gcc.target/mips/msub-3.c, gcc.target/mips/msub-4.c,
+ * gcc.target/mips/msubu-1.c, gcc.target/mips/msubu-2.c,
+ * gcc.target/mips/msubu-3.c, gcc.target/mips/msubu-4.c: New tests.
+
+2007-05-08 Simon Martin <simartin@users.sourceforge.net>
+
+ PR 31847
+ * gcc.dg/pr31847.c: New test.
+
+2007-05-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/31692
+ * gfortran.dg/actual_array_result_1.f90: New test.
+
+2007-05-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/29397
+ * gfortran.dg/parameter_array_init_1.f90: New test.
+
+ PR fortran/29400
+ * gfortran.dg/parameter_array_init_2.f90: New test.
+
+2007-05-08 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/31854
+ * gcc.target/i386/pr31854.c: New test.
+
+2007-05-07 Janis Johnson <janis187@us.ibm.com>
+
+ * gcc.dg/pch/pch.exp: XFAIL largefile on Solaris 10 x86.
+
+2007-05-07 Mike Stump <mrs@apple.com>
+
+ * g++.old-deja/g++.mike/empty.C: Add.
+
+2007-05-07 Eric Christopher <echristo@apple.com>
+
+ * gcc.dg/invalid-call-1.c: Fix options for 32-bit x86.
+
+2007-05-07 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/dfp/convert-bfp-fold.c: Remove extra assignment to 'sf'
+ variable. Rearrange conversions from binary float to decimal float.
+
+2007-05-07 Mark Mitchell <mark@codesourcery.com>
+
+ * gcc.dg/special/gcsec-1.c: Don't link statically on Solaris 10
+ x86.
+
+2007-05-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt1.ad[sb]: New testcase.
+
+2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/31399
+ * gfortran.dg/do_3.F90: New test.
+
+2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/31764
+ * gfortran.dg/new_line.f90: Add new checks.
+
+2007-05-06 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/31201
+ * gfortran.dg/large_unit_1.f90: New.
+ * gfortran.dg/large_unit_2.f90: New.
+ * gfortran.dg/iostat_4.f90: New
+ * gfortran.dg/bounds_check_fail_1.f90: Updated.
+
2007-05-06 Paul Thomas <pault@gcc.gnu.org>
PR fortran/31540
* gfortran.dg/char_result_4.f90: New test.
2007-06-05 Revital Eres <eres@il.ibm.com>
-
+
PR 30957
* gcc.dg/pr30957-1.c: New test.
@@ -32,9 +136,9 @@
* gfortran.dg/fseek.f90: New test.
2007-05-04 Bob Wilson <bob.wilson@acm.org>
-
+
* g++.old-deja/g++.pt/static11.C: Remove xtensa-*-elf* xfail.
-
+
2007-05-04 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR libfortran/31210
@@ -67,7 +171,7 @@
2007-05-03 Dorit Nuzman <dorit@il.ibm.com>
PR tree-optimization/31699
- * lib/target-supports.exp (check_effective_target_vect_intfloat_cvt):
+ * lib/target-supports.exp (check_effective_target_vect_intfloat_cvt):
New.
(check_effective_target_vect_floatint_cvt): New.
* gcc.dg/vect/vect-floatint-conversion-1.c: Use new keyword instead
@@ -86,8 +190,8 @@
2007-05-02 Seongbae Park <seongbae.park@gmail.com>
PR C++/31663
- * g++.dg/warn/anonymous-namespace-2.C: New.
- * g++.dg/warn/anonymous-namespace-2.h: New.
+ * g++.dg/warn/anonymous-namespace-2.C: New.
+ * g++.dg/warn/anonymous-namespace-2.h: New.
2007-05-02 Paul Brook <paul@codesourcery.com>
diff --git a/gcc/testsuite/g++.dg/abi/forced.C b/gcc/testsuite/g++.dg/abi/forced.C
new file mode 100644
index 00000000000..7a9c35964f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/forced.C
@@ -0,0 +1,25 @@
+// This test only applies to glibc (NPTL) targets.
+// { dg-do run { target *-*-linux* } }
+// { dg-options "-pthread" }
+
+#include <pthread.h>
+#include <cxxabi.h>
+extern "C" int printf (const char *, ...);
+
+int main()
+{
+ try
+ {
+ pthread_exit (0);
+ }
+ catch (abi::__forced_unwind &)
+ {
+ printf ("caught forced unwind\n");
+ throw;
+ }
+ catch (...)
+ {
+ printf ("caught ...\n");
+ return 1;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/other/first-global.C b/gcc/testsuite/g++.dg/other/first-global.C
index b50f3266b5d..81e7a96e2e0 100644
--- a/gcc/testsuite/g++.dg/other/first-global.C
+++ b/gcc/testsuite/g++.dg/other/first-global.C
@@ -1,4 +1,6 @@
/* { dg-do compile } */
+/* { dg-options "-fpie" { target *-*-darwin* } } */
/* { dg-final { scan-assembler "_GLOBAL__I_foobar" } } */
+
struct foo { foo (); };
foo foobar;
diff --git a/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C b/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C
index 9016bc4225a..98fec2b4a98 100644
--- a/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C
+++ b/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C
@@ -1,5 +1,6 @@
// { dg-do compile }
// { dg-options "-O3 -fwhole-program" }
+/* { dg-options "-O3 -fwhole-program -fpie" { target *-*-darwin* } } */
// { dg-final { scan-assembler "foo1" } }
// { dg-final { scan-assembler "foo2" } }
// { dg-final { scan-assembler "foo3" } }
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/empty.C b/gcc/testsuite/g++.old-deja/g++.mike/empty.C
new file mode 100644
index 00000000000..d69f3ad6243
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.mike/empty.C
@@ -0,0 +1,25 @@
+// { dg-options "-W" }
+
+#define NOPE
+
+void foo() {
+ while (1); /* { dg-error "suggest a space before " } */
+ {
+ }
+ for (;;); /* { dg-error "suggest a space before " } */
+ {
+ }
+ while (1)
+ ;
+ for (;;)
+ ;
+ while (1) ;
+ for (;;) ;
+ /* These two work when using mapped locations */
+ while (1) NOPE; /* { dg-bogus "suggest a space before " "suggest" { xfail *-*-* } } */
+ for (;;) NOPE; /* { dg-bogus "suggest a space before " "suggest" { xfail *-*-* } } */
+ while (1)
+ NOPE;
+ for (;;)
+ NOPE;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/inline8.C b/gcc/testsuite/g++.old-deja/g++.other/inline8.C
index b919ab5df3f..a46dc382a7d 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/inline8.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/inline8.C
@@ -4,6 +4,7 @@
#include <map>
#include <cstdlib>
+#include <cstring>
using namespace std;
diff --git a/gcc/testsuite/gcc.dg/20070507-1.c b/gcc/testsuite/gcc.dg/20070507-1.c
new file mode 100644
index 00000000000..2884d1aa8d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20070507-1.c
@@ -0,0 +1,103 @@
+/* This failed on s390x due to bug in loop.c.
+ loop.c failed to remove a REG_EQUAL note when
+ hoisting an insn from a loop body. */
+
+/* { dg-options "-O3 -fPIC" } */
+/* { dg-do run { target fpic } } */
+
+typedef __SIZE_TYPE__ size_t;
+int memcmp(const void *s1, const void *s2, size_t n);
+
+typedef struct
+{
+ char name[30];
+ int a;
+} LOCAL;
+
+int global = 0;
+int sy = 1;
+int subroutine_offset;
+
+LOCAL local = { "local", 0 };
+LOCAL keywords = { "keywords", 1 };
+int local_table = 0;
+int keywords_table = 0;
+
+void __attribute__((noinline)) bar (char *p_buffer)
+{
+ p_buffer[255] = 1;
+}
+
+int __attribute__((noinline)) foo (char *p_str1)
+{
+ global = 1;
+ return 1;
+}
+
+int __attribute__((noinline)) loop_next (int *p_table, char *p_table_head)
+{
+ static loop_next = 0;
+
+ if (loop_next == 1)
+ return 1;
+
+ loop_next = 1;
+ return 0;
+}
+
+int
+main ()
+{
+ char buffer[256];
+ int ende = 0;
+ int index;
+ int local_base = 2;
+
+ keywords.a = 1;
+ for (sy = 0;; sy++)
+ {
+ for (index = 1;;)
+ {
+ bar (buffer);
+ if (buffer[sy] != 0)
+ {
+ ende = 1;
+ break;
+ };
+ if (foo (buffer))
+ {
+ keywords.a += index - 1;
+ break;
+ }
+ index++;
+ }
+ if (ende)
+ break;
+ }
+
+ subroutine_offset = 0;
+
+ for (;;)
+ {
+ if (loop_next (&keywords_table, (char*)&keywords))
+ break;
+
+ if ((!memcmp (keywords.name, "+++", 3)))
+ local_base = 100;
+ else
+ local_base = 0;
+
+ if ((!memcmp (keywords.name, "+++", 3)))
+ subroutine_offset += local_table;
+
+ for (;;)
+ {
+ if (loop_next (&local_table, (char*)&local))
+ break;;
+ if ((local.a == 0))
+ continue;;
+ foo (local.name);
+ }
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/convert-bfp-fold.c b/gcc/testsuite/gcc.dg/dfp/convert-bfp-fold.c
index 7724e1d2c82..c5504993480 100644
--- a/gcc/testsuite/gcc.dg/dfp/convert-bfp-fold.c
+++ b/gcc/testsuite/gcc.dg/dfp/convert-bfp-fold.c
@@ -62,43 +62,42 @@ main ()
/* Conversions from binary float to decimal float. */
sf = 30.0f;
- d32 = sf;
- if (d32 != 30.0df)
+ d128 = sf;
+ if (d128 != 30.0dl)
link_error ();
d64 = sf;
if (d64 != 30.0dd)
link_error ();
+ d32 = sf;
+ if (d32 != 30.0df)
+ link_error ();
+
df = -2.0;
- d32 = df;
- if (d32 != -2.0df)
+ d128 = df;
+ if (d128 != -2.0dl)
link_error ();
d64 = df;
if (d64 != -2.0dd)
link_error ();
- d128 = df;
- if (d128 != -2.0dl)
- link_error ();
-
- sf = 30.0f;
- d128 = sf;
- if (d128 != 30.0dl)
- link_error ();
+ d32 = df;
+ if (d32 != -2.0df)
+ link_error ();
tf = -22.0l;
- d32 = tf;
- if (d32 != -22.0df)
+ d128 = tf;
+ if (d128 != -22.0dl)
link_error ();
d64 = tf;
if (d64 != -22.0dd)
link_error ();
- d128 = tf;
- if (d128 != -22.0dl)
+ d32 = tf;
+ if (d32 != -22.0df)
link_error ();
/* 2**(-11) = 0.00048828125. */
diff --git a/gcc/testsuite/gcc.dg/invalid-call-1.c b/gcc/testsuite/gcc.dg/invalid-call-1.c
index 7474227fa52..4126b5a4ff0 100644
--- a/gcc/testsuite/gcc.dg/invalid-call-1.c
+++ b/gcc/testsuite/gcc.dg/invalid-call-1.c
@@ -3,7 +3,7 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
-/* { dg-options "-O2 -mtune=i586" { target i?86-*-* } } */
+/* { dg-options "-O2 -march=i586" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
typedef void (*fp)(void);
extern char* bar(void* a1, int a2);
diff --git a/gcc/testsuite/gcc.dg/pch/pch.exp b/gcc/testsuite/gcc.dg/pch/pch.exp
index 7e65e03e657..c2b309e194c 100644
--- a/gcc/testsuite/gcc.dg/pch/pch.exp
+++ b/gcc/testsuite/gcc.dg/pch/pch.exp
@@ -40,6 +40,7 @@ foreach test [lsort [glob -nocomplain $srcdir/$subdir/*.c]] {
set test "largefile.c"
set testh "largefile.hs"
set f [open $test w]
+puts $f "/* { dg-xfail-if \"PR 14940\" { \"i?86-*-solaris2.10\" } { \"*\" } { \"\" } } */"
set v 0
for { set v 0 } { $v < 10000 } { incr v } {
puts $f "#define MACRO_${v} \"1234567890\" \"$v\""
diff --git a/gcc/testsuite/gcc.dg/pr31847.c b/gcc/testsuite/gcc.dg/pr31847.c
new file mode 100644
index 00000000000..4b945a994aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr31847.c
@@ -0,0 +1,15 @@
+/* PR 31847 */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-all" } */
+
+extern int bar(int);
+
+int foo()
+{
+ int a = 0;
+ return bar(a);
+}
+
+/* { dg-final { scan-tree-dump-not "Created value for " "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/special/gcsec-1.c b/gcc/testsuite/gcc.dg/special/gcsec-1.c
index 68d4066fa39..b76ad50aa78 100644
--- a/gcc/testsuite/gcc.dg/special/gcsec-1.c
+++ b/gcc/testsuite/gcc.dg/special/gcsec-1.c
@@ -5,7 +5,8 @@
/* { dg-options "-ffunction-sections -fdata-sections -Wl,--gc-sections -static" } */
/* { dg-options "-ffunction-sections -fdata-sections -Wl,--gc-sections -static" { target native } } */
-/* { dg-options "-ffunction-sections -fdata-sections -Wl,--gc-sections" { target *-*-netware* } } */
+/* Solaris 10 does not support static linking; there is no libc.a. */
+/* { dg-options "-ffunction-sections -fdata-sections -Wl,--gc-sections" { target *-*-netware* i?86-*-solaris2.1[0-9] } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-29.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-29.c
new file mode 100644
index 00000000000..13699aafd62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-29.c
@@ -0,0 +1,21 @@
+/* PR 31885 */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-empty" } */
+
+struct s {
+ int *blah;
+};
+
+static struct s array[] = { { 0 } };
+
+void
+foo (struct s *p)
+{
+ struct s *q = &array[1];
+ while (p < q)
+ p++;
+}
+
+/* { dg-final { scan-tree-dump-times "Removing empty loop" 1 "empty" } } */
+/* { dg-final { cleanup-tree-dump "empty" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr31854.c b/gcc/testsuite/gcc.target/i386/pr31854.c
new file mode 100644
index 00000000000..d5dca57ea63
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr31854.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target dfp } } */
+/* { dg-options "-O -std=gnu99" } */
+
+_Decimal128 d128;
+long double tf;
+
+void foo (void)
+{
+ d128 = tf;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msub-1.c b/gcc/testsuite/gcc.target/mips/msub-1.c
new file mode 100644
index 00000000000..d27e6479ef5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/msub-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=vr5400 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmsac\t\\\$0," 2 } } */
+
+long long
+f1 (int x, int y, long long z)
+{
+ return z - (long long) y * x;
+}
+
+long long
+f2 (int x, int y, long long z)
+{
+ long long t = (long long) x * y;
+ int temp = 5;
+ if (temp == 5)
+ z -= t;
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msub-2.c b/gcc/testsuite/gcc.target/mips/msub-2.c
new file mode 100644
index 00000000000..acb7efb2b43
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/msub-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=vr5500 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmsub\t" 2 } } */
+
+long long
+f1 (int x, int y, long long z)
+{
+ return z - (long long) y * x;
+}
+
+long long
+f2 (int x, int y, long long z)
+{
+ long long t = (long long) x * y;
+ int temp = 5;
+ if (temp == 5)
+ z -= t;
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msub-3.c b/gcc/testsuite/gcc.target/mips/msub-3.c
new file mode 100644
index 00000000000..85cfed2febe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/msub-3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmsub\t" 2 } } */
+
+long long
+f1 (int x, int y, long long z)
+{
+ return z - (long long) y * x;
+}
+
+long long
+f2 (int x, int y, long long z)
+{
+ long long t = (long long) x * y;
+ int temp = 5;
+ if (temp == 5)
+ z -= t;
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msub-4.c b/gcc/testsuite/gcc.target/mips/msub-4.c
new file mode 100644
index 00000000000..8a526f8f583
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/msub-4.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32r2 -mdspr2 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmsub\t\\\$ac" 2 } } */
+
+long long
+f1 (int x, int y, long long z)
+{
+ return z - (long long) y * x;
+}
+
+long long
+f2 (int x, int y, long long z)
+{
+ long long t = (long long) x * y;
+ int temp = 5;
+ if (temp == 5)
+ z -= t;
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msubu-1.c b/gcc/testsuite/gcc.target/mips/msubu-1.c
new file mode 100644
index 00000000000..9390c473f53
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/msubu-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=vr5400 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmsacu\t\\\$0," 2 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+ return z - (ull) y * x;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+ ull t = (ull) x * y;
+ int temp = 5;
+ if (temp == 5)
+ z -= t;
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msubu-2.c b/gcc/testsuite/gcc.target/mips/msubu-2.c
new file mode 100644
index 00000000000..75fb404eb97
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/msubu-2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=vr5500 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmsubu\t" 2 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+ return z - (ull) y * x;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+ ull t = (ull) x * y;
+ int temp = 5;
+ if (temp == 5)
+ z -= t;
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msubu-3.c b/gcc/testsuite/gcc.target/mips/msubu-3.c
new file mode 100644
index 00000000000..055ba589a95
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/msubu-3.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmsubu\t" 2 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+ return z - (ull) y * x;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+ ull t = (ull) x * y;
+ int temp = 5;
+ if (temp == 5)
+ z -= t;
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msubu-4.c b/gcc/testsuite/gcc.target/mips/msubu-4.c
new file mode 100644
index 00000000000..ea4adb1b080
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/msubu-4.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32r2 -mdspr2 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmsubu\t\\\$ac" 2 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+ return z - (ull) y * x;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+ ull t = (ull) x * y;
+ int temp = 5;
+ if (temp == 5)
+ z -= t;
+ return z;
+}
diff --git a/gcc/testsuite/gfortran.dg/actual_array_result_1.f90 b/gcc/testsuite/gfortran.dg/actual_array_result_1.f90
new file mode 100644
index 00000000000..cf79315cbb7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/actual_array_result_1.f90
@@ -0,0 +1,71 @@
+! { dg-do run }
+! PR fortan/31692
+! Passing array valued results to procedures
+!
+! Test case contributed by rakuen_himawari@yahoo.co.jp
+module one
+ integer :: flag = 0
+contains
+ function foo1 (n)
+ integer :: n
+ integer :: foo1(n)
+ if (flag == 0) then
+ call bar1 (n, foo1)
+ else
+ call bar2 (n, foo1)
+ end if
+ end function
+
+ function foo2 (n)
+ implicit none
+ integer :: n
+ integer,ALLOCATABLE :: foo2(:)
+ allocate (foo2(n))
+ if (flag == 0) then
+ call bar1 (n, foo2)
+ else
+ call bar2 (n, foo2)
+ end if
+ end function
+
+ function foo3 (n)
+ implicit none
+ integer :: n
+ integer,ALLOCATABLE :: foo3(:)
+ allocate (foo3(n))
+ foo3 = 0
+ call bar2(n, foo3(2:(n-1))) ! Check that sections are OK
+ end function
+
+ subroutine bar1 (n, array) ! Checks assumed size formal arg.
+ integer :: n
+ integer :: array(*)
+ integer :: i
+ do i = 1, n
+ array(i) = i
+ enddo
+ end subroutine
+
+ subroutine bar2(n, array) ! Checks assumed shape formal arg.
+ integer :: n
+ integer :: array(:)
+ integer :: i
+ do i = 1, size (array, 1)
+ array(i) = i
+ enddo
+ end subroutine
+end module
+
+program main
+ use one
+ integer :: n
+ n = 3
+ if(any (foo1(n) /= [ 1,2,3 ])) call abort()
+ if(any (foo2(n) /= [ 1,2,3 ])) call abort()
+ flag = 1
+ if(any (foo1(n) /= [ 1,2,3 ])) call abort()
+ if(any (foo2(n) /= [ 1,2,3 ])) call abort()
+ n = 5
+ if(any (foo3(n) /= [ 0,1,2,3,0 ])) call abort()
+end program
+! { dg-final { cleanup-modules "one" } }
diff --git a/gcc/testsuite/gfortran.dg/assumed_dummy_1.f90 b/gcc/testsuite/gfortran.dg/assumed_dummy_1.f90
index 97c163e8c6b..f0cf7750332 100644
--- a/gcc/testsuite/gfortran.dg/assumed_dummy_1.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_dummy_1.f90
@@ -1,4 +1,4 @@
-! { dg do-run}
+! { dg-do run}
! Tests the fix for PRs 19358, 19477, 21211 and 21622.
!
! Note that this tests only the valid cases with explicit interfaces.
diff --git a/gcc/testsuite/gfortran.dg/bounds_check_fail_1.f90 b/gcc/testsuite/gfortran.dg/bounds_check_fail_1.f90
index 938d19a6409..8617456f1e0 100644
--- a/gcc/testsuite/gfortran.dg/bounds_check_fail_1.f90
+++ b/gcc/testsuite/gfortran.dg/bounds_check_fail_1.f90
@@ -4,4 +4,4 @@
integer x(1)
x(2) = x(1) ! { dg-warning "out of bounds" }
end
-! { dg-output "out of bounds for array 'x', upper bound of dimension 1 exceeded.*at line 5" }
+! { dg-output "out of bounds for array 'x', upper bound of dimension 1 exceeded." }
diff --git a/gcc/testsuite/gfortran.dg/char_initialiser_actual.f90 b/gcc/testsuite/gfortran.dg/char_initialiser_actual.f90
index 3796f7ee21c..7975a7e424b 100644
--- a/gcc/testsuite/gfortran.dg/char_initialiser_actual.f90
+++ b/gcc/testsuite/gfortran.dg/char_initialiser_actual.f90
@@ -1,4 +1,4 @@
-! { dg do-run }
+! { dg-do run }
! Tests passing of character array initialiser as actual argument.
! Fixes PR18109.
! Contributed by Paul Thomas pault@gcc.gnu.org
diff --git a/gcc/testsuite/gfortran.dg/do_3.F90 b/gcc/testsuite/gfortran.dg/do_3.F90
new file mode 100644
index 00000000000..1e2e238bf7e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/do_3.F90
@@ -0,0 +1,110 @@
+! { dg-do run }
+! { dg-options "-std=legacy -ffree-line-length-none" }
+program test
+ integer :: count
+ integer :: i
+ integer(kind=1) :: i1
+ real :: r
+
+#define TEST_LOOP(var,from,to,step,total,test) \
+ count = 0 ; do var = from, to, step ; count = count + 1 ; end do ; \
+ if (count /= total) call abort ; \
+ if (test (from, to, step) /= total) call abort
+
+ ! Integer loops
+ TEST_LOOP(i, 0, 0, 1, 1, test_i)
+ TEST_LOOP(i, 0, 0, 2, 1, test_i)
+ TEST_LOOP(i, 0, 0, -1, 1, test_i)
+ TEST_LOOP(i, 0, 0, -2, 1, test_i)
+
+ TEST_LOOP(i, 0, 1, 1, 2, test_i)
+ TEST_LOOP(i, 0, 1, 2, 1, test_i)
+ TEST_LOOP(i, 0, 1, 3, 1, test_i)
+ TEST_LOOP(i, 0, 1, huge(0), 1, test_i)
+ TEST_LOOP(i, 0, 1, -1, 0, test_i)
+ TEST_LOOP(i, 0, 1, -2, 0, test_i)
+ TEST_LOOP(i, 0, 1, -3, 0, test_i)
+ TEST_LOOP(i, 0, 1, -huge(0), 0, test_i)
+ TEST_LOOP(i, 0, 1, -huge(0)-1, 0, test_i)
+
+ TEST_LOOP(i, 1, 0, 1, 0, test_i)
+ TEST_LOOP(i, 1, 0, 2, 0, test_i)
+ TEST_LOOP(i, 1, 0, 3, 0, test_i)
+ TEST_LOOP(i, 1, 0, huge(0), 0, test_i)
+ TEST_LOOP(i, 1, 0, -1, 2, test_i)
+ TEST_LOOP(i, 1, 0, -2, 1, test_i)
+ TEST_LOOP(i, 1, 0, -3, 1, test_i)
+ TEST_LOOP(i, 1, 0, -huge(0), 1, test_i)
+ TEST_LOOP(i, 1, 0, -huge(0)-1, 1, test_i)
+
+ TEST_LOOP(i, 0, 17, 1, 18, test_i)
+ TEST_LOOP(i, 0, 17, 2, 9, test_i)
+ TEST_LOOP(i, 0, 17, 3, 6, test_i)
+ TEST_LOOP(i, 0, 17, 4, 5, test_i)
+ TEST_LOOP(i, 0, 17, 5, 4, test_i)
+ TEST_LOOP(i, 17, 0, -1, 18, test_i)
+ TEST_LOOP(i, 17, 0, -2, 9, test_i)
+ TEST_LOOP(i, 17, 0, -3, 6, test_i)
+ TEST_LOOP(i, 17, 0, -4, 5, test_i)
+ TEST_LOOP(i, 17, 0, -5, 4, test_i)
+
+ TEST_LOOP(i1, -huge(i1)-1_1, huge(i1), 1_1, int(huge(i1))*2+2, test_i1)
+ TEST_LOOP(i1, -huge(i1)-1_1, huge(i1), 2_1, int(huge(i1))+1, test_i1)
+ TEST_LOOP(i1, -huge(i1)-1_1, huge(i1), huge(i1), 3, test_i1)
+
+ TEST_LOOP(i1, huge(i1), -huge(i1)-1_1, -1_1, int(huge(i1))*2+2, test_i1)
+ TEST_LOOP(i1, huge(i1), -huge(i1)-1_1, -2_1, int(huge(i1))+1, test_i1)
+ TEST_LOOP(i1, huge(i1), -huge(i1)-1_1, -huge(i1), 3, test_i1)
+ TEST_LOOP(i1, huge(i1), -huge(i1)-1_1, -huge(i1)-1_1, 2, test_i1)
+
+ TEST_LOOP(i1, -2_1, 3_1, huge(i1), 1, test_i1)
+ TEST_LOOP(i1, -2_1, 3_1, -huge(i1), 0, test_i1)
+ TEST_LOOP(i1, 2_1, -3_1, -huge(i1), 1, test_i1)
+ TEST_LOOP(i1, 2_1, -3_1, huge(i1), 0, test_i1)
+
+ ! Real loops
+ TEST_LOOP(r, 0.0, 1.0, 0.11, 1 + int(1.0/0.11), test_r)
+ TEST_LOOP(r, 0.0, 1.0, -0.11, 0, test_r)
+ TEST_LOOP(r, 0.0, -1.0, 0.11, 0, test_r)
+ TEST_LOOP(r, 0.0, -1.0, -0.11, 1 + int(1.0/0.11), test_r)
+ TEST_LOOP(r, 0.0, 0.0, 0.11, 1, test_r)
+ TEST_LOOP(r, 0.0, 0.0, -0.11, 1, test_r)
+
+#undef TEST_LOOP
+
+contains
+
+ function test_i1 (from, to, step) result(res)
+ integer(kind=1), intent(in) :: from, to, step
+ integer(kind=1) :: i
+ integer :: res
+
+ res = 0
+ do i = from, to, step
+ res = res + 1
+ end do
+ end function test_i1
+
+ function test_i (from, to, step) result(res)
+ integer, intent(in) :: from, to, step
+ integer :: i
+ integer :: res
+
+ res = 0
+ do i = from, to, step
+ res = res + 1
+ end do
+ end function test_i
+
+ function test_r (from, to, step) result(res)
+ real, intent(in) :: from, to, step
+ real :: i
+ integer :: res
+
+ res = 0
+ do i = from, to, step
+ res = res + 1
+ end do
+ end function test_r
+
+end program test
diff --git a/gcc/testsuite/gfortran.dg/iostat_4.f90 b/gcc/testsuite/gfortran.dg/iostat_4.f90
new file mode 100644
index 00000000000..34c25f962d4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/iostat_4.f90
@@ -0,0 +1,9 @@
+! { dg-do run }
+! PR31201 Too large unit number generates wrong code
+! This tests initialization of the IOSTAT variable
+ integer :: i
+ character(len=50) :: str
+ write (2_8*int(huge(0_4),kind=8)+9_8, iostat=i, iomsg=str) 555
+ if (i.ne.5005) call abort
+ if (str.ne."Unit number in I/O statement too large") call abort
+ end \ No newline at end of file
diff --git a/gcc/testsuite/gfortran.dg/large_unit_1.f90 b/gcc/testsuite/gfortran.dg/large_unit_1.f90
new file mode 100644
index 00000000000..60e2d1f17e8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/large_unit_1.f90
@@ -0,0 +1,17 @@
+! { dg-do run }
+! { dg-shouldfail "Unit number in I/O statement too large" }
+! PR31201 Unit number in I/O statement too large
+! Test case from PR
+ integer(kind=8) :: k= 2_8**36 + 10
+ integer(kind=4) :: j= 10
+ logical ex,op
+ INQUIRE(unit=k, exist=ex,opened=op)
+ print *, ex, op
+ IF (ex) THEN
+ OPEN(unit=k)
+ INQUIRE(unit=j, opened=op)
+ IF (op) CALL ABORT()
+ ENDIF
+ print *, k
+ close(k)
+ end
diff --git a/gcc/testsuite/gfortran.dg/large_unit_2.f90 b/gcc/testsuite/gfortran.dg/large_unit_2.f90
new file mode 100644
index 00000000000..5f3554cc5bb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/large_unit_2.f90
@@ -0,0 +1,13 @@
+! { dg-do run }
+! PR31201 Too large unit number generates wrong code
+! Test case by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+ integer :: i
+ logical :: l
+ character(len=60) :: s
+ open(2_8*huge(0)+20_8,file="foo",iostat=i)
+ if (i == 0) call abort
+ open(2_8*huge(0)+20_8,file="foo",err=99)
+ call abort
+ 99 inquire(unit=18,opened=l)
+ if (l) call abort
+ end
diff --git a/gcc/testsuite/gfortran.dg/nested_modules_2.f90 b/gcc/testsuite/gfortran.dg/nested_modules_2.f90
index 3d0985a7eac..5bfdaddaac2 100644
--- a/gcc/testsuite/gfortran.dg/nested_modules_2.f90
+++ b/gcc/testsuite/gfortran.dg/nested_modules_2.f90
@@ -1,4 +1,4 @@
-! { dg do-run }
+! { dg-do run }
! This tests the patch for PR16861.
!
! Contributed by Paul Thomas <pault@gcc.gnu.org>
diff --git a/gcc/testsuite/gfortran.dg/new_line.f90 b/gcc/testsuite/gfortran.dg/new_line.f90
index 355ca30209b..aacabc69f6e 100644
--- a/gcc/testsuite/gfortran.dg/new_line.f90
+++ b/gcc/testsuite/gfortran.dg/new_line.f90
@@ -2,6 +2,19 @@
! Checks Fortran 2003's new_line intrinsic function
! PR fortran/28585
program new_line_check
- implicit none
- if(achar(10) /= new_line('a')) call abort()
+ implicit none
+ character(len=10) :: a1
+ character(len=10) :: a2(2)
+ character(len=10), parameter :: a3 = "1234567890"
+ character(len=10), parameter :: a4(2) = "1234567890"
+ character(len=10), parameter :: a5(2) = repeat("1234567890",2)
+
+ if(achar(10) /= new_line('a')) call abort
+
+ if (iachar(new_line(a1)) /= 10) call abort
+ if (iachar(new_line(a2)) /= 10) call abort
+ if (iachar(new_line(a3)) /= 10) call abort
+ if (iachar(new_line(a4)) /= 10) call abort
+ if (iachar(new_line(a5)) /= 10) call abort
+
end program new_line_check
diff --git a/gcc/testsuite/gfortran.dg/parameter_array_init_1.f90 b/gcc/testsuite/gfortran.dg/parameter_array_init_1.f90
new file mode 100644
index 00000000000..bb029a5b080
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/parameter_array_init_1.f90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! tests the fix for PR29397, in which the initializer for the parameter
+! 'J' was not expanded into an array.
+!
+! Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+!
+ INTEGER :: K(3) = 1
+ INTEGER, PARAMETER :: J(3) = 2
+ IF (ANY (MAXLOC (K, J<3) .NE. 1)) CALL ABORT ()
+ IF (ANY (J .NE. 2)) CALL ABORT ()
+END
diff --git a/gcc/testsuite/gfortran.dg/parameter_array_init_2.f90 b/gcc/testsuite/gfortran.dg/parameter_array_init_2.f90
new file mode 100644
index 00000000000..bf238e5ee32
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/parameter_array_init_2.f90
@@ -0,0 +1,26 @@
+! { dg-do run }
+! { dg-options "-std=gnu" } ! suppress the warning about line 15
+! Thrashes the fix for PR29400, where the scalar initializers
+! were not expanded to arrays with the appropriate shape.
+!
+! Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+!
+ integer,parameter :: i(1,1) = 0, j(2) = 42
+
+ if (any (maxloc(j+j,mask=(j==2)) .ne. 0)) call abort ()
+ if (size(j+j) .ne. 2) call abort ()
+ if (minval(j+j) .ne. 84) call abort ()
+ if (minval(j,mask=(j==2)) .ne. huge (j)) call abort ()
+ if (maxval(j+j) .ne. 84) call abort ()
+ if (maxval(j,mask=(j==2)) .ne. -huge (j)-1) call abort ()
+ if (sum(j,mask=j==2) .ne. 0) call abort ()
+ if (sum(j+j) .ne. 168) call abort ()
+ if (product(j+j) .ne. 7056) call abort ()
+ if (any(ubound(j+j) .ne. 2)) call abort ()
+ if (any(lbound(j+j) .ne. 1)) call abort ()
+ if (dot_product(j+j,j) .ne. 7056) call abort ()
+ if (dot_product(j,j+j) .ne. 7056) call abort ()
+ if (count(i==1) .ne. 0) call abort ()
+ if (any(i==1)) call abort ()
+ if (all(i==1)) call abort ()
+ end
diff --git a/gcc/testsuite/gfortran.dg/shift-alloc.f90 b/gcc/testsuite/gfortran.dg/shift-alloc.f90
index 2d660317235..70f1cbb660e 100644
--- a/gcc/testsuite/gfortran.dg/shift-alloc.f90
+++ b/gcc/testsuite/gfortran.dg/shift-alloc.f90
@@ -1,4 +1,4 @@
-! { dg do-run }
+! { dg-do run }
! PR 22144: eoshift1, eoshift3 and cshift1 used to lack memory
! allocation, which caused the writes to segfault.
program main
diff --git a/gcc/testsuite/gfortran.dg/unf_read_corrupted_2.f90 b/gcc/testsuite/gfortran.dg/unf_read_corrupted_2.f90
new file mode 100644
index 00000000000..1788b457d19
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unf_read_corrupted_2.f90
@@ -0,0 +1,27 @@
+! { dg-do run }
+! PR31880 silent data corruption in gfortran read statement
+! Test from PR.
+ program r3
+
+ integer(kind=4) :: a(1025),b(1025),c(1025),d(2048),e(1022)
+
+ a = 5
+ b = 6
+ c = 7
+ e = 8
+
+ do i=1,2048
+ d(i)=i
+ end do
+
+ open (3,form='unformatted', status="scratch")
+ write (3) a,b,c,d,e
+ rewind 3
+ d = 0
+ read (3) a,b,c,d
+ close (3)
+
+ if (d(1).ne.1) call abort
+ if (d(2048).ne.2048) call abort
+
+ end
diff --git a/gcc/testsuite/gnat.dg/opt1.adb b/gcc/testsuite/gnat.dg/opt1.adb
new file mode 100644
index 00000000000..69bb8136d04
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt1.adb
@@ -0,0 +1,29 @@
+-- { dg-do compile }
+-- { dg-options "-O -gnatws" }
+
+package body Opt1 is
+
+ function De_Linear_Index
+ (Index : Natural;
+ D : Natural;
+ Ind_Lengths : Dimention_Length)
+ return Dimension_Indexes
+ is
+ Len : Natural := 1;
+ Tmp_Ind : Natural := Index;
+ Tmp_Res : Natural;
+ Result : Dimension_Indexes (1 .. D);
+ begin
+ for J in 1 .. D loop
+ Len := Len * Ind_Lengths (J);
+ end loop;
+
+ for J in Result'Range loop
+ Result (J) := Tmp_Res;
+ Tmp_Ind := Tmp_Ind - Len * (Result (J) - 1);
+ end loop;
+
+ return Result;
+ end;
+
+end Opt1;
diff --git a/gcc/testsuite/gnat.dg/opt1.ads b/gcc/testsuite/gnat.dg/opt1.ads
new file mode 100644
index 00000000000..247e7dc639c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt1.ads
@@ -0,0 +1,13 @@
+package Opt1 is
+
+ type Dimention_Length is array (1 .. 16) of Natural;
+
+ type Dimension_Indexes is array (Positive range <>) of Positive;
+
+ function De_Linear_Index
+ (Index : Natural;
+ D : Natural;
+ Ind_Lengths : Dimention_Length)
+ return Dimension_Indexes;
+
+end Opt1;
diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c
index b5c5a535589..03cd5f3eb8c 100644
--- a/gcc/tree-chrec.c
+++ b/gcc/tree-chrec.c
@@ -897,11 +897,12 @@ chrec_contains_undetermined (tree chrec)
{
int i, n;
- if (chrec == chrec_dont_know
- || chrec == chrec_not_analyzed_yet
- || chrec == NULL_TREE)
+ if (chrec == chrec_dont_know)
return true;
+ if (chrec == NULL_TREE)
+ return false;
+
n = TREE_OPERAND_LENGTH (chrec);
for (i = 0; i < n; i++)
if (chrec_contains_undetermined (TREE_OPERAND (chrec, i)))
diff --git a/gcc/tree-chrec.h b/gcc/tree-chrec.h
index 42bbb6c0440..70bb4c8ab89 100644
--- a/gcc/tree-chrec.h
+++ b/gcc/tree-chrec.h
@@ -36,8 +36,7 @@ extern GTY(()) tree chrec_known;
static inline bool
automatically_generated_chrec_p (tree chrec)
{
- return (chrec == chrec_not_analyzed_yet
- || chrec == chrec_dont_know
+ return (chrec == chrec_dont_know
|| chrec == chrec_known);
}
diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c
index ea8f378d2d1..16f71df2028 100644
--- a/gcc/tree-dump.c
+++ b/gcc/tree-dump.c
@@ -803,7 +803,7 @@ static const struct dump_option_value_info dump_options[] =
{"stmtaddr", TDF_STMTADDR},
{"memsyms", TDF_MEMSYMS},
{"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
- | TDF_STMTADDR | TDF_GRAPH)},
+ | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC)},
{NULL, 0}
};
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 832bd122626..cb74180c2da 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1863,7 +1863,8 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
return NULL_TREE;
base = TREE_OPERAND (base, 0);
- offset = int_const_binop (PLUS_EXPR, offset, offset2, 1);
+ offset = fold_convert (sizetype,
+ int_const_binop (PLUS_EXPR, offset, offset2, 1));
}
if (TREE_CODE (base) == ADDR_EXPR)
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 6e1387f7157..7a146157f99 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -275,6 +275,7 @@ tree_ssa_dominator_optimize (void)
init_walk_dominator_tree (&walk_data);
calculate_dominance_info (CDI_DOMINATORS);
+ cfg_altered = false;
/* We need to know which edges exit loops so that we can
aggressively thread through loop headers to an exit
@@ -320,17 +321,17 @@ tree_ssa_dominator_optimize (void)
/* Thread jumps, creating duplicate blocks as needed. */
cfg_altered |= thread_through_all_blocks ();
+ if (cfg_altered)
+ free_dominance_info (CDI_DOMINATORS);
+
/* Removal of statements may make some EH edges dead. Purge
such edges from the CFG as needed. */
if (!bitmap_empty_p (need_eh_cleanup))
{
- cfg_altered |= tree_purge_all_dead_eh_edges (need_eh_cleanup);
+ tree_purge_all_dead_eh_edges (need_eh_cleanup);
bitmap_zero (need_eh_cleanup);
}
- if (cfg_altered)
- free_dominance_info (CDI_DOMINATORS);
-
/* Finally, remove everything except invariants in SSA_NAME_VALUE.
Long term we will be able to let everything in SSA_NAME_VALUE
@@ -2336,7 +2337,7 @@ propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names)
te->count += e->count;
remove_edge (e);
- cfg_altered = 1;
+ cfg_altered = true;
}
else
ei_next (&ei);
@@ -2485,6 +2486,9 @@ eliminate_degenerate_phis (void)
interesting_names = BITMAP_ALLOC (NULL);
interesting_names1 = BITMAP_ALLOC (NULL);
+ calculate_dominance_info (CDI_DOMINATORS);
+ cfg_altered = false;
+
/* First phase. Eliminate degenerate PHIs via a dominator
walk of the CFG.
@@ -2493,7 +2497,6 @@ eliminate_degenerate_phis (void)
phase in dominator order. Presumably this is because walking
in dominator order leaves fewer PHIs for later examination
by the worklist phase. */
- calculate_dominance_info (CDI_DOMINATORS);
eliminate_degenerate_phis_1 (ENTRY_BLOCK_PTR, interesting_names);
/* Second phase. Eliminate second order degenerate PHIs as well
@@ -2522,18 +2525,19 @@ eliminate_degenerate_phis (void)
}
}
+ if (cfg_altered)
+ free_dominance_info (CDI_DOMINATORS);
+
/* Propagation of const and copies may make some EH edges dead. Purge
such edges from the CFG as needed. */
if (!bitmap_empty_p (need_eh_cleanup))
{
- cfg_altered |= tree_purge_all_dead_eh_edges (need_eh_cleanup);
+ tree_purge_all_dead_eh_edges (need_eh_cleanup);
BITMAP_FREE (need_eh_cleanup);
}
BITMAP_FREE (interesting_names);
BITMAP_FREE (interesting_names1);
- if (cfg_altered)
- free_dominance_info (CDI_DOMINATORS);
return 0;
}
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 239bbb32cd2..a8bdfebaecb 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -679,12 +679,15 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
mpz_t mmod;
tree assumption = boolean_true_node, bound, noloop;
bool ret = false;
+ tree type1 = type;
+ if (POINTER_TYPE_P (type))
+ type1 = sizetype;
if (TREE_CODE (mod) != INTEGER_CST)
return false;
if (integer_nonzerop (mod))
mod = fold_build2 (MINUS_EXPR, niter_type, step, mod);
- tmod = fold_convert (type, mod);
+ tmod = fold_convert (type1, mod);
mpz_init (mmod);
mpz_set_double_int (mmod, tree_to_double_int (mod), true);
@@ -698,7 +701,7 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
if (!iv1->no_overflow && !integer_zerop (mod))
{
bound = fold_build2 (MINUS_EXPR, type,
- TYPE_MAX_VALUE (type), tmod);
+ TYPE_MAX_VALUE (type1), tmod);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound);
if (integer_zerop (assumption))
@@ -709,7 +712,7 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
else
noloop = fold_build2 (GT_EXPR, boolean_type_node,
iv0->base,
- fold_build2 (PLUS_EXPR, type,
+ fold_build2 (PLUS_EXPR, type1,
iv1->base, tmod));
}
else
@@ -719,8 +722,8 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
iv0->base - MOD <= iv1->base. */
if (!iv0->no_overflow && !integer_zerop (mod))
{
- bound = fold_build2 (PLUS_EXPR, type,
- TYPE_MIN_VALUE (type), tmod);
+ bound = fold_build2 (PLUS_EXPR, type1,
+ TYPE_MIN_VALUE (type1), tmod);
assumption = fold_build2 (GE_EXPR, boolean_type_node,
iv0->base, bound);
if (integer_zerop (assumption))
@@ -730,7 +733,7 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
noloop = boolean_false_node;
else
noloop = fold_build2 (GT_EXPR, boolean_type_node,
- fold_build2 (MINUS_EXPR, type,
+ fold_build2 (MINUS_EXPR, type1,
iv0->base, tmod),
iv1->base);
}