public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] Fix wrong code for return of small aggregates on big-endian
@ 2017-01-09 10:46 Eric Botcazou
  2017-01-09 11:14 ` Richard Biener
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Botcazou @ 2017-01-09 10:46 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1893 bytes --]

Hi,

this is a regression present on all active branches for big-endian targets 
returning small aggregate types in registers under certain circumstances and 
when optimization is enabled: when the bitfield path of store_field is taken, 
the function ends up calling store_bit_field to store the value.  Now the 
behavior of store_bit_field is awkward when the mode is BLKmode: it always 
takes its value from the lsb up to the word size but expects it left justified 
beyond it (see expmed.c:890 and below) and I missed that when I got rid of the 
stack temporaries that were originally generated in that case.

Of course that's OK for little-endian targets but not for big-endian targets, 
and I have a couple of C++ testcases exposing the issue on SPARC 64-bit and a 
couple of Ada testcases exposing the issue on PowerPC with the SVR4 ABI (the 
Linux ABI is immune since it always returns on the stack); I think they cover 
all the cases in the problematic code.

The attached fix was tested on a bunch of platforms: x86/Linux, x86-64/Linux, 
PowerPC/Linux, PowerPC64/Linux, PowerPC/VxWorks, Aarch64/Linux, SPARC/Solaris 
and SPARC64/Solaris with no regressions.  OK for the mainline? other branches?


2017-01-09  Eric Botcazou  <ebotcazou@adacore.com>

	* expr.c (store_field): In the bitfield case, if the value comes from
	a function call and is of an aggregate type returned in registers, do
	not modify the field mode; extract the value in all cases if the mode
	is BLKmode and the size is not larger than a word.


2017-01-09  Eric Botcazou  <ebotcazou@adacore.com>

	* g++.dg/opt/call2.C: New test.
	* g++.dg/opt/call3.C: Likewise.
	* gnat.dg/array26.adb: New test.
	* gnat.dg/array26_pkg.ad[sb]: New helper.
	* gnat.dg/array27.adb: New test.
	* gnat.dg/array27_pkg.ad[sb]: New helper.
	* gnat.dg/array28.adb: New test.
	* gnat.dg/array28_pkg.ad[sb]: New helper.

-- 
Eric Botcazou

[-- Attachment #2: p.diff --]
[-- Type: text/x-patch, Size: 2276 bytes --]

Index: expr.c
===================================================================
--- expr.c	(revision 244194)
+++ expr.c	(working copy)
@@ -6888,33 +6888,30 @@ store_field (rtx target, HOST_WIDE_INT b
       if (GET_CODE (temp) == PARALLEL)
 	{
 	  HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
-	  rtx temp_target;
-	  if (mode == BLKmode || mode == VOIDmode)
-	    mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
-	  temp_target = gen_reg_rtx (mode);
+	  machine_mode temp_mode
+	    = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
+	  rtx temp_target = gen_reg_rtx (temp_mode);
 	  emit_group_store (temp_target, temp, TREE_TYPE (exp), size);
 	  temp = temp_target;
 	}
-      else if (mode == BLKmode)
+
+      /* Handle calls that return BLKmode values in registers.  */
+      else if (mode == BLKmode && REG_P (temp) && TREE_CODE (exp) == CALL_EXPR)
+	{
+	  rtx temp_target = gen_reg_rtx (GET_MODE (temp));
+	  copy_blkmode_from_reg (temp_target, temp, TREE_TYPE (exp));
+	  temp = temp_target;
+	}
+
+      /* The behavior of store_bit_field is awkward when mode is BLKmode:
+	 it always takes its value from the lsb up to the word size but
+	 expects it left justified beyond it.  At this point TEMP is left
+	 justified so extract the value in the former case.  */
+      if (mode == BLKmode && bitsize <= BITS_PER_WORD)
 	{
-	  /* Handle calls that return BLKmode values in registers.  */
-	  if (REG_P (temp) && TREE_CODE (exp) == CALL_EXPR)
-	    {
-	      rtx temp_target = gen_reg_rtx (GET_MODE (temp));
-	      copy_blkmode_from_reg (temp_target, temp, TREE_TYPE (exp));
-	      temp = temp_target;
-	    }
-	  else
-	    {
-	      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
-	      rtx temp_target;
-	      mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
-	      temp_target = gen_reg_rtx (mode);
-	      temp_target
-	        = extract_bit_field (temp, size * BITS_PER_UNIT, 0, 1,
-				     temp_target, mode, mode, false);
-	      temp = temp_target;
-	    }
+	  machine_mode temp_mode = smallest_mode_for_size (bitsize, MODE_INT);
+	  temp = extract_bit_field (temp, bitsize, 0, 1, NULL_RTX, temp_mode,
+				    temp_mode, false);
 	}
 
       /* Store the value in the bitfield.  */

[-- Attachment #3: call2.C --]
[-- Type: text/x-c++src, Size: 403 bytes --]

// { dg-do run }
// { dg-options "-O" }

struct Foo
{
  Foo() : a(1), b(1), c('a') {}
  int a;
  int b;
  char c;
};

static Foo copy_foo(Foo) __attribute__((noinline, noclone));

static Foo copy_foo(Foo A)
{
  return A;
}

struct Bar : Foo
{
  Bar(Foo t) : Foo(copy_foo(t)) {}
};

Foo F;

int main (void)
{
  Bar B (F);

  if (B.a != 1 || B.b != 1 || B.c != 'a')
    __builtin_abort ();

  return 0;
}

[-- Attachment #4: call3.C --]
[-- Type: text/x-c++src, Size: 382 bytes --]

// { dg-do run }
// { dg-options "-O" }

struct Foo
{
  Foo() : a(1), c('a') {}
  short int a;
  char c;
};

static Foo copy_foo(Foo) __attribute__((noinline, noclone));

static Foo copy_foo(Foo A)
{
  return A;
}

struct Bar : Foo
{
  Bar(Foo t) : Foo(copy_foo(t)) {}
};

Foo F;

int main (void)
{
  Bar B (F);

  if (B.a != 1 || B.c != 'a')
    __builtin_abort ();

  return 0;
}

[-- Attachment #5: array26.adb --]
[-- Type: text/x-adasrc, Size: 357 bytes --]

-- { dg-do run }
-- { dg-options "-O" }

with Array26_Pkg; use Array26_Pkg;

procedure Array26 is

  function Get return Outer_type is
    Ret : Outer_Type;
  begin
    Ret (Inner_Type'Range) := F;
    return Ret;
  end;

  A : Outer_Type := Get;
  B : Inner_Type := A (Inner_Type'Range);

begin
  if B /= "123" then
    raise Program_Error;
  end if;
end;

[-- Attachment #6: array26_pkg.adb --]
[-- Type: text/x-adasrc, Size: 114 bytes --]

package body Array26_Pkg is

  function F return Inner_Type is
  begin
    return "123";
  end;

end Array26_Pkg;

[-- Attachment #7: array27_pkg.ads --]
[-- Type: text/x-adasrc, Size: 157 bytes --]

package Array27_Pkg is

  subtype Outer_Type is String (1 .. 8);
  subtype Inner_Type is String (1 .. 3);

  function F return Inner_Type;

end Array27_Pkg;

[-- Attachment #8: array26_pkg.ads --]
[-- Type: text/x-adasrc, Size: 157 bytes --]

package Array26_Pkg is

  subtype Outer_Type is String (1 .. 4);
  subtype Inner_Type is String (1 .. 3);

  function F return Inner_Type;

end Array26_Pkg;

[-- Attachment #9: array28.adb --]
[-- Type: text/x-adasrc, Size: 359 bytes --]

-- { dg-do run }
-- { dg-options "-O" }

with Array28_Pkg; use Array28_Pkg;

procedure Array28 is

  function Get return Outer_type is
    Ret : Outer_Type;
  begin
    Ret (Inner_Type'Range) := F;
    return Ret;
  end;

  A : Outer_Type := Get;
  B : Inner_Type := A (Inner_Type'Range);

begin
  if B /= "12345" then
    raise Program_Error;
  end if;
end;

[-- Attachment #10: array27.adb --]
[-- Type: text/x-adasrc, Size: 359 bytes --]

-- { dg-do run }
-- { dg-options "-O" }

with Array27_Pkg; use Array27_Pkg;

procedure Array27 is

  function Get return Outer_type is
    Ret : Outer_Type;
  begin
    Ret (Inner_Type'Range) := F;
    return Ret;
  end;

  A : Outer_Type := Get;
  B : Inner_Type := A (Inner_Type'Range);

begin
    if B /= "123" then
    raise Program_Error;
  end if;
end;

[-- Attachment #11: array27_pkg.adb --]
[-- Type: text/x-adasrc, Size: 114 bytes --]

package body Array27_Pkg is

  function F return Inner_Type is
  begin
    return "123";
  end;

end Array27_Pkg;

[-- Attachment #12: array28_pkg.adb --]
[-- Type: text/x-adasrc, Size: 116 bytes --]

package body Array28_Pkg is

  function F return Inner_Type is
  begin
    return "12345";
  end;

end Array28_Pkg;

[-- Attachment #13: array28_pkg.ads --]
[-- Type: text/x-adasrc, Size: 157 bytes --]

package Array28_Pkg is

  subtype Outer_Type is String (1 .. 8);
  subtype Inner_Type is String (1 .. 5);

  function F return Inner_Type;

end Array28_Pkg;

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] Fix wrong code for return of small aggregates on big-endian
  2017-01-09 10:46 [patch] Fix wrong code for return of small aggregates on big-endian Eric Botcazou
@ 2017-01-09 11:14 ` Richard Biener
  2017-01-10  8:01   ` Christophe Lyon
  0 siblings, 1 reply; 9+ messages in thread
From: Richard Biener @ 2017-01-09 11:14 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: GCC Patches

On Mon, Jan 9, 2017 at 11:43 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> Hi,
>
> this is a regression present on all active branches for big-endian targets
> returning small aggregate types in registers under certain circumstances and
> when optimization is enabled: when the bitfield path of store_field is taken,
> the function ends up calling store_bit_field to store the value.  Now the
> behavior of store_bit_field is awkward when the mode is BLKmode: it always
> takes its value from the lsb up to the word size but expects it left justified
> beyond it (see expmed.c:890 and below) and I missed that when I got rid of the
> stack temporaries that were originally generated in that case.
>
> Of course that's OK for little-endian targets but not for big-endian targets,
> and I have a couple of C++ testcases exposing the issue on SPARC 64-bit and a
> couple of Ada testcases exposing the issue on PowerPC with the SVR4 ABI (the
> Linux ABI is immune since it always returns on the stack); I think they cover
> all the cases in the problematic code.
>
> The attached fix was tested on a bunch of platforms: x86/Linux, x86-64/Linux,
> PowerPC/Linux, PowerPC64/Linux, PowerPC/VxWorks, Aarch64/Linux, SPARC/Solaris
> and SPARC64/Solaris with no regressions.  OK for the mainline? other branches?

Ok for trunk and branches after a short burn-in.

Thanks,
Richard.

>
> 2017-01-09  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * expr.c (store_field): In the bitfield case, if the value comes from
>         a function call and is of an aggregate type returned in registers, do
>         not modify the field mode; extract the value in all cases if the mode
>         is BLKmode and the size is not larger than a word.
>
>
> 2017-01-09  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * g++.dg/opt/call2.C: New test.
>         * g++.dg/opt/call3.C: Likewise.
>         * gnat.dg/array26.adb: New test.
>         * gnat.dg/array26_pkg.ad[sb]: New helper.
>         * gnat.dg/array27.adb: New test.
>         * gnat.dg/array27_pkg.ad[sb]: New helper.
>         * gnat.dg/array28.adb: New test.
>         * gnat.dg/array28_pkg.ad[sb]: New helper.
>
> --
> Eric Botcazou

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] Fix wrong code for return of small aggregates on big-endian
  2017-01-09 11:14 ` Richard Biener
