https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127404
Bug ID: 127404
Summary: [avr] missed insn combine transformation (subreg
related?)
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: gjl at gcc dot gnu.org
Target Milestone: ---
Created attachment 65593
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65593&action=edit
x.c: C test case
int val;
long i32;
long volatile v32;
long f32 (void);
void func_1 (void)
{
int i = f32();
if (i & 1)
val = i;
}
void func_2 (void)
{
int i = v32;
if (i & 1)
val = i;
}
void func_3 (void)
{
int i = i32;
if (i & 1)
val = i;
}
$ avr-gcc -mmcu=atmega128 -S x.c -Os -dp -da
In this test case, the expected code for the bit test is a bit-test-and-skip
instruction, which is actually generated for func_3:
sbrs r24,0 ; 24 [c=4 l=2] *sbrx_branchhi
rjmp .L13
In func_1 and func_2 however, combine fails to find this and the outcome is a
code that requires 2 extra registers and needs 5 instructions, even though the
very test code is exactly the same:
mov r18,r24 ; 38 [c=4 l=2] *andqi3/3
andi r18,1<<0
ldi r19,0 ; 39 [c=4 l=1] movqi_insn/0
or r18,r19 ; 30 [c=8 l=1] cmphi3/1
breq .L7 ; 31 [c=4 l=1] branch
The combine dump shows for func_3:
Trying 7 -> 8:
7: {r47:HI=r45:HI&0x1;clobber scratch;}
8: {pc={(r47:HI==0)?L13:pc};clobber scratch;}
REG_DEAD r47:HI
REG_BR_PROB 536870913
Failed to match this instruction:
...
Successfully matched this instruction:
(set (pc)
(if_then_else (eq (zero_extract:HI (reg/v:HI 45 [ i ])
(const_int 1 [0x1])
(const_int 0 [0]))
(const_int 0 [0]))
(label_ref:HI 13)
(pc)))
allowing combination of insns 7 and 8
original costs 8 + 12 = 20
replacement cost 6
with insns:
(insn 7 6 8 2 (parallel [
(set (reg:HI 47 [ _2 ])
(and:HI (reg/v:HI 45 [ i ])
(const_int 1 [0x1])))
(clobber (scratch:QI))
]) "x.c":23:11 625 {andhi3}
(nil))
(jump_insn 8 7 9 2 (parallel [
(set (pc)
(if_then_else (eq (reg:HI 47 [ _2 ])
(const_int 0 [0]))
(label_ref:HI 13)
(pc)))
(clobber (scratch:QI))
]) "x.c":23:8 892 {cbranchhi4_insn}
In func_1 and func_2 however, the AND insn reads
(insn 8 6 9 2 (parallel [
(set (reg:HI 46 [ _2 ])
(and:HI (subreg:HI (reg:SI 43 [ _1 ]) 0)
(const_int 1 [0x1])))
(clobber (scratch:QI))
]) "x.c":9:11 625 {andhi3}
(nil))
Shouldn't it be possible to combine that, too?
Target: avr
Configured with: .../configure --target=avr --disable-nls --with-dwarf2
--with-gnu-as --with-gnu-ld --enable-languages=c,c++
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 17.0.0 20260912 (experimental) (GCC)