From patchwork Sat Nov 11 18:14:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Glisse X-Patchwork-Id: 837072 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-466584-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="f/tYDg9u"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yZ4mv0N6Fz9t2h for ; Sun, 12 Nov 2017 05:14:37 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=SE4KGrLhk2ccgFhdMOkPTCnsD9F0skmprxJ6PDcXD/DNI+mDVXlih 8m+MRSs+CxFmfObdONG5Ysu5hyN/h2jBa9Ppb6i+mXNOKDIFFZQH2Siu3HLpbAm7 ZBaW61jA9jp1NMvWzkvwYswJot+IRwe/vbK3xJBsPmwumPtfhUCQDc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=eURhlI4LrbVxnGvKlo8OQgLdC+U=; b=f/tYDg9uo5UrwHmSqbuc pt7zXkZ5sB4S04oG14IuOqZeKhUU7J1/H8008mnbPIR/Sx0ZJp6Q2uklQPXmtus0 kPjCRxnWjhd/NK5c/ax75MHhlUga0Je8jmgIlqgEqKPZ2IUB7V5n/dOP9DL5VvcL vcvHgrNobnc7igxGr0g1RoQ= Received: (qmail 98054 invoked by alias); 11 Nov 2017 18:14:30 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 98035 invoked by uid 89); 11 Nov 2017 18:14:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=bullet, belonging, Hx-languages-length:3670, H*c:HHHHH X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail2-relais-roc.national.inria.fr Received: from mail2-relais-roc.national.inria.fr (HELO mail2-relais-roc.national.inria.fr) (192.134.164.83) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 11 Nov 2017 18:14:26 +0000 Received: from ip-195.net-89-2-234.rev.numericable.fr (HELO stedding) ([89.2.234.195]) by mail2-relais-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES256-SHA; 11 Nov 2017 19:14:23 +0100 Date: Sat, 11 Nov 2017 19:14:14 +0100 (CET) From: Marc Glisse To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: Tweak vector::_M_realloc_insert for code size Message-ID: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 Hello, operator new can clobber memory, it is hard to teach the compiler otherwise since it is replaceable. Here I cache a couple values before the call to the allocator. I checked the result on this simple example: #include void f(std::vector&v){ v.push_back(0); } The patch does not affect the fast path where no reallocation is needed. Compiling with -O3 (everything gets inlined into f), I see a nice decrease in code size on x86_64 $ size old.o new.o text data bss dec hex filename 462 0 0 462 1ce old.o 376 0 0 376 178 new.o Even at -O2 where _M_realloc_insert is not inlined, I get a slight decrease in code size (490 -> 470). On x86, that's 531 -> 519 (465 -> 387 at -O3). I'm not going to modify every function like that, I just happened to be looking at this example for other reasons, and the size gain is larger than I expected, so I am posting the patch. Bootstrap+regtest on powerpc64le-unknown-linux-gnu. 2017-11-13 Marc Glisse * include/bits/vector.tcc (vector::_M_realloc_insert): Cache old values before the allocation. Index: libstdc++-v3/include/bits/vector.tcc =================================================================== --- libstdc++-v3/include/bits/vector.tcc (revision 254629) +++ libstdc++-v3/include/bits/vector.tcc (working copy) @@ -414,20 +414,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_realloc_insert(iterator __position, _Args&&... __args) #else template void vector<_Tp, _Alloc>:: _M_realloc_insert(iterator __position, const _Tp& __x) #endif { const size_type __len = _M_check_len(size_type(1), "vector::_M_realloc_insert"); + pointer __old_start = this->_M_impl._M_start; + pointer __old_finish = this->_M_impl._M_finish; const size_type __elems_before = __position - begin(); pointer __new_start(this->_M_allocate(__len)); pointer __new_finish(__new_start); __try { // The order of the three operations is dictated by the C++11 // case, where the moves could alter a new element belonging // to the existing vector. This is an issue only for callers // taking the element by lvalue ref (see last bullet of C++11 // [res.on.arguments]). @@ -435,45 +437,44 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __new_start + __elems_before, #if __cplusplus >= 201103L std::forward<_Args>(__args)...); #else __x); #endif __new_finish = pointer(); __new_finish = std::__uninitialized_move_if_noexcept_a - (this->_M_impl._M_start, __position.base(), + (__old_start, __position.base(), __new_start, _M_get_Tp_allocator()); ++__new_finish; __new_finish = std::__uninitialized_move_if_noexcept_a - (__position.base(), this->_M_impl._M_finish, + (__position.base(), __old_finish, __new_finish, _M_get_Tp_allocator()); } __catch(...) { if (!__new_finish) _Alloc_traits::destroy(this->_M_impl, __new_start + __elems_before); else std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); _M_deallocate(__new_start, __len); __throw_exception_again; } _GLIBCXX_ASAN_ANNOTATE_REINIT; - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - this->_M_impl._M_start); + std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator()); + _M_deallocate(__old_start, + this->_M_impl._M_end_of_storage - __old_start); this->_M_impl._M_start = __new_start; this->_M_impl._M_finish = __new_finish; this->_M_impl._M_end_of_storage = __new_start + __len; } template void vector<_Tp, _Alloc>:: _M_fill_insert(iterator __position, size_type __n, const value_type& __x) {