I recently found something I believe is optimizer bug in icc.
I've reported the issue. The version I used is XE 14,
haven't tried XE 15 yet (maybe someone could try?).
#include <vector>
#include <iostream>
using namespace std;
struct PackedColor
{
unsigned int packed;
unsigned char GetR() const {
return (packed >> 16) & 255;
}
unsigned char GetG() const {
return (packed >> 8) & 255;
}
void SetR( int nr ) {
unsigned int r = nr << 16;
packed &= ~(255u << 16);
packed |= r;
}
void SetG( int ng ) {
unsigned int g = ng << 8;
packed &= ~(255u << 8);
packed |= g;
}
};
int main()
{
vector< PackedColor > hmap( 256 );
for ( int i=0; i<256; i++ ) {
hmap[i].packed = 0;
hmap[i].SetR( 0 );
hmap[i].SetG( 128 );
}
int h = hmap[0].GetR() + 256 * hmap[0].GetG();
// expect 32768 here but get 0
cout << "h=" << h << endl;
return 0;
}
I only hope it doesn't exploit some hidden UB (making a fool of myself) problem but I doubt.
Prints 0 here (discarding GetG fetch). Scary, isn't it?
Considering I compiled the Windows version of my engine with icc...
It looks legitimate code to me, but could you try and recompile this with all occurances of "signed int" and "unsigned char" replaced with "unsigned int"? The rules for integral promotions (char to int) and signed/unsigned conversions are rather tricky.
Is that program minimal? What happens if you don't use a vector, but have a single PackedColor object? What do you get from GetR() and GetG() independently?
Yes this code works, but not because of signed/unsigned.
Replacing GetR/GetG to return unsigned char triggers the bug again hower.
Funny enough, multiplying with 257 "works", returning a number >32768.
Alvaro: not sure if it's minimal, but if I use a single PackedObject the bug disappears (has nothing to do with vector itself as I normally use my own containers).
Hmm, when I use this:
mar wrote:Yes this code works, but not because of signed/unsigned.
Replacing GetR/GetG to return unsigned char triggers the bug again hower.
Funny enough, multiplying with 257 "works", returning a number >32768.
Alvaro: not sure if it's minimal, but if I use a single PackedObject the bug disappears (has nothing to do with vector itself as I normally use my own containers).
Hmm, when I use this:
mar wrote:Yes this code works, but not because of signed/unsigned.
Replacing GetR/GetG to return unsigned char triggers the bug again hower.
Funny enough, multiplying with 257 "works", returning a number >32768.
Alvaro: not sure if it's minimal, but if I use a single PackedObject the bug disappears (has nothing to do with vector itself as I normally use my own containers).
Hmm, when I use this:
unsigned int h = 256u * (unsigned int)hmap[0].GetG();
it still returns 0.
Why don't you look at generated assembly? With 257 the compiler emits a multiply instruction. The 256 instead is probably optimized as left shift, and extra care could be needed (to prevent the compiler bug)?
xmas79 wrote:Why don't you look at generated assembly? With 257 the compiler emits a multiply instruction. The 256 instead is probably optimized as left shift, and extra care could be needed (to prevent the compiler bug)?
I don't want to prevent the bug, I want it gone!
Assembly: