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: Fix COND_EXPR foldings that are not happening


> [snip] The correct
way to catch these missing optimizations is to additionally recognize
"A < 0 ? N : 0" and "(A >> log2 N) & 1 ? N : 0".  [...]
I'd also recommend leaving the "A ? B : C" to "!A ? B : C"
canonicalization where it is.  [...]
Finally, and I appreciate that this is a pre-existing problem and not
specifically introduced by your patch, I believe that you can eliminate
almost all of the calls to pedantic_non_lvalue in your patch.

Could I ask you to resubmit your patch with the above changes?

Here it is. I fixed the problem with unbounded recursion of fold by not relying on recursion, and factoring a new function fold_cond_expr_with_comparison, which could be used by tree-ssa-phiopt.


Paolo
2004-06-11  Paolo Bonzini  <bonzini@gnu.org>

	* fold-const.c (fold_cond_expr_with_comparison):
	New function, extracted from fold.
	(fold): Extract code to fold A op B ? A : C, use
	it to fold A op B ? C : A.  Really optimize
	A & N ? N : 0 where N is a power of two.  Avoid
	relying on canonicalization and recursion for
	foldings of COND_EXPR to happen.

Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.389
diff -c -r1.389 fold-const.c
*** fold-const.c	8 Jun 2004 22:03:29 -0000	1.389
--- fold-const.c	11 Jun 2004 07:26:30 -0000
***************
*** 117,122 ****
--- 117,123 ----
  static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree,
  			 tree);
  static tree fold_range_test (tree);
+ static tree fold_cond_expr_with_comparison (tree, tree, tree);
  static tree unextend (tree, int, int, tree);
  static tree fold_truthop (enum tree_code, tree, tree, tree);
  static tree optimize_minmax_comparison (tree);
***************
*** 3964,3969 ****
--- 3965,4192 ----
    return 1;
  }
  
