public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-6057] PR target/32803: Add -Oz option for improved clang compatibility.
@ 2021-12-18 13:49 Roger Sayle
  0 siblings, 0 replies; only message in thread
From: Roger Sayle @ 2021-12-18 13:49 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:e742722f76c70be303248da7ca4842198d4fd1cc

commit r12-6057-ge742722f76c70be303248da7ca4842198d4fd1cc
Author: Roger Sayle <roger@nextmovesoftware.com>
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  <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.

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<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:
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" } } */


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-12-18 13:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-18 13:49 [gcc r12-6057] PR target/32803: Add -Oz option for improved clang compatibility Roger Sayle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).