Vineet Gupta <vine...@rivosinc.com> writes:
> On 6/3/25 08:24, Richard Sandiford wrote:
>> I think the issue is that:
>>
>> (insn 9 8 27 2 (parallel [
>>             (asm_operands/v ("fsrm %0") ("") 0 [
>>                     (reg:SI 15 a5 [139])
>>                 ]
>>                  [
>>                     (asm_input:SI ("r") frm-run-1.c:33)
>>                 ]
>>                  [] frm-run-1.c:33)
>>             (clobber (reg:V4096QI 69 frm))
>>         ]) "frm-run-1.c":33:3 -1
>>      (nil))
>>
>> is seen as invalidating FRM and so:
>>
>> (insn 27 9 28 2 (set (reg:SI 15 a5 [144])
>>         (reg:SI 69 frm)) "frm-run-1.c":43:1 2829 {frrmsi}
>>      (nil))
>>
>> is seen as an uninitialised read.  I suppose clobbers in inline asms
>> need to be treated as real definitions rather than just kills.
>
> In general or specifically inside of late_combine ?

We can start with the routines that rtl-ssa uses for its dataflow analysis.
Does the patch below help?

Jeff, Eric: any thoughts about this?

Richard


>From 29329926acfb15843f6dc3ac83a74a4e055bb3e6 Mon Sep 17 00:00:00 2001
From: Richard Sandiford <richard.sandif...@arm.com>
Date: Tue, 3 Jun 2025 17:48:12 +0100
Subject: [PATCH] rtlanal: Treat some asm clobbers as rmw accesses, not kills
To: gcc-patches@gcc.gnu.org

This patch treats certain asm clobbers as read-modify-write indicators,
rather than as mere kills.  See the comments in the patch for details.

gcc/
        * rtlanal.cc asm_clobber_is_read_modify_write_p): New function.
        (rtx_properties::try_to_add_pattern): Use it when processing CLOBBERs.
---
 gcc/rtlanal.cc | 44 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/gcc/rtlanal.cc b/gcc/rtlanal.cc
index 239d6691c4c..b8b563109c1 100644
--- a/gcc/rtlanal.cc
+++ b/gcc/rtlanal.cc
@@ -2072,6 +2072,37 @@ note_uses (rtx *pbody, void (*fun) (rtx *, void *), void 
*data)
     }
 }
 
+/* Return true if a clobber of X in an asm statement should be treated for
+   dataflow purposes as both a read of X and a write of a meaningful value
+   to X, rather than as a mere kill of X.  */
+
+static bool
+asm_clobber_is_read_modify_write_p (rtx x)
+{
+  if (MEM_P (x))
+    /* Asms that clobber memory can read from and write to arbitrary
+       memory locations.  */
+    return true;
+
+  if (REG_P (x) && HARD_REGISTER_P (x))
+    /* Some registers are suitable for asm operands.  If an asm reads
+       such a register, it should note that in the input operands.
+       If it writes a meaningful value to such a register, it should
+       note that in the output operands.  For these registers, a clobber
+       is just a kill.  For example, clobbers of argument registers should
+       not keep arbitrary earlier code live.
+
+       However, some fixed registers are not suitable for asm operands.
+       Neither the asm syntax nor the internal representation of asms provide
+       a direct way of indicating that an asm reads from or writes to such
+       registers.  The only indication that an asm can give is to clobber
+       the registers.  */
+    return !range_in_hard_reg_set_p (operand_reg_set, REGNO (x),
+                                    REG_NREGS (x));
+
+  return false;
+}
+
 /* Try to add a description of REG X to this object, stopping once
    the REF_END limit has been reached.  FLAGS is a bitmask of
    rtx_obj_reference flags that describe the context.  */
@@ -2262,8 +2293,17 @@ rtx_properties::try_to_add_pattern (const_rtx pat)
       break;
 
     case CLOBBER:
-      try_to_add_dest (XEXP (pat, 0), rtx_obj_flags::IS_CLOBBER);
-      break;
+      {
+       rtx x = XEXP (pat, 0);
+       if (has_asm && asm_clobber_is_read_modify_write_p (x))
+         {
+           try_to_add_dest (x);
+           try_to_add_src (x);
+         }
+       else
+         try_to_add_dest (x, rtx_obj_flags::IS_CLOBBER);
+       break;
+      }
 
     case SET:
       try_to_add_dest (SET_DEST (pat));
-- 
2.43.0

Reply via email to