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]

VOIDmode comparisons, take 2



Hi
Here is my patch for VOIDmode and conditions updated to current CVS.  Basically
the problem is that by folding constants into conditionals we may lose
information about mode of the comparison and get into trouble, since values
will not be properly truncated/promoted etc.

Originally the simplify_relational_operation accepted VOIDmode and used "infinite"
precision for the comparison.  This may result in the missoptimizations.

The patch changes simplify_relational_operation to require the non-VOIDmode
information and changes rest of the world to preserve it at any cost.  Most
tricky part was the compare expression, when combine (for instance) hits the
combine and produces (compare (const_int) (const_int)) it lost the mode
information.  If it was encosed in the relational comparison (le (compare
(const_int) (const_int)) (const_int 0)), we would get into trouble.  Way I am
handling it is converting compare into (compare (const:mode (const_int))
(const_int)) temporarily to not lose the information.  Also I am using this
representation for REG_EQUAL notes that gets from the gcse.

I got no new regressions and the patch solves latent problem in the spec2000
twolf test.

Thu Aug  3 20:18:53 MET DST 2000  Jan Hubicka  <jh@suse.cz>
	* combine.c (gen_binary): Refuse relational operations.
	(gen_relational): New
	(combine_splify_rtx): Keep track of mode of the comparsion,
	avoid creating VOIDmode comparisons.
	(simplify_if_then_else): Use gen_relational at the place
	we create relational operations.
	(simplify_set): Avoid creating of VOIDmode compares.
	(if_then_else_cond): Keep track of the comparison mode.
	(simplify_comparison): New parameter pmode, update it when
	mode has changed.
	* recog.c (validate_replace_rtx_1): Simplify relational
	operations, avoid VOIDmode compares.
	* simplify-rtx.c (simplify_relational_operation): Require
	mode to be valid;  get valid mode from the COMPARE
	expression; strip down the CONST.
Index: egcs/gcc/combine.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/combine.c,v
retrieving revision 1.140
diff -c -3 -p -r1.140 combine.c
*** combine.c	2000/08/01 03:11:55	1.140
--- combine.c	2000/08/03 17:51:12
*************** static rtx gen_rtx_combine PARAMS ((enum
*** 413,421 ****
  				    ...));
  static rtx gen_binary		PARAMS ((enum rtx_code, enum machine_mode,
  					 rtx, rtx));
  static rtx gen_unary		PARAMS ((enum rtx_code, enum machine_mode,
  					 enum machine_mode, rtx));
! static enum rtx_code simplify_comparison  PARAMS ((enum rtx_code, rtx *, rtx *));
  static int reversible_comparison_p  PARAMS ((rtx));
  static void update_table_tick	PARAMS ((rtx));
  static void record_value_for_reg  PARAMS ((rtx, rtx, rtx));
--- 413,426 ----
  				    ...));
  static rtx gen_binary		PARAMS ((enum rtx_code, enum machine_mode,
  					 rtx, rtx));
+ static rtx gen_relational	PARAMS ((enum rtx_code, enum machine_mode,
+ 					 enum machine_mode,
+ 					 rtx, rtx));
  static rtx gen_unary		PARAMS ((enum rtx_code, enum machine_mode,
  					 enum machine_mode, rtx));
! static enum rtx_code simplify_comparison  PARAMS ((enum rtx_code,
! 						   enum machine_mode *,
! 						   rtx *, rtx *));
  static int reversible_comparison_p  PARAMS ((rtx));
  static void update_table_tick	PARAMS ((rtx));
  static void record_value_for_reg  PARAMS ((rtx, rtx, rtx));
