I have queued the following patch for stage1 which improves the
ability to utilize the match-and-simplify combiner during SSA
propagation (by CCP and VRP).  It makes sure to mark stmts
as not-simulate-again when possible so that the valueization hooks
know when it is safe to combine multiple statements.  I had to
prevent CCP from prematurely deciding that simplifying isn't worth
it as well.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

I have applied the changes to valueize_op_1 and vrp_valueize_1 now,
as requested by Jakub.

Thanks,
Richard.

2015-02-02  Richard Biener  <rguent...@suse.de>

        * tree-ssa-ccp.c (likely_value): See if we have operands that
        are marked as never simulate again and return CONSTANT in this
        case.
        (valueize_op_1): Always allow valueizing default-defs.
        * tree-vrp.c (vrp_valueize_1): Likewise.
        * tree-ssa-propagate.c (simulate_stmt): Mark stmts that do
        not have any operands that will be simulated again as
        not being simulated again.

        * gcc.dg/tree-ssa/ssa-ccp-35.c: New testcase.
        * gcc.dg/tree-ssa/pr37508.c: Adjust.
        * gfortran.dg/reassoc_6.f: Remove XFAIL.

Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c.orig     2015-01-30 13:20:25.794134935 +0100
--- gcc/tree-ssa-ccp.c  2015-02-02 15:48:47.810028364 +0100
*************** static ccp_lattice_t
*** 645,650 ****
--- 645,651 ----
  likely_value (gimple stmt)
  {
    bool has_constant_operand, has_undefined_operand, all_undefined_operands;
+   bool has_nsa_operand;
    tree use;
    ssa_op_iter iter;
    unsigned i;
*************** likely_value (gimple stmt)
*** 667,672 ****
--- 668,674 ----
    has_constant_operand = false;
    has_undefined_operand = false;
    all_undefined_operands = true;
+   has_nsa_operand = false;
    FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
      {
        ccp_prop_value_t *val = get_value (use);
*************** likely_value (gimple stmt)
*** 678,683 ****
--- 680,689 ----
  
        if (val->lattice_val == CONSTANT)
        has_constant_operand = true;
+ 
+       if (SSA_NAME_IS_DEFAULT_DEF (use)
+         || !prop_simulate_again_p (SSA_NAME_DEF_STMT (use)))
+       has_nsa_operand = true;
      }
  
    /* There may be constants in regular rhs operands.  For calls we
*************** likely_value (gimple stmt)
*** 750,757 ****
  
    /* We do not consider virtual operands here -- load from read-only
       memory may have only VARYING virtual operands, but still be
!      constant.  */
    if (has_constant_operand
        || gimple_references_memory_p (stmt))
      return CONSTANT;
  
--- 756,765 ----
  
    /* We do not consider virtual operands here -- load from read-only
       memory may have only VARYING virtual operands, but still be
!      constant.  Also we can combine the stmt with definitions from
!      operands whose definitions are not simulated again.  */
    if (has_constant_operand
+       || has_nsa_operand
        || gimple_references_memory_p (stmt))
      return CONSTANT;
  
*************** valueize_op_1 (tree op)
*** 1145,1151 ****
           this SSA edge as the SSA propagator does not necessarily
         re-visit the use.  */
        gimple def_stmt = SSA_NAME_DEF_STMT (op);
!       if (prop_simulate_again_p (def_stmt))
        return NULL_TREE;
        tree tem = get_constant_value (op);
        if (tem)
--- 1153,1160 ----
           this SSA edge as the SSA propagator does not necessarily
         re-visit the use.  */
        gimple def_stmt = SSA_NAME_DEF_STMT (op);
!       if (!gimple_nop_p (def_stmt)
!         && prop_simulate_again_p (def_stmt))
        return NULL_TREE;
        tree tem = get_constant_value (op);
        if (tem)
Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c.orig 2015-01-30 13:20:25.816135225 +0100
--- gcc/tree-vrp.c      2015-02-02 15:48:47.825028438 +0100
*************** vrp_valueize_1 (tree name)
*** 7096,7102 ****
           this SSA edge as the SSA propagator does not necessarily
         re-visit the use.  */
        gimple def_stmt = SSA_NAME_DEF_STMT (name);
!       if (prop_simulate_again_p (def_stmt))
        return NULL_TREE;
        value_range_t *vr = get_value_range (name);
        if (range_int_cst_singleton_p (vr))
--- 7096,7103 ----
           this SSA edge as the SSA propagator does not necessarily
         re-visit the use.  */
        gimple def_stmt = SSA_NAME_DEF_STMT (name);
!       if (!gimple_nop_p (def_stmt)
!         && prop_simulate_again_p (def_stmt))
        return NULL_TREE;
        value_range_t *vr = get_value_range (name);
        if (range_int_cst_singleton_p (vr))
Index: gcc/tree-ssa-propagate.c
===================================================================
*** gcc/tree-ssa-propagate.c.orig       2015-01-30 13:20:25.817135239 +0100
--- gcc/tree-ssa-propagate.c    2015-02-02 15:48:47.825028438 +0100
*************** simulate_stmt (gimple stmt)
*** 364,369 ****
--- 364,370 ----
          FOR_EACH_EDGE (e, ei, bb->succs)
            add_control_edge (e);
        }
