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

            Bug ID: 116459
           Summary: gcc 12.0 optimized out functions which has observable
                    side affect
           Product: gcc
           Version: 12.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: xiaohuba2021 at 163 dot com
  Target Milestone: ---

The following code:

#include <iostream>
#include <cstring>

using namespace std;
struct Matrix {
    long long mat[2][2];
    Matrix() { memset(mat, 0, sizeof(mat)); }
    Matrix operator*(Matrix b) {
        Matrix ans;
        ans.mat[0][0] = (mat[0][0] * b.mat[0][0] + mat[0][1] * b.mat[1][0]);
        ans.mat[1][0] = (mat[1][0] * b.mat[0][0] + mat[1][1] * b.mat[1][0]);
        ans.mat[0][1] = (mat[0][0] * b.mat[0][1] + mat[0][1] * b.mat[1][1]);
        ans.mat[1][1] = (mat[1][0] * b.mat[0][1] + mat[1][1] * b.mat[1][1]);
        return ans;
    }
};
Matrix st, res;
volatile bool mask = 0;
void qpw(long long k) {
    mask = 1;
    while (k) {
        if (k & 1) st = st * res;
        res = res * res, k >>= 1;
    }
}
int main() {
    st.mat[0][0] = st.mat[0][1] = 1;
    res.mat[0][0] = 6;
    res.mat[1][0] = -2, res.mat[1][1] = 2;
    qpw(2);
    cout << st.mat[0][0] << '\n';
    return 0;
}

seems to produce wrong output(1) with -O2 or -O1 enabled, while the correct
answer is 20.

Uncomment line 20 (mask = 1) or explicitly add operator= for struct Matrix
solves this problem.

By looking at the assemble code, I found that the compiler did compile function
qpw, however didn't call it. So it's most likely a compiler bug, as the
compiler thought qpw did not have any side affects and optimized it out.

Is it caused by the default copy assignment of a struct containing only 2D
array?

Compiler info:

Using built-in specs.
COLLECT_GCC=/opt/compiler-explorer/gcc-12.2.0/bin/g++
COLLECT_LTO_WRAPPER=/opt/compiler-explorer/gcc-12.2.0/bin/../libexec/gcc/x86_64-linux-gnu/12.2.0/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../gcc-12.2.0/configure
--prefix=/opt/compiler-explorer/gcc-build/staging --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu --disable-bootstrap
--enable-multiarch --with-abi=m64 --with-multilib-list=m32,m64,mx32
--enable-multilib --enable-clocale=gnu
--enable-languages=c,c++,fortran,ada,objc,obj-c++,go,d --enable-ld=yes
--enable-gold=yes --enable-libstdcxx-debug --enable-libstdcxx-time=yes
--enable-linker-build-id --enable-lto --enable-plugins --enable-threads=posix
--with-pkgversion=Compiler-Explorer-Build-gcc--binutils-2.38
--enable-libstdcxx-backtrace=yes
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 12.2.0 (Compiler-Explorer-Build-gcc--binutils-2.38)

Reply via email to