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]

Fwd: Possible fix for target/8812 (register allocation bug)


[ This was sent some time ago to the gcc-bugs list instead of gcc-patches. ]

----------  Forwarded Message  ----------

Subject: Possible fix for target/8812 (register allocation bug)
Date: Fri, 17 Jan 2003 18:12:53 -0330
From: Michael Rendell <michaelgcc@mytelescope.com>
To: gcc-bugs@gcc.gnu.org

Hello,

  Have a (probably incorrect) fix for gcc-20030113 for the problem reported
in target/8812 and am looking for some feedback.

  The basic problem is the code generated for the line:
    long offset2MatchDest = offset2Dest - matchOffset;
is:
    movw r26,r12
    movw r24,r10
    ldd r22,Y+5
    ldd r23,Y+6
    ldd r24,Y+7
    ldd r25,Y+8
    sub r24,r22
    sbc r25,r23
    sbc r26,r24
    sbc r27,r25
the allocated registers r24..27 and r22..25 overlap so the result
is incorrect.

The rtl before optimization is
    (note 39 38 40 4 ("mx.c") 252)
    (insn 40 39 41 4 0x40180478 (set (reg/v:SI 55)
            (minus:SI (reg/v:SI 47)
                (reg/v:SI 53))) 31 {subsi3} (insn_list 38 (nil))
        (nil))

and after optimization:
    note 39 38 118 4 ("mx.c") 252)
    (insn 118 39 119 4 (nil) (set (reg/v:SI 24 r24 [55])
            (reg/v:SI 2 r2 [47])) -1 (nil)
        (nil))
    (insn 119 118 40 4 (nil) (set (reg:SI 22 r22)
            (mem:SI (plus:HI (reg/f:HI 28 r28)
                    (const_int 1 [0x1])) [15 matchOffset S4 A8])) -1 (nil)
        (nil))
    (insn 40 119 41 4 0x40180478 (set (reg/v:SI 24 r24 [55])
            (minus:SI (reg/v:SI 24 r24 [55])
                (reg:SI 22 r22))) 31 {subsi3} (insn_list 38 (nil))
        (nil))

pseudo-reg 55 is allocated to r24..27, then choose_reload_regs (of reload1.c)
is called to reload pseudo-reg 53.  It finds 53 was previously loaded
into r22..25 (in the "if (search_equiv)" code block) and checks to see
if it can re-use this with the following code:
	      if (equiv != 0
                  && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
                       && ! free_for_value_p (regno, rld[r].mode,
                                              rld[r].opnum,
rld[r].when_needed,
                                              rld[r].in, rld[r].out, r, 1))

                      || ! TEST_HARD_REG_BIT (reg_class_contents[(int)

rld[r].cl
ass],
                                              regno)))
                equiv = 0;

The TEST_HARD_REG_BIT (reload_reg_used_at_all, regno) test returns false
because the register overlap is not taken into account: r22 is not in use,
but the value is really in r22..25, and r24..27 are in use.

The code seems to be incorrectly assuming that the value is stored in one
hard register, when it is actually in four.  The problem can be fixed by
changing the call to TEST_HARD_REG_BIT() to something that tests if
any of the hard registers are used.

The attached patch adds this code and appears to work.

Am not sure that this is the correct fix - is this situation supposed to be
handled elsewhere?  If the fix is correct, other uses of TEST_HARD_REG_BIT()
are likely to suffer from the same problem.

Michael

-------------------------------------------------------

--- reload1.c.Orig	Fri Jan 17 16:55:31 2003
+++ reload1.c	Fri Jan 17 17:04:53 2003
@@ -5302,6 +5302,22 @@
 			      rld[i].when_needed, rld[i].mode);
 }
 
+static int
+test_hard_reg_bits(reg_set, regno, nregs)
+    const HARD_REG_SET *reg_set;
+    int regno;
+    int nregs;
+{
+  int i;
+  int max = regno + nregs;
+  if (max > FIRST_PSEUDO_REGISTER)
+    max = FIRST_PSEUDO_REGISTER;
+  for (i = regno; i < max; ++i)
+    if (TEST_HARD_REG_BIT(*reg_set, i))
+      return 1;
+  return 0;
+}
+
 /* Assign hard reg targets for the pseudo-registers we must reload
    into hard regs for this insn.
    Also output the instructions to copy them in and out of the hard regs.
@@ -5675,7 +5691,9 @@
 	      /* If we found a spill reg, reject it unless it is free
 		 and of the desired class.  */
 	      if (equiv != 0
-		  && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
+		  && (( /* TEST_HARD_REG_BIT (reload_reg_used_at_all, regno) */
+		       test_hard_reg_bits (&reload_reg_used_at_all, regno,
+				     rld[r].nregs)
 		       && ! free_for_value_p (regno, rld[r].mode,
 					      rld[r].opnum, rld[r].when_needed,
 					      rld[r].in, rld[r].out, r, 1))

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