*************** combine_simplify_rtx (x, op0_mode, last,
*** 3579,3586 ****
  		    || GET_RTX_CLASS (GET_CODE (false)) == '<')))
  	{
  	  rtx cop1 = const0_rtx;
! 	  enum rtx_code cond_code = simplify_comparison (NE, &cond, &cop1);
  
  	  if (cond_code == NE && GET_RTX_CLASS (GET_CODE (cond)) == '<')
  	    return x;
  
--- 3579,3589 ----
  		    || GET_RTX_CLASS (GET_CODE (false)) == '<')))
  	{
  	  rtx cop1 = const0_rtx;
! 	  enum machine_mode cond_mode = GET_MODE (cond);
! 	  enum rtx_code cond_code;
  
+ 	  cond_code = simplify_comparison (NE, &cond_mode, &cond, &cop1);
+ 
  	  if (cond_code == NE && GET_RTX_CLASS (GET_CODE (cond)) == '<')
  	    return x;
  
*************** combine_simplify_rtx (x, op0_mode, last,
*** 3600,3609 ****
  	      /* If the result values are STORE_FLAG_VALUE and zero, we can
  		 just make the comparison operation.  */
  	      if (true == const_true_rtx && false == const0_rtx)
! 		x = gen_binary (cond_code, mode, cond, cop1);
  	      else if (true == const0_rtx && false == const_true_rtx)
! 		x = gen_binary (reverse_condition (cond_code),
! 				mode, cond, cop1);
  
  	      /* Likewise, we can make the negate of a comparison operation
  		 if the result values are - STORE_FLAG_VALUE and zero.  */
--- 3603,3612 ----
  	      /* If the result values are STORE_FLAG_VALUE and zero, we can
  		 just make the comparison operation.  */
  	      if (true == const_true_rtx && false == const0_rtx)
! 		x = gen_relational (cond_code, mode, cond_mode, cond, cop1);
  	      else if (true == const0_rtx && false == const_true_rtx)
! 		x = gen_relational (reverse_condition (cond_code),
! 				    mode, cond_mode, cond, cop1);
  
  	      /* Likewise, we can make the negate of a comparison operation
  		 if the result values are - STORE_FLAG_VALUE and zero.  */
*************** combine_simplify_rtx (x, op0_mode, last,
*** 3611,3627 ****
  		       && INTVAL (true) == - STORE_FLAG_VALUE
  		       && false == const0_rtx)
  		x = gen_unary (NEG, mode, mode,
! 			       gen_binary (cond_code, mode, cond, cop1));
  	      else if (GET_CODE (false) == CONST_INT
  		       && INTVAL (false) == - STORE_FLAG_VALUE
  		       && true == const0_rtx)
  		x = gen_unary (NEG, mode, mode,
! 			       gen_binary (reverse_condition (cond_code),
! 					   mode, cond, cop1));
  	      else
  		return gen_rtx_IF_THEN_ELSE (mode,
! 					     gen_binary (cond_code, VOIDmode,
! 							 cond, cop1),
  					     true, false);
  
  	      code = GET_CODE (x);
--- 3614,3631 ----
  		       && INTVAL (true) == - STORE_FLAG_VALUE
  		       && false == const0_rtx)
  		x = gen_unary (NEG, mode, mode,
! 			       gen_relational (cond_code, mode, cond_mode,
! 					       cond, cop1));
  	      else if (GET_CODE (false) == CONST_INT
  		       && INTVAL (false) == - STORE_FLAG_VALUE
  		       && true == const0_rtx)
  		x = gen_unary (NEG, mode, mode,
! 			       gen_relational (reverse_condition (cond_code), 
! 					       mode, cond_mode, cond, cop1));
  	      else
  		return gen_rtx_IF_THEN_ELSE (mode,
! 					     gen_relational (cond_code, VOIDmode, cond_mode,
! 							     cond, cop1),
  					     true, false);
  
  	      code = GET_CODE (x);
*************** combine_simplify_rtx (x, op0_mode, last,
*** 3643,3648 ****
--- 3647,3654 ----
  	enum machine_mode cmp_mode = GET_MODE (XEXP (x, 0));
  	if (cmp_mode == VOIDmode)
  	  cmp_mode = GET_MODE (XEXP (x, 1));
+ 	if (cmp_mode == VOIDmode)
+ 	  cmp_mode = op0_mode;
  	temp = simplify_relational_operation (code, cmp_mode,
  					      XEXP (x, 0), XEXP (x, 1));
        }
*************** combine_simplify_rtx (x, op0_mode, last,
*** 4129,4136 ****
  	return SUBREG_REG (XEXP (x, 0));
        break;
  
- #ifdef HAVE_cc0
      case COMPARE:
        /* Convert (compare FOO (const_int 0)) to FOO unless we aren't
  	 using cc0, in which case we want to leave it as a COMPARE
  	 so we can distinguish it from a register-register-copy.  */
--- 4135,4142 ----
  	return SUBREG_REG (XEXP (x, 0));
        break;
  
      case COMPARE:
+ #ifdef HAVE_cc0
        /* Convert (compare FOO (const_int 0)) to FOO unless we aren't
  	 using cc0, in which case we want to leave it as a COMPARE
  	 so we can distinguish it from a register-register-copy.  */
*************** combine_simplify_rtx (x, op0_mode, last,
*** 4143,4151 ****
  	   || flag_fast_math)
  	  && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
  	return XEXP (x, 0);
-       break;
  #endif
  
      case CONST:
        /* (const (const X)) can become (const X).  Do it this way rather than
  	 returning the inner CONST since CONST can be shared with a
--- 4149,4171 ----
  	   || flag_fast_math)
  	  && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
  	return XEXP (x, 0);
  #endif
+       /* Comparisons in VOIDmode are not allowed and we will get into
+ 	 deep problem in the next iteration if COMPARE was nested inside
+ 	 comparison operator.  We avoid this by placing extra CONST with
+ 	 proper mode and taking care in simplify_condition to eliminate it
+ 	 when it is not necesary - ugly but workable.  */
+       if (GET_MODE (XEXP (x, 0)) == VOIDmode
+ 	  && GET_MODE (XEXP (x, 1)) == VOIDmode)
+ 	{
+ 	  if (op0_mode == VOIDmode)
+ 	    abort();
+ 	  SUBST (XEXP (x, 0), gen_rtx_CONST (op0_mode, XEXP (x, 0)));
+ 	  return x;
+ 	}
+       break;
  
+ 
      case CONST:
        /* (const (const X)) can become (const X).  Do it this way rather than
  	 returning the inner CONST since CONST can be shared with a
*************** combine_simplify_rtx (x, op0_mode, last,
*** 4213,4221 ****
  	      || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx)))
  	return
  	  gen_unary (NEG, mode, mode,
! 		     gen_binary (reverse_condition (GET_CODE (XEXP (x, 0))),
! 				 mode, XEXP (XEXP (x, 0), 0),
! 				 XEXP (XEXP (x, 0), 1)));
  
        /* If only the low-order bit of X is possibly nonzero, (plus x -1)
  	 can become (ashiftrt (ashift (xor x 1) C) C) where C is
--- 4233,4241 ----
  	      || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx)))
  	return
  	  gen_unary (NEG, mode, mode,
! 		     gen_relational (reverse_condition (GET_CODE (XEXP (x, 0))),
! 				     mode, VOIDmode, XEXP (XEXP (x, 0), 0),
! 				     XEXP (XEXP (x, 0), 1)));
  
        /* If only the low-order bit of X is possibly nonzero, (plus x -1)
  	 can become (ashiftrt (ashift (xor x 1) C) C) where C is
*************** combine_simplify_rtx (x, op0_mode, last,
*** 4261,4269 ****
  	  && XEXP (x, 0) == const1_rtx
  	  && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<'
  	  && reversible_comparison_p (XEXP (x, 1)))
! 	return gen_binary (reverse_condition (GET_CODE (XEXP (x, 1))), mode,
! 			   XEXP (XEXP (x, 1), 0),
! 			   XEXP (XEXP (x, 1), 1));
  
        /* (minus <foo> (and <foo> (const_int -pow2))) becomes
  	 (and <foo> (const_int pow2-1))  */
--- 4281,4289 ----
  	  && XEXP (x, 0) == const1_rtx
  	  && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<'
  	  && reversible_comparison_p (XEXP (x, 1)))
! 	return gen_relational (reverse_condition (GET_CODE (XEXP (x, 1))),
! 			       mode, VOIDmode, XEXP (XEXP (x, 1), 0),
! 			       XEXP (XEXP (x, 1), 1));
  
        /* (minus <foo> (and <foo> (const_int -pow2))) becomes
  	 (and <foo> (const_int pow2-1))  */
*************** combine_simplify_rtx (x, op0_mode, last,
*** 4334,4342 ****
  
  	  if (GET_CODE (op0) == COMPARE)
  	    op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
  
  	  /* Simplify our comparison, if possible.  */
! 	  new_code = simplify_comparison (code, &op0, &op1);
  
  	  /* If STORE_FLAG_VALUE is 1, we can convert (ne x 0) to simply X
  	     if only the low-order bit is possibly nonzero in X (such as when
--- 4354,4363 ----
  
  	  if (GET_CODE (op0) == COMPARE)
  	    op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
+ 	  op0_mode = GET_MODE (GET_MODE (op0) != VOIDmode ? op0 : op1);
  
  	  /* Simplify our comparison, if possible.  */
! 	  new_code = simplify_comparison (code, &op0_mode, &op0, &op1);
  
  	  /* If STORE_FLAG_VALUE is 1, we can convert (ne x 0) to simply X
  	     if only the low-order bit is possibly nonzero in X (such as when
*************** combine_simplify_rtx (x, op0_mode, last,
*** 4453,4462 ****
  
  	  /* If the code changed, return a whole new comparison.  */
  	  if (new_code != code)
! 	    return gen_rtx_combine (new_code, mode, op0, op1);
  
  	  /* Otherwise, keep this operation, but maybe change its operands.
  	     This also converts (ne (compare FOO BAR) 0) to (ne FOO BAR).  */
  	  SUBST (XEXP (x, 0), op0);
  	  SUBST (XEXP (x, 1), op1);
  	}
--- 4474,4490 ----
  
  	  /* If the code changed, return a whole new comparison.  */
  	  if (new_code != code)
! 	    return gen_relational (new_code, mode, op0_mode, op0, op1);
! 
! 	  /* Make sure that we won't create comparison of two
! 	     VOIDmodes.  */
! 	  temp = simplify_relational_operation (code, op0_mode, op0, op1);
! 	  if (temp)
! 	    return temp;
  
  	  /* Otherwise, keep this operation, but maybe change its operands.
  	     This also converts (ne (compare FOO BAR) 0) to (ne FOO BAR).  */
+ 	  
  	  SUBST (XEXP (x, 0), op0);
  	  SUBST (XEXP (x, 1), op1);
  	}
