https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84470
Bug ID: 84470 Summary: test for address of member being null not eliminated Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- The address of a member subobject can never be null. If it were, the address if the enclosing object would either have to be null which would make the member access expression (i.e., p->member) undefined, or the address of the object would have such that adding the offset of the member to it would wrap around zero, which would make the addition undefined. As a result, tests for the address of a member object being null can be eliminated. The test case below shows that GCC doesn't take advantage of this invariant. In constrast, Clang does take advantage of it for all but the first member. $ cat a.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout a.c struct A { char a[4]; }; void f (struct A *p) { if (p->a == 0) // could only be true when p is null __builtin_abort (); // can be eliminated } struct B { char a[4]; }; void b (struct B *p) { if (p->a == 0) // can never be true __builtin_abort (); // can be eliminated (as Clang does) } ;; Function f (f, funcdef_no=0, decl_uid=1959, cgraph_uid=0, symbol_order=0) f (struct A * p) { char[4] * _1; <bb 2> [local count: 1073741825]: _1 = &p_2(D)->a; if (_1 == 0B) goto <bb 3>; [0.00%] else goto <bb 4>; [99.96%] <bb 3> [count: 0]: __builtin_abort (); <bb 4> [local count: 1073312327]: return; } ;; Function b (b, funcdef_no=1, decl_uid=1964, cgraph_uid=1, symbol_order=1) b (struct B * p) { char[4] * _1; <bb 2> [local count: 1073741825]: _1 = &p_2(D)->a; if (_1 == 0B) goto <bb 3>; [0.00%] else goto <bb 4>; [99.96%] <bb 3> [count: 0]: __builtin_abort (); <bb 4> [local count: 1073312327]: return; }