[gcc r16-4103] Fix integer overflow in profile_count::probability_in

Jan Hubicka hubicka@gcc.gnu.org
Fri Sep 26 10:39:53 GMT 2025


https://gcc.gnu.org/g:9f9c8d63a5822378e18f3f8f188df21c6104e18e

commit r16-4103-g9f9c8d63a5822378e18f3f8f188df21c6104e18e
Author: Jan Hubicka <hubicka@ucw.cz>
Date:   Fri Sep 26 12:39:07 2025 +0200

    Fix integer overflow in profile_count::probability_in
    
    This patch fixes integer overflow in profile_count::probability_in which happens
    for very large counts.  This was probably not that common in practice until
    scaled AutoFDO profiles were intorduces.
    
    This was introduced as cut&paste from profile_probability implementation.
    I reviewed multiplicaitons in the file for safety and noticed that in some
    cases the code is over-protective. In profile_probability::operator/ we alrady
    scale that m_val <= other.m_val and thus we know result will be in the range
    0...max_probability.  In profile_probability::apply_scale we deal with 30bit
    value from profile_probability so no overflow can happen.
    
    gcc/ChangeLog:
    
            * profile-count.h (profile_probability::operator/): Do not cap
            twice.
            (profile_probability::operator/=): Likewise.
            (profile_probability::apply_scale): Do not watch for overflow.
            (profile_count::probability_in): Watch overflow.

Diff:
---
 gcc/profile-count.h | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/gcc/profile-count.h b/gcc/profile-count.h
index 65c4596a2b0f..89746c6749fd 100644
--- a/gcc/profile-count.h
+++ b/gcc/profile-count.h
@@ -450,9 +450,7 @@ public:
       else
 	{
 	  gcc_checking_assert (other.m_val);
-	  ret.m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
-				 other.m_val),
-			   max_probability);
+	  ret.m_val = RDIV ((uint64_t)m_val * max_probability, other.m_val);
 	}
       ret.set_quality (MIN (MIN (quality (), other.quality ()), ADJUSTED));
       return ret;
@@ -480,9 +478,7 @@ public:
 	  else
 	    {
 	      gcc_checking_assert (other.m_val);
-	      m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
-				 other.m_val),
-			   max_probability);
+	      m_val = RDIV ((uint64_t)m_val * max_probability, other.m_val);
 	    }
 	  set_quality (MIN (MIN (quality (), other.quality ()), ADJUSTED));
 	}
@@ -576,9 +572,8 @@ public:
       gcc_checking_assert (den.m_val);
 
       profile_probability ret;
-      uint64_t val;
-      safe_scale_64bit (m_val, num.m_val, den.m_val, &val);
-      ret.m_val = MIN (val, max_probability);
+      ret.m_val = MIN (RDIV ((uint64_t)m_val * num.m_val, den.m_val),
+		       max_probability);
       ret.set_quality (MIN (MIN (MIN (quality (), ADJUSTED),
 			    num.quality ()), den.quality ()));
       return ret;
@@ -1331,8 +1326,14 @@ public:
 	  return ret;
 	}
       else
-	ret.m_val = RDIV (m_val * profile_probability::max_probability,
-			  overall.m_val);
+	{
+	  gcc_checking_assert (overall.m_val);
+	  uint64_t tmp;
+	  safe_scale_64bit (m_val, profile_probability::max_probability,
+			    overall.m_val, &tmp);
+	  gcc_checking_assert (tmp <= profile_probability::max_probability);
+	  ret.m_val = tmp;
+	}
       ret.set_quality (MIN (MAX (MIN (m_quality, overall.m_quality),
 				 GUESSED), ADJUSTED));
       return ret;


More information about the Gcc-cvs mailing list