This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR51042


This fixes PR51042.

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

Richard.

2011-11-10  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/51042
	* tree-ssa-pre.c (phi_translate_1): Avoid recursing on
	self-referential expressions.  Refactor code to avoid duplication.

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

Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c	(revision 181252)
--- gcc/tree-ssa-pre.c	(working copy)
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1527,1533 ****
  	tree newvuse = vuse;
  	VEC (vn_reference_op_s, heap) *newoperands = NULL;
  	bool changed = false, same_valid = true;
! 	unsigned int i, j;
  	vn_reference_op_t operand;
  	vn_reference_t newref;
  
--- 1527,1533 ----
  	tree newvuse = vuse;
  	VEC (vn_reference_op_s, heap) *newoperands = NULL;
  	bool changed = false, same_valid = true;
! 	unsigned int i, j, n;
  	vn_reference_op_t operand;
  	vn_reference_t newref;
  
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1536,1635 ****
  	  {
  	    pre_expr opresult;
  	    pre_expr leader;
! 	    tree oldop0 = operand->op0;
! 	    tree oldop1 = operand->op1;
! 	    tree oldop2 = operand->op2;
! 	    tree op0 = oldop0;
! 	    tree op1 = oldop1;
! 	    tree op2 = oldop2;
  	    tree type = operand->type;
  	    vn_reference_op_s newop = *operand;
! 
! 	    if (op0 && TREE_CODE (op0) == SSA_NAME)
  	      {
! 		unsigned int op_val_id = VN_INFO (op0)->value_id;
! 		leader = find_leader_in_sets (op_val_id, set1, set2);
! 		opresult = phi_translate (leader, set1, set2, pred, phiblock);
! 		if (opresult && opresult != leader)
  		  {
! 		    tree name = get_representative_for (opresult);
! 		    if (!name)
  		      break;
! 		    op0 = name;
  		  }
! 		else if (!opresult)
! 		  break;
! 	      }
! 	    changed |= op0 != oldop0;
! 
! 	    if (op1 && TREE_CODE (op1) == SSA_NAME)
! 	      {
! 		unsigned int op_val_id = VN_INFO (op1)->value_id;
  		leader = find_leader_in_sets (op_val_id, set1, set2);
! 		opresult = phi_translate (leader, set1, set2, pred, phiblock);
! 		if (opresult && opresult != leader)
  		  {
! 		    tree name = get_representative_for (opresult);
! 		    if (!name)
  		      break;
! 		    op1 = name;
  		  }
- 		else if (!opresult)
- 		  break;
  	      }
! 	    /* We can't possibly insert these.  */
! 	    else if (op1 && !is_gimple_min_invariant (op1))
! 	      break;
! 	    changed |= op1 != oldop1;
! 	    if (op2 && TREE_CODE (op2) == SSA_NAME)
  	      {
! 		unsigned int op_val_id = VN_INFO (op2)->value_id;
! 		leader = find_leader_in_sets (op_val_id, set1, set2);
! 		opresult = phi_translate (leader, set1, set2, pred, phiblock);
! 		if (opresult && opresult != leader)
! 		  {
! 		    tree name = get_representative_for (opresult);
! 		    if (!name)
! 		      break;
! 		    op2 = name;
! 		  }
! 		else if (!opresult)
! 		  break;
  	      }
- 	    /* We can't possibly insert these.  */
- 	    else if (op2 && !is_gimple_min_invariant (op2))
- 	      break;
- 	    changed |= op2 != oldop2;
- 
  	    if (!newoperands)
  	      newoperands = VEC_copy (vn_reference_op_s, heap, operands);
  	    /* We may have changed from an SSA_NAME to a constant */
! 	    if (newop.opcode == SSA_NAME && TREE_CODE (op0) != SSA_NAME)
! 	      newop.opcode = TREE_CODE (op0);
  	    newop.type = type;
! 	    newop.op0 = op0;
! 	    newop.op1 = op1;
! 	    newop.op2 = op2;
  	    /* If it transforms a non-constant ARRAY_REF into a constant
  	       one, adjust the constant offset.  */
  	    if (newop.opcode == ARRAY_REF
  		&& newop.off == -1
! 		&& TREE_CODE (op0) == INTEGER_CST
! 		&& TREE_CODE (op1) == INTEGER_CST
! 		&& TREE_CODE (op2) == INTEGER_CST)
  	      {
! 		double_int off = tree_to_double_int (op0);
  		off = double_int_add (off,
  				      double_int_neg
! 				        (tree_to_double_int (op1)));
! 		off = double_int_mul (off, tree_to_double_int (op2));
  		if (double_int_fits_in_shwi_p (off))
  		  newop.off = off.low;
  	      }
  	    VEC_replace (vn_reference_op_s, newoperands, j, &newop);
  	    /* If it transforms from an SSA_NAME to an address, fold with
  	       a preceding indirect reference.  */
! 	    if (j > 0 && op0 && TREE_CODE (op0) == ADDR_EXPR
  		&& VEC_index (vn_reference_op_s,
  			      newoperands, j - 1)->opcode == MEM_REF)
  	      vn_reference_fold_indirect (&newoperands, &j);
--- 1536,1618 ----
  	  {
  	    pre_expr opresult;
  	    pre_expr leader;
! 	    tree op[3];
  	    tree type = operand->type;
  	    vn_reference_op_s newop = *operand;
! 	    op[0] = operand->op0;
! 	    op[1] = operand->op1;
! 	    op[2] = operand->op2;
! 	    for (n = 0; n < 3; ++n)
  	      {
! 		unsigned int op_val_id;
! 		if (!op[n])
! 		  continue;
! 		if (TREE_CODE (op[n]) != SSA_NAME)
  		  {
! 		    /* We can't possibly insert these.  */
! 		    if (n != 0
! 			&& !is_gimple_min_invariant (op[n]))
  		      break;
! 		    continue;
  		  }
! 		op_val_id = VN_INFO (op[n])->value_id;
  		leader = find_leader_in_sets (op_val_id, set1, set2);
! 		if (!leader)
! 		  break;
! 		/* Make sure we do not recursively translate ourselves
! 		   like for translating a[n_1] with the leader for
! 		   n_1 being a[n_1].  */
! 		if (get_expression_id (leader) != get_expression_id (expr))
  		  {
! 		    opresult = phi_translate (leader, set1, set2,
! 					      pred, phiblock);
! 		    if (!opresult)
  		      break;
! 		    if (opresult != leader)
! 		      {
! 			tree name = get_representative_for (opresult);
! 			if (!name)
! 			  break;
! 			changed |= name != op[n];
! 			op[n] = name;
! 		      }
  		  }
  	      }
! 	    if (n != 3)
  	      {
! 		if (newoperands)
! 		  VEC_free (vn_reference_op_s, heap, newoperands);
! 		return NULL;
  	      }
  	    if (!newoperands)
  	      newoperands = VEC_copy (vn_reference_op_s, heap, operands);
  	    /* We may have changed from an SSA_NAME to a constant */
! 	    if (newop.opcode == SSA_NAME && TREE_CODE (op[0]) != SSA_NAME)
! 	      newop.opcode = TREE_CODE (op[0]);
  	    newop.type = type;
! 	    newop.op0 = op[0];
! 	    newop.op1 = op[1];
! 	    newop.op2 = op[2];
  	    /* If it transforms a non-constant ARRAY_REF into a constant
  	       one, adjust the constant offset.  */
  	    if (newop.opcode == ARRAY_REF
  		&& newop.off == -1
! 		&& TREE_CODE (op[0]) == INTEGER_CST
! 		&& TREE_CODE (op[1]) == INTEGER_CST
! 		&& TREE_CODE (op[2]) == INTEGER_CST)
  	      {
! 		double_int off = tree_to_double_int (op[0]);
  		off = double_int_add (off,
  				      double_int_neg
! 				        (tree_to_double_int (op[1])));
! 		off = double_int_mul (off, tree_to_double_int (op[2]));
  		if (double_int_fits_in_shwi_p (off))
  		  newop.off = off.low;
  	      }
  	    VEC_replace (vn_reference_op_s, newoperands, j, &newop);
  	    /* If it transforms from an SSA_NAME to an address, fold with
  	       a preceding indirect reference.  */
! 	    if (j > 0 && op[0] && TREE_CODE (op[0]) == ADDR_EXPR
  		&& VEC_index (vn_reference_op_s,
  			      newoperands, j - 1)->opcode == MEM_REF)
  	      vn_reference_fold_indirect (&newoperands, &j);
Index: gcc/testsuite/gcc.dg/torture/pr51042.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr51042.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr51042.c	(revision 0)
***************
*** 0 ****
--- 1,22 ----
+ /* { dg-do compile } */
+ 
+ int a, b;
+ 
+ void
+ foo (int x)
+ {
+   int e[2];
+   int d;
+   while (x)
+     {
+       for (d = 0; d <= 1; d = 1)
+ 	if (e[a])
+ 	  break;
+       for (b = 0; b <= 0; b = 1)
+ 	{
+ 	  e[a] = a;
+ 	  if (a)
+ 	    break;
+ 	}
+     }
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]