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]

Minor fixes to insv/extv support


When extracting/inserting bitfields via insv/extv patterns; the generic parts of the compiler will use gen_rtx_SUBREG to convert the source (extract) or destination (insert) register if the register's mode does not match the appropriate mode in the md file. From my reading of the code, it appears (and makes logical sense) that we always want the low part of the source register. Unfortunately the code uses gen_rtx_SUBREG rather than gen_lowpart_SUBREG.

For little endian targets, this doesn't cause problems. It also doesn't generally cause problems on big endian targets because those with insv/extv support generally omit the mode on the key registers, or they explicitly use word_mode (and thus conversions are very rarely necessary).

However, the H8 predates the ability to omit modes on the key registers for insv/extv and explicitly uses HImode (which is different than WORD_MODE for the H8/300H, H8/S and H8/SX). Thus it is common to need a conversion from SImode to HImode for extv/insv.

Not surprisingly, this fails miserably and ultimately runs afoul of the final check in validate_subreg causing hundreds of failures in the testsuite for H8 port.

Luckily we can fix this by using gen_lowpart_SUBREG rather than gen_rtx_SUBREG.

Bootstrapped and regression tested on x86_64-pc-linux-gnu. Regression tested for h8300-elf.

OK?

Jeff

ps. Long term the H8 port insv/extv patterns ought to be tweaked to eliminate the explicit HImode requirements. They're no longer needed and removing those restrictions would generate better code for the H8/300H and H8/S.


	* expmed.c (store_bit_field_1): Use gen_lowpart_SUBREG rather
	than gen_rtx_SUBREG.
	(extract_bit_field_1): Likewise.

Index: expmed.c
===================================================================
*** expmed.c	(revision 156938)
--- expmed.c	(working copy)
*************** store_bit_field_1 (rtx str_rtx, unsigned
*** 698,704 ****
  	   and we will need the original value of op0 if insv fails.  */
  	xop0 = gen_rtx_SUBREG (op_mode, SUBREG_REG (xop0), SUBREG_BYTE (xop0));
        if (REG_P (xop0) && GET_MODE (xop0) != op_mode)
! 	xop0 = gen_rtx_SUBREG (op_mode, xop0, 0);
  
        /* If the destination is a paradoxical subreg such that we need a
  	 truncate to the inner mode, perform the insertion on a temporary and
--- 698,704 ----
  	   and we will need the original value of op0 if insv fails.  */
  	xop0 = gen_rtx_SUBREG (op_mode, SUBREG_REG (xop0), SUBREG_BYTE (xop0));
        if (REG_P (xop0) && GET_MODE (xop0) != op_mode)
! 	xop0 = gen_lowpart_SUBREG (op_mode, xop0);
  
        /* If the destination is a paradoxical subreg such that we need a
  	 truncate to the inner mode, perform the insertion on a temporary and
*************** extract_bit_field_1 (rtx str_rtx, unsign
*** 1542,1548 ****
        /* If op0 is a register, we need it in EXT_MODE to make it
  	 acceptable to the format of ext(z)v.  */
        if (REG_P (xop0) && GET_MODE (xop0) != ext_mode)
! 	xop0 = gen_rtx_SUBREG (ext_mode, xop0, 0);
        if (MEM_P (xop0))
  	/* Get ref to first byte containing part of the field.  */
  	xop0 = adjust_address (xop0, byte_mode, xoffset);
--- 1542,1548 ----
        /* If op0 is a register, we need it in EXT_MODE to make it
  	 acceptable to the format of ext(z)v.  */
        if (REG_P (xop0) && GET_MODE (xop0) != ext_mode)
! 	xop0 = gen_lowpart_SUBREG (ext_mode, xop0);
        if (MEM_P (xop0))
  	/* Get ref to first byte containing part of the field.  */
  	xop0 = adjust_address (xop0, byte_mode, xoffset);

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