+       return;
      }
    else if (val == SSA_PROP_INTERESTING)
      {
*************** simulate_stmt (gimple stmt)
*** 377,382 ****
--- 378,422 ----
        if (taken_edge)
        add_control_edge (taken_edge);
      }
+ 
+   /* If there are no SSA uses on the stmt whose defs are simulated
+      again then this stmt will be never visited again.  */
+   bool has_simulate_again_uses = false;
+   use_operand_p use_p;
+   ssa_op_iter iter;
+   if (gimple_code  (stmt) == GIMPLE_PHI)
+     {
+       edge_iterator ei;
+       edge e;
+       tree arg;
+       FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds)
+       if (!(e->flags & EDGE_EXECUTABLE)
+           || ((arg = PHI_ARG_DEF_FROM_EDGE (stmt, e))
+               && TREE_CODE (arg) == SSA_NAME
+               && !SSA_NAME_IS_DEFAULT_DEF (arg)
+               && prop_simulate_again_p (SSA_NAME_DEF_STMT (arg))))
+         {
+           has_simulate_again_uses = true;
+           break;
+         }
+     }
+   else
+     FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+       {
+       gimple def_stmt = SSA_NAME_DEF_STMT (USE_FROM_PTR (use_p));
+       if (!gimple_nop_p (def_stmt)
+           && prop_simulate_again_p (def_stmt))
+         {
+           has_simulate_again_uses = true;
+           break;
+         }
+       }
+   if (!has_simulate_again_uses)
+     {
+       if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "marking stmt to be not simulated again\n");
+       prop_set_simulate_again (stmt, false);
+     }
  }
  
  /* Process an SSA edge worklist.  WORKLIST is the SSA edge worklist to
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-35.c
===================================================================
*** /dev/null   1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-35.c  2015-02-02 15:48:47.840028513 
+0100
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-ccp1" } */
+ 
+ int foo (int i, int j)
+ {
+   int x = 1;
+   int y = i + x;
+   int z = y - i;
+   if (z == 1)
+     return 1;
+   return 2;
+ }
+ 
+ /* { dg-final { scan-tree-dump "return 1;" "ccp1" } } */
+ /* { dg-final { cleanup-tree-dump "ccp1" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/pr37508.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/pr37508.c.orig        2012-06-29 
15:52:56.055720744 +0200
--- gcc/testsuite/gcc.dg/tree-ssa/pr37508.c     2015-02-02 15:51:32.621918788 
+0100
*************** int test2 (struct foo2 *x)
*** 21,27 ****
  {
    if (x->i == 0)
      return 1;
!   else if (x->i == -1)
      return 1;
    return 0;
  }
--- 21,27 ----
  {
    if (x->i == 0)
      return 1;
!   else if (x->i == -1) /* This test is already folded to false by ccp1.  */
      return 1;
    return 0;
  }
*************** int test4 (struct foo2 *x)
*** 44,48 ****
    return 0;
  }
  
! /* { dg-final { scan-tree-dump-times "Folding" 3 "vrp1" } } */
  /* { dg-final { cleanup-tree-dump "vrp1" } } */
--- 44,48 ----
    return 0;
  }
  
! /* { dg-final { scan-tree-dump-times "Folding" 2 "vrp1" } } */
  /* { dg-final { cleanup-tree-dump "vrp1" } } */
Index: gcc/testsuite/gfortran.dg/reassoc_6.f
===================================================================
*** gcc/testsuite/gfortran.dg/reassoc_6.f.orig  2010-08-12 12:38:56.000000000 
+0200
--- gcc/testsuite/gfortran.dg/reassoc_6.f       2015-02-02 15:54:45.217118028 
+0100
***************
*** 16,22 ****
          return
          end
  ! Verify that offset of the first element is simplified
! ! While we understand to combine x + ~x IVOPTs now messes things
! ! up by hiding that operation in casts to unsigned.
! ! { dg-final { scan-tree-dump-not "~" "optimized" { xfail *-*-* } } }
  ! { dg-final { cleanup-tree-dump "optimized" } }
--- 16,20 ----
          return
          end
  ! Verify that offset of the first element is simplified
! ! { dg-final { scan-tree-dump-not "~" "optimized" } }
  ! { dg-final { cleanup-tree-dump "optimized" } }

Reply via email to