+ 
+ /* Subroutine of fold, looking inside expressions of the form
+    A op B ? A : C.  */
+ static tree
+ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg2)
+ {
+   enum tree_code comp_code = TREE_CODE (arg0);
+   tree arg00 = TREE_OPERAND (arg0, 0);
+   tree arg01 = TREE_OPERAND (arg0, 1);
+   tree tem;
+   STRIP_NOPS (arg2);
+ 
+   /* If we have A op 0 ? A : -A, consider applying the following
+      transformations:
+ 
+      A == 0? A : -A    same as -A
+      A != 0? A : -A    same as A
+      A >= 0? A : -A    same as abs (A)
+      A > 0?  A : -A    same as abs (A)
+      A <= 0? A : -A    same as -abs (A)
+      A < 0?  A : -A    same as -abs (A)
+ 
+      None of these transformations work for modes with signed
+      zeros.  If A is +/-0, the first two transformations will
+      change the sign of the result (from +0 to -0, or vice
+      versa).  The last four will fix the sign of the result,
+      even though the original expressions could be positive or
+      negative, depending on the sign of A.
+ 
+      Note that all these transformations are correct if A is
+      NaN, since the two alternatives (A and -A) are also NaNs.  */
+   if ((FLOAT_TYPE_P (TREE_TYPE (arg01))
+        ? real_zerop (arg01)
+        : integer_zerop (arg01))
+       && TREE_CODE (arg2) == NEGATE_EXPR
+       && operand_equal_p (TREE_OPERAND (arg2, 0), arg00, 0))
+     switch (comp_code)
+       {
+       case EQ_EXPR:
+ 	return fold_convert (type, negate_expr (arg00));
+       case NE_EXPR:
+ 	return pedantic_non_lvalue (fold_convert (type, arg00));
+       case GE_EXPR:
+       case GT_EXPR:
+ 	if (TYPE_UNSIGNED (TREE_TYPE (arg00)))
+ 	  arg00 = fold_convert (lang_hooks.types.signed_type
+ 			        (TREE_TYPE (arg00)), arg00);
+ 	tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg00), arg00));
+ 	return pedantic_non_lvalue (fold_convert (type, tem));
+       case LE_EXPR:
+       case LT_EXPR:
+ 	if (TYPE_UNSIGNED (TREE_TYPE (arg00)))
+ 	  arg00 = fold_convert (lang_hooks.types.signed_type
+ 			        (TREE_TYPE (arg00)), arg00);
+ 	tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg00), arg00));
+ 	return negate_expr (fold_convert (type, tem));
+       default:
+ 	abort ();
+       }
+ 
+   /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
+      A == 0 ? A : 0 is always 0 unless A is -0.  Note that
+      both transformations are correct when A is NaN: A != 0
+      is then true, and A == 0 is false.  */
+ 
+   if (integer_zerop (arg01) && integer_zerop (arg2))
+     {
+       if (comp_code == NE_EXPR)
+ 	return pedantic_non_lvalue (fold_convert (type, arg00));
+       else if (comp_code == EQ_EXPR)
+ 	return pedantic_non_lvalue (fold_convert (type, integer_zero_node));
+     }
+ 
+   /* Try some transformations of A op B ? A : B.
+ 
+      A == B? A : B    same as B
+      A != B? A : B    same as A
+      A >= B? A : B    same as max (A, B)
+      A > B?  A : B    same as max (B, A)
+      A <= B? A : B    same as min (A, B)
+      A < B?  A : B    same as min (B, A)
+ 
+      As above, these transformations don't work in the presence
+      of signed zeros.  For example, if A and B are zeros of
+      opposite sign, the first two transformations will change
+      the sign of the result.  In the last four, the original
+      expressions give different results for (A=+0, B=-0) and
+      (A=-0, B=+0), but the transformed expressions do not.
+ 
+      The first two transformations are correct if either A or B
+      is a NaN.  In the first transformation, the condition will
+      be false, and B will indeed be chosen.  In the case of the
+      second transformation, the condition A != B will be true,
+      and A will be chosen.
+ 
+      The conversions to max() and min() are not correct if B is
+      a number and A is not.  The conditions in the original
+      expressions will be false, so all four give B.  The min()
+      and max() versions would give a NaN instead.  */
+   if (operand_equal_for_comparison_p (arg01, arg2, arg00))
+     {
+       tree comp_op0 = arg00;
+       tree comp_op1 = arg01;
+       tree comp_type = TREE_TYPE (comp_op0);
+ 
+       /* Avoid adding NOP_EXPRs in case this is an lvalue.  */
+       if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
+ 	{
+ 	  comp_type = type;
+ 	  comp_op0 = arg00;
+ 	  comp_op1 = arg2;
+ 	}
+ 
+       switch (comp_code)
+ 	{
+ 	case EQ_EXPR:
+ 	  return pedantic_non_lvalue (fold_convert (type, arg2));
+ 	case NE_EXPR:
+ 	  return pedantic_non_lvalue (fold_convert (type, arg00));
+ 	case LE_EXPR:
+ 	case LT_EXPR:
+ 	  /* In C++ a ?: expression can be an lvalue, so put the
+ 	     operand which will be used if they are equal first
+ 	     so that we can convert this back to the
+ 	     corresponding COND_EXPR.  */
+ 	  if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00))))
+ 	    return pedantic_non_lvalue (
+ 		     fold_convert (type, fold (build2 (MIN_EXPR, comp_type,
+ 				         (comp_code == LE_EXPR
+ 				          ? comp_op0 : comp_op1),
+ 				         (comp_code == LE_EXPR
+ 				          ? comp_op1 : comp_op0)))));
+ 	  break;
+ 	case GE_EXPR:
+ 	case GT_EXPR:
+ 	  if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00))))
+ 	    return pedantic_non_lvalue (
+ 		     fold_convert (type, fold (build2 (MAX_EXPR, comp_type,
+ 				         (comp_code == GE_EXPR
+ 				          ? comp_op0 : comp_op1),
+ 				         (comp_code == GE_EXPR
+ 				          ? comp_op1 : comp_op0)))));
+ 	  break;
+ 	default:
+ 	  abort ();
+ 	}
+     }
+ 
+   /* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
+      we might still be able to simplify this.  For example,
+      if C1 is one less or one more than C2, this might have started
+      out as a MIN or MAX and been transformed by this function.
+      Only good for INTEGER_TYPEs, because we need TYPE_MAX_VALUE.  */
+ 
+   if (INTEGRAL_TYPE_P (type)
+       && TREE_CODE (arg01) == INTEGER_CST
+       && TREE_CODE (arg2) == INTEGER_CST)
+     switch (comp_code)
+       {
+       case EQ_EXPR:
+ 	/* We can replace A with C1 in this case.  */
+ 	arg00 = fold_convert (type, arg01);
+ 	return fold (build3 (COND_EXPR, type, arg0, arg00, arg2));
+ 
+       case LT_EXPR:
+ 	/* If C1 is C2 + 1, this is min(A, C2).  */
+ 	if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
+ 			       OEP_ONLY_CONST)
+ 	    && operand_equal_p (arg01,
+ 				const_binop (PLUS_EXPR, arg2,
+ 					     integer_one_node, 0),
+ 				OEP_ONLY_CONST))
+ 	  return pedantic_non_lvalue (fold (build2 (MIN_EXPR,
+ 						    type, arg00, arg2)));
+ 	break;
+ 
+       case LE_EXPR:
+ 	/* If C1 is C2 - 1, this is min(A, C2).  */
+ 	if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
+ 			       OEP_ONLY_CONST)
+ 	    && operand_equal_p (arg01,
+ 				const_binop (MINUS_EXPR, arg2,
+ 					     integer_one_node, 0),
+ 				OEP_ONLY_CONST))
+ 	  return pedantic_non_lvalue (fold (build2 (MIN_EXPR,
+ 						    type, arg00, arg2)));
+ 	break;
+ 
+       case GT_EXPR:
+ 	/* If C1 is C2 - 1, this is max(A, C2).  */
+ 	if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
+ 			       OEP_ONLY_CONST)
+ 	    && operand_equal_p (arg01,
+ 				const_binop (MINUS_EXPR, arg2,
+ 					     integer_one_node, 0),
+ 				OEP_ONLY_CONST))
+ 	  return pedantic_non_lvalue (fold (build2 (MAX_EXPR,
+ 						    type, arg00, arg2)));
+ 	break;
+ 
+       case GE_EXPR:
+ 	/* If C1 is C2 + 1, this is max(A, C2).  */
+ 	if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
+ 			       OEP_ONLY_CONST)
+ 	    && operand_equal_p (arg01,
+ 				const_binop (PLUS_EXPR, arg2,
+ 					     integer_one_node, 0),
+ 				OEP_ONLY_CONST))
+ 	  return pedantic_non_lvalue (fold (build2 (MAX_EXPR,
+ 						    type, arg00, arg2)));
+ 	break;
+       case NE_EXPR:
+ 	break;
+       default:
+ 	abort ();
+       }
+ 
+   return NULL_TREE;
+ }
+ 
+ 
+ 
  #ifndef RANGE_TEST_NON_SHORT_CIRCUIT
  #define RANGE_TEST_NON_SHORT_CIRCUIT (BRANCH_COST >= 2)
  #endif
