This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR31641: Fix S/390 setmem expander
- From: Andreas Krebbel <Andreas dot Krebbel at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Ulrich dot Weigand at de dot ibm dot com
- Date: Tue, 24 Apr 2007 10:03:38 +0200
- Subject: [PATCH] PR31641: Fix S/390 setmem expander
Hi,
this fixes the memset problem in PR31641. Although the testcase is broken
GCC should not response with an ICE.
The problem was a broken assertion in the back end. Instead of checking
whether the length argument to memset is below 0 using the INTVAL of the
argument we should take care to handle *large* values properly.
Bootstrapped on s390x.
No testsuite regressions.
Ok for mainline and 4.1 ? Since it is broken in 4.1 as well its not a new regression in 4.2.
Bye,
-Andreas-
2007-04-24 Andreas Krebbel <krebbel1@de.ibm.com>
PR target/31641
* config/s390/s390.c (s390_expand_setmem): Don't ICE for constant length
argument of 0 for memset.
(s390_expand_movmem, s390_expand_setmem, s390_expand_cmpmem): Use
unsigned shift instead of the signed variant.
2007-04-24 Andreas Krebbel <krebbel1@de.ibm.com>
PR target/31641
* gcc.c-torture/compile/pr31641.c: New testcase.
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig 2007-04-23 16:02:36.000000000 +0200
--- gcc/config/s390/s390.c 2007-04-23 16:50:06.000000000 +0200
*************** s390_expand_movmem (rtx dst, rtx src, rt
*** 3568,3574 ****
if (temp != count)
emit_move_insn (count, temp);
! temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0);
if (temp != blocks)
emit_move_insn (blocks, temp);
--- 3568,3574 ----
if (temp != count)
emit_move_insn (count, temp);
! temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1, 0);
if (temp != blocks)
emit_move_insn (blocks, temp);
*************** s390_expand_movmem (rtx dst, rtx src, rt
*** 3605,3614 ****
void
s390_expand_setmem (rtx dst, rtx len, rtx val)
{
! gcc_assert (GET_CODE (len) != CONST_INT || INTVAL (len) > 0);
gcc_assert (GET_CODE (val) == CONST_INT || GET_MODE (val) == QImode);
! if (GET_CODE (len) == CONST_INT && INTVAL (len) <= 257)
{
if (val == const0_rtx && INTVAL (len) <= 256)
emit_insn (gen_clrmem_short (dst, GEN_INT (INTVAL (len) - 1)));
--- 3605,3616 ----
void
s390_expand_setmem (rtx dst, rtx len, rtx val)
{
! if (GET_CODE (len) == CONST_INT && INTVAL (len) == 0)
! return;
!
gcc_assert (GET_CODE (val) == CONST_INT || GET_MODE (val) == QImode);
! if (GET_CODE (len) == CONST_INT && INTVAL (len) > 0 && INTVAL (len) <= 257)
{
if (val == const0_rtx && INTVAL (len) <= 256)
emit_insn (gen_clrmem_short (dst, GEN_INT (INTVAL (len) - 1)));
*************** s390_expand_setmem (rtx dst, rtx len, rt
*** 3682,3688 ****
if (temp != count)
emit_move_insn (count, temp);
! temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0);
if (temp != blocks)
emit_move_insn (blocks, temp);
--- 3684,3690 ----
if (temp != count)
emit_move_insn (count, temp);
! temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1, 0);
if (temp != blocks)
emit_move_insn (blocks, temp);
*************** s390_expand_cmpmem (rtx target, rtx op0,
*** 3774,3780 ****
if (temp != count)
emit_move_insn (count, temp);
! temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0);
if (temp != blocks)
emit_move_insn (blocks, temp);
--- 3776,3782 ----
if (temp != count)
emit_move_insn (count, temp);
! temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1, 0);
if (temp != blocks)
emit_move_insn (blocks, temp);
Index: gcc/testsuite/gcc.c-torture/compile/pr31641.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/compile/pr31641.c 2007-04-23 17:04:26.000000000 +0200
***************
*** 0 ****
--- 1,19 ----
+ /* This used to ICE on S/390 with -O1 when expanding
+ memset in the back end. */
+
+ typedef __SIZE_TYPE__ size_t;
+ extern void *memset(void *, int, size_t);
+
+ char *target;
+
+ void
+ foo ()
+ {
+ memset (target, 1, 0);
+ }
+
+ void
+ bar ()
+ {
+ memset (target, 1, -1);
+ }