http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50346
Bug #: 50346 Summary: Function call foils VRP/jump-threading of redundant predicate on struct member Classification: Unclassified Product: gcc Version: 4.6.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: scov...@gmail.com When compiling the following code with options `-O3 -DBUG' : // === bug.cpp ======= struct foo { bool b; foo() : b(false) { } void baz(); }; bool bar(); void baz(); void test() { foo f; bool b = false; if (bar()) b = f.b = true; #ifndef BUG if (f.b != b) __builtin_unreachable(); #endif if (f.b) f.baz(); } // === end ========== gcc fails to eliminate the second (redundant) if statement: _Z4testv: .LFB3: subq $24, %rsp movb $0, 15(%rsp) <=== assign f.b = 0 call _Z3barv <=== cannot access f.b testb %al, %al je .L2 movb $1, 15(%rsp) .L3: leaq 15(%rsp), %rdi call _ZN3foo3bazEv addq $24, %rsp ret .L2: cmpb $0, 15(%rsp) <=== always compares equal jne .L3 addq $24, %rsp ret Compiling with `-O3 -UBUG' gives the expected results: _Z4testv: .LFB3: subq $24, %rsp movb $0, 15(%rsp) call _Z3barv testb %al, %al je .L1 leaq 15(%rsp), %rdi movb $1, 15(%rsp) call _ZN3foo3bazEv .L1: addq $24, %rsp ret This sort of scenario comes up a lot with RAII-related code, particularly when some code paths clean up the object manually before the destructor runs (obviating the need for the destructor to do it again). While it should be possible to give hints using __builtin_unreachable(), it's not always easy to tell where to put it, and it may need to be placed multiple times to be effective.