This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] PR51374: combine.c and volatile correctness


This patch fixes PR51374 by more strictly updating mem_last_set.
Sloppy handling of mem_last_set can lead to error in volatile correctness
because combine then is allowed to drag one volatile access over an other
volatile thing (volatile access, asm volatile, unspec_volatile...).

As explained in the source comment, any volatile might change memory, even a
volatile read.

Moreover, writes of the shape (set (zero_extract (mem ... update mem_last_set.

combine still optimizes volatile insn like the SFR bit accesses in the PR
example if that does not require to drag one volatile over an other.

Tested without regressions on i686-pc-linux-gnu

Ok to apply?

Johann

	PR rtl-optimization/51374
	* combine.c (record_dead_and_set_regs_1): Update mem_last_set
	when reading from volatile memory or writing to mem via zero
	extract.

Index: combine.c
===================================================================
--- combine.c	(revision 183472)
+++ combine.c	(working copy)
@@ -12365,7 +12365,24 @@ record_dead_and_set_regs_1 (rtx dest, co
   else if (MEM_P (dest)
 	   /* Ignore pushes, they clobber nothing.  */
 	   && ! push_operand (dest, GET_MODE (dest)))
-    mem_last_set = DF_INSN_LUID (record_dead_insn);
+    {
+      mem_last_set = DF_INSN_LUID (record_dead_insn);
+    }
+  else if (ZERO_EXTRACT == GET_CODE (dest)
+           && MEM_P (XEXP (dest, 0)))
+    {
+      mem_last_set = DF_INSN_LUID (record_dead_insn);
+    }
+
+  /* Even reading a volatile memory location might change memory.
+     One example is reading an SFR that contains a latch or that belong to
+     a part of a communication unit where reading a FIFO register sets some
+     status or busy bits located elsewhere.  */
+
+  if (volatile_refs_p (PATTERN (record_dead_insn)))
+    {
+      mem_last_set = DF_INSN_LUID (record_dead_insn);
+    }
 }
 
 /* Update the records of when each REG was most recently set or killed

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]