This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix PR31096


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.
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" } } */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]