diff mbox

[PR66726] Factor conversion out of COND_EXPR

Message ID 55B583F6.4080904@linaro.org
State New
Headers show

Commit Message

Kugan Vivekanandarajah July 27, 2015, 1:05 a.m. UTC
On 24/07/15 05:05, Jeff Law wrote:
> On 07/15/2015 11:52 PM, Kugan wrote:
>>
>>>>
>>>> diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
>>>> index 932c83a..3058eb5 100644
>>>> --- a/gcc/tree-ssa-reassoc.c
>>>> +++ b/gcc/tree-ssa-reassoc.c
>>>
>>>>        return false;
>>>>      bb = gimple_bb (stmt);
>>>>      if (!single_succ_p (bb))
>>>> @@ -2729,9 +2743,8 @@ final_range_test_p (gimple stmt)
>>>>
>>>>      lhs = gimple_assign_lhs (stmt);
>>>>      rhs = gimple_assign_rhs1 (stmt);
>>>> -  if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
>>>> -      || TREE_CODE (rhs) != SSA_NAME
>>>> -      || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE)
>>>> +  if (TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE
>>>> +      && TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE)
>>>>        return false;
>>> So you're ensuring that one of the two is a boolean...  Note that
>>> previously we ensured that the rhs was a boolean and the lhs was an
>>> integral type (which I believe is true for booleans).
>>>
>>> Thus if we had
>>> bool x;
>>> int y;
>>>
>>> x = (bool) y;
>>>
>>> The old code would have rejected that case.  But I think it gets through
>>> now, right?
>>>
>>> I think once that issue is addressed, this will be good for the trunk.
>>>
>>
>> Thanks for the review. How about:
>>
>> -  if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
>> -      || TREE_CODE (rhs) != SSA_NAME
>> -      || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE)
>> +  if (gimple_assign_cast_p (stmt)
>> +      && (!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
>> +      || TREE_CODE (rhs) != SSA_NAME
>> +      || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE))
> But then I think you need to verify that for the  _234 = a_2(D) == 2;
> case that type of the RHS is a boolean.
> 
> ie, each case has requirements for the types.  I don't think they can be
> reasonably unified.  So something like this:
> 
> if (gimple_assign_cast_p (stmt)
>     && ! (correct types for cast)
>    return false;
> 
> if (!gimple_assign_cast_p (stmt)
>     && ! (correct types for tcc_comparison case))
>   return false;
> 
> 
> This works because we've already verified that it's either a type
> conversion or a comparison on the RHS.
>
I thought that when !gimple_assign_cast_p (stmt), RHS will always
boolean. I have now added this check in the attached patch.

I also noticed that in maybe_optimize_range_tests, GIMPLE_COND can
have non compatible types when new_op is updated
(boolean types coming from tcc_compare results) and hence need to be
converted. Changed that as well.

Bootstrapped and regression tested on x86-64-none-linux-gnu with no new
regressions. Is this OK for trunk?

Thanks,
Kugan
diff mbox

Patch

diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index efb813c..cc215b6 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -2707,18 +2707,32 @@  optimize_range_tests (enum tree_code opcode,
    # _345 = PHI <_123(N), 1(...), 1(...)>
    where _234 has bool type, _123 has single use and
    bb N has a single successor M.  This is commonly used in
-   the last block of a range test.  */
+   the last block of a range test.
+
+   Also Return true if STMT is tcc_compare like:
+   <bb N>:
+   ...
+   _234 = a_2(D) == 2;
 
+   <bb M>:
+   # _345 = PHI <_234(N), 1(...), 1(...)>
+   _346 = (int) _345;
+   where _234 has booltype, single use and
+   bb N has a single successor M.  This is commonly used in
+   the last block of a range test.  */
 static bool
 final_range_test_p (gimple stmt)
 {
-  basic_block bb, rhs_bb;
+  basic_block bb, rhs_bb, lhs_bb;
   edge e;
   tree lhs, rhs;
   use_operand_p use_p;
   gimple use_stmt;
 
-  if (!gimple_assign_cast_p (stmt))
+  if (!gimple_assign_cast_p (stmt)
+      && (!is_gimple_assign (stmt)
+	  || (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
+	      != tcc_comparison)))
     return false;
   bb = gimple_bb (stmt);
   if (!single_succ_p (bb))
@@ -2729,11 +2743,16 @@  final_range_test_p (gimple stmt)
 
   lhs = gimple_assign_lhs (stmt);
   rhs = gimple_assign_rhs1 (stmt);
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
-      || TREE_CODE (rhs) != SSA_NAME
-      || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE)
+  if (gimple_assign_cast_p (stmt)
+      && (!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+	  || TREE_CODE (rhs) != SSA_NAME
+	  || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE))
     return false;
 
+  if (!gimple_assign_cast_p (stmt)
+      && (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE))
+      return false;
+
   /* Test whether lhs is consumed only by a PHI in the only successor bb.  */
   if (!single_imm_use (lhs, &use_p, &use_stmt))
     return false;
@@ -2743,10 +2762,20 @@  final_range_test_p (gimple stmt)
     return false;
 
   /* And that the rhs is defined in the same loop.  */
-  rhs_bb = gimple_bb (SSA_NAME_DEF_STMT (rhs));
-  if (rhs_bb == NULL
-      || !flow_bb_inside_loop_p (loop_containing_stmt (stmt), rhs_bb))
-    return false;
+  if (gimple_assign_cast_p (stmt))
+    {
+      if (TREE_CODE (rhs) != SSA_NAME
+	  || !(rhs_bb = gimple_bb (SSA_NAME_DEF_STMT (rhs)))
+	  || !flow_bb_inside_loop_p (loop_containing_stmt (stmt), rhs_bb))
+	return false;
+    }
+  else
+    {
+      if (TREE_CODE (lhs) != SSA_NAME
+	  || !(lhs_bb = gimple_bb (SSA_NAME_DEF_STMT (lhs)))
+	  || !flow_bb_inside_loop_p (loop_containing_stmt (stmt), lhs_bb))
+	return false;
+    }
 
   return true;
 }
@@ -3132,6 +3161,8 @@  maybe_optimize_range_tests (gimple stmt)
 
 	  /* stmt is
 	     _123 = (int) _234;
+	     OR
+	     _234 = a_2(D) == 2;
 
 	     followed by:
 	     <bb M>:
@@ -3161,6 +3192,8 @@  maybe_optimize_range_tests (gimple stmt)
 	     of the bitwise or resp. and, recursively.  */
 	  if (!get_ops (rhs, code, &ops,
 			loop_containing_stmt (stmt))
+	      && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
+		  != tcc_comparison)
 	      && has_single_use (rhs))
 	    {
 	      /* Otherwise, push the _234 range test itself.  */
@@ -3173,6 +3206,23 @@  maybe_optimize_range_tests (gimple stmt)
 	      ops.safe_push (oe);
 	      bb_ent.last_idx++;
 	    }
