Commit 8dd5516b by Jakub Jelinek Committed by Jakub Jelinek

re PR middle-end/31150 (Not promoting an whole array to be static const)

	PR middle-end/31150
	* dse.c (struct store_info): Add const_rhs field.
	(clear_rhs_from_active_local_stores): Clear also const_rhs.
	(record_store): Try also cselib_expand_value_rtx to get a constant.
	(find_shift_sequence, get_stored_val): Use const_rhs instead of
	rhs if worthwhile.
	* cselib.c (cselib_record_sets): If !cselib_record_memory and
	there is just one set from read-only MEM, look at REG_EQUAL or
	REG_EQUIV note.

	* dse.c (struct store_info): Add redundant_reason field.
	(record_store): When storing the same constant as has been
	stored by an earlier store, set redundant_reason field
	to the earlier store's insn_info_t.  Don't delete cannot_delete
	insns.
	(find_shift_sequence): Remove read_info argument, add read_mode
	and require_cst arguments.  Return early if require_cst and
	constant wouldn't be returned.
	(get_stored_val): New function.
	(replace_read): Use it.
	(scan_insn): Put even cannot_delete insns with exactly 1 store
	into active_local_stores.
	(dse_step1): Don't delete cannot_delete insns.  Remove redundant
	constant stores if contains_cselib_groups and earlier store storing
	the same value hasn't been eliminated.
	(dse_step6): Renamed to dse_step7.  New function.
	(dse_step7): Renamed from dse_step6.
	(rest_of_handle_dse): Call dse_step6 and dse_step7 at the end.
	* cselib.c (cselib_expand_value_rtx): Don't wrap CONST_INTs
	into CONST unless really necessary.  Handle SUBREG, unary,
	ternary, bitfield and compares specially, to be able to simplify
	operations on constants.
	(expand_loc): Try to optimize LO_SUM.

	* dse.c (get_call_args): New function.
	(scan_insn): Don't handle BUILT_IN_BZERO.  For memset, attempt
	to get call arguments and if successful and both len and val are
	constants, handle the call as (mem:BLK) (const_int) store.

	* dse.c (struct store_info): Add is_large bool field, change
	positions_needed into a union of a bitmask and bitmap + count.
	(free_store_info): Free bitmap if is_large.
	(set_usage_bits): Don't look at stores where
	offset + width >= MAX_OFFSET.
	(set_position_unneeded, set_all_positions_unneeded,
	any_positions_needed_p, all_positions_needed_p): New static inline
	functions.
	(record_store): Handle BLKmode stores of CONST_INT, if
	MEM_SIZE is set on the MEM.  Use the new positions_needed
	accessor inlines.
	(replace_read): Handle reads from BLKmode CONST_INT stores.
	(check_mem_read_rtx): Use all_positions_needed_p function.
	(dse_step1): Free large positions_needed bitmaps and clear is_large.

	* dse.c (struct store_info): Change begin and end types to
	HOST_WIDE_INT.

	* dse.c (record_store): Fix check for unused store.

	* expr.c (block_clear_fn): No longer static.
	* expr.h (block_clear_fn): Declare.
	* dse.c (scan_insn): Memset and bzero can just read their
	arguments.

	* gcc.c-torture/execute/20081218-1.c: New test.