@ 2017-01-10  8:01   ` Christophe Lyon
  2017-01-10  8:58     ` Eric Botcazou
  2017-01-10 23:06     ` Eric Botcazou
  0 siblings, 2 replies; 9+ messages in thread
From: Christophe Lyon @ 2017-01-10  8:01 UTC (permalink / raw)
  To: Richard Biener; +Cc: Eric Botcazou, GCC Patches

On 9 January 2017 at 12:14, Richard Biener <richard.guenther@gmail.com> wrote:
> On Mon, Jan 9, 2017 at 11:43 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> Hi,
>>
>> this is a regression present on all active branches for big-endian targets
>> returning small aggregate types in registers under certain circumstances and
>> when optimization is enabled: when the bitfield path of store_field is taken,
>> the function ends up calling store_bit_field to store the value.  Now the
>> behavior of store_bit_field is awkward when the mode is BLKmode: it always
>> takes its value from the lsb up to the word size but expects it left justified
>> beyond it (see expmed.c:890 and below) and I missed that when I got rid of the
>> stack temporaries that were originally generated in that case.
>>
>> Of course that's OK for little-endian targets but not for big-endian targets,
>> and I have a couple of C++ testcases exposing the issue on SPARC 64-bit and a
>> couple of Ada testcases exposing the issue on PowerPC with the SVR4 ABI (the
>> Linux ABI is immune since it always returns on the stack); I think they cover
>> all the cases in the problematic code.
>>
>> The attached fix was tested on a bunch of platforms: x86/Linux, x86-64/Linux,
>> PowerPC/Linux, PowerPC64/Linux, PowerPC/VxWorks, Aarch64/Linux, SPARC/Solaris
>> and SPARC64/Solaris with no regressions.  OK for the mainline? other branches?
>
> Ok for trunk and branches after a short burn-in.
>

Hi Eric,

I have noticed new failures after this commit (r244249).
g++.dg/opt/call3.C fails at execution on armeb targets
g++.dg/opt/call2.C fails at execution on aarch64_be

Christophe




> Thanks,
> Richard.
>
>>
>> 2017-01-09  Eric Botcazou  <ebotcazou@adacore.com>
>>
>>         * expr.c (store_field): In the bitfield case, if the value comes from
>>         a function call and is of an aggregate type returned in registers, do
>>         not modify the field mode; extract the value in all cases if the mode
>>         is BLKmode and the size is not larger than a word.
>>
>>
>> 2017-01-09  Eric Botcazou  <ebotcazou@adacore.com>
>>
>>         * g++.dg/opt/call2.C: New test.
>>         * g++.dg/opt/call3.C: Likewise.
>>         * gnat.dg/array26.adb: New test.
>>         * gnat.dg/array26_pkg.ad[sb]: New helper.
>>         * gnat.dg/array27.adb: New test.
>>         * gnat.dg/array27_pkg.ad[sb]: New helper.
>>         * gnat.dg/array28.adb: New test.
>>         * gnat.dg/array28_pkg.ad[sb]: New helper.
>>
>> --
>> Eric Botcazou

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] Fix wrong code for return of small aggregates on big-endian
  2017-01-10  8:01   ` Christophe Lyon
