diff mbox

[fold-const] Fix native_encode_real for HFmode constants

Message ID 57F508EE.6020804@foss.arm.com
State New
Headers show

Commit Message

Kyrill Tkachov Oct. 5, 2016, 2:06 p.m. UTC
Hi all,

I encountered a wrong-code issue with my WIP store merging pass when it was trying to encode HFmode constants.
I am using native_encode_real to write the constants to a byte array and it's breaking on big-endian.
For a 2-byte constant it ended up writing bytes at offsets 3 and 2 rather than 1 and 0.

The fix in this patch makes the logic in native_encode_real match the logic in native_interpret_real,
I just copied the logic across.

I don't have a testcase against clean trunk that demonstrates the issue but with my store merging patch
the testcase gcc.target/aarch64/advsimd-intrinsics/vldX.c starts failing without this patch because
adjacent 16-bit float constants are not being merged correctly.

Bootstrapped and tested on aarch64-none-linux-gnu.
As this patch only affects the big-endian code path I also tested it on aarch64_be-none-elf.

Ok for trunk? Do you think this needs to be backported?

Thanks,
Kyrill

2016-10-05  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     * fold-const.c (native_encode_real): Fix logic for selecting offset
     to write to when BYTES_BIG_ENDIAN.

Comments

Bernd Schmidt Oct. 5, 2016, 2:33 p.m. UTC | #1
On 10/05/2016 04:06 PM, Kyrill Tkachov wrote:
> The fix in this patch makes the logic in native_encode_real match the
> logic in native_interpret_real,
> I just copied the logic across.

Looks reasonable to me. Ok.


Bernd
Richard Biener Oct. 6, 2016, 10:20 a.m. UTC | #2
On Wed, Oct 5, 2016 at 4:06 PM, Kyrill Tkachov
<kyrylo.tkachov@foss.arm.com> wrote:
> Hi all,
>
> I encountered a wrong-code issue with my WIP store merging pass when it was
> trying to encode HFmode constants.
> I am using native_encode_real to write the constants to a byte array and
> it's breaking on big-endian.
> For a 2-byte constant it ended up writing bytes at offsets 3 and 2 rather
> than 1 and 0.
>
> The fix in this patch makes the logic in native_encode_real match the logic
> in native_interpret_real,
> I just copied the logic across.
>
> I don't have a testcase against clean trunk that demonstrates the issue but
> with my store merging patch

Might be sth simple as

unsigned short foo (void)
{
  unsigned short bar;
  typedef HFmode alias_HF __attribute__((may_alias));
  *(ailas_HFmode *)bar = HFmode constant;
  return bar;
}

which should get a bogus integer representation from FRE.

> the testcase gcc.target/aarch64/advsimd-intrinsics/vldX.c starts failing
> without this patch because
> adjacent 16-bit float constants are not being merged correctly.
>
> Bootstrapped and tested on aarch64-none-linux-gnu.
> As this patch only affects the big-endian code path I also tested it on
> aarch64_be-none-elf.
>
> Ok for trunk? Do you think this needs to be backported?
>
> Thanks,
> Kyrill
>
> 2016-10-05  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>
>     * fold-const.c (native_encode_real): Fix logic for selecting offset
>     to write to when BYTES_BIG_ENDIAN.
diff mbox

Patch

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 81671e9fec68a3281b744626db1b94f26d19aabc..564d086e9636743104d629cd6f5620ac2ee6a544 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7142,7 +7142,16 @@  native_encode_real (const_tree expr, unsigned char *ptr, int len, int off)
 	    offset += byte % UNITS_PER_WORD;
 	}
       else
-	offset = BYTES_BIG_ENDIAN ? 3 - byte : byte;
+	{
+	  offset = byte;
+	  if (BYTES_BIG_ENDIAN)
+	    {
+	      /* Reverse bytes within each long, or within the entire float
+		 if it's smaller than a long (for HFmode).  */
+	      offset = MIN (3, total_bytes - 1) - offset;
+	      gcc_assert (offset >= 0);
+	    }
+	}
       offset = offset + ((bitpos / BITS_PER_UNIT) & ~3);
       if (offset >= off
 	  && offset - off < len)