From-SVN: r142892
parent 805903b5
2008-12-23 Jakub Jelinek <jakub@redhat.com>
PR middle-end/31150
* dse.c (struct store_info): Add const_rhs field.
(clear_rhs_from_active_local_stores): Clear also const_rhs.
(record_store): Try also cselib_expand_value_rtx to get a constant.
(find_shift_sequence, get_stored_val): Use const_rhs instead of
rhs if worthwhile.
* cselib.c (cselib_record_sets): If !cselib_record_memory and
there is just one set from read-only MEM, look at REG_EQUAL or
REG_EQUIV note.
* dse.c (struct store_info): Add redundant_reason field.
(record_store): When storing the same constant as has been
stored by an earlier store, set redundant_reason field
to the earlier store's insn_info_t. Don't delete cannot_delete
insns.
(find_shift_sequence): Remove read_info argument, add read_mode
and require_cst arguments. Return early if require_cst and
constant wouldn't be returned.
(get_stored_val): New function.
(replace_read): Use it.
(scan_insn): Put even cannot_delete insns with exactly 1 store
into active_local_stores.
(dse_step1): Don't delete cannot_delete insns. Remove redundant
constant stores if contains_cselib_groups and earlier store storing
the same value hasn't been eliminated.
(dse_step6): Renamed to dse_step7. New function.
(dse_step7): Renamed from dse_step6.
(rest_of_handle_dse): Call dse_step6 and dse_step7 at the end.
* cselib.c (cselib_expand_value_rtx): Don't wrap CONST_INTs
into CONST unless really necessary. Handle SUBREG, unary,
ternary, bitfield and compares specially, to be able to simplify
operations on constants.
(expand_loc): Try to optimize LO_SUM.
* dse.c (get_call_args): New function.
(scan_insn): Don't handle BUILT_IN_BZERO. For memset, attempt
to get call arguments and if successful and both len and val are
constants, handle the call as (mem:BLK) (const_int) store.
* dse.c (struct store_info): Add is_large bool field, change
positions_needed into a union of a bitmask and bitmap + count.
(free_store_info): Free bitmap if is_large.
(set_usage_bits): Don't look at stores where
offset + width >= MAX_OFFSET.
(set_position_unneeded, set_all_positions_unneeded,
any_positions_needed_p, all_positions_needed_p): New static inline
functions.
(record_store): Handle BLKmode stores of CONST_INT, if
MEM_SIZE is set on the MEM. Use the new positions_needed
accessor inlines.
(replace_read): Handle reads from BLKmode CONST_INT stores.
(check_mem_read_rtx): Use all_positions_needed_p function.
(dse_step1): Free large positions_needed bitmaps and clear is_large.
* dse.c (struct store_info): Change begin and end types to
HOST_WIDE_INT.
* dse.c (record_store): Fix check for unused store.
* expr.c (block_clear_fn): No longer static.
* expr.h (block_clear_fn): Declare.
* dse.c (scan_insn): Memset and bzero can just read their
arguments.
* config/i386/i386.c (expand_setmem_via_rep_stos): Add ORIG_VALUE
argument. If ORIG_VALUE is const0_rtx and COUNT is constant,
set MEM_SIZE on DESTMEM.
/* Common subexpression elimination library for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GCC.
......@@ -865,12 +866,18 @@ expand_loc (struct elt_loc_list *p, bitmap regs_active, int max_depth)
continue;
else if (!REG_P (p->loc))
{
rtx result;
rtx result, note;
if (dump_file)
{
print_inline_rtx (dump_file, p->loc, 0);
fprintf (dump_file, "\n");
}
if (GET_CODE (p->loc) == LO_SUM
&& GET_CODE (XEXP (p->loc, 1)) == SYMBOL_REF
&& p->setting_insn
&& (note = find_reg_note (p->setting_insn, REG_EQUAL, NULL_RTX))
&& XEXP (note, 0) == XEXP (p->loc, 1))
return XEXP (p->loc, 1);
result = cselib_expand_value_rtx (p->loc, regs_active, max_depth - 1);
if (result)
return result;
......@@ -928,6 +935,7 @@ cselib_expand_value_rtx (rtx orig, bitmap regs_active, int max_depth)
int i, j;
RTX_CODE code;
const char *format_ptr;
enum machine_mode mode;
code = GET_CODE (orig);
......@@ -1007,25 +1015,30 @@ cselib_expand_value_rtx (rtx orig, bitmap regs_active, int max_depth)
return orig;
break;
case VALUE:
case SUBREG:
{
rtx result;
if (dump_file)
fprintf (dump_file, "expanding value %s into: ", GET_MODE_NAME (GET_MODE (orig)));
result = expand_loc (CSELIB_VAL_PTR (orig)->locs, regs_active, max_depth);
if (result
&& GET_CODE (result) == CONST_INT
&& GET_MODE (orig) != VOIDmode)
{
result = gen_rtx_CONST (GET_MODE (orig), result);
if (dump_file)
fprintf (dump_file, " wrapping const_int result in const to preserve mode %s\n",
GET_MODE_NAME (GET_MODE (orig)));
}
return result;
rtx subreg = cselib_expand_value_rtx (SUBREG_REG (orig), regs_active,
max_depth - 1);
if (!subreg)
return NULL;
scopy = simplify_gen_subreg (GET_MODE (orig), subreg,
GET_MODE (SUBREG_REG (orig)),
SUBREG_BYTE (orig));
if (scopy == NULL
|| (GET_CODE (scopy) == SUBREG
&& !REG_P (SUBREG_REG (scopy))
&& !MEM_P (SUBREG_REG (scopy))))
return shallow_copy_rtx (orig);
return scopy;
}
case VALUE:
if (dump_file)
fprintf (dump_file, "expanding value %s into: ",
GET_MODE_NAME (GET_MODE (orig)));
return expand_loc (CSELIB_VAL_PTR (orig)->locs, regs_active, max_depth);
default:
break;
}
......@@ -1036,9 +1049,9 @@ cselib_expand_value_rtx (rtx orig, bitmap regs_active, int max_depth)
us to explicitly document why we are *not* copying a flag. */
copy = shallow_copy_rtx (orig);
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
format_ptr = GET_RTX_FORMAT (code);
for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
for (i = 0; i < GET_RTX_LENGTH (code); i++)
switch (*format_ptr++)
{
case 'e':
......@@ -1082,6 +1095,70 @@ cselib_expand_value_rtx (rtx orig, bitmap regs_active, int max_depth)
gcc_unreachable ();
}
mode = GET_MODE (copy);
/* If an operand has been simplified into CONST_INT, which doesn't
have a mode and the mode isn't derivable from whole rtx's mode,
try simplify_*_operation first with mode from original's operand
and as a fallback wrap CONST_INT into gen_rtx_CONST. */
scopy = copy;
switch (GET_RTX_CLASS (code))
{
case RTX_UNARY:
if (CONST_INT_P (XEXP (copy, 0))
&& GET_MODE (XEXP (orig, 0)) != VOIDmode)
{
scopy = simplify_unary_operation (code, mode, XEXP (copy, 0),
GET_MODE (XEXP (orig, 0)));
if (scopy)
return scopy;
}
break;
case RTX_COMM_ARITH:
case RTX_BIN_ARITH:
/* These expressions can derive operand modes from the whole rtx's mode. */
break;
case RTX_TERNARY:
case RTX_BITFIELD_OPS:
if (CONST_INT_P (XEXP (copy, 0))
&& GET_MODE (XEXP (orig, 0)) != VOIDmode)
{
scopy = simplify_ternary_operation (code, mode,
GET_MODE (XEXP (orig, 0)),
XEXP (copy, 0), XEXP (copy, 1),
XEXP (copy, 2));
if (scopy)
return scopy;
}
break;
case RTX_COMPARE:
case RTX_COMM_COMPARE:
if (CONST_INT_P (XEXP (copy, 0))
&& GET_MODE (XEXP (copy, 1)) == VOIDmode
&& (GET_MODE (XEXP (orig, 0)) != VOIDmode
|| GET_MODE (XEXP (orig, 1)) != VOIDmode))
{
scopy = simplify_relational_operation (code, mode,
(GET_MODE (XEXP (orig, 0))
!= VOIDmode)
? GET_MODE (XEXP (orig, 0))
: GET_MODE (XEXP (orig, 1)),
XEXP (copy, 0),
XEXP (copy, 1));
if (scopy)
return scopy;
}
break;
default:
break;
}
if (scopy == NULL_RTX)
{
XEXP (copy, 0)
= gen_rtx_CONST (GET_MODE (XEXP (orig, 0)), XEXP (copy, 0));
if (dump_file)
fprintf (dump_file, " wrapping const_int result in const to preserve mode %s\n",
GET_MODE_NAME (GET_MODE (XEXP (copy, 0))));
}
scopy = simplify_rtx (copy);
if (scopy)
return scopy;
......@@ -1581,6 +1658,17 @@ cselib_record_sets (rtx insn)
}
}
if (n_sets == 1
&& MEM_P (sets[0].src)
&& !cselib_record_memory
&& MEM_READONLY_P (sets[0].src))
{
rtx note = find_reg_equal_equiv_note (insn);
if (note && CONSTANT_P (XEXP (note, 0)))
sets[0].src = XEXP (note, 0);
}
/* Look up the values that are read. Do this before invalidating the
locations that are written. */
for (i = 0; i < n_sets; i++)
......
......@@ -2698,7 +2698,7 @@ set_storage_via_libcall (rtx object, rtx size, rtx val, bool tailcall)
for the function we use for block clears. The first time FOR_CALL
is true, we call assemble_external. */
static GTY(()) tree block_clear_fn;
tree block_clear_fn;
void
init_block_clear_fn (const char *asmspec)
......
......@@ -404,6 +404,7 @@ enum block_op_methods
BLOCK_OP_TAILCALL
};
extern tree GTY(()) block_clear_fn;
extern void init_block_move_fn (const char *);
extern void init_block_clear_fn (const char *);
......
2008-12-18 Jakub Jelinek <jakub@redhat.com>
PR middle-end/31150
* gcc.c-torture/execute/20081218-1.c: New test.
2008-12-22 Paul Thomas <pault@gcc.gnu.org>
PR fortran/35780
......
struct A { int i, j; char pad[512]; } a;
int __attribute__((noinline))
foo (void)
{
__builtin_memset (&a, 0x26, sizeof a);
return a.i;
}
void __attribute__((noinline))
bar (void)
{
__builtin_memset (&a, 0x36, sizeof a);
a.i = 0x36363636;
a.j = 0x36373636;
}
int
main (void)
{
int i;
if (sizeof (int) != 4 || __CHAR_BIT__ != 8)
return 0;
if (foo () != 0x26262626)
__builtin_abort ();
for (i = 0; i < sizeof a; i++)
if (((char *)&a)[i] != 0x26)
__builtin_abort ();
bar ();
if (a.j != 0x36373636)
__builtin_abort ();
a.j = 0x36363636;
for (i = 0; i < sizeof a; i++)
if (((char *)&a)[i] != 0x36)
__builtin_abort ();
return 0;
}
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