***************
*** 8139,8365 ****
        /* If we have A op B ? A : C, we may be able to convert this to a
  	 simpler expression, depending on the operation and the values
  	 of B and C.  Signed zeros prevent all of these transformations,
! 	 for reasons given above each one.  */
  
        if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
  	  && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
  					     arg1, TREE_OPERAND (arg0, 1))
  	  && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
  	{
! 	  tree arg2 = TREE_OPERAND (t, 2);
! 	  enum tree_code comp_code = TREE_CODE (arg0);
! 
! 	  STRIP_NOPS (arg2);
! 
! 	  /* If we have A op 0 ? A : -A, consider applying the following
! 	     transformations:
! 
! 	     A == 0? A : -A    same as -A
! 	     A != 0? A : -A    same as A
! 	     A >= 0? A : -A    same as abs (A)
! 	     A > 0?  A : -A    same as abs (A)
! 	     A <= 0? A : -A    same as -abs (A)
! 	     A < 0?  A : -A    same as -abs (A)
! 
! 	     None of these transformations work for modes with signed
! 	     zeros.  If A is +/-0, the first two transformations will
! 	     change the sign of the result (from +0 to -0, or vice
! 	     versa).  The last four will fix the sign of the result,
! 	     even though the original expressions could be positive or
! 	     negative, depending on the sign of A.
! 
! 	     Note that all these transformations are correct if A is
! 	     NaN, since the two alternatives (A and -A) are also NaNs.  */
! 	  if ((FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 1)))
! 	       ? real_zerop (TREE_OPERAND (arg0, 1))
! 	       : integer_zerop (TREE_OPERAND (arg0, 1)))
! 	      && TREE_CODE (arg2) == NEGATE_EXPR
! 	      && operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
! 	    switch (comp_code)
! 	      {
! 	      case EQ_EXPR:
! 		tem = fold_convert (TREE_TYPE (TREE_OPERAND (t, 1)), arg1);
! 		tem = fold_convert (type, negate_expr (tem));
! 		return pedantic_non_lvalue (tem);
! 	      case NE_EXPR:
! 		return pedantic_non_lvalue (fold_convert (type, arg1));
! 	      case GE_EXPR:
! 	      case GT_EXPR:
! 		if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
! 		  arg1 = fold_convert (lang_hooks.types.signed_type
! 				       (TREE_TYPE (arg1)), arg1);
! 		arg1 = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
! 		return pedantic_non_lvalue (fold_convert (type, arg1));
! 	      case LE_EXPR:
! 	      case LT_EXPR:
! 		if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
! 		  arg1 = fold_convert (lang_hooks.types.signed_type
! 				       (TREE_TYPE (arg1)), arg1);
! 		arg1 = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
! 		arg1 = negate_expr (fold_convert (type, arg1));
! 		return pedantic_non_lvalue (arg1);
! 	      default:
! 		abort ();
! 	      }
! 
! 	  /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
! 	     A == 0 ? A : 0 is always 0 unless A is -0.  Note that
! 	     both transformations are correct when A is NaN: A != 0
! 	     is then true, and A == 0 is false.  */
! 
! 	  if (integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (arg2))
! 	    {
! 	      if (comp_code == NE_EXPR)
! 		return pedantic_non_lvalue (fold_convert (type, arg1));
! 	      else if (comp_code == EQ_EXPR)
! 		return pedantic_non_lvalue (fold_convert (type, integer_zero_node));
! 	    }
! 
! 	  /* Try some transformations of A op B ? A : B.
! 
! 	     A == B? A : B    same as B
! 	     A != B? A : B    same as A
! 	     A >= B? A : B    same as max (A, B)
! 	     A > B?  A : B    same as max (B, A)
! 	     A <= B? A : B    same as min (A, B)
! 	     A < B?  A : B    same as min (B, A)
! 
! 	     As above, these transformations don't work in the presence
! 	     of signed zeros.  For example, if A and B are zeros of
! 	     opposite sign, the first two transformations will change
! 	     the sign of the result.  In the last four, the original
! 	     expressions give different results for (A=+0, B=-0) and
! 	     (A=-0, B=+0), but the transformed expressions do not.
! 
! 	     The first two transformations are correct if either A or B
! 	     is a NaN.  In the first transformation, the condition will
! 	     be false, and B will indeed be chosen.  In the case of the
! 	     second transformation, the condition A != B will be true,
! 	     and A will be chosen.
! 
! 	     The conversions to max() and min() are not correct if B is
! 	     a number and A is not.  The conditions in the original
! 	     expressions will be false, so all four give B.  The min()
! 	     and max() versions would give a NaN instead.  */
! 	  if (operand_equal_for_comparison_p (TREE_OPERAND (arg0, 1),
! 					      arg2, TREE_OPERAND (arg0, 0)))
! 	    {
! 	      tree comp_op0 = TREE_OPERAND (arg0, 0);
! 	      tree comp_op1 = TREE_OPERAND (arg0, 1);
! 	      tree comp_type = TREE_TYPE (comp_op0);
! 
! 	      /* Avoid adding NOP_EXPRs in case this is an lvalue.  */
! 	      if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
! 		{
! 		  comp_type = type;
! 		  comp_op0 = arg1;
! 		  comp_op1 = arg2;
! 		}
  
! 	      switch (comp_code)
! 		{
! 		case EQ_EXPR:
! 		  return pedantic_non_lvalue (fold_convert (type, arg2));
! 		case NE_EXPR:
! 		  return pedantic_non_lvalue (fold_convert (type, arg1));
! 		case LE_EXPR:
! 		case LT_EXPR:
! 		  /* In C++ a ?: expression can be an lvalue, so put the
! 		     operand which will be used if they are equal first
! 		     so that we can convert this back to the
! 		     corresponding COND_EXPR.  */
! 		  if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
! 		    return pedantic_non_lvalue (fold_convert
! 		      (type, fold (build2 (MIN_EXPR, comp_type,
! 					   (comp_code == LE_EXPR
! 					    ? comp_op0 : comp_op1),
! 					   (comp_code == LE_EXPR
! 					    ? comp_op1 : comp_op0)))));
! 		  break;
! 		case GE_EXPR:
! 		case GT_EXPR:
! 		  if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
! 		    return pedantic_non_lvalue (fold_convert
! 		      (type, fold (build2 (MAX_EXPR, comp_type,
! 					   (comp_code == GE_EXPR
! 					    ? comp_op0 : comp_op1),
! 					   (comp_code == GE_EXPR
! 					    ? comp_op1 : comp_op0)))));
! 		  break;
! 		default:
! 		  abort ();
! 		}
  	    }
