public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* What's wrong with this RTL?
@ 2022-01-10  4:48 Andras Tantos
  2022-01-10  6:19 ` Andrew Pinski
  0 siblings, 1 reply; 3+ messages in thread
From: Andras Tantos @ 2022-01-10  4:48 UTC (permalink / raw)
  To: gcc

All!

I'm trying to port GCC to a new target, I call 'brew'. I've based it on
the Moxie target mostly because of it's simplicity.

I must be doing something horribly wrong as the following C code crokes
in the LRA path:

   long long foo (long long a, long long *w)
   {
     return __builtin_add_overflow (a, a, w);
   }

The error message I get is the following:

   during RTL pass: reload
   ../brew-gcc-build/second.c: In function ‘foo’:
   ../brew-gcc-build/second.c:5:1: internal compiler error: maximum
   number of generated reload insns per insn achieved (90)
       5 | }
         | ^
   0xd23854 lra_constraints(bool)
   	../../brew-gcc/gcc/lra-constraints.c:5095
   0xd10322 lra(_IO_FILE*)
   	../../brew-gcc/gcc/lra.c:2336
   0xcc86d9 do_reload
   	../../brew-gcc/gcc/ira.c:5932
   0xcc86d9 execute
   	../../brew-gcc/gcc/ira.c:6118
   Please submit a full bug report,
   with preprocessed source if appropriate.
   Please include the complete backtrace with any bug report.
   See <https://gcc.gnu.org/bugs/> for instructions.

   The repro seems to go away, if:

   1. If I don't use the return value from __builtin_add_overflow
   2. If I don't return a long long value
   3. If I use some other function, which is not inlined
   4. If I write and call some other (somewhat non-trivial) force-inline
   function myself

   In other words, this is pretty much the minimal repro, I've found so
   far.
      
   The initial RTL passed in to LRA appears to be:

   (insn 2 4 3 2 (set (mem/f/c:SI (plus:SI (reg/f:SI 16 ?ap)
                   (const_int 12 [0xc])) [2 w+0 S4 A32])
           (reg:SI 4 $r4)) "../brew-gcc-build/second.c":2:1 23
   {*movsi_store}
        (expr_list:REG_DEAD (reg:SI 4 $r4)
           (nil)))

   (note 3 2 8 2 NOTE_INSN_FUNCTION_BEG)

   (insn 8 3 6 2 (clobber (reg:DI 27 [ _5+8 ])) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 6 8 7 2 (set (subreg:SI (reg:DI 27 [ _5+8 ]) 0)
           (const_int 0 [0])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (insn 7 6 13 2 (set (subreg:SI (reg:DI 27 [ _5+8 ]) 4)
           (const_int 0 [0])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (insn 13 7 18 2 (clobber (reg:DI 30)) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 18 13 19 2 (clobber (reg:DI 33)) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 19 18 20 2 (clobber (reg:DI 36)) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 20 19 21 2 (set (subreg:SI (reg:DI 36) 4)
           (plus:SI (subreg:SI (reg:DI 30) 4)
               (subreg:SI (reg:DI 33) 4))) "../brew-gcc-
   build/second.c":3:10 2 {addsi3}
        (nil))

   (insn 21 20 22 2 (set (reg:SI 37)
           (const_int 1 [0x1])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (jump_insn 22 21 83 2 (set (pc)
           (if_then_else (ltu (subreg:SI (reg:DI 36) 4)
                   (subreg:SI (reg:DI 30) 4))
               (label_ref 24)
               (pc))) "../brew-gcc-build/second.c":3:10 38 {cbranchsi4}
        (nil)
    -> 24)

   (note 83 22 23 3 [bb 3] NOTE_INSN_BASIC_BLOCK)

   (insn 23 83 24 3 (set (reg:SI 37)
           (const_int 0 [0])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (code_label 24 23 84 4 4 (nil) [1 uses])

   (note 84 24 25 4 [bb 4] NOTE_INSN_BASIC_BLOCK)

   (insn 25 84 26 4 (set (subreg:SI (reg:DI 36) 0)
           (plus:SI (subreg:SI (reg:DI 30) 0)
               (subreg:SI (reg:DI 33) 0))) "../brew-gcc-
   build/second.c":3:10 2 {addsi3}
        (expr_list:REG_DEAD (reg:DI 33)
           (expr_list:REG_DEAD (reg:DI 30)
               (nil))))

   (insn 26 25 27 4 (set (reg:SI 38)
           (plus:SI (reg:SI 37)
               (subreg:SI (reg:DI 36) 0))) "../brew-gcc-
   build/second.c":3:10 2 {addsi3}
        (expr_list:REG_DEAD (reg:SI 37)
           (nil)))

   (insn 27 26 28 4 (set (subreg:SI (reg:DI 36) 0)
           (reg:SI 38)) "../brew-gcc-build/second.c":3:10 21
   {*movsi_move}
        (expr_list:REG_DEAD (reg:SI 38)
           (nil)))

   (insn 28 27 29 4 (set (reg:SI 40)
           (mem/c:SI (plus:SI (reg/f:SI 16 ?ap)
                   (const_int 4 [0x4])) [1 a+0 S4 A32])) "../brew-gcc-
   build/second.c":3:10 22 {*movsi_load}
        (nil))

   (insn 29 28 30 4 (set (subreg:SI (reg:DI 39) 0)
           (xor:SI (reg:SI 40)
               (reg:SI 40))) "../brew-gcc-build/second.c":3:10 15
   {xorsi3}
        (expr_list:REG_DEAD (reg:SI 40)
           (nil)))

   (insn 30 29 31 4 (set (reg:SI 41)
           (mem/c:SI (plus:SI (reg/f:SI 16 ?ap)
                   (const_int 8 [0x8])) [1 a+4 S4 A32])) "../brew-gcc-
   build/second.c":3:10 22 {*movsi_load}
        (nil))

   (insn 31 30 32 4 (set (subreg:SI (reg:DI 39) 4)
           (xor:SI (reg:SI 41)
               (reg:SI 41))) "../brew-gcc-build/second.c":3:10 15
   {xorsi3}
        (expr_list:REG_DEAD (reg:SI 41)
           (nil)))

   (insn 32 31 33 4 (set (reg:SI 43)
           (mem/c:SI (plus:SI (reg/f:SI 16 ?ap)
                   (const_int 4 [0x4])) [1 a+0 S4 A32])) "../brew-gcc-
   build/second.c":3:10 22 {*movsi_load}
        (nil))

   (insn 33 32 34 4 (set (subreg:SI (reg:DI 42) 0)
           (xor:SI (reg:SI 43)
               (subreg:SI (reg:DI 36) 0))) "../brew-gcc-
   build/second.c":3:10 15 {xorsi3}
        (expr_list:REG_DEAD (reg:SI 43)
           (nil)))

   (insn 34 33 35 4 (set (reg:SI 44)
           (mem/c:SI (plus:SI (reg/f:SI 16 ?ap)
                   (const_int 8 [0x8])) [1 a+4 S4 A32])) "../brew-gcc-
   build/second.c":3:10 22 {*movsi_load}
        (nil))

   (insn 35 34 36 4 (set (subreg:SI (reg:DI 42) 4)
           (xor:SI (reg:SI 44)
               (subreg:SI (reg:DI 36) 4))) "../brew-gcc-
   build/second.c":3:10 15 {xorsi3}
        (expr_list:REG_DEAD (reg:SI 44)
           (nil)))

   (insn 36 35 37 4 (set (subreg:SI (reg:DI 45) 0)
           (not:SI (subreg:SI (reg:DI 39) 0))) "../brew-gcc-
   build/second.c":3:10 12 {one_cmplsi2}
        (nil))

   (insn 37 36 38 4 (set (subreg:SI (reg:DI 45) 4)
           (not:SI (subreg:SI (reg:DI 39) 4))) "../brew-gcc-
   build/second.c":3:10 12 {one_cmplsi2}
        (expr_list:REG_DEAD (reg:DI 39)
           (nil)))

   (insn 38 37 39 4 (set (subreg:SI (reg:DI 46) 0)
           (and:SI (subreg:SI (reg:DI 42) 0)
               (subreg:SI (reg:DI 45) 0))) "../brew-gcc-
   build/second.c":3:10 14 {andsi3}
        (nil))

   (insn 39 38 42 4 (set (subreg:SI (reg:DI 46) 4)
           (and:SI (subreg:SI (reg:DI 42) 4)
               (subreg:SI (reg:DI 45) 4))) "../brew-gcc-
   build/second.c":3:10 14 {andsi3}
        (expr_list:REG_DEAD (reg:DI 45)
           (expr_list:REG_DEAD (reg:DI 42)
               (nil))))

   (jump_insn 42 39 85 4 (set (pc)
           (if_then_else (ge (subreg:SI (reg:DI 46) 0)
                   (const_int 0 [0]))
               (label_ref 50)
               (pc))) "../brew-gcc-build/second.c":3:10 38 {cbranchsi4}
        (expr_list:REG_DEAD (reg:DI 46)
           (nil))
    -> 50)

   (note 85 42 49 5 [bb 5] NOTE_INSN_BASIC_BLOCK)

   (insn 49 85 47 5 (clobber (reg:DI 27 [ _5+8 ])) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 47 49 48 5 (set (subreg:SI (reg:DI 27 [ _5+8 ]) 0)
           (const_int 0 [0])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (insn 48 47 50 5 (set (subreg:SI (reg:DI 27 [ _5+8 ]) 4)
           (const_int 1 [0x1])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (code_label 50 48 88 6 2 (nil) [1 uses])

   (note 88 50 53 6 [bb 6] NOTE_INSN_BASIC_BLOCK)

   (insn 53 88 51 6 (clobber (reg:DI 26 [ _5 ])) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 51 53 52 6 (set (subreg:SI (reg:DI 26 [ _5 ]) 0)
           (subreg:SI (reg:DI 36) 0)) "../brew-gcc-build/second.c":3:10 
   21 {*movsi_move}
        (nil))

   (insn 52 51 56 6 (set (subreg:SI (reg:DI 26 [ _5 ]) 4)
           (subreg:SI (reg:DI 36) 4)) "../brew-gcc-build/second.c":3:10 
   21 {*movsi_move}
        (expr_list:REG_DEAD (reg:DI 36)
           (nil)))

   (insn 56 52 54 6 (clobber (reg:DI 23 [ _1 ])) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 54 56 55 6 (set (subreg:SI (reg:DI 23 [ _1 ]) 0)
           (subreg:SI (reg:DI 26 [ _5 ]) 0)) "../brew-gcc-
   build/second.c":3:10 21 {*movsi_move}
        (nil))

   (insn 55 54 57 6 (set (subreg:SI (reg:DI 23 [ _1 ]) 4)
           (subreg:SI (reg:DI 26 [ _5 ]) 4)) "../brew-gcc-
   build/second.c":3:10 21 {*movsi_move}
        (expr_list:REG_DEAD (reg:DI 26 [ _5 ])
           (nil)))

   (insn 57 55 58 6 (set (reg/f:SI 47)
           (mem/f/c:SI (plus:SI (reg/f:SI 16 ?ap)
                   (const_int 12 [0xc])) [2 w+0 S4 A32])) "../brew-gcc-
   build/second.c":3:10 22 {*movsi_load}
        (nil))

   (insn 58 57 59 6 (set (reg:SI 48)
           (subreg:SI (reg:DI 23 [ _1 ]) 0)) "../brew-gcc-
   build/second.c":3:10 21 {*movsi_move}
        (nil))

   (insn 59 58 60 6 (set (mem:SI (reg/f:SI 47) [1 *w_7(D)+0 S4 A32])
           (reg:SI 48)) "../brew-gcc-build/second.c":3:10 23
   {*movsi_store}
        (expr_list:REG_DEAD (reg:SI 48)
           (nil)))

   (insn 60 59 61 6 (set (reg:SI 49)
           (subreg:SI (reg:DI 23 [ _1 ]) 4)) "../brew-gcc-
   build/second.c":3:10 21 {*movsi_move}
        (expr_list:REG_DEAD (reg:DI 23 [ _1 ])
           (nil)))

   (insn 61 60 64 6 (set (mem:SI (plus:SI (reg/f:SI 47)
                   (const_int 4 [0x4])) [1 *w_7(D)+4 S4 A32])
           (reg:SI 49)) "../brew-gcc-build/second.c":3:10 23
   {*movsi_store}
        (expr_list:REG_DEAD (reg:SI 49)
           (expr_list:REG_DEAD (reg/f:SI 47)
               (nil))))

   (insn 64 61 62 6 (clobber (reg:DI 24 [ _2 ])) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 62 64 63 6 (set (subreg:SI (reg:DI 24 [ _2 ]) 0)
           (subreg:SI (reg:DI 27 [ _5+8 ]) 0)) "../brew-gcc-
   build/second.c":3:10 21 {*movsi_move}
        (nil))

   (insn 63 62 65 6 (set (subreg:SI (reg:DI 24 [ _2 ]) 4)
           (subreg:SI (reg:DI 27 [ _5+8 ]) 4)) "../brew-gcc-
   build/second.c":3:10 21 {*movsi_move}
        (expr_list:REG_DEAD (reg:DI 27 [ _5+8 ])
           (nil)))

   (insn 65 63 66 6 (set (reg:QI 25 [ _3 ])
           (subreg:QI (reg:DI 24 [ _2 ]) 7)) "../brew-gcc-
   build/second.c":3:10 31 {*movqi_move}
        (expr_list:REG_DEAD (reg:DI 24 [ _2 ])
           (nil)))

   (insn 66 65 67 6 (set (reg:SI 50)
           (and:SI (subreg:SI (reg:QI 25 [ _3 ]) 0)
               (const_int 1 [0x1]))) "../brew-gcc-build/second.c":3:10
   14 {andsi3}
        (expr_list:REG_DEAD (reg:QI 25 [ _3 ])
           (nil)))

   (insn 67 66 68 6 (set (reg:QI 25 [ _3 ])
           (subreg:QI (reg:SI 50) 3)) "../brew-gcc-build/second.c":3:10 
   31 {*movqi_move}
        (expr_list:REG_DEAD (reg:SI 50)
           (nil)))

   (insn 68 67 69 6 (set (reg:SI 51)
           (zero_extend:SI (reg:QI 25 [ _3 ]))) "../brew-gcc-
   build/second.c":3:10 35 {zero_extendqisi2}
        (expr_list:REG_DEAD (reg:QI 25 [ _3 ])
           (nil)))

   (insn 69 68 70 6 (set (subreg:SI (reg:DI 28 [ _9 ]) 4)
           (reg:SI 51)) "../brew-gcc-build/second.c":3:10 21
   {*movsi_move}
        (expr_list:REG_DEAD (reg:SI 51)
           (nil)))

   (insn 70 69 75 6 (set (subreg:SI (reg:DI 28 [ _9 ]) 0)
           (const_int 0 [0])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (insn 75 70 73 6 (clobber (reg:DI 29 [ <retval> ])) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 73 75 74 6 (set (subreg:SI (reg:DI 29 [ <retval> ]) 0)
           (subreg:SI (reg:DI 28 [ _9 ]) 0)) "../brew-gcc-
   build/second.c":3:10 21 {*movsi_move}
        (nil))

   (insn 74 73 79 6 (set (subreg:SI (reg:DI 29 [ <retval> ]) 4)
           (subreg:SI (reg:DI 28 [ _9 ]) 4)) "../brew-gcc-
   build/second.c":3:10 21 {*movsi_move}
        (expr_list:REG_DEAD (reg:DI 28 [ _9 ])
           (nil)))

   (insn 79 74 80 6 (set (reg:SI 4 $r4)
           (subreg:SI (reg:DI 29 [ <retval> ]) 0)) "../brew-gcc-
   build/second.c":5:1 21 {*movsi_move}
        (nil))

   (insn 80 79 81 6 (set (reg:SI 5 $r5 [orig:4+4 ] [4])
           (subreg:SI (reg:DI 29 [ <retval> ]) 4)) "../brew-gcc-
   build/second.c":5:1 21 {*movsi_move}
        (expr_list:REG_DEAD (reg:DI 29 [ <retval> ])
           (nil)))

   (insn 81 80 89 6 (use (reg/i:DI 4 $r4)) "../brew-gcc-
   build/second.c":5:1 -1
        (nil))

   (note 89 81 0 NOTE_INSN_DELETED)

   What I've noticed when I dump the RTL from LRA during each of its
   iterations is the following:

   In the first several iterations, LRA proceeds to delete the first
   several instructions (all the below gets deleted):

   (insn 2 4 3 2 (set (mem/f/c:SI (plus:SI (reg/f:SI 16 ?ap)
                   (const_int 12 [0xc])) [2 w+0 S4 A32])
           (reg:SI 4 $r4)) "../brew-gcc-build/second.c":2:1 23
   {*movsi_store}
        (expr_list:REG_DEAD (reg:SI 4 $r4)
           (nil)))

   (note 3 2 8 2 NOTE_INSN_FUNCTION_BEG)

   (insn 8 3 6 2 (clobber (reg:DI 27 [ _5+8 ])) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 6 8 7 2 (set (subreg:SI (reg:DI 27 [ _5+8 ]) 0)
           (const_int 0 [0])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (insn 7 6 13 2 (set (subreg:SI (reg:DI 27 [ _5+8 ]) 4)
           (const_int 0 [0])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (insn 13 7 18 2 (clobber (reg:DI 30)) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 18 13 19 2 (clobber (reg:DI 33)) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 19 18 20 2 (clobber (reg:DI 36)) "../brew-gcc-
   build/second.c":3:10 -1
        (nil))

   (insn 20 19 21 2 (set (subreg:SI (reg:DI 36) 4)
           (plus:SI (subreg:SI (reg:DI 30) 4)
               (subreg:SI (reg:DI 33) 4))) "../brew-gcc-
   build/second.c":3:10 2 {addsi3}
        (nil))

   (insn 21 20 22 2 (set (reg:SI 37)
           (const_int 1 [0x1])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (jump_insn 22 21 83 2 (set (pc)
           (if_then_else (ltu (subreg:SI (reg:DI 36) 4)
                   (subreg:SI (reg:DI 30) 4))
               (label_ref 24)
               (pc))) "../brew-gcc-build/second.c":3:10 38 {cbranchsi4}
        (nil)
    -> 24)

   (note 83 22 23 3 [bb 3] NOTE_INSN_BASIC_BLOCK)

   (insn 23 83 24 3 (set (reg:SI 37)
           (const_int 0 [0])) "../brew-gcc-build/second.c":3:10 20
   {*movsi_immed}
        (nil))

   (code_label 24 23 84 4 4 (nil) [1 uses])

   (note 84 24 25 4 [bb 4] NOTE_INSN_BASIC_BLOCK)

   (insn 25 84 26 4 (set (subreg:SI (reg:DI 36) 0)
           (plus:SI (subreg:SI (reg:DI 30) 0)
               (subreg:SI (reg:DI 33) 0))) "../brew-gcc-
   build/second.c":3:10 2 {addsi3}
        (expr_list:REG_DEAD (reg:DI 33)
           (expr_list:REG_DEAD (reg:DI 30)
               (nil))))

   (insn 26 25 27 4 (set (reg:SI 38)
           (plus:SI (reg:SI 37)
               (subreg:SI (reg:DI 36) 0))) "../brew-gcc-
   build/second.c":3:10 2 {addsi3}
        (expr_list:REG_DEAD (reg:SI 37)
           (nil)))

   (insn 27 26 28 4 (set (subreg:SI (reg:DI 36) 0)
           (reg:SI 38)) "../brew-gcc-build/second.c":3:10 21
   {*movsi_move}
        (expr_list:REG_DEAD (reg:SI 38)
           (nil)))

   (insn 28 27 29 4 (set (reg:SI 40)
           (mem/c:SI (plus:SI (reg/f:SI 16 ?ap)
                   (const_int 4 [0x4])) [1 a+0 S4 A32])) "../brew-gcc-
   build/second.c":3:10 22 {*movsi_load}
        (nil))

   After that, it replaces the XOR with a move:

   (insn 29 28 30 4 (set (subreg:SI (reg:DI 39) 0)
           (xor:SI (reg:SI 40)
               (reg:SI 40))) "../brew-gcc-build/second.c":3:10 15
   {xorsi3}
        (expr_list:REG_DEAD (reg:SI 40)
           (nil)))

   to:

   (insn 90 29 30 4 (set (subreg:SI (reg:DI 39) 0)
           (reg:SI 54)) "../brew-gcc-build/second.c":3:10 21
   {*movsi_move}
        (nil))

   After this, all that's happening is LRA keeps replaceing reg:SI 54 with
   newer and newer soft-regs (reg:SI 55, then 56, then 57 etc.) until it
   runs out of iterations and blows up.

   Now, I'm certain that I'm doing something wrong and it's not a bug in
   LRA. But what could the problem be? And how can I get closer to said
   problem? Why delete so much of the beginning of the function? And,
   while I understand why an xor(something, same thing) can be replaced by
   a zeroing of a register, that's not what's done here.

   The (hopefully) relevant pieces of machine definition:

   (define_constraint "O"
     "The constant zero"
     (and
       (match_code "const_int")
       (match_test "ival == 0")
     )
   )

   (define_insn "xorsi3"
     [(set
       (match_operand:SI 0 "register_operand" "=r,r,r,r")
       (xor:SI
         (match_operand:SI 1 "register_operand" "r,r,r,r")
         (match_operand:SI 2 "nonmemory_operand" "1,O,r,i")
       )
     )]
     ""
     "@
     %0 <- %1 - %1
     %0 <- %1
     %0 <- %1 ^ %2
     %0 <- %1 ^ (%2)"
   )

   (define_insn "*movsi_move"
     [(set
       (match_operand:SI 0 "register_operand" "=r")
       (match_operand:SI 1 "register_operand" "r")
     )]
     ""
     "%0 <- %1"
     [(set_attr "length" "2")]
   )


   (define_insn "*movsi_immed"
     [(set
       (match_operand:SI 0 "register_operand"  "=r,r")
       (match_operand:SI 1 "immediate_operand"  "O,i")
     )]
     ""
     "@
      %0 <- %0 - %0
      %0 <- %1"
     [(set_attr "length" "2,6")]
   )

   This is quite possibly not enough information for anyone to figure this
   out, so please tell me what else should I include to make things more
   clear?

   Thanks a lot!
   Andras



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-01-11  4:15 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-10  4:48 What's wrong with this RTL? Andras Tantos
2022-01-10  6:19 ` Andrew Pinski
2022-01-11  4:15   ` Andras Tantos

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).