re PR rtl-optimization/13473 (cc1 segfault w/-march=pentium4)

PR opt/13473
	* recog.c (validate_replace_rtx_1):  Take care for RTL sharing inside
	ASM input operands

	PR opt/12617
	* toplev.c (dump_file_index): Reorder ce3 and bbro.
	(dump_file): Likewise.
	(rest_of_compilation): Likewise.

	PR debug/13367
	* cgraph.c (cgraph_function_possibly_inlined):  Even with
	flag_really_no_inline we inline always_inline functions.
	* cgraphunit.c (cgraph_analyze_function): Clear inlinable flag
	for non-always_inline functions when there is flag_really_no_inline.
	(cgraph_decide_inlining): Limit work done when not inlining.
	(cgraph_decide_inlining_incrementally): Likewise.
	(cgraph_optimize_function): Check whether something got inlined.
	* c-objc-common.c (c_disregard_inline_limits): Do not always inline
	extern inline functions when not inlining.

	* opts.c (decode_options):  Disable crossjumping at -O1
	* invoke.texi (-O1): Document change.

	* gcc.dg/debug/20031231-1.c: New.
	* gcc.c-torture/compile/20040101-1.c: New.
	* gcc.dg/dwarf-die-[1-7].c: New.

From-SVN: r75303
This commit is contained in:
Jan Hubicka 2004-01-01 14:59:02 +01:00 committed by Jan Hubicka
parent 74aa338ad5
commit b684a3df8e
18 changed files with 307 additions and 120 deletions

View file

@ -1,2 +1,26 @@
2003-12-31 Jan Hubicka <jh@suse.cz>
PR opt/13473
* recog.c (validate_replace_rtx_1): Take care for RTL sharing inside
ASM input operands
PR opt/12617
* toplev.c (dump_file_index): Reorder ce3 and bbro.
(dump_file): Likewise.
(rest_of_compilation): Likewise.
PR debug/13367
* cgraph.c (cgraph_function_possibly_inlined): Even with
flag_really_no_inline we inline always_inline functions.
* cgraphunit.c (cgraph_analyze_function): Clear inlinable flag
for non-always_inline functions when there is flag_really_no_inline.
(cgraph_decide_inlining): Limit work done when not inlining.
(cgraph_decide_inlining_incrementally): Likewise.
(cgraph_optimize_function): Check whether something got inlined.
* c-objc-common.c (c_disregard_inline_limits): Do not always inline
extern inline functions when not inlining.
* opts.c (decode_options): Disable crossjumping at -O1
* invoke.texi (-O1): Document change.
See ChangeLog.10 for earlier changes.

View file

@ -1426,7 +1426,8 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
if (TREE_USED (olddecl)
/* In unit-at-a-time mode we never inline re-defined extern
inline functions. */
&& !flag_unit_at_a_time)
&& !flag_unit_at_a_time
&& cgraph_function_possibly_inlined_p (olddecl))
(*debug_hooks->outlining_inline_function) (olddecl);
/* The new defn must not be inline. */

View file