*************** simplify_if_then_else (x)
*** 4568,4580 ****
  
    /* Simplify storing of the truth value.  */
    if (comparison_p && true == const_true_rtx && false == const0_rtx)
!     return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1));
  
    /* Also when the truth value has to be reversed.  */
    if (comparison_p && reversible_comparison_p (cond)
        && true == const0_rtx && false == const_true_rtx)
!     return gen_binary (reverse_condition (true_code),
! 		       mode, XEXP (cond, 0), XEXP (cond, 1));
  
    /* Sometimes we can simplify the arm of an IF_THEN_ELSE if a register used
       in it is being compared against certain values.  Get the true and false
--- 4596,4609 ----
  
    /* Simplify storing of the truth value.  */
    if (comparison_p && true == const_true_rtx && false == const0_rtx)
!     return gen_relational (true_code, mode, VOIDmode,
! 			   XEXP (cond, 0), XEXP (cond, 1));
  
    /* Also when the truth value has to be reversed.  */
    if (comparison_p && reversible_comparison_p (cond)
        && true == const0_rtx && false == const_true_rtx)
!     return gen_relational (reverse_condition (true_code),
! 			   mode, VOIDmode, XEXP (cond, 0), XEXP (cond, 1));
  
    /* Sometimes we can simplify the arm of an IF_THEN_ELSE if a register used
       in it is being compared against certain values.  Get the true and false
*************** simplify_if_then_else (x)
*** 4649,4656 ****
      {
        true_code = reverse_condition (true_code);
        SUBST (XEXP (x, 0),
! 	     gen_binary (true_code, GET_MODE (cond), XEXP (cond, 0),
! 			 XEXP (cond, 1)));
  
        SUBST (XEXP (x, 1), false);
        SUBST (XEXP (x, 2), true);
--- 4678,4685 ----
      {
        true_code = reverse_condition (true_code);
        SUBST (XEXP (x, 0),
! 	     gen_relational (true_code, GET_MODE (cond), VOIDmode,
! 			     XEXP (cond, 0), XEXP (cond, 1)));
  
        SUBST (XEXP (x, 1), false);
        SUBST (XEXP (x, 2), true);
*************** simplify_if_then_else (x)
*** 4826,4832 ****
  
        if (z)
  	{
! 	  temp = subst (gen_binary (true_code, m, cond_op0, cond_op1),
  			pc_rtx, pc_rtx, 0, 0);
  	  temp = gen_binary (MULT, m, temp,
  			     gen_binary (MULT, m, c1, const_true_rtx));
--- 4855,4861 ----
  
        if (z)
  	{
! 	  temp = subst (gen_relational (true_code, m, VOIDmode, cond_op0, cond_op1),
  			pc_rtx, pc_rtx, 0, 0);
  	  temp = gen_binary (MULT, m, temp,
  			     gen_binary (MULT, m, c1, const_true_rtx));
*************** simplify_set (x)
*** 4901,4917 ****
      {
        enum rtx_code old_code = GET_CODE (*cc_use);
        enum rtx_code new_code;
        rtx op0, op1;
        int other_changed = 0;
        enum machine_mode compare_mode = GET_MODE (dest);
  
        if (GET_CODE (src) == COMPARE)
! 	op0 = XEXP (src, 0), op1 = XEXP (src, 1);
        else
! 	op0 = src, op1 = const0_rtx;
  
!       /* Simplify our comparison, if possible.  */
!       new_code = simplify_comparison (old_code, &op0, &op1);
  
  #ifdef EXTRA_CC_MODES
        /* If this machine has CC modes other than CCmode, check to see if we
--- 4930,4956 ----
      {
        enum rtx_code old_code = GET_CODE (*cc_use);
        enum rtx_code new_code;
+       enum machine_mode mode;
        rtx op0, op1;
        int other_changed = 0;
        enum machine_mode compare_mode = GET_MODE (dest);
  
        if (GET_CODE (src) == COMPARE)
! 	{
! 	  op0 = XEXP (src, 0), op1 = XEXP (src, 1);
!           mode = GET_MODE (op0);
! 	  if (mode == VOIDmode)
! 	    mode = GET_MODE (op1);
! 	}
        else
! 	{
! 	  op0 = src, op1 = const0_rtx;
! 	  mode = GET_MODE (dest);
! 	}
!       if (mode == VOIDmode)
! 	abort();
  
!       new_code = simplify_comparison (old_code, &mode, &op0, &op1);
  
  #ifdef EXTRA_CC_MODES
        /* If this machine has CC modes other than CCmode, check to see if we
*************** simplify_set (x)
*** 4995,5013 ****
        else
  #endif
  
!       /* Otherwise, if we didn't previously have a COMPARE in the
! 	 correct mode, we need one.  */
!       if (GET_CODE (src) != COMPARE || GET_MODE (src) != compare_mode)
! 	{
! 	  SUBST (SET_SRC (x),
! 		 gen_rtx_combine (COMPARE, compare_mode, op0, op1));
! 	  src = SET_SRC (x);
! 	}
!       else
! 	{
! 	  /* Otherwise, update the COMPARE if needed.  */
! 	  SUBST (XEXP (src, 0), op0);
! 	  SUBST (XEXP (src, 1), op1);
  	}
      }
    else