@ 2017-01-10  8:58     ` Eric Botcazou
  2017-01-10 10:20       ` Christophe Lyon
  2017-01-10 23:06     ` Eric Botcazou
  1 sibling, 1 reply; 9+ messages in thread
From: Eric Botcazou @ 2017-01-10  8:58 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: gcc-patches, Richard Biener

> I have noticed new failures after this commit (r244249).
> g++.dg/opt/call3.C fails at execution on armeb targets
> g++.dg/opt/call2.C fails at execution on aarch64_be

They are new testcases: can you find out whether they pass before the patch?

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] Fix wrong code for return of small aggregates on big-endian
  2017-01-10  8:58     ` Eric Botcazou
@ 2017-01-10 10:20       ` Christophe Lyon
  2017-01-10 10:27         ` Eric Botcazou
  2017-01-10 12:14         ` Eric Botcazou
  0 siblings, 2 replies; 9+ messages in thread
From: Christophe Lyon @ 2017-01-10 10:20 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Richard Biener

On 10 January 2017 at 09:58, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> I have noticed new failures after this commit (r244249).
>> g++.dg/opt/call3.C fails at execution on armeb targets
>> g++.dg/opt/call2.C fails at execution on aarch64_be
>
> They are new testcases: can you find out whether they pass before the patch?
>
They pass before the patch (I only checked armeb).

> --
> Eric Botcazou

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] Fix wrong code for return of small aggregates on big-endian
  2017-01-10 10:20       ` Christophe Lyon
