When `b` is known to be non-negative, the sign of both `MIN (a, b)`
and `a | b` depends only on the sign of `a`. Add patterns to match.pd
to optimize `MIN (a, b) cmp 0` and `(a | b) cmp 0` into `a cmp 0`,
where `cmp` is `<` or `>=`. Currently, `(a | b) cmp 0` is optimized
at the RTL level for some targets, but simplifying earlier is
preferable.
PR tree-optimization/126087
gcc/ChangeLog:
* match.pd: Simplify MIN and BIT_IOR compared to 0 when
one operand is non-negative.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/pr126087.c: New test.
Signed-off-by: Neal Patalay <nealpatalay0@gmail.com>
(cmp (bit_ior (convert:utype @0) (convert:utype @1))
{ build_zero_cst (utype); } ))))
+/* Optimize MIN (a, b) >= 0 to a >= 0 if b is non-negative.
+ Optimize MIN (a, b) < 0 to a < 0 if b is non-negative.
+ Optimize (a | b) >= 0 to a >= 0 if b is non-negative.
+ Optimize (a | b) < 0 to a < 0 if b is non-negative. */
+(for op (min bit_ior)
+ (for cmp (ge lt)
+ (simplify
+ (cmp (op:c @0 @1) integer_zerop@2)
+ (if (tree_expr_nonnegative_p (@1))
+ (cmp @0 @2)))))
+
/* Undo fancy ways of writing max/min or other ?: expressions, like
a - ((a - b) & -(a < b)) and a - (a - b) * (a < b) into (a < b) ? b : a.
People normally use ?: and that is what we actually try to optimize. */
--- /dev/null
+/* PR tree-optimization/126087 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+void use();
+
+void f2(int a, unsigned short bb) {
+ int b = bb;
+ int m = a < b ? a : b;
+ if (m >= 0)
+ use();
+}
+
+void f3(int a, unsigned short bb) {
+ int b = bb;
+ int m = a | b;
+ if (m >= 0)
+ use();
+}
+
+void f4(int a, unsigned short bb) {
+ int b = bb;
+ int m = a < b ? a : b;
+ if (m < 0)
+ use();
+}
+
+void f5(int a, unsigned short bb) {
+ int b = bb;
+ int m = a | b;
+ if (m < 0)
+ use();
+}
+
+/* { dg-final { scan-tree-dump-not "MIN_EXPR" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " \\| " "optimized" } } */