diff mbox series

[COMMITTED] Normalize irange_bitmask before union/intersect.

Message ID 20230717071603.242424-1-aldyh@redhat.com
State New
Headers show
Series [COMMITTED] Normalize irange_bitmask before union/intersect. | expand

Commit Message

Aldy Hernandez July 17, 2023, 7:16 a.m. UTC
The bit twiddling in union/intersect for the value/mask pair must be
normalized to have the unknown bits with a value of 0 in order to make
the math simpler.  Normalizing at construction slowed VRP by 1.5% so I
opted to normalize before updating the bitmask in range-ops, since it
was the only user.  However, with upcoming changes there will be
multiple setters of the mask (IPA and CCP), so we need something more
general.

I played with various alternatives, and settled on normalizing before
union/intersect which were the ones needing the bits cleared.  With
this patch, there's no noticeable difference in performance either in
VRP or in overall compilation.

gcc/ChangeLog:

	* value-range.cc (irange_bitmask::verify_mask): Mask need not be
	normalized.
	* value-range.h (irange_bitmask::union_): Normalize beforehand.
	(irange_bitmask::intersect): Same.
---
 gcc/value-range.cc |  3 ---
 gcc/value-range.h  | 12 ++++++++++--
 2 files changed, 10 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 011bdbdeae6..2abf57bcee8 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1953,9 +1953,6 @@  void
 irange_bitmask::verify_mask () const
 {
   gcc_assert (m_value.get_precision () == m_mask.get_precision ());
-  // Unknown bits must have their corresponding value bits cleared as
-  // it simplifies union and intersect.
-  gcc_assert (wi::bit_and (m_mask, m_value) == 0);
 }
 
 void
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 0170188201b..d8af6fca7d7 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -211,8 +211,12 @@  irange_bitmask::operator== (const irange_bitmask &src) const
 }
 
 inline bool
-irange_bitmask::union_ (const irange_bitmask &src)
+irange_bitmask::union_ (const irange_bitmask &orig_src)
 {
+  // Normalize mask.
+  irange_bitmask src (orig_src.m_value & ~orig_src.m_mask, orig_src.m_mask);
+  m_value &= ~m_mask;
+
   irange_bitmask save (*this);
   m_mask = (m_mask | src.m_mask) | (m_value ^ src.m_value);
   m_value = m_value & src.m_value;
@@ -222,8 +226,12 @@  irange_bitmask::union_ (const irange_bitmask &src)
 }
 
 inline bool
-irange_bitmask::intersect (const irange_bitmask &src)
+irange_bitmask::intersect (const irange_bitmask &orig_src)
 {
+  // Normalize mask.
+  irange_bitmask src (orig_src.m_value & ~orig_src.m_mask, orig_src.m_mask);
+  m_value &= ~m_mask;
+
   irange_bitmask save (*this);
   // If we have two known bits that are incompatible, the resulting
   // bit is undefined.  It is unclear whether we should set the entire