- 
- 	  /* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
- 	     we might still be able to simplify this.  For example,
- 	     if C1 is one less or one more than C2, this might have started
- 	     out as a MIN or MAX and been transformed by this function.
- 	     Only good for INTEGER_TYPEs, because we need TYPE_MAX_VALUE.  */
- 
- 	  if (INTEGRAL_TYPE_P (type)
- 	      && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- 	      && TREE_CODE (arg2) == INTEGER_CST)
- 	    switch (comp_code)
- 	      {
- 	      case EQ_EXPR:
- 		/* We can replace A with C1 in this case.  */
- 		arg1 = fold_convert (type, TREE_OPERAND (arg0, 1));
- 		return fold (build3 (code, type, TREE_OPERAND (t, 0), arg1,
- 				     TREE_OPERAND (t, 2)));
- 
- 	      case LT_EXPR:
- 		/* If C1 is C2 + 1, this is min(A, C2).  */
- 		if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
- 				       OEP_ONLY_CONST)
- 		    && operand_equal_p (TREE_OPERAND (arg0, 1),
- 					const_binop (PLUS_EXPR, arg2,
- 						     integer_one_node, 0),
- 					OEP_ONLY_CONST))
- 		  return pedantic_non_lvalue
- 		    (fold (build2 (MIN_EXPR, type, arg1, arg2)));
- 		break;
- 
- 	      case LE_EXPR:
- 		/* If C1 is C2 - 1, this is min(A, C2).  */
- 		if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
- 				       OEP_ONLY_CONST)
- 		    && operand_equal_p (TREE_OPERAND (arg0, 1),
- 					const_binop (MINUS_EXPR, arg2,
- 						     integer_one_node, 0),
- 					OEP_ONLY_CONST))
- 		  return pedantic_non_lvalue
- 		    (fold (build2 (MIN_EXPR, type, arg1, arg2)));
- 		break;
- 
- 	      case GT_EXPR:
- 		/* If C1 is C2 - 1, this is max(A, C2).  */
- 		if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
- 				       OEP_ONLY_CONST)
- 		    && operand_equal_p (TREE_OPERAND (arg0, 1),
- 					const_binop (MINUS_EXPR, arg2,
- 						     integer_one_node, 0),
- 					OEP_ONLY_CONST))
- 		  return pedantic_non_lvalue
- 		    (fold (build2 (MAX_EXPR, type, arg1, arg2)));
- 		break;
- 
- 	      case GE_EXPR:
- 		/* If C1 is C2 + 1, this is max(A, C2).  */
- 		if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
- 				       OEP_ONLY_CONST)
- 		    && operand_equal_p (TREE_OPERAND (arg0, 1),
- 					const_binop (PLUS_EXPR, arg2,
- 						     integer_one_node, 0),
- 					OEP_ONLY_CONST))
- 		  return pedantic_non_lvalue
- 		    (fold (build2 (MAX_EXPR, type, arg1, arg2)));
- 		break;
- 	      case NE_EXPR:
- 		break;
- 	      default:
- 		abort ();
- 	      }
  	}
  
        /* If the second operand is simpler than the third, swap them
--- 8362,8394 ----
        /* If we have A op B ? A : C, we may be able to convert this to a
  	 simpler expression, depending on the operation and the values
  	 of B and C.  Signed zeros prevent all of these transformations,
! 	 for reasons given above each one.
  
+          Also try swapping the arguments and inverting the conditional.  */
        if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
  	  && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
  					     arg1, TREE_OPERAND (arg0, 1))
  	  && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
  	{
! 	  tem = fold_cond_expr_with_comparison (type, arg0,
! 						TREE_OPERAND (t, 2));
! 	  if (tem)
! 	    return tem;
! 	}
  
