diff mbox

Fix PR31096

Message ID CO2PR07MB26943863309FC90F3CB2161983BB0@CO2PR07MB2694.namprd07.prod.outlook.com
State New
Headers show

Commit Message

Hurugalawadi, Naveen Nov. 11, 2016, 10:19 a.m. UTC
Hi,

Sorry for a very late reply as the mail was missed or overlooked.

>> could now move the test  tree_expr_nonzero_p next to 

>> tree_expr_nonnegative_p (it is redundant for  the last case). 


Done.

>> Often just a comment can really help here. 


Comments updated as per the suggestion

>> when C is zero and verify this transformation doesn't fire on that case.


Updated test to check with zero.

>> verifying that the operand orders change appropriately when dealing 

>> with a negative constant.


Done.

>> verify nothing happens with floating point or vector types.


Done.

Please review the patch and let me know if any modifications are required.
Regression tested on X86 and AArch64.

Thanks,
Naveen

2016-11-11  Naveen H.S  <Naveen.Hurugalawadi@caviumnetworks.com>
gcc
	* fold-const.c (tree_expr_nonzero_p) : Make non-static.
	* fold-const.h (tree_expr_nonzero_p) : Declare.
	* match.pd (cmp (mult:c @0 @1) (mult:c @2 @1) : New Pattern.
	* match.pd (cmp (mult:c @0 @1) (mult:c @2 @1) : New Pattern.
gcc/testsuite
	* gcc.dg/pr31096.c: New testcase.
	* gcc.dg/pr31096-1.c: New testcase.

Comments

Richard Biener Nov. 23, 2016, 9:56 a.m. UTC | #1
On Fri, Nov 11, 2016 at 11:19 AM, Hurugalawadi, Naveen
<Naveen.Hurugalawadi@cavium.com> wrote:
> Hi,

>

> Sorry for a very late reply as the mail was missed or overlooked.

>

>>> could now move the test  tree_expr_nonzero_p next to

>>> tree_expr_nonnegative_p (it is redundant for  the last case).

>

> Done.

>

>>> Often just a comment can really help here.

>

> Comments updated as per the suggestion

>

>>> when C is zero and verify this transformation doesn't fire on that case.

>

> Updated test to check with zero.

>

>>> verifying that the operand orders change appropriately when dealing

>>> with a negative constant.

>

> Done.

>

>>> verify nothing happens with floating point or vector types.

>

> Done.

>

> Please review the patch and let me know if any modifications are required.

> Regression tested on X86 and AArch64.


Ok with using wi::neg_p (@1, TYPE_SIGN (TREE_TYPE (@1))) instead of wi::lt_p.

Thanks,
Richard.

> Thanks,

> Naveen

>

> 2016-11-11  Naveen H.S  <Naveen.Hurugalawadi@caviumnetworks.com>

> gcc

>         * fold-const.c (tree_expr_nonzero_p) : Make non-static.

>         * fold-const.h (tree_expr_nonzero_p) : Declare.

>         * match.pd (cmp (mult:c @0 @1) (mult:c @2 @1) : New Pattern.

>         * match.pd (cmp (mult:c @0 @1) (mult:c @2 @1) : New Pattern.

> gcc/testsuite

>         * gcc.dg/pr31096.c: New testcase.

>         * gcc.dg/pr31096-1.c: New testcase.
diff mbox

Patch

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e14471e..8f13807 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -9015,7 +9015,7 @@  tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
 /* Return true when T is an address and is known to be nonzero.
    Handle warnings about undefined signed overflow.  */
 
-static bool
+bool
 tree_expr_nonzero_p (tree t)
 {
   bool ret, strict_overflow_p;
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 46dcd28..fbe1328 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -169,6 +169,7 @@  extern tree size_diffop_loc (location_t, tree, tree);
 #define non_lvalue(T) non_lvalue_loc (UNKNOWN_LOCATION, T)
 extern tree non_lvalue_loc (location_t, tree);
 
+extern bool tree_expr_nonzero_p (tree);
 extern bool tree_expr_nonnegative_p (tree);
 extern bool tree_expr_nonnegative_warnv_p (tree, bool *, int = 0);
 extern tree make_range (tree, int *, tree *, tree *, bool *);
diff --git a/gcc/match.pd b/gcc/match.pd
index 29ddcd8..eecfe23 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -31,6 +31,7 @@  along with GCC; see the file COPYING3.  If not see
    zerop
    CONSTANT_CLASS_P
    tree_expr_nonnegative_p
+   tree_expr_nonzero_p
    integer_valued_real_p
    integer_pow2p
    HONOR_NANS)
@@ -1017,7 +1018,31 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       && tree_nop_conversion_p (type, TREE_TYPE (@1)))
   (convert (bit_and (bit_not @1) @0))))
 
+/* For integral types with undefined overflow and C != 0 fold
+   x * C EQ/NE y * C into x EQ/NE y.  */
+(for cmp (eq ne)
+ (simplify
+  (cmp (mult:c @0 @1) (mult:c @2 @1))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+       && tree_expr_nonzero_p (@1))
+   (cmp @0 @2))))
+
+/* For integral types with undefined overflow and C != 0 fold
+   x * C RELOP y * C into:
 
+   x RELOP y for nonnegative C
+   y RELOP x for negative C  */
+(for cmp (lt gt le ge)
+ (simplify
+  (cmp (mult:c @0 @1) (mult:c @2 @1))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+   (if (tree_expr_nonnegative_p (@1) && tree_expr_nonzero_p (@1))
+    (cmp @0 @2)
+   (if (TREE_CODE (@1) == INTEGER_CST
+	&& wi::lt_p (@1, 0, TYPE_SIGN (TREE_TYPE (@1))))
+    (cmp @2 @0))))))
 
 /* ((X inner_op C0) outer_op C1)
    With X being a tree where value_range has reasoned certain bits to always be
diff --git a/gcc/testsuite/gcc.dg/pr31096-1.c b/gcc/testsuite/gcc.dg/pr31096-1.c
new file mode 100644
index 0000000..e681f0f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr31096-1.c
@@ -0,0 +1,51 @@ 
+/* PR middle-end/31096 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+#define zero(name, op) \
+int name (int a, int b) \
+{ return a * 0 op b * 0; }
+
+zero(zeq, ==) zero(zne, !=) zero(zlt, <)
+zero(zgt, >)  zero(zge, >=) zero(zle, <=)
+
+#define unsign_pos(name, op) \
+int name (unsigned a, unsigned b) \
+{ return a * 4 op b * 4; }
+
+unsign_pos(upeq, ==) unsign_pos(upne, !=) unsign_pos(uplt, <)
+unsign_pos(upgt, >)  unsign_pos(upge, >=) unsign_pos(uple, <=)
+
+#define unsign_neg(name, op) \
+int name (unsigned a, unsigned b) \
+{ return a * -2 op b * -2; }
+
+unsign_neg(uneq, ==) unsign_neg(unne, !=) unsign_neg(unlt, <)
+unsign_neg(ungt, >)  unsign_neg(unge, >=) unsign_neg(unle, <=)
+
+#define float(name, op) \
+int name (float a, float b) \
+{ return a * 5 op b * 5; }
+
+float(feq, ==) float(fne, !=) float(flt, <)
+float(fgt, >)  float(fge, >=) float(fle, <=)
+
+#define float_val(name, op) \
+int name (int a, int b) \
+{ return a * 54.0 op b * 54.0; }
+
+float_val(fveq, ==) float_val(fvne, !=) float_val(fvlt, <)
+float_val(fvgt, >)  float_val(fvge, >=) float_val(fvle, <=)
+
+#define vec(name, op) \
+int name (int a, int b) \
+{ int c[10]; return a * c[1] op b * c[1]; }
+
+vec(veq, ==) vec(vne, !=) vec(vlt, <)
+vec(vgt, >)  vec(vge, >=) vec(vle, <=)
+
+/* { dg-final { scan-tree-dump-times "\\(D\\) \\* 4" 24 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\\(D\\) \\* 4294967294" 12 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\\(D\\) \\* 5\\.0e\\+0" 12 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\\* 5\\.4e\\+1" 12 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\\(D\\) \\* c\\\$1_8\\(D\\)" 12 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr31096.c b/gcc/testsuite/gcc.dg/pr31096.c
new file mode 100644
index 0000000..32c979e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr31096.c
@@ -0,0 +1,36 @@ 
+/* PR middle-end/31096 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+#define signval_pos(name, op) \
+int name (int a, int b) \
+{ return a * 4 op b * 4; }
+
+signval_pos(peq, ==) signval_pos(pne, !=) signval_pos(plt, <)
+signval_pos(pgt, >)  signval_pos(pge, >=) signval_pos(ple, <=)
+
+#define signval_neg(name, op) \
+int name (int a, int b) \
+{ return a * -23 op b * -23; }
+
+signval_neg(neq, ==) signval_neg(nne, !=) signval_neg(nlt, <)
+signval_neg(ngt, >)  signval_neg(nge, >=) signval_neg(nle, <=)
+
+#define vec_pos(name, op) \
+int name (int a[10], int b[10]) \
+{ return a[3] * 4 op b[8] * 4; }
+
+vec_pos(vpeq, ==) vec_pos(vpne, !=) vec_pos(vplt, <)
+vec_pos(vpgt, >)  vec_pos(vpge, >=) vec_pos(vple, <=)
+
+#define vec_neg(name, op) \
+int name (int a[10], int b[10]) \
+{ return a[3] * -23 op b[8] * -23; }
+
+vec_neg(vneq, ==) vec_neg(vnne, !=) vec_neg(vnlt, <)
+vec_neg(vngt, >)  vec_neg(vnge, >=) vec_neg(vnle, <=)
+
+/* { dg-final { scan-tree-dump-not "\\(D\\) \\* 4" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "\\(D\\) \\* -23" "optimized" } } */
+/* { dg-final { scan-tree-dump-times "_1 = b_2\\(D\\)" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "_1 = MEM\\\[\\(int \\*\\)b" 4 "optimized" } } */