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]

force_operand tweek



Hi,
this patch modifies force_operand so it can grok basically any integral
expression.  It is based on my midlevel lowering pass, so it should be
stable and we do use it now for loop unrolling, where we use simplify_rtx
to prove constantness of the number of itrations and if that fails we simply
evaulate it into register using force_operand.

Previously we failed to grok NOTs, NEGs and friends that may happen during
simplifying of PLUS/MINUS expressions.

Regtested/bootstrapped cfg branch, mainline in progress.
OK for mainline?

Honza

Fri May  3 13:08:05 CEST 2002  Jan Hubicka  <jh@suse.cz>
	* expr.c (force_operand):  Revamp to be more generic.

Index: expr.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expr.c,v
retrieving revision 1.374.2.16
diff -c -3 -p -r1.374.2.16 expr.c
*** expr.c	24 Apr 2002 15:42:36 -0000	1.374.2.16
--- expr.c	3 May 2002 11:07:57 -0000
*************** rtx
*** 5432,5447 ****
  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
--- 5432,5444 ----
  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)
*** 5453,5512 ****
        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
--- 5450,5541 ----
        return subtarget;
      }
  
!   if (code == ZERO_EXTEND)
      {
!       convert_move (force_operand (XEXP (value, 0), NULL), subtarget, 1);
!       return subtarget;
!     }
!   else if (code == SIGN_EXTEND)
!     {
!       convert_move (force_operand (XEXP (value, 0), NULL), subtarget, 0);
!       return subtarget;
      }
  
!   if (GET_RTX_CLASS (GET_CODE (value)) == '2'
!       || GET_RTX_CLASS (GET_CODE (value)) == '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,
! 				      force_operand (op2, NULL_RTX),
! 				      target, 1, OPTAB_LIB_WIDEN);
! 	}
!     }
!   if (GET_RTX_CLASS (GET_CODE (value)) == '1')
!     {
!       op1 = force_operand (XEXP (value, 0), NULL_RTX);
!       return expand_simple_unop (code, 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]