@ -1,5 +1,5 @@
/* Some code common to C and ObjC front ends.
Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
@ -61,7 +61,8 @@ c_disregard_inline_limits (tree fn)
if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) != NULL)
return 1;
return DECL_DECLARED_INLINE_P (fn) && DECL_EXTERNAL (fn);
return (!flag_really_no_inline && DECL_DECLARED_INLINE_P (fn)
&& DECL_EXTERNAL (fn));
}
int

View file

@ -1,5 +1,5 @@
/* Callgraph handling code.
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
Contributed by Jan Hubicka
This file is part of GCC.
@ -613,7 +613,9 @@ bool
cgraph_function_possibly_inlined_p (tree decl)
{
if (!cgraph_global_info_ready)
return (DECL_INLINE (decl) && !flag_really_no_inline);
return (DECL_INLINE (decl)
&& (!flag_really_no_inline
|| (*lang_hooks.tree_inlining.disregard_inline_limits) (decl)));
return cgraph_node (decl)->global.inlined;
}

View file

@ -1,5 +1,5 @@
/* Callgraph based intraprocedural optimizations.
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
Contributed by Jan Hubicka
This file is part of GCC.
@ -325,7 +325,8 @@ cgraph_analyze_function (struct cgraph_node *node)
if (node->local.inlinable)
node->local.disregard_inline_limits
= (*lang_hooks.tree_inlining.disregard_inline_limits) (decl);
if (flag_really_no_inline && !node->local.disregard_inline_limits)
node->local.inlinable = 0;
/* Inlining characteristics are maintained by the cgraph_mark_inline. */
node->global.insns = node->local.self_insns;
if (!DECL_EXTERNAL (decl))
@ -471,7 +472,15 @@ cgraph_optimize_function (struct cgraph_node *node)
/* optimize_inline_calls avoids inlining of current_function_decl. */
current_function_decl = decl;
if (flag_inline_trees)
optimize_inline_calls (decl);
{
struct cgraph_edge *e;
for (e = node->callees; e; e = e->next_callee)
if (e->inline_call)
break;
if (e)
optimize_inline_calls (decl);
}
if (node->nested)
{
for (node = node->nested; node; node = node->next_nested)
@ -1137,80 +1146,84 @@ cgraph_decide_inlining (void)
inlined[y]->output = 0, node->aux = 0;
}
cgraph_decide_inlining_of_small_functions (inlined, inlined_callees);
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "\nDeciding on functions called once:\n");
/* And finally decide what functions are called once. */
for (i = nnodes - 1; i >= 0; i--)
if (!flag_really_no_inline)
{
node = order[i];
cgraph_decide_inlining_of_small_functions (inlined, inlined_callees);
if (node->callers && !node->callers->next_caller && !node->needed
&& node->local.inlinable && !node->callers->inline_call
&& !DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl))
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "\nDeciding on functions called once:\n");
/* And finally decide what functions are called once. */
for (i = nnodes - 1; i >= 0; i--)
{
bool ok = true;
struct cgraph_node *node1;
node = order[i];
/* Verify that we won't duplicate the caller. */
for (node1 = node->callers->caller;
node1->callers && node1->callers->inline_call
&& ok; node1 = node1->callers->caller)
if (node1->callers->next_caller || node1->needed)
ok = false;
if (ok)
if (node->callers && !node->callers->next_caller && !node->needed
&& node->local.inlinable && !node->callers->inline_call
&& !DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl))
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
"\nConsidering %s %i insns.\n"
" Called once from %s %i insns.\n",
cgraph_node_name (node), node->global.insns,
cgraph_node_name (node->callers->caller),
node->callers->caller->global.insns);
ninlined = cgraph_inlined_into (node->callers->caller, inlined);
old_insns = overall_insns;
if (cgraph_check_inline_limits
(node->callers->caller, node, inlined, ninlined))
bool ok = true;
struct cgraph_node *node1;
/* Verify that we won't duplicate the caller. */
for (node1 = node->callers->caller;
node1->callers && node1->callers->inline_call
&& ok; node1 = node1->callers->caller)
if (node1->callers->next_caller || node1->needed)
ok = false;
if (ok)
{
ninlined_callees =
cgraph_inlined_callees (node, inlined_callees);
cgraph_mark_inline (node->callers->caller, node, inlined,
ninlined, inlined_callees,
ninlined_callees);
for (y = 0; y < ninlined_callees; y++)
inlined_callees[y]->output = 0, node->aux = 0;
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
" Inlined into %s which now has %i insns"
" for a net change of %+i insns.\n",
"\nConsidering %s %i insns.\n"
" Called once from %s %i insns.\n",
cgraph_node_name (node), node->global.insns,
cgraph_node_name (node->callers->caller),
node->callers->caller->global.insns,
overall_insns - old_insns);
node->callers->caller->global.insns);
ninlined = cgraph_inlined_into (node->callers->caller,
inlined);
old_insns = overall_insns;
if (cgraph_check_inline_limits
(node->callers->caller, node, inlined, ninlined))
{
ninlined_callees =
cgraph_inlined_callees (node, inlined_callees);
cgraph_mark_inline (node->callers->caller, node, inlined,
ninlined, inlined_callees,
ninlined_callees);
for (y = 0; y < ninlined_callees; y++)
inlined_callees[y]->output = 0, node->aux = 0;
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
" Inlined into %s which now has %i insns"
" for a net change of %+i insns.\n",
cgraph_node_name (node->callers->caller),
node->callers->caller->global.insns,
overall_insns - old_insns);
}
else
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
" Inline limit reached, not inlined.\n");
}
for (y = 0; y < ninlined; y++)
inlined[y]->output = 0, node->aux = 0;
}
else
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
" Inline limit reached, not inlined.\n");
}
for (y = 0; y < ninlined; y++)
inlined[y]->output = 0, node->aux = 0;
}
}
}
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
"\nInlined %i calls, eliminated %i functions, "
"%i insns turned to %i insns.\n\n",
ncalls_inlined, nfunctions_inlined, initial_insns,
overall_insns);
free (order);
free (inlined);
free (inlined_callees);
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
"\nInlined %i calls, eliminated %i functions, "
"%i insns turned to %i insns.\n\n",
ncalls_inlined, nfunctions_inlined, initial_insns,
overall_insns);
free (order);
free (inlined);
free (inlined_callees);
}
}
/* Decide on the inlining. We do so in the topological order to avoid
@ -1242,20 +1255,24 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
inlined_callees[y]->output = 0, node->aux = 0;
}
/* Now do the automatic inlining. */
for (e = node->callees; e; e = e->next_callee)
if (e->callee->local.inlinable && !e->callee->output
&& e->callee != node && !e->inline_call
&& cgraph_default_inline_p (e->callee)
&& cgraph_check_inline_limits (node, e->callee, inlined,
ninlined))
{
ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees);
cgraph_mark_inline (node, e->callee, inlined, ninlined,
inlined_callees, ninlined_callees);
for (y = 0; y < ninlined_callees; y++)
inlined_callees[y]->output = 0, node->aux = 0;
}
if (!flag_really_no_inline)
{
/* Now do the automatic inlining. */
for (e = node->callees; e; e = e->next_callee)
if (e->callee->local.inlinable && !e->callee->output
&& e->callee != node && !e->inline_call
&& cgraph_default_inline_p (e->callee)
&& cgraph_check_inline_limits (node, e->callee, inlined,
ninlined))
{
ninlined_callees = cgraph_inlined_callees (e->callee,
inlined_callees);
cgraph_mark_inline (node, e->callee, inlined, ninlined,
inlined_callees, ninlined_callees);
for (y = 0; y < ninlined_callees; y++)
inlined_callees[y]->output = 0, node->aux = 0;
}
}
/* Clear the flags set by cgraph_inlined_into. */
for (y = 0; y < ninlined; y++)

