r.set_varying (type);
}
+// Call wi_fold when both op1 and op2 are equivalent. Further split small
+// subranges into constants. This can provide better precision.
+// For x + y, when x == y with a range of [0,4] instead of [0, 8] produce
+// [0,0][2, 2][4,4][6, 6][8, 8]
+// LIMIT is the maximum number of elements in range allowed before we
+// do not processs them individually.
+
+void
+range_operator::wi_fold_in_parts_equiv (irange &r, tree type,
+ const wide_int &lh_lb,
+ const wide_int &lh_ub,
+ unsigned limit) const
+{
+ int_range_max tmp;
+ widest_int lh_range = wi::sub (widest_int::from (lh_ub, TYPE_SIGN (type)),
+ widest_int::from (lh_lb, TYPE_SIGN (type)));
+ // if there are 1 to 8 values in the LH range, split them up.
+ r.set_undefined ();
+ if (lh_range >= 0 && lh_range < limit)
+ {
+ for (unsigned x = 0; x <= lh_range; x++)
+ {
+ wide_int val = lh_lb + x;
+ wi_fold (tmp, type, val, val, val, val);
+ r.union_ (tmp);
+ }
+ }
+ // Otherwise just call wi_fold.
+ else
+ wi_fold (r, type, lh_lb, lh_ub, lh_lb, lh_ub);
+}
+
// Call wi_fold, except further split small subranges into constants.
// This can provide better precision. For something 8 >> [0,1]
// Instead of [8, 16], we will produce [8,8][16,16]
unsigned num_lh = lh.num_pairs ();
unsigned num_rh = rh.num_pairs ();
+ // If op1 and op2 are equivalences, then we don't need a complete cross
+ // product, just pairs of matching elements.
+ if (relation_equiv_p (rel) && lh == rh)
+ {
+ int_range_max tmp;
+ r.set_undefined ();
+ for (unsigned x = 0; x < num_lh; ++x)
+ {
+ // If the number of subranges is too high, limit subrange creation.
+ unsigned limit = (r.num_pairs () > 32) ? 0 : 8;
+ wide_int lh_lb = lh.lower_bound (x);
+ wide_int lh_ub = lh.upper_bound (x);
+ wi_fold_in_parts_equiv (tmp, type, lh_lb, lh_ub, limit);
+ r.union_ (tmp);
+ if (r.varying_p ())
+ break;
+ }
+ op1_op2_relation_effect (r, type, lh, rh, rel);
+ update_known_bitmask (r, m_code, lh, rh);
+ return true;
+ }
+
// If both ranges are single pairs, fold directly into the result range.
// If the number of subranges grows too high, produce a summary result as the
// loop becomes exponential with little benefit. See PR 103821.
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* PR test case. */
+int b = 10;
+int c;
+char e;
+void foo();
+static char(a)(char f, char g) { return f && g == 1 ? 0 : f % g; }
+short(d)(short f, short g) { return f * g; }
+int main() {
+ short h;
+ int i;
+ unsigned j;
+ h = d(b && c, 5);
+ j = h;
+ i = a(h, 237);
+ unsigned k = i;
+ e = i < 0 || k >= 32 ? 0 : i >> k;
+ if (e) {
+ c = 0;
+ foo();
+ }
+}
+
+
+/* Also Check that small ranges are broken down and optimized properly
+ This function should never call foo (). */
+
+int otherfunc (int x, int z) {
+ if (x < 1 || x > 6 )
+ return 0;
+
+ if (x == z)
+ {
+ if (x >> z > 0)
+ foo ();
+ if (x * z > 26 && x * z < 35)
+ foo ();
+ if (x + z == 5)
+ foo ();
+ if ((x + z) % 2 == 1)
+ foo ();
+ if (x / z != 1)
+ foo ();
+
+ }
+ return 0;
+}
+
+
+/* { dg-final { scan-tree-dump-not "foo" "optimized" } } */