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

Alexander Cherepanov <ch3root at openwall dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ch3root at openwall dot com

--- Comment #20 from Alexander Cherepanov <ch3root at openwall dot com> ---
Minimized testcase that should still be quite close to the original:

----------------------------------------------------------------------
#include <stdio.h>

__attribute__((noipa)) // imagine it in a separate TU
static double opaque(double d) { return d; }

int main()
{
    double d;
    do {
        d = opaque(1e6);
    } while (opaque(0));

    if (d == 1e6)
        printf("yes\n");

    int i = d * 1e-6;
    printf("i = %d\n", i);

    if (i == 1)
        printf("equal to 1\n");
}
----------------------------------------------------------------------
$ gcc -std=gnu11 -pedantic -Wall -Wextra -m32 -march=i686 -O3 test.c && ./a.out
yes
i = 0
equal to 1
----------------------------------------------------------------------

According to https://godbolt.org/z/AmkmS5 , this happens for gcc versions
8.1--9.2 but not for trunk (I haven't tried earlier versions).

With gcc 8.3.0 from the stable Debian it works like this:
- (as described in comment 7) 120t.dom2 merges two `if`s, in particular
deducing that `i == 1` is true if `d == 1e6` is true but not substituting `i`
in `printf`;
- 142t.loopinit introduces `# d_4 = PHI <d_8(3)>` between the loop and the
first `if`;
- 181t.dom3 would fold computation of `i` in the `d == 1e6` branch but the
introduced `PHI` seems to prevent this.

With gcc from the trunk a new pass 180t.fre4 removes that `PHI` and 182t.dom3
then does its work. (The numeration of passes changed slightly since gcc
8.3.0.)

Reply via email to