From: Andras Tantos <andras@tantosonline.com>
To: gcc@gcc.gnu.org
Subject: What's wrong with this RTL?
Date: Sun, 09 Jan 2022 20:48:25 -0800 [thread overview]
Message-ID: <f7b7a10283bdfdc90f0142772c9c1f866d1585cd.camel@tantosonline.com> (raw)
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
next reply other threads:[~2022-01-10 4:48 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-10 4:48 Andras Tantos [this message]
2022-01-10 6:19 ` Andrew Pinski
2022-01-11 4:15 ` Andras Tantos
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f7b7a10283bdfdc90f0142772c9c1f866d1585cd.camel@tantosonline.com \
--to=andras@tantosonline.com \
--cc=gcc@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).