[Bug d/98607] New: GDC merging computations but rounding mode has changed

guillaume.piolat at gmail dot com gcc-bugzilla@gcc.gnu.org
Fri Jan 8 20:22:59 GMT 2021


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98607

            Bug ID: 98607
           Summary: GDC merging computations but rounding mode has changed
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: d
          Assignee: ibuclaw at gdcproject dot org
          Reporter: guillaume.piolat at gmail dot com
  Target Milestone: ---

Created attachment 49923
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49923&action=edit
Repro file

# Description

It seems GCC optimize common sub-expressions despite they are separated by a
__builtin_ia32_ldmxcsr call, which changes SSE rounding mode.


# Compiler version

GDC 10.2


# Godbolt

See on Godbolt: https://godbolt.org/z/c7EKfY
You can notice how only one cvtps2dq instruction is generated.



# Reproduce failure

Run this D program with GDC 10.2:

-------------- repro.d ---------------------

import core.simd;
import gcc.builtins;
alias __m128 = float4;
alias __m128i = int4;
alias __m128d = double2;

void bug()
{
    uint savedRounding = _MM_GET_ROUNDING_MODE();

    _MM_SET_ROUNDING_MODE(_MM_ROUND_NEAREST);
    __m128i A = _mm_cvtps_epi32(_mm_setr_ps(1.4f, -2.1f, 53.5f, -2.9f));
    assert(A.array == [1, -2, 54, -3]);

    // GCC might merge this branch with above! Despite _MM_SET_ROUNDING_MODE 
    // not being pure.
    _MM_SET_ROUNDING_MODE(_MM_ROUND_DOWN);
    A = _mm_cvtps_epi32(_mm_setr_ps(1.4f, -2.1f, 53.5f, -2.9f)); // that whole
expression is computed once, but rounding mode has changed
    assert(A.array == [1, -3, 53, -3]);
}

uint _mm_getcsr()
{
    return __builtin_ia32_stmxcsr();
}

void _mm_setcsr(uint controlWord) @trusted
{
    __builtin_ia32_ldmxcsr(controlWord);
}


__m128i _mm_cvtps_epi32 (__m128 a)
{
    return __builtin_ia32_cvtps2dq(a);
}

enum int _MM_ROUND_NEAREST     = 0x0000; /// MXCSR Rounding mode.
enum int _MM_ROUND_DOWN        = 0x2000; ///ditto
enum int _MM_ROUND_UP          = 0x4000; ///ditto
enum int _MM_ROUND_TOWARD_ZERO = 0x6000; ///ditto
enum int _MM_ROUND_MASK        = 0x6000; /// MXCSR Rounding mode mask.

uint _MM_GET_ROUNDING_MODE()
{
    return _mm_getcsr() & _MM_ROUND_MASK;
}

void _MM_SET_ROUNDING_MODE(int _MM_ROUND_xxxx)
{
    _mm_setcsr((_mm_getcsr() & ~_MM_ROUND_MASK) | _MM_ROUND_xxxx);
}

__m128 _mm_setr_ps (float e3, float e2, float e1, float e0)
{
    float[4] result = [e3, e2, e1, e0];
    return loadUnaligned!(float4)(result.ptr);
}

float4 loadUnaligned(Vec)(const(float)* pvec) @trusted if (is(Vec == float4))
{
    return __builtin_ia32_loadups(pvec);
}

------------------------------------------------------


More information about the Gcc-bugs mailing list