> On Jul 1, 2026, at 2:32 AM, Richard Biener <[email protected]> wrote: > > On Wed, Apr 15, 2026 at 9:22 AM Chris Copeland <[email protected] > <mailto:[email protected]>> wrote: >> >> v4: Remove ChangeLog edits from the patch. >> >> --- >> >> Record the presence of asm memory clobbers in ipa_fn_summary and use it >> in ipa-reference's analyze_function to mark all module statics as read >> and written. Move pass_ipa_reference before pass_ipa_free_fn_summary so >> the summary is still available when needed. >> >> gcc/ChangeLog: >> >> PR ipa/124218 >> * ipa-fnsummary.h (ipa_fn_summary): Add asm_memory_clobber field. >> * ipa-fnsummary.cc (analyze_function_body): Set asm_memory_clobber >> when a GIMPLE_ASM with a memory clobber is found. >> (ipa_merge_fn_summary_after_inlining): Merge asm_memory_clobber. >> (inline_read_section): Stream in asm_memory_clobber. >> (ipa_fn_summary_write): Stream out asm_memory_clobber. >> * ipa-reference.cc (analyze_function): Use asm_memory_clobber from >> fn summary to mark all module statics as read and written. >> * passes.def: Move pass_ipa_reference before pass_ipa_free_fn_summary. >> >> gcc/testsuite/ChangeLog: >> >> PR ipa/124218 >> * gcc.dg/ipa/pr124218.c: New test. >> * g++.dg/guality/pr55665.C: Remove memory clobber. This memory clobber >> was being ignored before, and leaving it in now triggers PR124864, >> breaking the test. Correct PR number in first comment. >> --- >> gcc/ipa-fnsummary.cc | 9 ++++++++ >> gcc/ipa-fnsummary.h | 6 +++++- >> gcc/ipa-reference.cc | 13 +++++++++++ >> gcc/passes.def | 2 +- >> gcc/testsuite/g++.dg/guality/pr55665.C | 4 ++-- >> gcc/testsuite/gcc.dg/ipa/pr124218.c | 30 ++++++++++++++++++++++++++ >> 6 files changed, 60 insertions(+), 4 deletions(-) >> create mode 100644 gcc/testsuite/gcc.dg/ipa/pr124218.c >> >> diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc >> index e187231dfb6..2e1387ec746 100644 >> --- a/gcc/ipa-fnsummary.cc >> +++ b/gcc/ipa-fnsummary.cc >> @@ -3200,6 +3200,11 @@ analyze_function_body (struct cgraph_node *node, bool >> early) >> } >> } >> >> + if (!info->asm_memory_clobber >> + && gimple_code (stmt) == GIMPLE_ASM >> + && gimple_asm_clobbers_memory_p (as_a <gasm *> (stmt))) >> + info->asm_memory_clobber = true; >> + >> /* For target specific information, we want to scan all statements >> rather than those statements with non-zero weights, to avoid >> missing to scan something interesting for target information, >> @@ -4492,6 +4497,7 @@ ipa_merge_fn_summary_after_inlining (struct >> cgraph_edge *edge) >> toplev_predicate = true; >> >> info->fp_expressions |= callee_info->fp_expressions; >> + info->asm_memory_clobber |= callee_info->asm_memory_clobber; >> info->target_info |= callee_info->target_info; >> >> if (callee_info->conds) >> @@ -4838,11 +4844,13 @@ inline_read_section (struct lto_file_decl_data >> *file_data, const char *data, >> { >> info->inlinable = bp_unpack_value (&bp, 1); >> info->fp_expressions = bp_unpack_value (&bp, 1); >> + info->asm_memory_clobber = bp_unpack_value (&bp, 1); >> if (!lto_stream_offload_p) >> info->target_info = streamer_read_uhwi (&ib); >> } >> else >> { >> + bp_unpack_value (&bp, 1); >> bp_unpack_value (&bp, 1); >> bp_unpack_value (&bp, 1); >> if (!lto_stream_offload_p) >> @@ -5084,6 +5092,7 @@ ipa_fn_summary_write (void) >> bp = bitpack_create (ob->main_stream); >> bp_pack_value (&bp, info->inlinable, 1); >> bp_pack_value (&bp, info->fp_expressions, 1); >> + bp_pack_value (&bp, info->asm_memory_clobber, 1); >> streamer_write_bitpack (&bp); >> if (!lto_stream_offload_p) >> streamer_write_uhwi (ob, info->target_info); >> diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h >> index de7b7f61cb1..896cb6c1725 100644 >> --- a/gcc/ipa-fnsummary.h >> +++ b/gcc/ipa-fnsummary.h >> @@ -126,7 +126,8 @@ public: >> ipa_fn_summary () >> : min_size (0), >> inlinable (false), single_caller (false), >> - fp_expressions (false), safe_to_inline_to_always_inline (0), >> + fp_expressions (false), asm_memory_clobber (false), >> + safe_to_inline_to_always_inline (0), >> target_info (0), estimated_stack_size (false), >> time (0), conds (NULL), >> size_time_table (), call_size_time_table (vNULL), >> @@ -141,6 +142,7 @@ public: >> : min_size (s.min_size), >> inlinable (s.inlinable), single_caller (s.single_caller), >> fp_expressions (s.fp_expressions), >> + asm_memory_clobber (s.asm_memory_clobber), >> target_info (s.target_info), >> estimated_stack_size (s.estimated_stack_size), >> time (s.time), conds (s.conds), size_time_table (), >> @@ -165,6 +167,8 @@ public: >> unsigned int single_caller : 1; >> /* True if function contains any floating point expressions. */ >> unsigned int fp_expressions : 1; >> + /* True if function contains an asm statement that clobbers memory. */ >> + unsigned int asm_memory_clobber : 1; >> /* Cache for analysis of can_early_inline_edge_p. */ >> unsigned int safe_to_inline_to_always_inline : 2; >> /* Like fp_expressions field above, but it's to hold some target specific >> diff --git a/gcc/ipa-reference.cc b/gcc/ipa-reference.cc >> index c5699312c8f..12b593b0f50 100644 >> --- a/gcc/ipa-reference.cc >> +++ b/gcc/ipa-reference.cc >> @@ -50,6 +50,11 @@ along with GCC; see the file COPYING3. If not see >> #include "ipa-reference.h" >> #include "alloc-pool.h" >> #include "symbol-summary.h" >> +#include "tree-vrp.h" >> +#include "sreal.h" >> +#include "ipa-cp.h" >> +#include "ipa-prop.h" >> +#include "ipa-fnsummary.h" >> >> /* The static variables defined within the compilation unit that are >> loaded or stored directly by function that owns this structure. */ >> @@ -507,6 +512,7 @@ analyze_function (struct cgraph_node *fn) >> { >> ipa_reference_local_vars_info_t local; >> struct ipa_ref *ref = NULL; >> + ipa_fn_summary *sum; >> int i; >> tree var; >> >> @@ -548,6 +554,13 @@ analyze_function (struct cgraph_node *fn) >> } >> } >> >> + sum = ipa_fn_summaries->get (fn); >> + if (sum && sum->asm_memory_clobber) > > Don't we need to treat the sum == NULL case conservatively, > thus if (!sum || sum->asm_memory_clobber)?
Yes, thanks for the catch. I've submitted v5 with this change and a corresponding test change. https://gcc.gnu.org/pipermail/gcc-patches/2026-July/722754.html > > Otherwise looks OK. > > Thanks, > Richard. > >> + { >> + local->statics_read = all_module_statics; >> + local->statics_written = all_module_statics; >> + } >> + >> if (fn->cannot_return_p ()) >> bitmap_clear (local->statics_written); >> } >> diff --git a/gcc/passes.def b/gcc/passes.def >> index cdddb87302f..8344ea1a584 100644 >> --- a/gcc/passes.def >> +++ b/gcc/passes.def >> @@ -176,8 +176,8 @@ along with GCC; see the file COPYING3. If not see >> NEXT_PASS (pass_ipa_locality_cloning); >> NEXT_PASS (pass_ipa_pure_const); >> NEXT_PASS (pass_ipa_modref); >> - NEXT_PASS (pass_ipa_free_fn_summary, false /* small_p */); >> NEXT_PASS (pass_ipa_reference); >> + NEXT_PASS (pass_ipa_free_fn_summary, false /* small_p */); >> /* This pass needs to be scheduled after any IP code duplication. */ >> NEXT_PASS (pass_ipa_single_use); >> /* Comdat privatization come last, as direct references to comdat local >> diff --git a/gcc/testsuite/g++.dg/guality/pr55665.C >> b/gcc/testsuite/g++.dg/guality/pr55665.C >> index 16c6d281661..d100d0abc29 100644 >> --- a/gcc/testsuite/g++.dg/guality/pr55665.C >> +++ b/gcc/testsuite/g++.dg/guality/pr55665.C >> @@ -1,4 +1,4 @@ >> -// PR debug/55655 >> +// PR debug/55665 >> // { dg-do run } >> // { dg-options "-g" } >> >> @@ -14,7 +14,7 @@ bar (void) >> __attribute__((noinline, noclone)) void >> foo (int x) >> { >> - __asm volatile ("" : : "r" (x) : "memory"); >> + __asm volatile ("" : : "r" (x)); >> } >> >> A::A (int x) >> diff --git a/gcc/testsuite/gcc.dg/ipa/pr124218.c >> b/gcc/testsuite/gcc.dg/ipa/pr124218.c >> new file mode 100644 >> index 00000000000..67e95914d6b >> --- /dev/null >> +++ b/gcc/testsuite/gcc.dg/ipa/pr124218.c >> @@ -0,0 +1,30 @@ >> +/* { dg-do run { target arm*-*-eabi* } } */ >> +/* { dg-options "-O1 -fwhole-program" } */ >> + >> +/* PR ipa/124218: ipa-reference must honor memory clobbers in inline asm. >> */ >> + >> +int flag; >> + >> +__attribute__ ((used)) >> +void >> +asm_set (void) >> +{ >> + flag = 1; >> +} >> + >> +__attribute__ ((noinline)) >> +static void >> +clobber_and_set (void) >> +{ >> + __asm__ volatile ("bl asm_set" ::: "r0", "r1", "r2", "r3", >> + "ip", "lr", "memory", "cc"); >> +} >> + >> +int main (void) >> +{ >> + flag = 0; >> + clobber_and_set (); >> + if (!flag) >> + __builtin_abort (); >> + return 0; >> +} >> -- >> 2.53.0
