Reproduction:
#include "debug.h"
typedef __INT24_TYPE__ i24;
int main()
{
volatile int24_t input = 5;
int24_t foo = input;
int24_t bar = -foo;
int24_t quux = -foo + 1;
dbg_printf("%d", bar);
dbg_printf("%d", quux);
}
Compiling this under -O0 prints the expected -5, -4, while compiling under -O3 prints -5, -5.
I suspect this is due to the carry bit being retained between computing bar=-foo via sbc 0 foo followed by quux=-foo+1 via sbc 1 foo, which actually computes 1-foo-1 due to the retained carry bit. -O0 avoids this by including or a, a after computing bar.
Should be able to see -O0 clearing the carry flag with or a, a while -O3 doesn't by viewing assembly generated for this:
typedef __INT24_TYPE__ i24;
extern void consume(i24, i24);
void test(i24 foo)
{
consume(-foo, 1 - foo);
}
On clang version 19.1.0, commit ef28e9c54cd1333a6091ab2ffbd315b465fc5090
Reproduction:
Compiling this under
-O0prints the expected -5, -4, while compiling under-O3prints -5, -5.I suspect this is due to the carry bit being retained between computing
bar=-fooviasbc 0 foofollowed byquux=-foo+1viasbc 1 foo, which actually computes1-foo-1due to the retained carry bit.-O0avoids this by includingor a, aafter computingbar.Should be able to see -O0 clearing the carry flag with
or a, awhile -O3 doesn't by viewing assembly generated for this:On clang version 19.1.0, commit
ef28e9c54cd1333a6091ab2ffbd315b465fc5090