The following testcase:
class Flag { public: Flag(bool f) : flag(f) {} bool test() const { return flag; } private: const bool flag; }; void bar(void); void foo(const Flag& f) { if (f.test()) bar(); if (f.test()) bar(); } Should from my point of view should generate exactly one test and optimize the redundant one. I miss what could be a not ill-formed way of bar() modifying Flag::flag. With mainline -O2 -S -fdump-tree-optimized-vops we get for t63.optimized: <bb 0>: if (f->flag != 0) goto <L1>; else goto <L2>; <L1>:; # TMT.2_17 = V_MAY_DEF <TMT.2_15>; bar (); <L2>:; if (f->flag != 0) goto <L4>; else goto <L5>; <L4>:; # TMT.2_16 = V_MAY_DEF <TMT.2_14>; bar () [tail call]; <L5>:; return; The RTL optimizers exploit a valid optimization, namely: _Z3fooRK4Flag: .LFB6: pushl %ebx # .LCFI0: subl $8, %esp #, .LCFI1: movl 16(%esp), %ebx # f, f cmpb $0, (%ebx) # <variable>.flag jne .L8 #, .L6: addl $8, %esp #, popl %ebx # ret .p2align 4,,7 .L8: call _Z3barv # cmpb $0, (%ebx) # <variable>.flag .p2align 4,,4 je .L6 #, addl $8, %esp #, popl %ebx # jmp _Z3barv # where you can see we optimized the function into the equivalent of if (!f.test()) return; bar(); if (!f.test()) return; bar(); Who is supposed to apply the corresponding tree optimization here? Of course, I think it is valid to omit the second test completely as there is no valid way for bar() to change Flag::flag. Note that this may be a frontend issue, as to the tree-optimizers this may be no different than void foo(const bool& f) { if (f) bar(); if (f) bar(); } where there of course are valid ways for bar() to change f. -- Summary: missed tree-optimization Product: gcc Version: 4.0.0 Status: UNCONFIRMED Severity: normal Priority: P2 Component: tree-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: rguenth at tat dot physik dot uni-tuebingen dot de CC: gcc-bugs at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19507