[PATCH] Fix PR67915

Richard Biener rguenther@suse.de
Wed Oct 14 12:55:00 GMT 2015


The following removes GENERIC folding from cleanup_control_expr_graph
in favor of GIMPLE one.  This likely doesn't solve the underlying issue
of PR67915 fully but using const_binop as I originally wanted doesn't
catch all cases fold_binary did because stmts that were previously
folded get non-folded as the cgraph state changes (and thus we
can start simplifying aliases and weaks).

I've adjusted match.pd to handle &"ab" < &"ab"[2] and gimplification
to fold the conditions it builds (the C++ FE leaves us with unfolded
COND_EXPR_CONDs).

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

Richard.

2015-10-14  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/67915
	* match.pd: Handle comparisons of addresses of STRING_CSTs.
	* gimplify.c (gimplify_cond_expr): Fold the GIMPLE conds we build.
	* tree-cfgcleanup.c (cleanup_control_expr_graph): Remove GENERIC
	stmt folding in favor of GIMPLE one.

	* gcc.dg/torture/pr67915.c: New testcase.

Index: gcc/testsuite/gcc.dg/torture/pr67915.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr67915.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr67915.c	(revision 0)
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile } */
+ 
+ int a, b, c, d, e, f, g;
+ 
+ int
+ fn1 (int p1)
+ {
+   return p1;
+ }
+ 
+ void
+ fn2 ()
+ {
+ lbl:
+   g = b;
+   if (fn1 (c && e))
+     {
+       f = a ? 0 : 1 << 1;
+       short h = b;
+       d = h < 0 || f ? 0 : 1;
+     }
+   goto lbl;
+ }
Index: gcc/match.pd
===================================================================
*** gcc/match.pd	(revision 228804)
--- gcc/match.pd	(working copy)
*************** (define_operator_list CEXPI BUILT_IN_CEX
*** 1998,2005 ****
  	   && decl_in_symtab_p (base1))
           equal = symtab_node::get_create (base0)
  	           ->equal_address_to (symtab_node::get_create (base1));
!        else if ((DECL_P (base0) || TREE_CODE (base0) == SSA_NAME)
! 		&& (DECL_P (base1) || TREE_CODE (base1) == SSA_NAME))
           equal = (base0 == base1);
       }
       (if (equal == 1
--- 1998,2009 ----
  	   && decl_in_symtab_p (base1))
           equal = symtab_node::get_create (base0)
  	           ->equal_address_to (symtab_node::get_create (base1));
!        else if ((DECL_P (base0)
! 		 || TREE_CODE (base0) == SSA_NAME
! 		 || TREE_CODE (base0) == STRING_CST)
! 		&& (DECL_P (base1)
! 		    || TREE_CODE (base1) == SSA_NAME
! 		    || TREE_CODE (base1) == STRING_CST))
           equal = (base0 == base1);
       }
       (if (equal == 1
*************** (define_operator_list CEXPI BUILT_IN_CEX
*** 2007,2015 ****
  	      /* If the offsets are equal we can ignore overflow.  */
  	      || off0 == off1
  	      || POINTER_TYPE_OVERFLOW_UNDEFINED
! 	      /* Or if we compare using pointers to decls.  */
  	      || (POINTER_TYPE_P (TREE_TYPE (@2))
! 		  && DECL_P (base0))))
        (switch
         (if (cmp == EQ_EXPR)
  	{ constant_boolean_node (off0 == off1, type); })
--- 2011,2019 ----
  	      /* If the offsets are equal we can ignore overflow.  */
  	      || off0 == off1
  	      || POINTER_TYPE_OVERFLOW_UNDEFINED
! 	      /* Or if we compare using pointers to decls or strings.  */
  	      || (POINTER_TYPE_P (TREE_TYPE (@2))
! 		  && (DECL_P (base0) || TREE_CODE (base0) == STRING_CST))))
        (switch
         (if (cmp == EQ_EXPR)
  	{ constant_boolean_node (off0 == off1, type); })
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c	(revision 228804)
--- gcc/gimplify.c	(working copy)
*************** gimplify_cond_expr (tree *expr_p, gimple
*** 3152,3162 ****
  
    gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
  				 &arm2);
- 
    cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true,
!                                    label_false);
! 
    gimplify_seq_add_stmt (&seq, cond_stmt);
    label_cont = NULL_TREE;
    if (!have_then_clause_p)
      {
--- 3152,3163 ----
  
    gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
  				 &arm2);
    cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true,
! 				 label_false);
    gimplify_seq_add_stmt (&seq, cond_stmt);
+   gimple_stmt_iterator gsi = gsi_last (seq);
+   maybe_fold_stmt (&gsi);
+ 
    label_cont = NULL_TREE;
    if (!have_then_clause_p)
      {
Index: gcc/tree-cfgcleanup.c
===================================================================
*** gcc/tree-cfgcleanup.c	(revision 228804)
--- gcc/tree-cfgcleanup.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 56,61 ****
--- 56,64 ----
  #include "cfgloop.h"
  #include "tree-ssa-propagate.h"
  #include "tree-scalar-evolution.h"
+ #include "gimple-match.h"
+ #include "gimple-fold.h"
+ 
  
  /* The set of blocks in that at least one of the following changes happened:
     -- the statement at the end of the block was changed
*************** cleanup_control_expr_graph (basic_block
*** 96,127 ****
    edge taken_edge;
    bool retval = false;
    gimple *stmt = gsi_stmt (gsi);
-   tree val;
  
    if (!single_succ_p (bb))
      {
        edge e;
        edge_iterator ei;
        bool warned;
!       location_t loc;
  
        fold_defer_overflow_warnings ();
-       loc = gimple_location (stmt);
        switch (gimple_code (stmt))
  	{
  	case GIMPLE_COND:
! 	  val = fold_binary_loc (loc, gimple_cond_code (stmt),
! 				 boolean_type_node,
! 			         gimple_cond_lhs (stmt),
! 				 gimple_cond_rhs (stmt));
! 	  break;
  
  	case GIMPLE_SWITCH:
  	  val = gimple_switch_index (as_a <gswitch *> (stmt));
  	  break;
  
  	default:
! 	  val = NULL_TREE;
  	}
        taken_edge = find_taken_edge (bb, val);
        if (!taken_edge)
--- 99,132 ----
    edge taken_edge;
    bool retval = false;
    gimple *stmt = gsi_stmt (gsi);
  
    if (!single_succ_p (bb))
      {
        edge e;
        edge_iterator ei;
        bool warned;
!       tree val = NULL_TREE;
  
        fold_defer_overflow_warnings ();
        switch (gimple_code (stmt))
  	{
  	case GIMPLE_COND:
! 	  {
! 	    code_helper rcode;
! 	    tree ops[3] = {};
! 	    if (gimple_simplify (stmt, &rcode, ops, NULL, no_follow_ssa_edges,
! 				 no_follow_ssa_edges)
! 		&& rcode == INTEGER_CST)
! 	      val = ops[0];
! 	    break;
! 	  }
  
  	case GIMPLE_SWITCH:
  	  val = gimple_switch_index (as_a <gswitch *> (stmt));
  	  break;
  
  	default:
! 	  ;
  	}
        taken_edge = find_taken_edge (bb, val);
        if (!taken_edge)



More information about the Gcc-patches mailing list