Understanding peephole2
Georg-Johann Lay
avr@gjlay.de
Wed Nov 20 10:27:02 GMT 2024
Consider the following RTL peephole from avr.md:
(define_peephole2 ; avr.md:5387
[(match_scratch:QI 3 "d")
(parallel [(set (match_operand:ALL4 0 "register_operand" "")
(ashift:ALL4 (match_operand:ALL4 1
"register_operand" "")
(match_operand:QI 2 "const_int_operand"
"")))
(clobber (reg:CC REG_CC))])]
""
[(parallel [(set (match_dup 0)
(ashift:ALL4 (match_dup 1)
(match_dup 2)))
(clobber (match_dup 3))
(clobber (reg:CC REG_CC))])])
As far as I understand, its purpose is to provide a QImode
scratch register provided such a scratch is available.
However, in the .peephole2 RTL dump with -da I see the following:
Splitting with gen_peephole2_100 (avr.md:5387)
...
(insn 24 8 15 2 (parallel [
(set (reg:SI 22 r22 [orig:47 _3 ] [47])
(ashift:SI (reg:SI 20 r20 [orig:48 x ] [48])
(const_int 7 [0x7])))
(clobber (reg:QI 24 r24))
(clobber (reg:CC 36 cc))
])
(nil))
That is, the scratch r24:QI is overlapping the output in
r22:SI. All hard registers are 8-bit regs and hence r22:SI
extends from r22...r25.
A scratch that overlaps the operands is pretty much useless
or even plain wrong. recog.cc::peep2_find_free_register()
has this comment: /* Don't use registers set or clobbered by the insn. */
from = peep2_buf_position (peep2_current + from);
to = peep2_buf_position (peep2_current + to);
gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
while (from != to)
{
gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
/* Don't use registers set or clobbered by the insn. */
FOR_EACH_INSN_DEF (def, peep2_insn_data[from].insn)
SET_HARD_REG_BIT (live, DF_REF_REGNO (def));
from = peep2_buf_position (from + 1);
}
So it this bogus in that it assumes all registers extend only
over one hard reg?
FYI, the purpose is to provide a scratch without increasing the register
pressure (which "match_scratch" would do). Therefore, the RTL peephole
is used instead of forcing reload to come up with a scratch.
More specifically, I see this with
$ avr-gcc bogus-peep2.c -S -Os -da
long ashl32_7 (int i, long x)
{
return x << 7;
}
with the attached WIP patch atop trunk b222ee10045d.
Johann
Target: avr
Configured with: ../../source/gcc-master/configure --target=avr
--disable-nls --with-dwarf2 --with-gnu-as --with-gnu-ld --disable-shared
--enable-languages=c,c++
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 15.0.0 20241119 (experimental) (GCC)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: bogus-peep2.diff
Type: text/x-patch
Size: 9428 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc/attachments/20241120/fb5ab0a1/attachment-0001.bin>
-------------- next part --------------
;; Function ashl32_7 (ashl32_7, funcdef_no=0, decl_uid=1900, cgraph_uid=1, symbol_order=0)
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
ashl32_7
Dataflow summary:
def_info->table_size = 0, use_info->table_size = 0
;; fully invalidated by EH 0 [r0] 1 [r1] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 26 [r26] 27 [r27] 30 [r30] 31 [r31] 33 [__SP_H__] 35 [argH] 36 [cc]
;; hardware regs used 32 [__SP_L__]
;; regular block artificial uses 32 [__SP_L__]
;; eh block artificial uses 32 [__SP_L__] 34 [argL]
;; entry block defs 8 [r8] 9 [r9] 10 [r10] 11 [r11] 12 [r12] 13 [r13] 14 [r14] 15 [r15] 16 [r16] 17 [r17] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; exit block uses 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; regs ever live 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 36 [cc]
;; ref usage r8={1d} r9={1d} r10={1d} r11={1d} r12={1d} r13={1d} r14={1d} r15={1d} r16={1d} r17={1d} r18={1d} r19={1d} r20={1d,1u} r21={1d,1u} r22={2d,3u} r23={2d,3u} r24={2d,2u} r25={2d,2u} r32={1d,2u} r36={1d}
;; total ref usage 38{24d,14u,0e} in 3{3 regular + 0 call} insns.
( )->[0]->( 2 )
;; bb 0 artificial_defs: { d-1(8){ }d-1(9){ }d-1(10){ }d-1(11){ }d-1(12){ }d-1(13){ }d-1(14){ }d-1(15){ }d-1(16){ }d-1(17){ }d-1(18){ }d-1(19){ }d-1(20){ }d-1(21){ }d-1(22){ }d-1(23){ }d-1(24){ }d-1(25){ }d-1(32){ }}
;; bb 0 artificial_uses: { }
;; lr in
;; lr use
;; lr def 8 [r8] 9 [r9] 10 [r10] 11 [r11] 12 [r12] 13 [r13] 14 [r14] 15 [r15] 16 [r16] 17 [r17] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; live in
;; live gen 8 [r8] 9 [r9] 10 [r10] 11 [r11] 12 [r12] 13 [r13] 14 [r14] 15 [r15] 16 [r16] 17 [r17] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; live kill
;; lr out 20 [r20] 21 [r21] 22 [r22] 23 [r23] 32 [__SP_L__]
;; live out 20 [r20] 21 [r21] 22 [r22] 23 [r23] 32 [__SP_L__]
( 0 )->[2]->( 1 )
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u-1(32){ }}
;; lr in 20 [r20] 21 [r21] 22 [r22] 23 [r23] 32 [__SP_L__]
;; lr use 20 [r20] 21 [r21] 22 [r22] 23 [r23] 32 [__SP_L__]
;; lr def 22 [r22] 23 [r23] 24 [r24] 25 [r25] 36 [cc]
;; live in 20 [r20] 21 [r21] 22 [r22] 23 [r23] 32 [__SP_L__]
;; live gen 22 [r22] 23 [r23] 24 [r24] 25 [r25]
;; live kill 36 [cc]
;; lr out 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; live out 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
( 2 )->[1]->( )
;; bb 1 artificial_defs: { }
;; bb 1 artificial_uses: { u-1(22){ }u-1(23){ }u-1(24){ }u-1(25){ }u-1(32){ }}
;; lr in 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; lr use 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; lr def
;; live in 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; live gen
;; live kill
;; lr out
;; live out
Finding needed instructions:
Adding insn 20 to worklist
Adding insn 13 to worklist
Finished finding needed instructions:
processing block 2 lr out = 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
Adding insn 17 to worklist
Splitting with gen_peephole2_100 (avr.md:5388)
scanning new insn with uid = 22.
deleting insn with uid = 17.
verify found no changes in insn with uid = 22.
starting the processing of deferred insns
ending the processing of deferred insns
ashl32_7
Dataflow summary:
;; fully invalidated by EH 0 [r0] 1 [r1] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 26 [r26] 27 [r27] 30 [r30] 31 [r31] 33 [__SP_H__] 35 [argH] 36 [cc]
;; hardware regs used 32 [__SP_L__]
;; regular block artificial uses 32 [__SP_L__]
;; eh block artificial uses 32 [__SP_L__] 34 [argL]
;; entry block defs 8 [r8] 9 [r9] 10 [r10] 11 [r11] 12 [r12] 13 [r13] 14 [r14] 15 [r15] 16 [r16] 17 [r17] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; exit block uses 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; regs ever live 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 36 [cc]
;; ref usage r8={1d} r9={1d} r10={1d} r11={1d} r12={1d} r13={1d} r14={1d} r15={1d} r16={1d} r17={1d} r18={1d} r19={1d} r20={1d,1u} r21={1d,1u} r22={2d,3u} r23={2d,3u} r24={3d,2u} r25={2d,2u} r32={1d,2u} r36={1d}
;; total ref usage 39{25d,14u,0e} in 3{3 regular + 0 call} insns.
(note 1 0 5 NOTE_INSN_DELETED)
;; basic block 2, loop depth 0, count 1073741824 (estimated locally, freq 1.0000), maybe hot
;; prev block 0, next block 1, flags: (REACHABLE, RTL, MODIFIED)
;; pred: ENTRY [always] count:1073741824 (estimated locally, freq 1.0000) (FALLTHRU)
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u-1(32){ }}
;; lr in 20 [r20] 21 [r21] 22 [r22] 23 [r23] 32 [__SP_L__]
;; lr use 20 [r20] 21 [r21] 22 [r22] 23 [r23] 32 [__SP_L__]
;; lr def 22 [r22] 23 [r23] 24 [r24] 25 [r25] 36 [cc]
;; live in 20 [r20] 21 [r21] 22 [r22] 23 [r23] 32 [__SP_L__]
;; live gen 22 [r22] 23 [r23] 24 [r24] 25 [r25]
;; live kill 36 [cc]
(note 5 1 18 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 18 5 3 2 NOTE_INSN_PROLOGUE_END)
(note 3 18 4 2 NOTE_INSN_DELETED)
(note 4 3 22 2 NOTE_INSN_FUNCTION_BEG)
(insn 22 4 13 2 (parallel [
(set (reg:SI 22 r22 [orig:46 _2 ] [46])
(ashift:SI (reg:SI 20 r20 [orig:47 x ] [47])
(const_int 7 [0x7])))
(clobber (reg:QI 24 r24))
(clobber (reg:CC 36 cc))
]) "bogus-peep2.c":3:14 -1
(nil))
(insn 13 22 19 2 (use (reg/i:SI 22 r22)) "bogus-peep2.c":4:1 -1
(nil))
(note 19 13 20 2 NOTE_INSN_EPILOGUE_BEG)
(jump_insn 20 19 21 2 (return) "bogus-peep2.c":4:1 -1
(nil)
-> return)
;; succ: EXIT [always] count:1073741824 (estimated locally, freq 1.0000)
;; lr out 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; live out 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
(barrier 21 20 16)
(note 16 21 0 NOTE_INSN_DELETED)
More information about the Gcc
mailing list