re PR middle-end/27226 (Compiler looses track of alignment for emit_block_move)
authorJ"orn Rennecke <joern.rennecke@st.com>
Fri, 1 Sep 2006 20:25:34 +0000 (20:25 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 1 Sep 2006 20:25:34 +0000 (20:25 +0000)
2006-09-01  J"orn Rennecke  <joern.rennecke@st.com>
Richard Guenther  <rguenther@suse.de>
Adam Nemet  <anemet@caviumnetworks.com>

PR middle-end/27226
* builtins.c (get_pointer_alignment): Handle more forms
of base addresses that can be used to derive more precise
information about alignment.

* gcc.target/mips/memcpy-1.c: New testcase.
* gcc.dg/pr27226.c: Likewise.

Co-Authored-By: Adam Nemet <anemet@caviumnetworks.com>
Co-Authored-By: Richard Guenther <rguenther@suse.de>
From-SVN: r116641

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr27226.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/memcpy-1.c [new file with mode: 0644]

index 242104b35e7d0ffe44d3bf68b216a42818811a4e..077b1c32a53db4938559aedb9670fb6242b79346 100644 (file)
@@ -1,3 +1,12 @@
+2006-09-01  J"orn Rennecke  <joern.rennecke@st.com>
+       Richard Guenther  <rguenther@suse.de>
+       Adam Nemet  <anemet@caviumnetworks.com>
+
+       PR middle-end/27226
+       * builtins.c (get_pointer_alignment): Handle more forms
+       of base addresses that can be used to derive more precise
+       information about alignment.
+
 2006-09-01  Jason Merrill  <jason@redhat.com>
 
        PR c++/28899
index 47c61cdb1332d376a092bf6f8aa2bd7aebd6bfc4..4aff7d09809462ffe4112af89285d98928a8f187 100644 (file)
@@ -275,16 +275,44 @@ get_pointer_alignment (tree exp, unsigned int max_align)
          /* See what we are pointing at and look at its alignment.  */
          exp = TREE_OPERAND (exp, 0);
          inner = max_align;
-         while (handled_component_p (exp))
+         if (handled_component_p (exp))
            {
-             /* Fields in a structure can be packed, honor DECL_ALIGN
-                of the FIELD_DECL.  For all other references the conservative
-                alignment is the element type alignment.  */
-             if (TREE_CODE (exp) == COMPONENT_REF)
-               inner = MIN (inner, DECL_ALIGN (TREE_OPERAND (exp, 1)));
-             else
-               inner = MIN (inner, TYPE_ALIGN (TREE_TYPE (exp)));
-             exp = TREE_OPERAND (exp, 0);
+             HOST_WIDE_INT bitsize, bitpos;
+             tree offset;
+             enum machine_mode mode; 
+             int unsignedp, volatilep;
+
+             exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
+                                        &mode, &unsignedp, &volatilep, true);
+             if (bitpos)
+               inner = MIN (inner, (unsigned) (bitpos & -bitpos));
+             if (offset && TREE_CODE (offset) == PLUS_EXPR
+                 && host_integerp (TREE_OPERAND (offset, 1), 1))
+               {
+                 /* Any overflow in calculating offset_bits won't change
+                    the alignment.  */
+                 unsigned offset_bits
+                   = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
+                      * BITS_PER_UNIT);
+
+                 if (offset_bits)
+                   inner = MIN (inner, (offset_bits & -offset_bits));
+                 offset = TREE_OPERAND (offset, 0);
+               }
+             if (offset && TREE_CODE (offset) == MULT_EXPR
+                 && host_integerp (TREE_OPERAND (offset, 1), 1))
+               {
+                 /* Any overflow in calculating offset_factor won't change
+                    the alignment.  */
+                 unsigned offset_factor
+                   = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
+                      * BITS_PER_UNIT);
+
+                 if (offset_factor)
+                   inner = MIN (inner, (offset_factor & -offset_factor));
+               }
+             else if (offset)
+               inner = MIN (inner, BITS_PER_UNIT);
            }
          if (TREE_CODE (exp) == FUNCTION_DECL)
            align = FUNCTION_BOUNDARY;
@@ -294,6 +322,9 @@ get_pointer_alignment (tree exp, unsigned int max_align)
          else if (CONSTANT_CLASS_P (exp))
            align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
 #endif
+         else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
+                  || TREE_CODE (exp) == INDIRECT_REF)
+           align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
          else
            align = MIN (align, inner);
          return MIN (align, max_align);
index 530c23e2aae2f34243f7a36b9e6a273346fe5ad2..e4210b84567d2fa1f74746da7817f207821fdb47 100644 (file)
@@ -1,3 +1,11 @@
+2006-09-01  J"orn Rennecke  <joern.rennecke@st.com>
+       Richard Guenther  <rguenther@suse.de>
+       Adam Nemet  <anemet@caviumnetworks.com>
+
+       PR middle-end/27226
+       * gcc.target/mips/memcpy-1.c: New testcase.
+       * gcc.dg/pr27226.c: Likewise.
+
 2006-09-01  Nathan Sidwell  <nathan@codesourcery.com>
 
        PR c++/28705
diff --git a/gcc/testsuite/gcc.dg/pr27226.c b/gcc/testsuite/gcc.dg/pr27226.c
new file mode 100644 (file)
index 0000000..df77a8c
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+char *strcpy (char *, const char *);
+
+extern void g ();
+
+f ()
+{
+  struct {
+    int i;
+    char str[31];
+  } s;
+
+  strcpy (s.str, "text text text text text text text text");
+  g (s.str);
+}
+
+/* { dg-final { scan-assembler-not "memcpy" } } */
diff --git a/gcc/testsuite/gcc.target/mips/memcpy-1.c b/gcc/testsuite/gcc.target/mips/memcpy-1.c
new file mode 100644 (file)
index 0000000..4e50b20
--- /dev/null
@@ -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);
+}