!       if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
! 	  && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
! 					     TREE_OPERAND (t, 2),
! 					     TREE_OPERAND (arg0, 1))
! 	  && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2)))))
! 	{
! 	  tem = invert_truthvalue (arg0);
! 	  if (TREE_CODE_CLASS (TREE_CODE (tem)) == '<')
! 	    {
! 	      tem = fold_cond_expr_with_comparison (type, tem, arg1);
! 	      if (tem)
! 		return tem;
  	    }
  	}
  
        /* If the second operand is simpler than the third, swap them
***************
*** 8395,8419 ****
  	return pedantic_non_lvalue (fold_convert (type,
  						  invert_truthvalue (arg0)));
  
!       /* Look for expressions of the form A & 2 ? 2 : 0.  The result of this
! 	 operation is simply A & 2.  */
  
!       if (integer_zerop (TREE_OPERAND (t, 2))
! 	  && TREE_CODE (arg0) == NE_EXPR
! 	  && integer_zerop (TREE_OPERAND (arg0, 1))
! 	  && integer_pow2p (arg1)
! 	  && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
! 	  && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
! 			      arg1, OEP_ONLY_CONST))
! 	return pedantic_non_lvalue (fold_convert (type,
! 						  TREE_OPERAND (arg0, 0)));
  
        /* Convert A ? B : 0 into A && B if A and B are truth values.  */
        if (integer_zerop (TREE_OPERAND (t, 2))
  	  && truth_value_p (TREE_CODE (arg0))
  	  && truth_value_p (TREE_CODE (arg1)))