--- 5034,5060 ----
        else
  #endif
  
!       /* Otherwise, update the COMPARE if needed
! 	 unless both operands are VOIDmode constants.  IN case
! 	 they are, resulting RTL is incorect and the insn won't match
! 	 anyway.  In the next iteration combine will probably remove
! 	 the test entirely.  */
!       if (GET_MODE (op0) != VOIDmode
! 	  || GET_MODE (op1) != VOIDmode)
! 	{
! 	  /* If we didn't previously have a COMPARE in the correct mode,
! 	     we need one.  */
! 	  if (GET_CODE (src) != COMPARE || GET_MODE (src) != compare_mode)
! 	    {
! 	      SUBST (SET_SRC (x),
! 		     gen_rtx_combine (COMPARE, compare_mode, op0, op1));
! 	      src = SET_SRC (x);
! 	    }
! 	  else
! 	    {
! 	      SUBST (XEXP (src, 0), op0);
! 	      SUBST (XEXP (src, 1), op1);
! 	    }
  	}
      }
    else
*************** if_then_else_cond (x, ptrue, pfalse)
*** 7247,7252 ****
--- 7294,7302 ----
        if ((cond0 != 0 || cond1 != 0)
  	  && ! (cond0 != 0 && cond1 != 0 && ! rtx_equal_p (cond0, cond1)))
  	{
+ 	  enum machine_mode cmp_mode
+ 	     = GET_MODE (GET_MODE (XEXP (x, 0)) != VOIDmode
+ 			 ? XEXP (x, 0) : XEXP (x, 1));
  	  /* If if_then_else_cond returned zero, then true/false are the
  	     same rtl.  We must copy one of them to prevent invalid rtl
  	     sharing.  */
*************** if_then_else_cond (x, ptrue, pfalse)
*** 7255,7262 ****
  	  else if (cond1 == 0)
  	    true1 = copy_rtx (true1);
  
! 	  *ptrue = gen_binary (code, mode, true0, true1);
! 	  *pfalse = gen_binary (code, mode, false0, false1);
  	  return cond0 ? cond0 : cond1;
  	}
  
