diff mbox

[RS6000,6/7] Cost multi-insn constants

Message ID 20150624005450.GA1723@bubble.grove.modra.org
State New
Headers show

Commit Message

Alan Modra June 24, 2015, 12:54 a.m. UTC
This small patch considerably improves code generated for large
constants in 64-bit code, teaching gcc that it is better to load a
constant from memory than to generate a sequence of five dependent
instructions.  Note that we already do this at expand time for plain
moves.  This change affects constants inside other RTL operations,
ie. those generated by various optimizations.

I would like to fix rtlanal.c:rtx_cost to not cost register moves at
zero, but that probably disrupts many targets.  See the comment.

	* config/rs6000/rs6000.c (rs6000_rtx_costs): Cost multi-insn
	CONST_INTs.
diff mbox

Patch

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 941ad02..0218d0f 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -30700,6 +30700,26 @@  rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code,
 
     case CONST_DOUBLE:
     case CONST_WIDE_INT:
+      /* Subtract one insn here for consistency with the above code
+	 that returns one less than the actual number of insns for
+	 SETs.  This is because (set (reg1) (reg2)) is costed at zero
+	 by rtlanal.c:rtx_cost.  If we cost (set (reg) (const_int 0))
+	 at greater than the register move cost, then a call like
+	 foo (0, 0) will be implemented as li "r3,0; mr r4,r3; bl foo"
+	 rather than "li r3,0; li r4,0; bl foo".  Don't subtract one
+	 for other than SETs, because other operations will require
+	 the constant to be loaded to a register before performing
+	 the operation.
+	 FIXME: A call like foo (x - 1, x - 1) results in
+	 "addi r3,rx,-1; mr r4,r3; bl foo" rather than the better
+	 "addi r3,rx,-1; addi r4,rx,-1; bl foo" because rtx_cost
+	 returns zero for register moves.  This cannot be fixed by
+	 reducing the cost of PLUS and other arithmetic/logic codes
+	 to zero.  */
+      *total = COSTS_N_INSNS (num_insns_constant (x, mode)
+			      - (outer_code == SET ? 1 : 0));
+      return true;
+
     case CONST:
     case HIGH:
     case SYMBOL_REF: