From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20378 invoked by alias); 5 Jan 2003 08:41:02 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 20364 invoked from network); 5 Jan 2003 08:40:58 -0000 Received: from unknown (HELO pimout2-ext.prodigy.net) (207.115.63.101) by 209.249.29.67 with SMTP; 5 Jan 2003 08:40:58 -0000 Received: from wobble.local (adsl-64-171-3-49.dsl.sntc01.pacbell.net [64.171.3.49]) by pimout2-ext.prodigy.net (8.12.3 da nor stuldap/8.12.3) with ESMTP id h058ej9F129524 for ; Sun, 5 Jan 2003 03:40:46 -0500 Received: (from martin@localhost) by wobble.local (8.11.6/8.11.6) id h058ejL21416; Sun, 5 Jan 2003 00:40:45 -0800 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <15895.61324.872456.502039@wobble.local> Date: Sun, 05 Jan 2003 10:44:00 -0000 From: Martin Buchholz To: gcc@gcc.gnu.org Subject: More embarrassing failures to optimize Reply-To: martin@xemacs.org X-SW-Source: 2003-01/txt/msg00197.txt.bz2 One can try creating a typesafe Bool class like this: class Bool { private: const bool val_; struct Conv { int Dummy; }; public: Bool (bool val) : val_ (val) {} operator int Conv::* () const { return val_ ? & Conv::Dummy : 0; } }; Unfortunately, g++ is less capable of optimizing this than other obvious Bool classes. For example, void f3 () { Bool t (true), f (false); assert (t); assert (! f); assert (t); assert (! f); } is "optimized" to xorl %edx, %edx subl $12, %esp testb %dl, %dl jne .L52 addl $12, %esp ret .L52: pushl $_ZZ2f3vE19__PRETTY_FUNCTION__ pushl $42 pushl $.LC0 pushl $.LC2 call __assert_fail Note that the resulting code contains exactly one branch, not two or four. To my eyes it looks like "testb %dl, %dl" always yields constant true; optimizing this shouldn't be too tough a job. g++ clearly knows how to optimize "assert (t); assert (! f);" away completely - but not if it's repeated! The following alternative Bool classes can be optimized without problems: class Bool // "obvious" Bool class { private: const bool val_; public: Bool (bool val) : val_ (val) {} operator bool () const { return val_; } }; class Bool // Note addition of operator! { private: const bool val_; struct Conv { int Dummy; }; public: Bool (bool val) : val_ (val) {} operator int Conv::* () const { return val_ ? & Conv::Dummy : 0; } bool operator! () { return val_ ? 0 : & Conv::Dummy; } }; A statement that is optimized away completely should not inhibit optimizations in subsequent statements. Like other optimization problems I have reported, this "looks" like "low-hanging fruit". To repeat: Linux x86, gcc 3.2.1: g++ -O3 -fomit-frame-pointer foo.cc ----------------------------------------------------------------- #include class Bool1 { private: const bool val_; public: Bool1 (bool val) : val_ (val) {} operator bool () const { return val_; } }; class Bool2 { private: const bool val_; struct Conv { int Dummy; }; public: Bool2 (bool val) : val_ (val) {} operator int Conv::* () const { return val_ ? & Conv::Dummy : 0; } //bool operator! () { return val_ ? 0 : & Conv::Dummy; } }; void f1 () // gcc optimizes this { Bool1 t (true), f (false); assert (t); assert (! f); assert (t); assert (! f); } void f2 () // gcc optimizes this { Bool2 t (true), f (false); assert (t); assert (! f); } void f3 () // gcc fails to optimize this { Bool2 t (true), f (false); assert (t); assert (! f); assert (t); assert (! f); }