View file

@ -1,5 +1,5 @@
@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
@c 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
@c 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@ -3626,7 +3626,6 @@ compilation time.
-fmerge-constants @gol
-fthread-jumps @gol
-floop-optimize @gol
-fcrossjumping @gol
-fif-conversion @gol
-fif-conversion2 @gol
-fdelayed-branch @gol
@ -3663,7 +3662,8 @@ also turns on the following optimization flags:
-fstrict-aliasing @gol
-funit-at-a-time @gol
-falign-functions -falign-jumps @gol
-falign-loops -falign-labels}
-falign-loops -falign-labels @gol
-fcrossjumping}
Please note the warning under @option{-fgcse} about
invoking @option{-O2} on programs that use computed gotos.

View file

@ -1,5 +1,5 @@
/* Command line option handling.
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Neil Booth.
This file is part of GCC.
@ -536,13 +536,13 @@ decode_options (unsigned int argc, const char **argv)
flag_guess_branch_prob = 1;
flag_cprop_registers = 1;
flag_loop_optimize = 1;
flag_crossjumping = 1;
flag_if_conversion = 1;
flag_if_conversion2 = 1;
}
if (optimize >= 2)
{
flag_crossjumping = 1;
flag_optimize_sibling_calls = 1;
flag_cse_follow_jumps = 1;
flag_cse_skip_blocks = 1;

View file

@ -1,6 +1,6 @@
/* Subroutines used by or related to instruction recognition.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
1999, 2000, 2001, 2002, 2003, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@ -476,16 +476,38 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
return;
}
/* Call ourself recursively to perform the replacements. */
/* Call ourself recursively to perform the replacements.
We must not replace inside already replaced expression, otherwise we
get infinite recursion for replacements like (reg X)->(subreg (reg X))
done by regmove, so we must special case shared ASM_OPERANDS. */
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
if (GET_CODE (x) == PARALLEL)
{
if (fmt[i] == 'e')
validate_replace_rtx_1 (&XEXP (x, i), from, to, object);
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);
for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
{
if (j && GET_CODE (XVECEXP (x, 0, j)) == SET
&& GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
{
/* Verify that operands are really shared. */
if (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0))) !=
ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, j))))
abort ();
validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
from, to, object);
}
else
validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object);
}
}
else
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
validate_replace_rtx_1 (&XEXP (x, i), from, to, object);
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);
}
/* If we didn't substitute, there is nothing more to do. */
if (num_changes == prev_changes)

