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