Hi, the use of inline assembly may lead to the optimizer being extra / overly careful. I'm not sure if the peephole optimizer looks into the resulting inline assembly or if it just sees a black box labeled "inline assembly inside" and assumes the worst: 'a' is read in there.
notUsed('a') asserts that (the value assigned to) register 'a' is... well... not used (as in: read) later on. notUsed() is true only if the compiler can prove that whatever value is stored in 'a' is not read later on - on any code path. If the compiler / optimizer cannot be sure that 'a' is not read later on (i.e., if the compiler has to assume that 'a' may be read later on), the optimization in question must not be applied: It could be incorrect and change the observable behavior / semantics of the program. Typically, only explicit or implicit writes to the register on all possible later code path convince the optimizer that the value / register is not used. Exceptions may include return statements (if the register is not used to return values and is handled as to-be saved by the caller) or inescapable endless loops. If you have code that is properly optimized, just add an empty chunk of inline assembly after the optimized code. If it stops being optimized, inline assembly is likely the reason. (If not, then not ;-).) Best regards Raphael Am Mo., 16. März 2020 um 17:37 Uhr schrieb Basil Hussain < ba...@stasisleak.uk>: > 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 >
_______________________________________________ Sdcc-user mailing list Sdcc-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sdcc-user