View file

@ -1,3 +1,9 @@
2004-01-01 Jan Hubicka <jh@suse.cz>
* gcc.dg/debug/20031231-1.c: New.
* gcc.c-torture/compile/20040101-1.c: New.
* gcc.dg/dwarf-die-[1-7].c: New.
2004-01-01 Jakub Jelinek <jakub@redhat.com>
PR optimization/13521

View file

@ -0,0 +1,28 @@
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#define CF (1<<0)
#define PF (1<<2)
#define AF (1<<4)
#define ZF (1<<6)
#define SF (1<<7)
#define OF (1<<11)
#define EFLAGS_BITS (CF|PF|AF|ZF|SF|OF)
void test16(uint16_t x, uint32_t eflags)
{
uint16_t bsr_result;
uint32_t bsr_eflags;
uint16_t bsf_result;
uint32_t bsf_eflags;
__asm volatile(""
: "=&r" (bsr_result), "=&r" (bsr_eflags)
: "r" (x), "i" (~EFLAGS_BITS), "r" (eflags));
__asm volatile(""
: "=&r" (bsf_result), "=&r" (bsf_eflags)
: "r" (x), "i" (~EFLAGS_BITS), "r" (eflags));
printf("%08x %04x bsrw %02x %08x bsfw %02x %08x\n",
x, eflags, bsr_result, bsr_eflags, bsf_result, bsf_eflags);
}

View file

@ -0,0 +1,22 @@
/* { dg-do compile } */
/* We used to fail because GCC didn't expect always inline to be inlined at
-O0. */
typedef union tree_node *tree;
typedef struct c_pretty_print_info c_pretty_printer;
void pp_c_string_literal (c_pretty_printer *, tree);
static __inline__ __attribute__((always_inline)) void
pp_c_shift_expression (c_pretty_printer *pp, tree e)
{
pp_c_shift_expression (pp,e);
}
static void
pp_c_relational_expression (c_pretty_printer *pp, tree e)
{
pp_c_shift_expression (pp, e);
}

View file

@ -0,0 +1,8 @@
/* Verify that inline function never actually inlined has no abstract DIE. */
/* { dg-do compile */
/* { dg-options "-O2 -gdwarf-2 -dA" } */
/* { dg-final { scan-assembler-not "DW_AT_inline" } } */
inline int t()
{
}
int (*q)()=t;

View file

@ -0,0 +1,7 @@
/* Verify that inline function never actually emit has no DIE. */
/* { dg-do compile */
/* { dg-options "-O0 -gdwarf-2 -dA" } */
/* { dg-final { scan-assembler-not "CIE Version" } } */
static inline int t()
{
}

View file

@ -0,0 +1,11 @@
/* Verify that extern inline function never actually inlined has no abstract DIE. */
/* { dg-do compile */
/* { dg-options "-O0 -gdwarf-2 -dA" } */
/* { dg-final { scan-assembler-not "DW_AT_inline" } } */
extern inline int t()
{
}
int (*q)()=t;
int t()
{
}

