https://gcc.gnu.org/g:087a28832a28543872386e6e98692e1b9ea93bdf

commit 087a28832a28543872386e6e98692e1b9ea93bdf
Author: Jan Hubicka <hubi...@ucw.cz>
Date:   Mon Jul 22 19:00:39 2024 +0200

    Fix modref's iteraction with store merging
    
    Hi,
    this patch fixes wrong code in case store-merging introduces load of 
function
    parameter that was previously write-only (which happens for bitfields).
    Without this, the whole store-merged area is consdered to be killed.
    
            PR ipa/111613
    
    gcc/ChangeLog:
    
            * ipa-modref.cc (analyze_parms): Do not preserve EAF_NO_DIRECT_READ 
and
            EAF_NO_INDIRECT_READ from past flags.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.c-torture/pr111613.c: New test.

Diff:
---
 gcc/ipa-modref.cc                      |  3 +++
 gcc/testsuite/gcc.c-torture/pr111613.c | 29 +++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/gcc/ipa-modref.cc b/gcc/ipa-modref.cc
index f994388a96ab..53a2e35133da 100644
--- a/gcc/ipa-modref.cc
+++ b/gcc/ipa-modref.cc
@@ -3004,6 +3004,9 @@ analyze_parms (modref_summary *summary, 
modref_summary_lto *summary_lto,
                     (past, ecf_flags,
                      VOID_TYPE_P (TREE_TYPE
                          (TREE_TYPE (current_function_decl))));
+         /* Store merging can produce reads when combining together multiple
+            bitfields.  See PR111613.  */
+         past &= ~(EAF_NO_DIRECT_READ | EAF_NO_INDIRECT_READ);
          if (dump_file && (flags | past) != flags && !(flags & EAF_UNUSED))
            {
              fprintf (dump_file,
diff --git a/gcc/testsuite/gcc.c-torture/pr111613.c 
b/gcc/testsuite/gcc.c-torture/pr111613.c
new file mode 100644
index 000000000000..1ea1c4dec072
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/pr111613.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+struct bitfield {
+       unsigned int field1 : 1;
+       unsigned int field2 : 1;
+       unsigned int field3 : 1;
+};
+
+__attribute__((noinline)) static void
+set_field1_and_field2(struct bitfield *b) {
+       b->field1 = 1;
+       b->field2 = 1;
+}
+
+__attribute__((noinline)) static struct bitfield *
+new_bitfield(void) {
+       struct bitfield *b = (struct bitfield *)malloc(sizeof(*b));
+       b->field3 = 1;
+       set_field1_and_field2(b);
+       return b;
+}
+
+int main(void) {
+       struct bitfield *b = new_bitfield();
+       if (b->field3 != 1)
+               __builtin_abort ();
+       return 0;
+}

Reply via email to