From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6364 invoked by alias); 14 May 2008 16:52:23 -0000 Received: (qmail 6219 invoked by uid 48); 14 May 2008 16:51:39 -0000 Date: Wed, 14 May 2008 16:52:00 -0000 Subject: [Bug c++/36235] New: Invalid optimization related to heavy function inlining with -O3 X-Bugzilla-Reason: CC Message-ID: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "cxl at ntllib dot org" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2008-05/txt/msg01108.txt.bz2 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 #include #include #include template inline const T& my_max(const T& a, const T& b) { return a > b ? a : b; } template inline const T& my_min(const T& a, const T& b) { return a < b ? a : b; } template 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 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 T * Vector::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 void Vector::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 void Vector::InsertN(int q, int count) { RawInsert(q, count); } void *MemoryAllocSz(size_t& sz); void MemoryFree(void *); struct Item { char h[32]; }; struct Bar { Vector 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