OSDN Git Service

PR tree-optimization/51315
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 8 Dec 2011 09:12:12 +0000 (09:12 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 8 Dec 2011 09:12:12 +0000 (09:12 +0000)
* tree-sra.c (tree_non_mode_aligned_mem_p): Rename to...
(tree_non_aligned_mem_p): ...this.  Add ALIGN parameter.  Look into
MEM_REFs and use get_object_or_type_alignment for them.
(build_accesses_from_assign): Adjust for above change.
(access_precludes_ipa_sra_p): Likewise.
ada/
Backport from mainline
2011-09-25  Eric Botcazou  <ebotcazou@adacore.com>

* gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Do not promote
the alignment if this doesn't prevent BLKmode access to the object.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch@182103 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/gcc-interface/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20111208-1.c [new file with mode: 0644]
gcc/testsuite/gnat.dg/frame_overflow.adb
gcc/testsuite/gnat.dg/frame_overflow.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/addr1.ads
gcc/tree-sra.c

index 050e3cd..afb12fd 100644 (file)
@@ -1,3 +1,12 @@
+2011-12-08  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR tree-optimization/51315
+       * tree-sra.c (tree_non_mode_aligned_mem_p): Rename to...
+       (tree_non_aligned_mem_p): ...this.  Add ALIGN parameter.  Look into
+       MEM_REFs and use get_object_or_type_alignment for them.
+       (build_accesses_from_assign): Adjust for above change.
+       (access_precludes_ipa_sra_p): Likewise.
+
 2011-12-06  Martin Jambor  <mjambor@suse.cz>
 
        Backport from mainline:
index ef96695..b2c355d 100644 (file)
@@ -1,3 +1,12 @@
+2011-12-07  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR tree-optimization/51315
+       Backport from mainline
+       2011-09-25  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Do not promote
+       the alignment if this doesn't prevent BLKmode access to the object.
+
 2011-11-13  Iain Sandoe  <iains@gcc.gnu.org>
 
        Backport from mainline r181474
index 848dbf6..58459d4 100644 (file)
@@ -808,16 +808,30 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
                    && No (Address_Clause (gnat_entity))))
            && TREE_CODE (TYPE_SIZE (gnu_type)) == INTEGER_CST)
          {
-           /* No point in jumping through all the hoops needed in order
+           unsigned int size_cap, align_cap;
+
+           /* No point in promoting the alignment if this doesn't prevent
+              BLKmode access to the object, in particular block copy, as
+              this will for example disable the NRV optimization for it.
+              No point in jumping through all the hoops needed in order
               to support BIGGEST_ALIGNMENT if we don't really have to.
               So we cap to the smallest alignment that corresponds to
               a known efficient memory access pattern of the target.  */
-           unsigned int align_cap = Is_Atomic (gnat_entity)
-                                    ? BIGGEST_ALIGNMENT
-                                    : get_mode_alignment (ptr_mode);
+           if (Is_Atomic (gnat_entity))
+             {
+               size_cap = UINT_MAX;
+               align_cap = BIGGEST_ALIGNMENT;
+             }
+           else
+             {
+               size_cap = MAX_FIXED_MODE_SIZE;
+               align_cap = get_mode_alignment (ptr_mode);
+             }
 
            if (!host_integerp (TYPE_SIZE (gnu_type), 1)
-               || compare_tree_int (TYPE_SIZE (gnu_type), align_cap) >= 0)
+               || compare_tree_int (TYPE_SIZE (gnu_type), size_cap) > 0)
+             align = 0;
+           else if (compare_tree_int (TYPE_SIZE (gnu_type), align_cap) > 0)
              align = align_cap;
            else
              align = ceil_alignment (tree_low_cst (TYPE_SIZE (gnu_type), 1));
index 6987613..1e53669 100644 (file)
@@ -1,3 +1,14 @@
+2011-12-08  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.c-torture/execute/20111208-1.c: New test.
+
+       Backport from mainline
+       2011-09-25  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/frame_overflow.ads: New.
+       * gnat.dg/frame_overflow.adb: Adjust.
+       * gnat.dg/specs/addr1.ads: Likewise.
+
 2011-12-06  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/51435
