The PIC14 backend misses an opportunity to generate DECFSZ for certain 8-bit decrement-and-branch loops.
The existing ifxForOp() matching logic requires the temporary's liveFrom to be at or after the subtraction instruction. This prevents the optimization in cases where the temporary was created earlier, even though the decrement result is used by the immediately following conditional branch.
I have implemented a small extension to genDjnz() that recognizes this pattern while retaining the existing optimization path.
Implementation
The patch:
Extends genDjnz() with an additional register requirement for the new matching path.
Requires a single-byte result mapped to a register.
Checks that the result and left operand are identical.
Requires subtraction by the literal value 1.
Requires an immediately following, matching IFX with a true branch and no false branch.
Checks that the temporary's liveTo does not extend beyond the matching IFX instruction.
Preserves the original genDjnz() behavior for previously recognized patterns.
Only src/pic14/gen.c is modified.
Reproducer
volatile unsigned char result;
void test_djnz_signed(signed char count)
{
do {
result++;
} while (--count);
}
Original SDCC SVN r17110 (PIC16F1939):
BANKSEL r0x1001
DECF r0x1001,F
MOVF r0x1001,W
BTFSS STATUS,2
GOTO _00105_DS_
With the proposed patch:
BANKSEL r0x1001
DECFSZ r0x1001,F
GOTO _00105_DS_
The decrement-and-branch sequence is reduced from four instructions to two, excluding the unchanged BANKSEL.
The same DECFSZ optimization was also confirmed for an unsigned char loop counter.
Validation
The following checks were performed:
Successfully built with SDCC SVN r17110.
Verified code generation for PIC16F1939 and PIC16F18855.
Positive regression examples generate the expected DECFSZ instructions.
Volatile decrement cases remain excluded from the extended optimization.
PIC16F1939 runtime regression tests passed in simulation using COFF-based debugging, with no failures observed.
A controlled fault-injection test in an isolated diagnostic compiler confirmed that violating the liveTo boundary prevents the optimization and falls back to the ordinary decrement sequence.
The patch applies cleanly to the unmodified r17110 source tree using patch --dry-run -p1.
The fault-injection test verifies the rejection and fallback path. It is not a naturally occurring iCode counterexample.
The patch is limited to the PIC14 code generator and does not modify the pCode optimizer or register allocation implementation.
I would appreciate a review of the extended IFX matching conditions and the register/liveness safety checks.
Thank you.
Thanks for the patch. However, I don't feel comfortable adding optimizations to pic14 at the moment. The port has no maintainer, and worse, we currently can't even run regression tests ([bugs:#4241]). IMO, before adding optimizations, we should get pic14 to run the regression tests, and not fail too many of them (ideally we'd get to 0 failures, but that might not be realistic for SDCC 4.7.0).
Related
Bugs: #4241
Ticket moved from /p/sdcc/bugs/4239/
Can't be converted: