From 743a16d57a4f9f65bbc663100d5e16c564f283ec Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 18 Sep 2019 11:37:02 +0000 Subject: [PATCH] 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 gcc/ * varasm.c (assemble_real): Generate canonical const_ints. From-SVN: r275873 --- gcc/ChangeLog | 4 ++++ gcc/varasm.c | 14 ++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1907307c762..a6869cfcbdb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2019-09-18 Richard Sandiford + + * varasm.c (assemble_real): Generate canonical const_ints. + 2019-09-18 Richard Biener PR lto/91763 diff --git a/gcc/varasm.c b/gcc/varasm.c index a7c22523f9f..57365ad2e76 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; } } -- 2.30.2