diff mbox series

[pushed,LRA] : Exclude some hard regs for multi-reg inout reload pseudos used in asm in different mode

Message ID db985c56-371f-4d26-a1a5-26b25c5e68cf@redhat.com
State New
Headers show
Series [pushed,LRA] : Exclude some hard regs for multi-reg inout reload pseudos used in asm in different mode | expand

Commit Message

Vladimir Makarov April 20, 2023, 3:07 p.m. UTC
The following patch fixes test failure of 20030222-1.c on moxie port.  
But the problem can occur on other targets.  The patch actually 
implements the old reload approach for the test case.

The patch was successfully tested and bootstrapped on x86-64, aarch64, 
and ppc64le.
commit 51703ac3c722cd94011ab5b499921f6c9fe9fab5
Author: Vladimir N. Makarov <vmakarov@redhat.com>
Date:   Thu Apr 20 10:02:13 2023 -0400

    [LRA]: Exclude some hard regs for multi-reg inout reload pseudos used in asm in different mode
    
    See gcc.c-torture/execute/20030222-1.c.  Consider the code for 32-bit (e.g. BE) target:
      int i, v; long x; x = v; asm ("" : "=r" (i) : "0" (x));
    We generate the following RTL with reload insns:
      1. subreg:si(x:di, 0) = 0;
      2. subreg:si(x:di, 4) = v:si;
      3. t:di = x:di, dead x;
      4. asm ("" : "=r" (subreg:si(t:di,4)) : "0" (t:di))
      5. i:si = subreg:si(t:di,4);
    If we assign hard reg of x to t, dead code elimination will remove insn #2
    and we will use unitialized hard reg.  So exclude the hard reg of x for t.
    We could ignore this problem for non-empty asm using all x value but it is hard to
    check that the asm are expanded into insn realy using x and setting r.
    The old reload pass used the same approach.
    
    gcc/ChangeLog
    
            * lra-constraints.cc (match_reload): Exclude some hard regs for
            multi-reg inout reload pseudos used in asm in different mode.
diff mbox series

Patch

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index b231cb60529..4dc2d70c402 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -1022,6 +1022,34 @@  match_reload (signed char out, signed char *ins, signed char *outs,
 	 are ordered.  */
       if (partial_subreg_p (outmode, inmode))
 	{
+	  bool asm_p = asm_noperands (PATTERN (curr_insn)) >= 0;
+	  int hr;
+	  HARD_REG_SET temp_hard_reg_set;
+	  
+	  if (asm_p && (hr = get_hard_regno (out_rtx)) >= 0
+	      && hard_regno_nregs (hr, inmode) > 1)
+	    {
+	      /* See gcc.c-torture/execute/20030222-1.c.
+		 Consider the code for 32-bit (e.g. BE) target:
+		   int i, v; long x; x = v; asm ("" : "=r" (i) : "0" (x));
+		 We generate the following RTL with reload insns:
+  		   1. subreg:si(x:di, 0) = 0;
+		   2. subreg:si(x:di, 4) = v:si;
+		   3. t:di = x:di, dead x;
+		   4. asm ("" : "=r" (subreg:si(t:di,4)) : "0" (t:di))
+		   5. i:si = subreg:si(t:di,4);
+		 If we assign hard reg of x to t, dead code elimination
+		 will remove insn #2 and we will use unitialized hard reg.
+		 So exclude the hard reg of x for t.  We could ignore this
+		 problem for non-empty asm using all x value but it is hard to
+		 check that the asm are expanded into insn realy using x
+		 and setting r.  */
+	      CLEAR_HARD_REG_SET (temp_hard_reg_set);
+	      if (exclude_start_hard_regs != NULL)
+		temp_hard_reg_set = *exclude_start_hard_regs;
+	      SET_HARD_REG_BIT (temp_hard_reg_set, hr);
+	      exclude_start_hard_regs = &temp_hard_reg_set;
+	    }
 	  reg = new_in_reg
 	    = lra_create_new_reg_with_unique_value (inmode, in_rtx, goal_class,
 						    exclude_start_hard_regs,