Skip to content

Commit 0c88866

Browse files
committed
Implement value/mask tracking for irange.
Integer ranges (irange) currently track known 0 bits. We've wanted to track known 1 bits for some time, and instead of tracking known 0 and known 1's separately, it has been suggested we track a value/mask pair similarly to what we do for CCP and RTL. This patch implements such a thing. With this we now track a VALUE integer which are the known values, and a MASK which tells us which bits contain meaningful information. This allows us to fix a handful of enhancement requests, such as PR107043 and PR107053. There is a 4.48% performance penalty for VRP and 0.42% in overall compilation for this entire patchset. It is expected and in line with the loss incurred when we started tracking known 0 bits. This patch just provides the value/mask tracking support. All the nonzero users (range-op, IPA, CCP, etc), are still using the nonzero nomenclature. For that matter, this patch reimplements the nonzero accessors with the value/mask functionality. In follow-up patches I will enhance these passes to use the value/mask information, and fix the aforementioned PRs. gcc/ChangeLog: * data-streamer-in.cc (streamer_read_value_range): Adjust for value/mask. * data-streamer-out.cc (streamer_write_vrange): Same. * range-op.cc (operator_cast::fold_range): Same. * value-range-pretty-print.cc (vrange_printer::print_irange_bitmasks): Same. * value-range-storage.cc (irange_storage::write_lengths_address): Same. (irange_storage::set_irange): Same. (irange_storage::get_irange): Same. (irange_storage::size): Same. (irange_storage::dump): Same. * value-range-storage.h: Same. * value-range.cc (debug): New. (irange_bitmask::dump): New. (add_vrange): Adjust for value/mask. (irange::operator=): Same. (irange::set): Same. (irange::verify_range): Same. (irange::operator==): Same. (irange::contains_p): Same. (irange::irange_single_pair_union): Same. (irange::union_): Same. (irange::intersect): Same. (irange::invert): Same. (irange::get_nonzero_bits_from_range): Rename to... (irange::get_bitmask_from_range): ...this. (irange::set_range_from_nonzero_bits): Rename to... (irange::set_range_from_bitmask): ...this. (irange::set_nonzero_bits): Rename to... (irange::update_bitmask): ...this. (irange::get_nonzero_bits): Rename to... (irange::get_bitmask): ...this. (irange::intersect_nonzero_bits): Rename to... (irange::intersect_bitmask): ...this. (irange::union_nonzero_bits): Rename to... (irange::union_bitmask): ...this. (irange_bitmask::verify_mask): New. * value-range.h (class irange_bitmask): New. (irange_bitmask::set_unknown): New. (irange_bitmask::unknown_p): New. (irange_bitmask::irange_bitmask): New. (irange_bitmask::get_precision): New. (irange_bitmask::get_nonzero_bits): New. (irange_bitmask::set_nonzero_bits): New. (irange_bitmask::operator==): New. (irange_bitmask::union_): New. (irange_bitmask::intersect): New. (class irange): Friend vrange_printer. (irange::varying_compatible_p): Adjust for bitmask. (irange::set_varying): Same. (irange::set_nonzero): Same. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/pr107009.c: Adjust irange dumping for value/mask changes. * gcc.dg/tree-ssa/vrp-unreachable.c: Same. * gcc.dg/tree-ssa/vrp122.c: Same.
1 parent a069b86 commit 0c88866

File tree

11 files changed

+351
-122
lines changed

11 files changed

+351
-122
lines changed

gcc/data-streamer-in.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,10 @@ streamer_read_value_range (class lto_input_block *ib, data_in *data_in,
241241
int_range<2> tmp (type, lb, ub);
242242
r.union_ (tmp);
243243
}
244-
wide_int nz = streamer_read_wide_int (ib);
245-
r.set_nonzero_bits (nz);
244+
wide_int value = streamer_read_wide_int (ib);
245+
wide_int mask = streamer_read_wide_int (ib);
246+
irange_bitmask bm (value, mask);
247+
r.update_bitmask (bm);
246248
return;
247249
}
248250
if (is_a <frange> (vr))

