This prepares things to share constant folding between passes
(CCP, FRE and VRP).  It simplifies maybe_fold_reference making
sure to first canonicalize MEM_REFs and then call other folders.

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

Richard.

2011-03-16  Richard Guenther  <rguent...@suse.de>

        * gimple-fold.c (maybe_fold_reference): Open-code relevant
        constant folding.  Move MEM_REF canonicalization first.
        Rely on fold_const_aggregate_ref for initializer folding.
        * tree-ssa-ccp.c (ccp_fold): Handle constant vector extracts.

        * gcc.dg/tree-ssa/pr14814.c: Adjust.
        * gcc.dg/tree-ssa/ssa-ccp-19.c: Likewise.

Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c.orig      2011-03-16 10:53:10.000000000 +0100
--- gcc/gimple-fold.c   2011-03-16 11:20:40.000000000 +0100
*************** maybe_fold_reference (tree expr, bool is
*** 560,582 ****
    tree *t = &expr;
    tree result;
  
!   if (!is_lhs
!       && (result = fold_const_aggregate_ref (expr))
!       && is_gimple_min_invariant (result))
!     return result;
  
!   /* ???  We might want to open-code the relevant remaining cases
!      to avoid using the generic fold.  */
!   if (handled_component_p (*t)
!       && CONSTANT_CLASS_P (TREE_OPERAND (*t, 0)))
      {
!       tree tem = fold (*t);
!       if (tem != *t)
!       return tem;
      }
  
!   while (handled_component_p (*t))
!     t = &TREE_OPERAND (*t, 0);
  
    /* Fold back MEM_REFs to reference trees.  */
    if (TREE_CODE (*t) == MEM_REF
--- 560,609 ----
    tree *t = &expr;
    tree result;
  
!   if ((TREE_CODE (expr) == VIEW_CONVERT_EXPR
!        || TREE_CODE (expr) == REALPART_EXPR
!        || TREE_CODE (expr) == IMAGPART_EXPR)
!       && CONSTANT_CLASS_P (TREE_OPERAND (expr, 0)))
!     return fold_unary_loc (EXPR_LOCATION (expr),
!                          TREE_CODE (expr),
!                          TREE_TYPE (expr),
!                          TREE_OPERAND (expr, 0));
!   else if (TREE_CODE (expr) == BIT_FIELD_REF
!          && CONSTANT_CLASS_P (TREE_OPERAND (expr, 0)))
!     return fold_ternary_loc (EXPR_LOCATION (expr),
!                            TREE_CODE (expr),
!                            TREE_TYPE (expr),
!                            TREE_OPERAND (expr, 0),
!                            TREE_OPERAND (expr, 1),
!                            TREE_OPERAND (expr, 2));
! 
!   while (handled_component_p (*t))
!     t = &TREE_OPERAND (*t, 0);
  
!   /* Canonicalize MEM_REFs invariant address operand.  Do this first
!      to avoid feeding non-canonical MEM_REFs elsewhere.  */
!   if (TREE_CODE (*t) == MEM_REF
!       && !is_gimple_mem_ref_addr (TREE_OPERAND (*t, 0)))
      {
!       bool volatile_p = TREE_THIS_VOLATILE (*t);
!       tree tem = fold_binary (MEM_REF, TREE_TYPE (*t),
!                             TREE_OPERAND (*t, 0),
!                             TREE_OPERAND (*t, 1));
!       if (tem)
!       {
!         TREE_THIS_VOLATILE (tem) = volatile_p;
!         *t = tem;
!         tem = maybe_fold_reference (expr, is_lhs);
!         if (tem)
!           return tem;
!         return expr;
!       }
      }
  
!   if (!is_lhs
!       && (result = fold_const_aggregate_ref (expr))
!       && is_gimple_min_invariant (result))
!     return result;
  
    /* Fold back MEM_REFs to reference trees.  */
    if (TREE_CODE (*t) == MEM_REF
*************** maybe_fold_reference (tree expr, bool is
*** 593,599 ****
         compatibility.  */
        && types_compatible_p (TREE_TYPE (*t),
                             TREE_TYPE (TREE_OPERAND
!                                         (TREE_OPERAND (*t, 0), 0))))
      {
        tree tem;
        *t = TREE_OPERAND (TREE_OPERAND (*t, 0), 0);
--- 620,626 ----
         compatibility.  */
        && types_compatible_p (TREE_TYPE (*t),
                             TREE_TYPE (TREE_OPERAND
!                                       (TREE_OPERAND (*t, 0), 0))))
      {
        tree tem;
        *t = TREE_OPERAND (TREE_OPERAND (*t, 0), 0);
*************** maybe_fold_reference (tree expr, bool is
*** 602,625 ****
        return tem;
        return expr;
      }
-   /* Canonicalize MEM_REFs invariant address operand.  */
-   else if (TREE_CODE (*t) == MEM_REF
-          && !is_gimple_mem_ref_addr (TREE_OPERAND (*t, 0)))
-     {
-       bool volatile_p = TREE_THIS_VOLATILE (*t);
-       tree tem = fold_binary (MEM_REF, TREE_TYPE (*t),
-                             TREE_OPERAND (*t, 0),
-                             TREE_OPERAND (*t, 1));
-       if (tem)
-       {
-         TREE_THIS_VOLATILE (tem) = volatile_p;
-         *t = tem;
-         tem = maybe_fold_reference (expr, is_lhs);
-         if (tem)
-           return tem;
-         return expr;
-       }
-     }
    else if (TREE_CODE (*t) == TARGET_MEM_REF)
      {
        tree tem = maybe_fold_tmr (*t);
--- 629,634 ----
*************** maybe_fold_reference (tree expr, bool is
*** 629,648 ****
          tem = maybe_fold_reference (expr, is_lhs);
          if (tem)
            return tem;
-         return expr;
-       }
-     }
-   else if (!is_lhs
-          && DECL_P (*t))
-     {
-       tree tem = get_symbol_constant_value (*t);
-       if (tem
-         && useless_type_conversion_p (TREE_TYPE (*t), TREE_TYPE (tem)))
-       {
-         *t = unshare_expr (tem);
-         tem = maybe_fold_reference (expr, is_lhs);
-         if (tem)
-           return tem;
          return expr;
        }
      }
--- 638,643 ----
Index: gcc/testsuite/gcc.dg/tree-ssa/pr14814.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/pr14814.c.orig        2011-03-16 
10:53:21.000000000 +0100
--- gcc/testsuite/gcc.dg/tree-ssa/pr14814.c     2011-03-16 11:04:42.000000000 
+0100
*************** int foo(const struct XX* r) {
*** 18,22 ****
    return 1;
  }
  
! /* { dg-final { scan-tree-dump-times "&" 0 "forwprop2" } } */
  /* { dg-final { cleanup-tree-dump "forwprop2" } } */
--- 18,22 ----
    return 1;
  }
  
! /* { dg-final { scan-tree-dump-times "= &" 0 "forwprop2" } } */
  /* { dg-final { cleanup-tree-dump "forwprop2" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-19.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-19.c.orig     2011-03-16 
10:53:21.000000000 +0100
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-19.c  2011-03-16 11:02:47.000000000 
+0100
*************** int g()
*** 12,16 ****
    return *i;  /* This should be turned into a.i */
  }
  
! /* { dg-final { scan-tree-dump "= a.i;" "ccp1" } } */
  /* { dg-final { cleanup-tree-dump "ccp1" } } */
--- 12,16 ----
    return *i;  /* This should be turned into a.i */
  }
  
! /* { dg-final { scan-tree-dump "= MEM\\\[\\\(int \\\*\\\)&a\\\];" "ccp1" } } 
*/
  /* { dg-final { cleanup-tree-dump "ccp1" } } */
Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c.orig     2011-03-16 10:53:21.000000000 +0100
--- gcc/tree-ssa-ccp.c  2011-03-16 10:56:36.000000000 +0100
*************** ccp_fold (gimple stmt)
*** 1182,1187 ****
--- 1182,1198 ----
                                               TREE_CODE (rhs),
                                               TREE_TYPE (rhs), val);
                    }
+                 else if (TREE_CODE (rhs) == BIT_FIELD_REF
+                          && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
+                   {
+                     tree val = get_constant_value (TREE_OPERAND (rhs, 0));
+                     if (val)
+                       return fold_ternary_loc (EXPR_LOCATION (rhs),
+                                                TREE_CODE (rhs),
+                                                TREE_TYPE (rhs), val,
+                                                TREE_OPERAND (rhs, 1),
+                                                TREE_OPERAND (rhs, 2));
+                   }
                  else if (TREE_CODE (rhs) == MEM_REF
                           && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
                    {

Reply via email to