Given ~[0,0] = op1 * op2, range-ops should determine that neither op1 nor
op2 is zero. Add this to the operator_mult for op1_range. op2_range
simply invokes op1_range, so both will be covered.
PR tree-optimzation/110992.c
PR tree-optimzation/119471.c
gcc/
* range-op.cc (operator_mult::op1_range): If the LHS does not
contain zero, return non-zero.
gcc/testsuite/
* gcc.dg/pr110992.c: New.
* gcc.dg/pr119471.c: New.
wide_int offset;
if (op2.singleton_p (offset) && offset != 0)
return range_op_handler (TRUNC_DIV_EXPR).fold_range (r, type, lhs, op2);
+
+ // ~[0, 0] = op1 * op2 defines op1 and op2 as non-zero.
+ if (!lhs.contains_p (wi::zero (TYPE_PRECISION (lhs.type ()))))
+ {
+ r.set_nonzero (type);
+ return true;
+ }
return false;
}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void foo (int);
+
+int f(unsigned b, short c)
+{
+ int bt = b;
+ int bt1 = bt;
+ int t = bt1 & -(c!=0);
+ // int t = bt1 * (c!=0);
+
+ if (!t) return 0;
+ foo(bt == 0);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "foo \\(0\\)" 1 "evrp" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+int fa(int a, int b)
+{
+ int c = a * b;
+ if (c != 0)
+ return (a != 0);
+ return 0;
+}
+int fb(int a, int b)
+{
+ int c = a * b;
+ if (c != 0)
+ return (b != 0);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "PHI <1" 2 "evrp" } } */