[Bug middle-end/24950] ICE in operand_subword_force

Alan Modra amodra@bigpond.net.au
Mon Nov 21 23:29:00 GMT 2005


On Mon, Nov 21, 2005 at 01:15:57PM -0800, Ian Lance Taylor wrote:
> Would it work to call get_best_mode if GET_MODE_SIZE (GET_MODE (op0))
> < GET_MODE_SIZE (fieldmode)?  That is, add that test to the
> conditional a couple of lines up?

Yes, because get_best_mode would return VOIDmode due to finding that op0
wasn't sufficiently aligned.  Actually, I think it would be safer to
always test GET_MODE_SIZE (bestmode) < GET_MODE_SIZE (fieldmode) even
when we use get_best_mode.  That way we protect against some future
change in get_best_mode from causing the nonsense attempt to store a
field in a reg smaller than the field.

> This kind of code appears several times in expmed.c, so I feel like
> there is something odd going on.  Doesn't this have to be fixed in a
> number of different places?

Hmm, yes.  The extzv and extv parts of extract_bit_field have a similar
problem, if  extract_bit_field ever gets passed a mem:SI struct with a
DImode field.

As I stated in my previous message, the difference between gcc-3.3 and
later is that gcc-3.3 passes a mem:BLK while later gcc seems to use a
mem:SI.  I think the mem:SI is entirely reasonable for the struct given
its alignment, but that's about all I know on this issue.  I suppose
another way of fixing this problem would be to generate emit_move_insn
instead of calling store_bit_field for a misaligned DImode, but that
strikes me as more of an optimisation than anything else, and possibly
wrong on STRICT_ALIGNMENT targets.

:ADDPATCH middle-end:

	PR middle-end/24950
	* expmed.c (store_bit_field): Don't attempt to insv a field
	larger than the reg.
	(extract_bit_field): Likewise for extzv and extv.

Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	(revision 107329)
+++ gcc/expmed.c	(working copy)
@@ -643,6 +643,7 @@ store_bit_field (rtx str_rtx, unsigned H
 	    bestmode = GET_MODE (op0);
 
 	  if (bestmode == VOIDmode
+	      || GET_MODE_SIZE (bestmode) < GET_MODE_SIZE (fieldmode)
 	      || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (op0))
 		  && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (op0)))
 	    goto insv_loses;
@@ -1396,6 +1397,7 @@ extract_bit_field (rtx str_rtx, unsigned
 		    bestmode = GET_MODE (xop0);
 
 		  if (bestmode == VOIDmode
+		      || GET_MODE_SIZE (bestmode) < GET_MODE_SIZE (fieldmode)
 		      || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (xop0))
 			  && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (xop0)))
 		    goto extzv_loses;
@@ -1530,6 +1532,7 @@ extract_bit_field (rtx str_rtx, unsigned
 		    bestmode = GET_MODE (xop0);
 
 		  if (bestmode == VOIDmode
+		      || GET_MODE_SIZE (bestmode) < GET_MODE_SIZE (fieldmode)
 		      || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (xop0))
 			  && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (xop0)))
 		    goto extv_loses;

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Gcc-patches mailing list