--- 7305,7320 ----
  	  else if (cond1 == 0)
  	    true1 = copy_rtx (true1);
  
! 	  if (GET_RTX_CLASS (code) == '<')
! 	    {
! 	      *ptrue = gen_relational (code, mode, cmp_mode, true0, true1);
! 	      *pfalse = gen_relational (code, mode, cmp_mode, false0, false1);
! 	    }
! 	  else
! 	    {
! 	      *ptrue = gen_binary (code, mode, true0, true1);
! 	      *pfalse = gen_binary (code, mode, false0, false1);
! 	    }
  	  return cond0 ? cond0 : cond1;
  	}
  
*************** gen_binary (code, mode, op0, op1)
*** 9841,9883 ****
    rtx tem;
  
    if (GET_RTX_CLASS (code) == 'c'
!       && (GET_CODE (op0) == CONST_INT
! 	  || (CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)))
      tem = op0, op0 = op1, op1 = tem;
  
    if (GET_RTX_CLASS (code) == '<')
!     {
!       enum machine_mode op_mode = GET_MODE (op0);
! 
!       /* Strip the COMPARE from (REL_OP (compare X Y) 0) to get
! 	 just (REL_OP X Y).  */
!       if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
! 	{
! 	  op1 = XEXP (op0, 1);
! 	  op0 = XEXP (op0, 0);
! 	  op_mode = GET_MODE (op0);
! 	}
! 
!       if (op_mode == VOIDmode)
! 	op_mode = GET_MODE (op1);
!       result = simplify_relational_operation (code, op_mode, op0, op1);
!     }
!   else
!     result = simplify_binary_operation (code, mode, op0, op1);
  
    if (result)
      return result;
  
