open-watcom / open-watcom-v2

Open Watcom V2.0 - Source code repository, Wiki, Latest Binary build, Archived builds including all installers for download.
Other
985 stars 160 forks source link

Code generator - wrong optimization of uint64_t addition #614

Open gmaxwell opened 4 years ago

gmaxwell commented 4 years ago

I'm getting incorrect additions of uint64_t as a result of optimization.

Here is a simplified test case:

static const uint64_t ONE = 1UL;
uint64_t funbad(uint64_t a){return ((uint64_t)1UL) + a + ((uint64_t)1UL);}
uint64_t fungood(uint64_t a){return ONE + a + ONE;}
int main(void){
    uint64_t good, bad;
    good = fungood(-1);
    bad = funbad(-1);
    printf("%016llx %016llx %d\n", bad, good, bad==good);
    return 0;
}

I did not simplify it as much as possible because I wanted it to be completely clear that this isn't just some confusion about promotion rules. E.g. a version of funbad that does a+2UL is also good. Swapping everything to 32-bit also fixes it.

On a 64-bit Linux host, running 014d6866b392d980c7f70bcd4441c621ae1d1436

$ wcl -v | head -n2
Open Watcom C/C++ x86 16-bit Compile and Link Utility
Version 2.0 beta Aug 15 2020 00:02:21 (64-bit)
$ wcl -0 -lr a.c && dosbox ./a.exe
0000000000010001 0000000000000001 0

The example works fine with -od set.

Disassembly:

0000                funbad_:
0000  50                push        ax
0001  B8 04 00              mov     ax,0x0004
0004  E8 00 00              call        __STK
0007  58                pop     ax
0008  56                push        si
0009  89 D6             mov     si,dx
000B  83 C6 01              add     si,0x0001
000E  83 D1 00              adc     cx,0x0000
0011  83 D3 00              adc     bx,0x0000
0014  15 00 00              adc     ax,0x0000
0017  83 C2 02              add     dx,0x0002
001A  83 D1 00              adc     cx,0x0000
001D  83 D3 00              adc     bx,0x0000
0020  15 00 00              adc     ax,0x0000
0023  5E                pop     si
0024  C3                ret
jmalak commented 4 years ago

Thanks for bug report. The same problem with 32-bit. It is old bug same behaviour with OW1.9. It looks like bug in Code Generator that optimizer doesn't eliminate old code but combine it strange way with optimized one. I will fix it.

I reproduced it on all supported platforms.

below is minimised test sample

``` typedef unsigned long long uint64_t; uint64_t funbad(uint64_t a){return ((uint64_t)1UL) + a + ((uint64_t)1UL);} ``` and compiler command line `wcc -s bug.c` disassembled code ``` _TEXT SEGMENT BYTE PUBLIC USE16 'CODE' ASSUME CS:_TEXT, DS:DGROUP, SS:DGROUP funbad_: push si mov si,dx add si,1 adc cx,0 adc bx,0 adc ax,0 add dx,2 adc cx,0 adc bx,0 adc ax,0 pop si ret _TEXT ENDS ```
gmaxwell commented 4 years ago

Thank you for paying attention to this. :) I'm happy to test out any fixes though I assume you've got it with the reproduction.

jmalak commented 4 years ago

It looks like it has similar symptoms as issue #515. It looks like incorrectly deleted code generator internal instructions. In your case following instruction should be deleted from code pipeline, but it is not.

        mov             si,dx
        add             si,1
        adc             cx,0
        adc             bx,0
        adc             ax,0