! 	return pedantic_non_lvalue (fold (build2 (TRUTH_ANDIF_EXPR, type,
! 						  arg0, arg1)));
  
        /* Convert A ? B : 1 into !A || B if A and B are truth values.  */
        if (integer_onep (TREE_OPERAND (t, 2))
--- 8424,8458 ----
  	return pedantic_non_lvalue (fold_convert (type,
  						  invert_truthvalue (arg0)));
  
!       /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>).  */
!       if (TREE_CODE (arg0) == LT_EXPR
!           && integer_zerop (TREE_OPERAND (arg0, 1))
!           && integer_zerop (TREE_OPERAND (t, 2))
!           && (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
!         return fold_convert (type, fold (build2 (BIT_AND_EXPR,
! 						 TREE_TYPE (tem), tem, arg1)));
  
!       /* (A >> N) & 1 ? (1 << N) : 0 is simply A & (1 << N).  A & 1 was
! 	 already handled above.  */
!       if (TREE_CODE (arg0) == BIT_AND_EXPR
! 	  && integer_onep (TREE_OPERAND (arg0, 1))
! 	  && integer_zerop (TREE_OPERAND (t, 2))
! 	  && integer_pow2p (arg1))
! 	{
! 	  tree tem = TREE_OPERAND (arg0, 0);
! 	  STRIP_NOPS (tem);
! 	  if (TREE_CODE (tem) == RSHIFT_EXPR
!               && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
! 	         TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)))
! 	    return fold (build2 (BIT_AND_EXPR, type,
! 				 TREE_OPERAND (tem, 0), arg1));
! 	}
  
        /* Convert A ? B : 0 into A && B if A and B are truth values.  */
        if (integer_zerop (TREE_OPERAND (t, 2))
  	  && truth_value_p (TREE_CODE (arg0))
  	  && truth_value_p (TREE_CODE (arg1)))
! 	return fold (build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1));
  
        /* Convert A ? B : 1 into !A || B if A and B are truth values.  */
        if (integer_onep (TREE_OPERAND (t, 2))
***************
*** 8423,8432 ****
  	  /* Only perform transformation if ARG0 is easily inverted.  */
  	  tem = invert_truthvalue (arg0);
  	  if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
! 	    return pedantic_non_lvalue (fold (build2 (TRUTH_ORIF_EXPR, type,
! 						      tem, arg1)));
  	}
  
        return t;
  
      case COMPOUND_EXPR:
--- 8462,8489 ----
  	  /* Only perform transformation if ARG0 is easily inverted.  */
  	  tem = invert_truthvalue (arg0);
  	  if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
! 	    return fold (build2 (TRUTH_ORIF_EXPR, type, tem, arg1));
  	}
  
+       /* Convert A ? 0 : B into !A && B if A and B are truth values.  */
+       if (integer_zerop (arg1)
+ 	  && truth_value_p (TREE_CODE (arg0))
+ 	  && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+ 	{
+ 	  /* Only perform transformation if ARG0 is easily inverted.  */
+ 	  tem = invert_truthvalue (arg0);
+ 	  if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+ 	    return fold (build2 (TRUTH_ANDIF_EXPR, type, tem,
+ 				 TREE_OPERAND (t, 2)));
+ 	}
+ 
+       /* Convert A ? 1 : B into A || B if A and B are truth values.  */
+       if (integer_onep (arg1)
+ 	  && truth_value_p (TREE_CODE (arg0))
+ 	  && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+ 	return fold (build2 (TRUTH_ORIF_EXPR, type, arg0,
+ 			     TREE_OPERAND (t, 2)));
+ 
        return t;
  
      case COMPOUND_EXPR:

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