diff mbox series

Fix modref's iteraction with store merging

Message ID Zp6TQTiN8AKD2tvE@kam.mff.cuni.cz
State New
Headers show
Series Fix modref's iteraction with store merging | expand

Commit Message

Jan Hubicka July 22, 2024, 5:13 p.m. UTC
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.

Bootstrapped/regtested x86_64-linux, comitted.  Will backport it to
GCC14.

	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 mbox series

Patch

diff --git a/gcc/ipa-modref.cc b/gcc/ipa-modref.cc
index f994388a96a..53a2e35133d 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 00000000000..1ea1c4dec07
--- /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;
+}