diff options
author | Jeff Law <jlaw@ventanamicro.com> | 2024-07-03 12:47:31 -0600 |
---|---|---|
committer | Jeff Law <jlaw@ventanamicro.com> | 2024-07-03 12:47:31 -0600 |
commit | e5f73853ae78d4e9ae434c707a12da1494459b24 (patch) | |
tree | 30be8b1e052d122ee7268172f21d8659b864f214 /gcc/reorg.cc | |
parent | ad2206d576603c94b0c1778c84b7f43fbf8a13b4 (diff) | |
download | gcc-e5f73853ae78d4e9ae434c707a12da1494459b24.zip gcc-e5f73853ae78d4e9ae434c707a12da1494459b24.tar.gz gcc-e5f73853ae78d4e9ae434c707a12da1494459b24.tar.bz2 |
[committed] Fix previously latent bug in reorg affecting cris port
The late-combine patch has triggered a previously latent bug in reorg.
Basically we have a sequence like this in the middle of reorg before we start
relaxing delay slots (cris-elf, gcc.dg/torture/pr98289.c)
> (insn 67 49 18 (sequence [
> (jump_insn 50 49 52 (set (pc)
> (if_then_else (ne (reg:CC 19 ccr)
> (const_int 0 [0]))
> (label_ref:SI 30)
> (pc))) "j.c":10:6 discrim 1 282 {*bnecc}
> (expr_list:REG_DEAD (reg:CC 19 ccr)
> (int_list:REG_BR_PROB 7 (nil)))
> -> 30)
> (insn/f 52 50 18 (set (mem:SI (reg/f:SI 14 sp) [1 S4 A8])
> (reg:SI 16 srp)) 37 {*mov_tomemsi}
> (nil))
> ]) "j.c":10:6 discrim 1 -1
> (nil))
>
> (note 18 67 54 [bb 3] NOTE_INSN_BASIC_BLOCK)
>
> (note 54 18 55 NOTE_INSN_EPILOGUE_BEG)
>
> (jump_insn 55 54 56 (return) "j.c":14:1 228 {*return_expanded}
> (nil)
> -> return)
>
> (barrier 56 55 43)
>
> (note 43 56 65 [bb 4] NOTE_INSN_BASIC_BLOCK)
>
> (note 65 43 30 NOTE_INSN_SWITCH_TEXT_SECTIONS)
>
> (code_label 30 65 8 5 6 (nil) [1 uses])
>
> (note 8 30 61 [bb 5] NOTE_INSN_BASIC_BLOCK)
So at a high level the things to note are that insn 50 conditionally jumps
around insn 55. Second there's a SWITCH_TEXT_SECTIONS note between insn 50 and
the target label for insn 50 (code_label 30).
reorg sees the conditional jump around the unconditional jump/return and will
invert the jump and retarget the original jump to an appropriate location. In
this case generating:
> (insn 67 49 18 (sequence [
> (jump_insn 50 49 52 (set (pc)
> (if_then_else (eq (reg:CC 19 ccr)
> (const_int 0 [0]))
> (label_ref:SI 68)
> (pc))) "j.c":10:6 discrim 1 281 {*beqcc}
> (expr_list:REG_DEAD (reg:CC 19 ccr)
> (int_list:REG_BR_PROB 1073741831 (nil)))
> -> 68)
> (insn/s/f 52 50 18 (set (mem:SI (reg/f:SI 14 sp) [1 S4 A8])
> (reg:SI 16 srp)) 37 {*mov_tomemsi}
> (nil))
> ]) "j.c":10:6 discrim 1 -1
> (nil))
>
> (note 18 67 54 [bb 3] NOTE_INSN_BASIC_BLOCK)
>
> (note 54 18 43 NOTE_INSN_EPILOGUE_BEG)
>
> (note 43 54 65 [bb 4] NOTE_INSN_BASIC_BLOCK)
>
> (note 65 43 8 NOTE_INSN_SWITCH_TEXT_SECTIONS)
>
> (note 8 65 61 [bb 5] NOTE_INSN_BASIC_BLOCK)
[ ... ]
Where the new target of the jump is a return statement later in the IL.
Note that we now have a SWITCH_TEXT_SECTIONS note that is not immediately
preceded by a BARRIER. That triggers an assertion in the dwarf2 code. Removal
of the BARRIER is inherent in this optimization.
The fix is simple, we avoid this optimization when there's a
SWITCH_TEXT_SECTIONS note between the conditional jump insn and its target.
Thankfully we already have a routine to test for this in reorg, so we just need
to call it appropriately. The other approach would be to drop the note which I
considered and discarded.
We don't have great coverage for delay slot targets. I've tested arc, cris,
fr30, frv, h8, iq2000, microblaze, or1k, sh3 visium in my tester as crosses
without new regressions, fixing one regression along the way. Bootstrap &
regression testing on sh4 and hppa will take considerably longer.
gcc/
* reorg.cc (relax_delay_slots): Do not optimize a conditional
jump around an unconditional jump/return in the presence of
a text section switch.
Diffstat (limited to 'gcc/reorg.cc')
-rw-r--r-- | gcc/reorg.cc | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/gcc/reorg.cc b/gcc/reorg.cc index 99228a2..633099c 100644 --- a/gcc/reorg.cc +++ b/gcc/reorg.cc @@ -3409,7 +3409,8 @@ relax_delay_slots (rtx_insn *first) && next && simplejump_or_return_p (next) && (next_active_insn (as_a<rtx_insn *> (target_label)) == next_active_insn (next)) - && no_labels_between_p (insn, next)) + && no_labels_between_p (insn, next) + && !switch_text_sections_between_p (insn, next_active_insn (next))) { rtx label = JUMP_LABEL (next); rtx old_label = JUMP_LABEL (delay_jump_insn); |