@ 2017-01-10 10:27         ` Eric Botcazou
  2017-01-10 11:09           ` Christophe Lyon
  2017-01-10 12:14         ` Eric Botcazou
  1 sibling, 1 reply; 9+ messages in thread
From: Eric Botcazou @ 2017-01-10 10:27 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: gcc-patches, Richard Biener

> They pass before the patch (I only checked armeb).

Thanks, I see what's going on, but can you post the configure line of armeb?

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] Fix wrong code for return of small aggregates on big-endian
  2017-01-10 10:27         ` Eric Botcazou
@ 2017-01-10 11:09           ` Christophe Lyon
  0 siblings, 0 replies; 9+ messages in thread
From: Christophe Lyon @ 2017-01-10 11:09 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Richard Biener

On 10 January 2017 at 11:26, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> They pass before the patch (I only checked armeb).
>
> Thanks, I see what's going on, but can you post the configure line of armeb?
>
Sure, it is:
--target=armeb-none-linux-gnueabihf  --with-float=hard --with-mode=arm
--with-cpu=cortex-a9 --with-fpu=neon


> --
> Eric Botcazou

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] Fix wrong code for return of small aggregates on big-endian
  2017-01-10 10:20       ` Christophe Lyon
  2017-01-10 10:27         ` Eric Botcazou
@ 2017-01-10 12:14         ` Eric Botcazou
  1 sibling, 0 replies; 9+ messages in thread
