cat test.c void foo(void); void bar(void); static char b = 2; static int d = -2, e; static int a(int f, int g) { return (g & -g) < 0 ? f : f - g; } int main() { d = 0; d = b; bar(); e = a(0, 0); if (a(-2, d) > 1) foo(); } 13.0.0 at -O3 can eliminate the call to foo but trunk cannot: clang-13 -O3 -S -o /dev/stdout test.c ... main: # @main .cfi_startproc # %bb.0: pushq %rax .cfi_def_cfa_offset 16 movb $1, d(%rip) callq bar xorl %eax, %eax popq %rcx .cfi_def_cfa_offset 8 retq clang-trunk -O3 -S -o /dev/stdout case13_clean.c ... main: # @main .cfi_startproc # %bb.0: pushq %rax .cfi_def_cfa_offset 16 movb $1, d(%rip) callq bar movzbl d(%rip), %eax leal -2(,%rax,4), %ecx movl %eax, %edx shll $2, %edx movl $2, %esi subl %edx, %esi testl %esi, %ecx js .LBB0_3 # %bb.1: leal -1(,%rax,4), %eax cmpl $-3, %eax jg .LBB0_3 # %bb.2: callq foo .LBB0_3: xorl %eax, %eax popq %rcx .cfi_def_cfa_offset 8 retq clang-trunk -v clang version 14.0.0 (https://github.com/llvm/llvm-project.git eda2ebd7807376829eb880c39623f364b438971f) Target: x86_64-unknown-linux-gnu Thread model: posix https://github.com/llvm/llvm-project/commit/da210f5d3425e8877ceabaf6ed3483d52cbd7448 introduced this regression
This select optimization falls through the cracks in -instcombine: define i32 @src(i1 %b) { %s = select i1 %b, i32 2, i32 -2 %n = sub nsw i32 0, %s %a = and i32 %s, %n ret i32 %a } define i32 @tgt(i1 %b) { ret i32 2 } https://alive2.llvm.org/ce/z/ckiVjn
That's an extreme example of a general problem - we don't thread a binop back into the arms of a select operand with constant arms when it has >1 use.
https://reviews.llvm.org/D112657
https://reviews.llvm.org/rGe8535fa78458