https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66776
Bug ID: 66776 Summary: [AArch64] zero-extend version of csel not matching properly Product: gcc Version: 6.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: ktkachov at gcc dot gnu.org Target Milestone: --- Consider the code: unsigned long foo (unsigned int a, unsigned int b, unsigned int c) { return a ? b : c; } On aarch64 this generates: foo: uxtw x1, w1 cmp w0, wzr uxtw x2, w2 csel x0, x2, x1, eq ret where in fact it could generate: cmp w0, #0 csel w0, w1, w2, ne ret A write to the 32-bit w-register implicitly zero-extends the value up to the full 64 bits of an x-register. This is reflected in aarch64.md by the cmovsi_insn_uxtw pattern that matches: (set (dest:DI) (zero_extend:DI (if_then_else:SI (cond) (src1:SI) (src2:SI)) ) ) However, this doesn't get matched because combine instead tries to match (set (dest:DI) (if_then_else:DI (cond) (zero_extend:DI (src1:SI)) (zero_extend:DI (src2:SI)) ) ) As discussed in PR66588 it seems preferable to write the *cmovsi_insn_uxtw pattern with the zero_extends inside the arms of the if_then_else