This is the mail archive of the gcc@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]

Re: bug in lra causes incorrect register usage / compiler crash


I've now confirmed this same issue occurs on a stock i386 build when -fomit-frame-pointer is specified with -O2 and a test case with reasonable register pressure.

On 28/04/14 07:47, Paul Shortis wrote:
I'm porting gcc to a 16 bit cpu with a two address ISA like x86.

When using LRA I was getting compiler crashes and results like this from the reload pass

(insn 97 96 98 21 (parallel [
            (set (reg/f:HI 3 r3 [59])
                (plus:HI (reg/f:HI 6 sp)
                    (const_int 4 [0x4])))
            (clobber (reg:CC 7 flags))
        ]) ../../../libgcc/unwind-dw2-fde.c:304 25 {addhi3}
     (expr_list:REG_EQUIV (plus:HI (reg/f:HI 3 r3)
            (const_int 4 [0x4]))
        (nil)))

which is invalid, because like x86 the cpu only has instructions of the form Rn op= operand (e.g add r3,4).

The md pattern for this instruction is...

(define_insn "<commName>hi3"
  [     (set (match_operand:HI 0 "register_operand" "=r,r,r")
(commOperator:HI (match_operand:HI 1 "register_operand" "0,0,0") (match_operand:HI 2 "rhs_operand" "r,i,m")))

looking back at the ira output I could see that the input to the LRA was

(insn 97 96 98 18 (parallel [
            (set (reg/f:HI 59)
                (plus:HI (reg/f:HI 3 r3)
                    (const_int 4 [0x4])))
            (clobber (reg:CC 7 flags))
        ]) ../../../libgcc/unwind-dw2-fde.c:304 25 {addhi3}
     (expr_list:REG_UNUSED (reg:CC 7 flags)
        (expr_list:REG_EQUIV (plus:HI (reg/f:HI 3 r3)
                (const_int 4 [0x4]))

R3 is the frame pointer which is eliminated to sp by the LRA. Then r3 is allocated to virtual R59.

Tracing through LRA constraints processing I found the problem to be get_hard_regno (rtx x) which translates the virtual register 59 to R3 then erroneously passes this to get_final_hard_regno() which eliminates R3 to sp causing constraints to be (incorrectly) satisfied.

At final register elimination this problem doesn't occur, as there is a check before elimination to confirm that a register to be eliminated is actually a hard register. However the get_hard_regno() bug does cause incorrect constraint checking leading to invalid RTL generation, forming an impossible instruction.

The same circumstances exist when using the LRA for the i386. I'm guessing it hasn't raised its head because -fomit-frame-pointer is off by default for the i386 port.

I don't have write access to the repository so below is a patch for the change I used to address this problem.

Cheers, Paul.

diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index aac5087..81817f2 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -197,6 +197,7 @@ get_hard_regno (rtx x)
 {
   rtx reg;
   int offset, hard_regno;
+  bool is_virtual = false;

   reg = x;
   if (GET_CODE (x) == SUBREG)
@@ -204,14 +205,18 @@ get_hard_regno (rtx x)
   if (! REG_P (reg))
     return -1;
   if ((hard_regno = REGNO (reg)) >= FIRST_PSEUDO_REGISTER)
+  {
+    is_virtual = true;
     hard_regno = lra_get_regno_hard_regno (hard_regno);
+  }
   if (hard_regno < 0)
     return -1;
   offset = 0;
   if (GET_CODE (x) == SUBREG)
     offset += subreg_regno_offset (hard_regno, GET_MODE (reg),
SUBREG_BYTE (x), GET_MODE (x));
-  return get_final_hard_regno (hard_regno, offset);
+  return is_virtual ? hard_regno + offset
+                    : get_final_hard_regno (hard_regno, offset);
 }

















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