-   /* Put complex operands first and constants second.  */
-   if (GET_RTX_CLASS (code) == 'c'
-       && ((CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
- 	  || (GET_RTX_CLASS (GET_CODE (op0)) == 'o'
- 	      && GET_RTX_CLASS (GET_CODE (op1)) != 'o')
- 	  || (GET_CODE (op0) == SUBREG
- 	      && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op0))) == 'o'
- 	      && GET_RTX_CLASS (GET_CODE (op1)) != 'o')))
-     return gen_rtx_combine (code, mode, op1, op0);
- 
    /* If we are turning off bits already known off in OP0, we need not do
       an AND.  */
    else if (code == AND && GET_CODE (op1) == CONST_INT
--- 9899,9914 ----
    rtx tem;
  
    if (GET_RTX_CLASS (code) == 'c'
!       && swap_commutative_operands_p (op0, op1))
      tem = op0, op0 = op1, op1 = tem;
  
    if (GET_RTX_CLASS (code) == '<')
!     abort ();
!   result = simplify_binary_operation (code, mode, op0, op1);
  
    if (result)
      return result;
  
    /* If we are turning off bits already known off in OP0, we need not do
       an AND.  */
    else if (code == AND && GET_CODE (op1) == CONST_INT
*************** gen_binary (code, mode, op0, op1)
*** 9888,9893 ****
--- 9919,9966 ----
    return gen_rtx_combine (code, mode, op0, op1);
  }
  
+ /* Like gen_binary, but for relational operations.  The op_mode is mode
+    of the operands.  It may be VOIDmode in case we are certain, that one
+    of operands is non-VOIDmode.  This holds for existing patterns since
+    relationals with two VOIDmode operands are improper.  */
+ static rtx
+ gen_relational (code, mode, op_mode, op0, op1)
+      enum rtx_code code;
+      enum machine_mode mode, op_mode;
+      rtx op0, op1;
+ {
+   rtx result;
+ 
+   if (GET_RTX_CLASS (code) != '<') 
+     abort();
+ 
+   /* Strip the COMPARE from (REL_OP (compare X Y) 0) to get 
+      just (REL_OP X Y).  */
+   if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
+     {
+       op1 = XEXP (op0, 1);
+       op0 = XEXP (op0, 0);
+       /* Previous pass of combine_simplify_rtx may have but
+ 	 extra CONST to the first operator in order to avoid
+ 	 losing of mode information - strip it.  */
+       if (GET_CODE (op0) == CONST
+ 	  && GET_CODE (XEXP (op0, 0)) == VOIDmode)
+ 	op0 = XEXP (op0, 0);
+       op_mode = GET_MODE (op0);
+     }
+   if (op_mode == VOIDmode)
+     op_mode = GET_MODE (GET_MODE (op0) != VOIDmode ? op0 : op1);
+   if (op_mode == VOIDmode)
+     abort();
+ 
+   result = simplify_relational_operation (code, op_mode, op0, op1);
+ 
+   if (result)
+     return result;
+ 
+   return gen_rtx_combine (code, mode, op0, op1);
+ }
+ 
  static rtx
  gen_unary (code, mode, op0_mode, op0)
       enum rtx_code code;
*************** gen_unary (code, mode, op0_mode, op0)
*** 9914,9921 ****
     should have been detected earlier.  Hence we ignore all such cases.  */
  
  static enum rtx_code
! simplify_comparison (code, pop0, pop1)
       enum rtx_code code;
       rtx *pop0;
       rtx *pop1;
  {
--- 9987,9995 ----
     should have been detected earlier.  Hence we ignore all such cases.  */
  
  static enum rtx_code
! simplify_comparison (code, pmode, pop0, pop1)
       enum rtx_code code;
+      enum machine_mode *pmode;
       rtx *pop0;
       rtx *pop1;
  {
*************** simplify_comparison (code, pop0, pop1)
*** 9953,9958 ****
--- 10027,10035 ----
  	{
  	  op0 = SUBREG_REG (XEXP (XEXP (op0, 0), 0));
  	  op1 = SUBREG_REG (XEXP (XEXP (op1, 0), 0));
+ 	  *pmode = GET_MODE (op0);
+ 	  if (*pmode == VOIDmode)
+ 	    abort();
  	}
  #endif
  
*************** simplify_comparison (code, pop0, pop1)
*** 9973,9979 ****
  	  && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_WIDE_INT
  	  && XEXP (op0, 1) == XEXP (op1, 1))
  	{
! 	  enum machine_mode mode = GET_MODE (op0);
  	  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (mode);
  	  int shift_count = INTVAL (XEXP (op0, 1));
  
--- 10050,10056 ----
  	  && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_WIDE_INT
  	  && XEXP (op0, 1) == XEXP (op1, 1))
  	{
! 	  enum machine_mode mode = *pmode;
  	  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (mode);
  	  int shift_count = INTVAL (XEXP (op0, 1));
  
*************** simplify_comparison (code, pop0, pop1)
*** 10026,10031 ****
--- 10103,10111 ----
  	    {
  	      op0 = SUBREG_REG (inner_op0);
  	      op1 = SUBREG_REG (inner_op1);
+ 	      *pmode = GET_MODE (op0);
+ 	      if (*pmode == VOIDmode)
+ 		abort();
  
  	      /* The resulting comparison is always unsigned since we masked
  		 off the original sign bit.  */
*************** simplify_comparison (code, pop0, pop1)
*** 10043,10048 ****
--- 10123,10129 ----
  		  op0 = gen_lowpart_for_combine (tmode, inner_op0);
  		  op1 = gen_lowpart_for_combine (tmode, inner_op1);
  		  code = unsigned_condition (code);
+ 		  *pmode = tmode;
  		  changed = 1;
  		  break;
  		}
*************** simplify_comparison (code, pop0, pop1)
*** 10079,10085 ****
  
    while (GET_CODE (op1) == CONST_INT)
      {
!       enum machine_mode mode = GET_MODE (op0);
        unsigned int mode_width = GET_MODE_BITSIZE (mode);
        unsigned HOST_WIDE_INT mask = GET_MODE_MASK (mode);
        int equality_comparison_p;
--- 10160,10166 ----
  
    while (GET_CODE (op1) == CONST_INT)
      {
!       enum machine_mode mode = *pmode;
        unsigned int mode_width = GET_MODE_BITSIZE (mode);
        unsigned HOST_WIDE_INT mask = GET_MODE_MASK (mode);
        int equality_comparison_p;
*************** simplify_comparison (code, pop0, pop1)
*** 10317,10322 ****
--- 10398,10404 ----
  	      op0 = XEXP (op0, 2);
  	      op1 = GEN_INT (i);
  	      const_op = i;
+ 	      *pmode = GET_MODE (op0);
  
  	      /* Result is nonzero iff shift count is equal to I.  */
  	      code = reverse_condition (code);
*************** simplify_comparison (code, pop0, pop1)
*** 10330,10335 ****
--- 10412,10418 ----
  	  if (tem != op0)
  	    {
  	      op0 = tem;
+ 	      *pmode = GET_MODE (op0);
  	      continue;
  	    }
  	  break;
*************** simplify_comparison (code, pop0, pop1)
*** 10443,10448 ****
--- 10526,10532 ----
  		      << (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) - 1)))))
  	    {
  	      op0 = XEXP (op0, 0);
+ 	      *pmode = GET_MODE (op0);
  	      continue;
  	    }
  	  break;
*************** simplify_comparison (code, pop0, pop1)
*** 10474,10479 ****
--- 10558,10564 ----
  			 - GET_MODE_BITSIZE (mode)))))
  	    {
  	      op0 = SUBREG_REG (op0);
+ 	      *pmode = GET_MODE (op0);
  	      continue;
  	    }
  
*************** simplify_comparison (code, pop0, pop1)
*** 10495,10500 ****
--- 10580,10586 ----
  		  < GET_MODE_MASK (GET_MODE (XEXP (op0, 0)))))
  	    {
  	      op0 = XEXP (op0, 0);
+ 	      *pmode = GET_MODE (op0);
  	      continue;
  	    }
  	  break;
*************** simplify_comparison (code, pop0, pop1)
*** 10590,10596 ****
  
  	  /* Get the two operands being compared.  */
  	  if (GET_CODE (XEXP (op0, 0)) == COMPARE)
! 	    tem = XEXP (XEXP (op0, 0), 0), tem1 = XEXP (XEXP (op0, 0), 1);
  	  else
  	    tem = XEXP (op0, 0), tem1 = XEXP (op0, 1);
  
--- 10676,10690 ----
  
  	  /* Get the two operands being compared.  */
  	  if (GET_CODE (XEXP (op0, 0)) == COMPARE)
