PR target/32803: Add -Oz option for improved clang compatibility.
authorRoger Sayle <roger@nextmovesoftware.com>
Sat, 18 Dec 2021 13:47:52 +0000 (13:47 +0000)
committerRoger Sayle <roger@nextmovesoftware.com>
Sat, 18 Dec 2021 13:47:52 +0000 (13:47 +0000)
commite742722f76c70be303248da7ca4842198d4fd1cc
treecaf44d6eb01f547b4cb58c4d158ddc475bfe4971
parentcc032ec1ecb34b006f42e170ccb9d76aa42fd8eb
PR target/32803: Add -Oz option for improved clang compatibility.

This patch adds support for an -Oz command line option, aggressively
optimizing for size at the expense of performance.  GCC's current -Os
provides a reasonable balance of size and performance, whereas -Oz is
probably only useful for code size benchmarks such as CSiBE.  Or so I
thought until I read in https://news.ycombinator.com/item?id=25408853
that clang's -Oz sometimes outperforms -O[23s]; I suspect modern instruction
decode stages can treat "pushq $1; popq %rax" as a short uop encoding.

Instead of introducing a new global variable, this patch simply abuses
the existing optimize_size by setting its value to 2.  The only change
in behaviour is the tweak to the i386 backend implementing the suggestion
in PR target/32803 to use a short push/pop sequence for loading small
immediate values (-128..127) on x86, matching the behaviour of LLVM.

On x86_64, the simple function:
int foo() { return 25; }

currently generates with -Os:
foo:    movl    $25, %eax       // 5 bytes
        ret

With the proposed -Oz, it generates:
foo:    pushq   $25             // 2 bytes
        popq    %rax            // 1 byte
        ret

On CSiBE, this results in a 0.94% improvement (3703513 bytes total
down to 3668516 bytes).

2021-12-18  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
PR target/32803
* common.opt (Oz): New command line option.
* doc/invoke.texi: Document the new -Oz option.
* lto-wrapper.c (merge_and_complain, append_compiler_options):
Treat OPT_Oz as synonymous with OPT_Os.
* optc-save-gen.awk: Increase maximum value of optimize_size to 2.
* opts.c (default_options_optimization) [OPT_Oz]: Handle OPT_Oz
just like OPT_Os, except set opt->x_optimize_size to 2.
(common_handle_option): Skip OPT_Oz just like OPT_Os.

* config/i386/i386.md (*movdi_internal): Use a push/pop sequence
for suitable SImode TYPE_IMOV moves when optimize_size > 1.
(*movsi_internal): Likewise.

gcc/testsuite/ChangeLog
PR target/32803
* gcc.target/i386/pr32803.c: New test case.
gcc/common.opt
gcc/config/i386/i386.md
gcc/doc/invoke.texi
gcc/lto-wrapper.c
gcc/optc-save-gen.awk
gcc/opts.c
gcc/testsuite/gcc.target/i386/pr32803.c [new file with mode: 0644]