gcc/data-streamer-out.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,10 @@ streamer_write_vrange (struct output_block *ob, const vrange &v)
423423
streamer_write_wide_int (ob, r.lower_bound (i));
424424
streamer_write_wide_int (ob, r.upper_bound (i));
425425
}
426-
streamer_write_wide_int (ob, r.get_nonzero_bits ());
426+
// TODO: We could avoid streaming out the value if the mask is -1.
427+
irange_bitmask bm = r.get_bitmask ();
428+
streamer_write_wide_int (ob, bm.value ());
429+
streamer_write_wide_int (ob, bm.mask ());
427430
return;
428431
}
429432
if (is_a <frange> (v))

gcc/range-op.cc

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2876,16 +2876,20 @@ operator_cast::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
28762876
return true;
28772877
}
28782878

2879-
// Update the nonzero mask. Truncating casts are problematic unless
2879+
// Update the bitmask. Truncating casts are problematic unless
28802880
// the conversion fits in the resulting outer type.
2881-
wide_int nz = inner.get_nonzero_bits ();
2881+
irange_bitmask bm = inner.get_bitmask ();
28822882
if (truncating_cast_p (inner, outer)
2883-
&& wi::rshift (nz, wi::uhwi (TYPE_PRECISION (outer.type ()),
2884-
TYPE_PRECISION (inner.type ())),
2883+
&& wi::rshift (bm.mask (),
2884+
wi::uhwi (TYPE_PRECISION (outer.type ()),
2885+
TYPE_PRECISION (inner.type ())),
28852886
TYPE_SIGN (inner.type ())) != 0)
28862887
return true;
2887-
nz = wide_int::from (nz, TYPE_PRECISION (type), TYPE_SIGN (inner.type ()));
2888-
r.set_nonzero_bits (nz);
2888+
unsigned prec = TYPE_PRECISION (type);
2889+
signop sign = TYPE_SIGN (inner.type ());
2890+
bm = irange_bitmask (wide_int::from (bm.value (), prec, sign),
2891+
wide_int::from (bm.mask (), prec, sign));
2892+
r.update_bitmask (bm);
28892893

28902894
return true;
28912895
}

gcc/testsuite/gcc.dg/tree-ssa/pr107009.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ void saxpy(size_t n)
1212
foobar (n);
1313
}
1414

15-
// { dg-final { scan-tree-dump "NONZERO.*fff8" "dom2" } }
15+
// { dg-final { scan-tree-dump "fff8 VALUE 0x0" "dom2" } }

gcc/testsuite/gcc.dg/tree-ssa/vrp-unreachable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ void func (unsigned n, unsigned m)
3939
/* { dg-final { scan-tree-dump-not "dead" "vrp1" } } */
4040
/* { dg-final { scan-tree-dump-times "builtin_unreachable" 1 "vrp1" } } */
4141
/* { dg-final { scan-tree-dump-not "builtin_unreachable" "vrp2" } } */
42-
/* { dg-final { scan-tree-dump-times "fff8" 4 "vrp2" } } */
42+
/* { dg-final { scan-tree-dump-times "fff8 VALUE 0x0" 4 "vrp2" } } */

gcc/testsuite/gcc.dg/tree-ssa/vrp122.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ int f(unsigned t)
1616
return 0;
1717
}
1818

19-
// { dg-final { scan-tree-dump "Global Exported: g_.* NONZERO 0x.*fff0" "evrp" } }
19+
// { dg-final { scan-tree-dump "Global Exported: g_.* MASK 0x1 VALUE 0x0" "evrp" } }

gcc/value-range-pretty-print.cc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,16 @@ vrange_printer::print_irange_bound (const wide_int &bound, tree type) const
9494
void
9595
vrange_printer::print_irange_bitmasks (const irange &r) const
9696
{
97-
wide_int nz = r.get_nonzero_bits ();
98-
if (nz == -1)
97+
irange_bitmask bm = r.m_bitmask;
98+
if (bm.unknown_p ())
9999
return;
100100

101-
pp_string (pp, " NONZERO ");
101+
pp_string (pp, " MASK ");
102102
char buf[WIDE_INT_PRINT_BUFFER_SIZE];
103-
print_hex (nz, buf);
103+
print_hex (bm.mask (), buf);
104+
pp_string (pp, buf);
105+
pp_string (pp, " VALUE ");
106+
print_hex (bm.value (), buf);
104107
pp_string (pp, buf);
105108
}
106109

