https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104950
--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Andrew Pinski from comment #1) > Confirmed, reduced testcase: > struct Node{ > int i, l,r; > }; > int eval(int t, struct Node *a) { > return t == 0 ? a->r : a->l; > } > > Note on aarch64, if we remove the i field, then ifcvt on the RTL level is > able to catch it but it does not do it for x86_64 (maybe a cost issue). I think it's for the fear of one of a->r / a->l trapping while the other is not. With struct Node{ int i, l,r; }; int eval(int t, struct Node *a) { int r = a->r; int l = a->l; return t == 0 ? r : l; } and using -fno-tree-sink we get branchless code on x86_64. I think we can use TBAA to argue that *a should be valid to dereference here. What Andrew shows with removing 'i' is likely struct Node then having large enough alignment guarantees(?) or a bug in the aarch64 backend.