This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Bad MEM_SIZE for cmpmem causes wrong scheduling
- From: Ulrich Weigand <weigand at i1 dot informatik dot uni-erlangen dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 24 Sep 2004 18:02:17 +0200 (CEST)
- Subject: [PATCH] Bad MEM_SIZE for cmpmem causes wrong scheduling
Hello,
I'm seeing testsuite failures in gcc.c-torture/execute/builtins/strpcpy.c
which are caused by the scheduler missing a dependency. The code in
question does something equivalent to
unsigned char a[16] = "";
memcpy (a + 2, "ab", 3);
if (memcmp (a + 1, "\0" "ab" "\0", 4))
abort ();
which gets expanded into a movmem insn followed by a cmpmem insn.
However, the scheduler reverses the order of the two insns.
This is caused by the MEM_SIZE attribute of the first argument of
the cmpmem insn being 1, which causes the scheduler to think there
is no dependency (because a+1/len1 doesn't overlap a+2/len3).
The following patch fixes the problem by simply setting MEM_SIZE
to the actual comparison length if that is known at compile-time.
This is analogous to what's being done for movmem in expr.c
(emit_block_move).
While this does fix the strpcpy.c test case, I'm not quite sure
this is the proper solution; shouldn't get_memory_rtx have
recognized that the whole array 'a' could potentially be the
target of the memcmp?
Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux.
OK for mainline?
Bye,
Ulrich
ChangeLog:
* builtins.c (expand_builtin_memcmp): Adjust MEM_SIZE to
reflect size of memory regions being compared.
Index: gcc/builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.386
diff -c -p -r1.386 builtins.c
*** gcc/builtins.c 20 Sep 2004 14:47:17 -0000 1.386
--- gcc/builtins.c 22 Sep 2004 23:37:43 -0000
*************** expand_builtin_memcmp (tree exp ATTRIBUT
*** 3537,3542 ****
--- 3537,3550 ----
arg1_rtx = get_memory_rtx (arg1);
arg2_rtx = get_memory_rtx (arg2);
arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+
+ /* Set MEM_SIZE as appropriate. */
+ if (GET_CODE (arg3_rtx) == CONST_INT)
+ {
+ set_mem_size (arg1_rtx, arg3_rtx);
+ set_mem_size (arg2_rtx, arg3_rtx);
+ }
+
#ifdef HAVE_cmpmemsi
if (HAVE_cmpmemsi)
insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
--
Dr. Ulrich Weigand
weigand@informatik.uni-erlangen.de