This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/36235] New: Invalid optimization related to heavy function inlining with -O3
- From: "cxl at ntllib dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 14 May 2008 16:51:39 -0000
- Subject: [Bug c++/36235] New: Invalid optimization related to heavy function inlining with -O3
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
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.
--
Summary: Invalid optimization related to heavy function inlining
with -O3
Product: gcc
Version: 4.1.3
Status: UNCONFIRMED
Severity: critical
Priority: P3
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: cxl at ntllib dot org
GCC build triplet: x86
GCC host triplet: x86
GCC target triplet: x86
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36235