diff --git a/gcc/testsuite/gcc.c-torture/execute/20111208-1.c b/gcc/testsuite/gcc.c-torture/execute/20111208-1.c
new file mode 100644 (file)
index 0000000..8bcb10a
--- /dev/null
@@ -0,0 +1,94 @@
+/* PR tree-optimization/51315 */
+/* Reported by Jurij Smakov <jurij@wooyd.org> */
+
+typedef unsigned int size_t;
+
+extern void *memcpy (void *__restrict __dest,
+       __const void *__restrict __src, size_t __n)
+     __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2)));
+
+extern size_t strlen (__const char *__s)
+     __attribute__ ((__nothrow__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+
+typedef short int int16_t;
+typedef int int32_t;
+
+extern void abort (void);
+
+int a;
+
+static void __attribute__ ((noinline,noclone))
+do_something (int item)
+{
+  a = item;
+}
+
+int
+pack_unpack (char *s, char *p)
+{
+  char *send, *pend;
+  char type;
+  int integer_size;
+
+  send = s + strlen (s);
+  pend = p + strlen (p);
+
+  while (p < pend)
+    {
+      type = *p++;
+
+      switch (type)
+ {
+ case 's':
+   integer_size = 2;
+   goto unpack_integer;
+
+ case 'l':
+   integer_size = 4;
+   goto unpack_integer;
+
+ unpack_integer:
+   switch (integer_size)
+     {
+     case 2:
+       {
+  union
+  {
+    int16_t i;
+    char a[sizeof (int16_t)];
+  }
+  v;
+  memcpy (v.a, s, sizeof (int16_t));
+  s += sizeof (int16_t);
+  do_something (v.i);
+       }
+       break;
+
+     case 4:
+       {
+  union
+  {
+    int32_t i;
+    char a[sizeof (int32_t)];
+  }
+  v;
+  memcpy (v.a, s, sizeof (int32_t));
+  s += sizeof (int32_t);
+  do_something (v.i);
+       }
+       break;
+     }
+   break;
+ }
+    }
+  return (int) *s;
+}
+
+int
+main (void)
+{
+  int n = pack_unpack ("\200\001\377\376\035\300", "sl");
+  if (n != 0)
+    abort ();
+  return 0;
+}
index e1ff4d3..1e7405f 100644 (file)
@@ -1,27 +1,20 @@
 -- { dg-do compile }
 
-with System;
+package body Frame_Overflow is
 
-procedure frame_overflow is
-
-   type Bitpos_Range_T is range 1..2**(System.Word_Size-1)-1;
-   type Bitmap_Array_T is array (Bitpos_Range_T) of Boolean;
-
-   type Bitmap_T is record
-      Bits : Bitmap_Array_T := (others => False);
-   end record;
-
-   function
+   function -- { dg-error "too large" }
      Set_In (Bitmap : Bitmap_T; Bitpos : Bitpos_Range_T)  return Bitmap_T
    is
-      Result: Bitmap_T := Bitmap; -- { dg-error "Storage_Error" }
+      Result: Bitmap_T := Bitmap;
    begin
       Result.Bits (Bitpos) := True;
       return Result;
    end;
 
-   function Negate (Bitmap : Bitmap_T) return Bitmap_T is
-      Result: Bitmap_T; -- { dg-error "Storage_Error" }
+   function -- { dg-error "too large" }
+     Negate (Bitmap : Bitmap_T) return Bitmap_T
+   is
+      Result: Bitmap_T;
    begin
       for E in Bitpos_Range_T loop
         Result.Bits (E) := not Bitmap.Bits (E);
@@ -29,6 +22,4 @@ procedure frame_overflow is
       return Result;
   end;
 
-begin
-   null;
-end;
+end Frame_Overflow;
diff --git a/gcc/testsuite/gnat.dg/frame_overflow.ads b/gcc/testsuite/gnat.dg/frame_overflow.ads
new file mode 100644 (file)
index 0000000..898e37a
--- /dev/null
@@ -0,0 +1,17 @@
+with System;
+
+package Frame_Overflow is
+
+   type Bitpos_Range_T is range 1..2**(System.Word_Size-1)-1;
+   type Bitmap_Array_T is array (Bitpos_Range_T) of Boolean;
+
+   type Bitmap_T is record
+      Bits : Bitmap_Array_T := (others => False);
+   end record;
+
+   function
+     Set_In (Bitmap : Bitmap_T; Bitpos : Bitpos_Range_T)  return Bitmap_T;
+
+   function Negate (Bitmap : Bitmap_T) return Bitmap_T;
+
+end Frame_Overflow;
index 83d432c..ed048f6 100644 (file)
@@ -15,7 +15,7 @@ package Addr1 is
   end record;
   for Rec2'Size use 64;
 
-  A: Arr (1 .. 12);
+  A: Arr (1 .. 4);
 
   Obj1: Rec1;
   for Obj1'Address use A'Address; -- { dg-bogus "alignment" }
index fafe820..c5e990e 100644 (file)
@@ -1020,26 +1020,28 @@ disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
   return false;
 }
 
-/* Return true iff type of EXP is not sufficiently aligned.  */
+/* Return true if EXP is a memory reference less aligned than ALIGN.  This is
+   invoked only on strict-alignment targets.  */
 
 static bool
-tree_non_mode_aligned_mem_p (tree exp)
+tree_non_aligned_mem_p (tree exp, unsigned int align)
 {
-  enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
-  unsigned int align;
+  unsigned int exp_align;
 
   if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
     exp = TREE_OPERAND (exp, 0);
 
-  if (TREE_CODE (exp) == SSA_NAME
-      || TREE_CODE (exp) == MEM_REF
-      || mode == BLKmode
-      || is_gimple_min_invariant (exp)
-      || !STRICT_ALIGNMENT)
+  if (TREE_CODE (exp) == SSA_NAME || is_gimple_min_invariant (exp))
     return false;
 
-  align = get_object_alignment (exp, BIGGEST_ALIGNMENT);
-  if (GET_MODE_ALIGNMENT (mode) > align)
+  /* get_object_alignment will fall back to BITS_PER_UNIT if it cannot
+     compute an explicit alignment.  Pretend that dereferenced pointers
+     are always aligned on strict-alignment targets.  */
+  exp_align = get_object_alignment (exp, BIGGEST_ALIGNMENT);
+  if (TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF)
+    exp_align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), exp_align);
+
+  if (exp_align < align)
     return true;
 
   return false;
