https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91965
Bug ID: 91965 Summary: missing simplification for (C - a) << N Product: gcc Version: 9.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: amonakov at gcc dot gnu.org Target Milestone: --- Noticed this issue when preparing a testcase for PR 87047. We do not simplify (1048575ull - x) << 44 on GIMPLE: unsigned long long foo(unsigned long long a) { return (1048575 - a) << 44; } void bar(unsigned long long *a) { for (int i = 0; i < 1024; i++) a[i] = foo(a[i]); } we use (~a)<<44 for 'foo', but that is thanks to combine, in 'bar' combine doesn't make the same transform (the 1048575 constant is moved into a pseudo in another BB, and combine doesn't know that's the only use): foo: movq %rdi, %rax notq %rax salq $44, %rax ret bar: leaq 8192(%rdi), %rcx movl $1048575, %edx .L4: movq %rdx, %rax subq (%rdi), %rax addq $8, %rdi salq $44, %rax movq %rax, -8(%rdi) cmpq %rcx, %rdi jne .L4 ret Do we want to handle this early on via match.pd? Perhaps also applies to simplifying (a +- C) << N.