[PATCH] Fix PR58742

Richard Biener rguenther@suse.de
Tue Jan 28 14:50:00 GMT 2014


This implements simple pattern matching for folding of
pointer subtraction GIMPLE IL which is performed in an
integer type.  It handles the simple case, like the
others in associate_plusminus (cases involving cancellation).

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

Richard.

2014-01-28  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/58742
	* tree-ssa-forwprop.c (associate_plusminus): Handle
	pointer subtraction of the form (T)(P + A) - (T)P.

Index: gcc/tree-ssa-forwprop.c
===================================================================
*** gcc/tree-ssa-forwprop.c	(revision 207180)
--- gcc/tree-ssa-forwprop.c	(working copy)
*************** associate_plusminus (gimple_stmt_iterato
*** 2543,2548 ****
--- 2543,2549 ----
  	CST +- (CST +- A)  ->  CST +- A
  	CST +- (A +- CST)  ->  CST +- A
  	A + ~A             ->  -1
+ 	(T)(P + A) - (T)P  -> (T)A
  
       via commutating the addition and contracting operations to zero
       by reassociation.  */
*************** associate_plusminus (gimple_stmt_iterato
*** 2646,2651 ****
--- 2647,2701 ----
  		  gimple_set_modified (stmt, true);
  		}
  	    }
+ 	  else if (CONVERT_EXPR_CODE_P (def_code) && code == MINUS_EXPR
+ 		   && TREE_CODE (rhs2) == SSA_NAME)
+ 	    {
+ 	      /* (T)(ptr + adj) - (T)ptr -> (T)adj.  */
+ 	      gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs2);
+ 	      if (TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
+ 		  && is_gimple_assign (def_stmt2)
+ 		  && can_propagate_from (def_stmt2)
+ 		  && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
+ 		  && TREE_CODE (gimple_assign_rhs1 (def_stmt2)) == SSA_NAME)
+ 		{
+ 		  /* Now we have (T)A - (T)ptr.  */
+ 		  tree ptr = gimple_assign_rhs1 (def_stmt2);
+ 		  def_stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
+ 		  if (is_gimple_assign (def_stmt2)
+ 		      && gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR
+ 		      && gimple_assign_rhs1 (def_stmt2) == ptr)
+ 		    {
+ 		      /* And finally (T)(ptr + X) - (T)ptr.  */
+ 		      tree adj = gimple_assign_rhs2 (def_stmt2);
+ 		      /* If the conversion of the pointer adjustment to the
+ 		         final type requires a sign- or zero-extension we
+ 			 have to punt - it is not defined which one is
+ 			 correct.  */
+ 		      if (TYPE_PRECISION (TREE_TYPE (rhs1))
+ 			  <= TYPE_PRECISION (TREE_TYPE (adj))
+ 			  || (TREE_CODE (adj) == INTEGER_CST
+ 			      && tree_int_cst_sign_bit (adj) == 0))
+ 			{
+ 			  if (useless_type_conversion_p (TREE_TYPE (rhs1),
+ 							 TREE_TYPE (adj)))
+ 			    {
+ 			      code = TREE_CODE (adj);
+ 			      rhs1 = adj;
+ 			    }
+ 			  else
+ 			    {
+ 			      code = NOP_EXPR;
+ 			      rhs1 = adj;
+ 			    }
+ 			  rhs2 = NULL_TREE;
+ 			  gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
+ 							  NULL_TREE);
+ 			  gcc_assert (gsi_stmt (*gsi) == stmt);
+ 			  gimple_set_modified (stmt, true);
+ 			}
+ 		    }
+ 		}
+ 	    }
  	}
      }
  



More information about the Gcc-patches mailing list