This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]