Commit b684a3df by Jan Hubicka Committed by Jan Hubicka

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
parent 74aa338a
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.
......@@ -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. */
......
/* 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
......
/* 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;
}
......
/* 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");
if (!flag_really_no_inline)
{
cgraph_decide_inlining_of_small_functions (inlined, inlined_callees);
/* And finally decide what functions are called once. */
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "\nDeciding on functions called once:\n");
for (i = nnodes - 1; i >= 0; i--)
{
node = order[i];
/* And finally decide what functions are called once. */
if (node->callers && !node->callers->next_caller && !node->needed
&& node->local.inlinable && !node->callers->inline_call
&& !DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl))
for (i = nnodes - 1; i >= 0; i--)
{
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)
node = order[i];
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++)
......
@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.
......
/* 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;
......
/* 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)
......
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
......
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);
}
/* { 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);
}
/* 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;
/* 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()
{
}
/* 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()
{
}
/* 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();
}
/* 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();
}
/* 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();
}
/* 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);
}
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");
branch_target_load_optimize (insns, true);
open_dump_file (DFI_branch_target_load, decl);
close_dump_file (DFI_branch_target_load, print_rtl_with_bb, insns);
branch_target_load_optimize (insns, true);
ggc_collect ();
}
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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment