@@ -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: