<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/93870>93870</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Wrong multiplication order with optimization flag ON
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          bfraboni
      </td>
    </tr>
</table>

<pre>
    Hello LLVM team,

I am not entirely sure this is an actual bug, but the following code does not enforce the multiplication order compiled with clang and optimization level 1 to 3. I feel this is simple enough that is should return the right result.
````c++
#include <iostream>

struct Vec2 {
    float x, y;
};

// wrong result for SA(a,a,b)
float signedAreaBroken(const Vec2& a, const Vec2& b, const Vec2& c) {
    return (((a.x - c.x) * (b.y - c.y)) - ((b.x - c.x) * (a.y - c.y)));
}

// correct result for SA(a,a,b)
float signedAreaRobust(const Vec2& a, const Vec2& b, const Vec2& c) {   
    const float u = (a.x - c.x) * (b.y - c.y);
    const float v = (b.x - c.x) * (a.y - c.y);
    return u - v;
}

int main() {
    const Vec2 b = {0.5f, 0.5f}, a = {1.4f, 0.7f};

    printf("robust(a,a,b)=%.12f\nbroken(a,a,b)=%.12f\nrobust(a,b,a)=%.12f\nbroken(a,b,a)=%.12f\n", 
        signedAreaRobust(a,a,b), // 0
        signedAreaBroken(a,a,b), // not 0
        signedAreaRobust(a,b,a), // 0 
        signedAreaBroken(a,b,a)); // 0
    
    return 0;
}
````

The scalar version in godbolt does not explain at all why the result between the two functions would be different, the generated instructions are identical: https://godbolt.org/z/5d7P6sxhE

However, using the flag -mavx2 gives more info on registers: https://godbolt.org/z/z61zj9d5d
And it seems that the second multiplication (instruction l.13) is done in reversed order for `signedAreaBroken`, in comparison to the one for `signedAreaRobust` (instruction l.28).
I can't explain why breaking down the same equation in two separate variables would enforce the order of operations.

Is that an expected behavior ? If yes, is there any good resources on how to enforce multiplication order with clang and optimization ON ?

Thank you 🙏 

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJykVtuS2jgTfhpx0zUuIw8YX_hiGH4qqcqfbGW3stc6tG0lssTqAMM8_ZZsEyAw2dTulAYoqQ9ff93qFvNetQaxJos1WWxmLIbOupo3jnFr1IxbeazfodYWPnz48n8IyHpCn0m-IfnT-PkeWA_GBkATlEN9BB8dQuiUB-WBGWAiRKaBx5bQZ-AxQOgQGqu1PSjTgrASQVr0k5nGOoGDTB91UDutBAvKGrBOogNh-53SKOGgQgdCM9MCMxLsLqhevY6iGveoYQ7BQpHBe2gQ9XdMXvU7jYDGxraD0LEw7HY2agkOQ3RmcO9U2wVw6KMO2RTzMv--BKHrtMYDWigjdJQIpHhW1geXuCr-d8mVDy6KAF9QUCDlpAkA0GjLArwkfo6kOJksN-ffk5MtoVs4OGvaCRc01sHvT4SuGKHP6Z8TWo3io9Uhw_LJIVs7-w0NoSthjR9hELqEpATXW_x2SxBaXYOemCJ0NS6WvcADiOxlkKRP6YRnx2HvmEDRCh4mcX5Hll3LpnVJxS0PwjqHIvwLJj5bHn34j0wAwJmMUWT0E4EUG_gVRor1fQv7k4V_5Km4TUiEB9i_RZ0yAXqmzJCGHxJ6DhP4CKBc59miSRQM3-Um_WSns3n2OJ2VzW2xJos7p0xoBl_UnTi_Sk-xIXSRzWlDFs-Gnwr0bZErK3wU-5mV-yKE0gT8DDT93SmPKxxJYSy8_C3F9d0Azoqpwb2p_PluaBde38S7vhvxUB13IN8UTH6nWC763GVS_-gQvGCaOdij86nVKgOtldzqcNHEX3aaKQMsANMaDt1xbKjjReUYDohjjw0HC000InVtD4ehBXMEqZoGHZqQ4k9yLRp0LKAEZcY2Oigwh6BkGj2CaVI8QRfCzpNiahETsMy6ltDtK6HbhSx_W_qX7qovv7MH3KNLvqJPI2kYUJq18NCz_QuFVu3RQ2-TN9NYsAYctsoHdP5XvL4u569fK7mQo78nI0EF8Ii9H-dPcuhRWCN_HHqEri4iBp3Ni3RxlQdpTYIDLmH3KKf5mNogWeY31bHMU3zKDAOUOeWtSeMxeU6GbtSmclzmtxCG3pGd5r9ghtDynPSUbe6QfUtMSnsYE-1Zj4B_xTEqZYbMe9yxlFXYM6cY13gqgctXwBiWbcDuUgmkvGdXL5CJQ2YSBBSpSDh2bK9SSMUW3jdwRD9En0TRITBzhNbaNO69jU6gTznt7CFRcnJ-9_nxs1fHp4_J3_V9YeYbHG0Ess1JtSVVRVbb6QrOZF3IqqjYDOt5OS_zqiqKxayrq7JshKhwxQs257QqGX8sxLxaMJ5LvmIzVdOcPuaLIqd5Tuc0W1IsZV7OWVPReS45ecyxZ0pnWu_7VIgz5X3EuipWZT7TjKP2w6OPUoMHGA5TU1xsZq5OOg88tp485lr54M9Wggoa6z-HB8jb9FyRMtyjTx9n0en6h3uiQhd5JmxP6Da5mL4eds5-RREI3Q7APKHbEfi-pn8HAAD__wKIO04">