diff mbox

[Ada] Do not overly promote alignment of local variable

Message ID 201109251747.12580.ebotcazou@adacore.com
State New
Headers show

Commit Message

Eric Botcazou Sept. 25, 2011, 3:47 p.m. UTC
This limits the alignment promotion we do for local aggregate variables in Ada, 
which doesn't play nice with the NRV optimization.

Tested on i586-suse-linux, applied on the 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-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.
diff mbox

Patch

Index: ada/gcc-interface/decl.c
===================================================================
--- ada/gcc-interface/decl.c	(revision 179163)
+++ ada/gcc-interface/decl.c	(working copy)
@@ -817,16 +817,30 @@  gnat_to_gnu_entity (Entity_Id gnat_entit
 		    && 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: testsuite/gnat.dg/frame_overflow.adb
===================================================================
--- testsuite/gnat.dg/frame_overflow.adb	(revision 179017)
+++ testsuite/gnat.dg/frame_overflow.adb	(working copy)
@@ -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;
Index: testsuite/gnat.dg/frame_overflow.ads
===================================================================
--- testsuite/gnat.dg/frame_overflow.ads	(revision 0)
+++ testsuite/gnat.dg/frame_overflow.ads	(revision 0)
@@ -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: testsuite/gnat.dg/specs/addr1.ads
===================================================================
--- testsuite/gnat.dg/specs/addr1.ads	(revision 179017)
+++ testsuite/gnat.dg/specs/addr1.ads	(working copy)
@@ -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" }