@@ -1071,7 +1073,11 @@ build_accesses_from_assign (gimple stmt)
   if (lacc)
     {
       lacc->grp_assignment_write = 1;
-      lacc->grp_unscalarizable_region |= tree_non_mode_aligned_mem_p (rhs);
+      if (STRICT_ALIGNMENT
+         && tree_non_aligned_mem_p (rhs,
+                                    get_object_alignment (lhs,
+                                                          BIGGEST_ALIGNMENT)))
+        lacc->grp_unscalarizable_region = 1;
     }
 
   if (racc)
@@ -1080,7 +1086,11 @@ build_accesses_from_assign (gimple stmt)
       if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
          && !is_gimple_reg_type (racc->type))
        bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
-      racc->grp_unscalarizable_region |= tree_non_mode_aligned_mem_p (lhs);
+      if (STRICT_ALIGNMENT
+         && tree_non_aligned_mem_p (lhs,
+                                    get_object_alignment (rhs,
+                                                          BIGGEST_ALIGNMENT)))
+        racc->grp_unscalarizable_region = 1;
     }
 
   if (lacc && racc
@@ -3608,7 +3618,8 @@ access_precludes_ipa_sra_p (struct access *access)
          || gimple_code (access->stmt) == GIMPLE_ASM))
     return true;
 
-  if (tree_non_mode_aligned_mem_p (access->expr))
+  if (STRICT_ALIGNMENT
+      && tree_non_aligned_mem_p (access->expr, TYPE_ALIGN (access->type)))
     return true;
 
   return false;