Potential optimizer bug in icc

Potential optimizer bug in icc

Hello,

I'm reporting this here, since there is no separate forum for the C compiler.

The attached testcase exhibits incorrect code generation by icc at -O2.

I could reproduce this under Linux with icc versions 10.1 and 11.0, but

only on 64bit platforms.

A quick description on how to reproduce the problem is given inside the

tarball.

Please let me know if I made some coding mistake and this is actually

not a compiler bug!

Thanks in advance,

Martin Reinecke

16 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hmm, it seems that I didn't manage to attach the tarball, so I'll list the involved files here:

main.c:

---- cut here

#include
#include

void foo(size_t length, double *data);

int main(void)
{
#define size 3
double data[2*size];
int m;
for (m=0;m<2*size;++m)
data[m]=m;
printf("before function (should be 0 1 2 3 4 5)n");
for (m=0;m<2*size;++m)
printf("%f ",data[m]);
printf("n");
foo(size,data);
printf("after function (should be 0 0 2 4 4 5)n");
for (m=0;m<2*size;++m)
printf("%f ",data[m]);
printf("n");
return 0;
}

---- cut here

foo.c:

----- cut here

#include

void foo(size_t length, double *data)
{
size_t n=length;
size_t m;
for (m=0; m data[m+1] = data[2*m];
}

---- cut here

README.bug:

--- cut here

To reproduce the bug, first run

icc -O1 main.c foo.c
./a.out

This should work as expected

Then try

icc -O2 main.c foo.c
./a.out

This will produce an incorrect result.

This happens with icc version 10.1 and 11.0
on 64bit Linux.

---- cut here

For me, it runs the same (in agreement with your comment) with gcc and with icc 11.0/074, on SuSE 10.3 x86_64. Did you look at pre-processed code to see if something went wrong in your installation?

See if adding -Qip- solves your problem. If it does, then it is a bug #524001 which is targeted to be fixed in the next compiler release.

--
Regards,
Igor Levicki

If you find my post helpfull, please rate it and/or select it as a best answer where applies. Thank you.

Quoting - Igor Levicki

See if adding -Qip- solves your problem. If it does, then it is a bug #524001 which is targeted to be fixed in the next compiler release.

adding this flag gives me

icc: command line warning #10006: ignoring unknown option '-Qip-'

:(

Quoting - mreinecke

icc: command line warning #10006: ignoring unknown option '-Qip-'

The linux spelling of this option is -fno-inline-functions. It's worth remembering that gcc -O2 doesn't imply -finline-functions (plus auto-vectorization), while icc -O2 does.

Thanks for the hint with the Linux syntax! Unfortunately this does not make the miscompilation go away, so this is probably an independent bug,

Some more observations:

The code is compiled correctly,

- if main.c and foo.c are merged into a single file, or

- if the local variables in foo() are defined as "int" instead of "size_t", or

- if the term "data[2*m]" in foo() is replaced by "data[m+m]" or "data[m<<1]"

Very confusing ...

Hi,

According to Intel Compiler Manual the linux equivalent for /Qip- is -no-ip

The behaviour you describe (for example replacing 2*m by m+m) reminds me of the behaviour described in this thread Bug in Intel C++ compiler when using option /Qipo. So I really think Igor had a good guess when specifying to add -Qip-

Regards,

Matthieu

Quoting - matthieu.darbois

Hi,

According to Intel Compiler Manual the linux equivalent for /Qip- is -no-ip

The behaviour you describe (for example replacing 2*m by m+m) reminds me of the behaviour described in this thread Bug in Intel C++ compiler when using option /Qipo. So I really think Igor had a good guess when specifying to add -Qip-

Regards,

Matthieu

Sorry, this doesn't change anything either :(

I ran the test case on CentOS 5.2 x86_64 (Equivalent to Red Hat Enterprise Linux 5 update 2) using icc 11.0/074. It fails as described in the original post.

...Tim

Quoting - tim-theisen

I ran the test case on CentOS 5.2 x86_64 (Equivalent to Red Hat Enterprise Linux 5 update 2) using icc 11.0/074. It fails as described in the original post.

...Tim

I have just ran the test under Windows with 11.0.061 (with a version of compiler backend where #524001 is fixed) and I can confirm that it is a different bug and a nasty one at that.

I have experimented with switches for code generation (-Qx[n]) and here is what I have found. If I compile with -QxK or -QxW I get the following output:

c:iccbug>main
before function (should be 0 1 2 3 4 5)
0.000000 1.000000 2.000000 3.000000 4.000000 5.000000
after function (should be 0 0 2 4 4 5)
0.000000 0.000000 0.000000 0.000000 4.000000 5.000000

When I compile with -QxN, -QxP, -QxT, or -QxS I get the following (different) output which is the result of unrolling:

c:iccbug>main
before function (should be 0 1 2 3 4 5)
0.000000 1.000000 2.000000 3.000000 4.000000 5.000000
after function (should be 0 0 2 4 4 5)
0.000000 0.000000 0.000000 4.000000 4.000000 5.000000

If you specify -Qunroll:0, then the output is the same as for -QxK and -QxW. My guess is that the compiler doesn't unroll the loop for -QxK and -QxW regardless of the -Qunroll switch. It is interesting that the unrolled version does the last iteration correctly.

From my analysis of the assembler code generated for the function foo(), it seems that the compiler mistakenly considers the expression data[2 * m] as invariant and it generates the load instruction before the loop instead of inside of the loop body thus replicating the same value into the first three elements of the array. Here is the offending assembler code:

_foo	PROC      NEAR
        mov       ecx, DWORD PTR [4+esp]
        test      ecx, ecx
        jbe       .B1.5
.B1.2:
        mov       edx, DWORD PTR [8+esp]
        movsd     xmm0, QWORD PTR [edx] ; this should be after .B1.3 with proper indexing
        xor       eax, eax

.B1.3:
        movsd     QWORD PTR [8+edx+eax*8], xmm0
        inc       eax
        cmp       eax, ecx
        jb        .B1.3
.B1.5:
        ret
_foo ENDP

As a temporary workaround you can define size_t m in function foo() as volatile. I will email Jennifer to take a look at this thread.

--
Regards,
Igor Levicki

If you find my post helpfull, please rate it and/or select it as a best answer where applies. Thank you.

I have only current icc versions installed on my EL5.2. I can't reproduce the problem, even if I put the buggy Red Hat versions of gcc and binutils first on PATH.

Quoting - tim18

I have only current icc versions installed on my EL5.2. I can't reproduce the problem, even if I put the buggy Red Hat versions of gcc and binutils first on PATH.

I tried with a minimal path (/opt/intel/Compiler/11.0/074/bin/intel64:/bin:/usr/bin). Igor is right, the compiler exhibits the same behavior on 32-bit Windows. Do you have anything in icc.cfg that might change the default behavior of the compiler?

...Tim

Quoting - tim18

I have only current icc versions installed on my EL5.2. I can't reproduce the problem, even if I put the buggy Red Hat versions of gcc and binutils first on PATH.

I don't understand what GCC and binutils have to do with ICC bug.

Nevertheless, if you have access to all bug reports on Premier Support take a look at issue #527663 which I have created approx. two hours ago -- issue status has just been changed to "Reproduced (Escalated)". That makes it a confirmed compiler bug. Perhaps you are running an internal daily build in which the bug has already been fixed?

--
Regards,
Igor Levicki

If you find my post helpfull, please rate it and/or select it as a best answer where applies. Thank you.

No, I'm not taking advantage of any icc version which hadn't been released at the time of this report. I did wonder whether an older icc version might have been a problem. I don't have access to reports on premier, unless the customer specifically requests it.

I've had issues where I couldn't compile on Red Hat 5.2 until I upgraded gcc and binutils. This doesn't appear to be one of those. I did ask if the people who had trouble were willing to examine or report pre-processed code, and the answer appears to be no. There are issues both ways between old header versions such as Red Hat supplies and up to date headers.

As you may have noticed, I couldn't run idb on RH5.2,even with the procedures in the install docs. So I think it likely that people will have performedindividual upgrades in order to get by with RH or CentOS.

Leave a Comment

Please sign in to add a comment. Not a member? Join today