Fix part of PR87913

Message ID alpine.LSU.2.20.1811071622550.1827@zhemvz.fhfr.qr
State New
Headers show
Series
  • Fix part of PR87913
Related show

Commit Message

Richard Biener Nov. 7, 2018, 3:26 p.m.
The following fixes MIN/MAX recognition for comparisons that
we turned into equality compares (for tests like unsigned < 1).

It turns out we don't do a very good job in expanding them,
nevertheless this GIMPLE level fix is good and we get slight
improvements in code generation.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

From 0b801cf0ed81d8bd0945e68196efc7d1fc676562 Mon Sep 17 00:00:00 2001
From: Richard Guenther <rguenther@suse.de>
Date: Wed, 7 Nov 2018 16:20:54 +0100
Subject: [PATCH] fix-pr87913

	PR tree-optimization/87913
	* tree-ssa-phiopt.c (minmax_replacement): Turn EQ/NE compares
	of extreme values to ordered comparisons.

	* gcc.dg/tree-ssa/phi-opt-20.c: New testcase.

Patch

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-20.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-20.c
new file mode 100644
index 00000000000..c310308e3a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-20.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt1" } */
+
+unsigned int f(unsigned int num)
+{
+  return num < 1 ? 1 : num;
+}
+
+unsigned int g(unsigned int num)
+{
+  return num > (unsigned)__INT_MAX__ * 2 ? (unsigned)__INT_MAX__ * 2 : num;
+}
+
+int h(int num)
+{
+  return num < -__INT_MAX__ ? -__INT_MAX__ : num;
+}
+
+int i(int num)
+{
+  return num > __INT_MAX__-1 ? __INT_MAX__-1 : num;
+}
+
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "phiopt1" } } */
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 07845101b86..64039e2484e 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -1204,7 +1204,7 @@  minmax_replacement (basic_block cond_bb, basic_block middle_bb,
 		    edge e0, edge e1, gimple *phi,
 		    tree arg0, tree arg1)
 {
-  tree result, type;
+  tree result, type, rhs;
   gcond *cond;
   gassign *new_stmt;
   edge true_edge, false_edge;
@@ -1220,6 +1220,25 @@  minmax_replacement (basic_block cond_bb, basic_block middle_bb,
 
   cond = as_a <gcond *> (last_stmt (cond_bb));
   cmp = gimple_cond_code (cond);
+  rhs = gimple_cond_rhs (cond);
+
+  /* Turn EQ/NE of extreme values to order comparisons.  */
+  if ((cmp == NE_EXPR || cmp == EQ_EXPR)
+      && TREE_CODE (rhs) == INTEGER_CST)
+    {
+      if (wi::eq_p (wi::to_wide (rhs), wi::min_value (TREE_TYPE (rhs))))
+	{
+	  cmp = (cmp == EQ_EXPR) ? LT_EXPR : GE_EXPR;
+	  rhs = wide_int_to_tree (TREE_TYPE (rhs),
+				  wi::min_value (TREE_TYPE (rhs)) + 1);
+	}
+      else if (wi::eq_p (wi::to_wide (rhs), wi::max_value (TREE_TYPE (rhs))))
+	{
+	  cmp = (cmp == EQ_EXPR) ? GT_EXPR : LE_EXPR;
+	  rhs = wide_int_to_tree (TREE_TYPE (rhs),
+				  wi::max_value (TREE_TYPE (rhs)) - 1);
+	}
+    }
 
   /* This transformation is only valid for order comparisons.  Record which
      operand is smaller/larger if the result of the comparison is true.  */
@@ -1228,7 +1247,7 @@  minmax_replacement (basic_block cond_bb, basic_block middle_bb,
   if (cmp == LT_EXPR || cmp == LE_EXPR)
     {
       smaller = gimple_cond_lhs (cond);
-      larger = gimple_cond_rhs (cond);
+      larger = rhs;
       /* If we have smaller < CST it is equivalent to smaller <= CST-1.
 	 Likewise smaller <= CST is equivalent to smaller < CST+1.  */
       if (TREE_CODE (larger) == INTEGER_CST)
@@ -1255,7 +1274,7 @@  minmax_replacement (basic_block cond_bb, basic_block middle_bb,
     }
   else if (cmp == GT_EXPR || cmp == GE_EXPR)
     {
-      smaller = gimple_cond_rhs (cond);
+      smaller = rhs;
       larger = gimple_cond_lhs (cond);
       /* If we have larger > CST it is equivalent to larger >= CST+1.
 	 Likewise larger >= CST is equivalent to larger > CST-1.  */