Bug 36235 - [4.2 Regression] Invalid optimization related to heavy function inlining with -O3
[4.2 Regression] Invalid optimization related to heavy function inlining with...
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: middle-end
4.2.3
: P3 normal
: 4.3.0
Assigned To: Not yet assigned to anyone
: alias, wrong-code
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2008-05-14 16:51 UTC by Mirek Fidler
Modified: 2009-03-31 15:38 UTC (History)
2 users (show)

See Also:
Host: x86
Target: x86
Build: x86
Known to work: 4.1.2 4.3.0
Known to fail: 4.2.3 4.2.5
Last reconfirmed: 2008-05-15 08:51:27


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mirek Fidler 2008-05-14 16:51:36 UTC
g++ (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu7)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Used flags:
-ggdb -g2 -fexceptions -O3 -x c++

Code (has to be in 4 files to keep inlining constelation):

-----------------
CGGBug.h

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <new>

template <class T> inline const T& my_max(const T& a, const T& b) { return a > b ? a : b; }
template <class T> inline const T& my_min(const T& a, const T& b) { return a < b ? a : b; }

template <class T>
inline T minmax(T x, T _min, T _max) { return my_min(my_max(x, _min), _max); }

void *MemoryAllocSz(size_t& sz);
void  MemoryFree(void *);

template <class T>
class Vector {
	T       *vector;
	int      items;
	int      alloc;

	static void RawFree(T *ptr)            { if(ptr) MemoryFree(ptr); }
	static T   *RawAlloc(int& n);

	void RawInsert(int q, int count);
	

public:
	void  InsertN(int q, int count);
	const T& First() { return vector[0]; }
	int   GetCount() const { return items; }
	
	Vector() { vector = NULL; items = alloc = 0; }
};

template <class T>
T * Vector<T>::RawAlloc(int& n)
{
	size_t sz0 = n * sizeof(T);
	size_t sz = sz0;
	void *q = MemoryAllocSz(sz);
	n += (int)((sz - sz0) / sizeof(T));
	return (T *)q;
}

template <class T>
void Vector<T>::RawInsert(int q, int count)
{
	if(!count) return;
	if(items + count > alloc) {
		T *newvector = RawAlloc(alloc = alloc + my_max(alloc, count));
		if(vector) {
			memcpy(newvector, vector, q * sizeof(T));
			memcpy(newvector + q + count, vector + q, (items - q) * sizeof(T));
			RawFree(vector);
		}
		vector = newvector;
	}
	else {
		memmove(vector + q + count, vector + q, (items - q) * sizeof(T));
	}
	items += count;
}

template <class T>
void Vector<T>::InsertN(int q, int count)
{
	RawInsert(q, count);
}

void *MemoryAllocSz(size_t& sz);
void  MemoryFree(void *);

struct Item {
	char h[32];
};

struct Bar {
	Vector<Item> li;
	
	void DoTest(int i, int count);
};

-------
GCCBug1.cpp:

#include "GCCBug.h"

char array[256];

void *MemoryAllocSz(size_t& sz)
{
	printf("%d\n", sz);
	return array;
}

void MemoryFree(void *) {}

---------
GCCBug2.cpp:

#include "GCCBug.h"

void Bar::DoTest(int i, int count)
{
	li.InsertN(minmax(i, 0, li.GetCount()), my_max(count, 0));
}
--------
GCCBug.cpp:

#include "GCCBug.h"

int main(int argc, char argv[])
{
	Bar b;
	b.DoTest(0, 1);
	return 0;
}
---------------

This code should print "32" (== sizeof(T)) and it does when compiled -Os, but compiled -O3 it prints "0". In assembly there seems a bug at the beginning of inlined "RawAlloc" method around the shift to perform "n * sizeof(T)" multiply.

Note that changing sizeof(T) to something else than power of two makes the code work as expected.

AMD64 compiler seems to be affected as well.
Comment 1 Mirek Fidler 2008-05-14 16:52:44 UTC
(fixed compiler version)
Comment 2 Andrew Pinski 2008-05-14 16:54:50 UTC
Can you try 4.3.0?
Comment 3 Richard Biener 2008-05-15 08:51:27 UTC
Confirmed.  It fails with -O -finline-functions -fstrict-aliasing.  Works with
4.3.0.  I suppose this is a dup of one of the known alias bugs with 4.2.
Comment 4 Joseph S. Myers 2008-05-19 20:25:22 UTC
4.2.4 is being released, changing milestones to 4.2.5.
Comment 5 Joseph S. Myers 2009-03-31 15:38:26 UTC
Closing 4.2 branch, fixed in 4.3.