From: Eric Botcazou @ 2017-01-10 12:14 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: gcc-patches, Richard Biener

> They pass before the patch (I only checked armeb).

I think that's not true for aarch64_be though, since the patch doesn't change 
code generation for this target.  But I'll fix that too.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] Fix wrong code for return of small aggregates on big-endian
  2017-01-10  8:01   ` Christophe Lyon
  2017-01-10  8:58     ` Eric Botcazou
@ 2017-01-10 23:06     ` Eric Botcazou
  1 sibling, 0 replies; 9+ messages in thread
From: Eric Botcazou @ 2017-01-10 23:06 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: gcc-patches, Richard Biener

[-- Attachment #1: Type: text/plain, Size: 1990 bytes --]

> I have noticed new failures after this commit (r244249).
> g++.dg/opt/call3.C fails at execution on armeb targets
> g++.dg/opt/call2.C fails at execution on aarch64_be

It turns out that there is already a big-endian adjustment a few lines above:

      /* If the value has a record type and an integral mode then, if BITSIZE
	 is narrower than this mode and this is for big-endian data, we must
        first put the value into the low-order bits.  Moreover, the field may
	 be not aligned on a byte boundary; in this case, if it has reverse
	storage order, it needs to be accessed as a scalar field with reverse
	 storage order and we must first put the value into target order.  */
      if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
	  && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT)
	{
	  HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (temp));

	  reverse = TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (exp));

	  if (reverse)
	    temp = flip_storage_order (GET_MODE (temp), temp);

	  if (bitsize < size
	      && reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
	    temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
				 size - bitsize, NULL_RTX, 1);
	}

and adding the extraction leads to a double adjustment on armeb, whereas no 
adjustment is still applied to aarch64_be...

That's why the attached patch merges the second adjustment in the first one by 
moving up the code fetching the return value from the registers; this ensures 
that only one adjustment is ever applied and that it is applied only on left- 
justified values.  But a final extraction (without big-endian adjustment) is 
still needed for small BLKmode values, otherwise store_bit_field aborts...

Tested on the same platforms as the original patch, applied as obvious.


        * expr.c (store_field): In the bitfield case, fetch the return value
	from the registers before applying a single big-endian adjustment.
	Always do a final load for a BLKmode value not larger than a word.

-- 
Eric Botcazou

[-- Attachment #2: p.diff --]
[-- Type: text/x-patch, Size: 5104 bytes --]

Index: expr.c
===================================================================
--- expr.c	(revision 244258)
+++ expr.c	(working copy)
@@ -6832,13 +6832,36 @@ store_field (rtx target, HOST_WIDE_INT b
 
       temp = expand_normal (exp);
 
-      /* If the value has a record type and an integral mode then, if BITSIZE
-	 is narrower than this mode and this is for big-endian data, we must
-	 first put the value into the low-order bits.  Moreover, the field may
-	 be not aligned on a byte boundary; in this case, if it has reverse
-	 storage order, it needs to be accessed as a scalar field with reverse
-	 storage order and we must first put the value into target order.  */
-      if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
+      /* Handle calls that return values in multiple non-contiguous locations.
+	 The Irix 6 ABI has examples of this.  */
+      if (GET_CODE (temp) == PARALLEL)
+	{
+	  HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
+	  machine_mode temp_mode
+	    = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
+	  rtx temp_target = gen_reg_rtx (temp_mode);
+	  emit_group_store (temp_target, temp, TREE_TYPE (exp), size);
+	  temp = temp_target;
+	}
+
+      /* Handle calls that return BLKmode values in registers.  */
+      else if (mode == BLKmode && REG_P (temp) && TREE_CODE (exp) == CALL_EXPR)
+	{
+	  rtx temp_target = gen_reg_rtx (GET_MODE (temp));
+	  copy_blkmode_from_reg (temp_target, temp, TREE_TYPE (exp));
+	  temp = temp_target;
+	}
+
+      /* If the value has aggregate type and an integral mode then, if BITSIZE
+	 is narrower than this mode and this is for big-endian data, we first
+	 need to put the value into the low-order bits for store_bit_field,
+	 except when MODE is BLKmode and BITSIZE larger than the word size
+	 (see the handling of fields larger than a word in store_bit_field).
+	 Moreover, the field may be not aligned on a byte boundary; in this
+	 case, if it has reverse storage order, it needs to be accessed as a
+	 scalar field with reverse storage order and we must first put the
+	 value into target order.  */
+      if (AGGREGATE_TYPE_P (TREE_TYPE (exp))
 	  && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT)
 	{
 	  HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (temp));
@@ -6849,7 +6872,8 @@ store_field (rtx target, HOST_WIDE_INT b
 	    temp = flip_storage_order (GET_MODE (temp), temp);
 
 	  if (bitsize < size
-	      && reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
+	      && reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN
+	      && !(mode == BLKmode && bitsize > BITS_PER_WORD))
 	    temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
 				 size - bitsize, NULL_RTX, 1);
 	}
@@ -6859,12 +6883,10 @@ store_field (rtx target, HOST_WIDE_INT b
 	  && mode != TYPE_MODE (TREE_TYPE (exp)))
 	temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1);
 
-      /* If TEMP is not a PARALLEL (see below) and its mode and that of TARGET
-	 are both BLKmode, both must be in memory and BITPOS must be aligned
-	 on a byte boundary.  If so, we simply do a block copy.  Likewise for
-	 a BLKmode-like TARGET.  */
-      if (GET_CODE (temp) != PARALLEL
-	  && GET_MODE (temp) == BLKmode
+      /* If the mode of TEMP and TARGET is BLKmode, both must be in memory
+	 and BITPOS must be aligned on a byte boundary.  If so, we simply do
+	 a block copy.  Likewise for a BLKmode-like TARGET.  */
+      if (GET_MODE (temp) == BLKmode
 	  && (GET_MODE (target) == BLKmode
 	      || (MEM_P (target)
 		  && GET_MODE_CLASS (GET_MODE (target)) == MODE_INT
@@ -6883,31 +6905,9 @@ store_field (rtx target, HOST_WIDE_INT b
 	  return const0_rtx;
 	}
 
-      /* Handle calls that return values in multiple non-contiguous locations.
-	 The Irix 6 ABI has examples of this.  */
-      if (GET_CODE (temp) == PARALLEL)
-	{
-	  HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
-	  machine_mode temp_mode
-	    = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
-	  rtx temp_target = gen_reg_rtx (temp_mode);
-	  emit_group_store (temp_target, temp, TREE_TYPE (exp), size);
-	  temp = temp_target;
-	}
-
-      /* Handle calls that return BLKmode values in registers.  */
-      else if (mode == BLKmode && REG_P (temp) && TREE_CODE (exp) == CALL_EXPR)
-	{
-	  rtx temp_target = gen_reg_rtx (GET_MODE (temp));
-	  copy_blkmode_from_reg (temp_target, temp, TREE_TYPE (exp));
-	  temp = temp_target;
-	}
-
-      /* The behavior of store_bit_field is awkward when mode is BLKmode:
-	 it always takes its value from the lsb up to the word size but
-	 expects it left justified beyond it.  At this point TEMP is left
-	 justified so extract the value in the former case.  */
-      if (mode == BLKmode && bitsize <= BITS_PER_WORD)
+      /* If the mode of TEMP is still BLKmode and BITSIZE not larger than the
+	 word size, we need to load the value (see again store_bit_field).  */
+      if (GET_MODE (temp) == BLKmode && bitsize <= BITS_PER_WORD)
 	{
 	  machine_mode temp_mode = smallest_mode_for_size (bitsize, MODE_INT);
 	  temp = extract_bit_field (temp, bitsize, 0, 1, NULL_RTX, temp_mode,

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-01-10 23:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-09 10:46 [patch] Fix wrong code for return of small aggregates on big-endian Eric Botcazou
2017-01-09 11:14 ` Richard Biener
2017-01-10  8:01   ` Christophe Lyon
2017-01-10  8:58     ` Eric Botcazou
2017-01-10 10:20       ` Christophe Lyon
2017-01-10 10:27         ` Eric Botcazou
2017-01-10 11:09           ` Christophe Lyon
2017-01-10 12:14         ` Eric Botcazou
2017-01-10 23:06     ` Eric Botcazou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).