Page 1 of 1

Visual Studio 2022 generates bad code (UPDATE: not any more)

PostPosted: Fri Dec 31, 2021 4:48 pm
by gm_matthew
I recently came across the issue of some games not working in Supermodel when using a Visual Studio 2022 release build. After hours of searching for a root cause, I discovered that it's due to the optimizing compiler generating bad code.

Here is the code that is incorrectly compiled, when ppc603_exception(EXCEPTION_IRQ) is called:

Code: Select all
            if( msr & MSR_IP )
               ppc.npc = 0xfff00000 | 0x0500;
            else
               ppc.npc = 0x00000000 | 0x0500;

            ppc_change_pc(ppc.npc);

If the MSR_IP flag is set, then we should be passing 0xFFF00500 to the ppc_change_pc() function, otherwise we should be passing 0x00000500. But the VS2022 compiler generates code that always passes 0xFFF00500, regardless of whether MSP_IP is set or not.

Here are some relevant excerpts from the generated assembly file:

Code: Select all
; 51   :             if (msr & MSR_IP)

   mov   edx, 1280            ; 00000500H
   bt   ebx, 6
   mov   eax, edx
   mov   ecx, -1047296            ; fff00500H
   cmovb   eax, ecx

; 235  :          {
; 236  :             ppc603_exception(EXCEPTION_IRQ);
; 237  :          }

   jmp   $LN199@ppc603_che

ebx contains the value of MSR and is tested for the MSR_IP flag (0x40); if it is set, eax is set to 0xFFF00500, otherwise it is set to 0x00000500. So far, so good.

Code: Select all
   test   ebx, 64               ; 00000040H
$LN199@ppc603_che:
   cmove   ecx, edx
   mov   DWORD PTR ?ppc@@3UPPC_REGS@@A+136, eax
   add   rsp, 32               ; 00000020H
   pop   rbx
   jmp   ?ppc_change_pc@@YAXI@Z         ; ppc_change_pc


The intention is to set ecx (0xFFF00500) to the value of edx (0x00000500) if the MSR_FLAG is not set. However, the compiler has messed up and is using the wrong compare instruction; instead of checking the carry flag (which is the one that stores the result of a bit test), it is checking the zero flag which, while correct for a regular test instruction, is undefined after a bit test. In this case, ecx is not being set to 0x00000500 and the ppc_change_pc() function is passed the wrong value (it should be noted that ppc.npc is always set to the correct value). Eventually, at some point the PowerPC interpreter fetches the wrong opcode and chaos ensues.

I'm going to switch back to Visual Studio 2019 for the time being since it compiles this code correctly. We shouldn't have to try and work around a bug with the VS2022 compiler.

Re: Visual Studio 2022 generates bad code

PostPosted: Fri Dec 31, 2021 5:50 pm
by Ian
That's pretty damn rare to find such a compiler bug. Should definitely file the bug to Microsoft. They are generally quite fast from what I understand in fixing them.

https://docs.microsoft.com/en-us/visual ... ual-studio

I think you can post it on the community pages too

Re: Visual Studio 2022 generates bad code

PostPosted: Mon Sep 19, 2022 2:02 pm
by Ian
Eric Brumer [MSFT] has posted a new comment on VS2022 compiler bug compiling supermodel emulator

Hi, thanks for the bug report. With the latest upload I confirm that there's incorrect codegen in the compiler. The bug is in a "test -> bt" optimization.
It finds these instructions (written in pseudo-asm code... destinations are on the left):
cc = test ebx, 64
eax = mov adx
eax = cmovne cc_zf, ecx, eax
LN1:
ecx = cmove cc_zf, edx, ecx
... other instructions ...
cc = test ebx, 64
jmp LN1
Of note:
There's a cmove instruction that has two paths into it. Each path has a 'cc = test ebx, 64' on it. The first path is fallthrough from above, and the second path is from the 'jmp LN1' later on.
The first test instruction feeds the cmove, and it also feeds the cmovne.
It looks like we have identified the test -> cmovne and changed that into a bt -> cmovb, but we didn't change the cmove instruction (or the 2nd test), which is what's causing the bad codegen.
We'll see if there's a viable workaround here, but this code is super old and I'm not seeing any recent changes to it. I suspect you're getting unlucky and the issue was exposed due to other optimizations. We'll reply back here as we have a fix ready.
Thanks,
Eric Brumer
Visual C++ Team

Re: Visual Studio 2022 generates bad code

PostPosted: Tue Nov 01, 2022 3:32 pm
by Ian
Feedback Bot has changed the status of VS2022 compiler bug compiling supermodel emulator on Visual Studio Developer Community to Pending Release.

A fix for this issue has been internally implemented and is being prepared for release. We'll update you once it becomes available for download.

Re: Visual Studio 2022 generates bad code

PostPosted: Thu Feb 23, 2023 3:57 am
by Ian
This issue has been marked as closed. So I guess it should compile with vs2022 now lol

Re: Visual Studio 2022 generates bad code

PostPosted: Mon Apr 10, 2023 10:09 am
by gm_matthew
VS2022 64-bit release builds are still not working properly, tested with version 17.5.3 :x

Re: Visual Studio 2022 generates bad code

PostPosted: Mon Apr 10, 2023 10:51 am
by Ian
Same error?

Re: Visual Studio 2022 generates bad code

PostPosted: Mon Apr 10, 2023 11:14 am
by gm_matthew
Ian wrote:Same error?

Yep

Re: Visual Studio 2022 generates bad code

PostPosted: Mon Apr 10, 2023 11:51 am
by Ian
Eric Brumer actually messaged me about this bug on reddit. I'll give him a shout directly to confirm the fix is actually in the latest version.

Re: Visual Studio 2022 generates bad code

PostPosted: Thu Aug 31, 2023 5:44 pm
by gm_matthew
Supermodel now compiles properly in the latest version of VS2022 :D