diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2019-09-18 11:37:02 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2019-09-18 11:37:02 +0000 |
commit | 743a16d57a4f9f65bbc663100d5e16c564f283ec (patch) | |
tree | c8f6533dc06f9ec92b25c46db395fd42100eaf58 /gcc | |
parent | a3d09469041ab66ee1e12c2f3e4de33c4bf96732 (diff) | |
download | gcc-743a16d57a4f9f65bbc663100d5e16c564f283ec.zip gcc-743a16d57a4f9f65bbc663100d5e16c564f283ec.tar.gz gcc-743a16d57a4f9f65bbc663100d5e16c564f283ec.tar.bz2 |
Make assemble_real generate canonical CONST_INTs
assemble_real used GEN_INT to create integers directly from the
longs returned by real_to_target. assemble_integer then went on
to interpret the const_ints as though they had the mode corresponding
to the accompanying size parameter:
imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0).require ();
for (i = 0; i < size; i += subsize)
{
rtx partial = simplify_subreg (omode, x, imode, i);
But in the assemble_real case, X might not be canonical for IMODE.
If the interface to assemble_integer is supposed to allow outputting
(say) the low 4 bytes of a DImode integer, then the simplify_subreg
above is wrong. But if the number of bytes passed to assemble_integer
is supposed to be the number of bytes that the integer actually contains,
assemble_real is wrong.
This patch takes the latter interpretation and makes assemble_real
generate const_ints that are canonical for the number of bytes passed.
The flip_storage_order handling assumes that each long is a full
SImode, which e.g. excludes BITS_PER_UNIT != 8 and float formats
whose memory size is not a multiple of 32 bits (which includes
HFmode at least). The patch therefore leaves that code alone.
If interpreting each integer as SImode is correct, the const_ints
that it generates are also correct.
2019-09-18 Richard Sandiford <richard.sandiford@arm.com>
gcc/
* varasm.c (assemble_real): Generate canonical const_ints.
From-SVN: r275873
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/varasm.c | 14 |
2 files changed, 12 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1907307..a6869cf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2019-09-18 Richard Sandiford <richard.sandiford@arm.com> + + * varasm.c (assemble_real): Generate canonical const_ints. + 2019-09-18 Richard Biener <rguenther@suse.de> PR lto/91763 diff --git a/gcc/varasm.c b/gcc/varasm.c index a7c2252..57365ad 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2873,25 +2873,27 @@ assemble_real (REAL_VALUE_TYPE d, scalar_float_mode mode, unsigned int align, real_to_target (data, &d, mode); /* Put out the first word with the specified alignment. */ + unsigned int chunk_nunits = MIN (nunits, units_per); if (reverse) elt = flip_storage_order (SImode, gen_int_mode (data[nelts - 1], SImode)); else - elt = GEN_INT (data[0]); - assemble_integer (elt, MIN (nunits, units_per), align, 1); - nunits -= units_per; + elt = GEN_INT (sext_hwi (data[0], chunk_nunits * BITS_PER_UNIT)); + assemble_integer (elt, chunk_nunits, align, 1); + nunits -= chunk_nunits; /* Subsequent words need only 32-bit alignment. */ align = min_align (align, 32); for (int i = 1; i < nelts; i++) { + chunk_nunits = MIN (nunits, units_per); if (reverse) elt = flip_storage_order (SImode, gen_int_mode (data[nelts - 1 - i], SImode)); else - elt = GEN_INT (data[i]); - assemble_integer (elt, MIN (nunits, units_per), align, 1); - nunits -= units_per; + elt = GEN_INT (sext_hwi (data[i], chunk_nunits * BITS_PER_UNIT)); + assemble_integer (elt, chunk_nunits, align, 1); + nunits -= chunk_nunits; } } |