The following code should generate something like
ld l, 4(ix) ld h, 5(ix) ld a, (hl) xor 1 ld (hl), a
but instead loads (hl) into de, then d into a then xors a with 1 then loads both back into (hl). Setting high optimisations doesn't improve things. If the target variable is 8bit then it generates fairly sensible code.
struct foo
{
int bar;
int baz;
};
int wibble(struct foo *p)
{
p->bar ^=1;
return 1;
}
With 16bit values it also makes a second mess up in the case where p is computed
The example below produces the bizarre
ld de,#_foobar add hl,de
;crap.c:12: p->baz^=1;
inc hl
inc hl
push hl
ld d,(hl)
inc hl
ld e,(hl)
pop hl
rather than just generating a matching dec hl, for that matter just storing them the other way around. Although I guess if the first bug was fixed so it didn't do the 16bit messing around the second would vanish.
struct foo
{
int bar;
int baz;
};
struct foo foobar[4];
int wibble(int n)
{
struct foo *p = &foobar[n];
p->baz^=1;
return 1;
}
I do have another more complex example that writes the following utter garbage
;tty.c:415: t->flag ^= TTYF_DISCARD;
ld l,-4 (ix)
ld h,-3 (ix)
ld a,(hl)
xor a, #0x02
ld l,-4 (ix)
ld h,-3 (ix)
ld (hl),a
even when optimising, but I've not found a good way to distill it out into a simple example. I can send you the entire build tree however if you want.
The generated code is inefficient, but correct, so I'll reclassify this as a feature request. Probably something to look into after the early 2015 release. If it turns out hard to do in code generation this looks like it would still be easy to do the optimization in the peephole optimizer.
Philipp
Ticket moved from /p/sdcc/bugs/2341/
Can't be converted:
I just checked current SDCC [r11285]. The generated code for wibble() looked better. Then, in [r11286] to [r11288], I implemented another small improvement in register allocation, that helps here.