aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorVladimir N. Makarov <vmakarov@redhat.com>2023-04-20 10:02:13 -0400
committerVladimir N. Makarov <vmakarov@redhat.com>2023-04-20 11:05:33 -0400
commit1d2aa9a8cb8fd078af930347392cfdfc14e1551c (patch)
treeda96939f6410edf0c7897fea85a6004fe2ad1300 /gcc
parentcae48a9d80790dcde6ae86122546c89a00d8bb4f (diff)
downloadgcc-1d2aa9a8cb8fd078af930347392cfdfc14e1551c.zip
gcc-1d2aa9a8cb8fd078af930347392cfdfc14e1551c.tar.gz
gcc-1d2aa9a8cb8fd078af930347392cfdfc14e1551c.tar.bz2
[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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/lra-constraints.cc28
1 files changed, 28 insertions, 0 deletions
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index b231cb6..4dc2d70 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,