! 	    {
! 	      tem = XEXP (XEXP (op0, 0), 0), tem1 = XEXP (XEXP (op0, 0), 1);
! 	      /* Previous pass of combine_simplify_rtx may have but
! 		 extra CONST to the first operator in order to avoid
! 		 losing of mode information - strip it.  */
! 	      if (GET_CODE (tem) == CONST
! 		  && GET_CODE (XEXP (tem, 0)) == VOIDmode)
! 		tem = XEXP (tem, 0);
! 	    }
  	  else
  	    tem = XEXP (op0, 0), tem1 = XEXP (op0, 1);
  
*************** simplify_comparison (code, pop0, pop1)
*** 10609,10614 ****
--- 10703,10709 ----
  	      code = (code == LT || code == NE
  		      ? GET_CODE (op0) : reverse_condition (GET_CODE (op0)));
  	      op0 = tem, op1 = tem1;
+ 	      *pmode = GET_MODE (GET_MODE (op0) != VOIDmode ? op0 : op1);
  	      continue;
  	    }
  	  break;
*************** simplify_comparison (code, pop0, pop1)
*** 10692,10697 ****
--- 10787,10793 ----
  	      && (tmode = mode_for_size (i, MODE_INT, 1)) != BLKmode)
  	    {
  	      op0 = gen_lowpart_for_combine (tmode, XEXP (op0, 0));
+ 	      *pmode = tmode;
  	      continue;
  	    }
  
*************** simplify_comparison (code, pop0, pop1)
*** 10821,10826 ****
--- 10917,10923 ----
  		      <= GET_MODE_MASK (tmode))))
  	    {
  	      op0 = gen_lowpart_for_combine (tmode, XEXP (XEXP (op0, 0), 0));
+ 	      *pmode = tmode;
  	      continue;
  	    }
  
*************** simplify_comparison (code, pop0, pop1)
*** 10847,10852 ****
--- 10944,10950 ----
  	      op0 = gen_binary (PLUS, tmode,
  				gen_lowpart_for_combine (tmode, inner),
  				new_const);
+ 	      *pmode = tmode;
  	      continue;
  	    }
  
*************** simplify_comparison (code, pop0, pop1)
*** 10910,10915 ****
--- 11008,11014 ----
      {
        op0 = SUBREG_REG (op0);
        op1 = gen_lowpart_for_combine (GET_MODE (op0), op1);
+       *pmode = GET_MODE (op0);
      }
  
    else if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
*************** simplify_comparison (code, pop0, pop1)
*** 10923,10929 ****
  					      op1),
  	       (nonzero_bits (tem, GET_MODE (SUBREG_REG (op0)))
  		& ~GET_MODE_MASK (GET_MODE (op0))) == 0))
!     op0 = SUBREG_REG (op0), op1 = tem;
  
    /* We now do the opposite procedure: Some machines don't have compare
       insns in all modes.  If OP0's mode is an integer mode smaller than a
--- 11022,11031 ----
  					      op1),
  	       (nonzero_bits (tem, GET_MODE (SUBREG_REG (op0)))
  		& ~GET_MODE_MASK (GET_MODE (op0))) == 0))
!     {
!       op0 = SUBREG_REG (op0), op1 = tem;
!       *pmode = GET_MODE (op0);
!     }
  
    /* We now do the opposite procedure: Some machines don't have compare
       insns in all modes.  If OP0's mode is an integer mode smaller than a
*************** simplify_comparison (code, pop0, pop1)
*** 10931,10937 ****
       mode for which we can do the compare.  There are a number of cases in
       which we can use the wider mode.  */
  
!   mode = GET_MODE (op0);
    if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT
        && GET_MODE_SIZE (mode) < UNITS_PER_WORD
        && cmp_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
--- 11033,11039 ----
       mode for which we can do the compare.  There are a number of cases in
       which we can use the wider mode.  */
  
!   mode = *pmode;
    if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT
        && GET_MODE_SIZE (mode) < UNITS_PER_WORD
        && cmp_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
*************** simplify_comparison (code, pop0, pop1)
*** 10967,10972 ****
--- 11069,11075 ----
  
  	      op0 = gen_lowpart_for_combine (tmode, op0);
  	      op1 = gen_lowpart_for_combine (tmode, op1);
+ 	      *pmode = tmode;
  	      break;
  	    }
  
*************** simplify_comparison (code, pop0, pop1)
*** 10980,10985 ****
--- 11083,11089 ----
  				gen_lowpart_for_combine (tmode, op0),
  				GEN_INT ((HOST_WIDE_INT) 1
  					 << (GET_MODE_BITSIZE (mode) - 1)));
+ 	      *pmode = tmode;
  	      code = (code == LT) ? NE : EQ;
  	      break;
  	    }
