On trunk I'll eventually do something different.. but it will be more
invasive than I think is reasonable for a backport.
The problem in the PR is that there is a variable with a range and has a
bitmask attached to it. We often defer bitmask processing, the the
change which triggers this problem "improves" the range by applying the
bitmask when we call update_bitmask. (PR 119712)
The case in point is a range of 0, combined with a bitmask that says the
'1' bit must be on. This results in an UNDEFINED range since its
impossible. this is rarely a problem but this particular snippet of
code in IPA is tripping over it because it has checked for undefined,
and then created a new range by combining the [0, 0] and the bitmask,
which we turn into an UNDEFINED.. which it isn't expected. and then
it asks for the type of the range.
As Jakub points out in the PR, this is effectively unreachable code that
is being propagated. A harmless fix would be to check if the result of
applying the bitmask results in an UNDEFINED value and to simply
replace it with a VARYING value.
WE still reduce the testcase to "return 0" and no more failure.
bootstraps on -x86_64-pc-linux-gnu with no regressions.
If this is acceptable, I will push it to trunk, then also test/verify
for the GCC15 and 14(?) branches and check it in there.
Andrew
From bfe4b05074232fbba28f0c189762f46f3b042616 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Fri, 2 May 2025 15:48:08 -0400
Subject: [PATCH 1/5] Allow IPA_CP to handle UNDEFINED as VARYING.
When applying a bitmask to reflect ranges, it is sometimes deferred and
this can result in an UNDEFINED result. IPA is not expecting this, and
add a check for it, and convert to VARYING if encountered.
PR tree-optimization/120048
gcc/
* ipa-cp.cc (ipcp_store_vr_results): Check for UNDEFINED.
gcc/testsuite/
* gcc.dg/pr120048.c: New.
---
gcc/ipa-cp.cc | 10 ++++++++++
gcc/testsuite/gcc.dg/pr120048.c | 12 ++++++++++++
2 files changed, 22 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/pr120048.c
diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index f7e5aa9bfd5..b41148c74de 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -6362,6 +6362,11 @@ ipcp_store_vr_results (void)
TYPE_PRECISION (type),
TYPE_SIGN (type)));
tmp.update_bitmask (bm);
+ // Reflecting the bitmask on the ranges can sometime
+ // produce an UNDEFINED value if the the bitmask update
+ // was previously deferred. See PR 120048.
+ if (tmp.undefined_p ())
+ tmp.set_varying (type);
ipa_vr vr (tmp);
ts->m_vr->quick_push (vr);
}
@@ -6383,6 +6388,11 @@ ipcp_store_vr_results (void)
TYPE_PRECISION (type),
TYPE_SIGN (type)));
tmp.update_bitmask (bm);
+ // Reflecting the bitmask on the ranges can sometime
+ // produce an UNDEFINED value if the the bitmask update
+ // was previously deferred. See PR 120048.
+ if (tmp.undefined_p ())
+ tmp.set_varying (type);
ipa_vr vr (tmp);
ts->m_vr->quick_push (vr);
}
diff --git a/gcc/testsuite/gcc.dg/pr120048.c b/gcc/testsuite/gcc.dg/pr120048.c
new file mode 100644
index 00000000000..6bb34b0e168
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120048.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-vrp -fno-tree-fre" } */
+
+int a, b, c;
+static int d(short e) { return e || (a && e) ? 0 : a; }
+static void f(int e) {
+ if (!e) {
+ d(0);
+ b = d(e);
+ }
+}
+int main() { f(c | 1); }
--
2.45.0