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.
This commit is contained in:
parent
cc032ec1ec
commit
e742722f76
7 changed files with 55 additions and 4 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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}";
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -370,12 +370,14 @@ merge_and_complain (vec<cl_decoded_option> &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<cl_decoded_option> &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<cl_decoded_option> &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<cl_decoded_option> opts)
|
|||
case OPT_Ofast:
|
||||
case OPT_Og:
|
||||
case OPT_Os:
|
||||
case OPT_Oz:
|
||||
break;
|
||||
|
||||
case OPT_Xassembler:
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
10
gcc/opts.c
10
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;
|
||||
|
||||
|
|
10
gcc/testsuite/gcc.target/i386/pr32803.c
Normal file
10
gcc/testsuite/gcc.target/i386/pr32803.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-Oz" } */
|
||||
|
||||
int foo()
|
||||
{
|
||||
return 25;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler "push" } } */
|
||||
/* { dg-final { scan-assembler "pop" } } */
|
Loading…
Add table
Reference in a new issue