This commit was generated by cvs2svn to compensate for changes in r104752,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
commit
0cd8fdc382
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=104753
@ -1,3 +1,335 @@
|
||||
2002-10-09 Zack Weinberg <zack@codesourcery.com>
|
||||
|
||||
PR c/7353
|
||||
* c-decl.c (start_decl): Unconditionally issue error for
|
||||
'typedef foo = bar'.
|
||||
(finish_decl): Remove special case for TYPE_DECL with initializer.
|
||||
|
||||
* doc/extend.texi: Delete "Naming Types" section. Change all
|
||||
cross-references to that section to refer to "Typeof" instead.
|
||||
Add the useful safe-max()-macro example from "Naming Types" to
|
||||
"Typeof", rewritten using that extension. Add some compatibility
|
||||
notes to "Typeof."
|
||||
|
||||
2002-10-02 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR opt/7124
|
||||
* config/i386/i386.c (ix86_register_move_cost): Increase cost
|
||||
for secondary_memory_needed pairs.
|
||||
|
||||
Wed Oct 9 19:09:13 CEST 2002 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR opt/7912
|
||||
PR opt/7390
|
||||
* i386.c (athlon_cost): Fix the move costs.
|
||||
|
||||
2002-10-09 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* libgcc2.c (__floatdisf): Properly cure double rounding.
|
||||
|
||||
2002-10-09 Gabriel Dos Reis <gdr@integrable-solutions.net>
|
||||
|
||||
PR doc/7484
|
||||
* doc/invoke.texi (Option Summary): List
|
||||
-Wmissing-declarations as a C only option.
|
||||
|
||||
2002-10-08 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/sparc/t-linux64 (MULTILIB_OPTIONS): Remove
|
||||
mno-app-regs|mcmodel=medany.
|
||||
(MULTILIB_DIRNAMES, MULTILIB_OSDIRNAMES): Remove alt.
|
||||
(MULTILIB_EXCEPTIONS, MULTILIB_EXCLUSIONS, MULTILIB_MATCHES): Remove.
|
||||
(CRTSTUFF_T_CFLAGS): Define.
|
||||
|
||||
2002-09-25 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
Volker Reichelt <reichelt@igpm.rwth-aachen.de>
|
||||
|
||||
PR c/7411
|
||||
* expr.c (expand_expr) [PLUS]: Simplify after the operands
|
||||
have been expanded in EXPAND_NORMAL mode.
|
||||
|
||||
2002-10-06 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/rs6000/rs6000.md (load_toc_v4_PIC_2): Fix base constraint.
|
||||
|
||||
2002-10-06 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR optimization/6627
|
||||
* toplev.c (force_align_functions_log): New global variable.
|
||||
* flags.h (force_align_functions_log): Add extern prototype.
|
||||
* varasm.c (assemble_start_function): Use it to force minimum
|
||||
function alignment.
|
||||
* config/i386/i386.h (FUNCTION_BOUNDARY): Set the correct
|
||||
minimum function alignment to one byte.
|
||||
(TARGET_PTRMEMFUNC_VBIT_LOCATION): Store the virtual bit in
|
||||
the least significant bit of vtable member function pointers.
|
||||
* tree.h (enum ptrmemfunc_vbit_where_t): Move definition to
|
||||
here from cp/cp-tree.h.
|
||||
|
||||
2002-10-06 Neil Booth <neil@daikokuya.co.uk>
|
||||
|
||||
Debian BTS Bug #157416
|
||||
* cpplib.c (destringize_and_run): Kludge around getting
|
||||
tokens from in-progress macros.
|
||||
(_cpp_do__Pragma): Simplify.
|
||||
|
||||
2002-10-06 Frank Ch. Eigler <fche@redhat.com>
|
||||
|
||||
* cppinit.c (init_standard_includes, parse_option): Use strncmp.
|
||||
|
||||
2002-10-05 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.c (set_multilib_dir): Don't access *end.
|
||||
Use memcpy instead of strncpy. Don't write beyond malloced buffer.
|
||||
(print_multilib_info): Don't show paths starting with ".:".
|
||||
* genmultilib: Add new option, "yes" if multilibs are enabled.
|
||||
Update comments. If multilibs not enabled, print .:${osdirout}
|
||||
for each directory. If multilibs are enabled, always print
|
||||
${dirout}:${osdirout}, even if the two are the same.
|
||||
* Makefile.in (s-mlib): Pass @enable_multilib@ to genmultilib.
|
||||
Pass all MULTILIB_* variables to genmultilib even if
|
||||
--disable-multilib but MULTILIB_OSDIRNAMES is not empty.
|
||||
|
||||
* gcc.c (print_multi_os_directory): New variable.
|
||||
(option_map): Support --print-multi-os-directory.
|
||||
(struct prefix_list): Add os_multilib field.
|
||||
(multilib_os_dir): New variable.
|
||||
(static_specs): Add multilib_options.
|
||||
(find_a_file): Add multilib argument. Search in GCC or OS multilib
|
||||
subdirs if non-zero.
|
||||
(read_specs, execute): Update callers.
|
||||
(find_file): Likewise. Don't prefix name with multilib_dir, instead
|
||||
pass 1 as multilib option.
|
||||
(display_help): Include --print-multi-os-directory.
|
||||
(add_prefix): Add os_multilib argument. Initialize pl->os_multilib.
|
||||
(process_command): Update callers. Handle --print-multi-os-directory.
|
||||
(do_spec_1) ['D']: Use multilib_os_directory if pl->os_multilib is
|
||||
set.
|
||||
(main): Update find_a_file and add_prefix callers.
|
||||
Handle print_multi_os_directory.
|
||||
(struct mdswitchstr): New.
|
||||
(mdswitches, n_mdswitches): New variables.
|
||||
(used_arg): Add MULTILIB_DEFAULT switches too if they are not
|
||||
present on the command line nor their mutually incompatible
|
||||
switches.
|
||||
(default_arg): Optimize.
|
||||
(set_multilib_dir): Compute multilib_os_dir. Initialize mdswitches
|
||||
array.
|
||||
(print_multilib_info): Only print GCC multilib dir name, not OS
|
||||
multilib dirname.
|
||||
* genmultilib: Add osdirnames parameter. Output multilib_options
|
||||
variable. If osdirnames is specified, output dirnames as
|
||||
dirname:osdirname.
|
||||
* mklibgcc.in: Use MULTILIB_OSDIRNAMES, --print-multi-directory
|
||||
and --print-multi-os-directory instead of SHLIB_SLIBDIR_SUFFIXES
|
||||
to compute libgcc_s soname and install path.
|
||||
* Makefile.in (libgcc.mk): Pass MULTILIB_OSDIRNAMES instead of
|
||||
SHLIB_SLIBDIR_SUFFIXES to mklibgcc.
|
||||
(s_mlib): Pass MULTILIB_OSDIRNAMES or nothing as last genmultilib
|
||||
argument.
|
||||
|
||||
* config/sparc/t-linux64 (MULTILIB_OSDIRNAMES): Set.
|
||||
(SHLIB_SLIBDIR_SUFFIXES): Remove.
|
||||
* config/sparc/linux64.h (STARTFILE_SPEC32, STARTFILE_SPEC64,
|
||||
ENDFILE_SPEC32, ENDFILE_SPEC64, ENDFILE_COMMON): Remove.
|
||||
(STARTFILE_SPEC, ENDFILE_SPEC): Don't distinguish between -m32
|
||||
and -m64.
|
||||
* config/sparc/t-sol2-64 (MULTILIB_OSDIRNAMES): Set.
|
||||
(SHLIB_SLIBDIR_SUFFIXES): Remove.
|
||||
* config/sparc/sol2-bi.h (STARTFILE_SPEC32, STARTFILE_SPEC64): Remove.
|
||||
(STARTFILE_ARCH_SPEC): Remove.
|
||||
(STARTFILE_SPEC): Add values-X*.o here.
|
||||
* config/i386/t-linux64 (MULTILIB_OSDIRNAMES): Set.
|
||||
(SHLIB_SLIBDIR_SUFFIXES): Remove.
|
||||
* config/i386/linux64.h (STARTFILE_PREFIX_SPEC): Remove.
|
||||
(STARTFILE_SPEC, ENDFILE_SPEC): Don't distinguish between m32 and
|
||||
!m32.
|
||||
* config/mips/t-iris6 (MULTILIB_OSDIRNAMES): Set.
|
||||
(SHLIB_SLIBDIR_SUFFIXES): Remove.
|
||||
|
||||
2002-10-05 Neil Booth <neil@daikokuya.co.uk>
|
||||
|
||||
PR preprocessor/8120
|
||||
* doc/cpp.texi: Update documentation of bad use of ##.
|
||||
|
||||
Thu Oct 3 23:15:15 CEST 2002 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* i386.h (CPP_SPECS): fix defines for -msse, -msse2, -mpentium2,3.
|
||||
|
||||
Thu Oct 3 21:35:36 CEST 2002 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* toplev.c (rest_of_compilation): Dump loops before clobbering
|
||||
the structure.
|
||||
|
||||
* expr.c (force_operand): Use expand_simple_* to handle more
|
||||
cases.
|
||||
|
||||
* i386.c (q_regs_operand): Use ANY_QI_REG_P.
|
||||
|
||||
* i386.c (override_options): Fix stack alignment.
|
||||
(classify_argument): Handle variable sized types.
|
||||
(ix86_expand_int_movcc): Avoid RTL sharing problem.
|
||||
|
||||
* i386.md (prefetch_sse_rex, prefetch_3dnow_rex): New.
|
||||
(prefetch): Properly handle 64bit case.
|
||||
|
||||
* i386.c (classify_argument): Properly compute word size of the analyzed object.
|
||||
|
||||
* jump.c (reg_or_subregno): New function.
|
||||
* rtl.h (reg_or_subregno): Declare
|
||||
* unroll.c (find_splittable_givs): Handle subregs.
|
||||
|
||||
Richard Sandiford <rsandifo@redhat.com>:
|
||||
|
||||
* expr.c (force_operand): Fix reversed move.
|
||||
|
||||
Andreas Jaeger <aj@suse.de>:
|
||||
|
||||
* config/i386/linux64.h (STARTFILE_PREFIX_SPEC): New.
|
||||
|
||||
Janis Johnson <janis187@us.ibm.com>:
|
||||
|
||||
* loop.c (emit_prefetch_instructions): Several small fixes.
|
||||
|
||||
Thu Sep 5 00:34:33 2002 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
* loop.c (scan_loop): Don't mark separate insns out of a libcall
|
||||
for moving.
|
||||
(move_movables): Abort if we see the first insn of a libcall.
|
||||
|
||||
2002-10-01 David S. Miller <davem@redhat.com>
|
||||
|
||||
PR middle-end/7151
|
||||
* config/sparc/sparc.md (movdi_insn_sp32_v9): Accept 'e' regs.
|
||||
(movdi reg/reg split): Match only on sparc32, and v9 when int regs.
|
||||
|
||||
2002-10-01 David S. Miller <davem@redhat.com>
|
||||
Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* reload1.c (gen_reload:SECONDARY_MEMORY_NEEDED): Handle SUBREG.
|
||||
* reload.c (push_reload:SECONDARY_MEMORY_NEEDED): Likewise.
|
||||
|
||||
2002-09-30 Bob Wilson <bob.wilson@acm.org>
|
||||
|
||||
* config/xtensa/xtensa.h (REG_CLASS_NAMES, REG_CLASS_CONTENTS):
|
||||
Add new RL_REGS register class.
|
||||
(PREFERRED_RELOAD_CLASS, PREFERRED_OUTPUT_RELOAD_CLASS):
|
||||
Call xtensa_preferred_reload_class for both input and output reloads.
|
||||
* config/xtensa/xtensa.c (xtensa_regno_to_class): Use new RL_REGS class.
|
||||
(xtensa_preferred_reload_class): Handle output reloads; use RL_REGS
|
||||
instead of either AR_REGS or GR_REGS classes.
|
||||
(xtensa_secondary_reload_class): Use new RL_REGS class.
|
||||
* config/xtensa/xtensa-protos.h (xtensa_preferred_reload_class): Update.
|
||||
|
||||
2002-08-21 John David Anglin <dave@hiauly1.hia.nrc.ca>
|
||||
|
||||
* cppinit.c (remove_dup_nonsys_dirs): Fix warning and return value.
|
||||
|
||||
2002-08-20 John David Anglin <dave@hiauly1.hia.nrc.ca>
|
||||
|
||||
* cppinit.c (remove_dup_dir): Add head_ptr argument to handle removal
|
||||
at head.
|
||||
(remove_dup_nonsys_dirs): New function.
|
||||
(remove_dup_dirs): Change argument head to head_ptr. Remove warnings.
|
||||
(merge_include_chains): Remove non-system include directories from
|
||||
quote and bracket include chains when they duplicate equivalent system
|
||||
directories.
|
||||
* doc/cpp.texi (-I): Update.
|
||||
* doc/cppopts.texi (-I): Update.
|
||||
* doc/install.texi (--with-local-prefix): Further document usage of
|
||||
this option.
|
||||
* doc/invoke.texi (-I): Update.
|
||||
|
||||
2002-09-30 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
* arm.h (BASE_REG_CLASS): Always return LO_REGS for Thumb.
|
||||
(MODE_BASE_REG_CLASS, case Thumb): Only return BASE_REGS if we know
|
||||
that we have a SImode access, and only then if reload hasn't completed;
|
||||
for all other cases, use LO_REGS.
|
||||
|
||||
2002-09-29 David S. Miller <davem@redhat.com>
|
||||
|
||||
* config/sparc/linux64.h (STARTFILE_SPEC32, ENDFILE_SPEC32): Kill
|
||||
hardcoded paths.
|
||||
|
||||
2002-09-27 Alexander N. Kabaev <ak03@gte.com>
|
||||
|
||||
PR preprocessor/8055
|
||||
* cppmacro.c (stringify_arg): Do not overflow the buffer
|
||||
with the terminating NUL when the argument to be stringified
|
||||
has no tokens.
|
||||
|
||||
2002-09-26 David S. Miller <davem@redhat.com>
|
||||
|
||||
PR optimization/7335
|
||||
* calls.c (emit_library_call_value_1): Passing args by reference
|
||||
converts a CONST function into a PURE one.
|
||||
|
||||
2002-09-26 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR c/7160
|
||||
* sched-deps.c (sched_analyze_insn): Make clobber insns depend
|
||||
on call insns.
|
||||
|
||||
2002-09-27 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* doloop.c (doloop_modify_runtime <biv skips initial incr>): Adjust
|
||||
by absolute loop increment, not loop increment.
|
||||
|
||||
2002-09-25 David S. Miller <davem@redhat.com>
|
||||
|
||||
PR target/7842
|
||||
* config/sparc/sparc.c (set_extends): SImode ASHIFT does not
|
||||
extend.
|
||||
|
||||
2002-09-20 Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
|
||||
|
||||
* config/arm/arm.md (sign_extract_onebit, not_signextract_onebit):
|
||||
Add clobber of the condition code register.
|
||||
|
||||
2002-09-18 Richard Earnshaw (rearnsha@arm.com)
|
||||
|
||||
PR optimization/7967
|
||||
* arm.md (ne_zeroextractsi): Add clobber of the condition code
|
||||
register.
|
||||
|
||||
2002-09-17 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* sibcall.c (optimize_sibling_and_tail_recursive_call): Also remove
|
||||
RTX_UNCHANGING_P markers for successful tail-recursive replacement.
|
||||
|
||||
2002-09-16 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR opt/7515
|
||||
* c-objc-common.c (c_cannot_inline_tree_fn): Don't auto-inline
|
||||
functions that don't bind locally.
|
||||
|
||||
2002-09-17 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
Merge from mainline.
|
||||
2002-07-20 Alan Modra <amodra@bigpond.net.au>
|
||||
PR optimization/7130
|
||||
* loop.h (struct loop_info): Add "preconditioned".
|
||||
* unroll.c (unroll_loop): Set it.
|
||||
* doloop.c (doloop_modify_runtime): Correct count for unrolled loops.
|
||||
|
||||
2002-06-24 Alan Modra <amodra@bigpond.net.au>
|
||||
PR optimization/6984
|
||||
* doloop.c (doloop_valid_p): Correct comment.
|
||||
(doloop_modify_runtime <abs_inc != 1>): Simplify.
|
||||
(doloop_modify_runtime <do-while>): Don't emit code when NE.
|
||||
|
||||
2002-09-16 Jeff Law <law@redhat.com>
|
||||
|
||||
* libgcc2.c: Do not include machmode.h.
|
||||
|
||||
2002-09-16 Jason Merrill <jason@redhat.com>
|
||||
Danny Smith <dannysmith@users.sourceforge.net>
|
||||
|
||||
* config/i386/winnt.c (ix86_handle_dll_attribute): Set
|
||||
DECL_EXTERN and TREE_PUBLIC for dllimported variables here...
|
||||
(i386_pe_mark_dllimport): Not here.
|
||||
|
||||
2002-09-14 Stephane Carrez <stcarrez@nerim.fr>
|
||||
|
||||
* config/m68hc11/m68hc11.md ("movdi_internal"): Allow any offsetable
|
||||
@ -185,7 +517,7 @@
|
||||
2002-08-27 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* doc/invoke.texi: Document -Wabi.
|
||||
|
||||
|
||||
2002-08-23 David Edelsohn <edelsohn@gnu.org>
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_select_section): Treat
|
||||
@ -201,7 +533,7 @@
|
||||
* explow.c (expr_size): Call it.
|
||||
(int_expr_size): New fn.
|
||||
* expr.h: Declare it.
|
||||
* expr.c (expand_expr) [CONSTRUCTOR]: Use it to calculate how
|
||||
* expr.c (expand_expr) [CONSTRUCTOR]: Use it to calculate how
|
||||
much to store.
|
||||
|
||||
2002-08-23 Alan Modra <amodra@bigpond.net.au>
|
||||
|
@ -149,6 +149,14 @@ c_cannot_inline_tree_fn (fnp)
|
||||
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
|
||||
return 1;
|
||||
|
||||
/* Don't auto-inline anything that might not be bound within
|
||||
this unit of translation. */
|
||||
if (!DECL_DECLARED_INLINE_P (fn) && flag_pic && TREE_PUBLIC (fn))
|
||||
{
|
||||
DECL_UNINLINABLE (fn) = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! function_attribute_inlinable_p (fn))
|
||||
{
|
||||
DECL_UNINLINABLE (fn) = 1;
|
||||
|
@ -3666,6 +3666,14 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
|
||||
#endif
|
||||
;
|
||||
|
||||
/* If this was a CONST function, it is now PURE since
|
||||
it now reads memory. */
|
||||
if (flags & ECF_CONST)
|
||||
{
|
||||
flags &= ~ECF_CONST;
|
||||
flags |= ECF_PURE;
|
||||
}
|
||||
|
||||
if (GET_MODE (val) == MEM && ! must_copy)
|
||||
slot = val;
|
||||
else if (must_copy)
|
||||
|
@ -1093,14 +1093,16 @@ enum reg_class
|
||||
|
||||
/* The class value for index registers, and the one for base regs. */
|
||||
#define INDEX_REG_CLASS (TARGET_THUMB ? LO_REGS : GENERAL_REGS)
|
||||
#define BASE_REG_CLASS (TARGET_THUMB ? BASE_REGS : GENERAL_REGS)
|
||||
#define BASE_REG_CLASS (TARGET_THUMB ? LO_REGS : GENERAL_REGS)
|
||||
|
||||
/* For the Thumb the high registers cannot be used as base
|
||||
registers when addressing quanitities in QI or HI mode. */
|
||||
/* For the Thumb the high registers cannot be used as base registers
|
||||
when addressing quanitities in QI or HI mode; if we don't know the
|
||||
mode, then we must be conservative. After reload we must also be
|
||||
conservative, since we can't support SP+reg addressing, and we
|
||||
can't fix up any bad substitutions. */
|
||||
#define MODE_BASE_REG_CLASS(MODE) \
|
||||
(TARGET_ARM ? BASE_REGS : \
|
||||
(((MODE) == QImode || (MODE) == HImode || (MODE) == VOIDmode) \
|
||||
? LO_REGS : BASE_REGS))
|
||||
(TARGET_ARM ? GENERAL_REGS : \
|
||||
(((MODE) == SImode && !reload_completed) ? BASE_REGS : LO_REGS))
|
||||
|
||||
/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
|
||||
registers explicitly used in the rtl to be used as spill registers
|
||||
|
@ -1837,7 +1837,8 @@
|
||||
(match_operand:SI 1 "s_register_operand" "r")
|
||||
(match_operand:SI 2 "const_int_operand" "n")
|
||||
(match_operand:SI 3 "const_int_operand" "n"))
|
||||
(const_int 0)))]
|
||||
(const_int 0)))
|
||||
(clobber (reg:CC CC_REGNUM))]
|
||||
"TARGET_ARM
|
||||
&& (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
|
||||
&& INTVAL (operands[2]) > 0
|
||||
@ -8947,7 +8948,8 @@
|
||||
[(set (match_operand:SI 0 "s_register_operand" "=r")
|
||||
(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
|
||||
(const_int 1)
|
||||
(match_operand:SI 2 "const_int_operand" "n")))]
|
||||
(match_operand:SI 2 "const_int_operand" "n")))
|
||||
(clobber (reg:CC CC_REGNUM))]
|
||||
"TARGET_ARM"
|
||||
"*
|
||||
operands[2] = GEN_INT (1 << INTVAL (operands[2]));
|
||||
@ -8963,7 +8965,8 @@
|
||||
(not:SI
|
||||
(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
|
||||
(const_int 1)
|
||||
(match_operand:SI 2 "const_int_operand" "n"))))]
|
||||
(match_operand:SI 2 "const_int_operand" "n"))))
|
||||
(clobber (reg:CC CC_REGNUM))]
|
||||
"TARGET_ARM"
|
||||
"*
|
||||
operands[2] = GEN_INT (1 << INTVAL (operands[2]));
|
||||
|
@ -50,21 +50,14 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC \
|
||||
"%{m32:%{!shared: \
|
||||
%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
|
||||
%{!p:%{profile:gcrt1.o%s} %{!profile:crt1.o%s}}}} \
|
||||
crti.o%s %{static:crtbeginT.o%s}\
|
||||
%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}} \
|
||||
%{!m32:%{!shared: \
|
||||
%{pg:/usr/lib64/gcrt1.o%s} %{!pg:%{p:/usr/lib64/gcrt1.o%s} \
|
||||
%{!p:%{profile:/usr/lib64/gcrt1.o%s} %{!profile:/usr/lib64/crt1.o%s}}}}\
|
||||
/usr/lib64/crti.o%s %{static:crtbeginT.o%s} \
|
||||
%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}}"
|
||||
"%{!shared: \
|
||||
%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
|
||||
%{!p:%{profile:gcrt1.o%s} %{!profile:crt1.o%s}}}} \
|
||||
crti.o%s %{static:crtbeginT.o%s} \
|
||||
%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC "\
|
||||
%{m32:%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s} \
|
||||
%{!m32:%{!shared:crtend.o%s} %{shared:crtendS.o%s} /usr/lib64/crtn.o%s}"
|
||||
#define ENDFILE_SPEC "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
|
||||
|
||||
#define MULTILIB_DEFAULTS { "m64" }
|
||||
|
||||
|
@ -6,10 +6,9 @@ SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver \
|
||||
|
||||
MULTILIB_OPTIONS = m64/m32
|
||||
MULTILIB_DIRNAMES = 64 32
|
||||
MULTILIB_OSDIRNAMES = ../lib64 ../lib
|
||||
|
||||
LIBGCC = stmp-multilib
|
||||
INSTALL_LIBGCC = install-multilib
|
||||
|
||||
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
|
||||
|
||||
SHLIB_SLIBDIR_SUFFIXES = 64:64 32:
|
||||
|
@ -76,6 +76,15 @@ ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs)
|
||||
}
|
||||
}
|
||||
|
||||
/* `extern' needn't be specified with dllimport.
|
||||
Specify `extern' now and hope for the best. Sigh. */
|
||||
else if (TREE_CODE (*node) == VAR_DECL
|
||||
&& is_attribute_p ("dllimport", name))
|
||||
{
|
||||
DECL_EXTERNAL (*node) = 1;
|
||||
TREE_PUBLIC (*node) = 1;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
@ -300,16 +309,6 @@ i386_pe_mark_dllimport (decl)
|
||||
return;
|
||||
}
|
||||
|
||||
/* `extern' needn't be specified with dllimport.
|
||||
Specify `extern' now and hope for the best. Sigh. */
|
||||
if (TREE_CODE (decl) == VAR_DECL
|
||||
/* ??? Is this test for vtables needed? */
|
||||
&& !DECL_VIRTUAL_P (decl))
|
||||
{
|
||||
DECL_EXTERNAL (decl) = 1;
|
||||
TREE_PUBLIC (decl) = 1;
|
||||
}
|
||||
|
||||
newname = alloca (strlen (oldname) + 11);
|
||||
sprintf (newname, "@i._imp__%s", oldname);
|
||||
|
||||
|
@ -9657,7 +9657,7 @@
|
||||
|
||||
(define_insn "load_toc_v4_PIC_2"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
|
||||
(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "b")
|
||||
(minus:SI (match_operand:SI 2 "immediate_operand" "s")
|
||||
(match_operand:SI 3 "immediate_operand" "s")))))]
|
||||
"TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions for 64-bit SPARC running Linux-based GNU systems with ELF.
|
||||
Copyright 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
|
||||
Copyright 1996, 1997, 1998, 2000, 2002 Free Software Foundation, Inc.
|
||||
Contributed by David S. Miller (davem@caip.rutgers.edu)
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -56,38 +56,12 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
|
||||
#define STARTFILE_SPEC32 \
|
||||
#define STARTFILE_SPEC \
|
||||
"%{!shared: \
|
||||
%{pg:/usr/lib/gcrt1.o%s} %{!pg:%{p:/usr/lib/gcrt1.o%s} %{!p:/usr/lib/crt1.o%s}}}\
|
||||
/usr/lib/crti.o%s %{static:crtbeginT.o%s}\
|
||||
%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
|
||||
crti.o%s %{static:crtbeginT.o%s}\
|
||||
%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
|
||||
|
||||
#define STARTFILE_SPEC64 \
|
||||
"%{!shared: \
|
||||
%{pg:/usr/lib64/gcrt1.o%s} %{!pg:%{p:/usr/lib64/gcrt1.o%s} %{!p:/usr/lib64/crt1.o%s}}}\
|
||||
/usr/lib64/crti.o%s %{static:crtbeginT.o%s}\
|
||||
%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
|
||||
|
||||
#ifdef SPARC_BI_ARCH
|
||||
|
||||
#if DEFAULT_ARCH32_P
|
||||
#define STARTFILE_SPEC "\
|
||||
%{m32:" STARTFILE_SPEC32 "} \
|
||||
%{m64:" STARTFILE_SPEC64 "} \
|
||||
%{!m32:%{!m64:" STARTFILE_SPEC32 "}}"
|
||||
#else
|
||||
#define STARTFILE_SPEC "\
|
||||
%{m32:" STARTFILE_SPEC32 "} \
|
||||
%{m64:" STARTFILE_SPEC64 "} \
|
||||
%{!m32:%{!m64:" STARTFILE_SPEC64 "}}"
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define STARTFILE_SPEC STARTFILE_SPEC64
|
||||
|
||||
#endif
|
||||
|
||||
/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on
|
||||
the GNU/Linux magical crtend.o file (see crtstuff.c) which
|
||||
provides part of the support for getting C++ file-scope static
|
||||
@ -96,36 +70,9 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
|
||||
#define ENDFILE_SPEC32 \
|
||||
"%{!shared:crtend.o%s} %{shared:crtendS.o%s} /usr/lib/crtn.o%s"
|
||||
|
||||
#define ENDFILE_SPEC64 \
|
||||
"%{!shared:crtend.o%s} %{shared:crtendS.o%s} /usr/lib64/crtn.o%s"
|
||||
|
||||
#define ENDFILE_SPEC_COMMON \
|
||||
"%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s}"
|
||||
|
||||
#ifdef SPARC_BI_ARCH
|
||||
|
||||
#if DEFAULT_ARCH32_P
|
||||
#define ENDFILE_SPEC "\
|
||||
%{m32:" ENDFILE_SPEC32 "} \
|
||||
%{m64:" ENDFILE_SPEC64 "} \
|
||||
%{!m32:%{!m64:" ENDFILE_SPEC32 "}} " \
|
||||
ENDFILE_SPEC_COMMON
|
||||
#else
|
||||
#define ENDFILE_SPEC "\
|
||||
%{m32:" ENDFILE_SPEC32 "} \
|
||||
%{m64:" ENDFILE_SPEC64 "} \
|
||||
%{!m32:%{!m64:" ENDFILE_SPEC64 "}} " \
|
||||
ENDFILE_SPEC_COMMON
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define ENDFILE_SPEC ENDFILE_SPEC64 " " ENDFILE_SPEC_COMMON
|
||||
|
||||
#endif
|
||||
#define ENDFILE_SPEC \
|
||||
"%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s\
|
||||
%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s}"
|
||||
|
||||
/* The GNU C++ standard library requires that these macros be defined. */
|
||||
#undef CPLUSPLUS_CPP_SPEC
|
||||
|
@ -72,30 +72,6 @@
|
||||
%{!mcpu*:%(asm_cpu_default)} \
|
||||
"
|
||||
|
||||
#define STARTFILE_SPEC32 "\
|
||||
%{ansi:values-Xc.o%s} \
|
||||
%{!ansi: \
|
||||
%{traditional:values-Xt.o%s} \
|
||||
%{!traditional:values-Xa.o%s}}"
|
||||
|
||||
#define STARTFILE_SPEC64 "\
|
||||
%{ansi:/usr/lib/sparcv9/values-Xc.o%s} \
|
||||
%{!ansi: \
|
||||
%{traditional:/usr/lib/sparcv9/values-Xt.o%s} \
|
||||
%{!traditional:/usr/lib/sparcv9/values-Xa.o%s}}"
|
||||
|
||||
#if DEFAULT_ARCH32_P
|
||||
#define STARTFILE_ARCH_SPEC "\
|
||||
%{m32:" STARTFILE_SPEC32 "} \
|
||||
%{m64:" STARTFILE_SPEC64 "} \
|
||||
%{!m32:%{!m64:" STARTFILE_SPEC32 "}}"
|
||||
#else
|
||||
#define STARTFILE_ARCH_SPEC "\
|
||||
%{m32:" STARTFILE_SPEC32 "} \
|
||||
%{m64:" STARTFILE_SPEC64 "} \
|
||||
%{!m32:%{!m64:" STARTFILE_SPEC64 "}}"
|
||||
#endif
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC "%{!shared: \
|
||||
%{!symbolic: \
|
||||
@ -103,7 +79,10 @@
|
||||
%{!p: \
|
||||
%{pg:gcrt1.o%s gmon.o%s} \
|
||||
%{!pg:crt1.o%s}}}} \
|
||||
crti.o%s " STARTFILE_ARCH_SPEC " \
|
||||
crti.o%s \
|
||||
%{ansi:values-Xc.o%s} \
|
||||
%{!ansi: %{traditional:values-Xt.o%s} \
|
||||
%{!traditional:values-Xa.o%s}} \
|
||||
crtbegin.o%s"
|
||||
|
||||
#undef CPP_CPU_DEFAULT_SPEC
|
||||
|
@ -8650,7 +8650,6 @@ set_extends (insn)
|
||||
return INTVAL (op1) >= 0;
|
||||
return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
|
||||
}
|
||||
case ASHIFT:
|
||||
case LSHIFTRT:
|
||||
return GET_MODE (SET_SRC (pat)) == SImode;
|
||||
/* Positive integers leave the high bits zero. */
|
||||
|
@ -2517,7 +2517,7 @@
|
||||
;
|
||||
}")
|
||||
|
||||
;; Be careful, fmovd does not exist when !arch64.
|
||||
;; Be careful, fmovd does not exist when !v9.
|
||||
;; We match MEM moves directly when we have correct even
|
||||
;; numbered registers, but fall into splits otherwise.
|
||||
;; The constraint ordering here is really important to
|
||||
@ -2531,9 +2531,9 @@
|
||||
|
||||
(define_insn "*movdi_insn_sp32_v9"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand"
|
||||
"=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
|
||||
"=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f,?e,?e,?W")
|
||||
(match_operand:DI 1 "input_operand"
|
||||
" J,J,U,T,r,o,i,r, f, T, o, f, f"))]
|
||||
" J,J,U,T,r,o,i,r, f, T, o, f, f, e, W, e"))]
|
||||
"! TARGET_ARCH64 && TARGET_V9
|
||||
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
|
||||
"@
|
||||
@ -2549,9 +2549,13 @@
|
||||
ldd\\t%1, %0
|
||||
#
|
||||
#
|
||||
#"
|
||||
[(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
|
||||
(set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,2")])
|
||||
#
|
||||
fmovd\\t%1, %0
|
||||
ldd\\t%1, %0
|
||||
std\\t%1, %0"
|
||||
[(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,*,fpmove,fpload,fpstore")
|
||||
(set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,2,*,*,*")
|
||||
(set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
|
||||
|
||||
(define_insn "*movdi_insn_sp32"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand"
|
||||
@ -2861,7 +2865,14 @@
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_operand:DI 1 "const_double_operand" ""))]
|
||||
"! TARGET_ARCH64 && reload_completed"
|
||||
"reload_completed
|
||||
&& (! TARGET_V9
|
||||
|| (! TARGET_ARCH64
|
||||
&& ((GET_CODE (operands[0]) == REG
|
||||
&& REGNO (operands[0]) < 32)
|
||||
|| (GET_CODE (operands[0]) == SUBREG
|
||||
&& GET_CODE (SUBREG_REG (operands[0])) == REG
|
||||
&& REGNO (SUBREG_REG (operands[0])) < 32))))"
|
||||
[(clobber (const_int 0))]
|
||||
"
|
||||
{
|
||||
|
@ -1,8 +1,6 @@
|
||||
MULTILIB_OPTIONS = m64/m32 mno-app-regs|mcmodel=medany
|
||||
MULTILIB_DIRNAMES = 64 32 alt
|
||||
MULTILIB_MATCHES = mcmodel?medany=mcmodel?medmid
|
||||
MULTILIB_EXCEPTIONS = m32/mno-app-regs* m32/mcmodel=*
|
||||
MULTILIB_EXCLUSIONS = m32/!m64/mno-app-regs m32/!m64/mcmodel=medany
|
||||
MULTILIB_OPTIONS = m64/m32
|
||||
MULTILIB_DIRNAMES = 64 32
|
||||
MULTILIB_OSDIRNAMES = ../lib64 ../lib
|
||||
|
||||
LIBGCC = stmp-multilib
|
||||
INSTALL_LIBGCC = install-multilib
|
||||
@ -10,10 +8,12 @@ INSTALL_LIBGCC = install-multilib
|
||||
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o \
|
||||
crtfastmath.o
|
||||
|
||||
SHLIB_SLIBDIR_SUFFIXES = 64:64 32:
|
||||
|
||||
# Override t-slibgcc-elf-ver to export some libgcc symbols with
|
||||
# the symbol versions that glibc used.
|
||||
# Avoid the t-linux version file.
|
||||
SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver \
|
||||
$(srcdir)/config/sparc/libgcc-sparc-glibc.ver
|
||||
|
||||
CRTSTUFF_T_CFLAGS = `if test x$$($(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) \
|
||||
-print-multi-os-directory) \
|
||||
= x../lib64; then echo -mcmodel=medany; fi`
|
||||
|
@ -1,11 +1,10 @@
|
||||
MULTILIB_OPTIONS = m32/m64
|
||||
MULTILIB_DIRNAMES = sparcv7 sparcv9
|
||||
MULTILIB_MATCHES =
|
||||
MULTILIB_OSDIRNAMES = . sparcv9
|
||||
|
||||
LIBGCC = stmp-multilib
|
||||
INSTALL_LIBGCC = install-multilib
|
||||
|
||||
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o gmon.o crt1.o crti.o crtn.o gcrt1.o \
|
||||
crtfastmath.o
|
||||
|
||||
SHLIB_SLIBDIR_SUFFIXES = sparcv9:/sparcv9 sparcv7:
|
||||
|
@ -1,3 +1,54 @@
|
||||
2002-10-09 Zack Weinberg <zack@codesourcery.com>
|
||||
|
||||
PR c/7353
|
||||
* decl.c (start_decl): Unconditionally issue error for
|
||||
'typedef foo = bar'.
|
||||
(cp_finish_decl): Remove special case for TYPE_DECL with initializer.
|
||||
(grokdeclarator): Remove redundant error for 'typedef foo = bar'.
|
||||
|
||||
2002-10-03 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/7754
|
||||
* decl2.c (finish_anon_union): Do not expand anonymous unions when
|
||||
procesing template functions.
|
||||
* pt.c (tsubst_decl, case VAR_DECL): Try to complete the variable
|
||||
type. Call layout_decl.
|
||||
(tsubst_expr, case DECL_STMT): Handle anonymous unions.
|
||||
|
||||
2002-10-07 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* decl2.c: Complete reversion of c++/7754.
|
||||
|
||||
2002-10-06 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR optimization/6627
|
||||
* cp/cp-tree.h (enum ptrmemfunc_vbit_where_t): Delete definition
|
||||
from here, and move it to tree.h.
|
||||
* cp/decl.c (cxx_init_decl_processing): If storing the vbit
|
||||
in function pointers, ensure that force_align_functions_log
|
||||
is atleast one.
|
||||
|
||||
2002-10-04 H.J. Lu (hjl@gnu.org)
|
||||
|
||||
* pt.c (tsubst_decl, case VAR_DECL): Back out the last change.
|
||||
(tsubst_expr, case DECL_STMT): Likewise.
|
||||
|
||||
2002-10-02 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/7754
|
||||
* decl2.c (finish_anon_union): Do not expand anonymous unions when
|
||||
procesing template functions.
|
||||
* pt.c (tsubst_decl, case VAR_DECL): Try to complete the variable
|
||||
type. Call layout_decl.
|
||||
(tsubst_expr, case DECL_STMT): Handle anonymous unions.
|
||||
|
||||
2002-10-02 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/7188.
|
||||
* init.c (expand_member_init): Allow a FIELD_DECL to be passed in
|
||||
directly.
|
||||
* pt.c (tsubst_initializer_list): Use expand_member_init.
|
||||
|
||||
2002-09-04 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* decl.c (start_cleanup_fn): Clear interface_only before
|
||||
@ -336,7 +387,7 @@
|
||||
2002-04-29 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
PR c++/5719
|
||||
* decl.c (grok_op_properties): Assignment ops don't have to return
|
||||
* decl.c (grok_op_properties): Assignment ops don't have to return
|
||||
by value. operator% should.
|
||||
|
||||
2002-04-28 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
|
||||
@ -420,7 +471,7 @@
|
||||
(finish_init_stmts): Set STMT_EXPR_NO_SCOPE.
|
||||
* semantics.c (begin_gobal_stmt_expr): Adjust call to
|
||||
expand_start_stmt_expr.
|
||||
|
||||
|
||||
2002-04-15 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* decl.c (register_dtor_fn): Pass the address of dso_handle, not
|
||||
@ -449,11 +500,11 @@
|
||||
|
||||
* typeck.c (type_after_usual_arithmetic_conversions):
|
||||
If two types have the same variant, return immediately.
|
||||
When two floating-point operands are the same precision:
|
||||
When two floating-point operands are the same precision:
|
||||
convert to float if one of the operands is float;
|
||||
if neither operand is one of the standard types, return the type
|
||||
of the first operand.
|
||||
|
||||
|
||||
2002-04-12 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* decl.c (duplicate_decls): Don't try to unify an implicit typedef
|
||||
@ -511,7 +562,7 @@
|
||||
set before checking it.
|
||||
|
||||
PR c++/6179
|
||||
* method.c (implicitly_declare_fn): Pass unqualified type to
|
||||
* method.c (implicitly_declare_fn): Pass unqualified type to
|
||||
synthesize_exception_spec.
|
||||
|
||||
2002-04-03 Jason Merrill <jason@redhat.com>
|
||||
@ -576,7 +627,7 @@
|
||||
PR c++/4884
|
||||
* call.c (build_op_delete_call): Allow for the fact the placement
|
||||
may be a COMPOUND_EXPR.
|
||||
|
||||
|
||||
2002-03-26 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
PR c++/5682
|
||||
@ -630,7 +681,7 @@
|
||||
|
||||
2002-03-18 Ashif Harji <asharji@uwaterloo.ca>
|
||||
|
||||
* lang-specs.h (compiler default_compilers): Add
|
||||
* lang-specs.h (compiler default_compilers): Add
|
||||
-no-integrated-cpp flag to invoke an external cpp.
|
||||
|
||||
2002-03-18 Jason Merrill <jason@redhat.com>
|
||||
@ -747,7 +798,7 @@
|
||||
with pointer to member conversions.
|
||||
|
||||
2002-03-08 Craig Rodrigues <rodrigc@gcc.gnu.org>
|
||||
|
||||
|
||||
* cp-tree.h (CLEAR_BINFO_MARKED): Make both parts of
|
||||
conditional return void.
|
||||
|
||||
@ -781,7 +832,7 @@
|
||||
* decl.c (finish_function): Only warn about missing return
|
||||
statement with -Wreturn-type.
|
||||
|
||||
2002-02-24 Craig Rodrigues <rodrigc@gcc.gnu.org>
|
||||
2002-02-24 Craig Rodrigues <rodrigc@gcc.gnu.org>
|
||||
|
||||
PR c++/4093
|
||||
* cp-tree.h (SET_BINFO_MARKED): Cast false part of condition
|
||||
@ -835,7 +886,7 @@
|
||||
|
||||
2002-02-19 Jason Merrill <jason@redhat.com>
|
||||
|
||||
ABI change: Mangle `void (A::*)() const' as
|
||||
ABI change: Mangle `void (A::*)() const' as
|
||||
M1AKFvvE, not MK1AFvvE.
|
||||
* mangle.c (write_function_type): Write cv-quals for member
|
||||
function type here.
|
||||
@ -910,14 +961,14 @@
|
||||
(coerce_template_template_parms, convert_template_argument,
|
||||
coerce_template_parms, maybe_get_template_decl_from_type_decl,
|
||||
lookup_template_class, tsubst_friend_function, tsubst_friend_class,
|
||||
instantiate_class_template, tsubst_template_arg_vector,
|
||||
tsubst_template_parms, tsubst_aggr_type, tsubst_default_argument,
|
||||
instantiate_class_template, tsubst_template_arg_vector,
|
||||
tsubst_template_parms, tsubst_aggr_type, tsubst_default_argument,
|
||||
tsubst_decl, tsubst_arg_types, tsubst_function_type,
|
||||
tsubst_call_declarator_parms, tsubst, tsubst_copy, tsubst_expr,
|
||||
tsubst_call_declarator_parms, tsubst, tsubst_copy, tsubst_expr,
|
||||
instantiate_template, fn_type_unification,
|
||||
resolve_overloaded_unification, verify_class_unification,
|
||||
unify, get_bindings_real, do_type_instantiation,
|
||||
regenerate_decl_from_template, instantiate_decl,
|
||||
resolve_overloaded_unification, verify_class_unification,
|
||||
unify, get_bindings_real, do_type_instantiation,
|
||||
regenerate_decl_from_template, instantiate_decl,
|
||||
tsubst_initializer_list, tsubst_enum,
|
||||
get_mostly_instantiated_function_type,
|
||||
invalid_nontype_parm_type_p): Likewise.
|
||||
@ -978,7 +1029,7 @@
|
||||
2002-02-01 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/4872
|
||||
* decl.c (finish_function): Warn about a non-void function with
|
||||
* decl.c (finish_function): Warn about a non-void function with
|
||||
no return statement and no abnormal exit.
|
||||
* cp-tree.h (struct cp_language_function): Add returns_abnormally.
|
||||
(current_function_returns_abnormally): New macro.
|
||||
|
@ -2557,32 +2557,6 @@ extern int flag_new_for_scope;
|
||||
member function. [expr.unary.op]/3 */
|
||||
#define PTRMEM_OK_P(NODE) TREE_LANG_FLAG_0 (NODE)
|
||||
|
||||
/* A pointer-to-function member type looks like:
|
||||
|
||||
struct {
|
||||
__P __pfn;
|
||||
ptrdiff_t __delta;
|
||||
};
|
||||
|
||||
If __pfn is NULL, it is a NULL pointer-to-member-function.
|
||||
|
||||
(Because the vtable is always the first thing in the object, we
|
||||
don't need its offset.) If the function is virtual, then PFN is
|
||||
one plus twice the index into the vtable; otherwise, it is just a
|
||||
pointer to the function.
|
||||
|
||||
Unfortunately, using the lowest bit of PFN doesn't work in
|
||||
architectures that don't impose alignment requirements on function
|
||||
addresses, or that use the lowest bit to tell one ISA from another,
|
||||
for example. For such architectures, we use the lowest bit of
|
||||
DELTA instead of the lowest bit of the PFN, and DELTA will be
|
||||
multiplied by 2. */
|
||||
enum ptrmemfunc_vbit_where_t
|
||||
{
|
||||
ptrmemfunc_vbit_in_pfn,
|
||||
ptrmemfunc_vbit_in_delta
|
||||
};
|
||||
|
||||
/* Get the POINTER_TYPE to the METHOD_TYPE associated with this
|
||||
pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true,
|
||||
before using this macro. */
|
||||
|
@ -1975,26 +1975,31 @@ finish_anon_union (anon_union_decl)
|
||||
return;
|
||||
}
|
||||
|
||||
main_decl = build_anon_union_vars (anon_union_decl,
|
||||
&DECL_ANON_UNION_ELEMS (anon_union_decl),
|
||||
static_p, external_p);
|
||||
|
||||
if (main_decl == NULL_TREE)
|
||||
if (!processing_template_decl)
|
||||
{
|
||||
warning ("anonymous aggregate with no members");
|
||||
return;
|
||||
main_decl
|
||||
= build_anon_union_vars (anon_union_decl,
|
||||
&DECL_ANON_UNION_ELEMS (anon_union_decl),
|
||||
static_p, external_p);
|
||||
|
||||
if (main_decl == NULL_TREE)
|
||||
{
|
||||
warning ("anonymous aggregate with no members");
|
||||
return;
|
||||
}
|
||||
|
||||
if (static_p)
|
||||
{
|
||||
make_decl_rtl (main_decl, 0);
|
||||
COPY_DECL_RTL (main_decl, anon_union_decl);
|
||||
expand_anon_union_decl (anon_union_decl,
|
||||
NULL_TREE,
|
||||
DECL_ANON_UNION_ELEMS (anon_union_decl));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (static_p)
|
||||
{
|
||||
make_decl_rtl (main_decl, 0);
|
||||
COPY_DECL_RTL (main_decl, anon_union_decl);
|
||||
expand_anon_union_decl (anon_union_decl,
|
||||
NULL_TREE,
|
||||
DECL_ANON_UNION_ELEMS (anon_union_decl));
|
||||
}
|
||||
else
|
||||
add_decl_stmt (anon_union_decl);
|
||||
add_decl_stmt (anon_union_decl);
|
||||
}
|
||||
|
||||
/* Finish processing a builtin type TYPE. It's name is NAME,
|
||||
|
@ -1094,7 +1094,10 @@ expand_member_init (exp, name, init)
|
||||
}
|
||||
else
|
||||
{
|
||||
field = lookup_field (type, name, 1, 0);
|
||||
if (TREE_CODE (name) == IDENTIFIER_NODE)
|
||||
field = lookup_field (type, name, 1, 0);
|
||||
else
|
||||
field = name;
|
||||
|
||||
if (! member_init_ok_or_else (field, type, name))
|
||||
return NULL_TREE;
|
||||
|
@ -6079,6 +6079,8 @@ tsubst_decl (t, args, type, complain)
|
||||
}
|
||||
|
||||
r = copy_decl (t);
|
||||
if (TREE_CODE (r) == VAR_DECL)
|
||||
type = complete_type (type);
|
||||
TREE_TYPE (r) = type;
|
||||
c_apply_type_quals_to_decl (cp_type_quals (type), r);
|
||||
DECL_CONTEXT (r) = ctx;
|
||||
@ -6115,6 +6117,8 @@ tsubst_decl (t, args, type, complain)
|
||||
TREE_CHAIN (r) = NULL_TREE;
|
||||
if (TREE_CODE (r) == VAR_DECL && VOID_TYPE_P (type))
|
||||
cp_error_at ("instantiation of `%D' as type `%T'", r, type);
|
||||
/* Compute the size, alignment, etc. of R. */
|
||||
layout_decl (r, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -7374,9 +7378,6 @@ tsubst_expr (t, args, complain, in_decl)
|
||||
decl = tsubst (decl, args, complain, in_decl);
|
||||
if (decl != error_mark_node)
|
||||
{
|
||||
if (TREE_CODE (decl) != TYPE_DECL)
|
||||
/* Make sure the type is instantiated now. */
|
||||
complete_type (TREE_TYPE (decl));
|
||||
if (init)
|
||||
DECL_INITIAL (decl) = error_mark_node;
|
||||
/* By marking the declaration as instantiated, we avoid
|
||||
@ -7386,19 +7387,26 @@ tsubst_expr (t, args, complain, in_decl)
|
||||
do. */
|
||||
if (TREE_CODE (decl) == VAR_DECL)
|
||||
DECL_TEMPLATE_INSTANTIATED (decl) = 1;
|
||||
maybe_push_decl (decl);
|
||||
if (DECL_PRETTY_FUNCTION_P (decl))
|
||||
if (TREE_CODE (decl) == VAR_DECL
|
||||
&& ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
|
||||
/* Anonymous aggregates are a special case. */
|
||||
finish_anon_union (decl);
|
||||
else
|
||||
{
|
||||
/* For __PRETTY_FUNCTION__ we have to adjust the
|
||||
initializer. */
|
||||
const char *const name
|
||||
= (*decl_printable_name) (current_function_decl, 2);
|
||||
init = cp_fname_init (name);
|
||||
TREE_TYPE (decl) = TREE_TYPE (init);
|
||||
maybe_push_decl (decl);
|
||||
if (DECL_PRETTY_FUNCTION_P (decl))
|
||||
{
|
||||
/* For __PRETTY_FUNCTION__ we have to adjust the
|
||||
initializer. */
|
||||
const char *const name
|
||||
= (*decl_printable_name) (current_function_decl, 2);
|
||||
init = cp_fname_init (name);
|
||||
TREE_TYPE (decl) = TREE_TYPE (init);
|
||||
}
|
||||
else
|
||||
init = tsubst_expr (init, args, complain, in_decl);
|
||||
cp_finish_decl (decl, init, NULL_TREE, 0);
|
||||
}
|
||||
else
|
||||
init = tsubst_expr (init, args, complain, in_decl);
|
||||
cp_finish_decl (decl, init, NULL_TREE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10274,8 +10282,10 @@ tsubst_initializer_list (t, argvec)
|
||||
else
|
||||
init = convert_from_reference (init);
|
||||
|
||||
*p = build_tree_list (decl, init);
|
||||
p = &TREE_CHAIN (*p);
|
||||
*p = expand_member_init (current_class_ref, decl,
|
||||
init ? init : void_type_node);
|
||||
if (*p)
|
||||
p = &TREE_CHAIN (*p);
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
@ -1224,6 +1224,9 @@ destringize_and_run (pfile, in)
|
||||
{
|
||||
const unsigned char *src, *limit;
|
||||
char *dest, *result;
|
||||
cpp_context saved_context;
|
||||
cpp_context *saved_cur_context;
|
||||
unsigned int saved_line;
|
||||
|
||||
dest = result = alloca (in->len + 1);
|
||||
for (src = in->text, limit = src + in->len; src < limit;)
|
||||
@ -1235,7 +1238,40 @@ destringize_and_run (pfile, in)
|
||||
}
|
||||
*dest = '\0';
|
||||
|
||||
/* FIXME. All this saving is a horrible kludge to handle the case
|
||||
when we're in a macro expansion.
|
||||
|
||||
A better strategy it to not convert _Pragma to #pragma if doing
|
||||
preprocessed output, but to just pass it through as-is, unless it
|
||||
is a CPP pragma in which case is should be processed normally.
|
||||
When compiling the preprocessed output the _Pragma should be
|
||||
handled. This will be become necessary when we move to
|
||||
line-at-a-time lexing since we will be macro-expanding the line
|
||||
before outputting / compiling it. */
|
||||
saved_line = pfile->line;
|
||||
saved_context = pfile->base_context;
|
||||
saved_cur_context = pfile->context;
|
||||
pfile->context = &pfile->base_context;
|
||||
run_directive (pfile, T_PRAGMA, result, dest - result);
|
||||
pfile->context = saved_cur_context;
|
||||
pfile->base_context = saved_context;
|
||||
pfile->line = saved_line;
|
||||
|
||||
/* See above comment. For the moment, we'd like
|
||||
|
||||
token1 _Pragma ("foo") token2
|
||||
|
||||
to be output as
|
||||
|
||||
token1
|
||||
# 7 "file.c"
|
||||
#pragma foo
|
||||
# 7 "file.c"
|
||||
token2
|
||||
|
||||
Getting the line markers is a little tricky. */
|
||||
if (pfile->cb.line_change)
|
||||
(*pfile->cb.line_change) (pfile, pfile->cur_token, false);
|
||||
}
|
||||
|
||||
/* Handle the _Pragma operator. */
|
||||
@ -1245,25 +1281,10 @@ _cpp_do__Pragma (pfile)
|
||||
{
|
||||
const cpp_token *string = get__Pragma_string (pfile);
|
||||
|
||||
if (!string)
|
||||
cpp_error (pfile, "_Pragma takes a parenthesized string literal");
|
||||
if (string)
|
||||
destringize_and_run (pfile, &string->val.str);
|
||||
else
|
||||
{
|
||||
/* Ideally, we'd like
|
||||
token1 _Pragma ("foo") token2
|
||||
to be output as
|
||||
token1
|
||||
# 7 "file.c"
|
||||
#pragma foo
|
||||
# 7 "file.c"
|
||||
token2
|
||||
Getting these correct line markers is a little tricky. */
|
||||
|
||||
unsigned int orig_line = pfile->line;
|
||||
destringize_and_run (pfile, &string->val.str);
|
||||
pfile->line = orig_line;
|
||||
pfile->buffer->saved_flags = BOL;
|
||||
}
|
||||
cpp_error (pfile, "_Pragma takes a parenthesized string literal");
|
||||
}
|
||||
|
||||
/* Just ignore #sccs, on systems where we define it at all. */
|
||||
|
@ -348,6 +348,12 @@ stringify_arg (pfile, arg)
|
||||
}
|
||||
|
||||
/* Commit the memory, including NUL, and return the token. */
|
||||
if ((size_t) (BUFF_LIMIT (pfile->u_buff) - dest) < 1)
|
||||
{
|
||||
size_t len_so_far = dest - BUFF_FRONT (pfile->u_buff);
|
||||
_cpp_extend_buff (pfile, &pfile->u_buff, 1);
|
||||
dest = BUFF_FRONT (pfile->u_buff) + len_so_far;
|
||||
}
|
||||
len = dest - BUFF_FRONT (pfile->u_buff);
|
||||
BUFF_FRONT (pfile->u_buff) = dest + 1;
|
||||
return new_string_token (pfile, dest - len, len);
|
||||
|
@ -830,11 +830,22 @@ version of GCC in use.
|
||||
|
||||
You can add to this list with the @option{-I@var{dir}} command line
|
||||
option. All the directories named by @option{-I} are searched, in
|
||||
left-to-right order, @emph{before} the default directories. You can
|
||||
also prevent GCC from searching any of the default directories with the
|
||||
@option{-nostdinc} option. This is useful when you are compiling an
|
||||
left-to-right order, @emph{before} the default directories. The only
|
||||
exception is when @file{dir} is already searched by default. In
|
||||
this case, the option is ignored and the search order for system
|
||||
directories remains unchanged.
|
||||
|
||||
Duplicate directories are removed from the quote and bracket search
|
||||
chains before the two chains are merged to make the final search chain.
|
||||
Thus, it is possible for a directory to occur twice in the final search
|
||||
chain if it was specified in both the quote and bracket chains.
|
||||
|
||||
You can prevent GCC from searching any of the default directories with
|
||||
the @option{-nostdinc} option. This is useful when you are compiling an
|
||||
operating system kernel or some other program that does not use the
|
||||
standard C library facilities, or the standard C library itself.
|
||||
@option{-I} options are not ignored as described above when
|
||||
@option{-nostdinc} is in effect.
|
||||
|
||||
GCC looks for headers requested with @code{@w{#include "@var{file}"}}
|
||||
first in the directory containing the current file, then in the same
|
||||
@ -843,12 +854,6 @@ For example, if @file{/usr/include/sys/stat.h} contains
|
||||
@code{@w{#include "types.h"}}, GCC looks for @file{types.h} first in
|
||||
@file{/usr/include/sys}, then in its usual search path.
|
||||
|
||||
If you name a search directory with @option{-I@var{dir}} that is also a
|
||||
system include directory, the @option{-I} wins; the directory will be
|
||||
searched according to the @option{-I} ordering, and it will not be
|
||||
treated as a system include directory. GCC will warn you when a system
|
||||
include directory is hidden in this way.
|
||||
|
||||
@samp{#line} (@pxref{Line Control}) does not change GCC's idea of the
|
||||
directory containing the current file.
|
||||
|
||||
@ -1081,8 +1086,8 @@ found in that directory will be considered system headers.
|
||||
All directories named by @option{-isystem} are searched @emph{after} all
|
||||
directories named by @option{-I}, no matter what their order was on the
|
||||
command line. If the same directory is named by both @option{-I} and
|
||||
@option{-isystem}, @option{-I} wins; it is as if the @option{-isystem} option
|
||||
had never been specified at all. GCC warns you when this happens.
|
||||
@option{-isystem}, the @option{-I} option is ignored. GCC provides an
|
||||
informative message when this occurs if @option{-v} is used.
|
||||
|
||||
@findex #pragma GCC system_header
|
||||
There is also a directive, @code{@w{#pragma GCC system_header}}, which
|
||||
@ -1815,9 +1820,7 @@ conformance to the C Standard. GNU CPP follows the host convention when
|
||||
processing system header files, but when processing user files
|
||||
@code{__STDC__} is always 1. This has been reported to cause problems;
|
||||
for instance, some versions of Solaris provide X Windows headers that
|
||||
expect @code{__STDC__} to be either undefined or 1. You may be able to
|
||||
work around this sort of problem by using an @option{-I} option to
|
||||
cancel treatment of those headers as system headers. @xref{Invocation}.
|
||||
expect @code{__STDC__} to be either undefined or 1. @xref{Invocation}.
|
||||
|
||||
@item __STDC_VERSION__
|
||||
This macro expands to the C Standard's version number, a long integer
|
||||
@ -3733,9 +3736,9 @@ Here are a few more obsolete features.
|
||||
@item Attempting to paste two tokens which together do not form a valid
|
||||
preprocessing token.
|
||||
|
||||
The preprocessor currently warns about this and outputs the two tokens
|
||||
adjacently, which is probably the behavior the programmer intends. It
|
||||
may not work in future, though.
|
||||
The preprocessor currently warns about this, and the resulting
|
||||
preprocessed output is undefined. The tokens remain distinct if the
|
||||
preprocessor is being used directly by the compiler front end.
|
||||
|
||||
Most of the time, when you get this warning, you will find that @samp{##}
|
||||
is being used superstitiously, to guard against whitespace appearing
|
||||
|
@ -385,7 +385,6 @@ extensions, accepted by GCC in C89 mode and in C++.
|
||||
* Labels as Values:: Getting pointers to labels, and computed gotos.
|
||||
* Nested Functions:: As in Algol and Pascal, lexical scoping of functions.
|
||||
* Constructing Calls:: Dispatching a call to another function.
|
||||
* Naming Types:: Giving a name to the type of some expression.
|
||||
* Typeof:: @code{typeof}: referring to the type of an expression.
|
||||
* Lvalues:: Using @samp{?:}, @samp{,} and casts in lvalues.
|
||||
* Conditionals:: Omitting the middle operand of a @samp{?:} expression.
|
||||
@ -495,8 +494,7 @@ the value of an enumeration constant, the width of a bit-field, or
|
||||
the initial value of a static variable.
|
||||
|
||||
If you don't know the type of the operand, you can still do this, but you
|
||||
must use @code{typeof} (@pxref{Typeof}) or type naming (@pxref{Naming
|
||||
Types}).
|
||||
must use @code{typeof} (@pxref{Typeof}).
|
||||
|
||||
Statement expressions are not supported fully in G++, and their fate
|
||||
there is unclear. (It is possible that they will become fully supported
|
||||
@ -845,29 +843,6 @@ the containing function. You should specify, for @var{result}, a value
|
||||
returned by @code{__builtin_apply}.
|
||||
@end deftypefn
|
||||
|
||||
@node Naming Types
|
||||
@section Naming an Expression's Type
|
||||
@cindex naming types
|
||||
|
||||
You can give a name to the type of an expression using a @code{typedef}
|
||||
declaration with an initializer. Here is how to define @var{name} as a
|
||||
type name for the type of @var{exp}:
|
||||
|
||||
@example
|
||||
typedef @var{name} = @var{exp};
|
||||
@end example
|
||||
|
||||
This is useful in conjunction with the statements-within-expressions
|
||||
feature. Here is how the two together can be used to define a safe
|
||||
``maximum'' macro that operates on any arithmetic type:
|
||||
|
||||
@example
|
||||
#define max(a,b) \
|
||||
(@{typedef _ta = (a), _tb = (b); \
|
||||
_ta _a = (a); _tb _b = (b); \
|
||||
_a > _b ? _a : _b; @})
|
||||
@end example
|
||||
|
||||
@cindex underscores in variables in macros
|
||||
@cindex @samp{_} in variables in macros
|
||||
@cindex local variables in macros
|
||||
@ -919,6 +894,21 @@ A @code{typeof}-construct can be used anywhere a typedef name could be
|
||||
used. For example, you can use it in a declaration, in a cast, or inside
|
||||
of @code{sizeof} or @code{typeof}.
|
||||
|
||||
@code{typeof} is often useful in conjunction with the
|
||||
statements-within-expressions feature. Here is how the two together can
|
||||
be used to define a safe ``maximum'' macro that operates on any
|
||||
arithmetic type and evaluates each of its arguments exactly once:
|
||||
|
||||
@example
|
||||
#define max(a,b) \
|
||||
(@{ typeof (a) _a = (a); \
|
||||
typeof (b) _b = (b); \
|
||||
_a > _b ? _a : _b; @})
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
Some more examples of the use of @code{typeof}:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
This declares @code{y} with the type of what @code{x} points to.
|
||||
@ -968,6 +958,26 @@ Thus, @code{array (pointer (char), 4)} is the type of arrays of 4
|
||||
pointers to @code{char}.
|
||||
@end itemize
|
||||
|
||||
@emph{Compatibility Note:} In addition to @code{typeof}, GCC 2 supported
|
||||
a more limited extension which permitted one to write
|
||||
|
||||
@example
|
||||
typedef @var{T} = @var{expr};
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
with the effect of declaring @var{T} to have the type of the expression
|
||||
@var{expr}. This extension does not work with GCC 3 (versions between
|
||||
3.0 and 3.2 will crash; 3.2.1 and later give an error). Code which
|
||||
relies on it should be rewritten to use @code{typeof}:
|
||||
|
||||
@example
|
||||
typedef typeof(@var{expr}) @var{T};
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
This will work with all versions of GCC@.
|
||||
|
||||
@node Lvalues
|
||||
@section Generalized Lvalues
|
||||
@cindex compound expressions as lvalues
|
||||
@ -6170,12 +6180,12 @@ the minimum value of variables @var{i} and @var{j}.
|
||||
|
||||
However, side effects in @code{X} or @code{Y} may cause unintended
|
||||
behavior. For example, @code{MIN (i++, j++)} will fail, incrementing
|
||||
the smaller counter twice. A GNU C extension allows you to write safe
|
||||
macros that avoid this kind of problem (@pxref{Naming Types,,Naming an
|
||||
Expression's Type}). However, writing @code{MIN} and @code{MAX} as
|
||||
macros also forces you to use function-call notation for a
|
||||
fundamental arithmetic operation. Using GNU C++ extensions, you can
|
||||
write @w{@samp{int min = i <? j;}} instead.
|
||||
the smaller counter twice. The GNU C @code{typeof} extension allows you
|
||||
to write safe macros that avoid this kind of problem (@pxref{Typeof}).
|
||||
However, writing @code{MIN} and @code{MAX} as macros also forces you to
|
||||
use function-call notation for a fundamental arithmetic operation.
|
||||
Using GNU C++ extensions, you can write @w{@samp{int min = i <? j;}}
|
||||
instead.
|
||||
|
||||
Since @code{<?} and @code{>?} are built into the compiler, they properly
|
||||
handle expressions with side-effects; @w{@samp{int min = i++ <? j++;}}
|
||||
|
@ -222,7 +222,7 @@ in the following sections.
|
||||
-Werror-implicit-function-declaration @gol
|
||||
-Wimport -Winline @gol
|
||||
-Wlarger-than-@var{len} -Wlong-long @gol
|
||||
-Wmain -Wmissing-braces -Wmissing-declarations @gol
|
||||
-Wmain -Wmissing-braces @gol
|
||||
-Wmissing-format-attribute -Wmissing-noreturn @gol
|
||||
-Wmultichar -Wno-format-extra-args -Wno-format-y2k @gol
|
||||
-Wno-import -Wpacked -Wpadded @gol
|
||||
@ -236,8 +236,8 @@ in the following sections.
|
||||
|
||||
@item C-only Warning Options
|
||||
@gccoptlist{
|
||||
-Wbad-function-cast -Wmissing-prototypes -Wnested-externs @gol
|
||||
-Wstrict-prototypes -Wtraditional}
|
||||
-Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes @gol
|
||||
-Wnested-externs -Wstrict-prototypes -Wtraditional}
|
||||
|
||||
@item Debugging Options
|
||||
@xref{Debugging Options,,Options for Debugging Your Program or GCC}.
|
||||
@ -4246,15 +4246,13 @@ one @option{-I} option, the directories are scanned in left-to-right
|
||||
order; the standard system directories come after.
|
||||
|
||||
If a standard system include directory, or a directory specified with
|
||||
@option{-isystem}, is also specified with @option{-I}, it will be
|
||||
searched only in the position requested by @option{-I}. Also, it will
|
||||
not be considered a system include directory. If that directory really
|
||||
does contain system headers, there is a good chance that they will
|
||||
break. For instance, if GCC's installation procedure edited the headers
|
||||
in @file{/usr/include} to fix bugs, @samp{-I/usr/include} will cause the
|
||||
original, buggy headers to be found instead of the corrected ones. GCC
|
||||
will issue a warning when a system include directory is hidden in this
|
||||
way.
|
||||
@option{-isystem}, is also specified with @option{-I}, the @option{-I}
|
||||
option will be ignored. The directory will still be searched but as a
|
||||
system directory at its normal position in the system include chain.
|
||||
This is to ensure that GCC's procedure to fix buggy system headers and
|
||||
the ordering for the include_next directive are not inadvertantly changed.
|
||||
If you really need to change the search order for system directories,
|
||||
use the @option{-nostdinc} and/or @option{-isystem} options.
|
||||
|
||||
@item -I-
|
||||
@opindex I-
|
||||
|
@ -552,6 +552,7 @@ doloop_modify_runtime (loop, iterations_max,
|
||||
{
|
||||
const struct loop_info *loop_info = LOOP_INFO (loop);
|
||||
HOST_WIDE_INT abs_inc;
|
||||
HOST_WIDE_INT abs_loop_inc;
|
||||
int neg_inc;
|
||||
rtx diff;
|
||||
rtx sequence;
|
||||
@ -591,13 +592,22 @@ doloop_modify_runtime (loop, iterations_max,
|
||||
n = abs (final - initial) / abs_inc;
|
||||
n += (abs (final - initial) % abs_inc) != 0;
|
||||
|
||||
If the loop has been unrolled, then the loop body has been
|
||||
preconditioned to iterate a multiple of unroll_number times. If
|
||||
abs_inc is != 1, the full calculation is
|
||||
But when abs_inc is a power of two, the summation won't overflow
|
||||
except in cases where the loop never terminates. So we don't
|
||||
need to use this more costly calculation.
|
||||
|
||||
t1 = abs_inc * unroll_number;
|
||||
n = abs (final - initial) / t1;
|
||||
n += (abs (final - initial) % t1) > t1 - abs_inc;
|
||||
If the loop has been unrolled, the full calculation is
|
||||
|
||||
t1 = abs_inc * unroll_number; increment per loop
|
||||
n = abs (final - initial) / t1; full loops
|
||||
n += (abs (final - initial) % t1) != 0; partial loop
|
||||
|
||||
However, in certain cases the unrolled loop will be preconditioned
|
||||
by emitting copies of the loop body with conditional branches,
|
||||
so that the unrolled loop is always a full loop and thus needs
|
||||
no exit tests. In this case we don't want to add the partial
|
||||
loop count. As above, when t1 is a power of two we don't need to
|
||||
worry about overflow.
|
||||
|
||||
The division and modulo operations can be avoided by requiring
|
||||
that the increment is a power of 2 (precondition_loop_p enforces
|
||||
@ -658,58 +668,32 @@ doloop_modify_runtime (loop, iterations_max,
|
||||
fprintf (loop_dump_stream,
|
||||
"Doloop: Basic induction var skips initial incr.\n");
|
||||
|
||||
diff = expand_simple_binop (mode, PLUS, diff, increment, diff,
|
||||
unsigned_p, OPTAB_LIB_WIDEN);
|
||||
diff = expand_simple_binop (mode, PLUS, diff, GEN_INT (abs_inc),
|
||||
diff, unsigned_p, OPTAB_LIB_WIDEN);
|
||||
}
|
||||
}
|
||||
|
||||
if (abs_inc * loop_info->unroll_number != 1)
|
||||
abs_loop_inc = abs_inc * loop_info->unroll_number;
|
||||
if (abs_loop_inc != 1)
|
||||
{
|
||||
int shift_count;
|
||||
rtx extra;
|
||||
rtx label;
|
||||
unsigned HOST_WIDE_INT limit;
|
||||
|
||||
shift_count = exact_log2 (abs_inc * loop_info->unroll_number);
|
||||
shift_count = exact_log2 (abs_loop_inc);
|
||||
if (shift_count < 0)
|
||||
abort ();
|
||||
|
||||
/* abs (final - initial) / (abs_inc * unroll_number) */
|
||||
iterations = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
|
||||
diff, GEN_INT (shift_count),
|
||||
NULL_RTX, 1,
|
||||
OPTAB_LIB_WIDEN);
|
||||
if (!loop_info->preconditioned)
|
||||
diff = expand_simple_binop (GET_MODE (diff), PLUS,
|
||||
diff, GEN_INT (abs_loop_inc - 1),
|
||||
diff, 1, OPTAB_LIB_WIDEN);
|
||||
|
||||
if (abs_inc != 1)
|
||||
{
|
||||
/* abs (final - initial) % (abs_inc * unroll_number) */
|
||||
rtx count = GEN_INT (abs_inc * loop_info->unroll_number - 1);
|
||||
extra = expand_simple_binop (GET_MODE (iterations), AND,
|
||||
diff, count, NULL_RTX, 1,
|
||||
OPTAB_LIB_WIDEN);
|
||||
|
||||
/* If (abs (final - initial) % (abs_inc * unroll_number)
|
||||
<= abs_inc * (unroll - 1)),
|
||||
jump past following increment instruction. */
|
||||
label = gen_label_rtx ();
|
||||
limit = abs_inc * (loop_info->unroll_number - 1);
|
||||
emit_cmp_and_jump_insns (extra, GEN_INT (limit),
|
||||
limit == 0 ? EQ : LEU, NULL_RTX,
|
||||
GET_MODE (extra), 0, label);
|
||||
JUMP_LABEL (get_last_insn ()) = label;
|
||||
LABEL_NUSES (label)++;
|
||||
|
||||
/* Increment the iteration count by one. */
|
||||
iterations = expand_simple_binop (GET_MODE (iterations), PLUS,
|
||||
iterations, GEN_INT (1),
|
||||
iterations, 1,
|
||||
OPTAB_LIB_WIDEN);
|
||||
|
||||
emit_label (label);
|
||||
}
|
||||
/* (abs (final - initial) + abs_inc * unroll_number - 1)
|
||||
/ (abs_inc * unroll_number) */
|
||||
diff = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
|
||||
diff, GEN_INT (shift_count),
|
||||
diff, 1, OPTAB_LIB_WIDEN);
|
||||
}
|
||||
else
|
||||
iterations = diff;
|
||||
iterations = diff;
|
||||
|
||||
/* If there is a NOTE_INSN_LOOP_VTOP, we have a `for' or `while'
|
||||
style loop, with a loop exit test at the start. Thus, we can
|
||||
@ -722,17 +706,20 @@ doloop_modify_runtime (loop, iterations_max,
|
||||
iteration count to one if necessary. */
|
||||
if (! loop->vtop)
|
||||
{
|
||||
rtx label;
|
||||
|
||||
if (loop_dump_stream)
|
||||
fprintf (loop_dump_stream, "Doloop: Do-while loop.\n");
|
||||
|
||||
/* A `do-while' loop must iterate at least once. If the
|
||||
iteration count is bogus, we set the iteration count to 1.
|
||||
/* A `do-while' loop must iterate at least once. For code like
|
||||
i = initial; do { ... } while (++i < final);
|
||||
we will calculate a bogus iteration count if initial > final.
|
||||
So detect this and set the iteration count to 1.
|
||||
Note that if the loop has been unrolled, then the loop body
|
||||
is guaranteed to execute at least once. */
|
||||
if (loop_info->unroll_number == 1)
|
||||
is guaranteed to execute at least once. Also, when the
|
||||
comparison is NE, our calculated count will be OK. */
|
||||
if (loop_info->unroll_number == 1 && comparison_code != NE)
|
||||
{
|
||||
rtx label;
|
||||
|
||||
/* Emit insns to test if the loop will immediately
|
||||
terminate and to set the iteration count to 1 if true. */
|
||||
label = gen_label_rtx();
|
||||
|
@ -5434,16 +5434,13 @@ rtx
|
||||
force_operand (value, target)
|
||||
rtx value, target;
|
||||
{
|
||||
optab binoptab = 0;
|
||||
/* Use a temporary to force order of execution of calls to
|
||||
`force_operand'. */
|
||||
rtx tmp;
|
||||
rtx op2;
|
||||
rtx op1, op2;
|
||||
/* Use subtarget as the target for operand 0 of a binary operation. */
|
||||
rtx subtarget = get_subtarget (target);
|
||||
enum rtx_code code = GET_CODE (value);
|
||||
|
||||
/* Check for a PIC address load. */
|
||||
if ((GET_CODE (value) == PLUS || GET_CODE (value) == MINUS)
|
||||
if ((code == PLUS || code == MINUS)
|
||||
&& XEXP (value, 0) == pic_offset_table_rtx
|
||||
&& (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
|
||||
|| GET_CODE (XEXP (value, 1)) == LABEL_REF
|
||||
@ -5455,60 +5452,88 @@ force_operand (value, target)
|
||||
return subtarget;
|
||||
}
|
||||
|
||||
if (GET_CODE (value) == PLUS)
|
||||
binoptab = add_optab;
|
||||
else if (GET_CODE (value) == MINUS)
|
||||
binoptab = sub_optab;
|
||||
else if (GET_CODE (value) == MULT)
|
||||
if (code == ZERO_EXTEND || code == SIGN_EXTEND)
|
||||
{
|
||||
op2 = XEXP (value, 1);
|
||||
if (!CONSTANT_P (op2)
|
||||
&& !(GET_CODE (op2) == REG && op2 != subtarget))
|
||||
subtarget = 0;
|
||||
tmp = force_operand (XEXP (value, 0), subtarget);
|
||||
return expand_mult (GET_MODE (value), tmp,
|
||||
force_operand (op2, NULL_RTX),
|
||||
target, 1);
|
||||
if (!target)
|
||||
target = gen_reg_rtx (GET_MODE (value));
|
||||
convert_move (target, force_operand (XEXP (value, 0), NULL),
|
||||
code == ZERO_EXTEND);
|
||||
return target;
|
||||
}
|
||||
|
||||
if (binoptab)
|
||||
if (GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c')
|
||||
{
|
||||
op2 = XEXP (value, 1);
|
||||
if (!CONSTANT_P (op2)
|
||||
&& !(GET_CODE (op2) == REG && op2 != subtarget))
|
||||
if (!CONSTANT_P (op2) && !(GET_CODE (op2) == REG && op2 != subtarget))
|
||||
subtarget = 0;
|
||||
if (binoptab == sub_optab && GET_CODE (op2) == CONST_INT)
|
||||
if (code == MINUS && GET_CODE (op2) == CONST_INT)
|
||||
{
|
||||
binoptab = add_optab;
|
||||
code = PLUS;
|
||||
op2 = negate_rtx (GET_MODE (value), op2);
|
||||
}
|
||||
|
||||
/* Check for an addition with OP2 a constant integer and our first
|
||||
operand a PLUS of a virtual register and something else. In that
|
||||
case, we want to emit the sum of the virtual register and the
|
||||
constant first and then add the other value. This allows virtual
|
||||
register instantiation to simply modify the constant rather than
|
||||
creating another one around this addition. */
|
||||
if (binoptab == add_optab && GET_CODE (op2) == CONST_INT
|
||||
operand a PLUS of a virtual register and something else. In that
|
||||
case, we want to emit the sum of the virtual register and the
|
||||
constant first and then add the other value. This allows virtual
|
||||
register instantiation to simply modify the constant rather than
|
||||
creating another one around this addition. */
|
||||
if (code == PLUS && GET_CODE (op2) == CONST_INT
|
||||
&& GET_CODE (XEXP (value, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
|
||||
&& REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
|
||||
&& REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
|
||||
{
|
||||
rtx temp = expand_binop (GET_MODE (value), binoptab,
|
||||
XEXP (XEXP (value, 0), 0), op2,
|
||||
subtarget, 0, OPTAB_LIB_WIDEN);
|
||||
return expand_binop (GET_MODE (value), binoptab, temp,
|
||||
force_operand (XEXP (XEXP (value, 0), 1), 0),
|
||||
target, 0, OPTAB_LIB_WIDEN);
|
||||
rtx temp = expand_simple_binop (GET_MODE (value), code,
|
||||
XEXP (XEXP (value, 0), 0), op2,
|
||||
subtarget, 0, OPTAB_LIB_WIDEN);
|
||||
return expand_simple_binop (GET_MODE (value), code, temp,
|
||||
force_operand (XEXP (XEXP (value,
|
||||
0), 1), 0),
|
||||
target, 0, OPTAB_LIB_WIDEN);
|
||||
}
|
||||
|
||||
tmp = force_operand (XEXP (value, 0), subtarget);
|
||||
return expand_binop (GET_MODE (value), binoptab, tmp,
|
||||
force_operand (op2, NULL_RTX),
|
||||
target, 0, OPTAB_LIB_WIDEN);
|
||||
/* We give UNSIGNEDP = 0 to expand_binop
|
||||
because the only operations we are expanding here are signed ones. */
|
||||
op1 = force_operand (XEXP (value, 0), subtarget);
|
||||
op2 = force_operand (op2, NULL_RTX);
|
||||
switch (code)
|
||||
{
|
||||
case MULT:
|
||||
return expand_mult (GET_MODE (value), op1, op2, target, 1);
|
||||
case DIV:
|
||||
if (!INTEGRAL_MODE_P (GET_MODE (value)))
|
||||
return expand_simple_binop (GET_MODE (value), code, op1, op2,
|
||||
target, 1, OPTAB_LIB_WIDEN);
|
||||
else
|
||||
return expand_divmod (0,
|
||||
FLOAT_MODE_P (GET_MODE (value))
|
||||
? RDIV_EXPR : TRUNC_DIV_EXPR,
|
||||
GET_MODE (value), op1, op2, target, 0);
|
||||
break;
|
||||
case MOD:
|
||||
return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
|
||||
target, 0);
|
||||
break;
|
||||
case UDIV:
|
||||
return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2,
|
||||
target, 1);
|
||||
break;
|
||||
case UMOD:
|
||||
return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
|
||||
target, 1);
|
||||
break;
|
||||
case ASHIFTRT:
|
||||
return expand_simple_binop (GET_MODE (value), code, op1, op2,
|
||||
target, 0, OPTAB_LIB_WIDEN);
|
||||
break;
|
||||
default:
|
||||
return expand_simple_binop (GET_MODE (value), code, op1, op2,
|
||||
target, 1, OPTAB_LIB_WIDEN);
|
||||
}
|
||||
}
|
||||
if (GET_RTX_CLASS (code) == '1')
|
||||
{
|
||||
op1 = force_operand (XEXP (value, 0), NULL_RTX);
|
||||
return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
|
||||
}
|
||||
|
||||
#ifdef INSN_SCHEDULING
|
||||
@ -7563,16 +7588,23 @@ expand_expr (exp, target, tmode, modifier)
|
||||
}
|
||||
}
|
||||
|
||||
if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
|
||||
subtarget = 0;
|
||||
|
||||
/* No sense saving up arithmetic to be done
|
||||
if it's all in the wrong mode to form part of an address.
|
||||
And force_operand won't know whether to sign-extend or
|
||||
zero-extend. */
|
||||
if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
|
||||
|| mode != ptr_mode)
|
||||
goto binop;
|
||||
|
||||
if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
|
||||
subtarget = 0;
|
||||
{
|
||||
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
|
||||
op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
|
||||
temp = simplify_binary_operation (PLUS, mode, op0, op1);
|
||||
if (temp)
|
||||
return temp;
|
||||
goto binop2;
|
||||
}
|
||||
|
||||
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
|
||||
op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "ansidecl.h"
|
||||
#include "f/version.h"
|
||||
|
||||
const char *const ffe_version_string = "3.2.1 20020916 (prerelease)";
|
||||
const char *const ffe_version_string = "3.2.1 20021009 (prerelease)";
|
||||
|
@ -63,6 +63,14 @@
|
||||
# for the rule to exclude a set. Options can be preceded with a '!' to
|
||||
# match a logical NOT.
|
||||
|
||||
# The optional sevenths argument is a list of OS subdirectory names.
|
||||
# The format is the same as of the second argument.
|
||||
# The difference is that second argument describes multilib directories
|
||||
# in GCC conventions, while this one the OS multilib convention.
|
||||
|
||||
# The last option should be "yes" if multilibs are enabled. If it is not
|
||||
# "yes", all GCC multilib dir names will be ".".
|
||||
|
||||
# The output looks like
|
||||
# #define MULTILIB_MATCHES "\
|
||||
# SUBDIRECTORY OPTIONS;\
|
||||
@ -79,17 +87,18 @@
|
||||
# Here is an example (this is from the actual sparc64 case):
|
||||
# genmultilib 'm64/m32 mno-app-regs|mcmodel=medany' '64 32 alt'
|
||||
# 'mcmodel?medany=mcmodel?medmid' 'm32/mno-app-regs* m32/mcmodel=*'
|
||||
# 'm32/!m64/mno-app-regs m32/!m64/mcmodel=medany'
|
||||
# '' 'm32/!m64/mno-app-regs m32/!m64/mcmodel=medany'
|
||||
# '../lib64 ../lib32 alt' yes
|
||||
# This produces:
|
||||
# ". !m64 !m32 !mno-app-regs !mcmodel=medany;",
|
||||
# "64 m64 !m32 !mno-app-regs !mcmodel=medany;",
|
||||
# "32 !m64 m32 !mno-app-regs !mcmodel=medany;",
|
||||
# "64:../lib64 m64 !m32 !mno-app-regs !mcmodel=medany;",
|
||||
# "32:../lib32 !m64 m32 !mno-app-regs !mcmodel=medany;",
|
||||
# "alt !m64 !m32 mno-app-regs mcmodel=medany;",
|
||||
# "alt !m64 !m32 mno-app-regs !mcmodel=medany;",
|
||||
# "alt !m64 !m32 !mno-app-regs mcmodel=medany;",
|
||||
# "64/alt m64 !m32 mno-app-regs mcmodel=medany;",
|
||||
# "64/alt m64 !m32 mno-app-regs !mcmodel=medany;",
|
||||
# "64/alt m64 !m32 !mno-app-regs mcmodel=medany;",
|
||||
# "64/alt:../lib64/alt m64 !m32 mno-app-regs mcmodel=medany;",
|
||||
# "64/alt:../lib64/alt m64 !m32 mno-app-regs !mcmodel=medany;",
|
||||
# "64/alt:../lib64/alt m64 !m32 !mno-app-regs mcmodel=medany;",
|
||||
#
|
||||
# The effect is that `gcc -mno-app-regs' (for example) will append "alt"
|
||||
# to the directory name when searching for libraries or startup files and
|
||||
@ -106,6 +115,8 @@ matches=$3
|
||||
exceptions=$4
|
||||
extra=$5
|
||||
exclusions=$6
|
||||
osdirnames=$7
|
||||
enable_multilib=$8
|
||||
|
||||
echo "static const char *const multilib_raw[] = {"
|
||||
|
||||
@ -202,6 +213,29 @@ if [ -n "${dirnames}" ]; then
|
||||
done
|
||||
fi
|
||||
|
||||
# Construct a sed pattern which will convert option names to OS directory
|
||||
# names.
|
||||
toosdirnames=
|
||||
if [ -n "${osdirnames}" ]; then
|
||||
set x ${osdirnames}
|
||||
shift
|
||||
for set in ${options}; do
|
||||
for opts in `echo ${set} | sed -e 's|/| |'g`; do
|
||||
patt="/"
|
||||
for opt in `echo ${opts} | sed -e 's_|_ _'g`; do
|
||||
if [ "$1" != "${opt}" ]; then
|
||||
toosdirnames="${toosdirnames} -e s|/${opt}/|/${1}/|g"
|
||||
patt="${patt}${1}/"
|
||||
if [ "${patt}" != "/${1}/" ]; then
|
||||
toosdirnames="${toosdirnames} -e s|${patt}|/${1}/|g"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
shift
|
||||
done
|
||||
done
|
||||
fi
|
||||
|
||||
# We need another recursive shell script to correctly handle positive
|
||||
# matches. If we are invoked as
|
||||
# genmultilib "opt1 opt2" "" "opt1=nopt1 opt2=nopt2"
|
||||
@ -257,6 +291,25 @@ for combo in ${combinations}; do
|
||||
# Remove the leading and trailing slashes.
|
||||
dirout=`echo ${dirout} | sed -e 's|^/||' -e 's|/$||g'`
|
||||
|
||||
# Use the OS directory names rather than the option names.
|
||||
if [ -n "${toosdirnames}" ]; then
|
||||
osdirout=`echo ${combo} | sed ${toosdirnames}`
|
||||
# Remove the leading and trailing slashes.
|
||||
osdirout=`echo ${osdirout} | sed -e 's|^/||' -e 's|/$||g'`
|
||||
if [ "x${enable_multilib}" != xyes ]; then
|
||||
dirout=".:${osdirout}"
|
||||
else
|
||||
dirout="${dirout}:${osdirout}"
|
||||
fi
|
||||
else
|
||||
if [ "x${enable_multilib}" != xyes ]; then
|
||||
# genmultilib with --disable-multilib should be
|
||||
# called with '' '' '' '' '' '' '' no
|
||||
# if MULTILIB_OSDIRNAMES is empty.
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Look through the options. We must output each option that is
|
||||
# present, and negate each option that is not present.
|
||||
optout=
|
||||
@ -313,6 +366,11 @@ done
|
||||
echo "NULL"
|
||||
echo "};"
|
||||
|
||||
# Output the options now
|
||||
moptions=`echo ${options} | sed -e 's,[ ][ ]*, ,g'`
|
||||
echo ""
|
||||
echo "static const char *multilib_options = \"${moptions}\";"
|
||||
|
||||
rm -f tmpmultilib2
|
||||
|
||||
exit 0
|
||||
|
@ -2428,3 +2428,15 @@ true_regnum (x)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return regno of the register REG and handle subregs too. */
|
||||
unsigned int
|
||||
reg_or_subregno (reg)
|
||||
rtx reg;
|
||||
{
|
||||
if (REG_P (reg))
|
||||
return REGNO (reg);
|
||||
if (GET_CODE (reg) == SUBREG)
|
||||
return REGNO (SUBREG_REG (reg));
|
||||
abort ();
|
||||
}
|
||||
|
@ -640,6 +640,7 @@ scan_loop (loop, flags)
|
||||
int threshold;
|
||||
/* Nonzero if we are scanning instructions in a sub-loop. */
|
||||
int loop_depth = 0;
|
||||
int in_libcall;
|
||||
|
||||
loop->top = 0;
|
||||
|
||||
@ -756,290 +757,311 @@ scan_loop (loop, flags)
|
||||
When MAYBE_NEVER is 0, all insns will be executed at least once
|
||||
so that is not a problem. */
|
||||
|
||||
for (p = next_insn_in_loop (loop, loop->scan_start);
|
||||
for (in_libcall = 0, p = next_insn_in_loop (loop, loop->scan_start);
|
||||
p != NULL_RTX;
|
||||
p = next_insn_in_loop (loop, p))
|
||||
{
|
||||
if (GET_CODE (p) == INSN
|
||||
&& (set = single_set (p))
|
||||
&& GET_CODE (SET_DEST (set)) == REG
|
||||
#ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
|
||||
&& SET_DEST (set) != pic_offset_table_rtx
|
||||
#endif
|
||||
&& ! regs->array[REGNO (SET_DEST (set))].may_not_optimize)
|
||||
if (in_libcall && INSN_P (p) && find_reg_note (p, REG_RETVAL, NULL_RTX))
|
||||
in_libcall--;
|
||||
if (GET_CODE (p) == INSN)
|
||||
{
|
||||
int tem1 = 0;
|
||||
int tem2 = 0;
|
||||
int move_insn = 0;
|
||||
rtx src = SET_SRC (set);
|
||||
rtx dependencies = 0;
|
||||
|
||||
/* Figure out what to use as a source of this insn. If a REG_EQUIV
|
||||
note is given or if a REG_EQUAL note with a constant operand is
|
||||
specified, use it as the source and mark that we should move
|
||||
this insn by calling emit_move_insn rather that duplicating the
|
||||
insn.
|
||||
|
||||
Otherwise, only use the REG_EQUAL contents if a REG_RETVAL note
|
||||
is present. */
|
||||
temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
|
||||
temp = find_reg_note (p, REG_LIBCALL, NULL_RTX);
|
||||
if (temp)
|
||||
src = XEXP (temp, 0), move_insn = 1;
|
||||
else
|
||||
in_libcall++;
|
||||
if (! in_libcall
|
||||
&& (set = single_set (p))
|
||||
&& GET_CODE (SET_DEST (set)) == REG
|
||||
#ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
|
||||
&& SET_DEST (set) != pic_offset_table_rtx
|
||||
#endif
|
||||
&& ! regs->array[REGNO (SET_DEST (set))].may_not_optimize)
|
||||
{
|
||||
temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
|
||||
if (temp && CONSTANT_P (XEXP (temp, 0)))
|
||||
int tem1 = 0;
|
||||
int tem2 = 0;
|
||||
int move_insn = 0;
|
||||
rtx src = SET_SRC (set);
|
||||
rtx dependencies = 0;
|
||||
|
||||
/* Figure out what to use as a source of this insn. If a
|
||||
REG_EQUIV note is given or if a REG_EQUAL note with a
|
||||
constant operand is specified, use it as the source and
|
||||
mark that we should move this insn by calling
|
||||
emit_move_insn rather that duplicating the insn.
|
||||
|
||||
Otherwise, only use the REG_EQUAL contents if a REG_RETVAL
|
||||
note is present. */
|
||||
temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
|
||||
if (temp)
|
||||
src = XEXP (temp, 0), move_insn = 1;
|
||||
if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX))
|
||||
else
|
||||
{
|
||||
src = XEXP (temp, 0);
|
||||
/* A libcall block can use regs that don't appear in
|
||||
the equivalent expression. To move the libcall,
|
||||
we must move those regs too. */
|
||||
dependencies = libcall_other_reg (p, src);
|
||||
}
|
||||
}
|
||||
|
||||
/* For parallels, add any possible uses to the depencies, as we can't move
|
||||
the insn without resolving them first. */
|
||||
if (GET_CODE (PATTERN (p)) == PARALLEL)
|
||||
{
|
||||
for (i = 0; i < XVECLEN (PATTERN (p), 0); i++)
|
||||
{
|
||||
rtx x = XVECEXP (PATTERN (p), 0, i);
|
||||
if (GET_CODE (x) == USE)
|
||||
dependencies = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0), dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't try to optimize a register that was made
|
||||
by loop-optimization for an inner loop.
|
||||
We don't know its life-span, so we can't compute the benefit. */
|
||||
if (REGNO (SET_DEST (set)) >= max_reg_before_loop)
|
||||
;
|
||||
else if (/* The register is used in basic blocks other
|
||||
than the one where it is set (meaning that
|
||||
something after this point in the loop might
|
||||
depend on its value before the set). */
|
||||
! reg_in_basic_block_p (p, SET_DEST (set))
|
||||
/* And the set is not guaranteed to be executed once
|
||||
the loop starts, or the value before the set is
|
||||
needed before the set occurs...
|
||||
|
||||
??? Note we have quadratic behaviour here, mitigated
|
||||
by the fact that the previous test will often fail for
|
||||
large loops. Rather than re-scanning the entire loop
|
||||
each time for register usage, we should build tables
|
||||
of the register usage and use them here instead. */
|
||||
&& (maybe_never
|
||||
|| loop_reg_used_before_p (loop, set, p)))
|
||||
/* It is unsafe to move the set.
|
||||
|
||||
This code used to consider it OK to move a set of a variable
|
||||
which was not created by the user and not used in an exit test.
|
||||
That behavior is incorrect and was removed. */
|
||||
;
|
||||
else if ((tem = loop_invariant_p (loop, src))
|
||||
&& (dependencies == 0
|
||||
|| (tem2 = loop_invariant_p (loop, dependencies)) != 0)
|
||||
&& (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1
|
||||
|| (tem1
|
||||
= consec_sets_invariant_p
|
||||
(loop, SET_DEST (set),
|
||||
regs->array[REGNO (SET_DEST (set))].set_in_loop,
|
||||
p)))
|
||||
/* If the insn can cause a trap (such as divide by zero),
|
||||
can't move it unless it's guaranteed to be executed
|
||||
once loop is entered. Even a function call might
|
||||
prevent the trap insn from being reached
|
||||
(since it might exit!) */
|
||||
&& ! ((maybe_never || call_passed)
|
||||
&& may_trap_p (src)))
|
||||
{
|
||||
struct movable *m;
|
||||
int regno = REGNO (SET_DEST (set));
|
||||
|
||||
/* A potential lossage is where we have a case where two insns
|
||||
can be combined as long as they are both in the loop, but
|
||||
we move one of them outside the loop. For large loops,
|
||||
this can lose. The most common case of this is the address
|
||||
of a function being called.
|
||||
|
||||
Therefore, if this register is marked as being used exactly
|
||||
once if we are in a loop with calls (a "large loop"), see if
|
||||
we can replace the usage of this register with the source
|
||||
of this SET. If we can, delete this insn.
|
||||
|
||||
Don't do this if P has a REG_RETVAL note or if we have
|
||||
SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */
|
||||
|
||||
if (loop_info->has_call
|
||||
&& regs->array[regno].single_usage != 0
|
||||
&& regs->array[regno].single_usage != const0_rtx
|
||||
&& REGNO_FIRST_UID (regno) == INSN_UID (p)
|
||||
&& (REGNO_LAST_UID (regno)
|
||||
== INSN_UID (regs->array[regno].single_usage))
|
||||
&& regs->array[regno].set_in_loop == 1
|
||||
&& GET_CODE (SET_SRC (set)) != ASM_OPERANDS
|
||||
&& ! side_effects_p (SET_SRC (set))
|
||||
&& ! find_reg_note (p, REG_RETVAL, NULL_RTX)
|
||||
&& (! SMALL_REGISTER_CLASSES
|
||||
|| (! (GET_CODE (SET_SRC (set)) == REG
|
||||
&& REGNO (SET_SRC (set)) < FIRST_PSEUDO_REGISTER)))
|
||||
/* This test is not redundant; SET_SRC (set) might be
|
||||
a call-clobbered register and the life of REGNO
|
||||
might span a call. */
|
||||
&& ! modified_between_p (SET_SRC (set), p,
|
||||
regs->array[regno].single_usage)
|
||||
&& no_labels_between_p (p, regs->array[regno].single_usage)
|
||||
&& validate_replace_rtx (SET_DEST (set), SET_SRC (set),
|
||||
regs->array[regno].single_usage))
|
||||
{
|
||||
/* Replace any usage in a REG_EQUAL note. Must copy the
|
||||
new source, so that we don't get rtx sharing between the
|
||||
SET_SOURCE and REG_NOTES of insn p. */
|
||||
REG_NOTES (regs->array[regno].single_usage)
|
||||
= replace_rtx (REG_NOTES (regs->array[regno].single_usage),
|
||||
SET_DEST (set), copy_rtx (SET_SRC (set)));
|
||||
|
||||
delete_insn (p);
|
||||
for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
|
||||
regs->array[regno+i].set_in_loop = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
m = (struct movable *) xmalloc (sizeof (struct movable));
|
||||
m->next = 0;
|
||||
m->insn = p;
|
||||
m->set_src = src;
|
||||
m->dependencies = dependencies;
|
||||
m->set_dest = SET_DEST (set);
|
||||
m->force = 0;
|
||||
m->consec = regs->array[REGNO (SET_DEST (set))].set_in_loop - 1;
|
||||
m->done = 0;
|
||||
m->forces = 0;
|
||||
m->partial = 0;
|
||||
m->move_insn = move_insn;
|
||||
m->move_insn_first = 0;
|
||||
m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
|
||||
m->savemode = VOIDmode;
|
||||
m->regno = regno;
|
||||
/* Set M->cond if either loop_invariant_p
|
||||
or consec_sets_invariant_p returned 2
|
||||
(only conditionally invariant). */
|
||||
m->cond = ((tem | tem1 | tem2) > 1);
|
||||
m->global = LOOP_REG_GLOBAL_P (loop, regno);
|
||||
m->match = 0;
|
||||
m->lifetime = LOOP_REG_LIFETIME (loop, regno);
|
||||
m->savings = regs->array[regno].n_times_set;
|
||||
if (find_reg_note (p, REG_RETVAL, NULL_RTX))
|
||||
m->savings += libcall_benefit (p);
|
||||
for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
|
||||
regs->array[regno+i].set_in_loop = move_insn ? -2 : -1;
|
||||
/* Add M to the end of the chain MOVABLES. */
|
||||
loop_movables_add (movables, m);
|
||||
|
||||
if (m->consec > 0)
|
||||
{
|
||||
/* It is possible for the first instruction to have a
|
||||
REG_EQUAL note but a non-invariant SET_SRC, so we must
|
||||
remember the status of the first instruction in case
|
||||
the last instruction doesn't have a REG_EQUAL note. */
|
||||
m->move_insn_first = m->move_insn;
|
||||
|
||||
/* Skip this insn, not checking REG_LIBCALL notes. */
|
||||
p = next_nonnote_insn (p);
|
||||
/* Skip the consecutive insns, if there are any. */
|
||||
p = skip_consec_insns (p, m->consec);
|
||||
/* Back up to the last insn of the consecutive group. */
|
||||
p = prev_nonnote_insn (p);
|
||||
|
||||
/* We must now reset m->move_insn, m->is_equiv, and possibly
|
||||
m->set_src to correspond to the effects of all the
|
||||
insns. */
|
||||
temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
|
||||
if (temp)
|
||||
m->set_src = XEXP (temp, 0), m->move_insn = 1;
|
||||
else
|
||||
temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
|
||||
if (temp && CONSTANT_P (XEXP (temp, 0)))
|
||||
src = XEXP (temp, 0), move_insn = 1;
|
||||
if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX))
|
||||
{
|
||||
temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
|
||||
if (temp && CONSTANT_P (XEXP (temp, 0)))
|
||||
m->set_src = XEXP (temp, 0), m->move_insn = 1;
|
||||
else
|
||||
m->move_insn = 0;
|
||||
|
||||
src = XEXP (temp, 0);
|
||||
/* A libcall block can use regs that don't appear in
|
||||
the equivalent expression. To move the libcall,
|
||||
we must move those regs too. */
|
||||
dependencies = libcall_other_reg (p, src);
|
||||
}
|
||||
m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
|
||||
}
|
||||
}
|
||||
/* If this register is always set within a STRICT_LOW_PART
|
||||
or set to zero, then its high bytes are constant.
|
||||
So clear them outside the loop and within the loop
|
||||
just load the low bytes.
|
||||
We must check that the machine has an instruction to do so.
|
||||
Also, if the value loaded into the register
|
||||
depends on the same register, this cannot be done. */
|
||||
else if (SET_SRC (set) == const0_rtx
|
||||
&& GET_CODE (NEXT_INSN (p)) == INSN
|
||||
&& (set1 = single_set (NEXT_INSN (p)))
|
||||
&& GET_CODE (set1) == SET
|
||||
&& (GET_CODE (SET_DEST (set1)) == STRICT_LOW_PART)
|
||||
&& (GET_CODE (XEXP (SET_DEST (set1), 0)) == SUBREG)
|
||||
&& (SUBREG_REG (XEXP (SET_DEST (set1), 0))
|
||||
== SET_DEST (set))
|
||||
&& !reg_mentioned_p (SET_DEST (set), SET_SRC (set1)))
|
||||
{
|
||||
int regno = REGNO (SET_DEST (set));
|
||||
if (regs->array[regno].set_in_loop == 2)
|
||||
|
||||
/* For parallels, add any possible uses to the depencies, as
|
||||
we can't move the insn without resolving them first. */
|
||||
if (GET_CODE (PATTERN (p)) == PARALLEL)
|
||||
{
|
||||
for (i = 0; i < XVECLEN (PATTERN (p), 0); i++)
|
||||
{
|
||||
rtx x = XVECEXP (PATTERN (p), 0, i);
|
||||
if (GET_CODE (x) == USE)
|
||||
dependencies
|
||||
= gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0),
|
||||
dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't try to optimize a register that was made
|
||||
by loop-optimization for an inner loop.
|
||||
We don't know its life-span, so we can't compute
|
||||
the benefit. */
|
||||
if (REGNO (SET_DEST (set)) >= max_reg_before_loop)
|
||||
;
|
||||
else if (/* The register is used in basic blocks other
|
||||
than the one where it is set (meaning that
|
||||
something after this point in the loop might
|
||||
depend on its value before the set). */
|
||||
! reg_in_basic_block_p (p, SET_DEST (set))
|
||||
/* And the set is not guaranteed to be executed once
|
||||
the loop starts, or the value before the set is
|
||||
needed before the set occurs...
|
||||
|
||||
??? Note we have quadratic behaviour here, mitigated
|
||||
by the fact that the previous test will often fail for
|
||||
large loops. Rather than re-scanning the entire loop
|
||||
each time for register usage, we should build tables
|
||||
of the register usage and use them here instead. */
|
||||
&& (maybe_never
|
||||
|| loop_reg_used_before_p (loop, set, p)))
|
||||
/* It is unsafe to move the set.
|
||||
|
||||
This code used to consider it OK to move a set of a variable
|
||||
which was not created by the user and not used in an exit
|
||||
test.
|
||||
That behavior is incorrect and was removed. */
|
||||
;
|
||||
else if ((tem = loop_invariant_p (loop, src))
|
||||
&& (dependencies == 0
|
||||
|| (tem2
|
||||
= loop_invariant_p (loop, dependencies)) != 0)
|
||||
&& (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1
|
||||
|| (tem1
|
||||
= consec_sets_invariant_p
|
||||
(loop, SET_DEST (set),
|
||||
regs->array[REGNO (SET_DEST (set))].set_in_loop,
|
||||
p)))
|
||||
/* If the insn can cause a trap (such as divide by zero),
|
||||
can't move it unless it's guaranteed to be executed
|
||||
once loop is entered. Even a function call might
|
||||
prevent the trap insn from being reached
|
||||
(since it might exit!) */
|
||||
&& ! ((maybe_never || call_passed)
|
||||
&& may_trap_p (src)))
|
||||
{
|
||||
struct movable *m;
|
||||
int regno = REGNO (SET_DEST (set));
|
||||
|
||||
/* A potential lossage is where we have a case where two insns
|
||||
can be combined as long as they are both in the loop, but
|
||||
we move one of them outside the loop. For large loops,
|
||||
this can lose. The most common case of this is the address
|
||||
of a function being called.
|
||||
|
||||
Therefore, if this register is marked as being used
|
||||
exactly once if we are in a loop with calls
|
||||
(a "large loop"), see if we can replace the usage of
|
||||
this register with the source of this SET. If we can,
|
||||
delete this insn.
|
||||
|
||||
Don't do this if P has a REG_RETVAL note or if we have
|
||||
SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */
|
||||
|
||||
if (loop_info->has_call
|
||||
&& regs->array[regno].single_usage != 0
|
||||
&& regs->array[regno].single_usage != const0_rtx
|
||||
&& REGNO_FIRST_UID (regno) == INSN_UID (p)
|
||||
&& (REGNO_LAST_UID (regno)
|
||||
== INSN_UID (regs->array[regno].single_usage))
|
||||
&& regs->array[regno].set_in_loop == 1
|
||||
&& GET_CODE (SET_SRC (set)) != ASM_OPERANDS
|
||||
&& ! side_effects_p (SET_SRC (set))
|
||||
&& ! find_reg_note (p, REG_RETVAL, NULL_RTX)
|
||||
&& (! SMALL_REGISTER_CLASSES
|
||||
|| (! (GET_CODE (SET_SRC (set)) == REG
|
||||
&& (REGNO (SET_SRC (set))
|
||||
< FIRST_PSEUDO_REGISTER))))
|
||||
/* This test is not redundant; SET_SRC (set) might be
|
||||
a call-clobbered register and the life of REGNO
|
||||
might span a call. */
|
||||
&& ! modified_between_p (SET_SRC (set), p,
|
||||
regs->array[regno].single_usage)
|
||||
&& no_labels_between_p (p,
|
||||
regs->array[regno].single_usage)
|
||||
&& validate_replace_rtx (SET_DEST (set), SET_SRC (set),
|
||||
regs->array[regno].single_usage))
|
||||
{
|
||||
/* Replace any usage in a REG_EQUAL note. Must copy
|
||||
the new source, so that we don't get rtx sharing
|
||||
between the SET_SOURCE and REG_NOTES of insn p. */
|
||||
REG_NOTES (regs->array[regno].single_usage)
|
||||
= (replace_rtx
|
||||
(REG_NOTES (regs->array[regno].single_usage),
|
||||
SET_DEST (set), copy_rtx (SET_SRC (set))));
|
||||
|
||||
delete_insn (p);
|
||||
for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set));
|
||||
i++)
|
||||
regs->array[regno+i].set_in_loop = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
m = (struct movable *) xmalloc (sizeof (struct movable));
|
||||
m->next = 0;
|
||||
m->insn = p;
|
||||
m->set_src = src;
|
||||
m->dependencies = dependencies;
|
||||
m->set_dest = SET_DEST (set);
|
||||
m->dependencies = 0;
|
||||
m->force = 0;
|
||||
m->consec = 0;
|
||||
m->consec
|
||||
= regs->array[REGNO (SET_DEST (set))].set_in_loop - 1;
|
||||
m->done = 0;
|
||||
m->forces = 0;
|
||||
m->move_insn = 0;
|
||||
m->partial = 0;
|
||||
m->move_insn = move_insn;
|
||||
m->move_insn_first = 0;
|
||||
m->partial = 1;
|
||||
/* If the insn may not be executed on some cycles,
|
||||
we can't clear the whole reg; clear just high part.
|
||||
Not even if the reg is used only within this loop.
|
||||
Consider this:
|
||||
while (1)
|
||||
while (s != t) {
|
||||
if (foo ()) x = *s;
|
||||
use (x);
|
||||
}
|
||||
Clearing x before the inner loop could clobber a value
|
||||
being saved from the last time around the outer loop.
|
||||
However, if the reg is not used outside this loop
|
||||
and all uses of the register are in the same
|
||||
basic block as the store, there is no problem.
|
||||
|
||||
If this insn was made by loop, we don't know its
|
||||
INSN_LUID and hence must make a conservative
|
||||
assumption. */
|
||||
m->global = (INSN_UID (p) >= max_uid_for_loop
|
||||
|| LOOP_REG_GLOBAL_P (loop, regno)
|
||||
|| (labels_in_range_p
|
||||
(p, REGNO_FIRST_LUID (regno))));
|
||||
if (maybe_never && m->global)
|
||||
m->savemode = GET_MODE (SET_SRC (set1));
|
||||
else
|
||||
m->savemode = VOIDmode;
|
||||
m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
|
||||
m->savemode = VOIDmode;
|
||||
m->regno = regno;
|
||||
m->cond = 0;
|
||||
/* Set M->cond if either loop_invariant_p
|
||||
or consec_sets_invariant_p returned 2
|
||||
(only conditionally invariant). */
|
||||
m->cond = ((tem | tem1 | tem2) > 1);
|
||||
m->global = LOOP_REG_GLOBAL_P (loop, regno);
|
||||
m->match = 0;
|
||||
m->lifetime = LOOP_REG_LIFETIME (loop, regno);
|
||||
m->savings = 1;
|
||||
m->savings = regs->array[regno].n_times_set;
|
||||
if (find_reg_note (p, REG_RETVAL, NULL_RTX))
|
||||
m->savings += libcall_benefit (p);
|
||||
for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
|
||||
regs->array[regno+i].set_in_loop = -1;
|
||||
regs->array[regno+i].set_in_loop = move_insn ? -2 : -1;
|
||||
/* Add M to the end of the chain MOVABLES. */
|
||||
loop_movables_add (movables, m);
|
||||
|
||||
if (m->consec > 0)
|
||||
{
|
||||
/* It is possible for the first instruction to have a
|
||||
REG_EQUAL note but a non-invariant SET_SRC, so we must
|
||||
remember the status of the first instruction in case
|
||||
the last instruction doesn't have a REG_EQUAL note. */
|
||||
m->move_insn_first = m->move_insn;
|
||||
|
||||
/* Skip this insn, not checking REG_LIBCALL notes. */
|
||||
p = next_nonnote_insn (p);
|
||||
/* Skip the consecutive insns, if there are any. */
|
||||
p = skip_consec_insns (p, m->consec);
|
||||
/* Back up to the last insn of the consecutive group. */
|
||||
p = prev_nonnote_insn (p);
|
||||
|
||||
/* We must now reset m->move_insn, m->is_equiv, and
|
||||
possibly m->set_src to correspond to the effects of
|
||||
all the insns. */
|
||||
temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
|
||||
if (temp)
|
||||
m->set_src = XEXP (temp, 0), m->move_insn = 1;
|
||||
else
|
||||
{
|
||||
temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
|
||||
if (temp && CONSTANT_P (XEXP (temp, 0)))
|
||||
m->set_src = XEXP (temp, 0), m->move_insn = 1;
|
||||
else
|
||||
m->move_insn = 0;
|
||||
|
||||
}
|
||||
m->is_equiv
|
||||
= (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
|
||||
}
|
||||
}
|
||||
/* If this register is always set within a STRICT_LOW_PART
|
||||
or set to zero, then its high bytes are constant.
|
||||
So clear them outside the loop and within the loop
|
||||
just load the low bytes.
|
||||
We must check that the machine has an instruction to do so.
|
||||
Also, if the value loaded into the register
|
||||
depends on the same register, this cannot be done. */
|
||||
else if (SET_SRC (set) == const0_rtx
|
||||
&& GET_CODE (NEXT_INSN (p)) == INSN
|
||||
&& (set1 = single_set (NEXT_INSN (p)))
|
||||
&& GET_CODE (set1) == SET
|
||||
&& (GET_CODE (SET_DEST (set1)) == STRICT_LOW_PART)
|
||||
&& (GET_CODE (XEXP (SET_DEST (set1), 0)) == SUBREG)
|
||||
&& (SUBREG_REG (XEXP (SET_DEST (set1), 0))
|
||||
== SET_DEST (set))
|
||||
&& !reg_mentioned_p (SET_DEST (set), SET_SRC (set1)))
|
||||
{
|
||||
int regno = REGNO (SET_DEST (set));
|
||||
if (regs->array[regno].set_in_loop == 2)
|
||||
{
|
||||
struct movable *m;
|
||||
m = (struct movable *) xmalloc (sizeof (struct movable));
|
||||
m->next = 0;
|
||||
m->insn = p;
|
||||
m->set_dest = SET_DEST (set);
|
||||
m->dependencies = 0;
|
||||
m->force = 0;
|
||||
m->consec = 0;
|
||||
m->done = 0;
|
||||
m->forces = 0;
|
||||
m->move_insn = 0;
|
||||
m->move_insn_first = 0;
|
||||
m->partial = 1;
|
||||
/* If the insn may not be executed on some cycles,
|
||||
we can't clear the whole reg; clear just high part.
|
||||
Not even if the reg is used only within this loop.
|
||||
Consider this:
|
||||
while (1)
|
||||
while (s != t) {
|
||||
if (foo ()) x = *s;
|
||||
use (x);
|
||||
}
|
||||
Clearing x before the inner loop could clobber a value
|
||||
being saved from the last time around the outer loop.
|
||||
However, if the reg is not used outside this loop
|
||||
and all uses of the register are in the same
|
||||
basic block as the store, there is no problem.
|
||||
|
||||
If this insn was made by loop, we don't know its
|
||||
INSN_LUID and hence must make a conservative
|
||||
assumption. */
|
||||
m->global = (INSN_UID (p) >= max_uid_for_loop
|
||||
|| LOOP_REG_GLOBAL_P (loop, regno)
|
||||
|| (labels_in_range_p
|
||||
(p, REGNO_FIRST_LUID (regno))));
|
||||
if (maybe_never && m->global)
|
||||
m->savemode = GET_MODE (SET_SRC (set1));
|
||||
else
|
||||
m->savemode = VOIDmode;
|
||||
m->regno = regno;
|
||||
m->cond = 0;
|
||||
m->match = 0;
|
||||
m->lifetime = LOOP_REG_LIFETIME (loop, regno);
|
||||
m->savings = 1;
|
||||
for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set));
|
||||
i++)
|
||||
regs->array[regno+i].set_in_loop = -1;
|
||||
/* Add M to the end of the chain MOVABLES. */
|
||||
loop_movables_add (movables, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1911,10 +1933,10 @@ move_movables (loop, movables, threshold, insn_count)
|
||||
for (count = m->consec; count >= 0; count--)
|
||||
{
|
||||
/* If this is the first insn of a library call sequence,
|
||||
skip to the end. */
|
||||
something is very wrong. */
|
||||
if (GET_CODE (p) != NOTE
|
||||
&& (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
|
||||
p = XEXP (temp, 0);
|
||||
abort ();
|
||||
|
||||
/* If this is the last insn of a libcall sequence, then
|
||||
delete every insn in the sequence except the last.
|
||||
@ -4090,11 +4112,17 @@ emit_prefetch_instructions (loop)
|
||||
{
|
||||
rtx reg = gen_reg_rtx (Pmode);
|
||||
rtx loop_start = loop->start;
|
||||
rtx init_val = info[i].class->initial_value;
|
||||
rtx add_val = simplify_gen_binary (PLUS, Pmode,
|
||||
info[i].giv->add_val,
|
||||
GEN_INT (y * PREFETCH_BLOCK));
|
||||
|
||||
loop_iv_add_mult_emit_before (loop, info[i].class->initial_value,
|
||||
/* Functions called by LOOP_IV_ADD_EMIT_BEFORE expect a
|
||||
non-constant INIT_VAL to have the same mode as REG, which
|
||||
in this case we know to be Pmode. */
|
||||
if (GET_MODE (init_val) != Pmode && !CONSTANT_P (init_val))
|
||||
init_val = convert_to_mode (Pmode, init_val, 0);
|
||||
loop_iv_add_mult_emit_before (loop, init_val,
|
||||
info[i].giv->mult_val,
|
||||
add_val, reg, 0, loop_start);
|
||||
emit_insn_before (gen_prefetch (reg, GEN_INT (info[i].write),
|
||||
|
@ -314,6 +314,9 @@ struct loop_info
|
||||
int has_multiple_exit_targets;
|
||||
/* Nonzero if there is an indirect jump in the current function. */
|
||||
int has_indirect_jump;
|
||||
/* Whether loop unrolling has emitted copies of the loop body so
|
||||
that the main loop needs no exit tests. */
|
||||
int preconditioned;
|
||||
/* Register or constant initial loop value. */
|
||||
rtx initial_value;
|
||||
/* Register or constant value used for comparison test. */
|
||||
|
@ -32,7 +32,7 @@
|
||||
# SHLIB_MAPFILES
|
||||
# SHLIB_NM_FLAGS
|
||||
# SHLIB_INSTALL
|
||||
# SHLIB_SLIBDIR_SUFFIXES
|
||||
# MULTILIB_OSDIRNAMES
|
||||
|
||||
# Make needs VPATH to be literal.
|
||||
echo 'srcdir = @srcdir@'
|
||||
@ -317,22 +317,18 @@ for ml in $MULTILIBS; do
|
||||
fi
|
||||
shlib_so_name="$shlib_base_name"
|
||||
shlib_dir=
|
||||
if [ -n "$SHLIB_SLIBDIR_SUFFIXES" ]; then
|
||||
if [ -n "$MULTILIB_OSDIRNAMES" ]; then
|
||||
if [ "$dir" != . ]; then
|
||||
gcc_multilib_dir=`./xgcc -B./ $flags --print-multi-directory`
|
||||
os_multilib_dir=`./xgcc -B./ $flags --print-multi-os-directory`
|
||||
shlib_dir="$dir"/
|
||||
for suffix_pair in $SHLIB_SLIBDIR_SUFFIXES ; do
|
||||
base_ml_dir=`echo ${suffix_pair} | sed -e 's/:.*$//' -e 's/=/$(EQ)/g'`
|
||||
if [ "$dir" = "$base_ml_dir" ]; then
|
||||
shlib_so_name=libgcc_s
|
||||
break
|
||||
else
|
||||
canon_dir=`echo $dir | sed -n -e "s:$base_ml_dir/::p"`
|
||||
if [ -n "$canon_dir" ]; then
|
||||
shlib_so_name=libgcc_s_`echo $canon_dir | sed s,/,_,g`
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
gcc_multilib_sup=`echo $gcc_multilib_dir | sed 's~^[^/]*/~~'`
|
||||
os_multilib_base=`echo $os_multilib_dir | sed -n "s~/${gcc_multilib_sup}\$~~p"`
|
||||
if [ -z "$os_multilib_base" ]; then
|
||||
shlib_so_name=libgcc_s
|
||||
else
|
||||
shlib_so_name=libgcc_s_`echo $gcc_multilib_sup | sed s,/,_,g`
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
@ -438,6 +434,7 @@ echo ""
|
||||
echo "install: $all"
|
||||
for ml in $MULTILIBS; do
|
||||
dir=`echo ${ml} | sed -e 's/;.*$//' -e 's/=/$(EQ)/g'`
|
||||
flags=`echo ${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`;
|
||||
if [ $dir != . ]; then
|
||||
ldir='$(libsubdir)'/$dir
|
||||
echo " if [ -d $ldir ]; then true; else mkdir $ldir; chmod a+rx $ldir; fi;"
|
||||
@ -460,39 +457,22 @@ for ml in $MULTILIBS; do
|
||||
shlib_so_name="$shlib_base_name"
|
||||
shlib_dir=
|
||||
shlib_slibdir_qual=
|
||||
if [ -n "$SHLIB_SLIBDIR_SUFFIXES" ]; then
|
||||
shlib_slibdir_qual=none
|
||||
if [ -n "$MULTILIB_OSDIRNAMES" ]; then
|
||||
gcc_multilib_dir=`./xgcc -B./ $flags --print-multi-directory`
|
||||
os_multilib_dir=`./xgcc -B./ $flags --print-multi-os-directory`
|
||||
if [ "$dir" != . ]; then
|
||||
shlib_dir="$dir"/
|
||||
for suffix_pair in $SHLIB_SLIBDIR_SUFFIXES ; do
|
||||
base_ml_dir=`echo ${suffix_pair} | sed -e 's/:.*$//' -e 's/=/$(EQ)/g'`
|
||||
if [ "$dir" = "$base_ml_dir" ]; then
|
||||
shlib_so_name=libgcc_s
|
||||
shlib_slibdir_qual=`echo ${suffix_pair} | sed -e 's/^[^:]*://'`
|
||||
break
|
||||
else
|
||||
canon_dir=`echo $dir | sed -n -e "s:$base_ml_dir/::p"`
|
||||
if [ -n "$canon_dir" ]; then
|
||||
shlib_so_name=libgcc_s_`echo $canon_dir | sed s,/,_,g`
|
||||
shlib_slibdir_qual=`echo ${suffix_pair} | sed -e 's/^[^:]*://'`
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ "$shlib_slibdir_qual" = none ]; then
|
||||
for suffix_pair in $SHLIB_SLIBDIR_SUFFIXES ; do
|
||||
base_ml_dir=`echo ${suffix_pair} | sed -e 's/:.*$//' -e 's/=/$(EQ)/g'`
|
||||
shlib_slibdir_qual=`echo ${suffix_pair} | sed -e 's/^[^:]*://'`
|
||||
for ml2 in $MULTILIBS; do
|
||||
dir2=`echo ${ml2} | sed -e 's/;.*$//' -e 's/=/$(EQ)/g'`
|
||||
if [ "$base_ml_dir" = "$dir2" ]; then
|
||||
shlib_slibdir_qual=
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -n "$shlib_slibdir_qual" ]; then break; fi
|
||||
done
|
||||
gcc_multilib_sup=`echo $gcc_multilib_dir | sed 's~^[^/]*/~~'`
|
||||
os_multilib_base=`echo $os_multilib_dir | sed -n "s~/${gcc_multilib_sup}\$~~p"`
|
||||
if [ -z "$os_multilib_base" ]; then
|
||||
shlib_so_name=libgcc_s
|
||||
if [ "$os_multilib_dir" != "." ]; then
|
||||
shlib_slibdir_qual="/$os_multilib_dir"
|
||||
fi
|
||||
else
|
||||
shlib_so_name=libgcc_s_`echo $gcc_multilib_sup | sed s,/,_,g`
|
||||
shlib_slibdir_qual="/$os_multilib_base"
|
||||
fi
|
||||
fi
|
||||
echo " $SHLIB_INSTALL" \
|
||||
|
@ -7354,6 +7354,9 @@ gen_reload (out, in, opnum, type)
|
||||
{
|
||||
rtx last = get_last_insn ();
|
||||
rtx tem;
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
int in_regnum, out_regnum;
|
||||
#endif
|
||||
|
||||
/* If IN is a paradoxical SUBREG, remove it and try to put the
|
||||
opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */
|
||||
@ -7516,20 +7519,22 @@ gen_reload (out, in, opnum, type)
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* If we need a memory location to do the move, do it that way. */
|
||||
else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER
|
||||
&& GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER
|
||||
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
|
||||
REGNO_REG_CLASS (REGNO (out)),
|
||||
else if ((in_regnum = true_regnum (in)) >= 0
|
||||
&& in_regnum < FIRST_PSEUDO_REGISTER
|
||||
&& (out_regnum = true_regnum (out)) >= 0
|
||||
&& out_regnum < FIRST_PSEUDO_REGISTER
|
||||
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (in_regnum),
|
||||
REGNO_REG_CLASS (out_regnum),
|
||||
GET_MODE (out)))
|
||||
{
|
||||
/* Get the memory to use and rewrite both registers to its mode. */
|
||||
rtx loc = get_secondary_mem (in, GET_MODE (out), opnum, type);
|
||||
|
||||
if (GET_MODE (loc) != GET_MODE (out))
|
||||
out = gen_rtx_REG (GET_MODE (loc), REGNO (out));
|
||||
out = gen_rtx_REG (GET_MODE (loc), out_regnum);
|
||||
|
||||
if (GET_MODE (loc) != GET_MODE (in))
|
||||
in = gen_rtx_REG (GET_MODE (loc), REGNO (in));
|
||||
in = gen_rtx_REG (GET_MODE (loc), in_regnum);
|
||||
|
||||
gen_reload (loc, in, opnum, type);
|
||||
gen_reload (out, loc, opnum, type);
|
||||
@ -7581,6 +7586,11 @@ delete_output_reload (insn, j, last_reload_reg)
|
||||
rtx i1;
|
||||
rtx substed;
|
||||
|
||||
/* It is possible that this reload has been only used to set another reload
|
||||
we eliminated earlier and thus deleted this instruction too. */
|
||||
if (INSN_DELETED_P (output_reload_insn))
|
||||
return;
|
||||
|
||||
/* Get the raw pseudo-register referred to. */
|
||||
|
||||
while (GET_CODE (reg) == SUBREG)
|
||||
|
@ -1811,6 +1811,7 @@ extern int invert_jump_1 PARAMS ((rtx, rtx));
|
||||
extern int invert_jump PARAMS ((rtx, rtx, int));
|
||||
extern int rtx_renumbered_equal_p PARAMS ((rtx, rtx));
|
||||
extern int true_regnum PARAMS ((rtx));
|
||||
extern unsigned int reg_or_subregno PARAMS ((rtx));
|
||||
extern int redirect_jump_1 PARAMS ((rtx, rtx));
|
||||
extern int redirect_jump PARAMS ((rtx, rtx, int));
|
||||
extern void rebuild_jump_labels PARAMS ((rtx));
|
||||
|
@ -923,7 +923,15 @@ sched_analyze_insn (deps, x, insn, loop_notes)
|
||||
code = GET_CODE (x);
|
||||
}
|
||||
if (code == SET || code == CLOBBER)
|
||||
sched_analyze_1 (deps, x, insn);
|
||||
{
|
||||
sched_analyze_1 (deps, x, insn);
|
||||
|
||||
/* Bare clobber insns are used for letting life analysis, reg-stack
|
||||
and others know that a value is dead. Depend on the last call
|
||||
instruction so that reg-stack won't get confused. */
|
||||
if (code == CLOBBER)
|
||||
add_dependence_list (insn, deps->last_function_call, REG_DEP_OUTPUT);
|
||||
}
|
||||
else if (code == PARALLEL)
|
||||
{
|
||||
int i;
|
||||
|
@ -574,8 +574,8 @@ optimize_sibling_and_tail_recursive_calls ()
|
||||
rtx insn, insns;
|
||||
basic_block alternate_exit = EXIT_BLOCK_PTR;
|
||||
bool no_sibcalls_this_function = false;
|
||||
int successful_sibling_call = 0;
|
||||
int replaced_call_placeholder = 0;
|
||||
bool successful_replacement = false;
|
||||
bool replaced_call_placeholder = false;
|
||||
edge e;
|
||||
|
||||
insns = get_insns ();
|
||||
@ -715,10 +715,11 @@ optimize_sibling_and_tail_recursive_calls ()
|
||||
/* Select a set of insns to implement the call and emit them.
|
||||
Tail recursion is the most efficient, so select it over
|
||||
a tail/sibling call. */
|
||||
if (sibcall)
|
||||
successful_sibling_call = 1;
|
||||
|
||||
replaced_call_placeholder = 1;
|
||||
if (sibcall || tailrecursion)
|
||||
successful_replacement = true;
|
||||
replaced_call_placeholder = true;
|
||||
|
||||
replace_call_placeholder (insn,
|
||||
tailrecursion != 0
|
||||
? sibcall_use_tail_recursion
|
||||
@ -728,7 +729,7 @@ optimize_sibling_and_tail_recursive_calls ()
|
||||
}
|
||||
}
|
||||
|
||||
if (successful_sibling_call)
|
||||
if (successful_replacement)
|
||||
{
|
||||
rtx insn;
|
||||
tree arg;
|
||||
|
@ -2051,6 +2051,33 @@ extern tree integer_types[itk_none];
|
||||
#define long_long_integer_type_node integer_types[itk_long_long]
|
||||
#define long_long_unsigned_type_node integer_types[itk_unsigned_long_long]
|
||||
|
||||
|
||||
/* A pointer-to-function member type looks like:
|
||||
|
||||
struct {
|
||||
__P __pfn;
|
||||
ptrdiff_t __delta;
|
||||
};
|
||||
|
||||
If __pfn is NULL, it is a NULL pointer-to-member-function.
|
||||
|
||||
(Because the vtable is always the first thing in the object, we
|
||||
don't need its offset.) If the function is virtual, then PFN is
|
||||
one plus twice the index into the vtable; otherwise, it is just a
|
||||
pointer to the function.
|
||||
|
||||
Unfortunately, using the lowest bit of PFN doesn't work in
|
||||
architectures that don't impose alignment requirements on function
|
||||
addresses, or that use the lowest bit to tell one ISA from another,
|
||||
for example. For such architectures, we use the lowest bit of
|
||||
DELTA instead of the lowest bit of the PFN, and DELTA will be
|
||||
multiplied by 2. */
|
||||
|
||||
enum ptrmemfunc_vbit_where_t
|
||||
{
|
||||
ptrmemfunc_vbit_in_pfn,
|
||||
ptrmemfunc_vbit_in_delta
|
||||
};
|
||||
|
||||
#define NULL_TREE (tree) NULL
|
||||
|
||||
|
@ -1188,6 +1188,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
|
||||
/* Keep track of the unroll factor for the loop. */
|
||||
loop_info->unroll_number = unroll_number;
|
||||
|
||||
/* And whether the loop has been preconditioned. */
|
||||
loop_info->preconditioned = loop_preconditioned;
|
||||
|
||||
/* For each biv and giv, determine whether it can be safely split into
|
||||
a different variable for each unrolled copy of the loop body.
|
||||
We precalculate and save this info here, since computing it is
|
||||
@ -2868,7 +2871,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
|
||||
value = tem;
|
||||
}
|
||||
|
||||
splittable_regs[REGNO (v->new_reg)] = value;
|
||||
splittable_regs[reg_or_subregno (v->new_reg)] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3047,21 +3050,21 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
|
||||
itself does not have to be splittable. */
|
||||
|
||||
if (v->same && v->same->giv_type == DEST_REG)
|
||||
addr_combined_regs[REGNO (v->same->new_reg)] = v->same;
|
||||
addr_combined_regs[reg_or_subregno (v->same->new_reg)] = v->same;
|
||||
|
||||
if (GET_CODE (v->new_reg) == REG)
|
||||
{
|
||||
/* This giv maybe hasn't been combined with any others.
|
||||
Make sure that it's giv is marked as splittable here. */
|
||||
|
||||
splittable_regs[REGNO (v->new_reg)] = value;
|
||||
splittable_regs[reg_or_subregno (v->new_reg)] = value;
|
||||
|
||||
/* Make it appear to depend upon itself, so that the
|
||||
giv will be properly split in the main loop above. */
|
||||
if (! v->same)
|
||||
{
|
||||
v->same = v;
|
||||
addr_combined_regs[REGNO (v->new_reg)] = v;
|
||||
addr_combined_regs[reg_or_subregno (v->new_reg)] = v;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3098,7 +3101,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
|
||||
if (! v->ignore)
|
||||
count = REG_IV_CLASS (ivs, REGNO (v->src_reg))->biv_count;
|
||||
|
||||
splittable_regs_updates[REGNO (v->new_reg)] = count;
|
||||
splittable_regs_updates[reg_or_subregno (v->new_reg)] = count;
|
||||
}
|
||||
|
||||
result++;
|
||||
|
@ -1194,6 +1194,8 @@ assemble_start_function (decl, fnname)
|
||||
|
||||
/* Tell assembler to move to target machine's alignment for functions. */
|
||||
align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
|
||||
if (align < force_align_functions_log)
|
||||
align = force_align_functions_log;
|
||||
if (align > 0)
|
||||
{
|
||||
ASM_OUTPUT_ALIGN (asm_out_file, align);
|
||||
|
Loading…
Reference in New Issue
Block a user