View file

@ -0,0 +1,12 @@
/* Inlined inline function must have abstract DIE */
/* { dg-do compile */
/* { dg-options "-O2 -gdwarf-2 -dA -fpreprocessed" } */
/* { dg-final { scan-assembler "3.*DW_AT_inline" } } */
#1 "test.h"
inline int t()
{
}
int q()
{
t();
}

View file

@ -0,0 +1,12 @@
/* not inline inline function must not have abstract DIE */
/* { dg-do compile */
/* { dg-options "-O2 -fno-inline -gdwarf-2 -dA -fpreprocessed" } */
/* { dg-final { scan-assembler-not "DW_AT_inline" } } */
#1 "test.h"
inline int t()
{
}
int q()
{
t();
}

View file

@ -0,0 +1,14 @@
/* Inlined non-inline function must have abstract DIE */
/* { dg-do compile */
/* { dg-options "-O2 -gdwarf-2 -dA -fpreprocessed" } */
/* { dg-final { scan-assembler "1.*DW_AT_inline" } } */
#1 "test.h"
void f(void);
static int t()
{
f();
}
int q()
{
t();
}

View file

@ -1,6 +1,6 @@
/* Top level of GCC compilers (cc1, cc1plus, etc.)
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
@ -277,8 +277,8 @@ enum dump_file_index
DFI_flow2,
DFI_peephole2,
DFI_rnreg,
DFI_bbro,
DFI_ce3,
DFI_bbro,
DFI_branch_target_load,
DFI_sched2,
DFI_stack,
@ -328,8 +328,8 @@ static struct dump_file_info dump_file[DFI_MAX] =
{ "flow2", 'w', 1, 0, 0 },
{ "peephole2", 'z', 1, 0, 0 },
{ "rnreg", 'n', 1, 0, 0 },
{ "bbro", 'B', 1, 0, 0 },
{ "ce3", 'E', 1, 0, 0 },
{ "bbro", 'B', 1, 0, 0 },
{ "btl", 'd', 1, 0, 0 }, /* Yes, duplicate enable switch. */
{ "sched2", 'R', 1, 0, 0 },
{ "stack", 'k', 1, 0, 0 },
@ -3463,14 +3463,6 @@ rest_of_compilation (tree decl)
}
#endif
if (optimize > 0)
{
if (flag_rename_registers || flag_cprop_registers)
rest_of_handle_regrename (decl, insns);
rest_of_handle_reorder_blocks (decl, insns);
}
if (flag_if_conversion2)
{
timevar_push (TV_IFCVT2);
@ -3482,23 +3474,31 @@ rest_of_compilation (tree decl)
timevar_pop (TV_IFCVT2);
}
if (flag_branch_target_load_optimize2)
{
/* Leave this a warning for now so that it is possible to experiment
with running this pass twice. In 3.6, we should either make this
an error, or use separate dump files. */
if (flag_branch_target_load_optimize)
warning ("branch target register load optimization is not intended "
"to be run twice");
if (optimize > 0)
{
if (flag_rename_registers || flag_cprop_registers)
rest_of_handle_regrename (decl, insns);
open_dump_file (DFI_branch_target_load, decl);
rest_of_handle_reorder_blocks (decl, insns);
}
branch_target_load_optimize (insns, true);
if (flag_branch_target_load_optimize2)
{
/* Leave this a warning for now so that it is possible to experiment
with running this pass twice. In 3.6, we should either make this
an error, or use separate dump files. */
if (flag_branch_target_load_optimize)
warning ("branch target register load optimization is not intended "
"to be run twice");
close_dump_file (DFI_branch_target_load, print_rtl_with_bb, insns);
open_dump_file (DFI_branch_target_load, decl);
ggc_collect ();
}
branch_target_load_optimize (insns, true);
close_dump_file (DFI_branch_target_load, print_rtl_with_bb, insns);
ggc_collect ();
}
#ifdef INSN_SCHEDULING
if (optimize > 0 && flag_schedule_insns_after_reload)