The following patch teaches VRP to disregard the intermediate
conversion in a sequence (T1)(T2)val if that sequence is
value-preserving for val.  There are possibly some more
cases that could be handled when a sign-change is involved
but the following is a first safe step.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2011-07-07  Richard Guenther  <rguent...@suse.de>

        * tree-vrp.c (simplify_conversion_using_ranges): New function.
        (simplify_stmt_using_ranges): Call it.

        * gcc.dg/tree-ssa/vrp58.c: New testcase.

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c      (revision 175962)
--- gcc/tree-vrp.c      (working copy)
*************** simplify_switch_using_ranges (gimple stm
*** 7342,7347 ****
--- 7342,7378 ----
    return false;
  }
  
+ /* Simplify an integral conversion from an SSA name in STMT.  */
+ 
+ static bool
+ simplify_conversion_using_ranges (gimple stmt)
+ {
+   tree rhs1 = gimple_assign_rhs1 (stmt);
+   gimple def_stmt = SSA_NAME_DEF_STMT (rhs1);
+   value_range_t *final, *inner;
+ 
+   /* Obtain final and inner value-ranges for a conversion
+      sequence (final-type)(intermediate-type)inner-type.  */
+   final = get_value_range (gimple_assign_lhs (stmt));
+   if (final->type != VR_RANGE)
+     return false;
+   if (!is_gimple_assign (def_stmt)
+       || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
+     return false;
+   rhs1 = gimple_assign_rhs1 (def_stmt);
+   if (TREE_CODE (rhs1) != SSA_NAME)
+     return false;
+   inner = get_value_range (rhs1);
+   if (inner->type != VR_RANGE)
+     return false;
+   if (!tree_int_cst_equal (final->min, inner->min)
+       || !tree_int_cst_equal (final->max, inner->max))
+     return false;
+   gimple_assign_set_rhs1 (stmt, rhs1);
+   update_stmt (stmt);
+   return true;
+ }
+ 
  /* Simplify STMT using ranges if possible.  */
  
  static bool
*************** simplify_stmt_using_ranges (gimple_stmt_
*** 7351,7356 ****
--- 7382,7388 ----
    if (is_gimple_assign (stmt))
      {
        enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
+       tree rhs1 = gimple_assign_rhs1 (stmt);
  
        switch (rhs_code)
        {
*************** simplify_stmt_using_ranges (gimple_stmt_
*** 7364,7370 ****
             or identity if the RHS is zero or one, and the LHS are known
             to be boolean values.  Transform all TRUTH_*_EXPR into
               BIT_*_EXPR if both arguments are known to be boolean values.  */
!         if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
            return simplify_truth_ops_using_ranges (gsi, stmt);
          break;
  
--- 7396,7402 ----
             or identity if the RHS is zero or one, and the LHS are known
             to be boolean values.  Transform all TRUTH_*_EXPR into
               BIT_*_EXPR if both arguments are known to be boolean values.  */
!         if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
            return simplify_truth_ops_using_ranges (gsi, stmt);
          break;
  
*************** simplify_stmt_using_ranges (gimple_stmt_
*** 7373,7387 ****
         than zero and the second operand is an exact power of two.  */
        case TRUNC_DIV_EXPR:
        case TRUNC_MOD_EXPR:
!         if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))
              && integer_pow2p (gimple_assign_rhs2 (stmt)))
            return simplify_div_or_mod_using_ranges (stmt);
          break;
  
        /* Transform ABS (X) into X or -X as appropriate.  */
        case ABS_EXPR:
!         if (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
!             && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
            return simplify_abs_using_ranges (stmt);
          break;
  
--- 7405,7419 ----
         than zero and the second operand is an exact power of two.  */
        case TRUNC_DIV_EXPR:
        case TRUNC_MOD_EXPR:
!         if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
              && integer_pow2p (gimple_assign_rhs2 (stmt)))
            return simplify_div_or_mod_using_ranges (stmt);
          break;
  
        /* Transform ABS (X) into X or -X as appropriate.  */
        case ABS_EXPR:
!         if (TREE_CODE (rhs1) == SSA_NAME
!             && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
            return simplify_abs_using_ranges (stmt);
          break;
  
*************** simplify_stmt_using_ranges (gimple_stmt_
*** 7390,7399 ****
          /* Optimize away BIT_AND_EXPR and BIT_IOR_EXPR
             if all the bits being cleared are already cleared or
             all the bits being set are already set.  */
!         if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
            return simplify_bit_ops_using_ranges (gsi, stmt);
          break;
  
        default:
          break;
        }
--- 7422,7437 ----
          /* Optimize away BIT_AND_EXPR and BIT_IOR_EXPR
             if all the bits being cleared are already cleared or
             all the bits being set are already set.  */
!         if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
            return simplify_bit_ops_using_ranges (gsi, stmt);
          break;
  
+       CASE_CONVERT:
+         if (TREE_CODE (rhs1) == SSA_NAME
+             && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
+           return simplify_conversion_using_ranges (stmt);
+         break;
+ 
        default:
          break;
        }
Index: gcc/testsuite/gcc.dg/tree-ssa/vrp58.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/vrp58.c       (revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/vrp58.c       (revision 0)
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+ 
+ long long
+ foo (long long a, signed char b, signed char c)
+ {
+   int bc = b * c;
+   return a + (short)bc;
+ }
+ 
+ /* { dg-final { scan-tree-dump "Folded into" "vrp1" } } */
+ /* { dg-final { cleanup-tree-dump "vrp1" } } */

Reply via email to