mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-28 20:01:18 +08:00
re PR rtl-optimization/38245 (stack corruption when a call is removed but not the outgoing argument pushes)
PR rtl-optimization/38245 * calls.c (expand_call): Add stack arguments to CALL_INSN_FUNCTION_USAGE even for pure calls (when ACCUMULATE_OUTGOING_ARGS) and even for args partially passed in regs and partially in memory or BLKmode arguments. (emit_library_call_value_1): Add stack arguments to CALL_INSN_FUNCTION_USAGE even for pure calls (when ACCUMULATE_OUTGOING_ARGS). * dce.c: Include tm_p.h. (find_call_stack_args): New function. (deletable_insn_p): Call it for CALL_P insns. Add ARG_STORES argument. (mark_insn): Call find_call_stack_args for CALL_Ps. (prescan_insns_for_dce): Walk insns backwards in bb rather than forwards. Allocate and free arg_stores bitmap if needed, pass it down to deletable_insn_p, don't mark stores set in arg_stores bitmap, clear the bitmap at the beginning of each bb. * Makefile.in (dce.o): Depend on $(TM_P_H). * gcc.dg/pr38245-3.c: New test. * gcc.dg/pr38245-3.h: New file. * gcc.dg/pr38245-4.c: New file. * gcc.dg/pr38364.c: New test. From-SVN: r143387
This commit is contained in:
parent
6df6bcfa0f
commit
0196c95ed4
@ -1,3 +1,24 @@
|
||||
2009-01-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR rtl-optimization/38245
|
||||
* calls.c (expand_call): Add stack arguments to
|
||||
CALL_INSN_FUNCTION_USAGE even for pure calls (when
|
||||
ACCUMULATE_OUTGOING_ARGS) and even for args partially passed
|
||||
in regs and partially in memory or BLKmode arguments.
|
||||
(emit_library_call_value_1): Add stack arguments to
|
||||
CALL_INSN_FUNCTION_USAGE even for pure calls (when
|
||||
ACCUMULATE_OUTGOING_ARGS).
|
||||
* dce.c: Include tm_p.h.
|
||||
(find_call_stack_args): New function.
|
||||
(deletable_insn_p): Call it for CALL_P insns. Add ARG_STORES
|
||||
argument.
|
||||
(mark_insn): Call find_call_stack_args for CALL_Ps.
|
||||
(prescan_insns_for_dce): Walk insns backwards in bb rather than
|
||||
forwards. Allocate and free arg_stores bitmap if needed, pass it
|
||||
down to deletable_insn_p, don't mark stores set in arg_stores
|
||||
bitmap, clear the bitmap at the beginning of each bb.
|
||||
* Makefile.in (dce.o): Depend on $(TM_P_H).
|
||||
|
||||
2009-01-14 Michael Meissner <gnu@the-meissners.org>
|
||||
|
||||
PR target/22599
|
||||
|
@ -2672,7 +2672,7 @@ cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
|
||||
$(DF_H) $(DBGCNT_H)
|
||||
dce.o : dce.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(TREE_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) $(DF_H) cselib.h \
|
||||
$(DBGCNT_H) dce.h $(TIMEVAR_H) tree-pass.h $(DBGCNT_H)
|
||||
$(DBGCNT_H) dce.h $(TIMEVAR_H) tree-pass.h $(DBGCNT_H) $(TM_P_H)
|
||||
dse.o : dse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(TREE_H) $(TM_P_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
|
||||
$(RECOG_H) $(EXPR_H) $(DF_H) cselib.h $(DBGCNT_H) $(TIMEVAR_H) tree-pass.h \
|
||||
|
43
gcc/calls.c
43
gcc/calls.c
@ -1,6 +1,6 @@
|
||||
/* Convert function calls to rtl insns, for GNU C compiler.
|
||||
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -2705,26 +2705,28 @@ expand_call (tree exp, rtx target, int ignore)
|
||||
but we do preallocate space here if they want that. */
|
||||
|
||||
for (i = 0; i < num_actuals; i++)
|
||||
if (args[i].reg == 0 || args[i].pass_on_stack)
|
||||
{
|
||||
rtx before_arg = get_last_insn ();
|
||||
{
|
||||
if (args[i].reg == 0 || args[i].pass_on_stack)
|
||||
{
|
||||
rtx before_arg = get_last_insn ();
|
||||
|
||||
if (store_one_arg (&args[i], argblock, flags,
|
||||
adjusted_args_size.var != 0,
|
||||
reg_parm_stack_space)
|
||||
|| (pass == 0
|
||||
&& check_sibcall_argument_overlap (before_arg,
|
||||
&args[i], 1)))
|
||||
sibcall_failure = 1;
|
||||
if (store_one_arg (&args[i], argblock, flags,
|
||||
adjusted_args_size.var != 0,
|
||||
reg_parm_stack_space)
|
||||
|| (pass == 0
|
||||
&& check_sibcall_argument_overlap (before_arg,
|
||||
&args[i], 1)))
|
||||
sibcall_failure = 1;
|
||||
}
|
||||
|
||||
if (flags & ECF_CONST
|
||||
&& args[i].stack
|
||||
&& args[i].value == args[i].stack)
|
||||
call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
|
||||
gen_rtx_USE (VOIDmode,
|
||||
args[i].value),
|
||||
call_fusage);
|
||||
}
|
||||
if (((flags & ECF_CONST)
|
||||
|| ((flags & ECF_PURE) && ACCUMULATE_OUTGOING_ARGS))
|
||||
&& args[i].stack)
|
||||
call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
|
||||
gen_rtx_USE (VOIDmode,
|
||||
args[i].stack),
|
||||
call_fusage);
|
||||
}
|
||||
|
||||
/* If we have a parm that is passed in registers but not in memory
|
||||
and whose alignment does not permit a direct copy into registers,
|
||||
@ -3672,7 +3674,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
|
||||
|
||||
NO_DEFER_POP;
|
||||
|
||||
if (flags & ECF_CONST)
|
||||
if ((flags & ECF_CONST)
|
||||
|| ((flags & ECF_PURE) && ACCUMULATE_OUTGOING_ARGS))
|
||||
{
|
||||
rtx use;
|
||||
|
||||
|
304
gcc/dce.c
304
gcc/dce.c
@ -1,5 +1,5 @@
|
||||
/* RTL dead code elimination.
|
||||
Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "timevar.h"
|
||||
#include "tree-pass.h"
|
||||
#include "dbgcnt.h"
|
||||
#include "tm_p.h"
|
||||
|
||||
DEF_VEC_I(int);
|
||||
DEF_VEC_ALLOC_I(int,heap);
|
||||
@ -57,6 +58,7 @@ static sbitmap marked;
|
||||
static bitmap_obstack dce_blocks_bitmap_obstack;
|
||||
static bitmap_obstack dce_tmp_bitmap_obstack;
|
||||
|
||||
static bool find_call_stack_args (rtx, bool, bool, bitmap);
|
||||
|
||||
/* A subroutine for which BODY is part of the instruction being tested;
|
||||
either the top-level pattern, or an element of a PARALLEL. The
|
||||
@ -94,7 +96,7 @@ deletable_insn_p_1 (rtx body)
|
||||
the DCE pass. */
|
||||
|
||||
static bool
|
||||
deletable_insn_p (rtx insn, bool fast)
|
||||
deletable_insn_p (rtx insn, bool fast, bitmap arg_stores)
|
||||
{
|
||||
rtx body, x;
|
||||
int i;
|
||||
@ -111,7 +113,7 @@ deletable_insn_p (rtx insn, bool fast)
|
||||
infinite loop. */
|
||||
&& (RTL_CONST_OR_PURE_CALL_P (insn)
|
||||
&& !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
|
||||
return true;
|
||||
return find_call_stack_args (insn, false, fast, arg_stores);
|
||||
|
||||
if (!NONJUMP_INSN_P (insn))
|
||||
return false;
|
||||
@ -174,6 +176,12 @@ mark_insn (rtx insn, bool fast)
|
||||
SET_BIT (marked, INSN_UID (insn));
|
||||
if (dump_file)
|
||||
fprintf (dump_file, " Adding insn %d to worklist\n", INSN_UID (insn));
|
||||
if (CALL_P (insn)
|
||||
&& !df_in_progress
|
||||
&& !SIBLING_CALL_P (insn)
|
||||
&& (RTL_CONST_OR_PURE_CALL_P (insn)
|
||||
&& !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
|
||||
find_call_stack_args (insn, true, fast, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,6 +220,254 @@ mark_nonreg_stores (rtx body, rtx insn, bool fast)
|
||||
}
|
||||
|
||||
|
||||
/* Try to find all stack stores of CALL_INSN arguments if
|
||||
ACCUMULATE_OUTGOING_ARGS. If all stack stores have been found
|
||||
and it is therefore safe to eliminate the call, return true,
|
||||
otherwise return false. This function should be first called
|
||||
with DO_MARK false, and only when the CALL_INSN is actually
|
||||
going to be marked called again with DO_MARK true. */
|
||||
|
||||
static bool
|
||||
find_call_stack_args (rtx call_insn, bool do_mark, bool fast,
|
||||
bitmap arg_stores)
|
||||
{
|
||||
rtx p, insn, prev_insn;
|
||||
bool ret;
|
||||
HOST_WIDE_INT min_sp_off, max_sp_off;
|
||||
bitmap sp_bytes;
|
||||
|
||||
gcc_assert (CALL_P (call_insn));
|
||||
if (!ACCUMULATE_OUTGOING_ARGS)
|
||||
return true;
|
||||
|
||||
if (!do_mark)
|
||||
{
|
||||
gcc_assert (arg_stores);
|
||||
bitmap_clear (arg_stores);
|
||||
}
|
||||
|
||||
min_sp_off = INTTYPE_MAXIMUM (HOST_WIDE_INT);
|
||||
max_sp_off = 0;
|
||||
|
||||
/* First determine the minimum and maximum offset from sp for
|
||||
stored arguments. */
|
||||
for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1))
|
||||
if (GET_CODE (XEXP (p, 0)) == USE
|
||||
&& MEM_P (XEXP (XEXP (p, 0), 0)))
|
||||
{
|
||||
rtx mem = XEXP (XEXP (p, 0), 0), addr, size;
|
||||
HOST_WIDE_INT off = 0;
|
||||
size = MEM_SIZE (mem);
|
||||
if (size == NULL_RTX)
|
||||
return false;
|
||||
addr = XEXP (mem, 0);
|
||||
if (GET_CODE (addr) == PLUS
|
||||
&& REG_P (XEXP (addr, 0))
|
||||
&& CONST_INT_P (XEXP (addr, 1)))
|
||||
{
|
||||
off = INTVAL (XEXP (addr, 1));
|
||||
addr = XEXP (addr, 0);
|
||||
}
|
||||
if (addr != stack_pointer_rtx)
|
||||
{
|
||||
if (!REG_P (addr))
|
||||
return false;
|
||||
/* If not fast, use chains to see if addr wasn't set to
|
||||
sp + offset. */
|
||||
if (!fast)
|
||||
{
|
||||
df_ref *use_rec;
|
||||
struct df_link *defs;
|
||||
rtx set;
|
||||
|
||||
for (use_rec = DF_INSN_USES (call_insn); *use_rec; use_rec++)
|
||||
if (rtx_equal_p (addr, DF_REF_REG (*use_rec)))
|
||||
break;
|
||||
|
||||
if (*use_rec == NULL)
|
||||
return false;
|
||||
|
||||
for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next)
|
||||
if (! DF_REF_IS_ARTIFICIAL (defs->ref))
|
||||
break;
|
||||
|
||||
if (defs == NULL)
|
||||
return false;
|
||||
|
||||
set = single_set (DF_REF_INSN (defs->ref));
|
||||
if (!set)
|
||||
return false;
|
||||
|
||||
if (GET_CODE (SET_SRC (set)) != PLUS
|
||||
|| XEXP (SET_SRC (set), 0) != stack_pointer_rtx
|
||||
|| !CONST_INT_P (XEXP (SET_SRC (set), 1)))
|
||||
return false;
|
||||
|
||||
off += INTVAL (XEXP (SET_SRC (set), 1));
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
min_sp_off = MIN (min_sp_off, off);
|
||||
max_sp_off = MAX (max_sp_off, off + INTVAL (size));
|
||||
}
|
||||
|
||||
if (min_sp_off >= max_sp_off)
|
||||
return true;
|
||||
sp_bytes = BITMAP_ALLOC (NULL);
|
||||
|
||||
/* Set bits in SP_BYTES bitmap for bytes relative to sp + min_sp_off
|
||||
which contain arguments. Checking has been done in the previous
|
||||
loop. */
|
||||
for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1))
|
||||
if (GET_CODE (XEXP (p, 0)) == USE
|
||||
&& MEM_P (XEXP (XEXP (p, 0), 0)))
|
||||
{
|
||||
rtx mem = XEXP (XEXP (p, 0), 0), addr;
|
||||
HOST_WIDE_INT off = 0, byte;
|
||||
addr = XEXP (mem, 0);
|
||||
if (GET_CODE (addr) == PLUS
|
||||
&& REG_P (XEXP (addr, 0))
|
||||
&& CONST_INT_P (XEXP (addr, 1)))
|
||||
{
|
||||
off = INTVAL (XEXP (addr, 1));
|
||||
addr = XEXP (addr, 0);
|
||||
}
|
||||
if (addr != stack_pointer_rtx)
|
||||
{
|
||||
df_ref *use_rec;
|
||||
struct df_link *defs;
|
||||
rtx set;
|
||||
|
||||
for (use_rec = DF_INSN_USES (call_insn); *use_rec; use_rec++)
|
||||
if (rtx_equal_p (addr, DF_REF_REG (*use_rec)))
|
||||
break;
|
||||
|
||||
for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next)
|
||||
if (! DF_REF_IS_ARTIFICIAL (defs->ref))
|
||||
break;
|
||||
|
||||
set = single_set (DF_REF_INSN (defs->ref));
|
||||
off += INTVAL (XEXP (SET_SRC (set), 1));
|
||||
}
|
||||
for (byte = off; byte < off + INTVAL (MEM_SIZE (mem)); byte++)
|
||||
{
|
||||
gcc_assert (!bitmap_bit_p (sp_bytes, byte - min_sp_off));
|
||||
bitmap_set_bit (sp_bytes, byte - min_sp_off);
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk backwards, looking for argument stores. The search stops
|
||||
when seeting another call, sp adjustment or memory store other than
|
||||
argument store. */
|
||||
ret = false;
|
||||
for (insn = PREV_INSN (call_insn); insn; insn = prev_insn)
|
||||
{
|
||||
rtx set, mem, addr;
|
||||
HOST_WIDE_INT off, byte;
|
||||
|
||||
if (insn == BB_HEAD (BLOCK_FOR_INSN (call_insn)))
|
||||
prev_insn = NULL_RTX;
|
||||
else
|
||||
prev_insn = PREV_INSN (insn);
|
||||
|
||||
if (CALL_P (insn))
|
||||
break;
|
||||
|
||||
if (!INSN_P (insn))
|
||||
continue;
|
||||
|
||||
set = single_set (insn);
|
||||
if (!set || SET_DEST (set) == stack_pointer_rtx)
|
||||
break;
|
||||
|
||||
if (!MEM_P (SET_DEST (set)))
|
||||
continue;
|
||||
|
||||
mem = SET_DEST (set);
|
||||
addr = XEXP (mem, 0);
|
||||
off = 0;
|
||||
if (GET_CODE (addr) == PLUS
|
||||
&& REG_P (XEXP (addr, 0))
|
||||
&& CONST_INT_P (XEXP (addr, 1)))
|
||||
{
|
||||
off = INTVAL (XEXP (addr, 1));
|
||||
addr = XEXP (addr, 0);
|
||||
}
|
||||
if (addr != stack_pointer_rtx)
|
||||
{
|
||||
if (!REG_P (addr))
|
||||
break;
|
||||
if (!fast)
|
||||
{
|
||||
df_ref *use_rec;
|
||||
struct df_link *defs;
|
||||
rtx set;
|
||||
|
||||
for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
|
||||
if (rtx_equal_p (addr, DF_REF_REG (*use_rec)))
|
||||
break;
|
||||
|
||||
if (*use_rec == NULL)
|
||||
break;
|
||||
|
||||
for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next)
|
||||
if (! DF_REF_IS_ARTIFICIAL (defs->ref))
|
||||
break;
|
||||
|
||||
if (defs == NULL)
|
||||
break;
|
||||
|
||||
set = single_set (DF_REF_INSN (defs->ref));
|
||||
if (!set)
|
||||
break;
|
||||
|
||||
if (GET_CODE (SET_SRC (set)) != PLUS
|
||||
|| XEXP (SET_SRC (set), 0) != stack_pointer_rtx
|
||||
|| !CONST_INT_P (XEXP (SET_SRC (set), 1)))
|
||||
break;
|
||||
|
||||
off += INTVAL (XEXP (SET_SRC (set), 1));
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (GET_MODE_SIZE (GET_MODE (mem)) == 0)
|
||||
break;
|
||||
|
||||
for (byte = off; byte < off + GET_MODE_SIZE (GET_MODE (mem)); byte++)
|
||||
{
|
||||
if (byte < min_sp_off
|
||||
|| byte >= max_sp_off
|
||||
|| !bitmap_bit_p (sp_bytes, byte - min_sp_off))
|
||||
break;
|
||||
bitmap_clear_bit (sp_bytes, byte - min_sp_off);
|
||||
}
|
||||
|
||||
if (!deletable_insn_p (insn, fast, NULL))
|
||||
break;
|
||||
|
||||
if (do_mark)
|
||||
mark_insn (insn, fast);
|
||||
else
|
||||
bitmap_set_bit (arg_stores, INSN_UID (insn));
|
||||
|
||||
if (bitmap_empty_p (sp_bytes))
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BITMAP_FREE (sp_bytes);
|
||||
if (!ret && arg_stores)
|
||||
bitmap_clear (arg_stores);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Delete all REG_EQUAL notes of the registers INSN writes, to prevent
|
||||
bad dangling REG_EQUAL notes. */
|
||||
|
||||
@ -266,6 +522,9 @@ delete_unmarked_insns (void)
|
||||
else if (marked_insn_p (insn))
|
||||
continue;
|
||||
|
||||
/* Beware that reaching a dbg counter limit here can easily result
|
||||
in miscompiled file, whenever some insn is eliminated, but
|
||||
insn that depends on it is not. */
|
||||
if (!dbg_cnt (dce))
|
||||
continue;
|
||||
|
||||
@ -300,20 +559,37 @@ static void
|
||||
prescan_insns_for_dce (bool fast)
|
||||
{
|
||||
basic_block bb;
|
||||
rtx insn, next;
|
||||
|
||||
rtx insn, prev;
|
||||
bitmap arg_stores = NULL;
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Finding needed instructions:\n");
|
||||
|
||||
|
||||
if (!df_in_progress && ACCUMULATE_OUTGOING_ARGS)
|
||||
arg_stores = BITMAP_ALLOC (NULL);
|
||||
|
||||
FOR_EACH_BB (bb)
|
||||
FOR_BB_INSNS_SAFE (bb, insn, next)
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
if (deletable_insn_p (insn, fast))
|
||||
mark_nonreg_stores (PATTERN (insn), insn, fast);
|
||||
else
|
||||
mark_insn (insn, fast);
|
||||
}
|
||||
{
|
||||
FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev)
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
/* Don't mark argument stores now. They will be marked
|
||||
if needed when the associated CALL is marked. */
|
||||
if (arg_stores && bitmap_bit_p (arg_stores, INSN_UID (insn)))
|
||||
continue;
|
||||
if (deletable_insn_p (insn, fast, arg_stores))
|
||||
mark_nonreg_stores (PATTERN (insn), insn, fast);
|
||||
else
|
||||
mark_insn (insn, fast);
|
||||
}
|
||||
/* find_call_stack_args only looks at argument stores in the
|
||||
same bb. */
|
||||
if (arg_stores)
|
||||
bitmap_clear (arg_stores);
|
||||
}
|
||||
|
||||
if (arg_stores)
|
||||
BITMAP_FREE (arg_stores);
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Finished finding needed instructions:\n");
|
||||
|
@ -1,3 +1,11 @@
|
||||
2009-01-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR rtl-optimization/38245
|
||||
* gcc.dg/pr38245-3.c: New test.
|
||||
* gcc.dg/pr38245-3.h: New file.
|
||||
* gcc.dg/pr38245-4.c: New file.
|
||||
* gcc.dg/pr38364.c: New test.
|
||||
|
||||
2009-01-14 Adam Nemet <anemet@caviumnetworks.com>
|
||||
|
||||
* gcc.target/mips/mips.exp (mips_option_tests(-mips16)): Make the
|
||||
|
112
gcc/testsuite/gcc.dg/pr38245-3.c
Normal file
112
gcc/testsuite/gcc.dg/pr38245-3.c
Normal file
@ -0,0 +1,112 @@
|
||||
/* PR rtl-optimization/38245 */
|
||||
/* { dg-do run } */
|
||||
/* { dg-additional-sources "pr38245-4.c" } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
#include "pr38245-3.h"
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
struct A { int i, j; union { short s[4]; long long l; }; char pad[512]; } a;
|
||||
int globv = 6;
|
||||
|
||||
void __attribute__((noinline))
|
||||
f1 (void)
|
||||
{
|
||||
a.s[2] = b1 (6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21);
|
||||
a.l = 6;
|
||||
}
|
||||
|
||||
void __attribute__((noinline))
|
||||
f2 (void)
|
||||
{
|
||||
a.s[2] = b2 (6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21);
|
||||
a.l = 6;
|
||||
}
|
||||
|
||||
void __attribute__((noinline))
|
||||
f3 (void)
|
||||
{
|
||||
struct B b = { 30, 31, { 32, 33 } };
|
||||
a.s[2] = b3 (6, 7, 8, 9, 10, 11, 12, b, 14, b, 16, b, 18, 19, 20, 21,
|
||||
6, b, 8, b, 10, 11, 12, 13, 14, b, 16, b, 18, 19, 20, 21);
|
||||
a.l = 6;
|
||||
}
|
||||
|
||||
void __attribute__((noinline))
|
||||
f4 (void)
|
||||
{
|
||||
struct B b = { 30, 31, { 32, 33 } };
|
||||
a.s[2] = b4 (6, 7, 8, 9, 10, 11, 12, b, 14, b, 16, b, 18, 19, 20, 21,
|
||||
6, b, 8, b, 10, 11, 12, 13, 14, b, 16, b, 18, 19, 20, 21);
|
||||
a.l = 6;
|
||||
}
|
||||
|
||||
void __attribute__((noinline))
|
||||
f5 (void)
|
||||
{
|
||||
a.s[2] = b5 (6.0, 7, 8, 9, 10, 11, 21.0, 22.0, 23.0);
|
||||
a.l = 6;
|
||||
}
|
||||
|
||||
void __attribute__((noinline))
|
||||
f6 (void)
|
||||
{
|
||||
a.s[2] = b6 (6.0, 7, 8, 9, 10, 11, 21.0, 22.0, 23.0);
|
||||
a.l = 6;
|
||||
}
|
||||
|
||||
void __attribute__((noinline))
|
||||
f7 (void)
|
||||
{
|
||||
a.s[2] = b7 (6, 7);
|
||||
a.l = 6;
|
||||
}
|
||||
|
||||
void __attribute__((noinline))
|
||||
f8 (void)
|
||||
{
|
||||
a.s[2] = b8 (6, 7);
|
||||
a.l = 6;
|
||||
}
|
||||
|
||||
void __attribute__((noinline))
|
||||
f9 (void)
|
||||
{
|
||||
a.s[2] = b9 (6, 7, 8, 9, 10, 11, 12);
|
||||
a.l = 6;
|
||||
}
|
||||
|
||||
void __attribute__((noinline))
|
||||
f10 (void)
|
||||
{
|
||||
a.s[2] = b10 (6, 7, 8, 9, 10, 11, 12);
|
||||
a.l = 6;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
char buf[256];
|
||||
int i;
|
||||
for (i = 0; i < (int) sizeof buf; i++)
|
||||
buf[i] = i;
|
||||
asm volatile ("" : : "r" (buf) : "memory");
|
||||
f1 ();
|
||||
f2 ();
|
||||
f3 ();
|
||||
f4 ();
|
||||
f5 ();
|
||||
f6 ();
|
||||
f7 ();
|
||||
f8 ();
|
||||
f9 ();
|
||||
f10 ();
|
||||
asm volatile ("" : : "r" (buf) : "memory");
|
||||
for (i = 0; i < (int) sizeof buf; i++)
|
||||
if (buf[i] != (char) i)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
35
gcc/testsuite/gcc.dg/pr38245-3.h
Normal file
35
gcc/testsuite/gcc.dg/pr38245-3.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* PR rtl-optimization/38245 */
|
||||
|
||||
struct B { long a, b; char p[32]; };
|
||||
extern int globv;
|
||||
|
||||
extern int b1 (long long, long, long, long, long, long, long, long,
|
||||
long long, long, long, long, long, long, long, long,
|
||||
long long, long, long, long, long, long, long, long,
|
||||
long long, long, long, long, long, long, long, long)
|
||||
__attribute__((pure, noinline));
|
||||
extern int b2 (long long, long, long, long, long, long, long, long,
|
||||
long long, long, long, long, long, long, long, long,
|
||||
long long, long, long, long, long, long, long, long,
|
||||
long long, long, long, long, long, long, long, long)
|
||||
__attribute__((const, noinline));
|
||||
extern int b3 (long long, long, long, long, long, long, long, struct B,
|
||||
long long, struct B, long, struct B, long, long, long, long,
|
||||
long long, struct B, long, struct B, long, long, long, long,
|
||||
long long, struct B, long, struct B, long, long, long, long)
|
||||
__attribute__((pure, noinline));
|
||||
extern int b4 (long long, long, long, long, long, long, long, struct B,
|
||||
long long, struct B, long, struct B, long, long, long, long,
|
||||
long long, struct B, long, struct B, long, long, long, long,
|
||||
long long, struct B, long, struct B, long, long, long, long)
|
||||
__attribute__((const, noinline));
|
||||
extern int b5 () __attribute__((pure, noinline));
|
||||
extern int b6 () __attribute__((const, noinline));
|
||||
extern int b7 (int, int)
|
||||
__attribute__((pure, noinline));
|
||||
extern int b8 (int, int)
|
||||
__attribute__((const, noinline));
|
||||
extern int b9 (int, int, int, int, int, int, int)
|
||||
__attribute__((pure, noinline));
|
||||
extern int b10 (int, int, int, int, int, int, int)
|
||||
__attribute__((const, noinline));
|
107
gcc/testsuite/gcc.dg/pr38245-4.c
Normal file
107
gcc/testsuite/gcc.dg/pr38245-4.c
Normal file
@ -0,0 +1,107 @@
|
||||
/* PR rtl-optimization/38245 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "" } */
|
||||
|
||||
#include "pr38245-3.h"
|
||||
|
||||
int
|
||||
b1 (long long a1, long a2, long a3, long a4,
|
||||
long a5, long a6, long a7, long a8,
|
||||
long long a9, long a10, long a11, long a12,
|
||||
long a13, long a14, long a15, long a16,
|
||||
long long a17, long a18, long a19, long a20,
|
||||
long a21, long a22, long a23, long a24,
|
||||
long long a25, long a26, long a27, long a28,
|
||||
long a29, long a30, long a31, long a32)
|
||||
{
|
||||
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10
|
||||
+ a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20
|
||||
+ a21 + a22 + a23 + a24 + a25 + a26 + a27 + a28 + a29 + a30
|
||||
+ a31 + a32 + globv;
|
||||
}
|
||||
|
||||
int
|
||||
b2 (long long a1, long a2, long a3, long a4,
|
||||
long a5, long a6, long a7, long a8,
|
||||
long long a9, long a10, long a11, long a12,
|
||||
long a13, long a14, long a15, long a16,
|
||||
long long a17, long a18, long a19, long a20,
|
||||
long a21, long a22, long a23, long a24,
|
||||
long long a25, long a26, long a27, long a28,
|
||||
long a29, long a30, long a31, long a32)
|
||||
{
|
||||
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10
|
||||
+ a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20
|
||||
+ a21 + a22 + a23 + a24 + a25 + a26 + a27 + a28 + a29 + a30
|
||||
+ a31 + a32;
|
||||
}
|
||||
|
||||
int
|
||||
b3 (long long a1, long a2, long a3, long a4,
|
||||
long a5, long a6, long a7, struct B a8,
|
||||
long long a9, struct B a10, long a11, struct B a12,
|
||||
long a13, long a14, long a15, long a16,
|
||||
long long a17, struct B a18, long a19, struct B a20,
|
||||
long a21, long a22, long a23, long a24,
|
||||
long long a25, struct B a26, long a27, struct B a28,
|
||||
long a29, long a30, long a31, long a32)
|
||||
{
|
||||
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8.a + a9 + a10.a
|
||||
+ a11 + a12.a + a13 + a14 + a15 + a16 + a17 + a18.a + a19 + a20.a
|
||||
+ a21 + a22 + a23 + a24 + a25 + a26.a + a27 + a28.a + a29 + a30
|
||||
+ a31 + a32 + globv;
|
||||
}
|
||||
|
||||
int
|
||||
b4 (long long a1, long a2, long a3, long a4,
|
||||
long a5, long a6, long a7, struct B a8,
|
||||
long long a9, struct B a10, long a11, struct B a12,
|
||||
long a13, long a14, long a15, long a16,
|
||||
long long a17, struct B a18, long a19, struct B a20,
|
||||
long a21, long a22, long a23, long a24,
|
||||
long long a25, struct B a26, long a27, struct B a28,
|
||||
long a29, long a30, long a31, long a32)
|
||||
{
|
||||
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8.a + a9 + a10.a
|
||||
+ a11 + a12.a + a13 + a14 + a15 + a16 + a17 + a18.a + a19 + a20.a
|
||||
+ a21 + a22 + a23 + a24 + a25 + a26.a + a27 + a28.a + a29 + a30
|
||||
+ a31 + a32;
|
||||
}
|
||||
|
||||
int
|
||||
b5 (double a1, int a2, int a3, int a4, int a5, int a6, double a7,
|
||||
double a8, double a9)
|
||||
{
|
||||
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + globv;
|
||||
}
|
||||
|
||||
int
|
||||
b6 (double a1, int a2, int a3, int a4, int a5, int a6, double a7,
|
||||
double a8, double a9)
|
||||
{
|
||||
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
|
||||
}
|
||||
|
||||
int
|
||||
b7 (int a1, int a2)
|
||||
{
|
||||
return a1 + a2 + globv;
|
||||
}
|
||||
|
||||
int
|
||||
b8 (int a1, int a2)
|
||||
{
|
||||
return a1 + a2;
|
||||
}
|
||||
|
||||
int
|
||||
b9 (int a1, int a2, int a3, int a4, int a5, int a6, int a7)
|
||||
{
|
||||
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + globv;
|
||||
}
|
||||
|
||||
int
|
||||
b10 (int a1, int a2, int a3, int a4, int a5, int a6, int a7)
|
||||
{
|
||||
return a1 + a2 + a3 + a4 + a5 + a6 + a7;
|
||||
}
|
79
gcc/testsuite/gcc.dg/pr38364.c
Normal file
79
gcc/testsuite/gcc.dg/pr38364.c
Normal file
@ -0,0 +1,79 @@
|
||||
/* PR middle-end/38364 */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -ftrapv" } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
static inline short
|
||||
f1 (short x, short y)
|
||||
{
|
||||
if (x > 0)
|
||||
{
|
||||
if (y > 0)
|
||||
{
|
||||
if (x > __SHRT_MAX__ / y)
|
||||
return x;
|
||||
}
|
||||
else if (y < (-__SHRT_MAX__ - 1) / x)
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (y > 0)
|
||||
{
|
||||
if (x < (-__SHRT_MAX__ - 1) / y)
|
||||
return x;
|
||||
}
|
||||
else if (x != 0 && y < __SHRT_MAX__ / x)
|
||||
return x;
|
||||
}
|
||||
return x * y;
|
||||
}
|
||||
|
||||
static inline signed char
|
||||
f2 (signed char x, signed char y)
|
||||
{
|
||||
if (((x ^ y) & (((x ^ ((x ^ y) & (1 << (__CHAR_BIT__ - 1)))) - y) ^ y)) < 0)
|
||||
return x;
|
||||
return x - y;
|
||||
}
|
||||
|
||||
unsigned int v;
|
||||
|
||||
int
|
||||
f3 (int x, unsigned int y)
|
||||
{
|
||||
f1 (1, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
f4 (unsigned short x)
|
||||
{
|
||||
v = x;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
f5 (int x)
|
||||
{
|
||||
if (f2 (x, 1))
|
||||
f1 (1, f4 (1));
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
f6 (unsigned int x)
|
||||
{
|
||||
f4 (x < (1 != f5 (0)));
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
f6 (1);
|
||||
if (v != 0)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user