This fixes PR53168 - and removes some of the more odd code in
phi-translation (I've added a testcase to make sure the intended
PREs still happen).  There is still some issues in phi translation
I believe, but those are for later.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2012-05-04  Richard Guenther  <rguent...@suse.de>

        PR tree-optimization/53168
        * tree-ssa-pre.c (phi_translate_1): Only handle type-punned
        memory reads when the result is a constant we can pun.

        * gcc.dg/torture/pr53168.c: New testcase.
        * gcc.dg/tree-ssa/ssa-pre-30.c: Likewise.

Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c  (revision 187148)
--- gcc/tree-ssa-pre.c  (working copy)
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1659,1665 ****
          {
            unsigned int new_val_id;
            pre_expr constant;
-           bool converted = false;
  
            tree result = vn_reference_lookup_pieces (newvuse, ref->set,
                                                      ref->type,
--- 1659,1664 ----
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1668,1679 ****
            if (result)
              VEC_free (vn_reference_op_s, heap, newoperands);
  
!           if (result
!               && !useless_type_conversion_p (ref->type, TREE_TYPE (result)))
              {
!               result = fold_build1 (VIEW_CONVERT_EXPR, ref->type, result);
!               converted = true;
              }
            else if (!result && newref
                     && !useless_type_conversion_p (ref->type, newref->type))
              {
--- 1667,1695 ----
            if (result)
              VEC_free (vn_reference_op_s, heap, newoperands);
  
!           /* We can always insert constants, so if we have a partial
!              redundant constant load of another type try to translate it
!              to a constant of appropriate type.  */
!           if (result && is_gimple_min_invariant (result))
              {
!               tree tem = result;
!               if (!useless_type_conversion_p (ref->type, TREE_TYPE (result)))
!                 {
!                   tem = fold_unary (VIEW_CONVERT_EXPR, ref->type, result);
!                   if (tem && !is_gimple_min_invariant (tem))
!                     tem = NULL_TREE;
!                 }
!               if (tem)
!                 return get_or_alloc_expr_for_constant (tem);
              }
+ 
+           /* If we'd have to convert things we would need to validate
+              if we can insert the translated expression.  So fail
+              here for now - we cannot insert an alias with a different
+              type in the VN tables either, as that would assert.  */
+           if (result
+               && !useless_type_conversion_p (ref->type, TREE_TYPE (result)))
+             return NULL;
            else if (!result && newref
                     && !useless_type_conversion_p (ref->type, newref->type))
              {
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1681,1741 ****
                return NULL;
              }
  
-           if (result && is_gimple_min_invariant (result))
-             {
-               gcc_assert (!newoperands);
-               return get_or_alloc_expr_for_constant (result);
-             }
- 
            expr = (pre_expr) pool_alloc (pre_expr_pool);
            expr->kind = REFERENCE;
            expr->id = 0;
  
!           if (converted)
!             {
!               vn_nary_op_t nary;
!               tree nresult;
! 
!               gcc_assert (CONVERT_EXPR_P (result)
!                           || TREE_CODE (result) == VIEW_CONVERT_EXPR);
! 
!               nresult = vn_nary_op_lookup_pieces (1, TREE_CODE (result),
!                                                   TREE_TYPE (result),
!                                                   &TREE_OPERAND (result, 0),
!                                                   &nary);
!               if (nresult && is_gimple_min_invariant (nresult))
!                 return get_or_alloc_expr_for_constant (nresult);
! 
!               expr->kind = NARY;
!               if (nary)
!                 {
!                   PRE_EXPR_NARY (expr) = nary;
!                   constant = fully_constant_expression (expr);
!                   if (constant != expr)
!                     return constant;
! 
!                   new_val_id = nary->value_id;
!                   get_or_alloc_expression_id (expr);
!                 }
!               else
!                 {
!                   new_val_id = get_next_value_id ();
!                   VEC_safe_grow_cleared (bitmap_set_t, heap,
!                                          value_expressions,
!                                          get_max_value_id() + 1);
!                   nary = vn_nary_op_insert_pieces (1, TREE_CODE (result),
!                                                    TREE_TYPE (result),
!                                                    &TREE_OPERAND (result, 0),
!                                                    NULL_TREE,
!                                                    new_val_id);
!                   PRE_EXPR_NARY (expr) = nary;
!                   constant = fully_constant_expression (expr);
!                   if (constant != expr)
!                     return constant;
!                   get_or_alloc_expression_id (expr);
!                 }
!             }
!           else if (newref)
              {
                PRE_EXPR_REFERENCE (expr) = newref;
                constant = fully_constant_expression (expr);
--- 1697,1707 ----
                return NULL;
              }
  
            expr = (pre_expr) pool_alloc (pre_expr_pool);
            expr->kind = REFERENCE;
            expr->id = 0;
  
!           if (newref)
              {
                PRE_EXPR_REFERENCE (expr) = newref;
                constant = fully_constant_expression (expr);
Index: gcc/testsuite/gcc.dg/torture/pr53168.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr53168.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr53168.c      (revision 0)
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do compile } */
+ 
+ int a, b, c;
+ unsigned *d;
+ int e[1];
+ void fn1 ();
+ int fn2 ();
+ int
+ fn3 ()
+ {
+   int *f = &a;
+   if (fn2 ())
+     {
+       for (; c; c++)
+       {
+         e[a] && (b = 0);
+         fn1 ();
+         if (e[a])
+           return 0;
+       }
+       for (; c <= 0; c++)
+       for (;;)
+         ;
+     }
+   else
+     e[0] = 0 != (d = f);
+   return *d;
+ }
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c  (revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c  (revision 0)
***************
*** 0 ****
--- 1,27 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-pre-details" } */
+ 
+ int f;
+ int g;
+ unsigned int
+ foo (int b, int x)
+ {
+   if (b)
+     x = *(int *)&f;
+   g = x;
+   return *(unsigned int*)&f;
+ }
+ float
+ bar (int b, int x)
+ {
+   if (b)
+     x = *(int *)&f;
+   g = x;
+   return *(float *)&f;
+ }
+ 
+ /* We should see the partial redundant loads of f even though they
+    are using different types (of the same size).  */
+ 
+ /* { dg-final { scan-tree-dump-times "Replaced MEM" 2 "pre" } } */
+ /* { dg-final { cleanup-tree-dump "pre" } } */

Reply via email to