Let's look at some code, a simple wrapper around "double" static struct X {} x; static struct Y {} y; struct Double { double d_; Double (double d) : d_ (d) {} Double (const X&) : d_ (1.2) {} Double (const Y&) : d_ (3.4) {} operator double () { return d_; } inline friend Double operator/ (Double d1, Double d2) { return Double (double (d1) / double (d2)); } }; double f1 () { return Double (1.2) / Double (3.4); } double f2 () { return Double (1.2) / Double (y ); } double f3 () { return Double (x ) / Double (3.4); } double f4 () { return Double (x ) / Double (y ); } It's obvious that all the Double objects above are compile-time constant objects, and thus can be constant-folded. All the functions f1 f2 f3 f4 return the same constant value. Of course, g++ can optimize f1 to fldl .LC2 ret f2 and f3 are optimized to the only slightly inferior subl $12, %esp fldl .LC5 addl $12, %esp ret This shows that g++ "knows" that Double (x) and Double (y) are both compile-time constants, else they could not be folded. Then why can g++ not optimize f4 as well? subl $20, %esp movl $858993459, (%esp) movl $1074475827, 4(%esp) fldl (%esp) movl $858993459, 8(%esp) movl $1072902963, 12(%esp) fdivrl 8(%esp) addl $20, %esp ret f4 compiles to a run-time division. Even at the assembly language level it is relatively easy to do constant folding of the division here. What confuses me about this is that g++ can clearly constant fold Double (x) and Double (y), but only when combined with an "even more constant" Double (1.2), not with each other. Release: gcc-3.2.1 Environment: Linux x86 How-To-Repeat: g++ -Wall -O3 -S -fomit-frame-pointer and look at the resulting .s file
Fix: Fixed in GCC 3.3, GCC 3.4 with: http://gcc.gnu.org/ml/gcc-patches/2003-03/msg01345.html
State-Changed-From-To: open->analyzed State-Changed-Why: Confirmed. This is actually a regression: up to gcc3.0.4, all four functions were compiled just as f1(), i.e. in an optimal way. Starting with 3.2, f2-f4 show the behavior Martin demonstrated. Not good :-(
From: mmitchel@gcc.gnu.org To: gcc-gnats@gcc.gnu.org Cc: Subject: optimization/9016 Date: 16 Mar 2003 20:13:37 -0000 CVSROOT: /cvs/gcc Module name: gcc Changes by: mmitchel@gcc.gnu.org 2003-03-16 20:13:37 Modified files: gcc : ChangeLog gcc/config/i386: i386.c Log message: PR optimization/9016 * config/i386/i386.c (ix86_expand_move): Force more CONST_DOUBLEs into the constant pool. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=1.17103&r2=1.17104 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/i386/i386.c.diff?cvsroot=gcc&r1=1.548&r2=1.549
From: mmitchel@gcc.gnu.org To: gcc-gnats@gcc.gnu.org Cc: Subject: optimization/9016 Date: 16 Mar 2003 20:15:04 -0000 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_3-branch Changes by: mmitchel@gcc.gnu.org 2003-03-16 20:15:04 Modified files: gcc : ChangeLog gcc/config/i386: i386.c Log message: PR optimization/9016 * config/i386/i386.c (ix86_expand_move): Force more CONST_DOUBLEs into the constant pool. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.16114.2.309&r2=1.16114.2.310 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/i386/i386.c.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.495.2.18&r2=1.495.2.19
State-Changed-From-To: analyzed->closed State-Changed-Why: Fixed for 3.3.