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]

[Committed] Three comparison constant folding tweaks


The following patch implements three minor clean-ups to GCC's
constant folding of comparisons.

The first simplifies the logic in fold_relational_const by calling
real.c's real_compare to perform comparisons between two REAL_CSTs.
Previously we were playing games with TREE_CODE and ultimately using
either REAL_VALUES_EQUAL or REAL_VALUES_LESS directly.  Many thanks
to Paolo Bonzini for suggesting this change.

The second was spotted whilst implementing the first.  One of the
transformations in fold_relational_const doesn't belong there as
it doesn't just apply to constants, and is therefore never triggered
by calls from nondestructive_fold_binary_to_constant, for example.
This patch hoists this transformation out of fold_relational_const
into fold where it belongs.  This required adding a prototype for
tree_expr_nonzero_p to the top of fold-const.c.

The third and final improvement is that it adds the optimizations
that "x UNEQ x", "x UNLE x" and "x UNGE x" are always true, and that
"x LTGT x" is always false if we don't honor trapping math.  This
should help Diego's "Linearize COND_EXPRs involving a single SSA_NAME"
patch.


The following patch was tested on i686-pc-linux-gnu with a full "make
bootstrap", all default languages, and regression tested with a
top-level "make -k check" with no new failures.

Committed to mainline CVS.



2004-07-19  Roger Sayle  <roger@eyesopen.com>

	* fold-const.c (tree_expr_nonzero_p): Add function prototype.
	(fold) <EQ_EXPR>: Move tree_expr_nonzero_p optimization from
	fold_relational_const to here, i.e. "(x | 5) == 0" -> false.
	(fold) (UNEQ_EXPR>: Add optimizations for unordered comparisons
	of the form "x op x" where op is UNLE, UNGE, UNEQ or LTGT.
	(fold_relational_const): Tidy up handling of floating point
	comparisons by calling real_compare.  Remove tree_expr_nonzero_p
	transformation; fold_relational_const assumes constant operands.


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.424
diff -c -3 -p -r1.424 fold-const.c
*** fold-const.c	11 Jul 2004 21:56:37 -0000	1.424
--- fold-const.c	19 Jul 2004 01:55:52 -0000
*************** static tree fold_not_const (tree, tree);
*** 137,142 ****
--- 137,143 ----
  static tree fold_relational_const (enum tree_code, tree, tree, tree);
  static tree fold_relational_hi_lo (enum tree_code *, const tree,
                                     tree *, tree *);
+ static bool tree_expr_nonzero_p (tree);

  /* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
     overflow.  Suppose A, B and SUM have the same respective signs as A1, B1,
*************** fold (tree expr)
*** 8638,8646 ****
  	    return t1;
  	}

!       /* Both ARG0 and ARG1 are known to be constants at this point.  */
        t1 = fold_relational_const (code, type, arg0, arg1);
!       return (t1 == NULL_TREE ? t : t1);

      case UNORDERED_EXPR:
      case ORDERED_EXPR:
--- 8639,8652 ----
  	    return t1;
  	}

!       if ((code == EQ_EXPR || code == NE_EXPR)
! 	  && !TREE_SIDE_EFFECTS (arg0)
! 	  && integer_zerop (arg1)
! 	  && tree_expr_nonzero_p (arg0))
! 	return constant_boolean_node (code==NE_EXPR, type);
!
        t1 = fold_relational_const (code, type, arg0, arg1);
!       return t1 == NULL_TREE ? t : t1;

      case UNORDERED_EXPR:
      case ORDERED_EXPR:
*************** fold (tree expr)
*** 8679,8684 ****
--- 8685,8700 ----
  	  return omit_one_operand (type, t1, arg0);
  	}

+       /* Simplify unordered comparison of something with itself.  */
+       if ((code == UNLE_EXPR || code == UNGE_EXPR || code == UNEQ_EXPR)
+ 	  && operand_equal_p (arg0, arg1, 0))
+ 	return constant_boolean_node (1, type);
+
+       if (code == LTGT_EXPR
+ 	  && !flag_trapping_math
+ 	  && operand_equal_p (arg0, arg1, 0))
+ 	return constant_boolean_node (0, type);
+
        /* Fold (double)float1 CMP (double)float2 into float1 CMP float2.  */
        {
  	tree targ0 = strip_float_extensions (arg0);
*************** fold_relational_const (enum tree_code co
*** 10394,10402 ****

    if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
      {
        /* Handle the cases where either operand is a NaN.  */
!       if (REAL_VALUE_ISNAN (TREE_REAL_CST (op0))
!           || REAL_VALUE_ISNAN (TREE_REAL_CST (op1)))
  	{
  	  switch (code)
  	    {
--- 10410,10420 ----

    if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
      {
+       const REAL_VALUE_TYPE *c0 = TREE_REAL_CST_PTR (op0);
+       const REAL_VALUE_TYPE *c1 = TREE_REAL_CST_PTR (op1);
+
        /* Handle the cases where either operand is a NaN.  */
!       if (real_isnan (c0) || real_isnan (c1))
  	{
  	  switch (code)
  	    {
*************** fold_relational_const (enum tree_code co
*** 10432,10468 ****
  	  return constant_boolean_node (result, type);
  	}

!       /* From here on we're sure there are no NaNs.  */
!       switch (code)
! 	{
! 	case ORDERED_EXPR:
! 	  return constant_boolean_node (true, type);
!
! 	case UNORDERED_EXPR:
! 	  return constant_boolean_node (false, type);
!
! 	case UNLT_EXPR:
! 	  code = LT_EXPR;
! 	  break;
! 	case UNLE_EXPR:
! 	  code = LE_EXPR;
! 	  break;
! 	case UNGT_EXPR:
! 	  code = GT_EXPR;
! 	  break;
! 	case UNGE_EXPR:
! 	  code = GE_EXPR;
! 	  break;
! 	case UNEQ_EXPR:
! 	  code = EQ_EXPR;
! 	  break;
! 	case LTGT_EXPR:
! 	  code = NE_EXPR;
! 	  break;
!
! 	default:
! 	  break;
! 	}
      }

    /* From here on we only handle LT, LE, GT, GE, EQ and NE.
--- 10450,10456 ----
  	  return constant_boolean_node (result, type);
  	}

!       return constant_boolean_node (real_compare (code, c0, c1), type);
      }

    /* From here on we only handle LT, LE, GT, GE, EQ and NE.
*************** fold_relational_const (enum tree_code co
*** 10503,10523 ****
        else
  	result = INT_CST_LT (op0, op1);
      }
-
-   else if (code == EQ_EXPR && !TREE_SIDE_EFFECTS (op0)
-            && integer_zerop (op1) && tree_expr_nonzero_p (op0))
-     result = 0;
-
-   /* Two real constants can be compared explicitly.  */
-   else if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
-     {
-       if (code == EQ_EXPR)
- 	result = REAL_VALUES_EQUAL (TREE_REAL_CST (op0),
- 				    TREE_REAL_CST (op1));
-       else
- 	result = REAL_VALUES_LESS (TREE_REAL_CST (op0),
- 				   TREE_REAL_CST (op1));
-     }
    else
      return NULL_TREE;

--- 10491,10496 ----


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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