From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1251) id 6522A3858D28; Sat, 18 Dec 2021 13:49:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6522A3858D28 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Roger Sayle To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-6057] PR target/32803: Add -Oz option for improved clang compatibility. X-Act-Checkin: gcc X-Git-Author: Roger Sayle X-Git-Refname: refs/heads/master X-Git-Oldrev: cc032ec1ecb34b006f42e170ccb9d76aa42fd8eb X-Git-Newrev: e742722f76c70be303248da7ca4842198d4fd1cc Message-Id: <20211218134922.6522A3858D28@sourceware.org> Date: Sat, 18 Dec 2021 13:49:22 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 18 Dec 2021 13:49:22 -0000 https://gcc.gnu.org/g:e742722f76c70be303248da7ca4842198d4fd1cc commit r12-6057-ge742722f76c70be303248da7ca4842198d4fd1cc Author: Roger Sayle Date: Sat Dec 18 13:47:52 2021 +0000 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 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. Diff: --- gcc/common.opt | 4 ++++ gcc/config/i386/i386.md | 17 ++++++++++++++++- gcc/doc/invoke.texi | 9 ++++++++- gcc/lto-wrapper.c | 7 ++++++- gcc/optc-save-gen.awk | 2 +- gcc/opts.c | 10 ++++++++++ gcc/testsuite/gcc.target/i386/pr32803.c | 10 ++++++++++ 7 files changed, 55 insertions(+), 4 deletions(-) diff --git a/gcc/common.opt b/gcc/common.opt index 4af89ce8fd2..2ed818d6057 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -483,6 +483,10 @@ Og Common Optimization Optimize for debugging experience rather than speed or size. +Oz +Common Optimization +Optimize for space aggressively rather than speed. + Q Driver diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index f6d9c4ba6cc..862d933465b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -2213,7 +2213,14 @@ case TYPE_IMOV: gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1])); if (get_attr_mode (insn) == MODE_SI) - return "mov{l}\t{%k1, %k0|%k0, %k1}"; + { + if (optimize_size > 1 + && TARGET_64BIT + && CONST_INT_P (operands[1]) + && IN_RANGE (INTVAL (operands[1]), -128, 127)) + return "push{q}\t%1\n\tpop{q}\t%0"; + return "mov{l}\t{%k1, %k0|%k0, %k1}"; + } else if (which_alternative == 4) return "movabs{q}\t{%1, %0|%0, %1}"; else if (ix86_use_lea_for_mov (insn, operands)) @@ -2431,6 +2438,14 @@ gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1])); if (ix86_use_lea_for_mov (insn, operands)) return "lea{l}\t{%E1, %0|%0, %E1}"; + else if (optimize_size > 1 + && CONST_INT_P (operands[1]) + && IN_RANGE (INTVAL (operands[1]), -128, 127)) + { + if (TARGET_64BIT) + return "push{q}\t%1\n\tpop{q}\t%q0"; + return "push{l}\t%1\n\tpop{l}\t%0"; + } else return "mov{l}\t{%1, %0|%0, %1}"; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index de552b5a88a..ca621577432 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -588,7 +588,7 @@ Objective-C and Objective-C++ Dialects}. -fipa-ra -fvariable-expansion-in-unroller -fvect-cost-model -fvpt @gol -fweb -fwhole-program -fwpa -fuse-linker-plugin -fzero-call-used-regs @gol --param @var{name}=@var{value} --O -O0 -O1 -O2 -O3 -Os -Ofast -Og} +-O -O0 -O1 -O2 -O3 -Os -Ofast -Og -Oz} @item Program Instrumentation Options @xref{Instrumentation Options,,Program Instrumentation Options}. @@ -10734,6 +10734,13 @@ optimization flags except for those that may interfere with debugging: -fmove-loop-invariants -fmove-loop-stores -fssa-phiopt @gol -ftree-bit-ccp -ftree-dse -ftree-pta -ftree-sra} +@item -Oz +@opindex Oz +Optimize aggressively for size rather than speed. This may increase +the number of instructions executed if those instructions require +fewer bytes to encode. @option{-Oz} behaves similarly to @option{-Os} +including enabling most @option{-O2} optimizations. + @end table If you use multiple @option{-O} options, with or without level numbers, diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index 54f642d7692..7d2b7e56ded 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -370,12 +370,14 @@ merge_and_complain (vec &decoded_options, case OPT_Ofast: case OPT_Og: case OPT_Os: + case OPT_Oz: existing_opt = -1; for (j = 0; j < decoded_options.length (); ++j) if (decoded_options[j].opt_index == OPT_O || decoded_options[j].opt_index == OPT_Ofast || decoded_options[j].opt_index == OPT_Og - || decoded_options[j].opt_index == OPT_Os) + || decoded_options[j].opt_index == OPT_Os + || decoded_options[j].opt_index == OPT_Oz) { existing_opt = j; break; @@ -407,6 +409,7 @@ merge_and_complain (vec &decoded_options, level = MAX (level, 1); break; case OPT_Os: + case OPT_Oz: level = MAX (level, 2); break; default: @@ -428,6 +431,7 @@ merge_and_complain (vec &decoded_options, level = MAX (level, 1); break; case OPT_Os: + case OPT_Oz: level = MAX (level, 2); break; default: @@ -725,6 +729,7 @@ append_compiler_options (obstack *argv_obstack, vec opts) case OPT_Ofast: case OPT_Og: case OPT_Os: + case OPT_Oz: break; case OPT_Xassembler: diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk index e363ac731e1..81c2db03f63 100644 --- a/gcc/optc-save-gen.awk +++ b/gcc/optc-save-gen.awk @@ -93,7 +93,7 @@ var_opt_char[1] = "optimize_size"; var_opt_char[2] = "optimize_debug"; var_opt_char[3] = "optimize_fast"; var_opt_range["optimize"] = "0, 255"; -var_opt_range["optimize_size"] = "0, 1"; +var_opt_range["optimize_size"] = "0, 2"; var_opt_range["optimize_debug"] = "0, 1"; var_opt_range["optimize_fast"] = "0, 1"; diff --git a/gcc/opts.c b/gcc/opts.c index 870cceca85a..f45ecc56726 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -745,6 +745,15 @@ default_options_optimization (struct gcc_options *opts, opts->x_optimize_debug = 0; break; + case OPT_Oz: + opts->x_optimize_size = 2; + + /* Optimizing for size forces optimize to be 2. */ + opts->x_optimize = 2; + opts->x_optimize_fast = 0; + opts->x_optimize_debug = 0; + break; + case OPT_Ofast: /* -Ofast only adds flags to -O3. */ opts->x_optimize_size = 0; @@ -2609,6 +2618,7 @@ common_handle_option (struct gcc_options *opts, case OPT_Os: case OPT_Ofast: case OPT_Og: + case OPT_Oz: /* Currently handled in a prescan. */ break; diff --git a/gcc/testsuite/gcc.target/i386/pr32803.c b/gcc/testsuite/gcc.target/i386/pr32803.c new file mode 100644 index 00000000000..f26f07a3b29 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr32803.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-Oz" } */ + +int foo() +{ + return 25; +} + +/* { dg-final { scan-assembler "push" } } */ +/* { dg-final { scan-assembler "pop" } } */