]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Tweak -Os costs for scalar-to-vector pass.
authorRoger Sayle <roger@nextmovesoftware.com>
Tue, 24 Aug 2021 02:04:48 +0000 (03:04 +0100)
committerRoger Sayle <roger@nextmovesoftware.com>
Tue, 24 Aug 2021 02:04:48 +0000 (03:04 +0100)
Back in June I briefly mentioned in one of my gcc-patches posts that
a change that should have always reduced code size, would mysteriously
occasionally result in slightly larger code (according to CSiBE):
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573233.html

Investigating further, the cause turns out to be that x86_64's
scalar-to-vector (stv) pass is relying on poor estimates of the size
costs/benefits.  This patch tweaks the backend's compute_convert_gain
method to provide slightly more accurate values when compiling with
-Os. Compilation without -Os is (should be) unaffected.  And for
completeness, I'll mention that the stv pass is a net win for code
size so it's much better to improve its heuristics than simply gate
the pass on !optimize_for_size.

The net effect of this change is to save 1399 bytes on the CSiBE
code size benchmark when compiling with -Os.

2021-08-24  Roger Sayle  <roger@nextmovesoftware.com>
    Richard Biener  <rguenther@suse.de>

gcc/ChangeLog
* config/i386/i386-features.c (compute_convert_gain): Provide
more accurate values for CONST_INT, when optimizing for size.
* config/i386/i386.c (COSTS_N_BYTES): Move definition from here...
* config/i386/i386.h (COSTS_N_BYTES): to here.

gcc/config/i386/i386-features.c
gcc/config/i386/i386.c
gcc/config/i386/i386.h

index d9c6652d1c9c560c69602cf818daba81f5835fb8..5a99ea7c0465f74163936762e719074531ab0171 100644 (file)
@@ -610,12 +610,40 @@ general_scalar_chain::compute_convert_gain ()
 
          case CONST_INT:
            if (REG_P (dst))
-             /* DImode can be immediate for TARGET_64BIT and SImode always.  */
-             igain += m * COSTS_N_INSNS (1);
+             {
+               if (optimize_insn_for_size_p ())
+                 {
+                   /* xor (2 bytes) vs. xorps (3 bytes).  */
+                   if (src == const0_rtx)
+                     igain -= COSTS_N_BYTES (1);
+                   /* movdi_internal vs. movv2di_internal.  */
+                   /* => mov (5 bytes) vs. movaps (7 bytes).  */
+                   else if (x86_64_immediate_operand (src, SImode))
+                     igain -= COSTS_N_BYTES (2);
+                   else
+                     /* ??? Larger immediate constants are placed in the
+                        constant pool, where the size benefit/impact of
+                        STV conversion is affected by whether and how
+                        often each constant pool entry is shared/reused.
+                        The value below is empirically derived from the
+                        CSiBE benchmark (and the optimal value may drift
+                        over time).  */
+                     igain += COSTS_N_BYTES (0);
+                 }
+               else
+                 {
+                   /* DImode can be immediate for TARGET_64BIT
+                      and SImode always.  */
+                   igain += m * COSTS_N_INSNS (1);
+                   igain -= vector_const_cost (src);
+                 }
+             }
            else if (MEM_P (dst))
-             igain += (m * ix86_cost->int_store[2]
-                       - ix86_cost->sse_store[sse_cost_idx]);
-           igain -= vector_const_cost (src);
+             {
+               igain += (m * ix86_cost->int_store[2]
+                         - ix86_cost->sse_store[sse_cost_idx]);
+               igain -= vector_const_cost (src);
+             }
            break;
 
          default:
index 46844fab08f82b6f502cdfbd00331ae9106d477d..5bff131f6d9e908cfbe6c4314bc57bdf3108d650 100644 (file)
@@ -19982,8 +19982,6 @@ ix86_division_cost (const struct processor_costs *cost,
     return cost->divide[MODE_INDEX (mode)];
 }
 
-#define COSTS_N_BYTES(N) ((N) * 2)
-
 /* Return cost of shift in MODE.
    If CONSTANT_OP1 is true, the op1 value is known and set in OP1_VAL.
    AND_IN_OP1 specify in op1 is result of and and SHIFT_AND_TRUNCATE
index 8aba86d11b4bd63706a313df220b38a93933e086..11ac8d01100394d6cfcf387420dbed2987dc8ab7 100644 (file)
@@ -88,6 +88,11 @@ struct stringop_algs
   } size [MAX_STRINGOP_ALGS];
 };
 
+/* Analog of COSTS_N_INSNS when optimizing for size.  */
+#ifndef COSTS_N_BYTES
+#define COSTS_N_BYTES(N) ((N) * 2)
+#endif
+
 /* Define the specific costs for a given cpu.  NB: hard_register is used
    by TARGET_REGISTER_MOVE_COST and TARGET_MEMORY_MOVE_COST to compute
    hard register move costs by register allocator.  Relative costs of