From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 34498 invoked by alias); 11 Aug 2016 17:55:53 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 34489 invoked by uid 89); 11 Aug 2016 17:55:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.3 required=5.0 tests=BAYES_50,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.2 spammy=r2, bfs, rts, 4,r1 X-HELO: paperclip.tbsaunde.org Received: from tbsaunde.org (HELO paperclip.tbsaunde.org) (66.228.47.254) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 11 Aug 2016 17:55:42 +0000 Received: from ball (unknown [IPv6:2607:f0c8:8000:80e0:56ee:75ff:fe52:afb9]) by paperclip.tbsaunde.org (Postfix) with ESMTPSA id E169EC112; Thu, 11 Aug 2016 17:55:40 +0000 (UTC) Date: Thu, 11 Aug 2016 17:55:00 -0000 From: Trevor Saunders To: Oleg Endo Cc: Jeff Law , Richard Biener , Aldy Hernandez , Martin Sebor , gcc-patches Subject: Re: protected alloca class for malloc fallback Message-ID: <20160811180219.GA6440@ball> References: <44EE0FB0-A8B9-43F9-BF58-C4D7D27DA944@gmail.com> <57A5B8BE.2000004@redhat.com> <941D179C-146F-4004-BECB-9FB066DDCC8D@gmail.com> <21bcbebe-28a8-58a7-68e8-af9abcb03dce@redhat.com> <20160808173939.GA13790@ball> <1470742429.639.196.camel@t-online.de> <20160809174139.GA18239@ball> <1470848609.639.405.camel@t-online.de> <20160811013118.GE21468@ball> <1470917914.639.432.camel@t-online.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1470917914.639.432.camel@t-online.de> User-Agent: Mutt/1.6.0 (2016-04-01) X-SW-Source: 2016-08/txt/msg00950.txt.bz2 On Thu, Aug 11, 2016 at 09:18:34PM +0900, Oleg Endo wrote: > On Wed, 2016-08-10 at 21:31 -0400, Trevor Saunders wrote: > > > > > Well, I'd say the compromises made in std::string make it pretty > > terrible for general purpose use accept where perf and memory doesn't > > matter at all. > > > > std::vector isn't very great size wise either, imho the size / > > capacity fields would be much better put in the buffer than in the > > struct itself, to save 2 * sizeof (void *) in sizeof std::vector. > > There's nothing in the standard that says those fields have to go into > the vector struct/class itself and not into the data buffer. It just > happens to be the way it's implemented in libstdc++. E.g. libc++ > implements some things in different ways to save a few bytes here and > there. > > It looks more practical to put those fields into the container itself, > otherwise you'd have to do a nullptr check every time you access the > size field etc. Although newer compilers optimize away the redundant > nullptr checks, older compilers (which GCC wants to be good with) might > not do it. In any case, it seems to generate slightly bigger code, at > least in one instance (see attachment). if you are clever you can have a empty global vector that you point all the empty vectors at and so eliminate the null check. Well, I guess that doesn't work quite as well if the global needs to be accessed through a plt sigh, but at least you only need to check against it for reallocation which is rather heavy weight anyway. > Anyway, normally there is more data in the vectors than there are > vectors around, so whether sizeof (vector) is 8 or 24 bytes doesn't > matter. It matters if you have any empty vectors around. The only numbers I can find are https://bugzilla.mozilla.org/show_bug.cgi?id=1007846 but I seem to remember seeing that for Firefox at least most vectors contained 0 elements. > > > > or just having your stack_string type convert to the normal string > > type so that you can pass mutable references. > > But that would imply copying, wouldn't it? Not if you are clever, you can use the same trick gcc uses in vec / auto_vec with strings. Trev > > Cheers, > Oleg > > #if 0 > template > class vector > { > public: > unsigned int size (void) const { return m_buffer != nullptr ? m_buffer->size : 0; } > bool empty (void) const { return size () == 0; } > > unsigned int capacity (void) const { return m_buffer != nullptr ? m_buffer->capacity : 0; } > > T* data (void) { return (T*)(m_buffer + 1); } > const T* data (void) const { return (const T*)(m_buffer + 1); } > > T& operator [] (unsigned int i) { return data ()[i]; } > const T& operator [] (unsigned int i) const { return data ()[i]; } > > private: > struct buffer_header > { > unsigned int size; > unsigned int capacity; > }; > > buffer_header* m_buffer; > }; > > > int foo (const vector& x) > { > if (x.empty ()) > return 0; > > int r = 0; > for (unsigned int i = 0; i < x.size (); ++i) > r += x[i]; > > return r; > } > > /* > -O2 -m2a > mov.l @r4,r2 > tst r2,r2 > bt .L5 > mov.l @r2,r1 > tst r1,r1 > bt.s .L5 > shll2 r1 > add #-4,r1 > shlr2 r1 > add #8,r2 > mov #0,r0 > add #1,r1 > .align 2 > .L3: > mov.l @r2+,r3 > dt r1 > bf.s .L3 > add r3,r0 > rts/n > .align 1 > .L5: > rts > mov #0,r0 > */ > #endif > > > #if 1 > > template > class vector > { > public: > unsigned int size (void) const { return m_size; } > bool empty (void) const { return size () == 0; } > > unsigned int capacity (void) const { return m_capacity; } > > T* data (void) { return (T*)(m_buffer); } > const T* data (void) const { return (const T*)(m_buffer); } > > T& operator [] (unsigned int i) { return data ()[i]; } > const T& operator [] (unsigned int i) const { return data ()[i]; } > > private: > unsigned int m_size; > unsigned int m_capacity; > T* m_buffer; > }; > > > int foo (const vector& x) > { > if (x.empty ()) > return 0; > > int r = 0; > for (unsigned int i = 0; i < x.size (); ++i) > r += x[i]; > > return r; > } > > /* > -O2 -m2a > mov.l @r4,r1 > tst r1,r1 > bt.s .L7 > mov #0,r0 > shll2 r1 > mov.l @(8,r4),r2 > add #-4,r1 > shlr2 r1 > add #1,r1 > .align 2 > .L3: > mov.l @r2+,r3 > dt r1 > bf.s .L3 > add r3,r0 > .L7: > rts/n > */ > > #endif >