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]

Bug 14927: latent IA-64 movxf bug


This fixes a bug in the movxf pattern that has been there since it was
added about 4 years ago.  The code doesn't handle SUBREG correctly in two
places.  It doesn't handle a SUBREG in operand[0].  This results in the
abort for the testcase in the bug report.  Also, I noticed that the code
applies SUBREG_REG to a GR reg in one place.  I don't have a testcase for
that, but added a sensible fix for it.

This was tested with a full ia64-linux bootstrap and make check.

2004-04-26  James E Wilson  <wilson@specifixinc.com>

	Bug 14927
	* config/ia64/ia64.md (movxf): New local op0.  Handle case where
	operands[0] is a SUBREG.  Handle case where operands[1] is a GR reg.

Index: ia64.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.md,v
retrieving revision 1.128
diff -p -r1.128 ia64.md
*** ia64.md	21 Apr 2004 01:39:17 -0000	1.128
--- ia64.md	23 Apr 2004 06:12:47 -0000
***************
*** 677,688 ****
  	(match_operand:XF 1 "general_operand" ""))]
    ""
  {
    /* We must support XFmode loads into general registers for stdarg/vararg
       and unprototyped calls.  We split them into DImode loads for convenience.
       We don't need XFmode stores from general regs, because a stdarg/vararg
       routine does a block store to memory of unnamed arguments.  */
!   if (GET_CODE (operands[0]) == REG
!       && GR_REGNO_P (REGNO (operands[0])))
      {
        /* We're hoping to transform everything that deals with XFmode
  	 quantities and GR registers early in the compiler.  */
--- 677,693 ----
  	(match_operand:XF 1 "general_operand" ""))]
    ""
  {
+   rtx op0 = operands[0];
+ 
+   if (GET_CODE (op0) == SUBREG)
+     op0 = SUBREG_REG (op0);
+ 
    /* We must support XFmode loads into general registers for stdarg/vararg
       and unprototyped calls.  We split them into DImode loads for convenience.
       We don't need XFmode stores from general regs, because a stdarg/vararg
       routine does a block store to memory of unnamed arguments.  */
! 
!   if (GET_CODE (op0) == REG && GR_REGNO_P (REGNO (op0)))
      {
        /* We're hoping to transform everything that deals with XFmode
  	 quantities and GR registers early in the compiler.  */
***************
*** 695,710 ****
  	  || (GET_CODE (operands[1]) == REG
  	      && GR_REGNO_P (REGNO (operands[1]))))
  	{
! 	  emit_move_insn (gen_rtx_REG (TImode, REGNO (operands[0])),
! 			  SUBREG_REG (operands[1]));
  	  DONE;
  	}
  
        if (GET_CODE (operands[1]) == CONST_DOUBLE)
  	{
! 	  emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0])),
  			  operand_subword (operands[1], 0, 0, XFmode));
! 	  emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0]) + 1),
  			  operand_subword (operands[1], 1, 0, XFmode));
  	  DONE;
  	}
--- 700,722 ----
  	  || (GET_CODE (operands[1]) == REG
  	      && GR_REGNO_P (REGNO (operands[1]))))
  	{
! 	  rtx op1 = operands[1];
! 
! 	  if (GET_CODE (op1) == SUBREG)
! 	    op1 = SUBREG_REG (op1);
! 	  else
! 	    /* ??? Maybe we should make a SUBREG here?  */
! 	    op1 = gen_rtx_REG (TImode, REGNO (op1));
! 
! 	  emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1);
  	  DONE;
  	}
  
        if (GET_CODE (operands[1]) == CONST_DOUBLE)
  	{
! 	  emit_move_insn (gen_rtx_REG (DImode, REGNO (op0)),
  			  operand_subword (operands[1], 0, 0, XFmode));
! 	  emit_move_insn (gen_rtx_REG (DImode, REGNO (op0) + 1),
  			  operand_subword (operands[1], 1, 0, XFmode));
  	  DONE;
  	}
***************
*** 717,724 ****
  	{
  	  rtx out[2];
  
! 	  out[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[0]));
! 	  out[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[0])+1);
  
  	  emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
  	  emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
--- 729,736 ----
  	{
  	  rtx out[2];
  
! 	  out[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (op0));
! 	  out[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (op0) + 1);
  
  	  emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
  	  emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com


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