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]

Re: [testcase] 3.{1,1.1,2} ICE on IA-32


On Mon, Jul 29, 2002 at 07:01:52PM +0200, Jakub Jelinek wrote:
> Should the fix be some force_reg like function for loop which would try to
> recog the instruction and if it would not recognize it, would go
> inside PLUS, MULT or ASHIFT, maybe others, and first do force_reg on the
> argument, then on the whole pattern with the arguments replaced by the
> registers (and should it add REG_EQUIV in that case or not)?

Something like that.  Merging the following two changes should do the job.

I've not tested this except on your test case.  Approved for
3.2.1 once the branch is open and this is properly tested.



r~



2002-05-17  Richard Sandiford  <rsandifo@redhat.com>

        * expr.c (force_operand): Fix reversed move.

Sat May  4 13:20:54 CEST 2002  Jan Hubicka  <jh@suse.cz>

        * expr.c (force_operand): Use expand_simple_* to handle more
        cases.


Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.423.2.19
diff -c -p -d -r1.423.2.19 expr.c
*** expr.c	7 May 2002 05:43:11 -0000	1.423.2.19
--- expr.c	1 Aug 2002 22:26:22 -0000
*************** rtx
*** 5434,5449 ****
  force_operand (value, target)
       rtx value, target;
  {
!   optab binoptab = 0;
!   /* Use a temporary to force order of execution of calls to
!      `force_operand'.  */
!   rtx tmp;
!   rtx op2;
    /* Use subtarget as the target for operand 0 of a binary operation.  */
    rtx subtarget = get_subtarget (target);
  
    /* Check for a PIC address load.  */
!   if ((GET_CODE (value) == PLUS || GET_CODE (value) == MINUS)
        && XEXP (value, 0) == pic_offset_table_rtx
        && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
  	  || GET_CODE (XEXP (value, 1)) == LABEL_REF
--- 5434,5446 ----
  force_operand (value, target)
       rtx value, target;
  {
!   rtx op1, op2;
    /* Use subtarget as the target for operand 0 of a binary operation.  */
    rtx subtarget = get_subtarget (target);
+   enum rtx_code code = GET_CODE (value);
  
    /* Check for a PIC address load.  */
!   if ((code == PLUS || code == MINUS)
        && XEXP (value, 0) == pic_offset_table_rtx
        && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
  	  || GET_CODE (XEXP (value, 1)) == LABEL_REF
*************** force_operand (value, target)
*** 5455,5514 ****
        return subtarget;
      }
  
!   if (GET_CODE (value) == PLUS)
!     binoptab = add_optab;
!   else if (GET_CODE (value) == MINUS)
!     binoptab = sub_optab;
!   else if (GET_CODE (value) == MULT)
      {
!       op2 = XEXP (value, 1);
!       if (!CONSTANT_P (op2)
! 	  && !(GET_CODE (op2) == REG && op2 != subtarget))
! 	subtarget = 0;
!       tmp = force_operand (XEXP (value, 0), subtarget);
!       return expand_mult (GET_MODE (value), tmp,
! 			  force_operand (op2, NULL_RTX),
! 			  target, 1);
      }
  
!   if (binoptab)
      {
        op2 = XEXP (value, 1);
!       if (!CONSTANT_P (op2)
! 	  && !(GET_CODE (op2) == REG && op2 != subtarget))
  	subtarget = 0;
!       if (binoptab == sub_optab && GET_CODE (op2) == CONST_INT)
  	{
! 	  binoptab = add_optab;
  	  op2 = negate_rtx (GET_MODE (value), op2);
  	}
  
        /* Check for an addition with OP2 a constant integer and our first
! 	 operand a PLUS of a virtual register and something else.  In that
! 	 case, we want to emit the sum of the virtual register and the
! 	 constant first and then add the other value.  This allows virtual
! 	 register instantiation to simply modify the constant rather than
! 	 creating another one around this addition.  */
!       if (binoptab == add_optab && GET_CODE (op2) == CONST_INT
  	  && GET_CODE (XEXP (value, 0)) == PLUS
  	  && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
  	  && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
  	  && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
  	{
! 	  rtx temp = expand_binop (GET_MODE (value), binoptab,
! 				   XEXP (XEXP (value, 0), 0), op2,
! 				   subtarget, 0, OPTAB_LIB_WIDEN);
! 	  return expand_binop (GET_MODE (value), binoptab, temp,
! 			       force_operand (XEXP (XEXP (value, 0), 1), 0),
! 			       target, 0, OPTAB_LIB_WIDEN);
  	}
  
!       tmp = force_operand (XEXP (value, 0), subtarget);
!       return expand_binop (GET_MODE (value), binoptab, tmp,
! 			   force_operand (op2, NULL_RTX),
! 			   target, 0, OPTAB_LIB_WIDEN);
!       /* We give UNSIGNEDP = 0 to expand_binop
! 	 because the only operations we are expanding here are signed ones.  */
      }
  
  #ifdef INSN_SCHEDULING
--- 5452,5539 ----
        return subtarget;
      }
  
!   if (code == ZERO_EXTEND || code == SIGN_EXTEND)
      {
!       if (!target)
! 	target = gen_reg_rtx (GET_MODE (value));
!       convert_move (target, force_operand (XEXP (value, 0), NULL),
! 		    code == ZERO_EXTEND);
!       return target;
      }
  
!   if (GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c')
      {
        op2 = XEXP (value, 1);
!       if (!CONSTANT_P (op2) && !(GET_CODE (op2) == REG && op2 != subtarget))
  	subtarget = 0;
!       if (code == MINUS && GET_CODE (op2) == CONST_INT)
  	{
! 	  code = PLUS;
  	  op2 = negate_rtx (GET_MODE (value), op2);
  	}
  
        /* Check for an addition with OP2 a constant integer and our first
!          operand a PLUS of a virtual register and something else.  In that
!          case, we want to emit the sum of the virtual register and the
!          constant first and then add the other value.  This allows virtual
!          register instantiation to simply modify the constant rather than
!          creating another one around this addition.  */
!       if (code == PLUS && GET_CODE (op2) == CONST_INT
  	  && GET_CODE (XEXP (value, 0)) == PLUS
  	  && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
  	  && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
  	  && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
  	{
! 	  rtx temp = expand_simple_binop (GET_MODE (value), code,
! 					  XEXP (XEXP (value, 0), 0), op2,
! 					  subtarget, 0, OPTAB_LIB_WIDEN);
! 	  return expand_simple_binop (GET_MODE (value), code, temp,
! 				      force_operand (XEXP (XEXP (value,
! 								 0), 1), 0),
! 				      target, 0, OPTAB_LIB_WIDEN);
  	}
  
!       op1 = force_operand (XEXP (value, 0), subtarget);
!       op2 = force_operand (op2, NULL_RTX);
!       switch (code)
! 	{
! 	case MULT:
! 	  return expand_mult (GET_MODE (value), op1, op2, target, 1);
! 	case DIV:
! 	  if (!INTEGRAL_MODE_P (GET_MODE (value)))
! 	    return expand_simple_binop (GET_MODE (value), code, op1, op2,
! 					target, 1, OPTAB_LIB_WIDEN);
! 	  else
! 	    return expand_divmod (0,
! 				  FLOAT_MODE_P (GET_MODE (value))
! 				  ? RDIV_EXPR : TRUNC_DIV_EXPR,
! 				  GET_MODE (value), op1, op2, target, 0);
! 	  break;
! 	case MOD:
! 	  return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
! 				target, 0);
! 	  break;
! 	case UDIV:
! 	  return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2,
! 				target, 1);
! 	  break;
! 	case UMOD:
! 	  return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
! 				target, 1);
! 	  break;
! 	case ASHIFTRT:
! 	  return expand_simple_binop (GET_MODE (value), code, op1, op2,
! 				      target, 0, OPTAB_LIB_WIDEN);
! 	  break;
! 	default:
! 	  return expand_simple_binop (GET_MODE (value), code, op1, op2,
! 				      target, 1, OPTAB_LIB_WIDEN);
! 	}
!     }
!   if (GET_RTX_CLASS (code) == '1')
!     {
!       op1 = force_operand (XEXP (value, 0), NULL_RTX);
!       return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
      }
  
  #ifdef INSN_SCHEDULING


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