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] Fix unaligned load on the IA-64


Hi,

for the testcase:

? type R1 is record
? ? A1, A2, A3 : System.Address;
? end record;

? type R2 is record
? ? C : Character;
? ? R : R1;
? end record;
? pragma Pack (R2);

? procedure Dummy (R : R1) is begin null; end;

? procedure Init (X : R2) is
? begin
? ? Dummy (X.R);
? end;

R1 is passed in registers on the IA-64 and for Dummy (X.R) the compiler 
(move_block_to_reg) generates an unaligned word move:

(insn 9 8 10 3 q.adb:22 (set (reg:DI 120 out0)
        (mem/s/j:DI (reg/f:DI 341) [0 S8 A8])) -1 (nil))

(gdb) frame 1
#1  0x00000000007baa32 in load_register_parameters (args=0x7fffffff9c30,
    num_actuals=1, call_fusage=0x7fffffff9db8, flags=0, is_sibcall=0,
    sibcall_failure=0x7fffffff9d8c) at /home/eric/svn/gcc/gcc/calls.c:1697
1697                    move_block_to_reg (REGNO (reg), mem, nregs, 
args[i].mode);
(gdb) p debug_rtx(reg)
(reg:BLK 120 out0)
$1 = void
(gdb) p debug_rtx(mem)
(mem/s/j:BLK (reg/f:DI 341) [0 S24 A8])


The calls.c code contains a machinery that could prevent that from happening:

/* If any elements in ARGS refer to parameters that are to be passed in
? ?registers, but not in memory, and whose alignment does not permit a
? ?direct copy into registers. ?Copy the values into a group of pseudos
? ?which we will later copy into the appropriate hard registers.

? ?Pseudos for each unaligned argument will be stored into the array
? ?args[argnum].aligned_regs. ?The caller is responsible for deallocating
? ?the aligned_regs array if it is nonzero. ?*/

static void
store_unaligned_arguments_into_pseudos (struct arg_data *args, int 
num_actuals)
{
? int i, j;

? for (i = 0; i < num_actuals; i++)
? ? if (args[i].reg != 0 && ! args[i].pass_on_stack
????????&& args[i].mode == BLKmode
????????&& (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
???????? ? ?< (unsigned int) MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))

but it doesn't kick in since the type is sufficiently aligned:

(gdb) p debug_tree(args[i]->tree_value)
    type <record_type 0x2aaaab226a80 q__r1 sizes-gimplified BLK
        size <integer_cst 0x2aaaab180b40 constant 192>
        unit size <integer_cst 0x2aaaab2399f0 constant 24>
        align 64 symtab 0 alias set -1 canonical type 0x2aaaab226a80

although the actual argument isn't:

(gdb) p debug_rtx(args[i]->value)
(mem/s/j:BLK (reg/f:DI 341) [0 S24 A8])

because of the packedness.


Fixed by adding a check on the alignment of the actual argument, tested on 
IA-64/Linux and SPARC/Solaris, OK for mainline?


2008-10-31  Eric Botcazou  <ebotcazou@adacore.com>

        * calls.c (store_unaligned_arguments_into_pseudos): Also look into the
        actual alignment of the argument if it lives in memory.


2008-10-31  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/pack11.adb: New test.


-- 
Eric Botcazou
-- { dg-do run }
-- { dg-options "-gnatws" }

with System;

procedure Q is

  type R1 is record
    A1, A2, A3 : System.Address;
  end record;

  type R2 is record
    C : Character;
    R : R1;
  end record;
  pragma Pack (R2);

  procedure Dummy (R : R1) is begin null; end;

  procedure Init (X : R2) is
  begin
    Dummy (X.R);
  end;

  My_R2 : R2;

begin
  Init (My_R2);
end;
Index: calls.c
===================================================================
--- calls.c	(revision 141459)
+++ calls.c	(working copy)
@@ -832,13 +832,14 @@ restore_fixed_argument_area (rtx save_ar
 static void
 store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals)
 {
+  const unsigned int ralign = MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD);
   int i, j;
 
   for (i = 0; i < num_actuals; i++)
     if (args[i].reg != 0 && ! args[i].pass_on_stack
 	&& args[i].mode == BLKmode
-	&& (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
-	    < (unsigned int) MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
+	&& (TYPE_ALIGN (TREE_TYPE (args[i].tree_value)) < ralign
+	    || (MEM_P (args[i].value) && MEM_ALIGN (args[i].value) < ralign)))
       {
 	int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
 	int endian_correction = 0;

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