re PR middle-end/58742 (pointer arithmetic simplification)
authorRichard Biener <rguenther@suse.de>
Tue, 28 Jan 2014 14:53:52 +0000 (14:53 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 28 Jan 2014 14:53:52 +0000 (14:53 +0000)
2014-01-28  Richard Biener  <rguenther@suse.de>

PR tree-optimization/58742
* tree-ssa-forwprop.c (associate_plusminus): Handle
pointer subtraction of the form (T)(P + A) - (T)P.

From-SVN: r207194

gcc/ChangeLog
gcc/tree-ssa-forwprop.c

index 364cc8a..0dc6d60 100644 (file)
@@ -1,3 +1,9 @@
+2014-01-28  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/58742
+       * tree-ssa-forwprop.c (associate_plusminus): Handle
+       pointer subtraction of the form (T)(P + A) - (T)P.
+
 2014-01-28  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * config/arm/arm.c (arm_new_rtx_costs): Remove useless statement
index ce9e426..6389811 100644 (file)
@@ -2543,6 +2543,7 @@ associate_plusminus (gimple_stmt_iterator *gsi)
        CST +- (CST +- A)  ->  CST +- A
        CST +- (A +- CST)  ->  CST +- A
        A + ~A             ->  -1
+       (T)(P + A) - (T)P  -> (T)A
 
      via commutating the addition and contracting operations to zero
      by reassociation.  */
@@ -2646,6 +2647,55 @@ associate_plusminus (gimple_stmt_iterator *gsi)
                  gimple_set_modified (stmt, true);
                }
            }
+         else if (CONVERT_EXPR_CODE_P (def_code) && code == MINUS_EXPR
+                  && TREE_CODE (rhs2) == SSA_NAME)
+           {
+             /* (T)(ptr + adj) - (T)ptr -> (T)adj.  */
+             gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs2);
+             if (TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
+                 && is_gimple_assign (def_stmt2)
+                 && can_propagate_from (def_stmt2)
+                 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
+                 && TREE_CODE (gimple_assign_rhs1 (def_stmt2)) == SSA_NAME)
+               {
+                 /* Now we have (T)A - (T)ptr.  */
+                 tree ptr = gimple_assign_rhs1 (def_stmt2);
+                 def_stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
+                 if (is_gimple_assign (def_stmt2)
+                     && gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR
+                     && gimple_assign_rhs1 (def_stmt2) == ptr)
+                   {
+                     /* And finally (T)(ptr + X) - (T)ptr.  */
+                     tree adj = gimple_assign_rhs2 (def_stmt2);
+                     /* If the conversion of the pointer adjustment to the
+                        final type requires a sign- or zero-extension we
+                        have to punt - it is not defined which one is
+                        correct.  */
+                     if (TYPE_PRECISION (TREE_TYPE (rhs1))
+                         <= TYPE_PRECISION (TREE_TYPE (adj))
+                         || (TREE_CODE (adj) == INTEGER_CST
+                             && tree_int_cst_sign_bit (adj) == 0))
+                       {
+                         if (useless_type_conversion_p (TREE_TYPE (rhs1),
+                                                        TREE_TYPE (adj)))
+                           {
+                             code = TREE_CODE (adj);
+                             rhs1 = adj;
+                           }
+                         else
+                           {
+                             code = NOP_EXPR;
+                             rhs1 = adj;
+                           }
+                         rhs2 = NULL_TREE;
+                         gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
+                                                         NULL_TREE);
+                         gcc_assert (gsi_stmt (*gsi) == stmt);
+                         gimple_set_modified (stmt, true);
+                       }
+                   }
+               }
+           }
        }
     }