]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Normalize irange_bitmask before union/intersect.
authorAldy Hernandez <aldyh@redhat.com>
Fri, 14 Jul 2023 10:16:17 +0000 (12:16 +0200)
committerAldy Hernandez <aldyh@redhat.com>
Mon, 17 Jul 2023 07:17:59 +0000 (09:17 +0200)
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
gcc/value-range.h

index 011bdbdeae62845b5627a8dfa0d261370df7e5db..2abf57bcee8055ec8b297c3d624e54621a7b5eef 100644 (file)
@@ -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
index 0170188201bc9b1c4e117661c9a62819dc1547c5..d8af6fca7d7740051f717490ffc85642c0eaa463 100644 (file)
@@ -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