> On Mar 4, 2026, at 8:34 AM, Jan Hubicka <[email protected]> wrote:
>
>
>>
>>> On Wed, Mar 4, 2026 at 11:05 AM Chris Copeland <[email protected]> wrote:
>>>
>>> I reported https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124218
>>> recently after learning it affects the synchronization interfaces
>>> provided by real-time operating systems when using -fwhole-program or
>>> -flto. For example, this can leads to moving accesses outside of a
>>> section where a FreeRTOS mutex is held. Other ipa passes like
>>> ipa-pure-const and ipa-modref handle memory clobbers in their analysis
>>> already.
>>>
>>> I've added a new test that runs on arm-none and will fail without the
>>> change to ipa-reference.cc, by having an assembly statement that
>>> declares a memory clobber and actually writes a global that the previous
>>> version of the analysis would treat as not modified. Please let me know
>>> if there's a more appropriate way to test this. Other tests are passing
>>> on an aarch64 linux host.
>>>
>>> PR ipa/124218
>>> ---
>>> gcc/ChangeLog | 6 ++++++
>>> gcc/ipa-reference.cc | 23 +++++++++++++++++++++++
>>> gcc/testsuite/gcc.dg/ipa/pr124218.c | 25 +++++++++++++++++++++++++
>>> 3 files changed, 54 insertions(+)
>>> create mode 100644 gcc/testsuite/gcc.dg/ipa/pr124218.c
>>>
>>> diff --git a/gcc/ChangeLog b/gcc/ChangeLog
>>> index 8f5a62893c1..1be3b678fda 100644
>>> --- a/gcc/ChangeLog
>>> +++ b/gcc/ChangeLog
>>> @@ -1,3 +1,9 @@
>>> +2026-03-03 Chris Copeland <[email protected]>
>>> +
>>> + PR ipa/124218
>>> + * ipa-reference.cc (analyze_function): Treat memory clobbers as
>>> + reading/writing all_module_statics.
>>> +
>>> 2026-03-03 H.J. Lu <[email protected]>
>>>
>>> PR target/124165
>>> diff --git a/gcc/ipa-reference.cc b/gcc/ipa-reference.cc
>>> index c5699312c8f..0c50b4b2df7 100644
>>> --- a/gcc/ipa-reference.cc
>>> +++ b/gcc/ipa-reference.cc
>>> @@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
>>> #include "backend.h"
>>> #include "tree.h"
>>> #include "gimple.h"
>>> +#include "gimple-iterator.h"
>>> #include "tree-pass.h"
>>> #include "cgraph.h"
>>> #include "data-streamer.h"
>>> @@ -550,6 +551,28 @@ analyze_function (struct cgraph_node *fn)
>>>
>>> if (fn->cannot_return_p ())
>>> bitmap_clear (local->statics_written);
>>> +
>>> + /* If the function body contains any asm statement that clobbers memory,
>>> + mark all module statics as read and written. */
>>
>> An extra IL walk seems excessive for this, I wonder if we (should)
>> have recorded such fact
>> elsewhere, like in some other IPA summary?
>
> I suppose best fit is fnsummary which holds all kinds of stuff useful
> for IPA passes and is always computed.
>
>>> +/* PR ipa/124218: ipa-reference must honor memory clobbers in inline asm.
>>> */
>>> +
>>> +int flag;
>>> +
>>> +__attribute__ ((noinline))
>>> +static void
>>> +clobber_and_set (void)
>>> +{
>>> + __asm__ volatile ("ldr r0, =flag\n\t"
>>> + "mov r1, #1\n\t"
>>> + "str r1, [r0]"
>>> + ::: "r0", "r1", "memory");
>
> At least withtout new Michal's heuristics, for making this safe with LTO
> you need used attribute on flag and that disables ipa-reference on it.
This was discussed some on the bug report, but in the real code this clobber is
at the location where a context switch is triggered, which eventually leads to
another task executing that modifies flag. I wrote the test this way because
it's the simplest thing I could come up with to represent that situation. Would
an unrelated and not-called function that does modify the flag obviate the need
for ((used)) in this test, even without forthcoming changes?
>
> Honza
>>> +}
>>> +
>>> +int main (void)
>>> +{
>>> + flag = 0;
>>> + clobber_and_set ();
>>> + if (!flag)
>>> + __builtin_abort ();
>>> + return 0;
>>> +}
>>> --
>>> 2.53.0
>>>