+	  else if (!get_ops (lhs, code, &ops,
+			     loop_containing_stmt (stmt))
+		   && TREE_CODE (lhs) == SSA_NAME
+		   && INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+		   && is_gimple_assign (stmt)
+		   && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
+		       == tcc_comparison)
+		   && has_single_use (lhs))
+	    {
+	      operand_entry_t oe = operand_entry_pool.allocate ();
+	      oe->op = lhs;
+	      oe->rank = code;
+	      oe->id = 0;
+	      oe->count = 1;
+	      ops.safe_push (oe);
+	      bb_ent.last_idx++;
+	    }
 	  else
 	    bb_ent.last_idx = ops.length ();
 	  bb_ent.op = rhs;
@@ -3258,16 +3308,46 @@  maybe_optimize_range_tests (gimple stmt)
 		  gimple use_stmt, cast_stmt = NULL;
 
 		  FOR_EACH_IMM_USE_STMT (use_stmt, iter, bbinfo[idx].op)
-		    if (is_gimple_debug (use_stmt))
+		    if (is_gimple_debug (use_stmt)
+			|| (TREE_CODE (new_op) == SSA_NAME
+			    && !reassoc_stmt_dominates_stmt_p
+			    (SSA_NAME_DEF_STMT (new_op), use_stmt)))
 		      continue;
-		    else if (gimple_code (use_stmt) == GIMPLE_COND
-			     || gimple_code (use_stmt) == GIMPLE_PHI)
-		      FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
-			SET_USE (use_p, new_op);
+		    else if (gimple_code (use_stmt) == GIMPLE_PHI)
+			FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+			  SET_USE (use_p, new_op);
+		    else if (gimple_code (use_stmt) == GIMPLE_COND)
+		      {
+			tree new_type, new_lhs;
+			gassign *g;
+			gcond *cond_stmt = as_a <gcond *> (use_stmt);
+			new_type = TREE_TYPE (gimple_cond_lhs (cond_stmt));
+			if (!types_compatible_p (new_type, TREE_TYPE (new_op)))
+			  {
+			    new_lhs = make_ssa_name (new_type);
+			    if (is_gimple_min_invariant (new_op))
+			      {
+				new_op = fold_convert (new_type, new_op);
+				g = gimple_build_assign (new_lhs, new_op);
+			      }
+			    else
+			      g = gimple_build_assign (new_lhs,
+						       CONVERT_EXPR, new_op);
+			    gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+			    gimple_set_uid (g, gimple_uid (use_stmt));
+			    gimple_set_visited (g, true);
+			    gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+			  }
+			else
+			  new_lhs = new_op;
+			FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+			  SET_USE (use_p, new_lhs);
+		      }
 		    else if (gimple_assign_cast_p (use_stmt))
 		      cast_stmt = use_stmt;
 		    else
-		      gcc_unreachable ();
+		      cast_stmt = NULL;
+
 		  if (cast_stmt)
 		    {
 		      gcc_assert (bb == last_bb);
@@ -3291,7 +3371,8 @@  maybe_optimize_range_tests (gimple stmt)
 			if (is_gimple_debug (use_stmt))
 			  continue;
 			else if (gimple_code (use_stmt) == GIMPLE_COND
-				 || gimple_code (use_stmt) == GIMPLE_PHI)
+				 || gimple_code (use_stmt) == GIMPLE_PHI
+				 || is_gimple_assign (use_stmt))
 			  FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
 			    SET_USE (use_p, new_lhs);
 			else