rewrite undefined overflow to defined in ifcombine

Message ID 20220505094459.912A313A65@imap2.suse-dmz.suse.de
State Committed
Commit c2a0d2e6f636c6ad7da44256b6bea7470d895100
Headers
Series rewrite undefined overflow to defined in ifcombine |

Commit Message

Richard Biener May 5, 2022, 9:44 a.m. UTC
  When we make stmts to execute unconditionally in ifcombine we have
to make sure to rewrite stmts that can invoke undefined behavior
on overflow into a form with defined overflow.  That's possible
for all but signed division for which we have to avoid the transform.

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

This was developed as not working solution to fix PR105142 and
I do not have a testcase that experiences wrong-code (but I only
tried for about 10 minutes to construct one).  Still the problem
is obviously latent and we should fix it.

Thus - OK for trunk?

Thanks,
Richard.

2022-04-04  Richard Biener  <rguenther@suse.de>

	* tree-ssa-ifcombine.cc (bb_no_side_effects_p): Avoid executing
	divisions with undefined overflow unconditionally.
	(pass_tree_ifcombine::execute): Rewrite stmts with undefined
	overflow to defined.
---
 gcc/tree-ssa-ifcombine.cc | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
  

Comments

Jakub Jelinek May 5, 2022, 9:46 a.m. UTC | #1
On Thu, May 05, 2022 at 11:44:59AM +0200, Richard Biener wrote:
> When we make stmts to execute unconditionally in ifcombine we have
> to make sure to rewrite stmts that can invoke undefined behavior
> on overflow into a form with defined overflow.  That's possible
> for all but signed division for which we have to avoid the transform.
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu.
> 
> This was developed as not working solution to fix PR105142 and
> I do not have a testcase that experiences wrong-code (but I only
> tried for about 10 minutes to construct one).  Still the problem
> is obviously latent and we should fix it.
> 
> Thus - OK for trunk?
> 
> Thanks,
> Richard.
> 
> 2022-04-04  Richard Biener  <rguenther@suse.de>
> 
> 	* tree-ssa-ifcombine.cc (bb_no_side_effects_p): Avoid executing
> 	divisions with undefined overflow unconditionally.
> 	(pass_tree_ifcombine::execute): Rewrite stmts with undefined
> 	overflow to defined.

LGTM.

	Jakub
  

Patch

diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
index 3a4ab694b71..cb86cc1ea5f 100644
--- a/gcc/tree-ssa-ifcombine.cc
+++ b/gcc/tree-ssa-ifcombine.cc
@@ -125,10 +125,26 @@  bb_no_side_effects_p (basic_block bb)
       if (is_gimple_debug (stmt))
 	continue;
 
+      gassign *ass;
+      enum tree_code rhs_code;
       if (gimple_has_side_effects (stmt)
 	  || gimple_uses_undefined_value_p (stmt)
 	  || gimple_could_trap_p (stmt)
 	  || gimple_vuse (stmt)
+	  /* We need to rewrite stmts with undefined overflow to use
+	     unsigned arithmetic but cannot do so for signed division.  */
+	  || ((ass = dyn_cast <gassign *> (stmt))
+	      && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (ass)))
+	      && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (gimple_assign_lhs (ass)))
+	      && ((rhs_code = gimple_assign_rhs_code (ass)), true)
+	      && (rhs_code == TRUNC_DIV_EXPR
+		  || rhs_code == CEIL_DIV_EXPR
+		  || rhs_code == FLOOR_DIV_EXPR
+		  || rhs_code == ROUND_DIV_EXPR)
+	      /* We cannot use expr_not_equal_to since we'd have to restrict
+		 flow-sensitive info to whats known at the outer if.  */
+	      && (TREE_CODE (gimple_assign_rhs2 (ass)) != INTEGER_CST
+		  || !integer_minus_onep (gimple_assign_rhs2 (ass))))
 	  /* const calls don't match any of the above, yet they could
 	     still have some side-effects - they could contain
 	     gimple_could_trap_p statements, like floating point
@@ -847,6 +863,19 @@  pass_tree_ifcombine::execute (function *fun)
 	    /* Clear range info from all stmts in BB which is now executed
 	       conditional on a always true/false condition.  */
 	    reset_flow_sensitive_info_in_bb (bb);
+	    for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+		 gsi_next (&gsi))
+	      {
+		gassign *ass = dyn_cast <gassign *> (gsi_stmt (gsi));
+		if (!ass)
+		  continue;
+		tree lhs = gimple_assign_lhs (ass);
+		if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+		     || POINTER_TYPE_P (TREE_TYPE (lhs)))
+		    && arith_code_with_undefined_signed_overflow
+			 (gimple_assign_rhs_code (ass)))
+		  rewrite_to_defined_overflow (ass, true);
+	      }
 	    cfg_changed |= true;
 	  }
     }