gcc/value-range-storage.cc

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ vrange_storage::equal_p (const vrange &r) const
232232
unsigned char *
233233
irange_storage::write_lengths_address ()
234234
{
235-
return (unsigned char *)&m_val[(m_num_ranges * 2 + 1)
235+
return (unsigned char *)&m_val[(m_num_ranges * 2 + 2)
236236
* WIDE_INT_MAX_HWIS (m_precision)];
237237
}
238238

@@ -301,7 +301,11 @@ irange_storage::set_irange (const irange &r)
301301
write_wide_int (val, len, r.lower_bound (i));
302302
write_wide_int (val, len, r.upper_bound (i));
303303
}
304-
write_wide_int (val, len, r.m_nonzero_mask);
304+
305+
// TODO: We could avoid streaming out the value if the mask is -1.
306+
irange_bitmask bm = r.m_bitmask;
307+
write_wide_int (val, len, bm.value ());
308+
write_wide_int (val, len, bm.mask ());
305309

306310
if (flag_checking)
307311
{
@@ -367,7 +371,12 @@ irange_storage::get_irange (irange &r, tree type) const
367371
r.union_ (tmp);
368372
}
369373
}
370-
read_wide_int (r.m_nonzero_mask, val, *len, m_precision);
374+
375+
wide_int bits_value, bits_mask;
376+
read_wide_int (bits_value, val, *len, m_precision);
377+
val += *len++;
378+
read_wide_int (bits_mask, val, *len, m_precision);
379+
r.m_bitmask = irange_bitmask (bits_value, bits_mask);
371380
if (r.m_kind == VR_VARYING)
372381
r.m_kind = VR_RANGE;
373382

@@ -399,7 +408,7 @@ irange_storage::size (const irange &r)
399408
return sizeof (irange_storage);
400409

401410
unsigned prec = TYPE_PRECISION (r.type ());
402-
unsigned n = r.num_pairs () * 2 + 1;
411+
unsigned n = r.num_pairs () * 2 + 2;
403412
unsigned hwi_size = ((n * WIDE_INT_MAX_HWIS (prec) - 1)
404413
* sizeof (HOST_WIDE_INT));
405414
unsigned len_size = n;
@@ -428,7 +437,7 @@ irange_storage::dump () const
428437
int i, j;
429438

430439
fprintf (stderr, " lengths = [ ");
431-
for (i = 0; i < m_num_ranges * 2 + 1; ++i)
440+
for (i = 0; i < m_num_ranges * 2 + 2; ++i)
432441
fprintf (stderr, "%d ", len[i]);
433442
fprintf (stderr, "]\n");
434443

@@ -443,8 +452,13 @@ irange_storage::dump () const
443452
*val++);
444453
++len;
445454
}
455+
456+
// Dump value/mask pair.
457+
for (j = 0; j < *len; ++j)
458+
fprintf (stderr, " [VALUE] " HOST_WIDE_INT_PRINT_DEC "\n", *val++);
459+
++len;
446460
for (j = 0; j < *len; ++j)
447-
fprintf (stderr, " [NZ] " HOST_WIDE_INT_PRINT_DEC "\n", *val++);
461+
fprintf (stderr, " [MASK] " HOST_WIDE_INT_PRINT_DEC "\n", *val++);
448462
}
449463

450464
DEBUG_FUNCTION void

gcc/value-range-storage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class irange_storage : public vrange_storage
9191

9292
enum value_range_kind m_kind : 3;
9393

94-
// The length of this is m_num_ranges * 2 + 1 to accomodate the nonzero bits.
94+
// The length of this is m_num_ranges * 2 + 2 to accomodate the bitmask.
9595
HOST_WIDE_INT m_val[1];
9696

9797
// Another variable-length part of the structure following the HWIs.

0 commit comments

Comments
 (0)