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]

RFA: Another TRULY_NOOP_TRUNCATION problem


The recent dse.c patch showed up a latent bug.  If we have a register
parameter that is (a) BLKmode, (b) a power of 2 in size and (c) smaller
than a word, the caller passes the parameter as word_mode, but the
callee generates a store in the integer mode corresponding to the size
of the type.  The callee is effectively introducing an implicit
truncation on !TRULY_NOOP_TRUNCATION targets.

This has (apparently) worked until now because the store itself doesn't
need the value to be correctly truncated, and because the optimisers
haven't tried to reuse the stored register.  DSE now does that.

The patch below introduces an explicit conversion if the callee's
truncation is not a no-op.  If a target defines TRULY_NOOP_TRUNCATION,
its truncate pattern should generally allow a memory destination,
so combine can still reconstitute the original store if the truncation
is not used again.  This does indeed happen on MIPS.

The patch below fixes gcc.c-torture/execute/20040709-[12].c at -O
for little-endian MIPS o64 targets.  Regression-tested on mipsisa64-elfoabi.
Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?

Richard


gcc/
	* function.c (assign_parm_setup_block): Explicitly convert BLKmode
	parameters from word_mode to the subword type if such a truncation
	is not a no-op.

Index: gcc/function.c
===================================================================
--- gcc/function.c	2007-09-17 23:00:33.000000000 +0100
+++ gcc/function.c	2007-09-17 23:02:08.000000000 +0100
@@ -2591,7 +2591,21 @@ assign_parm_setup_block (struct assign_p
 #endif
 	      )
 	    {
-	      rtx reg = gen_rtx_REG (mode, REGNO (entry_parm));
+	      rtx reg;
+
+	      /* We are really truncating a word_mode value containing
+		 SIZE bytes into a value of mode MODE.  If such an
+		 operation requires no actual instructions, we can refer
+		 to the value directly in mode MODE, otherwise we must
+		 start with the register in word_mode and explicitly
+		 convert it.  */
+	      if (TRULY_NOOP_TRUNCATION (size * BITS_PER_UNIT, BITS_PER_WORD))
+		reg = gen_rtx_REG (mode, REGNO (entry_parm));
+	      else
+		{
+		  reg = gen_rtx_REG (word_mode, REGNO (entry_parm));
+		  reg = convert_to_mode (mode, copy_to_reg (reg), 1);
+		}
 	      emit_move_insn (change_address (mem, mode, 0), reg);
 	    }
 


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