Index: egcs/gcc/recog.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/recog.c,v
retrieving revision 1.71
diff -c -3 -p -r1.71 recog.c
*** recog.c	2000/07/31 08:42:26	1.71
--- recog.c	2000/08/03 17:51:13
*************** validate_replace_rtx_1 (loc, from, to, o
*** 456,467 ****
  
    switch (code)
      {
      case PLUS:
        /* If we have a PLUS whose second operand is now a CONST_INT, use
  	 plus_constant to try to simplify it.  */
        if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to)
! 	validate_change (object, loc, plus_constant (XEXP (x, 0), INTVAL (to)),
! 			 1);
        return;
  
      case MINUS:
--- 457,501 ----
  
    switch (code)
      {
+     case COMPARE:
+       /* Comparison of two VOIDmode values is incorrect.  We get around
+ 	 by embedding first VOIDmode value by CONST with proper mode.
+ 	 Resulting insn would not match, but this is usefull for keeping
+ 	 the information in REG_EQUAL notes constructed by gcse.  */
+       if (GET_MODE (to) == VOIDmode)
+ 	{
+ 	  enum machine_mode mode;
+ 	  rtx op0, op1;
+ 	  op0 = XEXP (x, 0);
+ 	  op1 = XEXP (x, 1);
+ 	  mode = GET_MODE (GET_MODE (op0) != VOIDmode ? op0 : op1);
+ 	  /* Comparison of two VOIDmode values in incorrect.  */
+ 	  if (mode == VOIDmode)
+ 	    abort();
+ 	  if (rtx_equal_p (op0, from))
+ 	    op0 = to;
+ 	  if (rtx_equal_p (op1, from))
+ 	    op1 = to;
+ 	  if (GET_MODE (op0) == VOIDmode
+ 	      && GET_MODE (op1) == VOIDmode)
+ 	    {
+ 	      validate_change (object, &XEXP (*loc, 0),
+ 			       gen_rtx_CONST (mode, op0), 1);
+ 	      validate_change (object, &XEXP (*loc, 1),
+ 			       op1, 1);
+ 	      return;
+ 	    }
+ 	}
+       break;
      case PLUS:
        /* If we have a PLUS whose second operand is now a CONST_INT, use
  	 plus_constant to try to simplify it.  */
        if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to)
! 	{
! 	  validate_change (object, loc, plus_constant (XEXP (x, 0),
! 						       INTVAL (to)),
! 			   1);
! 	}
        return;
  
      case MINUS:
*************** validate_replace_rtx_1 (loc, from, to, o
*** 587,592 ****
--- 621,645 ----
        break;
        
      default:
+       /* We need to take care for simplifying the comparisons.  In case we replace
+          both operands by VOIDmode constants, the information about the rtx type is
+          lost.  */
+       if (GET_RTX_CLASS (code) == '<'
+ 	  && (rtx_equal_p (XEXP (x, 0), from)
+ 	      || rtx_equal_p (XEXP (x, 1), from)))
+ 	{
+ 	  rtx y;
+ 	  enum machine_mode mode = GET_MODE (GET_MODE (XEXP (x, 0)) != VOIDmode
+ 	                                     ? XEXP (x, 0) : XEXP (x, 1));
+ 	  y = simplify_relational_operation (code, mode, 
+ 					     rtx_equal_p (XEXP (x, 0), from) ? to : XEXP (x, 0),
+ 					     rtx_equal_p (XEXP (x, 1), from) ? to : XEXP (x, 1));
+ 	  if (y)
+ 	    {
+ 	      validate_change (object, loc, y, 1);
+ 	      return;
+ 	    }
+ 	}
        break;
      }
        
Index: egcs/gcc/simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/simplify-rtx.c,v
retrieving revision 1.23
diff -c -3 -p -r1.23 simplify-rtx.c
*** simplify-rtx.c	2000/07/30 18:13:10	1.23
--- simplify-rtx.c	2000/08/03 17:51:16
*************** simplify_relational_operation (code, mod
*** 1691,1704 ****
    int equal, op0lt, op0ltu, op1lt, op1ltu;
    rtx tem;
  
!   if (mode == VOIDmode
!       && (GET_MODE (op0) != VOIDmode
! 	  || GET_MODE (op1) != VOIDmode))
      abort();
  
    /* If op0 is a compare, extract the comparison arguments from it.  */
    if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
!     op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
  
    /* We can't simplify MODE_CC values since we don't know what the
       actual comparison is.  */
--- 1686,1724 ----
    int equal, op0lt, op0ltu, op1lt, op1ltu;
    rtx tem;
  
!   /* Do simple checking of mode.  The mode should be never VOIDmode, since we
!      don't know the mode of operands in case they are both VOIDmode and mode
!      of the operands must match.  */
!   if (mode == VOIDmode)
      abort();
+   if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode)
+     abort();
+   if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode)
+     abort();
  
    /* If op0 is a compare, extract the comparison arguments from it.  */
    if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
!     {
!       op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
!       if (GET_MODE (op0) != VOIDmode)
! 	mode = GET_MODE (op0);
!       else
! 	mode = GET_MODE (op1);
!       /* We can't have both operands of COMPARE VOIDmode, since we would
! 	 not be able to determine the mode of comparison them, we create
! 	 fake CONST with proper mode when such expression needs to be
! 	 created temporarily - this happends in the combine and in gcse
! 	 when we happen to propagate constant into comparison.  */
!       if (GET_CODE (op0) == CONST
! 	  && GET_MODE (XEXP (op0, 0)) == VOIDmode)
! 	op0 = XEXP (op0, 0);
!     }
!   /* We can handle comparison only in the integral or floating point modes.
!      When CCmode or VOIDmode appears here, it means mistake elsewhere
!      most probably because the real mode of comparison got lost by replacing
!      by VOIDmode constants.  */
!   if (!INTEGRAL_MODE_P (mode)
!       && !FLOAT_MODE_P (mode))
  
    /* We can't simplify MODE_CC values since we don't know what the
       actual comparison is.  */

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