Hi all,
Sometimes, for reasons unclear to me, SDCC's optimiser fails to
optimise simple C statements doing register bit set/clear operations
in to the appropriate STM8 bset/bres instructions.
Here's the example I noticed today. The C code, and the ASM it became:
FLASH_NCR2 &= ~(1U << FLASH_NCR2_NPRG);
ld a, 0x505c
and a, #0xfe
ld 0x505c, a
It's not "bres 0x505c, #0" like it really should be. What's ironic is
that the immediately preceding line of C is a bit set operation (on
FLASH_CR2 reg), and that got optimised to bset, but this didn't.
I thought I would dig a little into the workings of the peephole
optimiser to try and find out why this particular optimisation didn't
happen. I believe the relevant optimiser rule is this one:
replace restart {
ld a, %1
and a, #0xfe
ld %1, a
} by {
bres %2, #0
; peephole 19-0 replaced and by bres.
} if notUsed('a'), operandsLiteral(%1), immdInRange(0 65535 '+' 0 %1 %2)
I see there are several conditions attached. It is obvious that the last
two are satisfied (register address is literal value of 0x505c and
within 0-65535). I am not so sure about the first.
The description of 'notUsed' (according to comment in SDCCpeeph.c) is
"if value in register is not read again". What is the definition of
this? Is it meaning that the register in question is read, but only if
not first modified? The next use of the A register in this function is
where I have some inline assembly, which first thing unconditionally
does a "push a" (in case it was being used). For the peephole optimiser,
does this count as a read from that register?
Regards,
Basil
P.S. Can someone explain why the match part of the rule uses "%1" for
the address literal, but the substitution uses "%2"? Where does "%2"
come from? Is it an output parameter from immdInRange?
_______________________________________________
Sdcc-user mailing list
Sdcc-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sdcc-user