This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] CONSTANT_ALIGNMENT is missed in builtins.c
- From: Adam Nemet <anemet at caviumnetworks dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 31 Aug 2006 16:10:08 -0700
- Subject: [PATCH] CONSTANT_ALIGNMENT is missed in builtins.c
The function builtins.c:get_pointer_alignment does not apply
CONSTANT_ALIGNMENT to constant strings at least in some cases. For
example in:
memcpy (c, "123456", 6);
get_pointer_alignment is invoked with
<ADDR_EXRP <ARRAY_REF <STRING_CST> 0>>
and returns the alignment of type char because it is unprepared to
deal with ARRAY_REFs.
In the patch I use extract_array_ref to either simplify the expression
into <ADDR_EXRP <STRING_CST>> or to lower into pointer arithmetic both
of which are readily recognized by get_pointer_alignment.
Now even things like &"12345678"[2] are handled correctly.
This is a code-quality regression relative to 3.4. The patch also
adds a new MIPS testcase. Bootstrapped and tested on
x86_64-unknown-linux-gnu and tested on mipsisa64-elf.
OK to install?
* tree.h (extract_array_ref): Declare it.
* fold-const.c (extract_array_ref): Export it.
* builtins.c (get_pointer_alignment): Use extract_array_ref to
handle ARRAY_REFs.
* gcc.target/mips/memcpy-1.c: New test.
Index: tree.h
===================================================================
--- tree.h (revision 116501)
+++ tree.h (working copy)
@@ -4268,6 +4268,8 @@ extern enum tree_code invert_tree_compar
extern bool tree_expr_nonzero_p (tree);
+bool extract_array_ref (tree expr, tree *, tree *);
+
/* In builtins.c */
extern tree fold_builtin (tree, tree, bool);
extern tree fold_builtin_fputs (tree, bool, bool, tree);
Index: builtins.c
===================================================================
--- builtins.c (revision 116501)
+++ builtins.c (working copy)
@@ -234,6 +234,7 @@ static int
get_pointer_alignment (tree exp, unsigned int max_align)
{
unsigned int align, inner;
+ tree base, offset;
if (! POINTER_TYPE_P (TREE_TYPE (exp)))
return 0;
@@ -241,6 +242,18 @@ get_pointer_alignment (tree exp, unsigne
align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
align = MIN (align, max_align);
+ /* Lower ARRAY_REFs into pointer arithmetic. */
+ if (extract_array_ref (exp, &base, &offset))
+ {
+ /* extract_array_ref strips ADDR_EXPR in front of ARRAY_TYPEs. */
+ if (TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
+ base = fold_build1 (ADDR_EXPR, TREE_TYPE (exp), base);
+
+ if (offset)
+ base = fold_build2 (PLUS_EXPR, TREE_TYPE (exp), base, offset);
+ exp = base;
+ }
+
while (1)
{
switch (TREE_CODE (exp))
Index: fold-const.c
===================================================================
--- fold-const.c (revision 116501)
+++ fold-const.c (working copy)
@@ -5684,7 +5684,7 @@ constant_boolean_node (int value, tree t
TREE_TYPE (TREE_TYPE (base)). Offset will be the offset
in bytes to the base. */
-static bool
+bool
extract_array_ref (tree expr, tree *base, tree *offset)
{
/* One canonical form is a PLUS_EXPR with the first
Index: testsuite/gcc.target/mips/memcpy-1.c
===================================================================
--- testsuite/gcc.target/mips/memcpy-1.c (revision 0)
+++ testsuite/gcc.target/mips/memcpy-1.c (revision 0)
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2" } */
+/* { dg-final { scan-assembler-not "\tlbu\t" } } */
+
+#include <string.h>
+
+char c[10];
+
+void
+f1 ()
+{
+ memcpy (c, "123456", 6);
+}
+
+void
+f2 ()
+{
+ memcpy (c, &"12345678"[2], 6);
+}