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:
Jakub Jelinek 2009-01-15 09:07:38 +01:00 committed by Jakub Jelinek
parent 6df6bcfa0f
commit 0196c95ed4
9 changed files with 676 additions and 35 deletions

View File

@ -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

View File

@ -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 \

View File

@ -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
View File

@ -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");

View File

@ -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

View 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;
}

View 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));

View 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;
}

View 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;
}