[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