I hope the summary is descriptive enough. Take the following code: ----- testcase.c ----- void bar(void); void foo(int c) { if (c) bar(); } ---------------------- With -O3, gcc generated this code: foo: .LFB0: .cfi_startproc test edi, edi # c jne .L4 #, rep ret .p2align 4,,10 .p2align 3 .L4: jmp bar # .cfi_endproc and with -Os: foo: .LFB0: .cfi_startproc test edi, edi # c je .L1 #, jmp bar # .L1: ret .cfi_endproc while better would be: foo: test edi, edi jne .L1 rep # only without -Os ret I tested 3.3.6, 3.4.6, 4.4.5, 4.6.0, neither generates the "better" code.
(In reply to comment #0) > I hope the summary is descriptive enough. > Take the following code: > > ----- testcase.c ----- > void bar(void); > > void foo(int c) > { > if (c) bar(); > } .. > while better would be: > foo: > test edi, edi > jne .L1 > rep # only without -Os > ret > Where is .L1?
(In reply to comment #1) > > Where is .L1? Thanks, it should be: foo: test edi, edi jne bar rep # only without -Os ret
jne only takes 8bit displacement.
(In reply to comment #3) > jne only takes 8bit displacement. There are two opcodes for jne - 0x75 taking 8bit displacement, and 0x0f 0x85 taking 16/32bit displacement: (pasted from IA-32 Intel Architecture Software Developer’s Manual Volume 2: Instruction Set Reference) 75 cb JNE rel8 Jump short if not equal (ZF=0) 0F 85 cw/cd JNE rel16/32 Jump near if not equal (ZF=0) Jcc is no different from JMP, both can take 8/(16/)32bit displacement - even in 64bit mode.
*** Bug 69576 has been marked as a duplicate of this bug. ***
*** Bug 60159 has been marked as a duplicate of this bug. ***
*** Bug 109844 has been marked as a duplicate of this bug. ***
Another repro: https://godbolt.org/z/K4zc6GMjY Given the code: > void t(), f(); > > void decide(bool ok) { > if (ok) { > t(); > } else { > f(); > } > } GCC emits: > decide(bool): > test dil, dil > je .L2 > jmp t() > .L2: > jmp f() This contains a je to a jmp instruction, which is obviously redundant. The expected output (Clang, MSVC) is: > decide(bool): > test edi, edi > je f()@PLT > jmp t()@PLT
Created attachment 60445 [details] A patch [hjl@gnu-tgl-3 pr47253]$ cat y.c void t(), f(); void decide(bool ok) { if (ok) t(); else f(); } [hjl@gnu-tgl-3 pr47253]$ make y.s /export/build/gnu/tools-build/gcc-gitlab-debug/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/tools-build/gcc-gitlab-debug/build-x86_64-linux/gcc/ -O2 -S y.c [hjl@gnu-tgl-3 pr47253]$ cat y.s .file "y.c" .text .p2align 4 .globl decide .type decide, @function decide: .LFB0: .cfi_startproc testb %dil, %dil je f jmp t .p2align 4,,10 .p2align 3 .L2: jmp f .cfi_endproc .LFE0: .size decide, .-decide .ident "GCC: (GNU) 15.0.1 20250210 (experimental)" .section .note.GNU-stack,"",@progbits [hjl@gnu-tgl-3 pr47253]$ But the unreachable basic block isn't removed.
Created attachment 60446 [details] An updated patch This patch deletes the unreachable block.
Created attachment 60448 [details] An improved patch with tests
Created attachment 60454 [details] An updated patch This patch passed "make bootstrap" with C/C++.
Created attachment 60457 [details] A new patch
Created attachment 60458 [details] A patch to fold jump table with tests I got [hjl@gnu-tgl-3 pr47253]$ cat j.c void bar0 (void); void bar1 (void); void bar2 (void); void bar3 (void); void bar4 (void); void foo (int i) { switch (i) { case 0: bar0 (); break; case 1: bar1 (); break; case 2: bar2 (); break; case 3: bar3 (); break; case 4: bar4 (); break; } } [hjl@gnu-tgl-3 pr47253]$ cat j.s .file "j.c" .text .p2align 4 .globl foo .type foo, @function foo: .LFB0: .cfi_startproc cmpl $4, %edi ja .L1 movl %edi, %edi jmp *.L4(,%rdi,8) .section .rodata .align 8 .align 4 .L4: .quad bar0 .quad bar1 .quad bar2 .quad bar3 .quad bar4 .text .L1: ret .cfi_endproc .LFE0: .size foo, .-foo .ident "GCC: (GNU) 15.0.1 20250211 (experimental)" .section .note.GNU-stack,"",@progbits [hjl@gnu-tgl-3 pr47253]$
Created attachment 60460 [details] A patch to fold sibcall
Created attachment 60461 [details] An updated patch to fold sibcall in jump table
My current patches are at https://gitlab.com/x86-gcc/gcc/-/tree/users/hjl/condjmp/master?ref_type=heads
My current patches are at https://gitlab.com/x86-gcc/gcc/-/tree/users/hjl/condjmp/v7?ref_type=heads They passed GCC bootstrap and tests on x86-64.
*** Bug 119299 has been marked as a duplicate of this bug. ***