cat test.c void foo(void); static int a; static int *b = &a; static int **c = &b; static char e; static unsigned d() { if (c) return a; else return 1; } int main() { int f = d(); unsigned char g = f; e = g >> 4; if (e) { for (;;) { if (f) break; c = 0; foo(); } for (;;) ; } } 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: testb $-16, a(%rip) je .LBB0_2 .p2align 4, 0x90 .LBB0_1: # =>This Inner Loop Header: Depth=1 jmp .LBB0_1 .LBB0_2: xorl %eax, %eax retq clang-trunk -O3 -S -o /dev/stdout test.c main: # @main .cfi_startproc # %bb.0: pushq %rax .cfi_def_cfa_offset 16 cmpq $0, c(%rip) movl $1, %eax je .LBB0_2 # %bb.1: movl a(%rip), %eax .LBB0_2: cmpb $16, %al jae .LBB0_3 # %bb.6: xorl %eax, %eax popq %rcx .cfi_def_cfa_offset 8 retq .LBB0_3: .cfi_def_cfa_offset 16 testl %eax, %eax je .LBB0_4 .p2align 4, 0x90 .LBB0_5: # =>This Inner Loop Header: Depth=1 jmp .LBB0_5 .p2align 4, 0x90 .LBB0_4: # =>This Inner Loop Header: Depth=1 movq $0, c(%rip) callq foo jmp .LBB0_4 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/f32c0fe8e50534f4210d878b9a1420793860c567 introduced this regression
void foo(void); static int a[] = {0, 0, 1}; static int b; static unsigned char c; int main() { for (; b >= 0; b--) { unsigned char d = a[b]; c = d >> 1; if (c) foo(); } } this test case also triggers the regression
Still stepping through, so I'm not sure if this is the entire problem, but are missing an icmp canonicalization and/or analysis to recognize this: https://alive2.llvm.org/ce/z/7-6UPc declare void @llvm.assume(i1) declare i8 @llvm.ctpop.i8(i8) define i1 @src(i32 %x, i8 %C) { ; compare constant must be power-of-2 %pop = call i8 @llvm.ctpop.i8(i8 %C) %ispow2 = icmp eq i8 %pop, 1 call void @llvm.assume(i1 %ispow2) %t = trunc i32 %x to i8 %tobool = icmp ult i8 %t, %C ret i1 %tobool } define i1 @tgt(i32 %x, i8 %C) { ; create mask constant for source type %zextC = zext i8 %C to i32 %maskC = sub i32 256, %zextC %a = and i32 %x, %maskC %tobool = icmp eq i32 %a, 0 ret i1 %tobool }
I plan to extend this: https://reviews.llvm.org/rGacabad9ff6bf ...but that should solve the examples in this report.