v5: Handle a missing fn summary as though the function has an asm clobber.
Update the new test to include this case.
---
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, or the absence of a 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 | 42 ++++++++++++++++++++++++++
6 files changed, 72 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 a6ccdb1852a..7d1ffef1d65 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -3201,6 +3201,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,
@@ -4493,6 +4498,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)
@@ -4839,11 +4845,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)
@@ -5085,6 +5093,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 0503ec4c8d7..7e76882e454 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 130cd4c1e66..a7291ecb79e 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)
+ {
+ 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 1fc867fae51..89ecdc8ee8e 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..468689d82fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr124218.c
@@ -0,0 +1,42 @@
+/* { 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");
+}
+
+__attribute__ ((noinline, optimize ("O0", "-fipa-reference")))
+static void
+no_summary_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 ();
+
+ flag = 0;
+ no_summary_clobber_and_set ();
+ if (!flag)
+ __builtin_abort ();
+}
--
2.55.0