Richard Sandiford rsandifo@nildram.co.uk
Mon Sep 17 22:26:00 GMT 2007

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?


	* 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
-	      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.  */
+		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);

More information about the Gcc-patches mailing list