public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] rtx_costs vs. const_int
@ 2015-06-15  3:50 Alan Modra
  2015-06-15 18:40 ` Segher Boessenkool
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Alan Modra @ 2015-06-15  3:50 UTC (permalink / raw)
  To: gcc-patches

This patch changes the targetm.rtx_costs interface to pass a mode
parameter, and removes a redundant parameter.  The reason for the
change is that powerpc and other backends need the mode that a
const_int is used in to properly determine the cost.  For instance,
(set (reg) (ior (reg) (const_int))) where const_int is 0xff..ffff0000
can be implemented in one instruction on powerpc if the regs and
constant are SImode, but not when DImode.

Some backends work around this problem by calculating the cost of the
entire expression under the IOR, which allows the mode of the
const_int to be inferred.  This of course results in huge rtx_costs
functions since you must inspect the operands of many rtx codes that
take const_int operands.  Worse, it doesn't work for all calls to
targetm.rtx_costs;  gcc doesn't always pass an entire insn, or even
the complete right hand side of a SET, to rtx_costs.  One place this
is seen is in expand, for example, emit_store_flag makes calls like
  rtx_cost (GEN_INT (normalizep), PLUS, ...)
This sort of thing seems like a fundamental requirement in expand
where insns are being built.  cse also makes similar calls.  So
rtx_cost must be able to handle sub-expressions of an insn.

As to the patch itself, the bulk is mostly mechanical.  I haven't made
any simplification to the arm, aarch64 and mips rtx_costs that might
be possible with this interface change.  rtlanal.c:rtx_cost also needs
a machine_mode parameter to deal with the expand rtl mentioned above,
as do a few other rtx cost functions.  sub-rtx's in rtx_cost are
summed in order rather than reverse order so that the mode from an
earlier operand can be used for a later operand lacking a mode.  This
is for ZERO_EXTEND and similar codes where the sub-rtx mode is
different to the outer mode.  Canonicalization puts const_int operands
after other operands.

I moved some inline functions in rtl.h later in the file because an
earlier patch iteration passed GET_MODE (SET_DEST (x)) as the mode in
set_rtx_cost and get_full_set_rtx_cost.  That meant the inlines needed
to be after the definition of SET_DEST.  Later I realized that
rtx_cost needed to provide the mode for a SET anyway, so VOIDmode
would do just as well in set_rtx_cost.  That means the inlines don't
need to be moved, but their new location seems better.

The patch also doesn't contain any real changes to the powerpc
backend, and in fact produces worse code than before in cases where
rldic should be allowed by combine.  A later patch will cure the
powerpc regressions.

The patch was tested by full powerpc64-linux and x86_64-linux
regression testing, and building cross-compilers for aarch64-linux,
alpha-linux, arc-elf, arm-linuxeabi, avr-elf, bfin-elf, cris-linux,
epiphany-elf, frv-linux, h8300-linux, hppa-linux, ia64-linux,
iq2000-elf, lm32-elf, m32c-elf, m32r-elf, m68k-linux, mcore-elf,
mep-elf, microblaze-linux, mips64-linux, mmix, mn10300-elf,
msp430-elf, nds32le-elf, pdp11-aout, rl78-elf, s390x-linux,
sh64-linux, sparc64-linux, spu-elf, tic6x-elf, tilegx-linux,
tilepro-linux, v850-elf, vax-linux, visium-elf, xstormy16-elf, and
xtensa-linux.  I examined x86_64-linux gcc/*.o files and didn't see
any unexpected changes.

The testing showed some pre-existing bugs..

arc-elf dies on attempting to assemble first libgcc file, due to gas
not understanding the options being passed by gcc.  Apparently no one
cared enough to push gas changes upstream.

ia64-linux, m68k-linux, tilegx-linux and tilepro-linux have
dependencies on include files, not solved by -Dinhibit_libc, so die
building libgcc.  Can be solved by hand, but annoying.

iq2000-elf: internal compiler error: in dwarf2out_var_location, at
dwarf2out.c:22302.

mep-elf: internal compiler error: in pre_and_rev_post_order_compute,
at cfganal.c:1029

s390x-linux doesn't build as a cross-compiler.  undefined reference to
`s390_host_detect_local_cpu(int, char const**)'

tic6x-elf hits gas errors: Error: inconsistent uses of .cfi_sections

vax-linux: internal compiler error: Segmentation fault.  Due to trying
to find MEM_ADDR_SPACE of a SUBREG in this insn predicate
   && (REG_P (operands[1])
       || ! mode_dependent_address_p (XEXP (operands[1], 0),
				      MEM_ADDR_SPACE (operands[1])))"


	* target.def (rtx_costs): Remove "code" param, add "mode".
	* rtl.h (rtx_cost, get_full_rtx_cost): Update prototype.
	(set_src_cost, get_full_set_src_cost): Likewise.  Move later in file.
	(set_rtx_cost, get_full_set_rtx_cost): Move later in file.
	* rtlanal.c (rtx_cost): Add "mode" parameter.  Update targetm.rtx_costs
	call.  Track mode when given in rtx.
	(get_full_rtx_cost): Add "mode" parameter.  Update rtx_cost calls.
	(default_address_cost): Pass Pmode to rtx_cost.
	(insn_rtx_cost): Pass dest mode of set to set_src_cost.
	* cprop.c (try_replace_reg): Ensure set_rtx_cost is not called
	with NULL set.
	* cse.c (COST, COST_IN): Add MODE param.  Update all uses.
	(notreg_cost): Add mode param.  Use it.
	* gcse.c (want_to_gcse_p): Delete forward declaration.  Add
	mode param and pass to set_src_cost.  Update all calls.
	(hash_scan_set): Formatting.
	* hooks.c (hook_bool_rtx_int_int_int_intp_bool_false): Delete.
	(hook_bool_rtx_mode_int_int_intp_bool_false): New function.
	* hooks.h: Ditto.
	* expmed.c (init_expmed_one_conv, init_expmed_one_mode,
	init_expmed, expand_mult, mult_by_coeff_cost, expand_smod_pow2,
	emit_store_flag): Update set_src_cost and rtx_cost calls.
	* auto-inc-dec.c (attempt_change): Likewise.
	* calls.c (precompute_register_parameters): Likewise.
	* combine.c (expand_compound_operation, make_extraction,
	force_to_mode, distribute_and_simplify_rtx): Likewise.
	* dojump.c (prefer_and_bit_test): Likewise.
	* dse.c (find_shift_sequence): Likewise.
	* expr.c (compress_float_constant): Likewise.
	* fwprop.c (should_replace_address, try_fwprop_subst): Likewise.
	* ifcvt.c (noce_try_sign_mask): Likewise.
	* loop-doloop.c (doloop_optimize): Likewise.
	* loop-invariant.c (create_new_invariant): Likewise.
	* lower-subreg.c (shift_cost, compute_costs): Likewise.
	* optabs.c (avoid_expensive_constant, prepare_cmp_insn,
	lshift_cheap_p): Likewise.
	* postreload.c (reload_cse_simplify_set, reload_cse_simplify_operands,
	try_replace_in_use, reload_cse_move2add): Likewise.
	* reload1.c (calculate_elim_costs_all_insns, note_reg_elim_costly):
	Likewise.
	* simplify-rtx.c (simplify_binary_operation_1): Likewise.
	* tree-ssa-loop-ivopts.c (computation_cost): Likewise.
	* tree-ssa-reassoc.c (optimize_range_tests_to_bit_test): Likewise.
	* tree-switch-conversion.c (emit_case_bit_tests): Likewise.
	* config/aarch64/aarch64.c (aarch64_rtx_costs): Delete "code" param,
	add "mode" param.  Use "mode: in place of GET_MODE (x).  Pass mode
	to rtx_cost calls.
	* config/alpha/alpha.c (alpha_rtx_costs): Likewise.
	* config/arc/arc.c (arc_rtx_costs): Likewise.
	* config/arm/arm.c (arm_rtx_costs): Likewise.
	* config/avr/avr.c (avr_rtx_costs, avr_rtx_costs_1): Likewise.
	* config/bfin/bfin.c (bfin_rtx_costs): Likewise.
	* config/c6x/c6x.c (c6x_rtx_costs): Likewise.
	* config/cris/cris.c (cris_rtx_costs): Likewise.
	* config/epiphany/epiphany.c (epiphany_rtx_costs): Likewise.
	* config/frv/frv.c (frv_rtx_costs): Likewise.
	* config/h8300/h8300.c (h8300_rtx_costs): Likewise.
	* config/i386/i386.c (ix86_rtx_costs): Likewise.
	* config/ia64/ia64.c (ia64_rtx_costs): Likewise.
	* config/iq2000/iq2000.c (iq2000_rtx_costs): Likewise.
	* config/lm32/lm32.c (lm32_rtx_costs): Likewise.
	* config/m32c/m32c.c (m32c_rtx_costs): Likewise.
	* config/m32r/m32r.c (m32r_rtx_costs): Likewise.
	* config/m68k/m68k.c (m68k_rtx_costs): Likewise.
	* config/mcore/mcore.c (mcore_rtx_costs): Likewise.
	* config/mep/mep.c (mep_rtx_cost): Likewise.
	* config/microblaze/microblaze.c (microblaze_rtx_costs): Likewise.
	* config/mips/mips.c (mips_rtx_costs): Likewise.
	* config/mmix/mmix.c (mmix_rtx_costs): Likewise.
	* config/mn10300/mn10300.c (mn10300_rtx_costs): Likewise.
	* config/msp430/msp430.c (msp430_rtx_costs): Likewise.
	* config/nds32/nds32-cost.c (nds32_rtx_costs_impl): Likewise.
	* config/nds32/nds32-protos.h (nds32_rtx_costs_impl): Likewise.
	* config/nds32/nds32.c (nds32_rtx_costs): Likewise.
	* config/nios2/nios2.c (nios2_rtx_costs): Likewise.
	* config/pa/pa.c (hppa_rtx_costs): Likewise.
	* config/pdp11/pdp11.c (pdp11_rtx_costs): Likewise.
	* config/rl78/rl78.c (rl78_rtx_costs): Likewise.
	* config/rs6000/rs6000.c (rs6000_rtx_costs): Likewise.
	* config/s390/s390.c (s390_rtx_costs): Likewise.
	* config/sh/sh.c (sh_rtx_costs): Likewise.
	* config/sparc/sparc.c (sparc_rtx_costs): Likewise.
	* config/spu/spu.c (spu_rtx_costs): Likewise.
	* config/stormy16/stormy16.c (xstormy16_rtx_costs): Likewise.
	* config/tilegx/tilegx.c (tilegx_rtx_costs): Likewise.
	* config/tilepro/tilepro.c (tilepro_rtx_costs): Likewise.
	* config/v850/v850.c (v850_rtx_costs): Likewise.
	* config/vax/vax.c (vax_rtx_costs): Likewise.
	* config/visium/visium.c (visium_rtx_costs): Likewise.
	* config/xtensa/xtensa.c (xtensa_rtx_costs): Likewise.
	* config/aarch64/aarch64.c (aarch64_rtx_mult_cost): Change type of
	"code" param, and pass as outer_code to first rtx_cost call.  Pass
	mode to rtx_cost calls.
	(aarch64_address_cost, aarch64_if_then_else_costs): Update rtx_cost
	calls.
	(aarch64_rtx_costs_wrapper): Update.
	* config/arm/arm.c (arm_rtx_costs_1, arm_size_rtx_costs,
	arm_unspec_cost, arm_new_rtx_costs, arm_slowmul_rtx_costs): Update
	rtx_cost calls.
	* config/avr/avr.c (avr_final_prescan_insn): Update set_src_cost
	and rtx_cost calls.
	(avr_operand_rtx_cost): Similarly.
	(avr_rtx_costs_1): Correct mode passed to avr_operand_rtx_cost
	for subexpressions of ZERO_EXTEND, SIGN_EXTEND and COMPARE.
	* config/mips/mips.c (mips_stack_address_p): Comment typo.
	(mips_binary_cost): Update rtx_cost and set_src_cost calls.
	(mips_rtx_costs): Use GET_MODE (x) to detect const_int.
	* config/mn10300/mn10300.c (mn10300_address_cost): Pass Pmode to
	rtx_cost.
	(mn10300_rtx_costs): Correct mode passed to mn10300_address_cost.
	* config/rs6000/rs6000.c (rs6000_debug_rtx_costs): Update.
	* config/sh/sh.c (and_xor_ior_costs): Update rtx_cost call.
	* doc/tm.texi: Regenerate.

OK for mainline?

Index: gcc/target.def
===================================================================
--- gcc/target.def	(revision 224310)
+++ gcc/target.def	(working copy)
@@ -3390,7 +3390,7 @@ DEFHOOKPOD
 /* Compute a (partial) cost for rtx X.  Return true if the complete
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.  */
-/* Note that CODE and OUTER_CODE ought to be RTX_CODE, but that's
+/* Note that OUTER_CODE ought to be RTX_CODE, but that's
    not necessarily defined at this point.  */
 DEFHOOK
 (rtx_costs,
@@ -3404,8 +3404,8 @@ that @samp{GET_CODE (@var{y}) == @var{outer_code}}
 either (a) @samp{XEXP (@var{y}, @var{opno}) == @var{x}} or\n\
 (b) @samp{XVEC (@var{y}, @var{opno})} contains @var{x}.\n\
 \n\
-@var{code} is @var{x}'s expression code---redundant, since it can be\n\
-obtained with @code{GET_CODE (@var{x})}.\n\
+@var{mode} is @var{x}'s machine mode, or for cases like @code{const_int} that\n\
+do not have a mode, the mode in which @var{x} is used.\n\
 \n\
 In implementing this hook, you can use the construct\n\
 @code{COSTS_N_INSNS (@var{n})} to specify a cost equal to @var{n} fast\n\
@@ -3423,8 +3423,8 @@ size cost of an expression, again relative to @cod
 \n\
 The hook returns true when all subexpressions of @var{x} have been\n\
 processed, and false when @code{rtx_cost} should recurse.",
- bool, (rtx x, int code, int outer_code, int opno, int *total, bool speed),
- hook_bool_rtx_int_int_int_intp_bool_false)
+ bool, (rtx x, machine_mode mode, int outer_code, int opno, int *total, bool speed),
+ hook_bool_rtx_mode_int_int_intp_bool_false)
 
 /* Compute the cost of X, used as an address.  Never called with
    invalid addresses.  */
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	(revision 224310)
+++ gcc/rtl.h	(working copy)
@@ -2149,9 +2149,9 @@ wi::max_value (machine_mode mode, signop sgn)
 }
 
 extern void init_rtlanal (void);
-extern int rtx_cost (rtx, enum rtx_code, int, bool);
+extern int rtx_cost (rtx, machine_mode, enum rtx_code, int, bool);
 extern int address_cost (rtx, machine_mode, addr_space_t, bool);
-extern void get_full_rtx_cost (rtx, enum rtx_code, int,
+extern void get_full_rtx_cost (rtx, machine_mode, enum rtx_code, int,
 			       struct full_rtx_costs *);
 extern unsigned int subreg_lsb (const_rtx);
 extern unsigned int subreg_lsb_1 (machine_mode, machine_mode,
@@ -2180,43 +2180,6 @@ extern void update_address (struct address_info *)
 extern HOST_WIDE_INT get_index_scale (const struct address_info *);
 extern enum rtx_code get_index_code (const struct address_info *);
 
-#ifndef GENERATOR_FILE
-/* Return the cost of SET X.  SPEED_P is true if optimizing for speed
-   rather than size.  */
-
-static inline int
-set_rtx_cost (rtx x, bool speed_p)
-{
-  return rtx_cost (x, INSN, 4, speed_p);
-}
-
-/* Like set_rtx_cost, but return both the speed and size costs in C.  */
-
-static inline void
-get_full_set_rtx_cost (rtx x, struct full_rtx_costs *c)
-{
-  get_full_rtx_cost (x, INSN, 4, c);
-}
-
-/* Return the cost of moving X into a register, relative to the cost
-   of a register move.  SPEED_P is true if optimizing for speed rather
-   than size.  */
-
-static inline int
-set_src_cost (rtx x, bool speed_p)
-{
-  return rtx_cost (x, SET, 1, speed_p);
-}
-
-/* Like set_src_cost, but return both the speed and size costs in C.  */
-
-static inline void
-get_full_set_src_cost (rtx x, struct full_rtx_costs *c)
-{
-  get_full_rtx_cost (x, SET, 1, c);
-}
-#endif
-
 /* 1 if RTX is a subreg containing a reg that is already known to be
    sign- or zero-extended from the mode of the subreg to the mode of
    the reg.  SUBREG_PROMOTED_UNSIGNED_P gives the signedness of the
@@ -2648,6 +2611,43 @@ extern int currently_expanding_to_rtl;
 
 /* Generally useful functions.  */
 
+#ifndef GENERATOR_FILE
+/* Return the cost of SET X.  SPEED_P is true if optimizing for speed
+   rather than size.  */
+
+static inline int
+set_rtx_cost (rtx x, bool speed_p)
+{
+  return rtx_cost (x, VOIDmode, INSN, 4, speed_p);
+}
+
+/* Like set_rtx_cost, but return both the speed and size costs in C.  */
+
+static inline void
+get_full_set_rtx_cost (rtx x, struct full_rtx_costs *c)
+{
+  get_full_rtx_cost (x, VOIDmode, INSN, 4, c);
+}
+
+/* Return the cost of moving X into a register, relative to the cost
+   of a register move.  SPEED_P is true if optimizing for speed rather
+   than size.  */
+
+static inline int
+set_src_cost (rtx x, machine_mode mode, bool speed_p)
+{
+  return rtx_cost (x, mode, SET, 1, speed_p);
+}
+
+/* Like set_src_cost, but return both the speed and size costs in C.  */
+
+static inline void
+get_full_set_src_cost (rtx x, machine_mode mode, struct full_rtx_costs *c)
+{
+  get_full_rtx_cost (x, mode, SET, 1, c);
+}
+#endif
+
 /* In explow.c */
 extern HOST_WIDE_INT trunc_int_for_mode	(HOST_WIDE_INT, machine_mode);
 extern rtx plus_constant (machine_mode, rtx, HOST_WIDE_INT, bool = false);
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	(revision 224310)
+++ gcc/rtlanal.c	(working copy)
@@ -3814,7 +3814,8 @@ label_is_jump_target_p (const_rtx label, const rtx
    be returned.  */
 
 int
-rtx_cost (rtx x, enum rtx_code outer_code, int opno, bool speed)
+rtx_cost (rtx x, machine_mode mode, enum rtx_code outer_code,
+	  int opno, bool speed)
 {
   int i, j;
   enum rtx_code code;
@@ -3825,9 +3826,12 @@ int
   if (x == 0)
     return 0;
 
+  if (GET_MODE (x) != VOIDmode)
+    mode = GET_MODE (x);
+
   /* A size N times larger than UNITS_PER_WORD likely needs N times as
      many insns, taking N times as long.  */
-  factor = GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD;
+  factor = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
   if (factor == 0)
     factor = 1;
 
@@ -3857,7 +3861,8 @@ int
     case SET:
       /* A SET doesn't have a mode, so let's look at the SET_DEST to get
 	 the mode for the factor.  */
-      factor = GET_MODE_SIZE (GET_MODE (SET_DEST (x))) / UNITS_PER_WORD;
+      mode = GET_MODE (SET_DEST (x));
+      factor = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
       if (factor == 0)
 	factor = 1;
       /* Pass through.  */
@@ -3874,12 +3879,12 @@ int
       total = 0;
       /* If we can't tie these modes, make this expensive.  The larger
 	 the mode, the more expensive it is.  */
-      if (! MODES_TIEABLE_P (GET_MODE (x), GET_MODE (SUBREG_REG (x))))
+      if (! MODES_TIEABLE_P (mode, GET_MODE (SUBREG_REG (x))))
 	return COSTS_N_INSNS (2 + factor);
       break;
 
     default:
-      if (targetm.rtx_costs (x, code, outer_code, opno, &total, speed))
+      if (targetm.rtx_costs (x, mode, outer_code, opno, &total, speed))
 	return total;
       break;
     }
@@ -3888,12 +3893,16 @@ int
      which is already in total.  */
 
   fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+  for (i = 0; i < GET_RTX_LENGTH (code); i++)
     if (fmt[i] == 'e')
-      total += rtx_cost (XEXP (x, i), code, i, speed);
+      {
+	if (GET_MODE (XEXP (x, i)) != VOIDmode)
+	  mode = GET_MODE (XEXP (x, i));
+	total += rtx_cost (XEXP (x, i), mode, code, i, speed);
+      }
     else if (fmt[i] == 'E')
       for (j = 0; j < XVECLEN (x, i); j++)
-	total += rtx_cost (XVECEXP (x, i, j), code, i, speed);
+	total += rtx_cost (XVECEXP (x, i, j), mode, code, i, speed);
 
   return total;
 }
@@ -3902,11 +3911,11 @@ int
    costs for X, which is operand OPNO in an expression with code OUTER.  */
 
 void
-get_full_rtx_cost (rtx x, enum rtx_code outer, int opno,
+get_full_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer, int opno,
 		   struct full_rtx_costs *c)
 {
-  c->speed = rtx_cost (x, outer, opno, true);
-  c->size = rtx_cost (x, outer, opno, false);
+  c->speed = rtx_cost (x, mode, outer, opno, true);
+  c->size = rtx_cost (x, mode, outer, opno, false);
 }
 
 \f
@@ -3934,7 +3943,7 @@ address_cost (rtx x, machine_mode mode, addr_space
 int
 default_address_cost (rtx x, machine_mode, addr_space_t, bool speed)
 {
-  return rtx_cost (x, MEM, 0, speed);
+  return rtx_cost (x, Pmode, MEM, 0, speed);
 }
 \f
 
@@ -4941,7 +4950,7 @@ insn_rtx_cost (rtx pat, bool speed)
   else
     return 0;
 
-  cost = set_src_cost (SET_SRC (set), speed);
+  cost = set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)), speed);
   return cost > 0 ? cost : COSTS_N_INSNS (1);
 }
 
Index: gcc/auto-inc-dec.c
===================================================================
--- gcc/auto-inc-dec.c	(revision 224310)
+++ gcc/auto-inc-dec.c	(working copy)
@@ -495,9 +495,9 @@ attempt_change (rtx new_addr, rtx inc_reg)
   PUT_MODE (mem_tmp, mode);
   XEXP (mem_tmp, 0) = new_addr;
 
-  old_cost = (set_src_cost (mem, speed)
+  old_cost = (set_src_cost (mem, mode, speed)
 	      + set_rtx_cost (PATTERN (inc_insn.insn), speed));
-  new_cost = set_src_cost (mem_tmp, speed);
+  new_cost = set_src_cost (mem_tmp, mode, speed);
 
   /* The first item of business is to see if this is profitable.  */
   if (old_cost < new_cost)
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	(revision 224310)
+++ gcc/calls.c	(working copy)
@@ -926,8 +926,9 @@ precompute_register_parameters (int num_actuals, s
 		     || (GET_CODE (args[i].value) == SUBREG
 			 && REG_P (SUBREG_REG (args[i].value)))))
 		 && args[i].mode != BLKmode
-		 && set_src_cost (args[i].value, optimize_insn_for_speed_p ())
-		    > COSTS_N_INSNS (1)
+		 && (set_src_cost (args[i].value, args[i].mode,
+				   optimize_insn_for_speed_p ())
+		     > COSTS_N_INSNS (1))
 		 && ((*reg_parm_seen
 		      && targetm.small_register_classes_for_mode_p (args[i].mode))
 		     || optimize))
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	(revision 224310)
+++ gcc/combine.c	(working copy)
@@ -7055,15 +7055,16 @@ expand_compound_operation (rtx x)
 		     >> 1))
 	       == 0)))
     {
-      rtx temp = gen_rtx_ZERO_EXTEND (GET_MODE (x), XEXP (x, 0));
+      machine_mode mode = GET_MODE (x);
+      rtx temp = gen_rtx_ZERO_EXTEND (mode, XEXP (x, 0));
       rtx temp2 = expand_compound_operation (temp);
 
       /* Make sure this is a profitable operation.  */
-      if (set_src_cost (x, optimize_this_for_speed_p)
-          > set_src_cost (temp2, optimize_this_for_speed_p))
+      if (set_src_cost (x, mode, optimize_this_for_speed_p)
+          > set_src_cost (temp2, mode, optimize_this_for_speed_p))
        return temp2;
-      else if (set_src_cost (x, optimize_this_for_speed_p)
-               > set_src_cost (temp, optimize_this_for_speed_p))
+      else if (set_src_cost (x, mode, optimize_this_for_speed_p)
+               > set_src_cost (temp, mode, optimize_this_for_speed_p))
        return temp;
       else
        return x;
@@ -7489,8 +7490,8 @@ make_extraction (machine_mode mode, rtx inner, HOS
 
 	  /* Prefer ZERO_EXTENSION, since it gives more information to
 	     backends.  */
-	  if (set_src_cost (temp, optimize_this_for_speed_p)
-	      <= set_src_cost (temp1, optimize_this_for_speed_p))
+	  if (set_src_cost (temp, mode, optimize_this_for_speed_p)
+	      <= set_src_cost (temp1, mode, optimize_this_for_speed_p))
 	    return temp;
 	  return temp1;
 	}
@@ -7675,8 +7676,8 @@ make_extraction (machine_mode mode, rtx inner, HOS
 
 	  /* Prefer ZERO_EXTENSION, since it gives more information to
 	     backends.  */
-	  if (set_src_cost (temp1, optimize_this_for_speed_p)
-	      < set_src_cost (temp, optimize_this_for_speed_p))
+	  if (set_src_cost (temp1, pos_mode, optimize_this_for_speed_p)
+	      < set_src_cost (temp, pos_mode, optimize_this_for_speed_p))
 	    temp = temp1;
 	}
       pos_rtx = temp;
@@ -8448,8 +8449,8 @@ force_to_mode (rtx x, machine_mode mode, unsigned
 
 	      y = simplify_gen_binary (AND, GET_MODE (x), XEXP (x, 0),
 				       gen_int_mode (cval, GET_MODE (x)));
-	      if (set_src_cost (y, optimize_this_for_speed_p)
-	          < set_src_cost (x, optimize_this_for_speed_p))
+	      if (set_src_cost (y, GET_MODE (x), optimize_this_for_speed_p)
+	          < set_src_cost (x, GET_MODE (x), optimize_this_for_speed_p))
 		x = y;
 	    }
 
@@ -9642,8 +9643,8 @@ distribute_and_simplify_rtx (rtx x, int n)
   tmp = apply_distributive_law (simplify_gen_binary (inner_code, mode,
 						     new_op0, new_op1));
   if (GET_CODE (tmp) != outer_code
-      && (set_src_cost (tmp, optimize_this_for_speed_p)
-	  < set_src_cost (x, optimize_this_for_speed_p)))
+      && (set_src_cost (tmp, mode, optimize_this_for_speed_p)
+	  < set_src_cost (x, mode, optimize_this_for_speed_p)))
     return tmp;
 
   return NULL_RTX;
Index: gcc/cprop.c
===================================================================
--- gcc/cprop.c	(revision 224310)
+++ gcc/cprop.c	(working copy)
@@ -760,11 +760,12 @@ try_replace_reg (rtx from, rtx to, rtx_insn *insn)
   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
   int old_cost = set ? set_rtx_cost (set, speed) : 0;
 
-  if ((note != 0
-      && REG_NOTE_KIND (note) == REG_EQUAL
-      && (GET_CODE (XEXP (note, 0)) == CONST
-	  || CONSTANT_P (XEXP (note, 0))))
-      || (set && CONSTANT_P (SET_SRC (set))))
+  if (!set
+      || CONSTANT_P (SET_SRC (set))
+      || (note != 0
+	  && REG_NOTE_KIND (note) == REG_EQUAL
+	  && (GET_CODE (XEXP (note, 0)) == CONST
+	      || CONSTANT_P (XEXP (note, 0)))))
     check_rtx_costs = false;
 
   /* Usually we substitute easy stuff, so we won't copy everything.
@@ -780,7 +781,7 @@ try_replace_reg (rtx from, rtx to, rtx_insn *insn)
 
   if (check_rtx_costs
       && CONSTANT_P (to)
-      && (set_rtx_cost (set, speed) > old_cost))
+      && set_rtx_cost (set, speed) > old_cost)
     {
       cancel_changes (0);
       return false;
Index: gcc/cse.c
===================================================================
--- gcc/cse.c	(revision 224310)
+++ gcc/cse.c	(working copy)
@@ -478,8 +478,10 @@ struct table_elt
    || (HARD_REGISTER_NUM_P (N)						\
        && FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
 
-#define COST(X) (REG_P (X) ? 0 : notreg_cost (X, SET, 1))
-#define COST_IN(X, OUTER, OPNO) (REG_P (X) ? 0 : notreg_cost (X, OUTER, OPNO))
+#define COST(X, MODE)							\
+  (REG_P (X) ? 0 : notreg_cost (X, MODE, SET, 1))
+#define COST_IN(X, MODE, OUTER, OPNO)					\
+  (REG_P (X) ? 0 : notreg_cost (X, MODE, OUTER, OPNO))
 
 /* Get the number of times this register has been updated in this
    basic block.  */
@@ -555,7 +557,7 @@ static bitmap cse_ebb_live_in, cse_ebb_live_out;
 static sbitmap cse_visited_basic_blocks;
 
 static bool fixed_base_plus_p (rtx x);
-static int notreg_cost (rtx, enum rtx_code, int);
+static int notreg_cost (rtx, machine_mode, enum rtx_code, int);
 static int preferable (int, int, int, int);
 static void new_basic_block (void);
 static void make_new_qty (unsigned int, machine_mode);
@@ -732,19 +734,17 @@ preferable (int cost_a, int regcost_a, int cost_b,
    from COST macro to keep it simple.  */
 
 static int
-notreg_cost (rtx x, enum rtx_code outer, int opno)
+notreg_cost (rtx x, machine_mode mode, enum rtx_code outer, int opno)
 {
   return ((GET_CODE (x) == SUBREG
 	   && REG_P (SUBREG_REG (x))
-	   && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
+	   && GET_MODE_CLASS (mode) == MODE_INT
 	   && GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_INT
-	   && (GET_MODE_SIZE (GET_MODE (x))
-	       < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+	   && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
 	   && subreg_lowpart_p (x)
-	   && TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (x),
-					     GET_MODE (SUBREG_REG (x))))
+	   && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (SUBREG_REG (x))))
 	  ? 0
-	  : rtx_cost (x, outer, opno, optimize_this_for_speed_p) * 2);
+	  : rtx_cost (x, mode, outer, opno, optimize_this_for_speed_p) * 2);
 }
 
 \f
@@ -1248,7 +1248,7 @@ insert_const_anchor (HOST_WIDE_INT anchor, rtx reg
      don't prefer pseudos over hard regs so that we derive constants in
      argument registers from other argument registers rather than from the
      original pseudo that was used to synthesize the constant.  */
-  insert_with_costs (exp, elt, hash, mode, COST (reg), 1);
+  insert_with_costs (exp, elt, hash, mode, COST (reg, mode), 1);
 }
 
 /* The constant CST is equivalent to the register REG.  Create
@@ -1729,8 +1729,8 @@ static struct table_elt *
 insert (rtx x, struct table_elt *classp, unsigned int hash,
 	machine_mode mode)
 {
-  return
-    insert_with_costs (x, classp, hash, mode, COST (x), approx_reg_cost (x));
+  return insert_with_costs (x, classp, hash, mode,
+			    COST (x, mode), approx_reg_cost (x));
 }
 
 \f
@@ -3265,7 +3265,8 @@ fold_rtx (rtx x, rtx_insn *insn)
 	   argument.  */
 	if (const_arg != 0
 	    && const_arg != folded_arg
-	    && COST_IN (const_arg, code, i) <= COST_IN (folded_arg, code, i)
+	    && (COST_IN (const_arg, mode_arg, code, i)
+		<= COST_IN (folded_arg, mode_arg, code, i))
 
 	    /* It's not safe to substitute the operand of a conversion
 	       operator with a constant, as the conversion's identity
@@ -3392,7 +3393,7 @@ fold_rtx (rtx x, rtx_insn *insn)
 		  if (p != NULL)
 		    {
 		      cheapest_simplification = x;
-		      cheapest_cost = COST (x);
+		      cheapest_cost = COST (x, mode);
 
 		      for (p = p->first_same_value; p != NULL; p = p->next_same_value)
 			{
@@ -3412,7 +3413,7 @@ fold_rtx (rtx x, rtx_insn *insn)
 			  if (simp_result == NULL)
 			    continue;
 
-			  cost = COST (simp_result);
+			  cost = COST (simp_result, mode);
 			  if (cost < cheapest_cost)
 			    {
 			      cheapest_cost = cost;
@@ -5002,7 +5003,7 @@ cse_insn (rtx_insn *insn)
 	    src_cost = src_regcost = -1;
 	  else
 	    {
-	      src_cost = COST (src);
+	      src_cost = COST (src, mode);
 	      src_regcost = approx_reg_cost (src);
 	    }
 	}
@@ -5013,7 +5014,7 @@ cse_insn (rtx_insn *insn)
 	    src_eqv_cost = src_eqv_regcost = -1;
 	  else
 	    {
-	      src_eqv_cost = COST (src_eqv_here);
+	      src_eqv_cost = COST (src_eqv_here, mode);
 	      src_eqv_regcost = approx_reg_cost (src_eqv_here);
 	    }
 	}
@@ -5024,7 +5025,7 @@ cse_insn (rtx_insn *insn)
 	    src_folded_cost = src_folded_regcost = -1;
 	  else
 	    {
-	      src_folded_cost = COST (src_folded);
+	      src_folded_cost = COST (src_folded, mode);
 	      src_folded_regcost = approx_reg_cost (src_folded);
 	    }
 	}
@@ -5035,7 +5036,7 @@ cse_insn (rtx_insn *insn)
 	    src_related_cost = src_related_regcost = -1;
 	  else
 	    {
-	      src_related_cost = COST (src_related);
+	      src_related_cost = COST (src_related, mode);
 	      src_related_regcost = approx_reg_cost (src_related);
 
 	      /* If a const-anchor is used to synthesize a constant that
@@ -5348,7 +5349,7 @@ cse_insn (rtx_insn *insn)
 		  /* If we had a constant that is cheaper than what we are now
 		     setting SRC to, use that constant.  We ignored it when we
 		     thought we could make this into a no-op.  */
-		  if (src_const && COST (src_const) < COST (src)
+		  if (src_const && COST (src_const, mode) < COST (src, mode)
 		      && validate_change (insn, &SET_SRC (sets[i].rtl),
 					  src_const, 0))
 		    src = src_const;
Index: gcc/dojump.c
===================================================================
--- gcc/dojump.c	(revision 224310)
+++ gcc/dojump.c	(working copy)
@@ -206,8 +206,8 @@ prefer_and_bit_test (machine_mode mode, int bitnum
   XEXP (XEXP (shift_test, 0), 1) = GEN_INT (bitnum);
 
   speed_p = optimize_insn_for_speed_p ();
-  return (rtx_cost (and_test, IF_THEN_ELSE, 0, speed_p)
-	  <= rtx_cost (shift_test, IF_THEN_ELSE, 0, speed_p));
+  return (rtx_cost (and_test, mode, IF_THEN_ELSE, 0, speed_p)
+	  <= rtx_cost (shift_test, mode, IF_THEN_ELSE, 0, speed_p));
 }
 
 /* Subroutine of do_jump, dealing with exploded comparisons of the type
Index: gcc/dse.c
===================================================================
--- gcc/dse.c	(revision 224310)
+++ gcc/dse.c	(working copy)
@@ -1845,7 +1845,8 @@ find_shift_sequence (int access_size,
 		  byte = subreg_lowpart_offset (read_mode, new_mode);
 		  ret = simplify_subreg (read_mode, ret, new_mode, byte);
 		  if (ret && CONSTANT_P (ret)
-		      && set_src_cost (ret, speed) <= COSTS_N_INSNS (1))
+		      && (set_src_cost (ret, read_mode, speed)
+			  <= COSTS_N_INSNS (1)))
 		    return ret;
 		}
 	    }
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	(revision 224310)
+++ gcc/expmed.c	(working copy)
@@ -151,7 +151,8 @@ init_expmed_one_conv (struct init_expmed_rtl *all,
   which = (to_size < from_size ? all->trunc : all->zext);
 
   PUT_MODE (all->reg, from_mode);
-  set_convert_cost (to_mode, from_mode, speed, set_src_cost (which, speed));
+  set_convert_cost (to_mode, from_mode, speed,
+		    set_src_cost (which, to_mode, speed));
 }
 
 static void
@@ -180,15 +181,15 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
   PUT_MODE (all->zext, mode);
   PUT_MODE (all->trunc, mode);
 
-  set_add_cost (speed, mode, set_src_cost (all->plus, speed));
-  set_neg_cost (speed, mode, set_src_cost (all->neg, speed));
-  set_mul_cost (speed, mode, set_src_cost (all->mult, speed));
-  set_sdiv_cost (speed, mode, set_src_cost (all->sdiv, speed));
-  set_udiv_cost (speed, mode, set_src_cost (all->udiv, speed));
+  set_add_cost (speed, mode, set_src_cost (all->plus, mode, speed));
+  set_neg_cost (speed, mode, set_src_cost (all->neg, mode, speed));
+  set_mul_cost (speed, mode, set_src_cost (all->mult, mode, speed));
+  set_sdiv_cost (speed, mode, set_src_cost (all->sdiv, mode, speed));
+  set_udiv_cost (speed, mode, set_src_cost (all->udiv, mode, speed));
 
-  set_sdiv_pow2_cheap (speed, mode, (set_src_cost (all->sdiv_32, speed)
+  set_sdiv_pow2_cheap (speed, mode, (set_src_cost (all->sdiv_32, mode, speed)
 				     <= 2 * add_cost (speed, mode)));
-  set_smod_pow2_cheap (speed, mode, (set_src_cost (all->smod_32, speed)
+  set_smod_pow2_cheap (speed, mode, (set_src_cost (all->smod_32, mode, speed)
 				     <= 4 * add_cost (speed, mode)));
 
   set_shift_cost (speed, mode, 0, 0);
@@ -205,10 +206,13 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
       XEXP (all->shift, 1) = all->cint[m];
       XEXP (all->shift_mult, 1) = all->pow2[m];
 
-      set_shift_cost (speed, mode, m, set_src_cost (all->shift, speed));
-      set_shiftadd_cost (speed, mode, m, set_src_cost (all->shift_add, speed));
-      set_shiftsub0_cost (speed, mode, m, set_src_cost (all->shift_sub0, speed));
-      set_shiftsub1_cost (speed, mode, m, set_src_cost (all->shift_sub1, speed));
+      set_shift_cost (speed, mode, m, set_src_cost (all->shift, mode, speed));
+      set_shiftadd_cost (speed, mode, m, set_src_cost (all->shift_add, mode,
+						       speed));
+      set_shiftsub0_cost (speed, mode, m, set_src_cost (all->shift_sub0, mode,
+							speed));
+      set_shiftsub1_cost (speed, mode, m, set_src_cost (all->shift_sub1, mode,
+							speed));
     }
 
   if (SCALAR_INT_MODE_P (mode))
@@ -228,9 +232,9 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
 	  XEXP (all->wide_lshr, 1) = GEN_INT (mode_bitsize);
 
 	  set_mul_widen_cost (speed, wider_mode,
-			      set_src_cost (all->wide_mult, speed));
+			      set_src_cost (all->wide_mult, wider_mode, speed));
 	  set_mul_highpart_cost (speed, mode,
-				 set_src_cost (all->wide_trunc, speed));
+				 set_src_cost (all->wide_trunc, mode, speed));
 	}
     }
 }
@@ -272,7 +276,7 @@ init_expmed (void)
   for (speed = 0; speed < 2; speed++)
     {
       crtl->maybe_hot_insn_p = speed;
-      set_zero_cost (speed, set_src_cost (const0_rtx, speed));
+      set_zero_cost (speed, set_src_cost (const0_rtx, mode, speed));
 
       for (mode = MIN_MODE_INT; mode <= MAX_MODE_INT;
 	   mode = (machine_mode)(mode + 1))
@@ -3213,7 +3217,8 @@ expand_mult (machine_mode mode, rtx op0, rtx op1,
 	     Exclude cost of op0 from max_cost to match the cost
 	     calculation of the synth_mult.  */
 	  coeff = -(unsigned HOST_WIDE_INT) coeff;
-	  max_cost = (set_src_cost (gen_rtx_MULT (mode, fake_reg, op1), speed)
+	  max_cost = (set_src_cost (gen_rtx_MULT (mode, fake_reg, op1),
+				    mode, speed)
 		      - neg_cost (speed, mode));
 	  if (max_cost <= 0)
 	    goto skip_synth;
@@ -3238,7 +3243,7 @@ expand_mult (machine_mode mode, rtx op0, rtx op1,
 
       /* Exclude cost of op0 from max_cost to match the cost
 	 calculation of the synth_mult.  */
-      max_cost = set_src_cost (gen_rtx_MULT (mode, fake_reg, op1), speed);
+      max_cost = set_src_cost (gen_rtx_MULT (mode, fake_reg, op1), mode, speed);
       if (choose_mult_variant (mode, coeff, &algorithm, &variant, max_cost))
 	return expand_mult_const (mode, op0, coeff, target,
 				  &algorithm, variant);
@@ -3279,7 +3284,8 @@ mult_by_coeff_cost (HOST_WIDE_INT coeff, machine_m
   enum mult_variant variant;
 
   rtx fake_reg = gen_raw_REG (mode, LAST_VIRTUAL_REGISTER + 1);
-  max_cost = set_src_cost (gen_rtx_MULT (mode, fake_reg, fake_reg), speed);
+  max_cost = set_src_cost (gen_rtx_MULT (mode, fake_reg, fake_reg),
+			   mode, speed);
   if (choose_mult_variant (mode, coeff, &algorithm, &variant, max_cost))
     return algorithm.cost.cost;
   else
@@ -3705,7 +3711,7 @@ expand_smod_pow2 (machine_mode mode, rtx op0, HOST
 
 	  temp = gen_rtx_LSHIFTRT (mode, result, shift);
 	  if (optab_handler (lshr_optab, mode) == CODE_FOR_nothing
-	      || (set_src_cost (temp, optimize_insn_for_speed_p ())
+	      || (set_src_cost (temp, mode, optimize_insn_for_speed_p ())
 		  > COSTS_N_INSNS (2)))
 	    {
 	      temp = expand_binop (mode, xor_optab, op0, signmask,
@@ -5509,7 +5515,7 @@ emit_store_flag (rtx target, enum rtx_code code, r
 
 	  /* For the reverse comparison, use either an addition or a XOR.  */
           if (want_add
-	      && rtx_cost (GEN_INT (normalizep), PLUS, 1,
+	      && rtx_cost (GEN_INT (normalizep), mode, PLUS, 1,
 			   optimize_insn_for_speed_p ()) == 0)
 	    {
 	      tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
@@ -5520,7 +5526,7 @@ emit_store_flag (rtx target, enum rtx_code code, r
 				     target, 0, OPTAB_WIDEN);
 	    }
           else if (!want_add
-	           && rtx_cost (trueval, XOR, 1,
+	           && rtx_cost (trueval, mode, XOR, 1,
 			        optimize_insn_for_speed_p ()) == 0)
 	    {
 	      tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
@@ -5612,7 +5618,7 @@ emit_store_flag (rtx target, enum rtx_code code, r
 
       /* Again, for the reverse comparison, use either an addition or a XOR.  */
       if (want_add
-	  && rtx_cost (GEN_INT (normalizep), PLUS, 1,
+	  && rtx_cost (GEN_INT (normalizep), mode, PLUS, 1,
 		       optimize_insn_for_speed_p ()) == 0)
 	{
 	  tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
@@ -5623,7 +5629,7 @@ emit_store_flag (rtx target, enum rtx_code code, r
 				target, 0, OPTAB_WIDEN);
 	}
       else if (!want_add
-	       && rtx_cost (trueval, XOR, 1,
+	       && rtx_cost (trueval, mode, XOR, 1,
 			    optimize_insn_for_speed_p ()) == 0)
 	{
 	  tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 224310)
+++ gcc/expr.c	(working copy)
@@ -3661,9 +3661,9 @@ compress_float_constant (rtx x, rtx y)
   REAL_VALUE_FROM_CONST_DOUBLE (r, y);
 
   if (targetm.legitimate_constant_p (dstmode, y))
-    oldcost = set_src_cost (y, speed);
+    oldcost = set_src_cost (y, orig_srcmode, speed);
   else
-    oldcost = set_src_cost (force_const_mem (dstmode, y), speed);
+    oldcost = set_src_cost (force_const_mem (dstmode, y), dstmode, speed);
 
   for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
        srcmode != orig_srcmode;
@@ -3692,7 +3692,7 @@ compress_float_constant (rtx x, rtx y)
 	    continue;
 	  /* This is valid, but may not be cheaper than the original. */
 	  newcost = set_src_cost (gen_rtx_FLOAT_EXTEND (dstmode, trunc_y),
-				  speed);
+				  dstmode, speed);
 	  if (oldcost < newcost)
 	    continue;
 	}
@@ -3701,7 +3701,7 @@ compress_float_constant (rtx x, rtx y)
 	  trunc_y = force_const_mem (srcmode, trunc_y);
 	  /* This is valid, but may not be cheaper than the original. */
 	  newcost = set_src_cost (gen_rtx_FLOAT_EXTEND (dstmode, trunc_y),
-				  speed);
+				  dstmode, speed);
 	  if (oldcost < newcost)
 	    continue;
 	  trunc_y = validize_mem (trunc_y);
Index: gcc/fwprop.c
===================================================================
--- gcc/fwprop.c	(revision 224310)
+++ gcc/fwprop.c	(working copy)
@@ -412,7 +412,8 @@ should_replace_address (rtx old_rtx, rtx new_rtx,
      eliminating the most insns without additional costs, and it
      is the same that cse.c used to do.  */
   if (gain == 0)
-    gain = set_src_cost (new_rtx, speed) - set_src_cost (old_rtx, speed);
+    gain = (set_src_cost (new_rtx, VOIDmode, speed)
+	    - set_src_cost (old_rtx, VOIDmode, speed));
 
   return (gain > 0);
 }
@@ -960,7 +961,7 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rt
      multiple sets.  If so, assume the cost of the new instruction is
      not greater than the old one.  */
   if (set)
-    old_cost = set_src_cost (SET_SRC (set), speed);
+    old_cost = set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)), speed);
   if (dump_file)
     {
       fprintf (dump_file, "\nIn insn %d, replacing\n ", INSN_UID (insn));
@@ -981,7 +982,8 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rt
 
   else if (DF_REF_TYPE (use) == DF_REF_REG_USE
 	   && set
-	   && set_src_cost (SET_SRC (set), speed) > old_cost)
+	   && (set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)), speed)
+	       > old_cost))
     {
       if (dump_file)
 	fprintf (dump_file, "Changes to insn %d not profitable\n",
Index: gcc/gcse.c
===================================================================
--- gcc/gcse.c	(revision 224310)
+++ gcc/gcse.c	(working copy)
@@ -475,7 +475,6 @@ static void hash_scan_insn (rtx_insn *, struct gcs
 static void hash_scan_set (rtx, rtx_insn *, struct gcse_hash_table_d *);
 static void hash_scan_clobber (rtx, rtx_insn *, struct gcse_hash_table_d *);
 static void hash_scan_call (rtx, rtx_insn *, struct gcse_hash_table_d *);
-static int want_to_gcse_p (rtx, int *);
 static int oprs_unchanged_p (const_rtx, const rtx_insn *, int);
 static int oprs_anticipatable_p (const_rtx, const rtx_insn *);
 static int oprs_available_p (const_rtx, const rtx_insn *);
@@ -766,7 +765,7 @@ static basic_block current_bb;
    GCSE.  */
 
 static int
-want_to_gcse_p (rtx x, int *max_distance_ptr)
+want_to_gcse_p (rtx x, machine_mode mode, int *max_distance_ptr)
 {
 #ifdef STACK_REGS
   /* On register stack architectures, don't GCSE constants from the
@@ -817,7 +816,7 @@ static int
 
 	  gcc_assert (!optimize_function_for_speed_p (cfun)
 		      && optimize_function_for_size_p (cfun));
-	  cost = set_src_cost (x, 0);
+	  cost = set_src_cost (x, mode, 0);
 
 	  if (cost < COSTS_N_INSNS (GCSE_UNRESTRICTED_COST))
 	    {
@@ -1274,7 +1273,7 @@ hash_scan_set (rtx set, rtx_insn *insn, struct gcs
       if (note != 0
 	  && REG_NOTE_KIND (note) == REG_EQUAL
 	  && !REG_P (src)
-	  && want_to_gcse_p (XEXP (note, 0), NULL))
+	  && want_to_gcse_p (XEXP (note, 0), GET_MODE (dest), NULL))
 	src = XEXP (note, 0), set = gen_rtx_SET (dest, src);
 
       /* Only record sets of pseudo-regs in the hash table.  */
@@ -1288,7 +1287,7 @@ hash_scan_set (rtx set, rtx_insn *insn, struct gcs
 	     can't do the same thing at the rtl level.  */
 	  && !can_throw_internal (insn)
 	  /* Is SET_SRC something we want to gcse?  */
-	  && want_to_gcse_p (src, &max_distance)
+	  && want_to_gcse_p (src, GET_MODE (dest), &max_distance)
 	  /* Don't CSE a nop.  */
 	  && ! set_noop_p (set)
 	  /* Don't GCSE if it has attached REG_EQUIV note.
@@ -1320,43 +1319,42 @@ hash_scan_set (rtx set, rtx_insn *insn, struct gcs
      the REG stored in that memory. This makes it possible to remove
      redundant loads from due to stores to the same location.  */
   else if (flag_gcse_las && REG_P (src) && MEM_P (dest))
-      {
-        unsigned int regno = REGNO (src);
-	int max_distance = 0;
+    {
+      unsigned int regno = REGNO (src);
+      int max_distance = 0;
 
-	/* Only record sets of pseudo-regs in the hash table.  */
-        if (regno >= FIRST_PSEUDO_REGISTER
-	   /* Don't GCSE something if we can't do a reg/reg copy.  */
-	   && can_copy_p (GET_MODE (src))
-	   /* GCSE commonly inserts instruction after the insn.  We can't
-	      do that easily for EH edges so disable GCSE on these for now.  */
-	   && !can_throw_internal (insn)
-	   /* Is SET_DEST something we want to gcse?  */
-	   && want_to_gcse_p (dest, &max_distance)
-	   /* Don't CSE a nop.  */
-	   && ! set_noop_p (set)
-	   /* Don't GCSE if it has attached REG_EQUIV note.
-	      At this point this only function parameters should have
-	      REG_EQUIV notes and if the argument slot is used somewhere
-	      explicitly, it means address of parameter has been taken,
-	      so we should not extend the lifetime of the pseudo.  */
-	   && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0
-	       || ! MEM_P (XEXP (note, 0))))
-             {
-               /* Stores are never anticipatable.  */
-               int antic_p = 0;
-	       /* An expression is not available if its operands are
-	          subsequently modified, including this insn.  It's also not
-	          available if this is a branch, because we can't insert
-	          a set after the branch.  */
-               int avail_p = oprs_available_p (dest, insn)
-			     && ! JUMP_P (insn);
+      /* Only record sets of pseudo-regs in the hash table.  */
+      if (regno >= FIRST_PSEUDO_REGISTER
+	  /* Don't GCSE something if we can't do a reg/reg copy.  */
+	  && can_copy_p (GET_MODE (src))
+	  /* GCSE commonly inserts instruction after the insn.  We can't
+	     do that easily for EH edges so disable GCSE on these for now.  */
+	  && !can_throw_internal (insn)
+	  /* Is SET_DEST something we want to gcse?  */
+	  && want_to_gcse_p (dest, GET_MODE (dest), &max_distance)
+	  /* Don't CSE a nop.  */
+	  && ! set_noop_p (set)
+	  /* Don't GCSE if it has attached REG_EQUIV note.
+	     At this point this only function parameters should have
+	     REG_EQUIV notes and if the argument slot is used somewhere
+	     explicitly, it means address of parameter has been taken,
+	     so we should not extend the lifetime of the pseudo.  */
+	  && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0
+	      || ! MEM_P (XEXP (note, 0))))
+	{
+	  /* Stores are never anticipatable.  */
+	  int antic_p = 0;
+	  /* An expression is not available if its operands are
+	     subsequently modified, including this insn.  It's also not
+	     available if this is a branch, because we can't insert
+	     a set after the branch.  */
+	  int avail_p = oprs_available_p (dest, insn) && ! JUMP_P (insn);
 
-	       /* Record the memory expression (DEST) in the hash table.  */
-	       insert_expr_in_table (dest, GET_MODE (dest), insn,
-				     antic_p, avail_p, max_distance, table);
-             }
-      }
+	  /* Record the memory expression (DEST) in the hash table.  */
+	  insert_expr_in_table (dest, GET_MODE (dest), insn,
+				antic_p, avail_p, max_distance, table);
+	}
+    }
 }
 
 static void
Index: gcc/hooks.c
===================================================================
--- gcc/hooks.c	(revision 224310)
+++ gcc/hooks.c	(working copy)
@@ -333,12 +333,12 @@ hook_bool_uintp_uintp_false (unsigned int *a ATTRI
 }
 
 bool
-hook_bool_rtx_int_int_int_intp_bool_false (rtx a ATTRIBUTE_UNUSED,
-					   int b ATTRIBUTE_UNUSED,
-					   int c ATTRIBUTE_UNUSED,
-					   int d ATTRIBUTE_UNUSED,
-					   int *e ATTRIBUTE_UNUSED,
-					   bool speed_p ATTRIBUTE_UNUSED)
+hook_bool_rtx_mode_int_int_intp_bool_false (rtx a ATTRIBUTE_UNUSED,
+					    machine_mode b ATTRIBUTE_UNUSED,
+					    int c ATTRIBUTE_UNUSED,
+					    int d ATTRIBUTE_UNUSED,
+					    int *e ATTRIBUTE_UNUSED,
+					    bool speed_p ATTRIBUTE_UNUSED)
 {
   return false;
 }
Index: gcc/hooks.h
===================================================================
--- gcc/hooks.h	(revision 224310)
+++ gcc/hooks.h	(working copy)
@@ -55,8 +55,8 @@ extern bool hook_bool_rtx_insn_true (rtx_insn *);
 extern bool hook_bool_rtx_false (rtx);
 extern bool hook_bool_rtx_insn_int_false (rtx_insn *, int);
 extern bool hook_bool_uintp_uintp_false (unsigned int *, unsigned int *);
-extern bool hook_bool_rtx_int_int_int_intp_bool_false (rtx, int, int, int,
-						       int *, bool);
+extern bool hook_bool_rtx_mode_int_int_intp_bool_false (rtx, machine_mode,
+							int, int, int *, bool);
 extern bool hook_bool_tree_tree_false (tree, tree);
 extern bool hook_bool_tree_tree_true (tree, tree);
 extern bool hook_bool_tree_bool_false (tree, bool);
Index: gcc/ifcvt.c
===================================================================
--- gcc/ifcvt.c	(revision 224310)
+++ gcc/ifcvt.c	(working copy)
@@ -2243,7 +2243,7 @@ noce_try_sign_mask (struct noce_if_info *if_info)
      && (if_info->insn_b == NULL_RTX
 	 || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb));
   if (!(t_unconditional
-	|| (set_src_cost (t, optimize_bb_for_speed_p (if_info->test_bb))
+	|| (set_src_cost (t, mode, optimize_bb_for_speed_p (if_info->test_bb))
 	    < COSTS_N_INSNS (2))))
     return FALSE;
 
Index: gcc/loop-doloop.c
===================================================================
--- gcc/loop-doloop.c	(revision 224310)
+++ gcc/loop-doloop.c	(working copy)
@@ -663,7 +663,7 @@ doloop_optimize (struct loop *loop)
 
   max_cost
     = COSTS_N_INSNS (PARAM_VALUE (PARAM_MAX_ITERATIONS_COMPUTATION_COST));
-  if (set_src_cost (desc->niter_expr, optimize_loop_for_speed_p (loop))
+  if (set_src_cost (desc->niter_expr, mode, optimize_loop_for_speed_p (loop))
       > max_cost)
     {
       if (dump_file)
Index: gcc/loop-invariant.c
===================================================================
--- gcc/loop-invariant.c	(revision 224310)
+++ gcc/loop-invariant.c	(working copy)
@@ -738,7 +738,8 @@ create_new_invariant (struct def *def, rtx_insn *i
     }
   else
     {
-      inv->cost = set_src_cost (SET_SRC (set), speed);
+      inv->cost = set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
+				speed);
       inv->cheap_address = false;
     }
 
Index: gcc/lower-subreg.c
===================================================================
--- gcc/lower-subreg.c	(revision 224310)
+++ gcc/lower-subreg.c	(working copy)
@@ -146,7 +146,7 @@ shift_cost (bool speed_p, struct cost_rtxes *rtxes
   PUT_MODE (rtxes->shift, mode);
   PUT_MODE (rtxes->source, mode);
   XEXP (rtxes->shift, 1) = GEN_INT (op1);
-  return set_src_cost (rtxes->shift, speed_p);
+  return set_src_cost (rtxes->shift, mode, speed_p);
 }
 
 /* For each X in the range [0, BITS_PER_WORD), set SPLITTING[X]
@@ -250,7 +250,7 @@ compute_costs (bool speed_p, struct cost_rtxes *rt
       /* The only case here to check to see if moving the upper part with a
 	 zero is cheaper than doing the zext itself.  */
       PUT_MODE (rtxes->source, word_mode);
-      zext_cost = set_src_cost (rtxes->zext, speed_p);
+      zext_cost = set_src_cost (rtxes->zext, twice_word_mode, speed_p);
 
       if (LOG_COSTS)
 	fprintf (stderr, "%s %s: original cost %d, split cost %d + %d\n",
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	(revision 224310)
+++ gcc/optabs.c	(working copy)
@@ -1369,8 +1369,8 @@ avoid_expensive_constant (machine_mode mode, optab
   if (mode != VOIDmode
       && optimize
       && CONSTANT_P (x)
-      && (rtx_cost (x, optab_to_code (binoptab), opn, speed)
-	  > set_src_cost (x, speed)))
+      && (rtx_cost (x, mode, optab_to_code (binoptab), opn, speed)
+	  > set_src_cost (x, mode, speed)))
     {
       if (CONST_INT_P (x))
 	{
@@ -4051,12 +4051,12 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comp
 
   /* If we are optimizing, force expensive constants into a register.  */
   if (CONSTANT_P (x) && optimize
-      && (rtx_cost (x, COMPARE, 0, optimize_insn_for_speed_p ())
+      && (rtx_cost (x, mode, COMPARE, 0, optimize_insn_for_speed_p ())
           > COSTS_N_INSNS (1)))
     x = force_reg (mode, x);
 
   if (CONSTANT_P (y) && optimize
-      && (rtx_cost (y, COMPARE, 1, optimize_insn_for_speed_p ())
+      && (rtx_cost (y, mode, COMPARE, 1, optimize_insn_for_speed_p ())
           > COSTS_N_INSNS (1)))
     y = force_reg (mode, y);
 
@@ -8645,7 +8645,7 @@ lshift_cheap_p (bool speed_p)
     {
       rtx reg = gen_raw_REG (word_mode, 10000);
       int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
-			       speed_p);
+			       word_mode, speed_p);
       cheap[speed_p] = cost < COSTS_N_INSNS (3);
       init[speed_p] = true;
     }
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	(revision 224310)
+++ gcc/postreload.c	(working copy)
@@ -300,7 +300,7 @@ reload_cse_simplify_set (rtx set, rtx_insn *insn)
     old_cost = register_move_cost (GET_MODE (src),
 				   REGNO_REG_CLASS (REGNO (src)), dclass);
   else
-    old_cost = set_src_cost (src, speed);
+    old_cost = set_src_cost (src, GET_MODE (SET_DEST (set)), speed);
 
   for (l = val->locs; l; l = l->next)
     {
@@ -335,7 +335,7 @@ reload_cse_simplify_set (rtx set, rtx_insn *insn)
 	      this_rtx = immed_wide_int_const (result, word_mode);
 	    }
 #endif
-	  this_cost = set_src_cost (this_rtx, speed);
+	  this_cost = set_src_cost (this_rtx, GET_MODE (SET_DEST (set)), speed);
 	}
       else if (REG_P (this_rtx))
 	{
@@ -343,7 +343,7 @@ reload_cse_simplify_set (rtx set, rtx_insn *insn)
 	  if (extend_op != UNKNOWN)
 	    {
 	      this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
-	      this_cost = set_src_cost (this_rtx, speed);
+	      this_cost = set_src_cost (this_rtx, word_mode, speed);
 	    }
 	  else
 #endif
@@ -586,10 +586,10 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx
 		      && TEST_BIT (preferred, j)
 		      && reg_fits_class_p (testreg, rclass, 0, mode)
 		      && (!CONST_INT_P (recog_data.operand[i])
-			  || (set_src_cost (recog_data.operand[i],
+			  || (set_src_cost (recog_data.operand[i], mode,
 					    optimize_bb_for_speed_p
 					     (BLOCK_FOR_INSN (insn)))
-			      > set_src_cost (testreg,
+			      > set_src_cost (testreg, mode,
 					      optimize_bb_for_speed_p
 					       (BLOCK_FOR_INSN (insn))))))
 		    {
@@ -922,12 +922,13 @@ try_replace_in_use (struct reg_use *use, rtx reg,
 	  && CONSTANT_P (XEXP (SET_SRC (new_set), 1)))
 	{
 	  rtx new_src;
-	  int old_cost = set_src_cost (SET_SRC (new_set), speed);
+	  machine_mode mode = GET_MODE (SET_DEST (new_set));
+	  int old_cost = set_src_cost (SET_SRC (new_set), mode, speed);
 
 	  gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg));
 	  new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src);
 
-	  if (set_src_cost (new_src, speed) <= old_cost
+	  if (set_src_cost (new_src, mode, speed) <= old_cost
 	      && validate_change (use_insn, &SET_SRC (new_set),
 				  new_src, 0))
 	    return true;
@@ -2025,7 +2026,7 @@ reload_cse_move2add (rtx_insn *first)
 
 			  get_full_set_rtx_cost (set, &oldcst);
 			  SET_SRC (set) = tem;
-			  get_full_set_src_cost (tem, &newcst);
+			  get_full_set_src_cost (tem, GET_MODE (reg), &newcst);
 			  SET_SRC (set) = old_src;
 			  costs_add_n_insns (&oldcst, 1);
 
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c	(revision 224310)
+++ gcc/reload1.c	(working copy)
@@ -1648,7 +1648,9 @@ calculate_elim_costs_all_insns (void)
 		    {
 		      rtx t = eliminate_regs_1 (SET_SRC (set), VOIDmode, insn,
 						false, true);
-		      int cost = set_src_cost (t, optimize_bb_for_speed_p (bb));
+		      machine_mode mode = GET_MODE (SET_DEST (set));
+		      int cost = set_src_cost (t, mode,
+					       optimize_bb_for_speed_p (bb));
 		      int freq = REG_FREQ_FROM_BB (bb);
 
 		      reg_equiv_init_cost[regno] = cost * freq;
@@ -2520,7 +2522,8 @@ note_reg_elim_costly (const_rtx x, rtx insn)
 	{
 	  rtx t = reg_equiv_invariant (REGNO (x));
 	  rtx new_rtx = eliminate_regs_1 (t, Pmode, insn, true, true);
-	  int cost = set_src_cost (new_rtx, optimize_bb_for_speed_p (elim_bb));
+	  int cost = set_src_cost (new_rtx, Pmode,
+				   optimize_bb_for_speed_p (elim_bb));
 	  int freq = REG_FREQ_FROM_BB (elim_bb);
 
 	  if (cost != 0)
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	(revision 224310)
+++ gcc/simplify-rtx.c	(working copy)
@@ -2095,8 +2095,8 @@ simplify_binary_operation_1 (enum rtx_code code, m
 	      coeff = immed_wide_int_const (coeff0 + coeff1, mode);
 
 	      tem = simplify_gen_binary (MULT, mode, lhs, coeff);
-	      return set_src_cost (tem, speed) <= set_src_cost (orig, speed)
-		? tem : 0;
+	      return (set_src_cost (tem, mode, speed)
+		      <= set_src_cost (orig, mode, speed) ? tem : 0);
 	    }
 	}
 
@@ -2270,8 +2270,8 @@ simplify_binary_operation_1 (enum rtx_code code, m
 	      coeff = immed_wide_int_const (coeff0 + negcoeff1, mode);
 
 	      tem = simplify_gen_binary (MULT, mode, lhs, coeff);
-	      return set_src_cost (tem, speed) <= set_src_cost (orig, speed)
-		? tem : 0;
+	      return (set_src_cost (tem, mode, speed)
+		      <= set_src_cost (orig, mode, speed) ? tem : 0);
 	    }
 	}
 
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c	(revision 224310)
+++ gcc/tree-ssa-loop-ivopts.c	(working copy)
@@ -3295,7 +3295,7 @@ computation_cost (tree expr, bool speed)
     cost += address_cost (XEXP (rslt, 0), TYPE_MODE (type),
 			  TYPE_ADDR_SPACE (type), speed);
   else if (!REG_P (rslt))
-    cost += set_src_cost (rslt, speed);
+    cost += set_src_cost (rslt, TYPE_MODE (type), speed);
 
   return cost;
 }
Index: gcc/tree-ssa-reassoc.c
===================================================================
--- gcc/tree-ssa-reassoc.c	(revision 224310)
+++ gcc/tree-ssa-reassoc.c	(working copy)
@@ -2549,10 +2549,10 @@ optimize_range_tests_to_bit_test (enum tree_code o
 						      GEN_INT (-m)), speed_p);
 	      rtx r = immed_wide_int_const (mask, word_mode);
 	      cost_diff += set_src_cost (gen_rtx_AND (word_mode, reg, r),
-					 speed_p);
+					 word_mode, speed_p);
 	      r = immed_wide_int_const (wi::lshift (mask, m), word_mode);
 	      cost_diff -= set_src_cost (gen_rtx_AND (word_mode, reg, r),
-					 speed_p);
+					 word_mode, speed_p);
 	      if (cost_diff > 0)
 		{
 		  mask = wi::lshift (mask, m);
Index: gcc/tree-switch-conversion.c
===================================================================
--- gcc/tree-switch-conversion.c	(revision 224310)
+++ gcc/tree-switch-conversion.c	(working copy)
@@ -380,9 +380,11 @@ emit_case_bit_tests (gswitch *swtch, tree index_ex
       for (i = 0; i < count; i++)
 	{
 	  rtx r = immed_wide_int_const (test[i].mask, word_mode);
-	  cost_diff += set_src_cost (gen_rtx_AND (word_mode, reg, r), speed_p);
+	  cost_diff += set_src_cost (gen_rtx_AND (word_mode, reg, r),
+				     word_mode, speed_p);
 	  r = immed_wide_int_const (wi::lshift (test[i].mask, m), word_mode);
-	  cost_diff -= set_src_cost (gen_rtx_AND (word_mode, reg, r), speed_p);
+	  cost_diff -= set_src_cost (gen_rtx_AND (word_mode, reg, r),
+				     word_mode, speed_p);
 	}
       if (cost_diff > 0)
 	{
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	(revision 224310)
+++ gcc/config/aarch64/aarch64.c	(working copy)
@@ -5182,7 +5182,7 @@ aarch64_shift_p (enum rtx_code code)
    operands where needed.  */
 
 static int
-aarch64_rtx_mult_cost (rtx x, int code, int outer, bool speed)
+aarch64_rtx_mult_cost (rtx x, enum rtx_code code, int outer, bool speed)
 {
   rtx op0, op1;
   const struct cpu_cost_table *extra_cost
@@ -5233,7 +5233,7 @@ static int
 	  if (is_extend)
 	    op0 = aarch64_strip_extend (op0);
 
-	  cost += rtx_cost (op0, GET_CODE (op0), 0, speed);
+	  cost += rtx_cost (op0, VOIDmode, code, 0, speed);
 
 	  return cost;
 	}
@@ -5253,8 +5253,8 @@ static int
 	  || (GET_CODE (op0) == SIGN_EXTEND
 	      && GET_CODE (op1) == SIGN_EXTEND))
 	{
-	  cost += rtx_cost (XEXP (op0, 0), MULT, 0, speed)
-		  + rtx_cost (XEXP (op1, 0), MULT, 1, speed);
+	  cost += rtx_cost (XEXP (op0, 0), VOIDmode, MULT, 0, speed);
+	  cost += rtx_cost (XEXP (op1, 0), VOIDmode, MULT, 1, speed);
 
 	  if (speed)
 	    {
@@ -5271,8 +5271,8 @@ static int
 
       /* This is either an integer multiply or a MADD.  In both cases
 	 we want to recurse and cost the operands.  */
-      cost += rtx_cost (op0, MULT, 0, speed)
-	      + rtx_cost (op1, MULT, 1, speed);
+      cost += rtx_cost (op0, mode, MULT, 0, speed);
+      cost += rtx_cost (op1, mode, MULT, 1, speed);
 
       if (speed)
 	{
@@ -5305,8 +5305,8 @@ static int
 	    cost += extra_cost->fp[mode == DFmode].mult;
 	}
 
-      cost += rtx_cost (op0, MULT, 0, speed)
-	      + rtx_cost (op1, MULT, 1, speed);
+      cost += rtx_cost (op0, mode, MULT, 0, speed);
+      cost += rtx_cost (op1, mode, MULT, 1, speed);
       return cost;
     }
 }
@@ -5330,7 +5330,7 @@ aarch64_address_cost (rtx x,
 	  /* This is a CONST or SYMBOL ref which will be split
 	     in a different way depending on the code model in use.
 	     Cost it through the generic infrastructure.  */
-	  int cost_symbol_ref = rtx_cost (x, MEM, 1, speed);
+	  int cost_symbol_ref = rtx_cost (x, Pmode, MEM, 1, speed);
 	  /* Divide through by the cost of one instruction to
 	     bring it to the same units as the address costs.  */
 	  cost_symbol_ref /= COSTS_N_INSNS (1);
@@ -5553,11 +5553,11 @@ aarch64_if_then_else_costs (rtx op0, rtx op1, rtx
 		  /* TBZ/TBNZ/CBZ/CBNZ.  */
 		  if (GET_CODE (inner) == ZERO_EXTRACT)
 		    /* TBZ/TBNZ.  */
-		    *cost += rtx_cost (XEXP (inner, 0), ZERO_EXTRACT,
-			 	       0, speed);
-		else
-		  /* CBZ/CBNZ.  */
-		  *cost += rtx_cost (inner, cmpcode, 0, speed);
+		    *cost += rtx_cost (XEXP (inner, 0), VOIDmode,
+				       ZERO_EXTRACT, 0, speed);
+		  else
+		    /* CBZ/CBNZ.  */
+		    *cost += rtx_cost (inner, VOIDmode, cmpcode, 0, speed);
 
 	        return true;
 	      }
@@ -5581,8 +5581,8 @@ aarch64_if_then_else_costs (rtx op0, rtx op1, rtx
           || (GET_CODE (op1) == PLUS && XEXP (op1, 1) == const1_rtx))
 	op1 = XEXP (op1, 0);
 
-      *cost += rtx_cost (op1, IF_THEN_ELSE, 1, speed);
-      *cost += rtx_cost (op2, IF_THEN_ELSE, 2, speed);
+      *cost += rtx_cost (op1, VOIDmode, IF_THEN_ELSE, 1, speed);
+      *cost += rtx_cost (op2, VOIDmode, IF_THEN_ELSE, 2, speed);
       return true;
     }
 
@@ -5593,13 +5593,13 @@ aarch64_if_then_else_costs (rtx op0, rtx op1, rtx
 /* Calculate the cost of calculating X, storing it in *COST.  Result
    is true if the total cost of the operation has now been calculated.  */
 static bool
-aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
+aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 		   int param ATTRIBUTE_UNUSED, int *cost, bool speed)
 {
   rtx op0, op1, op2;
   const struct cpu_cost_table *extra_cost
     = aarch64_tune_params->insn_extra_cost;
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
 
   /* By default, assume that everything has equivalent cost to the
      cheapest instruction.  Any additional costs are applied as a delta
@@ -5634,12 +5634,12 @@ static bool
 						     0, speed));
 	    }
 
-	  *cost += rtx_cost (op1, SET, 1, speed);
+	  *cost += rtx_cost (op1, mode, SET, 1, speed);
 	  return true;
 
 	case SUBREG:
 	  if (! REG_P (SUBREG_REG (op0)))
-	    *cost += rtx_cost (SUBREG_REG (op0), SET, 0, speed);
+	    *cost += rtx_cost (SUBREG_REG (op0), VOIDmode, SET, 0, speed);
 
 	  /* Fall through.  */
 	case REG:
@@ -5661,7 +5661,7 @@ static bool
 	    }
           else
 	    /* Cost is just the cost of the RHS of the set.  */
-	    *cost += rtx_cost (op1, SET, 1, speed);
+	    *cost += rtx_cost (op1, mode, SET, 1, speed);
 	  return true;
 
 	case ZERO_EXTRACT:
@@ -5687,7 +5687,7 @@ static bool
               /* BFM.  */
 	      if (speed)
 		*cost += extra_cost->alu.bfi;
-              *cost += rtx_cost (op1, (enum rtx_code) code, 1, speed);
+	      *cost += rtx_cost (op1, VOIDmode, (enum rtx_code) code, 1, speed);
             }
 
 	  return true;
@@ -5785,23 +5785,23 @@ static bool
 	  return false;
 	}
 
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
-       {
+      if (GET_MODE_CLASS (mode) == MODE_INT)
+	{
           if (GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMPARE
               || GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMM_COMPARE)
             {
               /* CSETM.  */
-              *cost += rtx_cost (XEXP (op0, 0), NEG, 0, speed);
+	      *cost += rtx_cost (XEXP (op0, 0), VOIDmode, NEG, 0, speed);
               return true;
             }
 
 	  /* Cost this as SUB wzr, X.  */
-          op0 = CONST0_RTX (GET_MODE (x));
+          op0 = CONST0_RTX (mode);
           op1 = XEXP (x, 0);
           goto cost_minus;
         }
 
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
         {
           /* Support (neg(fma...)) as a single instruction only if
              sign of zeros is unimportant.  This matches the decision
@@ -5809,7 +5809,7 @@ static bool
           if (GET_CODE (op0) == FMA && !HONOR_SIGNED_ZEROS (GET_MODE (op0)))
             {
 	      /* FNMADD.  */
-              *cost = rtx_cost (op0, NEG, 0, speed);
+	      *cost = rtx_cost (op0, mode, NEG, 0, speed);
               return true;
             }
 	  if (speed)
@@ -5840,6 +5840,7 @@ static bool
 	  && GET_CODE (op0) == AND)
 	{
 	  x = op0;
+	  mode = GET_MODE (op0);
 	  goto cost_logic;
 	}
 
@@ -5849,9 +5850,10 @@ static bool
 	     needs encoding in the cost tables.  */
 
           /* CC_ZESWPmode supports zero extend for free.  */
-          if (GET_MODE (x) == CC_ZESWPmode && GET_CODE (op0) == ZERO_EXTEND)
+          if (mode == CC_ZESWPmode && GET_CODE (op0) == ZERO_EXTEND)
             op0 = XEXP (op0, 0);
 
+	  mode = GET_MODE (op0);
           /* ANDS.  */
           if (GET_CODE (op0) == AND)
             {
@@ -5879,8 +5881,8 @@ static bool
 	      if (speed)
 		*cost += extra_cost->alu.arith;
 
-              *cost += rtx_cost (op0, COMPARE, 0, speed);
-	      *cost += rtx_cost (XEXP (op1, 0), NEG, 1, speed);
+	      *cost += rtx_cost (op0, mode, COMPARE, 0, speed);
+	      *cost += rtx_cost (XEXP (op1, 0), mode, NEG, 1, speed);
               return true;
             }
 
@@ -5907,7 +5909,7 @@ static bool
 
           if (CONST_DOUBLE_P (op1) && aarch64_float_const_zero_rtx_p (op1))
             {
-              *cost += rtx_cost (op0, COMPARE, 0, speed);
+	      *cost += rtx_cost (op0, VOIDmode, COMPARE, 0, speed);
               /* FCMP supports constant 0.0 for no extra cost. */
               return true;
             }
@@ -5936,7 +5938,7 @@ static bool
 	op1 = XEXP (x, 1);
 
 cost_minus:
-	*cost += rtx_cost (op0, MINUS, 0, speed);
+	*cost += rtx_cost (op0, mode, MINUS, 0, speed);
 
 	/* Detect valid immediates.  */
 	if ((GET_MODE_CLASS (mode) == MODE_INT
@@ -5957,9 +5959,8 @@ cost_minus:
 	    if (speed)
 	      *cost += extra_cost->alu.extend_arith;
 
-	    *cost += rtx_cost (XEXP (XEXP (op1, 0), 0),
-			       (enum rtx_code) GET_CODE (op1),
-			       0, speed);
+	    *cost += rtx_cost (XEXP (XEXP (op1, 0), 0), VOIDmode,
+			       (enum rtx_code) GET_CODE (op1), 0, speed);
 	    return true;
 	  }
 
@@ -5976,7 +5977,7 @@ cost_minus:
 	    return true;
 	  }
 
-	*cost += rtx_cost (new_op1, MINUS, 1, speed);
+	*cost += rtx_cost (new_op1, VOIDmode, MINUS, 1, speed);
 
 	if (speed)
 	  {
@@ -6011,8 +6012,8 @@ cost_plus:
 	    || GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMM_COMPARE)
 	  {
 	    /* CSINC.  */
-	    *cost += rtx_cost (XEXP (op0, 0), PLUS, 0, speed);
-	    *cost += rtx_cost (op1, PLUS, 1, speed);
+	    *cost += rtx_cost (XEXP (op0, 0), mode, PLUS, 0, speed);
+	    *cost += rtx_cost (op1, mode, PLUS, 1, speed);
 	    return true;
 	  }
 
@@ -6020,7 +6021,7 @@ cost_plus:
 	    && CONST_INT_P (op1)
 	    && aarch64_uimm12_shift (INTVAL (op1)))
 	  {
-	    *cost += rtx_cost (op0, PLUS, 0, speed);
+	    *cost += rtx_cost (op0, mode, PLUS, 0, speed);
 
 	    if (speed)
 	      /* ADD (immediate).  */
@@ -6028,7 +6029,7 @@ cost_plus:
 	    return true;
 	  }
 
-	*cost += rtx_cost (op1, PLUS, 1, speed);
+	*cost += rtx_cost (op1, mode, PLUS, 1, speed);
 
 	/* Look for ADD (extended register).  */
         if (aarch64_rtx_arith_op_extract_p (op0, mode))
@@ -6036,9 +6037,8 @@ cost_plus:
 	    if (speed)
 	      *cost += extra_cost->alu.extend_arith;
 
-	    *cost += rtx_cost (XEXP (XEXP (op0, 0), 0),
-			       (enum rtx_code) GET_CODE (op0),
-			       0, speed);
+	    *cost += rtx_cost (XEXP (XEXP (op0, 0), 0), VOIDmode,
+			       (enum rtx_code) GET_CODE (op0), 0, speed);
 	    return true;
 	  }
 
@@ -6054,7 +6054,7 @@ cost_plus:
 	    return true;
 	  }
 
-	*cost += rtx_cost (new_op0, PLUS, 0, speed);
+	*cost += rtx_cost (new_op0, VOIDmode, PLUS, 0, speed);
 
 	if (speed)
 	  {
@@ -6106,8 +6106,8 @@ cost_plus:
 
       if (aarch64_extr_rtx_p (x, &op0, &op1))
         {
-          *cost += rtx_cost (op0, IOR, 0, speed)
-                   + rtx_cost (op1, IOR, 1, speed);
+	  *cost += rtx_cost (op0, mode, IOR, 0, speed);
+	  *cost += rtx_cost (op1, mode, IOR, 1, speed);
           if (speed)
             *cost += extra_cost->alu.shift;
 
@@ -6135,20 +6135,20 @@ cost_plus:
                                INTVAL (op1)) != 0)
         {
           /* This is a UBFM/SBFM.  */
-          *cost += rtx_cost (XEXP (op0, 0), ZERO_EXTRACT, 0, speed);
+	  *cost += rtx_cost (XEXP (op0, 0), mode, ZERO_EXTRACT, 0, speed);
 	  if (speed)
 	    *cost += extra_cost->alu.bfx;
           return true;
         }
 
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
+      if (GET_MODE_CLASS (mode) == MODE_INT)
 	{
 	  /* We possibly get the immediate for free, this is not
 	     modelled.  */
 	  if (CONST_INT_P (op1)
-	      && aarch64_bitmask_imm (INTVAL (op1), GET_MODE (x)))
+	      && aarch64_bitmask_imm (INTVAL (op1), mode))
 	    {
-	      *cost += rtx_cost (op0, (enum rtx_code) code, 0, speed);
+	      *cost += rtx_cost (op0, mode, (enum rtx_code) code, 0, speed);
 
 	      if (speed)
 		*cost += extra_cost->alu.logical;
@@ -6183,8 +6183,8 @@ cost_plus:
 		}
 
 	      /* In both cases we want to cost both operands.  */
-	      *cost += rtx_cost (new_op0, (enum rtx_code) code, 0, speed)
-		       + rtx_cost (op1, (enum rtx_code) code, 1, speed);
+	      *cost += rtx_cost (new_op0, mode, (enum rtx_code) code, 0, speed);
+	      *cost += rtx_cost (op1, mode, (enum rtx_code) code, 1, speed);
 
 	      return true;
 	    }
@@ -6205,7 +6205,7 @@ cost_plus:
       /* MVN-shifted-reg.  */
       if (op0 != x)
         {
-          *cost += rtx_cost (op0, (enum rtx_code) code, 0, speed);
+	  *cost += rtx_cost (op0, mode, (enum rtx_code) code, 0, speed);
 
           if (speed)
             *cost += extra_cost->alu.log_shift;
@@ -6221,8 +6221,8 @@ cost_plus:
           rtx newop1 = XEXP (op0, 1);
           rtx op0_stripped = aarch64_strip_shift (newop0);
 
-          *cost += rtx_cost (newop1, (enum rtx_code) code, 1, speed)
-                   + rtx_cost (op0_stripped, XOR, 0, speed);
+	  *cost += rtx_cost (newop1, mode, (enum rtx_code) code, 1, speed);
+	  *cost += rtx_cost (op0_stripped, mode, XOR, 0, speed);
 
           if (speed)
             {
@@ -6255,7 +6255,7 @@ cost_plus:
 	  && GET_MODE (op0) == SImode
 	  && outer == SET)
 	{
-	  int op_cost = rtx_cost (XEXP (x, 0), ZERO_EXTEND, 0, speed);
+	  int op_cost = rtx_cost (op0, VOIDmode, ZERO_EXTEND, 0, speed);
 
 	  if (!op_cost && speed)
 	    /* MOV.  */
@@ -6266,10 +6266,10 @@ cost_plus:
 
 	  return true;
 	}
-      else if (MEM_P (XEXP (x, 0)))
+      else if (MEM_P (op0))
 	{
 	  /* All loads can zero extend to any size for free.  */
-	  *cost = rtx_cost (XEXP (x, 0), ZERO_EXTEND, param, speed);
+	  *cost = rtx_cost (op0, VOIDmode, ZERO_EXTEND, param, speed);
 	  return true;
 	}
 
@@ -6339,7 +6339,7 @@ cost_plus:
               || GET_CODE (op0) == SIGN_EXTEND)
             op0 = XEXP (op0, 0);
 
-          *cost += rtx_cost (op0, ASHIFT, 0, speed);
+	  *cost += rtx_cost (op0, VOIDmode, ASHIFT, 0, speed);
           return true;
         }
       else
@@ -6378,7 +6378,7 @@ cost_plus:
 		*cost += extra_cost->alu.shift;
 	    }
 
-	  *cost += rtx_cost (op0, (enum rtx_code) code, 0, speed);
+	  *cost += rtx_cost (op0, mode, (enum rtx_code) code, 0, speed);
 	  return true;
 	}
       else
@@ -6448,7 +6448,7 @@ cost_plus:
 
       /* We can trust that the immediates used will be correct (there
 	 are no by-register forms), so we need only cost op0.  */
-      *cost += rtx_cost (XEXP (x, 0), (enum rtx_code) code, 0, speed);
+      *cost += rtx_cost (XEXP (x, 0), VOIDmode, (enum rtx_code) code, 0, speed);
       return true;
 
     case MULT:
@@ -6463,13 +6463,13 @@ cost_plus:
 	{
 	  if (VECTOR_MODE_P (mode))
 	    *cost += extra_cost->vect.alu;
-	  else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
-	    *cost += (extra_cost->mult[GET_MODE (x) == DImode].add
-		      + extra_cost->mult[GET_MODE (x) == DImode].idiv);
-	  else if (GET_MODE (x) == DFmode)
+	  else if (GET_MODE_CLASS (mode) == MODE_INT)
+	    *cost += (extra_cost->mult[mode == DImode].add
+		      + extra_cost->mult[mode == DImode].idiv);
+	  else if (mode == DFmode)
 	    *cost += (extra_cost->fp[1].mult
 		      + extra_cost->fp[1].div);
-	  else if (GET_MODE (x) == SFmode)
+	  else if (mode == SFmode)
 	    *cost += (extra_cost->fp[0].mult
 		      + extra_cost->fp[0].div);
 	}
@@ -6552,9 +6552,9 @@ cost_plus:
 
       /* If the remaining parameters are not registers,
          get the cost to put them into registers.  */
-      *cost += rtx_cost (op0, FMA, 0, speed);
-      *cost += rtx_cost (op1, FMA, 1, speed);
-      *cost += rtx_cost (op2, FMA, 2, speed);
+      *cost += rtx_cost (op0, mode, FMA, 0, speed);
+      *cost += rtx_cost (op1, mode, FMA, 1, speed);
+      *cost += rtx_cost (op2, mode, FMA, 2, speed);
       return true;
 
     case FLOAT:
@@ -6613,7 +6613,7 @@ cost_plus:
 	  else
 	    *cost += extra_cost->fp[GET_MODE (x) == DFmode].toint;
 	}
-      *cost += rtx_cost (x, (enum rtx_code) code, 0, speed);
+      *cost += rtx_cost (x, VOIDmode, (enum rtx_code) code, 0, speed);
       return true;
 
     case ABS:
@@ -6630,8 +6630,8 @@ cost_plus:
 	  /* FABD, which is analogous to FADD.  */
 	  if (GET_CODE (op0) == MINUS)
 	    {
-	      *cost += rtx_cost (XEXP (op0, 0), MINUS, 0, speed);
-			+ rtx_cost (XEXP (op0, 1), MINUS, 1, speed);
+	      *cost += rtx_cost (XEXP (op0, 0), mode, MINUS, 0, speed);
+	      *cost += rtx_cost (XEXP (op0, 1), mode, MINUS, 1, speed);
 	      if (speed)
 		*cost += extra_cost->fp[mode == DFmode].addsub;
 
@@ -6712,10 +6712,10 @@ cost_plus:
           /* UMULH/SMULH.  */
 	  if (speed)
 	    *cost += extra_cost->mult[mode == DImode].extend;
-          *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0),
-			     MULT, 0, speed);
-          *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0),
-			     MULT, 1, speed);
+	  *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0),
+			     mode, MULT, 0, speed);
+	  *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0),
+			     mode, MULT, 1, speed);
           return true;
         }
 
@@ -6735,10 +6735,10 @@ cost_plus:
    calculated for X.  This cost is stored in *COST.  Returns true
    if the total cost of X was calculated.  */
 static bool
-aarch64_rtx_costs_wrapper (rtx x, int code, int outer,
+aarch64_rtx_costs_wrapper (rtx x, machine_mode mode, int outer,
 		   int param, int *cost, bool speed)
 {
-  bool result = aarch64_rtx_costs (x, code, outer, param, cost, speed);
+  bool result = aarch64_rtx_costs (x, mode, outer, param, cost, speed);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	(revision 224310)
+++ gcc/config/alpha/alpha.c	(working copy)
@@ -1371,10 +1371,10 @@ alpha_legitimize_reload_address (rtx x,
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-alpha_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
+alpha_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total,
 		 bool speed)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   bool float_mode_p = FLOAT_MODE_P (mode);
   const struct alpha_rtx_cost_data *cost_data;
 
@@ -1439,9 +1439,9 @@ static bool
       else if (GET_CODE (XEXP (x, 0)) == MULT
 	       && const48_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
 	{
-	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0),
+	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0), mode,
 			      (enum rtx_code) outer_code, opno, speed)
-		    + rtx_cost (XEXP (x, 1),
+		    + rtx_cost (XEXP (x, 1), mode,
 				(enum rtx_code) outer_code, opno, speed)
 		    + COSTS_N_INSNS (1));
 	  return true;
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c	(revision 224310)
+++ gcc/config/arc/arc.c	(working copy)
@@ -4116,9 +4116,11 @@ static void arc_file_start (void)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-	       int *total, bool speed)
+arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
+	       int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       /* Small integers are as cheap as registers.  */
@@ -4210,7 +4212,8 @@ static bool
 	  if (CONSTANT_P (XEXP (x, 0)))
 	    {
 	      *total += (COSTS_N_INSNS (2)
-			 + rtx_cost (XEXP (x, 1), (enum rtx_code) code, 0, speed));
+			 + rtx_cost (XEXP (x, 1), mode, (enum rtx_code) code,
+				     0, speed));
 	      return true;
 	    }
 	  *total = COSTS_N_INSNS (1);
@@ -4252,8 +4255,8 @@ static bool
       if (GET_CODE (XEXP (x, 0)) == MULT
 	  && _2_4_8_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
 	{
-	  *total += (rtx_cost (XEXP (x, 1), PLUS, 0, speed)
-		     + rtx_cost (XEXP (XEXP (x, 0), 0), PLUS, 1, speed));
+	  *total += (rtx_cost (XEXP (x, 1), mode, PLUS, 0, speed)
+		     + rtx_cost (XEXP (XEXP (x, 0), 0), mode, PLUS, 1, speed));
 	  return true;
 	}
       return false;
@@ -4261,8 +4264,8 @@ static bool
       if (GET_CODE (XEXP (x, 1)) == MULT
 	  && _2_4_8_operand (XEXP (XEXP (x, 1), 1), VOIDmode))
 	{
-	  *total += (rtx_cost (XEXP (x, 0), PLUS, 0, speed)
-		     + rtx_cost (XEXP (XEXP (x, 1), 0), PLUS, 1, speed));
+	  *total += (rtx_cost (XEXP (x, 0), mode, PLUS, 0, speed)
+		     + rtx_cost (XEXP (XEXP (x, 1), 0), mode, PLUS, 1, speed));
 	  return true;
 	}
       return false;
@@ -4277,8 +4280,9 @@ static bool
 	    /* btst / bbit0 / bbit1:
 	       Small integers and registers are free; everything else can
 	       be put in a register.  */
-	    *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
-		      + rtx_cost (XEXP (op0, 2), SET, 1, speed));
+	    mode = GET_MODE (XEXP (op0, 0));
+	    *total = (rtx_cost (XEXP (op0, 0), mode, SET, 1, speed)
+		      + rtx_cost (XEXP (op0, 2), mode, SET, 1, speed));
 	    return true;
 	  }
 	if (GET_CODE (op0) == AND && op1 == const0_rtx
@@ -4285,7 +4289,7 @@ static bool
 	    && satisfies_constraint_C1p (XEXP (op0, 1)))
 	  {
 	    /* bmsk.f */
-	    *total = rtx_cost (XEXP (op0, 0), SET, 1, speed);
+	    *total = rtx_cost (XEXP (op0, 0), VOIDmode, SET, 1, speed);
 	    return true;
 	  }
 	/* add.f  */
@@ -4294,8 +4298,9 @@ static bool
 	    /* op0 might be constant, the inside of op1 is rather
 	       unlikely to be so.  So swapping the operands might lower
 	       the cost.  */
-	    *total = (rtx_cost (op0, PLUS, 1, speed)
-		      + rtx_cost (XEXP (op1, 0), PLUS, 0, speed));
+	    mode = GET_MODE (op0);
+	    *total = (rtx_cost (op0, mode, PLUS, 1, speed)
+		      + rtx_cost (XEXP (op1, 0), mode, PLUS, 0, speed));
 	  }
 	return false;
       }
@@ -4310,18 +4315,19 @@ static bool
 	     be put in a register.  */
 	  rtx op0 = XEXP (x, 0);
 
-	  *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
-		    + rtx_cost (XEXP (op0, 2), SET, 1, speed));
+	  mode = GET_MODE (XEXP (op0, 0));
+	  *total = (rtx_cost (XEXP (op0, 0), mode, SET, 1, speed)
+		    + rtx_cost (XEXP (op0, 2), mode, SET, 1, speed));
 	  return true;
 	}
       /* Fall through.  */
     /* scc_insn expands into two insns.  */
     case GTU: case GEU: case LEU:
-      if (GET_MODE (x) == SImode)
+      if (mode == SImode)
 	*total += COSTS_N_INSNS (1);
       return false;
     case LTU: /* might use adc.  */
-      if (GET_MODE (x) == SImode)
+      if (mode == SImode)
 	*total += COSTS_N_INSNS (1) - 1;
       return false;
     default:
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(revision 224310)
+++ gcc/config/arm/arm.c	(working copy)
@@ -190,7 +190,7 @@ static bool arm_slowmul_rtx_costs (rtx, enum rtx_c
 static bool arm_fastmul_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
 static bool arm_xscale_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
 static bool arm_9e_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
-static bool arm_rtx_costs (rtx, int, int, int, int *, bool);
+static bool arm_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int arm_address_cost (rtx, machine_mode, addr_space_t, bool);
 static int arm_register_move_cost (machine_mode, reg_class_t, reg_class_t);
 static int arm_memory_move_cost (machine_mode, reg_class_t, bool);
@@ -8262,7 +8262,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (REG_P (XEXP (x, 1)))
 	*total = COSTS_N_INSNS (1); /* Need to subtract from 32 */
       else if (!CONST_INT_P (XEXP (x, 1)))
-	*total = rtx_cost (XEXP (x, 1), code, 1, speed);
+	*total = rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 
       /* Fall through */
     case ROTATERT:
@@ -8274,7 +8274,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 
       /* Fall through */
     case ASHIFT: case LSHIFTRT: case ASHIFTRT:
-      *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+      *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
       if (mode == DImode)
 	{
 	  *total += COSTS_N_INSNS (3);
@@ -8297,7 +8297,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	  if (CONST_INT_P (XEXP (x, 0))
 	      && const_ok_for_arm (INTVAL (XEXP (x, 0))))
 	    {
-	      *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	      *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	      return true;
 	    }
 
@@ -8304,7 +8304,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	  if (CONST_INT_P (XEXP (x, 1))
 	      && const_ok_for_arm (INTVAL (XEXP (x, 1))))
 	    {
-	      *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+	      *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 	      return true;
 	    }
 
@@ -8321,7 +8321,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	      if (CONST_DOUBLE_P (XEXP (x, 0))
 		  && arm_const_double_rtx (XEXP (x, 0)))
 		{
-		  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+		  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 		  return true;
 		}
 
@@ -8328,7 +8328,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	      if (CONST_DOUBLE_P (XEXP (x, 1))
 		  && arm_const_double_rtx (XEXP (x, 1)))
 		{
-		  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+		  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 		  return true;
 		}
 
@@ -8342,7 +8342,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (CONST_INT_P (XEXP (x, 0))
 	  && const_ok_for_arm (INTVAL (XEXP (x, 0))))
 	{
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	  return true;
 	}
 
@@ -8351,8 +8351,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	  || subcode == LSHIFTRT
 	  || subcode == ROTATE || subcode == ROTATERT)
 	{
-	  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 1), 0), subcode, 0, speed);
+	  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 1), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
@@ -8360,8 +8360,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (GET_CODE (XEXP (x, 0)) == MULT
 	  && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
 	{
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), code, 0, speed);
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, code, 0, speed);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	  return true;
 	}
 
@@ -8368,8 +8368,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (subcode == MULT
 	  && power_of_two_operand (XEXP (XEXP (x, 1), 1), SImode))
 	{
-	  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 1), 0), subcode, 0, speed);
+	  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 1), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
@@ -8376,7 +8376,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == RTX_COMPARE
 	  || GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == RTX_COMM_COMPARE)
 	{
-	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, speed);
 	  if (REG_P (XEXP (XEXP (x, 1), 0))
 	      && REGNO (XEXP (XEXP (x, 1), 0)) != CC_REGNUM)
 	    *total += COSTS_N_INSNS (1);
@@ -8392,9 +8393,9 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	      || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
 	{
 	  *total = COSTS_N_INSNS (1);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), GET_CODE (XEXP (x, 0)),
-			      0, speed);
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode,
+			      GET_CODE (XEXP (x, 0)), 0, speed);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	  return true;
 	}
 
@@ -8418,7 +8419,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	      if (CONST_DOUBLE_P (XEXP (x, 1))
 		  && arm_const_double_rtx (XEXP (x, 1)))
 		{
-		  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+		  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 		  return true;
 		}
 
@@ -8432,7 +8433,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_COMPARE
 	  || GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_COMM_COMPARE)
 	{
-	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 1), code, 1, speed);
+	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 1), mode, code,
+						 1, speed);
 	  if (REG_P (XEXP (XEXP (x, 0), 0))
 	      && REGNO (XEXP (XEXP (x, 0), 0)) != CC_REGNUM)
 	    *total += COSTS_N_INSNS (1);
@@ -8459,7 +8461,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	  if (CONST_INT_P (XEXP (x, 1))
 	      && const_ok_for_op (INTVAL (XEXP (x, 1)), code))
 	    {
-	      *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+	      *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 	      return true;
 	    }
 
@@ -8470,7 +8472,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (CONST_INT_P (XEXP (x, 1))
 	  && const_ok_for_op (INTVAL (XEXP (x, 1)), code))
 	{
-	  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 	  return true;
 	}
       subcode = GET_CODE (XEXP (x, 0));
@@ -8478,8 +8480,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	  || subcode == LSHIFTRT
 	  || subcode == ROTATE || subcode == ROTATERT)
 	{
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
@@ -8486,8 +8488,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (subcode == MULT
 	  && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
 	{
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
@@ -8513,7 +8515,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	  && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
 	      || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND))
 	{
-	  *total = rtx_cost (XEXP (XEXP (x, 0), 0), LSHIFTRT, 0, speed);
+	  *total = rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, LSHIFTRT,
+			     0, speed);
 	  return true;
 	}
       *total = COSTS_N_INSNS (2); /* Plus the cost of the MULT */
@@ -8545,11 +8548,13 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	      || (subcode == MULT
 		  && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode)))
 	    {
-	      *total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
+	      *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode,
+				  0, speed);
 	      /* Register shifts cost an extra cycle.  */
 	      if (!CONST_INT_P (XEXP (XEXP (x, 0), 1)))
 		*total += COSTS_N_INSNS (1) + rtx_cost (XEXP (XEXP (x, 0), 1),
-							subcode, 1, speed);
+							mode, subcode,
+							1, speed);
 	      return true;
 	    }
 	}
@@ -8570,14 +8575,15 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	    && REG_P (XEXP (operand, 0))
 	    && REGNO (XEXP (operand, 0)) == CC_REGNUM))
 	*total += COSTS_N_INSNS (1);
-      *total += (rtx_cost (XEXP (x, 1), code, 1, speed)
-		 + rtx_cost (XEXP (x, 2), code, 2, speed));
+      *total += rtx_cost (XEXP (x, 1), VOIDmode, code, 1, speed);
+      *total += rtx_cost (XEXP (x, 2), VOIDmode, code, 2, speed);
       return true;
 
     case NE:
       if (mode == SImode && XEXP (x, 1) == const0_rtx)
 	{
-	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, speed);
 	  return true;
 	}
       goto scc_insn;
@@ -8586,7 +8592,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if ((!REG_P (XEXP (x, 0)) || REGNO (XEXP (x, 0)) != CC_REGNUM)
 	  && mode == SImode && XEXP (x, 1) == const0_rtx)
 	{
-	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, speed);
 	  return true;
 	}
       goto scc_insn;
@@ -8595,7 +8602,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if ((!REG_P (XEXP (x, 0)) || REGNO (XEXP (x, 0)) != CC_REGNUM)
 	  && mode == SImode && XEXP (x, 1) == const0_rtx)
 	{
-	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, speed);
 	  return true;
 	}
       goto scc_insn;
@@ -8636,7 +8644,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (CONST_INT_P (XEXP (x, 1))
 	  && const_ok_for_op (INTVAL (XEXP (x, 1)), code))
 	{
-	  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed);
 	  return true;
 	}
 
@@ -8645,8 +8653,9 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	  || subcode == LSHIFTRT
 	  || subcode == ROTATE || subcode == ROTATERT)
 	{
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
+	  mode = GET_MODE (XEXP (x, 0));
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
@@ -8653,8 +8662,9 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (subcode == MULT
 	  && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
 	{
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
+	  mode = GET_MODE (XEXP (x, 0));
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
@@ -8664,10 +8674,10 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
     case UMAX:
     case SMIN:
     case SMAX:
-      *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code, 0, speed);
+      *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code, 0, speed);
       if (!CONST_INT_P (XEXP (x, 1))
 	  || !const_ok_for_arm (INTVAL (XEXP (x, 1))))
-	*total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	*total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
       return true;
 
     case ABS:
@@ -8744,7 +8754,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 
     case ZERO_EXTRACT:
     case SIGN_EXTRACT:
-      *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code, 0, speed);
+      mode = GET_MODE (XEXP (x, 0));
+      *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code, 0, speed);
       return true;
 
     case CONST_INT:
@@ -8769,7 +8780,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 
     case LO_SUM:
       *total = COSTS_N_INSNS (1);
-      *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+      *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
       return true;
 
     case CONST_DOUBLE:
@@ -8787,7 +8798,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
       if (TARGET_NEON && MEM_P (SET_DEST (x))
 	  && GET_CODE (SET_SRC (x)) == VEC_SELECT)
 	{
-	  *total = rtx_cost (SET_DEST (x), code, 0, speed);
+	  mode = GET_MODE (SET_DEST (x));
+	  *total = rtx_cost (SET_DEST (x), mode, code, 0, speed);
 	  if (!neon_vector_mem_operand (SET_DEST (x), 2, true))
 	    *total += COSTS_N_INSNS (1);
 	  return true;
@@ -8798,7 +8810,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int*
 	  && MEM_P (XEXP (XEXP (SET_SRC (x), 0), 0)))
 	{
 	  rtx mem = XEXP (XEXP (SET_SRC (x), 0), 0);
-	  *total = rtx_cost (mem, code, 0, speed);
+	  mode = GET_MODE (SET_DEST (x));
+	  *total = rtx_cost (mem, mode, code, 0, speed);
 	  if (!neon_vector_mem_operand (mem, 2, true))
 	    *total += COSTS_N_INSNS (1);
 	  return true;
@@ -9021,7 +9034,8 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enu
     case ROTATE:
       if (mode == SImode && REG_P (XEXP (x, 1)))
 	{
-	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code, 0, false);
+	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, false);
 	  return true;
 	}
       /* Fall through */
@@ -9031,15 +9045,17 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enu
     case ASHIFTRT:
       if (mode == DImode && CONST_INT_P (XEXP (x, 1)))
 	{
-	  *total = COSTS_N_INSNS (3) + rtx_cost (XEXP (x, 0), code, 0, false);
+	  *total = COSTS_N_INSNS (3) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, false);
 	  return true;
 	}
       else if (mode == SImode)
 	{
-	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code, 0, false);
+	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, false);
 	  /* Slightly disparage register shifts, but not by much.  */
 	  if (!CONST_INT_P (XEXP (x, 1)))
-	    *total += 1 + rtx_cost (XEXP (x, 1), code, 1, false);
+	    *total += 1 + rtx_cost (XEXP (x, 1), mode, code, 1, false);
 	  return true;
 	}
 
@@ -9091,8 +9107,8 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enu
 	  && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
 	{
 	  *total = COSTS_N_INSNS (TARGET_THUMB2 ? 2 : 1);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), code, 0, false);
-	  *total += rtx_cost (XEXP (x, 1), code, 1, false);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, code, 0, false);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, false);
 	  return true;
 	}
 
@@ -9270,7 +9286,7 @@ arm_unspec_cost (rtx x, enum rtx_code /* outer_cod
 	*cost += (ARM_NUM_REGS (GET_MODE (x)) * extra_cost->ldst.store
 		  + extra_cost->ldst.store_unaligned);
 
-      *cost += rtx_cost (XVECEXP (x, 0, 0), UNSPEC, 0, speed_p);
+      *cost += rtx_cost (XVECEXP (x, 0, 0), VOIDmode, UNSPEC, 0, speed_p);
 #ifdef NOT_YET
       *cost += arm_address_cost (XEXP (XVECEXP (x, 0, 0), 0), GET_MODE (x),
 				 ADDR_SPACE_GENERIC, speed_p);
@@ -9309,15 +9325,18 @@ arm_unspec_cost (rtx x, enum rtx_code /* outer_cod
 	        if (shift_reg)						\
 		  {							\
 		    if (speed_p)					\
-		      *cost += extra_cost->alu.arith_shift_reg;	\
-		    *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);	\
+		      *cost += extra_cost->alu.arith_shift_reg;		\
+		    *cost += rtx_cost (shift_reg, GET_MODE (shift_reg),	\
+				       ASHIFT, 1, speed_p);		\
 		  }							\
 	        else if (speed_p)					\
-		  *cost += extra_cost->alu.arith_shift;		\
+		  *cost += extra_cost->alu.arith_shift;			\
 									\
-		  *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)	\
+		*cost += (rtx_cost (shift_op, GET_MODE (shift_op),	\
+				    ASHIFT, 0, speed_p)			\
 			  + rtx_cost (XEXP (x, 1 - IDX),		\
-			              OP, 1, speed_p));		\
+				      GET_MODE (shift_op),		\
+			              OP, 1, speed_p));			\
 	        return true;						\
 	      }								\
 	  }								\
@@ -9381,7 +9400,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	{
 	  /* Handle CONST_INT here, since the value doesn't have a mode
 	     and we would otherwise be unable to work out the true cost.  */
-	  *cost = rtx_cost (SET_DEST (x), SET, 0, speed_p);
+	  *cost = rtx_cost (SET_DEST (x), GET_MODE (SET_DEST (x)), SET,
+			    0, speed_p);
 	  outer_code = SET;
 	  /* Slightly lower the cost of setting a core reg to a constant.
 	     This helps break up chains and allows for better scheduling.  */
@@ -9488,7 +9508,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
       if (mode == SImode && REG_P (XEXP (x, 1)))
 	{
 	  *cost = (COSTS_N_INSNS (2)
-		   + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+		   + rtx_cost (XEXP (x, 0), mode, code, 0, speed_p));
 	  if (speed_p)
 	    *cost += extra_cost->alu.shift_reg;
 	  return true;
@@ -9501,7 +9521,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
       if (mode == DImode && CONST_INT_P (XEXP (x, 1)))
 	{
 	  *cost = (COSTS_N_INSNS (3)
-		   + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+		   + rtx_cost (XEXP (x, 0), mode, code, 0, speed_p));
 	  if (speed_p)
 	    *cost += 2 * extra_cost->alu.shift;
 	  return true;
@@ -9509,11 +9529,11 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
       else if (mode == SImode)
 	{
 	  *cost = (COSTS_N_INSNS (1)
-		   + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+		   + rtx_cost (XEXP (x, 0), mode, code, 0, speed_p));
 	  /* Slightly disparage register shifts at -Os, but not by much.  */
 	  if (!CONST_INT_P (XEXP (x, 1)))
 	    *cost += (speed_p ? extra_cost->alu.shift_reg : 1
-		      + rtx_cost (XEXP (x, 1), code, 1, speed_p));
+		      + rtx_cost (XEXP (x, 1), mode, code, 1, speed_p));
 	  return true;
 	}
       else if (GET_MODE_CLASS (mode) == MODE_INT
@@ -9522,12 +9542,12 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	  if (code == ASHIFT)
 	    {
 	      *cost = (COSTS_N_INSNS (1)
-		       + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+		       + rtx_cost (XEXP (x, 0), mode, code, 0, speed_p));
 	      /* Slightly disparage register shifts at -Os, but not by
 	         much.  */
 	      if (!CONST_INT_P (XEXP (x, 1)))
 		*cost += (speed_p ? extra_cost->alu.shift_reg : 1
-			  + rtx_cost (XEXP (x, 1), code, 1, speed_p));
+			  + rtx_cost (XEXP (x, 1), mode, code, 1, speed_p));
 	    }
 	  else if (code == LSHIFTRT || code == ASHIFTRT)
 	    {
@@ -9537,12 +9557,12 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		  *cost = COSTS_N_INSNS (1);
 		  if (speed_p)
 		    *cost += extra_cost->alu.bfx;
-		  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 		}
 	      else
 		{
 		  *cost = COSTS_N_INSNS (2);
-		  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 		  if (speed_p)
 		    {
 		      if (CONST_INT_P (XEXP (x, 1)))
@@ -9559,7 +9579,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	  else /* Rotates.  */
 	    {
 	      *cost = COSTS_N_INSNS (3 + !CONST_INT_P (XEXP (x, 1)));
-	      *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	      *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 	      if (speed_p)
 		{
 		  if (CONST_INT_P (XEXP (x, 1)))
@@ -9649,9 +9669,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      if (GET_CODE (mul_op0) == NEG)
 		mul_op0 = XEXP (mul_op0, 0);
 
-	      *cost += (rtx_cost (mul_op0, code, 0, speed_p)
-			+ rtx_cost (mul_op1, code, 0, speed_p)
-			+ rtx_cost (sub_op, code, 0, speed_p));
+	      *cost += (rtx_cost (mul_op0, mode, code, 0, speed_p)
+			+ rtx_cost (mul_op1, mode, code, 0, speed_p)
+			+ rtx_cost (sub_op, mode, code, 0, speed_p));
 
 	      return true;
 	    }
@@ -9684,13 +9704,13 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		{
 		  if (speed_p)
 		    *cost += extra_cost->alu.arith_shift_reg;
-		  *cost += rtx_cost (shift_by_reg, code, 0, speed_p);
+		  *cost += rtx_cost (shift_by_reg, mode, code, 0, speed_p);
 		}
 	      else if (speed_p)
 		*cost += extra_cost->alu.arith_shift;
 
-	      *cost += (rtx_cost (shift_op, code, 0, speed_p)
-			+ rtx_cost (non_shift_op, code, 0, speed_p));
+	      *cost += rtx_cost (shift_op, mode, code, 0, speed_p);
+	      *cost += rtx_cost (non_shift_op, mode, code, 0, speed_p);
 	      return true;
 	    }
 
@@ -9700,9 +9720,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      /* MLS.  */
 	      if (speed_p)
 		*cost += extra_cost->mult[0].add;
-	      *cost += (rtx_cost (XEXP (x, 0), MINUS, 0, speed_p)
-			+ rtx_cost (XEXP (XEXP (x, 1), 0), MULT, 0, speed_p)
-			+ rtx_cost (XEXP (XEXP (x, 1), 1), MULT, 1, speed_p));
+	      *cost += rtx_cost (XEXP (x, 0), mode, MINUS, 0, speed_p);
+	      *cost += rtx_cost (XEXP (XEXP (x, 1), 0), mode, MULT, 0, speed_p);
+	      *cost += rtx_cost (XEXP (XEXP (x, 1), 1), mode, MULT, 1, speed_p);
 	      return true;
 	    }
 
@@ -9714,7 +9734,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      *cost = COSTS_N_INSNS (insns);
 	      if (speed_p)
 		*cost += insns * extra_cost->alu.arith;
-	      *cost += rtx_cost (XEXP (x, 1), code, 1, speed_p);
+	      *cost += rtx_cost (XEXP (x, 1), mode, code, 1, speed_p);
 	      return true;
 	    }
 	  else if (speed_p)
@@ -9742,7 +9762,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 
 	  if (CONST_INT_P (XEXP (x, 0)))
 	    {
-	      *cost += rtx_cost (XEXP (x, 1), code, 1, speed_p);
+	      *cost += rtx_cost (XEXP (x, 1), mode, code, 1, speed_p);
 	      return true;
 	    }
 
@@ -9761,10 +9781,11 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		*cost += 2 * extra_cost->alu.arith;
 
 	      if (GET_CODE (op1) == ZERO_EXTEND)
-		*cost += rtx_cost (XEXP (op1, 0), ZERO_EXTEND, 0, speed_p);
+		*cost += rtx_cost (XEXP (op1, 0), VOIDmode, ZERO_EXTEND,
+				   0, speed_p);
 	      else
-		*cost += rtx_cost (op1, MINUS, 1, speed_p);
-	      *cost += rtx_cost (XEXP (XEXP (x, 0), 0), ZERO_EXTEND,
+		*cost += rtx_cost (op1, mode, MINUS, 1, speed_p);
+	      *cost += rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, ZERO_EXTEND,
 				 0, speed_p);
 	      return true;
 	    }
@@ -9772,9 +9793,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	    {
 	      if (speed_p)
 		*cost += extra_cost->alu.arith + extra_cost->alu.arith_shift;
-	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), SIGN_EXTEND,
+	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, SIGN_EXTEND,
 				  0, speed_p)
-			+ rtx_cost (XEXP (x, 1), MINUS, 1, speed_p));
+			+ rtx_cost (XEXP (x, 1), mode, MINUS, 1, speed_p));
 	      return true;
 	    }
 	  else if (GET_CODE (XEXP (x, 1)) == ZERO_EXTEND
@@ -9785,8 +9806,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 			  + (GET_CODE (XEXP (x, 1)) == ZERO_EXTEND
 			     ? extra_cost->alu.arith
 			     : extra_cost->alu.arith_shift));
-	      *cost += (rtx_cost (XEXP (x, 0), MINUS, 0, speed_p)
-			+ rtx_cost (XEXP (XEXP (x, 1), 0),
+	      *cost += (rtx_cost (XEXP (x, 0), mode, MINUS, 0, speed_p)
+			+ rtx_cost (XEXP (XEXP (x, 1), 0), VOIDmode,
 				    GET_CODE (XEXP (x, 1)), 0, speed_p));
 	      return true;
 	    }
@@ -9817,9 +9838,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      mul_op1 = XEXP (XEXP (x, 0), 1);
 	      add_op = XEXP (x, 1);
 
-	      *cost += (rtx_cost (mul_op0, code, 0, speed_p)
-			+ rtx_cost (mul_op1, code, 0, speed_p)
-			+ rtx_cost (add_op, code, 0, speed_p));
+	      *cost += (rtx_cost (mul_op0, mode, code, 0, speed_p)
+			+ rtx_cost (mul_op1, mode, code, 0, speed_p)
+			+ rtx_cost (add_op, mode, code, 0, speed_p));
 
 	      return true;
 	    }
@@ -9856,7 +9877,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		*cost += insns * extra_cost->alu.arith;
 	      /* Slightly penalize a narrow operation as the result may
 		 need widening.  */
-	      *cost += 1 + rtx_cost (XEXP (x, 0), PLUS, 0, speed_p);
+	      *cost += 1 + rtx_cost (XEXP (x, 0), mode, PLUS, 0, speed_p);
 	      return true;
 	    }
 
@@ -9881,9 +9902,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      /* UXTA[BH] or SXTA[BH].  */
 	      if (speed_p)
 		*cost += extra_cost->alu.extend_arith;
-	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), ZERO_EXTEND, 0,
-				  speed_p)
-			+ rtx_cost (XEXP (x, 1), PLUS, 0, speed_p));
+	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, ZERO_EXTEND,
+				  0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, PLUS, 0, speed_p));
 	      return true;
 	    }
 
@@ -9895,13 +9916,13 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		{
 		  if (speed_p)
 		    *cost += extra_cost->alu.arith_shift_reg;
-		  *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+		  *cost += rtx_cost (shift_reg, mode, ASHIFT, 1, speed_p);
 		}
 	      else if (speed_p)
 		*cost += extra_cost->alu.arith_shift;
 
-	      *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+	      *cost += (rtx_cost (shift_op, mode, ASHIFT, 0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed_p));
 	      return true;
 	    }
 	  if (GET_CODE (XEXP (x, 0)) == MULT)
@@ -9928,19 +9949,19 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		  /* SMLA[BT][BT].  */
 		  if (speed_p)
 		    *cost += extra_cost->mult[0].extend_add;
-		  *cost += (rtx_cost (XEXP (XEXP (mul_op, 0), 0),
+		  *cost += (rtx_cost (XEXP (XEXP (mul_op, 0), 0), mode,
 				      SIGN_EXTEND, 0, speed_p)
-			    + rtx_cost (XEXP (XEXP (mul_op, 1), 0),
+			    + rtx_cost (XEXP (XEXP (mul_op, 1), 0), mode,
 					SIGN_EXTEND, 0, speed_p)
-			    + rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+			    + rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed_p));
 		  return true;
 		}
 
 	      if (speed_p)
 		*cost += extra_cost->mult[0].add;
-	      *cost += (rtx_cost (XEXP (mul_op, 0), MULT, 0, speed_p)
-			+ rtx_cost (XEXP (mul_op, 1), MULT, 1, speed_p)
-			+ rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+	      *cost += (rtx_cost (XEXP (mul_op, 0), mode, MULT, 0, speed_p)
+			+ rtx_cost (XEXP (mul_op, 1), mode, MULT, 1, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed_p));
 	      return true;
 	    }
 	  if (CONST_INT_P (XEXP (x, 1)))
@@ -9951,7 +9972,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      *cost = COSTS_N_INSNS (insns);
 	      if (speed_p)
 		*cost += insns * extra_cost->alu.arith;
-	      *cost += rtx_cost (XEXP (x, 0), PLUS, 0, speed_p);
+	      *cost += rtx_cost (XEXP (x, 0), mode, PLUS, 0, speed_p);
 	      return true;
 	    }
 	  else if (speed_p)
@@ -9972,11 +9993,11 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      *cost = COSTS_N_INSNS (1);
 	      if (speed_p)
 		*cost += extra_cost->mult[1].extend_add;
-	      *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0),
+	      *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0), mode,
 				  ZERO_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (XEXP (XEXP (x, 0), 1), 0),
+			+ rtx_cost (XEXP (XEXP (XEXP (x, 0), 1), 0), mode,
 				    ZERO_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+			+ rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed_p));
 	      return true;
 	    }
 
@@ -9991,9 +10012,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 			     ? extra_cost->alu.arith
 			     : extra_cost->alu.arith_shift));
 
-	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), ZERO_EXTEND, 0,
-				  speed_p)
-			+ rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, ZERO_EXTEND,
+				  0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed_p));
 	      return true;
 	    }
 
@@ -10037,13 +10058,13 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		{
 		  if (speed_p)
 		    *cost += extra_cost->alu.log_shift_reg;
-		  *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+		  *cost += rtx_cost (shift_reg, mode, ASHIFT, 1, speed_p);
 		}
 	      else if (speed_p)
 		*cost += extra_cost->alu.log_shift;
 
-	      *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), code, 1, speed_p));
+	      *cost += (rtx_cost (shift_op, mode, ASHIFT, 0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, code, 1, speed_p));
 	      return true;
 	    }
 
@@ -10056,14 +10077,14 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      *cost = COSTS_N_INSNS (insns);
 	      if (speed_p)
 		*cost += insns * extra_cost->alu.logical;
-	      *cost += rtx_cost (op0, code, 0, speed_p);
+	      *cost += rtx_cost (op0, mode, code, 0, speed_p);
 	      return true;
 	    }
 
 	  if (speed_p)
 	    *cost += extra_cost->alu.logical;
-	  *cost += (rtx_cost (op0, code, 0, speed_p)
-		    + rtx_cost (XEXP (x, 1), code, 1, speed_p));
+	  *cost += (rtx_cost (op0, mode, code, 0, speed_p)
+		    + rtx_cost (XEXP (x, 1), mode, code, 1, speed_p));
 	  return true;
 	}
 
@@ -10084,8 +10105,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      if (speed_p)
 		*cost += 2 * extra_cost->alu.logical;
 
-	      *cost += (rtx_cost (XEXP (op0, 0), ZERO_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), code, 0, speed_p));
+	      *cost += (rtx_cost (XEXP (op0, 0), VOIDmode, ZERO_EXTEND,
+				  0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, code, 0, speed_p));
 	      return true;
 	    }
 	  else if (GET_CODE (op0) == SIGN_EXTEND)
@@ -10093,8 +10115,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      if (speed_p)
 		*cost += extra_cost->alu.logical + extra_cost->alu.log_shift;
 
-	      *cost += (rtx_cost (XEXP (op0, 0), SIGN_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), code, 0, speed_p));
+	      *cost += (rtx_cost (XEXP (op0, 0), VOIDmode, SIGN_EXTEND,
+				  0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, code, 0, speed_p));
 	      return true;
 	    }
 
@@ -10122,8 +10145,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	  if (speed_p)
 	    *cost += extra_cost->fp[mode != SFmode].mult;
 
-	  *cost += (rtx_cost (op0, MULT, 0, speed_p)
-		    + rtx_cost (XEXP (x, 1), MULT, 1, speed_p));
+	  *cost += (rtx_cost (op0, mode, MULT, 0, speed_p)
+		    + rtx_cost (XEXP (x, 1), mode, MULT, 1, speed_p));
 	  return true;
 	}
       else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
@@ -10153,8 +10176,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      /* SMUL[TB][TB].  */
 	      if (speed_p)
 		*cost += extra_cost->mult[0].extend;
-	      *cost += (rtx_cost (XEXP (x, 0), SIGN_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), SIGN_EXTEND, 0, speed_p));
+	      *cost += rtx_cost (XEXP (x, 0), mode, SIGN_EXTEND, 0, speed_p);
+	      *cost += rtx_cost (XEXP (x, 1), mode, SIGN_EXTEND, 1, speed_p);
 	      return true;
 	    }
 	  if (speed_p)
@@ -10173,9 +10196,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      *cost = COSTS_N_INSNS (1);
 	      if (speed_p)
 		*cost += extra_cost->mult[1].extend;
-	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0),
+	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode,
 				  ZERO_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (XEXP (x, 1), 0),
+			+ rtx_cost (XEXP (XEXP (x, 1), 0), VOIDmode,
 				    ZERO_EXTEND, 0, speed_p));
 	      return true;
 	    }
@@ -10213,7 +10236,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      if (speed_p)
 		*cost += (extra_cost->alu.log_shift
 			  + extra_cost->alu.arith_shift);
-	      *cost += rtx_cost (XEXP (XEXP (x, 0), 0), ABS, 0, speed_p);
+	      *cost += rtx_cost (XEXP (XEXP (x, 0), 0), mode, ABS, 0, speed_p);
 	      return true;
 	    }
 
@@ -10228,11 +10251,12 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		    && REGNO (XEXP (XEXP (x, 0), 0)) == CC_REGNUM
 		    && XEXP (XEXP (x, 0), 1) == const0_rtx))
 		{
+		  mode = GET_MODE (XEXP (XEXP (x, 0), 0));
 		  *cost += (COSTS_N_INSNS (1)
-			    + rtx_cost (XEXP (XEXP (x, 0), 0), COMPARE, 0,
-					speed_p)
-			    + rtx_cost (XEXP (XEXP (x, 0), 1), COMPARE, 1,
-					speed_p));
+			    + rtx_cost (XEXP (XEXP (x, 0), 0), mode, COMPARE,
+					0, speed_p)
+			    + rtx_cost (XEXP (XEXP (x, 0), 1), mode, COMPARE,
+					1, speed_p));
 		  if (speed_p)
 		    *cost += extra_cost->alu.arith;
 		}
@@ -10281,11 +10305,11 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		{
 		  if (speed_p)
 		    *cost += extra_cost->alu.log_shift_reg;
-		  *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+		  *cost += rtx_cost (shift_reg, mode, ASHIFT, 1, speed_p);
 		}
 	      else if (speed_p)
 		*cost += extra_cost->alu.log_shift;
-	      *cost += rtx_cost (shift_op, ASHIFT, 0, speed_p);
+	      *cost += rtx_cost (shift_op, mode, ASHIFT, 0, speed_p);
 	      return true;
 	    }
 
@@ -10311,10 +10335,10 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	    *cost = COSTS_N_INSNS (4);
 	    return true;
 	  }
-	int op1cost = rtx_cost (XEXP (x, 1), SET, 1, speed_p);
-	int op2cost = rtx_cost (XEXP (x, 2), SET, 1, speed_p);
+	int op1cost = rtx_cost (XEXP (x, 1), mode, SET, 1, speed_p);
+	int op2cost = rtx_cost (XEXP (x, 2), mode, SET, 1, speed_p);
 
-	*cost = rtx_cost (XEXP (x, 0), IF_THEN_ELSE, 0, speed_p);
+	*cost = rtx_cost (XEXP (x, 0), mode, IF_THEN_ELSE, 0, speed_p);
 	/* Assume that if one arm of the if_then_else is a register,
 	   that it will be tied with the result and eliminate the
 	   conditional insn.  */
@@ -10357,7 +10381,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 
 	      if (XEXP (x, 1) == CONST0_RTX (op0mode))
 		{
-		  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 0), op0mode, code, 0, speed_p);
 		  return true;
 		}
 
@@ -10388,7 +10412,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		       || (GET_CODE (XEXP (x, 0)) == SUBREG
 			   && REG_P (SUBREG_REG (XEXP (x, 0))))))
 		{
-		  *cost = rtx_cost (XEXP (x, 0), COMPARE, 0, speed_p);
+		  *cost = rtx_cost (XEXP (x, 0), op0mode, COMPARE, 0, speed_p);
 
 		  /* Multiply operations that set the flags are often
 		     significantly more expensive.  */
@@ -10413,14 +10437,15 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		  *cost = COSTS_N_INSNS (1);
 		  if (shift_reg != NULL)
 		    {
-		      *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+		      *cost += rtx_cost (shift_reg, op0mode, ASHIFT,
+					 1, speed_p);
 		      if (speed_p)
 			*cost += extra_cost->alu.arith_shift_reg;
 		    }
 		  else if (speed_p)
 		    *cost += extra_cost->alu.arith_shift;
-		  *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)
-			    + rtx_cost (XEXP (x, 1), COMPARE, 1, speed_p));
+		  *cost += rtx_cost (shift_op, op0mode, ASHIFT, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 1), op0mode, COMPARE, 1, speed_p);
 		  return true;
 		}
 
@@ -10430,7 +10455,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      if (CONST_INT_P (XEXP (x, 1))
 		  && const_ok_for_op (INTVAL (XEXP (x, 1)), COMPARE))
 		{
-		  *cost += rtx_cost (XEXP (x, 0), COMPARE, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 0), op0mode, COMPARE, 0, speed_p);
 		  return true;
 		}
 	      return false;
@@ -10523,7 +10548,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 		  *cost = COSTS_N_INSNS (3);
 		  break;
 		}
-	      *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	      *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 	      return true;
 	    }
 	  else
@@ -10532,7 +10557,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      if (CONST_INT_P (XEXP (x, 1))
 		  && const_ok_for_op (INTVAL (XEXP (x, 1)), COMPARE))
 		{
-		  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 		  return true;
 		}
 
@@ -10583,7 +10608,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
       if ((arm_arch4 || GET_MODE (XEXP (x, 0)) == SImode)
 	  && MEM_P (XEXP (x, 0)))
 	{
-	  *cost = rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost = rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 
 	  if (mode == DImode)
 	    *cost += COSTS_N_INSNS (1);
@@ -10607,7 +10632,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	{
 	  /* We have SXTB/SXTH.  */
 	  *cost = COSTS_N_INSNS (1);
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  if (speed_p)
 	    *cost += extra_cost->alu.extend;
 	}
@@ -10615,7 +10640,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	{
 	  /* Needs two shifts.  */
 	  *cost = COSTS_N_INSNS (2);
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  if (speed_p)
 	    *cost += 2 * extra_cost->alu.shift;
 	}
@@ -10636,7 +10661,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	   || GET_MODE (XEXP (x, 0)) == QImode)
 	  && MEM_P (XEXP (x, 0)))
 	{
-	  *cost = rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost = rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 
 	  if (mode == DImode)
 	    *cost += COSTS_N_INSNS (1);  /* No speed penalty.  */
@@ -10660,7 +10685,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	{
 	  /* We have UXTB/UXTH.  */
 	  *cost = COSTS_N_INSNS (1);
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  if (speed_p)
 	    *cost += extra_cost->alu.extend;
 	}
@@ -10671,7 +10696,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	     shift may merge with a subsequent insn as a shifter
 	     op.  */
 	  *cost = COSTS_N_INSNS (2);
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  if (speed_p)
 	    *cost += 2 * extra_cost->alu.shift;
 	}
@@ -10815,7 +10840,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	  *cost = COSTS_N_INSNS (1);
 	  if (speed_p)
 	    *cost += extra_cost->alu.log_shift;
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 	  return true;
 	}
       /* Fall through.  */
@@ -10839,10 +10864,10 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	  *cost = COSTS_N_INSNS (1);
 	  if (speed_p)
 	    *cost += extra_cost->mult[1].extend;
-	  *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0), ZERO_EXTEND, 0,
-			      speed_p)
-		    + rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 1), ZERO_EXTEND,
-				0, speed_p));
+	  *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0), VOIDmode,
+			      ZERO_EXTEND, 0, speed_p)
+		    + rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 1), VOIDmode,
+				ZERO_EXTEND, 0, speed_p));
 	  return true;
 	}
       *cost = LIBCALL_COST (1);
@@ -10870,7 +10895,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	  *cost = COSTS_N_INSNS (1);
 	  if (speed_p)
 	    *cost += extra_cost->alu.bfx;
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 	  return true;
 	}
       /* Without UBFX/SBFX, need to resort to shift operations.  */
@@ -10877,7 +10902,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
       *cost = COSTS_N_INSNS (2);
       if (speed_p)
 	*cost += 2 * extra_cost->alu.shift;
-      *cost += rtx_cost (XEXP (x, 0), ASHIFT, 0, speed_p);
+      *cost += rtx_cost (XEXP (x, 0), mode, ASHIFT, 0, speed_p);
       return true;
 
     case FLOAT_EXTEND:
@@ -10895,7 +10920,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	      if (speed_p)
 		*cost += extra_cost->fp[0].widen;
 	    }
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  return true;
 	}
 
@@ -10908,7 +10933,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	  *cost = COSTS_N_INSNS (1);
 	  if (speed_p)
 	    *cost += extra_cost->fp[mode == DFmode].narrow;
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  return true;
 	  /* Vector modes?  */
 	}
@@ -10932,9 +10957,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
           if (GET_CODE (op2) == NEG)
             op2 = XEXP (op2, 0);
 
-          *cost += rtx_cost (op0, FMA, 0, speed_p);
-          *cost += rtx_cost (op1, FMA, 1, speed_p);
-          *cost += rtx_cost (op2, FMA, 2, speed_p);
+          *cost += rtx_cost (op0, mode, FMA, 0, speed_p);
+          *cost += rtx_cost (op1, mode, FMA, 1, speed_p);
+          *cost += rtx_cost (op2, mode, FMA, 2, speed_p);
 
           if (speed_p)
             *cost += extra_cost->fp[mode ==DFmode].fma;
@@ -10952,13 +10977,15 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 	  if (GET_MODE_CLASS (mode) == MODE_INT)
 	    {
 	      *cost = COSTS_N_INSNS (1);
+	      mode = GET_MODE (XEXP (x, 0));
 	      if (speed_p)
-		*cost += extra_cost->fp[GET_MODE (XEXP (x, 0)) == DFmode].toint;
+		*cost += extra_cost->fp[mode == DFmode].toint;
 	      /* Strip of the 'cost' of rounding towards zero.  */
 	      if (GET_CODE (XEXP (x, 0)) == FIX)
-		*cost += rtx_cost (XEXP (XEXP (x, 0), 0), code, 0, speed_p);
+		*cost += rtx_cost (XEXP (XEXP (x, 0), 0), mode, code,
+				   0, speed_p);
 	      else
-		*cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+		*cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 	      /* ??? Increase the cost to deal with transferring from
 		 FP -> CORE registers?  */
 	      return true;
@@ -11018,10 +11045,11 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum
 
 /* RTX costs when optimizing for size.  */
 static bool
-arm_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-	       int *total, bool speed)
+arm_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
+	       int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
   bool result;
+  int code = GET_CODE (x);
 
   if (TARGET_OLD_RTX_COSTS
       || (!current_tune->insn_extra_cost && !TARGET_NEW_GENERIC_COSTS))
@@ -11102,7 +11130,7 @@ arm_slowmul_rtx_costs (rtx x, enum rtx_code code,
 	    }
 
 	  *total = COSTS_N_INSNS (cost);
-	  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 	  return true;
 	}
 
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c	(revision 224310)
+++ gcc/config/avr/avr.c	(working copy)
@@ -175,7 +175,7 @@ static struct machine_function * avr_init_machine_
 
 /* Prototypes for hook implementors if needed before their implementation.  */
 
-static bool avr_rtx_costs (rtx, int, int, int, int*, bool);
+static bool avr_rtx_costs (rtx, machine_mode, int, int, int*, bool);
 
 
 /* Allocate registers from r25 to r8 for parameters for function calls.  */
@@ -2703,10 +2703,11 @@ avr_final_prescan_insn (rtx_insn *insn, rtx *opera
 
       if (set)
         fprintf (asm_out_file, "/* DEBUG: cost = %d.  */\n",
-                 set_src_cost (SET_SRC (set), optimize_insn_for_speed_p ()));
+                 set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
+			       optimize_insn_for_speed_p ()));
       else
         fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d.  */\n",
-                 rtx_cost (PATTERN (insn), INSN, 0,
+                 rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
                            optimize_insn_for_speed_p()));
     }
 }
@@ -9916,7 +9917,7 @@ avr_operand_rtx_cost (rtx x, machine_mode mode, en
     }
 
   total = 0;
-  avr_rtx_costs (x, code, outer, opno, &total, speed);
+  avr_rtx_costs (x, mode, outer, opno, &total, speed);
   return total;
 }
 
@@ -9927,11 +9928,10 @@ avr_operand_rtx_cost (rtx x, machine_mode mode, en
    In either case, *TOTAL contains the cost result.  */
 
 static bool
-avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
+avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
                  int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
-  enum rtx_code code = (enum rtx_code) codearg;
-  machine_mode mode = GET_MODE (x);
+  enum rtx_code code = GET_CODE (x);
   HOST_WIDE_INT val;
 
   switch (code)
@@ -9992,13 +9992,15 @@ static bool
     case ZERO_EXTEND:
       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
 			      - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
-      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
+      *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
+				      code, 0, speed);
       return true;
 
     case SIGN_EXTEND:
       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
 			      - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
-      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
+      *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
+				      code, 0, speed);
       return true;
 
     case PLUS:
@@ -10704,13 +10706,15 @@ static bool
 	case QImode:
 	  *total = COSTS_N_INSNS (1);
 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
-	    *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+	    *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
+					    1, speed);
 	  break;
 
         case HImode:
 	  *total = COSTS_N_INSNS (2);
 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
-            *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+            *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
+					    1, speed);
 	  else if (INTVAL (XEXP (x, 1)) != 0)
 	    *total += COSTS_N_INSNS (1);
           break;
@@ -10724,7 +10728,8 @@ static bool
         case SImode:
           *total = COSTS_N_INSNS (4);
           if (GET_CODE (XEXP (x, 1)) != CONST_INT)
-            *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+            *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
+					    1, speed);
 	  else if (INTVAL (XEXP (x, 1)) != 0)
 	    *total += COSTS_N_INSNS (3);
           break;
@@ -10732,7 +10737,8 @@ static bool
 	default:
 	  return false;
 	}
-      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
+      *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
+				      code, 0, speed);
       return true;
 
     case TRUNCATE:
@@ -10759,10 +10765,10 @@ static bool
 /* Implement `TARGET_RTX_COSTS'.  */
 
 static bool
-avr_rtx_costs (rtx x, int codearg, int outer_code,
+avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	       int opno, int *total, bool speed)
 {
-  bool done = avr_rtx_costs_1 (x, codearg, outer_code,
+  bool done = avr_rtx_costs_1 (x, mode, outer_code,
                                opno, total, speed);
 
   if (avr_log.rtx_costs)
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	(revision 224310)
+++ gcc/config/bfin/bfin.c	(working copy)
@@ -2803,10 +2803,10 @@ bfin_legitimate_constant_p (machine_mode mode ATTR
 }
 
 static bool
-bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
-		bool speed)
+bfin_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
+		int *total, bool speed)
 {
-  enum rtx_code code = (enum rtx_code) code_i;
+  enum rtx_code code = GET_CODE (x);
   enum rtx_code outer_code = (enum rtx_code) outer_code_i;
   int cost2 = COSTS_N_INSNS (1);
   rtx op0, op1;
@@ -2845,7 +2845,7 @@ static bool
     case PLUS:
       op0 = XEXP (x, 0);
       op1 = XEXP (x, 1);
-      if (GET_MODE (x) == SImode)
+      if (mode == SImode)
 	{
 	  if (GET_CODE (op0) == MULT
 	      && GET_CODE (XEXP (op0, 1)) == CONST_INT)
@@ -2854,8 +2854,9 @@ static bool
 	      if (val == 2 || val == 4)
 		{
 		  *total = cost2;
-		  *total += rtx_cost (XEXP (op0, 0), outer_code, opno, speed);
-		  *total += rtx_cost (op1, outer_code, opno, speed);
+		  *total += rtx_cost (XEXP (op0, 0), mode, outer_code,
+				      opno, speed);
+		  *total += rtx_cost (op1, mode, outer_code, opno, speed);
 		  return true;
 		}
 	    }
@@ -2862,27 +2863,27 @@ static bool
 	  *total = cost2;
 	  if (GET_CODE (op0) != REG
 	      && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	    *total += set_src_cost (op0, speed);
+	    *total += set_src_cost (op0, mode, speed);
 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
 	 towards creating too many induction variables.  */
 	  if (!reg_or_7bit_operand (op1, SImode))
-	    *total += set_src_cost (op1, speed);
+	    *total += set_src_cost (op1, mode, speed);
 #endif
 	}
-      else if (GET_MODE (x) == DImode)
+      else if (mode == DImode)
 	{
 	  *total = 6 * cost2;
 	  if (GET_CODE (op1) != CONST_INT
 	      || !satisfies_constraint_Ks7 (op1))
-	    *total += rtx_cost (op1, PLUS, 1, speed);
+	    *total += rtx_cost (op1, mode, PLUS, 1, speed);
 	  if (GET_CODE (op0) != REG
 	      && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	    *total += rtx_cost (op0, PLUS, 0, speed);
+	    *total += rtx_cost (op0, mode, PLUS, 0, speed);
 	}
       return true;
 
     case MINUS:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	*total = 6 * cost2;
       else
 	*total = cost2;
@@ -2891,7 +2892,7 @@ static bool
     case ASHIFT: 
     case ASHIFTRT:
     case LSHIFTRT:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	*total = 6 * cost2;
       else
 	*total = cost2;
@@ -2900,7 +2901,7 @@ static bool
       op1 = XEXP (x, 1);
       if (GET_CODE (op0) != REG
 	  && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	*total += rtx_cost (op0, code, 0, speed);
+	*total += rtx_cost (op0, mode, code, 0, speed);
 
       return true;
 	  
@@ -2925,26 +2926,26 @@ static bool
 
       if (GET_CODE (op0) != REG
 	  && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	*total += rtx_cost (op0, code, 0, speed);
+	*total += rtx_cost (op0, mode, code, 0, speed);
 
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	{
 	  *total = 2 * cost2;
 	  return true;
 	}
       *total = cost2;
-      if (GET_MODE (x) != SImode)
+      if (mode != SImode)
 	return true;
 
       if (code == AND)
 	{
 	  if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
-	    *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	    *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	}
       else
 	{
 	  if (! regorlog2_operand (XEXP (x, 1), SImode))
-	    *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	    *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	}
 
       return true;
@@ -2984,10 +2985,10 @@ static bool
 
 	  if (GET_CODE (op0) != REG
 	      && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	    *total += rtx_cost (op0, MULT, 0, speed);
+	    *total += rtx_cost (op0, mode, MULT, 0, speed);
 	  if (GET_CODE (op1) != REG
 	      && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
-	    *total += rtx_cost (op1, MULT, 1, speed);
+	    *total += rtx_cost (op1, mode, MULT, 1, speed);
 	}
       return true;
 
Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	(revision 224310)
+++ gcc/config/c6x/c6x.c	(working copy)
@@ -6049,11 +6049,12 @@ shift_p (rtx x, enum rtx_code code, int amount)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
+c6x_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total,
 	       bool speed)
 {
   int cost2 = COSTS_N_INSNS (1);
   rtx op0, op1;
+  int code = GET_CODE (x);
 
   switch (code)
     {
@@ -6082,12 +6083,12 @@ static bool
 
     case TRUNCATE:
       /* Recognize a mult_highpart operation.  */
-      if ((GET_MODE (x) == HImode || GET_MODE (x) == SImode)
+      if ((mode == HImode || mode == SImode)
 	  && GET_CODE (XEXP (x, 0)) == LSHIFTRT
-	  && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (GET_MODE (x))
+	  && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (mode)
 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
 	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-	  && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (GET_MODE (x)))
+	  && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode))
 	{
 	  rtx mul = XEXP (XEXP (x, 0), 0);
 	  rtx op0 = XEXP (mul, 0);
@@ -6097,15 +6098,16 @@ static bool
 
 	  if ((code0 == code1
 	       && (code0 == SIGN_EXTEND || code0 == ZERO_EXTEND))
-	      || (GET_MODE (x) == HImode
+	      || (mode == HImode
 		  && code0 == ZERO_EXTEND && code1 == SIGN_EXTEND))
 	    {
-	      if (GET_MODE (x) == HImode)
+	      if (mode == HImode)
 		*total = COSTS_N_INSNS (2);
 	      else
 		*total = COSTS_N_INSNS (12);
-	      *total += rtx_cost (XEXP (op0, 0), code0, 0, speed);
-	      *total += rtx_cost (XEXP (op1, 0), code1, 0, speed);
+	      mode = GET_MODE (XEXP (op0, 0));
+	      *total += rtx_cost (XEXP (op0, 0), mode, code0, 0, speed);
+	      *total += rtx_cost (XEXP (op1, 0), mode, code1, 0, speed);
 	      return true;
 	    }
 	}
@@ -6114,7 +6116,7 @@ static bool
     case ASHIFT:
     case ASHIFTRT:
     case LSHIFTRT:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	*total = COSTS_N_INSNS (CONSTANT_P (XEXP (x, 1)) ? 4 : 15);
       else
 	*total = COSTS_N_INSNS (1);
@@ -6125,8 +6127,8 @@ static bool
       *total = COSTS_N_INSNS (1);
       op0 = code == PLUS ? XEXP (x, 0) : XEXP (x, 1);
       op1 = code == PLUS ? XEXP (x, 1) : XEXP (x, 0);
-      if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
-	  && INTEGRAL_MODE_P (GET_MODE (x))
+      if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+	  && INTEGRAL_MODE_P (mode)
 	  && GET_CODE (op0) == MULT
 	  && GET_CODE (XEXP (op0, 1)) == CONST_INT
 	  && (INTVAL (XEXP (op0, 1)) == 2
@@ -6133,8 +6135,8 @@ static bool
 	      || INTVAL (XEXP (op0, 1)) == 4
 	      || (code == PLUS && INTVAL (XEXP (op0, 1)) == 8)))
 	{
-	  *total += rtx_cost (XEXP (op0, 0), ASHIFT, 0, speed);
-	  *total += rtx_cost (op1, (enum rtx_code) code, 1, speed);
+	  *total += rtx_cost (XEXP (op0, 0), mode, ASHIFT, 0, speed);
+	  *total += rtx_cost (op1, mode, (enum rtx_code) code, 1, speed);
 	  return true;
 	}
       return false;
@@ -6142,7 +6144,7 @@ static bool
     case MULT:
       op0 = XEXP (x, 0);
       op1 = XEXP (x, 1);
-      if (GET_MODE (x) == DFmode)
+      if (mode == DFmode)
 	{
 	  if (TARGET_FP)
 	    *total = COSTS_N_INSNS (speed ? 10 : 1);
@@ -6149,7 +6151,7 @@ static bool
 	  else
 	    *total = COSTS_N_INSNS (speed ? 200 : 4);
 	}
-      else if (GET_MODE (x) == SFmode)
+      else if (mode == SFmode)
 	{
 	  if (TARGET_FP)
 	    *total = COSTS_N_INSNS (speed ? 4 : 1);
@@ -6156,7 +6158,7 @@ static bool
 	  else
 	    *total = COSTS_N_INSNS (speed ? 100 : 4);
 	}
-      else if (GET_MODE (x) == DImode)
+      else if (mode == DImode)
 	{
 	  if (TARGET_MPY32
 	      && GET_CODE (op0) == GET_CODE (op1)
@@ -6171,7 +6173,7 @@ static bool
 	    /* Maybe improve this laster.  */
 	    *total = COSTS_N_INSNS (20);
 	}
-      else if (GET_MODE (x) == SImode)
+      else if (mode == SImode)
 	{
 	  if (((GET_CODE (op0) == ZERO_EXTEND
 		|| GET_CODE (op0) == SIGN_EXTEND
@@ -6199,15 +6201,15 @@ static bool
 	  else
 	    *total = COSTS_N_INSNS (6);
 	}
-      else if (GET_MODE (x) == HImode)
+      else if (mode == HImode)
 	*total = COSTS_N_INSNS (speed ? 2 : 1);
 
       if (GET_CODE (op0) != REG
 	  && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	*total += rtx_cost (op0, MULT, 0, speed);
+	*total += rtx_cost (op0, mode, MULT, 0, speed);
       if (op1 && GET_CODE (op1) != REG
 	  && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
-	*total += rtx_cost (op1, MULT, 1, speed);
+	*total += rtx_cost (op1, mode, MULT, 1, speed);
       return true;
 
     case UDIV:
@@ -6225,7 +6227,7 @@ static bool
 	  && XEXP (op0, 1) == const0_rtx
 	  && rtx_equal_p (XEXP (x, 1), XEXP (op0, 0)))
 	{
-	  *total = rtx_cost (XEXP (x, 1), (enum rtx_code) outer_code,
+	  *total = rtx_cost (XEXP (x, 1), VOIDmode, (enum rtx_code) outer_code,
 			     opno, speed);
 	  return false;
 	}
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	(revision 224310)
+++ gcc/config/cris/cris.c	(working copy)
@@ -155,7 +155,7 @@ static reg_class_t cris_preferred_reload_class (rt
 
 static int cris_register_move_cost (machine_mode, reg_class_t, reg_class_t);
 static int cris_memory_move_cost (machine_mode, reg_class_t, bool);
-static bool cris_rtx_costs (rtx, int, int, int, int *, bool);
+static bool cris_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int cris_address_cost (rtx, machine_mode, addr_space_t, bool);
 static bool cris_pass_by_reference (cumulative_args_t, machine_mode,
 				    const_tree, bool);
@@ -2106,9 +2106,11 @@ cris_expand_return (bool on_stack)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-cris_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
-		bool speed)
+cris_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+		int *total, bool speed)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -2138,7 +2140,7 @@ static bool
       return true;
 
     case CONST_DOUBLE:
-      if (x != CONST0_RTX (GET_MODE (x) == VOIDmode ? DImode : GET_MODE (x)))
+      if (x != CONST0_RTX (mode == VOIDmode ? DImode : mode))
 	*total = 12;
       else
         /* Make 0.0 cheap, else test-insns will not be used.  */
@@ -2200,9 +2202,9 @@ static bool
 	  && !satisfies_constraint_I (XEXP (x, 1)))
 	{
 	  *total
-	    = (rtx_cost (XEXP (x, 0), (enum rtx_code) outer_code,
+	    = (rtx_cost (XEXP (x, 0), mode, (enum rtx_code) outer_code,
 			 opno, speed) + 2
-	       + 2 * GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))));
+	       + 2 * GET_MODE_NUNITS (mode));
 	  return true;
 	}
       return false;
@@ -2213,7 +2215,8 @@ static bool
       /* fall through */
 
     case ZERO_EXTEND: case SIGN_EXTEND:
-      *total = rtx_cost (XEXP (x, 0), (enum rtx_code) outer_code, opno, speed);
+      *total = rtx_cost (XEXP (x, 0), VOIDmode, (enum rtx_code) outer_code,
+			 opno, speed);
       return true;
 
     default:
Index: gcc/config/epiphany/epiphany.c
===================================================================
--- gcc/config/epiphany/epiphany.c	(revision 224310)
+++ gcc/config/epiphany/epiphany.c	(working copy)
@@ -773,9 +773,12 @@ epiphany_arg_partial_bytes (cumulative_args_t cum,
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-epiphany_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+epiphany_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		    int opno ATTRIBUTE_UNUSED,
 		    int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       /* Small integers in the right context are as cheap as registers.  */
@@ -816,7 +819,7 @@ static bool
       return true;
 
     case COMPARE:
-      switch (GET_MODE (x))
+      switch (mode)
 	{
 	/* There are a number of single-insn combiner patterns that use
 	   the flag side effects of arithmetic.  */
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	(revision 224310)
+++ gcc/config/frv/frv.c	(working copy)
@@ -384,8 +384,8 @@ static void frv_setup_incoming_varargs		(cumulativ
 						 tree, int *, int);
 static rtx frv_expand_builtin_saveregs		(void);
 static void frv_expand_builtin_va_start		(tree, rtx);
-static bool frv_rtx_costs			(rtx, int, int, int, int*,
-						 bool);
+static bool frv_rtx_costs			(rtx, machine_mode, int, int,
+						 int*, bool);
 static int frv_register_move_cost		(machine_mode,
 						 reg_class_t, reg_class_t);
 static int frv_memory_move_cost			(machine_mode,
@@ -9456,12 +9456,14 @@ frv_in_small_data_p (const_tree decl)
 \f
 static bool
 frv_rtx_costs (rtx x,
-               int code ATTRIBUTE_UNUSED,
-               int outer_code ATTRIBUTE_UNUSED,
+               machine_mode mode,
+               int outer_code,
 	       int opno ATTRIBUTE_UNUSED,
                int *total,
 	       bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   if (outer_code == MEM)
     {
       /* Don't differentiate between memory addresses.  All the ones
@@ -9499,9 +9501,9 @@ frv_rtx_costs (rtx x,
     case NOT:
     case NEG:
     case COMPARE:
-      if (GET_MODE (x) == SImode)
+      if (mode == SImode)
 	*total = COSTS_N_INSNS (1);
-      else if (GET_MODE (x) == DImode)
+      else if (mode == DImode)
         *total = COSTS_N_INSNS (2);
       else
         *total = COSTS_N_INSNS (3);
@@ -9508,7 +9510,7 @@ frv_rtx_costs (rtx x,
       return true;
 
     case MULT:
-      if (GET_MODE (x) == SImode)
+      if (mode == SImode)
         *total = COSTS_N_INSNS (2);
       else
         *total = COSTS_N_INSNS (6);	/* guess */
Index: gcc/config/h8300/h8300.c
===================================================================
--- gcc/config/h8300/h8300.c	(revision 224310)
+++ gcc/config/h8300/h8300.c	(working copy)
@@ -1240,9 +1240,11 @@ h8300_shift_costs (rtx x)
 /* Worker function for TARGET_RTX_COSTS.  */
 
 static bool
-h8300_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-		 int *total, bool speed)
+h8300_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
+		 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
+  int code = GET_CODE (x);
+
   if (TARGET_H8300SX && outer_code == MEM)
     {
       /* Estimate the number of execution states needed to calculate
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 224310)
+++ gcc/config/i386/i386.c	(working copy)
@@ -42000,13 +42000,12 @@ ix86_set_reg_reg_cost (machine_mode mode)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
-		bool speed)
+ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
+		int *total, bool speed)
 {
   rtx mask;
-  enum rtx_code code = (enum rtx_code) code_i;
+  enum rtx_code code = GET_CODE (x);
   enum rtx_code outer_code = (enum rtx_code) outer_code_i;
-  machine_mode mode = GET_MODE (x);
   const struct processor_costs *cost = speed ? ix86_cost : &ix86_size_cost;
 
   switch (code)
@@ -42137,7 +42136,7 @@ static bool
 		  if (CONSTANT_P (XEXP (x, 1)))
 		    {
 		      *total = (cost->fabs
-				+ rtx_cost (XEXP (x, 0), code, 0, speed)
+				+ rtx_cost (XEXP (x, 0), mode, code, 0, speed)
 				+ (speed ? 2 : COSTS_N_BYTES (16)));
 		      return true;
 		    }
@@ -42193,18 +42192,18 @@ static bool
         /* ??? SSE scalar/vector cost should be used here.  */
         /* ??? Bald assumption that fma has the same cost as fmul.  */
         *total = cost->fmul;
-	*total += rtx_cost (XEXP (x, 1), FMA, 1, speed);
+	*total += rtx_cost (XEXP (x, 1), mode, FMA, 1, speed);
 
         /* Negate in op0 or op2 is free: FMS, FNMA, FNMS.  */
 	sub = XEXP (x, 0);
 	if (GET_CODE (sub) == NEG)
 	  sub = XEXP (sub, 0);
-	*total += rtx_cost (sub, FMA, 0, speed);
+	*total += rtx_cost (sub, mode, FMA, 0, speed);
 
 	sub = XEXP (x, 2);
 	if (GET_CODE (sub) == NEG)
 	  sub = XEXP (sub, 0);
-	*total += rtx_cost (sub, FMA, 2, speed);
+	*total += rtx_cost (sub, mode, FMA, 2, speed);
 	return true;
       }
 
@@ -42294,8 +42293,8 @@ static bool
 
   	  *total = (cost->mult_init[MODE_INDEX (mode)]
 		    + nbits * cost->mult_bit
-	            + rtx_cost (op0, outer_code, opno, speed)
-		    + rtx_cost (op1, outer_code, opno, speed));
+	            + rtx_cost (op0, mode, outer_code, opno, speed)
+		    + rtx_cost (op1, mode, outer_code, opno, speed));
 
           return true;
 	}
@@ -42329,11 +42328,12 @@ static bool
 	      if (val == 2 || val == 4 || val == 8)
 		{
 		  *total = cost->lea;
-		  *total += rtx_cost (XEXP (XEXP (x, 0), 1),
+		  *total += rtx_cost (XEXP (XEXP (x, 0), 1), mode,
 				      outer_code, opno, speed);
-		  *total += rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0),
+		  *total += rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0), mode,
 				      outer_code, opno, speed);
-		  *total += rtx_cost (XEXP (x, 1), outer_code, opno, speed);
+		  *total += rtx_cost (XEXP (x, 1), mode,
+				      outer_code, opno, speed);
 		  return true;
 		}
 	    }
@@ -42344,9 +42344,10 @@ static bool
 	      if (val == 2 || val == 4 || val == 8)
 		{
 		  *total = cost->lea;
-		  *total += rtx_cost (XEXP (XEXP (x, 0), 0),
+		  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode,
 				      outer_code, opno, speed);
-		  *total += rtx_cost (XEXP (x, 1), outer_code, opno, speed);
+		  *total += rtx_cost (XEXP (x, 1), mode,
+				      outer_code, opno, speed);
 		  return true;
 		}
 	    }
@@ -42353,11 +42354,12 @@ static bool
 	  else if (GET_CODE (XEXP (x, 0)) == PLUS)
 	    {
 	      *total = cost->lea;
-	      *total += rtx_cost (XEXP (XEXP (x, 0), 0),
+	      *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode,
 				  outer_code, opno, speed);
-	      *total += rtx_cost (XEXP (XEXP (x, 0), 1),
+	      *total += rtx_cost (XEXP (XEXP (x, 0), 1), mode,
 				  outer_code, opno, speed);
-	      *total += rtx_cost (XEXP (x, 1), outer_code, opno, speed);
+	      *total += rtx_cost (XEXP (x, 1), mode,
+				  outer_code, opno, speed);
 	      return true;
 	    }
 	}
@@ -42390,9 +42392,9 @@ static bool
 	  && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
 	{
 	  *total = (cost->add * 2
-		    + (rtx_cost (XEXP (x, 0), outer_code, opno, speed)
+		    + (rtx_cost (XEXP (x, 0), mode, outer_code, opno, speed)
 		       << (GET_MODE (XEXP (x, 0)) != DImode))
-		    + (rtx_cost (XEXP (x, 1), outer_code, opno, speed)
+		    + (rtx_cost (XEXP (x, 1), mode, outer_code, opno, speed)
 	               << (GET_MODE (XEXP (x, 1)) != DImode)));
 	  return true;
 	}
@@ -42440,9 +42442,11 @@ static bool
 	{
 	  /* This kind of construct is implemented using test[bwl].
 	     Treat it as if we had an AND.  */
+	  mode = GET_MODE (XEXP (XEXP (x, 0), 0));
 	  *total = (cost->add
-		    + rtx_cost (XEXP (XEXP (x, 0), 0), outer_code, opno, speed)
-		    + rtx_cost (const1_rtx, outer_code, opno, speed));
+		    + rtx_cost (XEXP (XEXP (x, 0), 0), mode, outer_code,
+				opno, speed)
+		    + rtx_cost (const1_rtx, mode, outer_code, opno, speed));
 	  return true;
 	}
       return false;
@@ -42492,7 +42496,7 @@ static bool
       /* This is masked instruction, assume the same cost,
 	 as nonmasked variant.  */
       if (TARGET_AVX512F && register_operand (mask, GET_MODE (mask)))
-	*total = rtx_cost (XEXP (x, 0), outer_code, opno, speed);
+	*total = rtx_cost (XEXP (x, 0), mode, outer_code, opno, speed);
       else
 	*total = cost->fabs;
       return true;
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(revision 224310)
+++ gcc/config/ia64/ia64.c	(working copy)
@@ -242,7 +242,7 @@ static int ia64_register_move_cost (machine_mode,
                                     reg_class_t);
 static int ia64_memory_move_cost (machine_mode mode, reg_class_t,
 				  bool);
-static bool ia64_rtx_costs (rtx, int, int, int, int *, bool);
+static bool ia64_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int ia64_unspec_may_trap_p (const_rtx, unsigned);
 static void fix_range (const char *);
 static struct machine_function * ia64_init_machine_status (void);
@@ -5599,9 +5599,12 @@ ia64_print_operand_punct_valid_p (unsigned char co
 /* ??? This is incomplete.  */
 
 static bool
-ia64_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+ia64_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED,
 		int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -5645,9 +5648,9 @@ static bool
          which normally involves copies.  Plus there's the latency
          of the multiply itself, and the latency of the instructions to
          transfer integer regs to FP regs.  */
-      if (FLOAT_MODE_P (GET_MODE (x)))
+      if (FLOAT_MODE_P (mode))
 	*total = COSTS_N_INSNS (4);
-      else if (GET_MODE_SIZE (GET_MODE (x)) > 2)
+      else if (GET_MODE_SIZE (mode) > 2)
         *total = COSTS_N_INSNS (10);
       else
 	*total = COSTS_N_INSNS (2);
@@ -5655,7 +5658,7 @@ static bool
 
     case PLUS:
     case MINUS:
-      if (FLOAT_MODE_P (GET_MODE (x)))
+      if (FLOAT_MODE_P (mode))
 	{
 	  *total = COSTS_N_INSNS (4);
 	  return true;
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	(revision 224310)
+++ gcc/config/iq2000/iq2000.c	(working copy)
@@ -172,7 +172,7 @@ static bool iq2000_return_in_memory   (const_tree,
 static void iq2000_setup_incoming_varargs (cumulative_args_t,
 					   machine_mode, tree, int *,
 					   int);
-static bool iq2000_rtx_costs          (rtx, int, int, int, int *, bool);
+static bool iq2000_rtx_costs          (rtx, machine_mode, int, int, int *, bool);
 static int  iq2000_address_cost       (rtx, machine_mode, addr_space_t,
 				       bool);
 static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT);
@@ -3309,11 +3309,11 @@ iq2000_legitimize_address (rtx xinsn, rtx old_x AT
 
 
 static bool
-iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+iq2000_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 		  int opno ATTRIBUTE_UNUSED, int * total,
 		  bool speed ATTRIBUTE_UNUSED)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
 
   switch (code)
     {
Index: gcc/config/lm32/lm32.c
===================================================================
--- gcc/config/lm32/lm32.c	(revision 224310)
+++ gcc/config/lm32/lm32.c	(working copy)
@@ -87,7 +87,7 @@ static bool lm32_in_small_data_p (const_tree);
 static void lm32_setup_incoming_varargs (cumulative_args_t cum,
 					 machine_mode mode, tree type,
 					 int *pretend_size, int no_rtl);
-static bool lm32_rtx_costs (rtx x, int code, int outer_code, int opno,
+static bool lm32_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
 			    int *total, bool speed);
 static bool lm32_can_eliminate (const int, const int);
 static bool
@@ -940,10 +940,10 @@ nonpic_symbol_mentioned_p (rtx x)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-lm32_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-		int *total, bool speed)
+lm32_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   bool small_mode;
 
   const int arithmetic_latency = 1;
Index: gcc/config/m32c/m32c.c
===================================================================
--- gcc/config/m32c/m32c.c	(revision 224310)
+++ gcc/config/m32c/m32c.c	(working copy)
@@ -2231,9 +2231,11 @@ m32c_memory_move_cost (machine_mode mode ATTRIBUTE
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS m32c_rtx_costs
 static bool
-m32c_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+m32c_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED,
 		int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
   switch (code)
     {
     case REG:
@@ -2301,7 +2303,7 @@ static bool
 
     default:
       /* Reasonable default.  */
-      if (TARGET_A16 && GET_MODE(x) == SImode)
+      if (TARGET_A16 && mode == SImode)
 	*total += COSTS_N_INSNS (2);
       break;
     }
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c	(revision 224310)
+++ gcc/config/m32r/m32r.c	(working copy)
@@ -104,7 +104,7 @@ static bool m32r_function_value_regno_p (const uns
 static void m32r_setup_incoming_varargs (cumulative_args_t, machine_mode,
 					 tree, int *, int);
 static void init_idents (void);
-static bool m32r_rtx_costs (rtx, int, int, int, int *, bool speed);
+static bool m32r_rtx_costs (rtx, machine_mode, int, int, int *, bool speed);
 static int m32r_memory_move_cost (machine_mode, reg_class_t, bool);
 static bool m32r_pass_by_reference (cumulative_args_t, machine_mode,
 				    const_tree, bool);
@@ -1367,10 +1367,13 @@ m32r_memory_move_cost (machine_mode mode,
 }
 
 static bool
-m32r_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+m32r_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+		int outer_code ATTRIBUTE_UNUSED,
 		int opno ATTRIBUTE_UNUSED, int *total,
 		bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       /* Small integers are as cheap as registers.  4 byte values can be
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c	(revision 224310)
+++ gcc/config/m68k/m68k.c	(working copy)
@@ -171,7 +171,7 @@ static bool m68k_save_reg (unsigned int regno, boo
 static bool m68k_ok_for_sibcall_p (tree, tree);
 static bool m68k_tls_symbol_p (rtx);
 static rtx m68k_legitimize_address (rtx, rtx, machine_mode);
-static bool m68k_rtx_costs (rtx, int, int, int, int *, bool);
+static bool m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 #if M68K_HONOR_TARGET_STRICT_ALIGNMENT
 static bool m68k_return_in_memory (const_tree, const_tree);
 #endif
@@ -2793,9 +2793,12 @@ const_int_cost (HOST_WIDE_INT i)
 }
 
 static bool
-m68k_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+m68k_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED,
 		int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -2852,7 +2855,7 @@ static bool
 
     case PLUS:
       /* An lea costs about three times as much as a simple add.  */
-      if (GET_MODE (x) == SImode
+      if (mode == SImode
 	  && GET_CODE (XEXP (x, 1)) == REG
 	  && GET_CODE (XEXP (x, 0)) == MULT
 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
@@ -2908,9 +2911,9 @@ static bool
     case MULT:
       if ((GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
 	   || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
-	  && GET_MODE (x) == SImode)
+	  && mode == SImode)
         *total = COSTS_N_INSNS (MULW_COST);
-      else if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
+      else if (mode == QImode || mode == HImode)
         *total = COSTS_N_INSNS (MULW_COST);
       else
         *total = COSTS_N_INSNS (MULL_COST);
@@ -2920,7 +2923,7 @@ static bool
     case UDIV:
     case MOD:
     case UMOD:
-      if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
+      if (mode == QImode || mode == HImode)
         *total = COSTS_N_INSNS (DIVW_COST);	/* div.w */
       else if (TARGET_CF_HWDIV)
         *total = COSTS_N_INSNS (18);
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c	(revision 224310)
+++ gcc/config/mcore/mcore.c	(working copy)
@@ -142,7 +142,7 @@ static const char *mcore_strip_name_encoding	(cons
 static int        mcore_const_costs             (rtx, RTX_CODE);
 static int        mcore_and_cost                (rtx);
 static int        mcore_ior_cost                (rtx);
-static bool       mcore_rtx_costs		(rtx, int, int, int,
+static bool       mcore_rtx_costs		(rtx, machine_mode, int, int,
 						 int *, bool);
 static void       mcore_external_libcall	(rtx);
 static bool       mcore_return_in_memory	(const_tree, const_tree);
@@ -534,9 +534,12 @@ mcore_ior_cost (rtx x)
 }
 
 static bool
-mcore_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+mcore_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
+		 int opno ATTRIBUTE_UNUSED,
 		 int * total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
Index: gcc/config/mep/mep.c
===================================================================
--- gcc/config/mep/mep.c	(revision 224310)
+++ gcc/config/mep/mep.c	(working copy)
@@ -240,7 +240,7 @@ static void mep_move_ready_insn (rtx_insn **, int,
 static int mep_sched_reorder (FILE *, int, rtx_insn **, int *, int);
 static rtx_insn *mep_make_bundle (rtx, rtx_insn *);
 static void mep_bundle_insns (rtx_insn *);
-static bool mep_rtx_cost (rtx, int, int, int, int *, bool);
+static bool mep_rtx_cost (rtx, machine_mode, int, int, int *, bool);
 static int mep_address_cost (rtx, machine_mode, addr_space_t, bool);
 static void mep_setup_incoming_varargs (cumulative_args_t, machine_mode,
 					tree, int *, int);
@@ -7130,10 +7130,13 @@ mep_expand_binary_intrinsic (int ATTRIBUTE_UNUSED
 }
 
 static bool
-mep_rtx_cost (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+mep_rtx_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+	      int outer_code ATTRIBUTE_UNUSED,
 	      int opno ATTRIBUTE_UNUSED, int *total,
 	      bool ATTRIBUTE_UNUSED speed_t)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
Index: gcc/config/microblaze/microblaze.c
===================================================================
--- gcc/config/microblaze/microblaze.c	(revision 224310)
+++ gcc/config/microblaze/microblaze.c	(working copy)
@@ -1240,11 +1240,11 @@ microblaze_expand_block_move (rtx dest, rtx src, r
 }
 
 static bool
-microblaze_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+microblaze_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 		      int opno ATTRIBUTE_UNUSED, int *total,
 		      bool speed ATTRIBUTE_UNUSED)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
 
   switch (code)
     {
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	(revision 224310)
+++ gcc/config/mips/mips.c	(working copy)
@@ -2438,7 +2438,7 @@ mips_legitimate_address_p (machine_mode mode, rtx
   return mips_classify_address (&addr, x, mode, strict_p);
 }
 
-/* Return true if X is a legitimate $sp-based address for mode MDOE.  */
+/* Return true if X is a legitimate $sp-based address for mode MODE.  */
 
 bool
 mips_stack_address_p (rtx x, machine_mode mode)
@@ -3731,8 +3731,8 @@ mips_binary_cost (rtx x, int single_cost, int doub
   else
     cost = single_cost;
   return (cost
-	  + set_src_cost (XEXP (x, 0), speed)
-	  + rtx_cost (XEXP (x, 1), GET_CODE (x), 1, speed));
+	  + set_src_cost (XEXP (x, 0), GET_MODE (x), speed)
+	  + rtx_cost (XEXP (x, 1), GET_MODE (x), GET_CODE (x), 1, speed));
 }
 
 /* Return the cost of floating-point multiplications of mode MODE.  */
@@ -3833,10 +3833,10 @@ mips_set_reg_reg_cost (machine_mode mode)
 /* Implement TARGET_RTX_COSTS.  */
 
 static bool
-mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-		int *total, bool speed)
+mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   bool float_mode_p = FLOAT_MODE_P (mode);
   int cost;
   rtx addr;
@@ -3935,7 +3935,7 @@ static bool
 	     for a word or doubleword operation, so we cannot rely on
 	     the result of mips_build_integer.  */
 	  else if (!TARGET_MIPS16
-		   && (outer_code == SET || mode == VOIDmode))
+		   && (outer_code == SET || GET_MODE (x) == VOIDmode))
 	    cost = 1;
 	  *total = COSTS_N_INSNS (cost);
 	  return true;
@@ -3981,7 +3981,7 @@ static bool
 	  && UINTVAL (XEXP (x, 1)) == 0xffffffff)
 	{
 	  *total = (mips_zero_extend_cost (mode, XEXP (x, 0))
-		    + set_src_cost (XEXP (x, 0), speed));
+		    + set_src_cost (XEXP (x, 0), mode, speed));
 	  return true;
 	}
       if (ISA_HAS_CINS && CONST_INT_P (XEXP (x, 1)))
@@ -3991,7 +3991,8 @@ static bool
 	      && CONST_INT_P (XEXP (op, 1))
 	      && mask_low_and_shift_p (mode, XEXP (x, 1), XEXP (op, 1), 32))
 	    {
-	      *total = COSTS_N_INSNS (1) + set_src_cost (XEXP (op, 0), speed);
+	      *total = COSTS_N_INSNS (1);
+	      *total += set_src_cost (XEXP (op, 0), mode, speed);
 	      return true;
 	    }
 	}
@@ -4003,8 +4004,8 @@ static bool
 	{
 	  cost = GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1;
           *total = (COSTS_N_INSNS (cost)
-		    + set_src_cost (XEXP (XEXP (x, 0), 0), speed)
-		    + set_src_cost (XEXP (XEXP (x, 1), 0), speed));
+		    + set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
+		    + set_src_cost (XEXP (XEXP (x, 1), 0), mode, speed));
 	  return true;
 	}
 	    
@@ -4040,7 +4041,7 @@ static bool
     case LO_SUM:
       /* Low-part immediates need an extended MIPS16 instruction.  */
       *total = (COSTS_N_INSNS (TARGET_MIPS16 ? 2 : 1)
-		+ set_src_cost (XEXP (x, 0), speed));
+		+ set_src_cost (XEXP (x, 0), mode, speed));
       return true;
 
     case LT:
@@ -4081,17 +4082,17 @@ static bool
 	  if (GET_CODE (op0) == MULT && GET_CODE (XEXP (op0, 0)) == NEG)
 	    {
 	      *total = (mips_fp_mult_cost (mode)
-			+ set_src_cost (XEXP (XEXP (op0, 0), 0), speed)
-			+ set_src_cost (XEXP (op0, 1), speed)
-			+ set_src_cost (op1, speed));
+			+ set_src_cost (XEXP (XEXP (op0, 0), 0), mode, speed)
+			+ set_src_cost (XEXP (op0, 1), mode, speed)
+			+ set_src_cost (op1, mode, speed));
 	      return true;
 	    }
 	  if (GET_CODE (op1) == MULT)
 	    {
 	      *total = (mips_fp_mult_cost (mode)
-			+ set_src_cost (op0, speed)
-			+ set_src_cost (XEXP (op1, 0), speed)
-			+ set_src_cost (XEXP (op1, 1), speed));
+			+ set_src_cost (op0, mode, speed)
+			+ set_src_cost (XEXP (op1, 0), mode, speed)
+			+ set_src_cost (XEXP (op1, 1), mode, speed));
 	      return true;
 	    }
 	}
@@ -4121,8 +4122,8 @@ static bool
 	  if (const_immlsa_operand (op2, mode))
 	    {
 	      *total = (COSTS_N_INSNS (1)
-			+ set_src_cost (XEXP (XEXP (x, 0), 0), speed)
-			+ set_src_cost (XEXP (x, 1), speed));
+			+ set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
+			+ set_src_cost (XEXP (x, 1), mode, speed));
 	      return true;
 	    }
 	}
@@ -4149,9 +4150,9 @@ static bool
 	      && GET_CODE (XEXP (op, 0)) == MULT)
 	    {
 	      *total = (mips_fp_mult_cost (mode)
-			+ set_src_cost (XEXP (XEXP (op, 0), 0), speed)
-			+ set_src_cost (XEXP (XEXP (op, 0), 1), speed)
-			+ set_src_cost (XEXP (op, 1), speed));
+			+ set_src_cost (XEXP (XEXP (op, 0), 0), mode, speed)
+			+ set_src_cost (XEXP (XEXP (op, 0), 1), mode, speed)
+			+ set_src_cost (XEXP (op, 1), mode, speed));
 	      return true;
 	    }
 	}
@@ -4194,10 +4195,10 @@ static bool
 	  if (outer_code == SQRT || GET_CODE (XEXP (x, 1)) == SQRT)
 	    /* An rsqrt<mode>a or rsqrt<mode>b pattern.  Count the
 	       division as being free.  */
-	    *total = set_src_cost (XEXP (x, 1), speed);
+	    *total = set_src_cost (XEXP (x, 1), mode, speed);
 	  else
 	    *total = (mips_fp_div_cost (mode)
-		      + set_src_cost (XEXP (x, 1), speed));
+		      + set_src_cost (XEXP (x, 1), mode, speed));
 	  return true;
 	}
       /* Fall through.  */
@@ -4225,7 +4226,8 @@ static bool
 	      && CONST_INT_P (XEXP (x, 1))
 	      && exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
 	    {
-	      *total = COSTS_N_INSNS (2) + set_src_cost (XEXP (x, 0), speed);
+	      *total = COSTS_N_INSNS (2);
+	      *total += set_src_cost (XEXP (x, 0), mode, speed);
 	      return true;
 	    }
 	  *total = COSTS_N_INSNS (mips_idiv_insns ());
@@ -4248,7 +4250,7 @@ static bool
 	  && GET_MODE (XEXP (x, 0)) == QImode
 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS)
 	{
-	  *total = set_src_cost (XEXP (XEXP (x, 0), 0), speed);
+	  *total = set_src_cost (XEXP (XEXP (x, 0), 0), VOIDmode, speed);
 	  return true;
 	}
       *total = mips_zero_extend_cost (mode, XEXP (x, 0));
@@ -4291,9 +4293,10 @@ static bool
 	      if (ISA_HAS_R6DMUL
 		  && GET_CODE (op) == ZERO_EXTEND
 		  && GET_MODE (op) == DImode)
-		*total += rtx_cost (op, MULT, i, speed);
+		*total += rtx_cost (op, DImode, MULT, i, speed);
 	      else
-		*total += rtx_cost (XEXP (op, 0), GET_CODE (op), 0, speed);
+		*total += rtx_cost (XEXP (op, 0), VOIDmode, GET_CODE (op),
+				    0, speed);
 	    }
 
 	  return true;
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c	(revision 224310)
+++ gcc/config/mmix/mmix.c	(working copy)
@@ -155,7 +155,7 @@ static void mmix_setup_incoming_varargs
   (cumulative_args_t, machine_mode, tree, int *, int);
 static void mmix_file_start (void);
 static void mmix_file_end (void);
-static bool mmix_rtx_costs (rtx, int, int, int, int *, bool);
+static bool mmix_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int mmix_register_move_cost (machine_mode,
 				    reg_class_t, reg_class_t);
 static rtx mmix_struct_value_rtx (tree, int);
@@ -1180,7 +1180,7 @@ mmix_reversible_cc_mode (machine_mode mode)
 
 static bool
 mmix_rtx_costs (rtx x ATTRIBUTE_UNUSED,
-		int code ATTRIBUTE_UNUSED,
+		machine_mode mode ATTRIBUTE_UNUSED,
 		int outer_code ATTRIBUTE_UNUSED,
 		int opno ATTRIBUTE_UNUSED,
 		int *total ATTRIBUTE_UNUSED,
Index: gcc/config/mn10300/mn10300.c
===================================================================
--- gcc/config/mn10300/mn10300.c	(revision 224310)
+++ gcc/config/mn10300/mn10300.c	(working copy)
@@ -2233,7 +2233,7 @@ mn10300_address_cost (rtx x, machine_mode mode ATT
       return speed ? 2 : 6;
 
     default:
-      return rtx_cost (x, MEM, 0, speed);
+      return rtx_cost (x, Pmode, MEM, 0, speed);
     }
 }
 
@@ -2347,13 +2347,14 @@ mn10300_memory_move_cost (machine_mode mode ATTRIB
    to represent cycles.  Size-relative costs are in bytes.  */
 
 static bool
-mn10300_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-		   int *ptotal, bool speed)
+mn10300_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		   int opno ATTRIBUTE_UNUSED, int *ptotal, bool speed)
 {
   /* This value is used for SYMBOL_REF etc where we want to pretend
      we have a full 32-bit constant.  */
   HOST_WIDE_INT i = 0x12345678;
   int total;
+  int code = GET_CODE (x);
 
   switch (code)
     {
@@ -2439,7 +2440,7 @@ static bool
 	  i = INTVAL (XEXP (x, 1));
 	  if (i == 1 || i == 4)
 	    {
-	      total = 1 + rtx_cost (XEXP (x, 0), PLUS, 0, speed);
+	      total = 1 + rtx_cost (XEXP (x, 0), mode, PLUS, 0, speed);
 	      goto alldone;
 	    }
 	}
@@ -2495,7 +2496,7 @@ static bool
       break;
 
     case MEM:
-      total = mn10300_address_cost (XEXP (x, 0), GET_MODE (x),
+      total = mn10300_address_cost (XEXP (x, 0), mode,
 				    MEM_ADDR_SPACE (x), speed);
       if (speed)
 	total = COSTS_N_INSNS (2 + total);
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	(revision 224310)
+++ gcc/config/msp430/msp430.c	(working copy)
@@ -1010,17 +1010,19 @@ msp430_legitimate_constant (machine_mode mode, rtx
 #undef  TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS msp430_rtx_costs
 
-static bool msp430_rtx_costs (rtx   x ATTRIBUTE_UNUSED,
-			      int   code,
-			      int   outer_code ATTRIBUTE_UNUSED,
-			      int   opno ATTRIBUTE_UNUSED,
-			      int * total,
-			      bool  speed ATTRIBUTE_UNUSED)
+static bool msp430_rtx_costs (rtx	   x ATTRIBUTE_UNUSED,
+			      machine_mode mode,
+			      int	   outer_code ATTRIBUTE_UNUSED,
+			      int	   opno ATTRIBUTE_UNUSED,
+			      int *	   total,
+			      bool	   speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case SIGN_EXTEND:
-      if (GET_MODE (x) == SImode && outer_code == SET)
+      if (mode == SImode && outer_code == SET)
 	{
 	  *total = COSTS_N_INSNS (4);
 	  return true;
Index: gcc/config/nds32/nds32-cost.c
===================================================================
--- gcc/config/nds32/nds32-cost.c	(revision 224310)
+++ gcc/config/nds32/nds32-cost.c	(working copy)
@@ -73,12 +73,14 @@
 
 bool
 nds32_rtx_costs_impl (rtx x,
-		      int code,
+		      machine_mode mode ATTRIBUTE_UNUSED,
 		      int outer_code,
 		      int opno ATTRIBUTE_UNUSED,
 		      int *total,
 		      bool speed)
 {
+  int code = GET_CODE (x);
+
   /* According to 'speed', goto suitable cost model section.  */
   if (speed)
     goto performance_cost;
Index: gcc/config/nds32/nds32-protos.h
===================================================================
--- gcc/config/nds32/nds32-protos.h	(revision 224310)
+++ gcc/config/nds32/nds32-protos.h	(working copy)
@@ -144,7 +144,7 @@ extern bool nds32_isr_function_p (tree);
 
 /* Auxiliary functions for cost calculation.  */
 
-extern bool nds32_rtx_costs_impl (rtx, int, int, int, int *, bool);
+extern bool nds32_rtx_costs_impl (rtx, machine_mode, int, int, int *, bool);
 extern int nds32_address_cost_impl (rtx, machine_mode, addr_space_t, bool);
 
 /* ------------------------------------------------------------------------ */
Index: gcc/config/nds32/nds32.c
===================================================================
--- gcc/config/nds32/nds32.c	(revision 224310)
+++ gcc/config/nds32/nds32.c	(working copy)
@@ -2106,13 +2106,13 @@ nds32_memory_move_cost (machine_mode mode ATTRIBUT
    Refer to gcc/rtlanal.c for more information.  */
 static bool
 nds32_rtx_costs (rtx x,
-		 int code,
+		 machine_mode mode,
 		 int outer_code,
 		 int opno,
 		 int *total,
 		 bool speed)
 {
-  return nds32_rtx_costs_impl (x, code, outer_code, opno, total, speed);
+  return nds32_rtx_costs_impl (x, mode, outer_code, opno, total, speed);
 }
 
 static int
Index: gcc/config/nios2/nios2.c
===================================================================
--- gcc/config/nios2/nios2.c	(revision 224310)
+++ gcc/config/nios2/nios2.c	(working copy)
@@ -1097,10 +1097,13 @@ nios2_simple_const_p (const_rtx cst)
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.  */
 static bool
-nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+nios2_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+		 int outer_code ATTRIBUTE_UNUSED,
 		 int opno ATTRIBUTE_UNUSED,
 		 int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       case CONST_INT:
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	(revision 224310)
+++ gcc/config/pa/pa.c	(working copy)
@@ -112,7 +112,7 @@ static void fix_range (const char *);
 static int hppa_register_move_cost (machine_mode mode, reg_class_t,
 				    reg_class_t);
 static int hppa_address_cost (rtx, machine_mode mode, addr_space_t, bool);
-static bool hppa_rtx_costs (rtx, int, int, int, int *, bool);
+static bool hppa_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static inline rtx force_mode (machine_mode, rtx);
 static void pa_reorg (void);
 static void pa_combine_instructions (void);
@@ -1486,10 +1486,12 @@ hppa_address_cost (rtx X, machine_mode mode ATTRIB
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-hppa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+hppa_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED,
 		int *total, bool speed ATTRIBUTE_UNUSED)
 {
   int factor;
+  int code = GET_CODE (x);
 
   switch (code)
     {
@@ -1521,7 +1523,7 @@ static bool
       return true;
 
     case MULT:
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
 	{
 	  *total = COSTS_N_INSNS (3);
 	  return true;
@@ -1528,7 +1530,7 @@ static bool
 	}
 
       /* A mode size N times larger than SImode needs O(N*N) more insns.  */
-      factor = GET_MODE_SIZE (GET_MODE (x)) / 4;
+      factor = GET_MODE_SIZE (mode) / 4;
       if (factor == 0)
 	factor = 1;
 
@@ -1539,7 +1541,7 @@ static bool
       return true;
 
     case DIV:
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
 	{
 	  *total = COSTS_N_INSNS (14);
 	  return true;
@@ -1550,7 +1552,7 @@ static bool
     case MOD:
     case UMOD:
       /* A mode size N times larger than SImode needs O(N*N) more insns.  */
-      factor = GET_MODE_SIZE (GET_MODE (x)) / 4;
+      factor = GET_MODE_SIZE (mode) / 4;
       if (factor == 0)
 	factor = 1;
 
@@ -1559,7 +1561,7 @@ static bool
 
     case PLUS: /* this includes shNadd insns */
     case MINUS:
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
 	{
 	  *total = COSTS_N_INSNS (3);
 	  return true;
@@ -1567,7 +1569,7 @@ static bool
 
       /* A size N times larger than UNITS_PER_WORD needs N times as
 	 many insns, taking N times as long.  */
-      factor = GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD;
+      factor = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
       if (factor == 0)
 	factor = 1;
       *total = factor * COSTS_N_INSNS (1);
Index: gcc/config/pdp11/pdp11.c
===================================================================
--- gcc/config/pdp11/pdp11.c	(revision 224310)
+++ gcc/config/pdp11/pdp11.c	(working copy)
@@ -164,7 +164,7 @@ decode_pdp11_d (const struct real_format *fmt ATTR
 
 static const char *singlemove_string (rtx *);
 static bool pdp11_assemble_integer (rtx, unsigned int, int);
-static bool pdp11_rtx_costs (rtx, int, int, int, int *, bool);
+static bool pdp11_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static bool pdp11_return_in_memory (const_tree, const_tree);
 static rtx pdp11_function_value (const_tree, const_tree, bool);
 static rtx pdp11_libcall_value (machine_mode, const_rtx);
@@ -916,10 +916,12 @@ pdp11_register_move_cost (machine_mode mode ATTRIB
 }
 
 static bool
-pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+pdp11_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 		 int opno ATTRIBUTE_UNUSED, int *total,
 		 bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -978,9 +980,9 @@ static bool
       return false;
 
     case SIGN_EXTEND:
-      if (GET_MODE (x) == HImode)
+      if (mode == HImode)
       	*total = COSTS_N_INSNS (1);
-      else if (GET_MODE (x) == SImode)
+      else if (mode == SImode)
 	*total = COSTS_N_INSNS (6);
       else
 	*total = COSTS_N_INSNS (2);
@@ -991,7 +993,7 @@ static bool
     case ASHIFTRT:
       if (optimize_size)
         *total = COSTS_N_INSNS (1);
-      else if (GET_MODE (x) ==  QImode)
+      else if (mode ==  QImode)
         {
           if (GET_CODE (XEXP (x, 1)) != CONST_INT)
    	    *total = COSTS_N_INSNS (8); /* worst case */
@@ -998,7 +1000,7 @@ static bool
           else
 	    *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
         }
-      else if (GET_MODE (x) == HImode)
+      else if (mode == HImode)
         {
           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
             {
@@ -1010,7 +1012,7 @@ static bool
           else
             *total = COSTS_N_INSNS (10); /* worst case */
         }
-      else if (GET_MODE (x) == SImode)
+      else if (mode == SImode)
         {
           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
 	    *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
Index: gcc/config/rl78/rl78.c
===================================================================
--- gcc/config/rl78/rl78.c	(revision 224310)
+++ gcc/config/rl78/rl78.c	(working copy)
@@ -4159,13 +4159,15 @@ rl78_return_in_memory (const_tree type, const_tree
 #define TARGET_RTX_COSTS rl78_rtx_costs
 
 static bool
-rl78_rtx_costs (rtx   x,
-		int   code,
-		int   outer_code ATTRIBUTE_UNUSED,
-		int   opno ATTRIBUTE_UNUSED,
-		int * total,
-		bool  speed ATTRIBUTE_UNUSED)
+rl78_rtx_costs (rtx          x,
+		machine_mode mode,
+		int          outer_code ATTRIBUTE_UNUSED,
+		int          opno ATTRIBUTE_UNUSED,
+		int *        total,
+		bool         speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   if (code == IF_THEN_ELSE)
     {
       *total = COSTS_N_INSNS (10);
@@ -4172,7 +4174,7 @@ static bool
       return true;
     }
 
-  if (GET_MODE (x) == SImode)
+  if (mode == SImode)
     {
       switch (code)
 	{
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 224310)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1118,7 +1118,7 @@ static tree rs6000_handle_struct_attribute (tree *
 static tree rs6000_builtin_vectorized_libmass (tree, tree, tree);
 static void rs6000_emit_set_long_const (rtx, HOST_WIDE_INT);
 static int rs6000_memory_move_cost (machine_mode, reg_class_t, bool);
-static bool rs6000_debug_rtx_costs (rtx, int, int, int, int *, bool);
+static bool rs6000_debug_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int rs6000_debug_address_cost (rtx, machine_mode, addr_space_t,
 				      bool);
 static int rs6000_debug_adjust_cost (rtx_insn *, rtx, rtx_insn *, int);
@@ -30645,10 +30645,10 @@ rs6000_xcoff_encode_section_info (tree decl, rtx r
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-rs6000_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-		  int *total, bool speed)
+rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		  int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
 
   switch (code)
     {
@@ -30969,16 +30969,16 @@ static bool
 /* Debug form of r6000_rtx_costs that is selected if -mdebug=cost.  */
 
 static bool
-rs6000_debug_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
-			bool speed)
+rs6000_debug_rtx_costs (rtx x, machine_mode mode, int outer_code,
+			int opno, int *total, bool speed)
 {
-  bool ret = rs6000_rtx_costs (x, code, outer_code, opno, total, speed);
+  bool ret = rs6000_rtx_costs (x, mode, outer_code, opno, total, speed);
 
   fprintf (stderr,
-	   "\nrs6000_rtx_costs, return = %s, code = %s, outer_code = %s, "
+	   "\nrs6000_rtx_costs, return = %s, mode = %s, outer_code = %s, "
 	   "opno = %d, total = %d, speed = %s, x:\n",
 	   ret ? "complete" : "scan inner",
-	   GET_RTX_NAME (code),
+	   GET_MODE_NAME (mode),
 	   GET_RTX_NAME (outer_code),
 	   opno,
 	   *total,
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	(revision 224310)
+++ gcc/config/s390/s390.c	(working copy)
@@ -3185,13 +3185,14 @@ s390_memory_move_cost (machine_mode mode ATTRIBUTE
 /* Compute a (partial) cost for rtx X.  Return true if the complete
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.
-   CODE contains GET_CODE (x), OUTER_CODE contains the code
-   of the superexpression of x.  */
+   OUTER_CODE contains the code of the superexpression of x.  */
 
 static bool
-s390_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+s390_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED,
 		int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
   switch (code)
     {
     case CONST:
@@ -3222,7 +3223,7 @@ static bool
       return false;
 
     case MULT:
-      switch (GET_MODE (x))
+      switch (mode)
 	{
 	case SImode:
 	  {
@@ -3281,7 +3282,7 @@ static bool
       return false;
 
     case FMA:
-      switch (GET_MODE (x))
+      switch (mode)
 	{
 	case DFmode:
 	  *total = s390_cost->madbr;
@@ -3295,9 +3296,9 @@ static bool
       /* Negate in the third argument is free: FMSUB.  */
       if (GET_CODE (XEXP (x, 2)) == NEG)
 	{
-	  *total += (rtx_cost (XEXP (x, 0), FMA, 0, speed)
-		     + rtx_cost (XEXP (x, 1), FMA, 1, speed)
-		     + rtx_cost (XEXP (XEXP (x, 2), 0), FMA, 2, speed));
+	  *total += (rtx_cost (XEXP (x, 0), mode, FMA, 0, speed)
+		     + rtx_cost (XEXP (x, 1), mode, FMA, 1, speed)
+		     + rtx_cost (XEXP (XEXP (x, 2), 0), mode, FMA, 2, speed));
 	  return true;
 	}
       return false;
@@ -3304,9 +3305,9 @@ static bool
 
     case UDIV:
     case UMOD:
-      if (GET_MODE (x) == TImode) 	       /* 128 bit division */
+      if (mode == TImode) 	       /* 128 bit division */
 	*total = s390_cost->dlgr;
-      else if (GET_MODE (x) == DImode)
+      else if (mode == DImode)
 	{
 	  rtx right = XEXP (x, 1);
 	  if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */
@@ -3314,13 +3315,13 @@ static bool
 	  else 	                               /* 64 by 64 bit division */
 	    *total = s390_cost->dlgr;
 	}
-      else if (GET_MODE (x) == SImode)         /* 32 bit division */
+      else if (mode == SImode)         /* 32 bit division */
 	*total = s390_cost->dlr;
       return false;
 
     case DIV:
     case MOD:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	{
 	  rtx right = XEXP (x, 1);
 	  if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */
@@ -3331,17 +3332,17 @@ static bool
 	  else 	                               /* 64 by 64 bit division */
 	    *total = s390_cost->dsgr;
 	}
-      else if (GET_MODE (x) == SImode)         /* 32 bit division */
+      else if (mode == SImode)         /* 32 bit division */
 	*total = s390_cost->dlr;
-      else if (GET_MODE (x) == SFmode)
+      else if (mode == SFmode)
 	{
 	  *total = s390_cost->debr;
 	}
-      else if (GET_MODE (x) == DFmode)
+      else if (mode == DFmode)
 	{
 	  *total = s390_cost->ddbr;
 	}
-      else if (GET_MODE (x) == TFmode)
+      else if (mode == TFmode)
 	{
 	  *total = s390_cost->dxbr;
 	}
@@ -3348,9 +3349,9 @@ static bool
       return false;
 
     case SQRT:
-      if (GET_MODE (x) == SFmode)
+      if (mode == SFmode)
 	*total = s390_cost->sqebr;
-      else if (GET_MODE (x) == DFmode)
+      else if (mode == DFmode)
 	*total = s390_cost->sqdbr;
       else /* TFmode */
 	*total = s390_cost->sqxbr;
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	(revision 224310)
+++ gcc/config/sh/sh.c	(working copy)
@@ -284,7 +284,7 @@ static int addsubcosts (rtx);
 static int multcosts (rtx);
 static bool unspec_caller_rtx_p (rtx);
 static bool sh_cannot_copy_insn_p (rtx_insn *);
-static bool sh_rtx_costs (rtx, int, int, int, int *, bool);
+static bool sh_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int sh_address_cost (rtx, machine_mode, addr_space_t, bool);
 static int sh_pr_n_sets (void);
 static rtx sh_allocate_initial_value (rtx);
@@ -3272,7 +3272,7 @@ and_xor_ior_costs (rtx x, int code)
 	  || satisfies_constraint_J16 (XEXP (x, 1)))
 	return 1;
       else
-	return 1 + rtx_cost (XEXP (x, 1), AND, 1, !optimize_size);
+	return 1 + rtx_cost (XEXP (x, 1), GET_MODE (x), AND, 1, !optimize_size);
     }
 
   /* These constants are single cycle extu.[bw] instructions.  */
@@ -3412,9 +3412,12 @@ multcosts (rtx x ATTRIBUTE_UNUSED)
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.  */
 static bool
-sh_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+sh_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
+	      int opno ATTRIBUTE_UNUSED,
 	      int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       /* The lower-subreg pass decides whether to split multi-word regs
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	(revision 224310)
+++ gcc/config/sparc/sparc.c	(working copy)
@@ -597,7 +597,7 @@ static rtx sparc_tls_get_addr (void);
 static rtx sparc_tls_got (void);
 static int sparc_register_move_cost (machine_mode,
 				     reg_class_t, reg_class_t);
-static bool sparc_rtx_costs (rtx, int, int, int, int *, bool);
+static bool sparc_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static rtx sparc_function_value (const_tree, const_tree, bool);
 static rtx sparc_libcall_value (machine_mode, const_rtx);
 static bool sparc_function_value_regno_p (const unsigned int);
@@ -10930,10 +10930,11 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIB
    ??? the latencies and then CSE will just use that.  */
 
 static bool
-sparc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+sparc_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		 int opno ATTRIBUTE_UNUSED,
 		 int *total, bool speed ATTRIBUTE_UNUSED)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   bool float_mode_p = FLOAT_MODE_P (mode);
 
   switch (code)
@@ -10957,7 +10958,7 @@ static bool
       return true;
 
     case CONST_DOUBLE:
-      if (GET_MODE (x) == VOIDmode
+      if (mode == VOIDmode
 	  && ((CONST_DOUBLE_HIGH (x) == 0
 	       && CONST_DOUBLE_LOW (x) < 0x1000)
 	      || (CONST_DOUBLE_HIGH (x) == -1
@@ -11009,12 +11010,12 @@ static bool
 	sub = XEXP (x, 0);
 	if (GET_CODE (sub) == NEG)
 	  sub = XEXP (sub, 0);
-	*total += rtx_cost (sub, FMA, 0, speed);
+	*total += rtx_cost (sub, mode, FMA, 0, speed);
 
 	sub = XEXP (x, 2);
 	if (GET_CODE (sub) == NEG)
 	  sub = XEXP (sub, 0);
-	*total += rtx_cost (sub, FMA, 2, speed);
+	*total += rtx_cost (sub, mode, FMA, 2, speed);
 	return true;
       }
 
@@ -11133,7 +11134,7 @@ static bool
 
     case IOR:
       /* Handle the NAND vector patterns.  */
-      if (sparc_vector_mode_supported_p (GET_MODE (x))
+      if (sparc_vector_mode_supported_p (mode)
 	  && GET_CODE (XEXP (x, 0)) == NOT
 	  && GET_CODE (XEXP (x, 1)) == NOT)
 	{
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	(revision 224310)
+++ gcc/config/spu/spu.c	(working copy)
@@ -5245,11 +5245,11 @@ spu_asm_globalize_label (FILE * file, const char *
 }
 
 static bool
-spu_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+spu_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 	       int opno ATTRIBUTE_UNUSED, int *total,
 	       bool speed ATTRIBUTE_UNUSED)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   int cost = COSTS_N_INSNS (2);
 
   /* Folding to a CONST_VECTOR will use extra space but there might
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c	(revision 224310)
+++ gcc/config/stormy16/stormy16.c	(working copy)
@@ -86,7 +86,6 @@ static void xstormy16_asm_output_mi_thunk (FILE *,
 
 static void xstormy16_init_builtins (void);
 static rtx xstormy16_expand_builtin (tree, rtx, rtx, machine_mode, int);
-static bool xstormy16_rtx_costs (rtx, int, int, int, int *, bool);
 static int xstormy16_address_cost (rtx, machine_mode, addr_space_t, bool);
 static bool xstormy16_return_in_memory (const_tree, const_tree);
 
@@ -97,10 +96,13 @@ static GTY(()) section *bss100_section;
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-xstormy16_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+xstormy16_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+		     int outer_code ATTRIBUTE_UNUSED,
 		     int opno ATTRIBUTE_UNUSED, int *total,
 		     bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
Index: gcc/config/tilegx/tilegx.c
===================================================================
--- gcc/config/tilegx/tilegx.c	(revision 224310)
+++ gcc/config/tilegx/tilegx.c	(working copy)
@@ -559,9 +559,11 @@ tilegx_gimplify_va_arg_expr (tree valist, tree typ
 
 /* Implement TARGET_RTX_COSTS.  */
 static bool
-tilegx_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
-		  bool speed)
+tilegx_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+		  int *total, bool speed)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -628,9 +630,9 @@ static bool
       if (GET_CODE (XEXP (x, 0)) == MULT
 	  && cint_248_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
 	{
-	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0),
+	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0), mode,
 			      (enum rtx_code) outer_code, opno, speed)
-		    + rtx_cost (XEXP (x, 1),
+		    + rtx_cost (XEXP (x, 1), mode,
 				(enum rtx_code) outer_code, opno, speed)
 		    + COSTS_N_INSNS (1));
 	  return true;
Index: gcc/config/tilepro/tilepro.c
===================================================================
--- gcc/config/tilepro/tilepro.c	(revision 224310)
+++ gcc/config/tilepro/tilepro.c	(working copy)
@@ -501,9 +501,11 @@ tilepro_gimplify_va_arg_expr (tree valist, tree ty
 
 /* Implement TARGET_RTX_COSTS.  */
 static bool
-tilepro_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
-		   bool speed)
+tilepro_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+		   int *total, bool speed)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -570,9 +572,9 @@ static bool
       if (GET_CODE (XEXP (x, 0)) == MULT
 	  && cint_248_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
 	{
-	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0),
+	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0), mode,
 			      (enum rtx_code) outer_code, opno, speed)
-		    + rtx_cost (XEXP (x, 1),
+		    + rtx_cost (XEXP (x, 1), mode,
 				(enum rtx_code) outer_code, opno, speed)
 		    + COSTS_N_INSNS (1));
 	  return true;
Index: gcc/config/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c	(revision 224310)
+++ gcc/config/v850/v850.c	(working copy)
@@ -360,13 +360,10 @@ const_costs (rtx r, enum rtx_code c)
 }
 
 static bool
-v850_rtx_costs (rtx x,
-                int codearg,
-                int outer_code ATTRIBUTE_UNUSED,
-		int opno ATTRIBUTE_UNUSED,
-                int * total, bool speed)
+v850_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
-  enum rtx_code code = (enum rtx_code) codearg;
+  enum rtx_code code = GET_CODE (x);
 
   switch (code)
     {
@@ -390,9 +387,7 @@ static bool
 
     case MULT:
       if (TARGET_V850E
-	  && (   GET_MODE (x) == SImode
-	      || GET_MODE (x) == HImode
-	      || GET_MODE (x) == QImode))
+	  && (mode == SImode || mode == HImode || mode == QImode))
         {
 	  if (GET_CODE (XEXP (x, 1)) == REG)
 	    *total = 4;
Index: gcc/config/vax/vax.c
===================================================================
--- gcc/config/vax/vax.c	(revision 224310)
+++ gcc/config/vax/vax.c	(working copy)
@@ -73,7 +73,7 @@ static void vax_output_mi_thunk (FILE *, tree, HOS
 				 HOST_WIDE_INT, tree);
 static int vax_address_cost_1 (rtx);
 static int vax_address_cost (rtx, machine_mode, addr_space_t, bool);
-static bool vax_rtx_costs (rtx, int, int, int, int *, bool);
+static bool vax_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static rtx vax_function_arg (cumulative_args_t, machine_mode,
 			     const_tree, bool);
 static void vax_function_arg_advance (cumulative_args_t, machine_mode,
@@ -773,10 +773,11 @@ vax_address_cost (rtx x, machine_mode mode ATTRIBU
    costs on a per cpu basis.  */
 
 static bool
-vax_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
+	       int opno ATTRIBUTE_UNUSED,
 	       int *total, bool speed ATTRIBUTE_UNUSED)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   int i = 0;				   /* may be modified in switch */
   const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
 
@@ -816,7 +817,7 @@ static bool
       return true;
 
     case CONST_DOUBLE:
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
 	*total = vax_float_literal (x) ? 5 : 8;
       else
 	*total = ((CONST_DOUBLE_HIGH (x) == 0
@@ -1004,7 +1005,7 @@ static bool
 	{
 	case CONST_INT:
 	  if ((unsigned HOST_WIDE_INT)INTVAL (op) > 63
-	      && GET_MODE (x) != QImode)
+	      && mode != QImode)
 	    *total += 1;	/* 2 on VAX 2 */
 	  break;
 	case CONST:
Index: gcc/config/visium/visium.c
===================================================================
--- gcc/config/visium/visium.c	(revision 224310)
+++ gcc/config/visium/visium.c	(working copy)
@@ -192,7 +192,7 @@ static int visium_register_move_cost (enum machine
 
 static int visium_memory_move_cost (enum machine_mode, reg_class_t, bool);
 
-static bool visium_rtx_costs (rtx, int, int, int, int *, bool);
+static bool visium_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 
 static void visium_option_override (void);
 
@@ -1889,11 +1889,11 @@ visium_memory_move_cost (enum machine_mode mode,
 /* Return the relative costs of expression X.  */
 
 static bool
-visium_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+visium_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 		  int opno ATTRIBUTE_UNUSED, int *total,
 		  bool speed ATTRIBUTE_UNUSED)
 {
-  enum machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
 
   switch (code)
     {
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	(revision 224310)
+++ gcc/config/xtensa/xtensa.c	(working copy)
@@ -152,7 +152,7 @@ static unsigned int xtensa_multibss_section_type_f
 							int) ATTRIBUTE_UNUSED;
 static section *xtensa_select_rtx_section (machine_mode, rtx,
 					   unsigned HOST_WIDE_INT);
-static bool xtensa_rtx_costs (rtx, int, int, int, int *, bool);
+static bool xtensa_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int xtensa_register_move_cost (machine_mode, reg_class_t,
 				      reg_class_t);
 static int xtensa_memory_move_cost (machine_mode, reg_class_t, bool);
@@ -3576,9 +3576,12 @@ xtensa_memory_move_cost (machine_mode mode ATTRIBU
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		  int opno ATTRIBUTE_UNUSED,
 		  int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -3648,9 +3651,9 @@ static bool
     case MEM:
       {
 	int num_words =
-	  (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) ?  2 : 1;
+	  (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ?  2 : 1;
 
-	if (memory_address_p (GET_MODE (x), XEXP ((x), 0)))
+	if (memory_address_p (mode, XEXP ((x), 0)))
 	  *total = COSTS_N_INSNS (num_words);
 	else
 	  *total = COSTS_N_INSNS (2*num_words);
@@ -3667,13 +3670,13 @@ static bool
       return true;
 
     case NOT:
-      *total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 3 : 2);
+      *total = COSTS_N_INSNS (mode == DImode ? 3 : 2);
       return true;
 
     case AND:
     case IOR:
     case XOR:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	*total = COSTS_N_INSNS (2);
       else
 	*total = COSTS_N_INSNS (1);
@@ -3682,7 +3685,7 @@ static bool
     case ASHIFT:
     case ASHIFTRT:
     case LSHIFTRT:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	*total = COSTS_N_INSNS (50);
       else
 	*total = COSTS_N_INSNS (1);
@@ -3690,10 +3693,9 @@ static bool
 
     case ABS:
       {
-	machine_mode xmode = GET_MODE (x);
-	if (xmode == SFmode)
+	if (mode == SFmode)
 	  *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
-	else if (xmode == DFmode)
+	else if (mode == DFmode)
 	  *total = COSTS_N_INSNS (50);
 	else
 	  *total = COSTS_N_INSNS (4);
@@ -3703,10 +3705,9 @@ static bool
     case PLUS:
     case MINUS:
       {
-	machine_mode xmode = GET_MODE (x);
-	if (xmode == SFmode)
+	if (mode == SFmode)
 	  *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
-	else if (xmode == DFmode || xmode == DImode)
+	else if (mode == DFmode || mode == DImode)
 	  *total = COSTS_N_INSNS (50);
 	else
 	  *total = COSTS_N_INSNS (1);
@@ -3714,17 +3715,16 @@ static bool
       }
 
     case NEG:
-      *total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 4 : 2);
+      *total = COSTS_N_INSNS (mode == DImode ? 4 : 2);
       return true;
 
     case MULT:
       {
-	machine_mode xmode = GET_MODE (x);
-	if (xmode == SFmode)
+	if (mode == SFmode)
 	  *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 4 : 50);
-	else if (xmode == DFmode)
+	else if (mode == DFmode)
 	  *total = COSTS_N_INSNS (50);
-	else if (xmode == DImode)
+	else if (mode == DImode)
 	  *total = COSTS_N_INSNS (TARGET_MUL32_HIGH ? 10 : 50);
 	else if (TARGET_MUL32)
 	  *total = COSTS_N_INSNS (4);
@@ -3740,13 +3740,12 @@ static bool
     case DIV:
     case MOD:
       {
-	machine_mode xmode = GET_MODE (x);
-	if (xmode == SFmode)
+	if (mode == SFmode)
 	  {
 	    *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_DIV ? 8 : 50);
 	    return true;
 	  }
-	else if (xmode == DFmode)
+	else if (mode == DFmode)
 	  {
 	    *total = COSTS_N_INSNS (50);
 	    return true;
@@ -3757,8 +3756,7 @@ static bool
     case UDIV:
     case UMOD:
       {
-	machine_mode xmode = GET_MODE (x);
-	if (xmode == DImode)
+	if (mode == DImode)
 	  *total = COSTS_N_INSNS (50);
 	else if (TARGET_DIV32)
 	  *total = COSTS_N_INSNS (32);
@@ -3768,7 +3766,7 @@ static bool
       }
 
     case SQRT:
-      if (GET_MODE (x) == SFmode)
+      if (mode == SFmode)
 	*total = COSTS_N_INSNS (TARGET_HARD_FLOAT_SQRT ? 8 : 50);
       else
 	*total = COSTS_N_INSNS (50);

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] rtx_costs vs. const_int
  2015-06-15  3:50 [PATCH] rtx_costs vs. const_int Alan Modra
@ 2015-06-15 18:40 ` Segher Boessenkool
  2015-06-16  4:09   ` Alan Modra
  2015-06-22  1:32 ` Alan Modra
  2015-07-06 22:42 ` Jeff Law
  2 siblings, 1 reply; 5+ messages in thread
From: Segher Boessenkool @ 2015-06-15 18:40 UTC (permalink / raw)
  To: gcc-patches

Hi Alan,

On Mon, Jun 15, 2015 at 12:03:47PM +0930, Alan Modra wrote:
> This patch changes the targetm.rtx_costs interface to pass a mode
> parameter, and removes a redundant parameter.  The reason for the
> change is that powerpc and other backends need the mode that a
> const_int is used in to properly determine the cost.  For instance,
> (set (reg) (ior (reg) (const_int))) where const_int is 0xff..ffff0000
> can be implemented in one instruction on powerpc if the regs and
> constant are SImode, but not when DImode.

Nice :-)

> Some backends work around this problem by calculating the cost of the
> entire expression under the IOR, which allows the mode of the
> const_int to be inferred.

Yeah, I do this in my series to improve the PowerPC rotate-and-mask
instructions.  Some of the time you really have to look at a bigger
part of the pattern, but your patch should help here.

> sub-rtx's in rtx_cost are
> summed in order rather than reverse order so that the mode from an
> earlier operand can be used for a later operand lacking a mode.  This
> is for ZERO_EXTEND and similar codes where the sub-rtx mode is
> different to the outer mode.  Canonicalization puts const_int operands
> after other operands.

Not always; only for commutative operations, or operations that can be
swapped (like comparisons).  As a counterexample, see PowerPC subfic
(imm - reg).

> The testing showed some pre-existing bugs..
> 
> arc-elf dies on attempting to assemble first libgcc file, due to gas
> not understanding the options being passed by gcc.  Apparently no one
> cared enough to push gas changes upstream.

You need to configure it with --with-cpu.  Not that that makes any
sense :-)

> ia64-linux, m68k-linux, tilegx-linux and tilepro-linux have
> dependencies on include files, not solved by -Dinhibit_libc, so die
> building libgcc.  Can be solved by hand, but annoying.

Very annoying yes.  Have patches for all; will send.

> s390x-linux doesn't build as a cross-compiler.  undefined reference to
> `s390_host_detect_local_cpu(int, char const**)'

This is recent, maybe already fixed?


Segher

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] rtx_costs vs. const_int
  2015-06-15 18:40 ` Segher Boessenkool
@ 2015-06-16  4:09   ` Alan Modra
  0 siblings, 0 replies; 5+ messages in thread
From: Alan Modra @ 2015-06-16  4:09 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: gcc-patches

On Mon, Jun 15, 2015 at 01:37:48PM -0500, Segher Boessenkool wrote:
> > sub-rtx's in rtx_cost are
> > summed in order rather than reverse order so that the mode from an
> > earlier operand can be used for a later operand lacking a mode.  This
> > is for ZERO_EXTEND and similar codes where the sub-rtx mode is
> > different to the outer mode.  Canonicalization puts const_int operands
> > after other operands.
> 
> Not always; only for commutative operations, or operations that can be
> swapped (like comparisons).  As a counterexample, see PowerPC subfic
> (imm - reg).

Hmm.  Actually, on thinking over this some more I reckon I don't need
the change for sub-rtx's at all.  Clearly not for ZERO_EXTEND which
only has one operand.  To take your counter example,
  (zero_extend (minus (const_int) (reg)))
will use the mode of the MINUS for the CONST_INT.
Please consider that part of the patch removed.

> > The testing showed some pre-existing bugs..
> > 
> > arc-elf dies on attempting to assemble first libgcc file, due to gas
> > not understanding the options being passed by gcc.  Apparently no one
> > cared enough to push gas changes upstream.
> 
> You need to configure it with --with-cpu.  Not that that makes any
> sense :-)

Yes, I wouldn't have got past configure without adding --with-cpu.
--with-cpu doesn't solve the problem I'm talking about, which is that
you need an assembler built from a branch.  Mainline arc binutils does
not support mainline arc gcc.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] rtx_costs vs. const_int
  2015-06-15  3:50 [PATCH] rtx_costs vs. const_int Alan Modra
  2015-06-15 18:40 ` Segher Boessenkool
@ 2015-06-22  1:32 ` Alan Modra
  2015-07-06 22:42 ` Jeff Law
  2 siblings, 0 replies; 5+ messages in thread
From: Alan Modra @ 2015-06-22  1:32 UTC (permalink / raw)
  To: gcc-patches

On Mon, Jun 15, 2015 at 12:03:46PM +0930, Alan Modra wrote:
https://gcc.gnu.org/ml/gcc-patches/2015-06/msg00987.html
Ping?  Reposting due to the rtlanal.c:rtx_cost change mentioned in the
thread.

    rtx_costs vs. const_int
    
    This patch changes the targetm.rtx_costs interface to pass a mode
    parameter, and removes a redundant parameter.  The reason for the
    change is that powerpc and other backends need the mode that a
    const_int is used in to properly determine the cost.  For instance,
    (set (reg) (ior (reg) (const_int))) where const_int is 0xff..ffff0000
    can be implemented in one instruction on powerpc if the regs and
    constant are SImode, but not when DImode.
    
    Some backends work around this problem by calculating the cost of the
    entire expression under the IOR, which allows the mode of the
    const_int to be inferred.  This of course results in huge rtx_costs
    functions since you must inspect the operands of many rtx codes that
    take const_int operands.  Worse, it doesn't work for all calls to
    targetm.rtx_costs;  gcc doesn't always pass an entire insn, or even
    the complete right hand side of a SET, to rtx_costs.  One place this
    is seen is in expand, for example, emit_store_flag makes calls like
      rtx_cost (GEN_INT (normalizep), PLUS, ...)
    This sort of thing seems like a fundamental requirement in expand
    where insns are being built.  cse also makes similar calls.  So
    rtx_cost must be able to handle sub-expressions of an insn.
    
    As to the patch itself, the bulk is mostly mechanical.  I haven't made
    any simplification to the arm, aarch64 and mips rtx_costs that might
    be possible with this interface change.  rtlanal.c:rtx_cost also needs
    a machine_mode parameter to deal with the expand rtl mentioned above,
    as do a few other rtx cost functions.  Note that if the rtx passed to
    rtx_cost has a mode, then that is used rather than the "mode"
    parameter.
    
    I moved some inline functions in rtl.h later in the file because an
    earlier patch iteration passed GET_MODE (SET_DEST (x)) as the mode in
    set_rtx_cost and get_full_set_rtx_cost.  That meant the inlines needed
    to be after the definition of SET_DEST.  Later I realized that
    rtx_cost needed to provide the mode for a SET anyway, so VOIDmode
    would do just as well in set_rtx_cost.  That means the inlines don't
    need to be moved, but their new location seems better.
    
    The patch also doesn't contain any real changes to the powerpc
    backend, and in fact produces worse code than before in cases where
    rldic should be allowed by combine.  A later patch will cure the
    powerpc regressions.
    
    	* target.def (rtx_costs): Remove "code" param, add "mode".
    	* rtl.h (rtx_cost, get_full_rtx_cost): Update prototype.
    	(set_src_cost, get_full_set_src_cost): Likewise.  Move later in file.
    	(set_rtx_cost, get_full_set_rtx_cost): Move later in file.
    	* rtlanal.c (rtx_cost): Add "mode" parameter.  Update targetm.rtx_costs
    	call.  Track mode when given in rtx.
    	(get_full_rtx_cost): Add "mode" parameter.  Update rtx_cost calls.
    	(default_address_cost): Pass Pmode to rtx_cost.
    	(insn_rtx_cost): Pass dest mode of set to set_src_cost.
    	* cprop.c (try_replace_reg): Ensure set_rtx_cost is not called
    	with NULL set.
    	* cse.c (COST, COST_IN): Add MODE param.  Update all uses.
    	(notreg_cost): Add mode param.  Use it.
    	* gcse.c (want_to_gcse_p): Delete forward declaration.  Add
    	mode param and pass to set_src_cost.  Update all calls.
    	(hash_scan_set): Formatting.
    	* hooks.c (hook_bool_rtx_int_int_int_intp_bool_false): Delete.
    	(hook_bool_rtx_mode_int_int_intp_bool_false): New function.
    	* hooks.h: Ditto.
    	* expmed.c (init_expmed_one_conv, init_expmed_one_mode,
    	init_expmed, expand_mult, mult_by_coeff_cost, expand_smod_pow2,
    	emit_store_flag): Update set_src_cost and rtx_cost calls.
    	* auto-inc-dec.c (attempt_change): Likewise.
    	* calls.c (precompute_register_parameters): Likewise.
    	* combine.c (expand_compound_operation, make_extraction,
    	force_to_mode, distribute_and_simplify_rtx): Likewise.
    	* dojump.c (prefer_and_bit_test): Likewise.
    	* dse.c (find_shift_sequence): Likewise.
    	* expr.c (compress_float_constant): Likewise.
    	* fwprop.c (should_replace_address, try_fwprop_subst): Likewise.
    	* ifcvt.c (noce_try_sign_mask): Likewise.
    	* loop-doloop.c (doloop_optimize): Likewise.
    	* loop-invariant.c (create_new_invariant): Likewise.
    	* lower-subreg.c (shift_cost, compute_costs): Likewise.
    	* optabs.c (avoid_expensive_constant, prepare_cmp_insn,
    	lshift_cheap_p): Likewise.
    	* postreload.c (reload_cse_simplify_set, reload_cse_simplify_operands,
    	try_replace_in_use, reload_cse_move2add): Likewise.
    	* reload1.c (calculate_elim_costs_all_insns, note_reg_elim_costly):
    	Likewise.
    	* simplify-rtx.c (simplify_binary_operation_1): Likewise.
    	* tree-ssa-loop-ivopts.c (computation_cost): Likewise.
    	* tree-ssa-reassoc.c (optimize_range_tests_to_bit_test): Likewise.
    	* tree-switch-conversion.c (emit_case_bit_tests): Likewise.
    	* config/aarch64/aarch64.c (aarch64_rtx_costs): Delete "code" param,
    	add "mode" param.  Use "mode: in place of GET_MODE (x).  Pass mode
    	to rtx_cost calls.
    	* config/alpha/alpha.c (alpha_rtx_costs): Likewise.
    	* config/arc/arc.c (arc_rtx_costs): Likewise.
    	* config/arm/arm.c (arm_rtx_costs): Likewise.
    	* config/avr/avr.c (avr_rtx_costs, avr_rtx_costs_1): Likewise.
    	* config/bfin/bfin.c (bfin_rtx_costs): Likewise.
    	* config/c6x/c6x.c (c6x_rtx_costs): Likewise.
    	* config/cris/cris.c (cris_rtx_costs): Likewise.
    	* config/epiphany/epiphany.c (epiphany_rtx_costs): Likewise.
    	* config/frv/frv.c (frv_rtx_costs): Likewise.
    	* config/h8300/h8300.c (h8300_rtx_costs): Likewise.
    	* config/i386/i386.c (ix86_rtx_costs): Likewise.
    	* config/ia64/ia64.c (ia64_rtx_costs): Likewise.
    	* config/iq2000/iq2000.c (iq2000_rtx_costs): Likewise.
    	* config/lm32/lm32.c (lm32_rtx_costs): Likewise.
    	* config/m32c/m32c.c (m32c_rtx_costs): Likewise.
    	* config/m32r/m32r.c (m32r_rtx_costs): Likewise.
    	* config/m68k/m68k.c (m68k_rtx_costs): Likewise.
    	* config/mcore/mcore.c (mcore_rtx_costs): Likewise.
    	* config/mep/mep.c (mep_rtx_cost): Likewise.
    	* config/microblaze/microblaze.c (microblaze_rtx_costs): Likewise.
    	* config/mips/mips.c (mips_rtx_costs): Likewise.
    	* config/mmix/mmix.c (mmix_rtx_costs): Likewise.
    	* config/mn10300/mn10300.c (mn10300_rtx_costs): Likewise.
    	* config/msp430/msp430.c (msp430_rtx_costs): Likewise.
    	* config/nds32/nds32-cost.c (nds32_rtx_costs_impl): Likewise.
    	* config/nds32/nds32-protos.h (nds32_rtx_costs_impl): Likewise.
    	* config/nds32/nds32.c (nds32_rtx_costs): Likewise.
    	* config/nios2/nios2.c (nios2_rtx_costs): Likewise.
    	* config/pa/pa.c (hppa_rtx_costs): Likewise.
    	* config/pdp11/pdp11.c (pdp11_rtx_costs): Likewise.
    	* config/rl78/rl78.c (rl78_rtx_costs): Likewise.
    	* config/rs6000/rs6000.c (rs6000_rtx_costs): Likewise.
    	* config/s390/s390.c (s390_rtx_costs): Likewise.
    	* config/sh/sh.c (sh_rtx_costs): Likewise.
    	* config/sparc/sparc.c (sparc_rtx_costs): Likewise.
    	* config/spu/spu.c (spu_rtx_costs): Likewise.
    	* config/stormy16/stormy16.c (xstormy16_rtx_costs): Likewise.
    	* config/tilegx/tilegx.c (tilegx_rtx_costs): Likewise.
    	* config/tilepro/tilepro.c (tilepro_rtx_costs): Likewise.
    	* config/v850/v850.c (v850_rtx_costs): Likewise.
    	* config/vax/vax.c (vax_rtx_costs): Likewise.
    	* config/visium/visium.c (visium_rtx_costs): Likewise.
    	* config/xtensa/xtensa.c (xtensa_rtx_costs): Likewise.
    	* config/aarch64/aarch64.c (aarch64_rtx_mult_cost): Change type of
    	"code" param, and pass as outer_code to first rtx_cost call.  Pass
    	mode to rtx_cost calls.
    	(aarch64_address_cost, aarch64_if_then_else_costs): Update rtx_cost
    	calls.
    	(aarch64_rtx_costs_wrapper): Update.
    	* config/arm/arm.c (arm_rtx_costs_1, arm_size_rtx_costs,
    	arm_unspec_cost, arm_new_rtx_costs, arm_slowmul_rtx_costs): Update
    	rtx_cost calls.
    	* config/avr/avr.c (avr_final_prescan_insn): Update set_src_cost
    	and rtx_cost calls.
    	(avr_operand_rtx_cost): Similarly.
    	(avr_rtx_costs_1): Correct mode passed to avr_operand_rtx_cost
    	for subexpressions of ZERO_EXTEND, SIGN_EXTEND and COMPARE.
    	* config/mips/mips.c (mips_stack_address_p): Comment typo.
    	(mips_binary_cost): Update rtx_cost and set_src_cost calls.
    	(mips_rtx_costs): Use GET_MODE (x) to detect const_int.
    	* config/mn10300/mn10300.c (mn10300_address_cost): Pass Pmode to
    	rtx_cost.
    	(mn10300_rtx_costs): Correct mode passed to mn10300_address_cost.
    	* config/rs6000/rs6000.c (rs6000_debug_rtx_costs): Update.
    	* config/sh/sh.c (and_xor_ior_costs): Update rtx_cost call.
    	* doc/tm.texi: Regenerate.

diff --git a/gcc/target.def b/gcc/target.def
index b606b81..3b46c75 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3390,7 +3390,7 @@ DEFHOOKPOD
 /* Compute a (partial) cost for rtx X.  Return true if the complete
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.  */
-/* Note that CODE and OUTER_CODE ought to be RTX_CODE, but that's
+/* Note that OUTER_CODE ought to be RTX_CODE, but that's
    not necessarily defined at this point.  */
 DEFHOOK
 (rtx_costs,
@@ -3404,8 +3404,8 @@ that @samp{GET_CODE (@var{y}) == @var{outer_code}} and such that\n\
 either (a) @samp{XEXP (@var{y}, @var{opno}) == @var{x}} or\n\
 (b) @samp{XVEC (@var{y}, @var{opno})} contains @var{x}.\n\
 \n\
-@var{code} is @var{x}'s expression code---redundant, since it can be\n\
-obtained with @code{GET_CODE (@var{x})}.\n\
+@var{mode} is @var{x}'s machine mode, or for cases like @code{const_int} that\n\
+do not have a mode, the mode in which @var{x} is used.\n\
 \n\
 In implementing this hook, you can use the construct\n\
 @code{COSTS_N_INSNS (@var{n})} to specify a cost equal to @var{n} fast\n\
@@ -3423,8 +3423,8 @@ size cost of an expression, again relative to @code{COSTS_N_INSNS}.\n\
 \n\
 The hook returns true when all subexpressions of @var{x} have been\n\
 processed, and false when @code{rtx_cost} should recurse.",
- bool, (rtx x, int code, int outer_code, int opno, int *total, bool speed),
- hook_bool_rtx_int_int_int_intp_bool_false)
+ bool, (rtx x, machine_mode mode, int outer_code, int opno, int *total, bool speed),
+ hook_bool_rtx_mode_int_int_intp_bool_false)
 
 /* Compute the cost of X, used as an address.  Never called with
    invalid addresses.  */
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 5b4a525..6aea9de 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2149,9 +2149,9 @@ wi::max_value (machine_mode mode, signop sgn)
 }
 
 extern void init_rtlanal (void);
-extern int rtx_cost (rtx, enum rtx_code, int, bool);
+extern int rtx_cost (rtx, machine_mode, enum rtx_code, int, bool);
 extern int address_cost (rtx, machine_mode, addr_space_t, bool);
-extern void get_full_rtx_cost (rtx, enum rtx_code, int,
+extern void get_full_rtx_cost (rtx, machine_mode, enum rtx_code, int,
 			       struct full_rtx_costs *);
 extern unsigned int subreg_lsb (const_rtx);
 extern unsigned int subreg_lsb_1 (machine_mode, machine_mode,
@@ -2180,43 +2180,6 @@ extern void update_address (struct address_info *);
 extern HOST_WIDE_INT get_index_scale (const struct address_info *);
 extern enum rtx_code get_index_code (const struct address_info *);
 
-#ifndef GENERATOR_FILE
-/* Return the cost of SET X.  SPEED_P is true if optimizing for speed
-   rather than size.  */
-
-static inline int
-set_rtx_cost (rtx x, bool speed_p)
-{
-  return rtx_cost (x, INSN, 4, speed_p);
-}
-
-/* Like set_rtx_cost, but return both the speed and size costs in C.  */
-
-static inline void
-get_full_set_rtx_cost (rtx x, struct full_rtx_costs *c)
-{
-  get_full_rtx_cost (x, INSN, 4, c);
-}
-
-/* Return the cost of moving X into a register, relative to the cost
-   of a register move.  SPEED_P is true if optimizing for speed rather
-   than size.  */
-
-static inline int
-set_src_cost (rtx x, bool speed_p)
-{
-  return rtx_cost (x, SET, 1, speed_p);
-}
-
-/* Like set_src_cost, but return both the speed and size costs in C.  */
-
-static inline void
-get_full_set_src_cost (rtx x, struct full_rtx_costs *c)
-{
-  get_full_rtx_cost (x, SET, 1, c);
-}
-#endif
-
 /* 1 if RTX is a subreg containing a reg that is already known to be
    sign- or zero-extended from the mode of the subreg to the mode of
    the reg.  SUBREG_PROMOTED_UNSIGNED_P gives the signedness of the
@@ -2648,6 +2611,43 @@ extern int currently_expanding_to_rtl;
 
 /* Generally useful functions.  */
 
+#ifndef GENERATOR_FILE
+/* Return the cost of SET X.  SPEED_P is true if optimizing for speed
+   rather than size.  */
+
+static inline int
+set_rtx_cost (rtx x, bool speed_p)
+{
+  return rtx_cost (x, VOIDmode, INSN, 4, speed_p);
+}
+
+/* Like set_rtx_cost, but return both the speed and size costs in C.  */
+
+static inline void
+get_full_set_rtx_cost (rtx x, struct full_rtx_costs *c)
+{
+  get_full_rtx_cost (x, VOIDmode, INSN, 4, c);
+}
+
+/* Return the cost of moving X into a register, relative to the cost
+   of a register move.  SPEED_P is true if optimizing for speed rather
+   than size.  */
+
+static inline int
+set_src_cost (rtx x, machine_mode mode, bool speed_p)
+{
+  return rtx_cost (x, mode, SET, 1, speed_p);
+}
+
+/* Like set_src_cost, but return both the speed and size costs in C.  */
+
+static inline void
+get_full_set_src_cost (rtx x, machine_mode mode, struct full_rtx_costs *c)
+{
+  get_full_rtx_cost (x, mode, SET, 1, c);
+}
+#endif
+
 /* In explow.c */
 extern HOST_WIDE_INT trunc_int_for_mode	(HOST_WIDE_INT, machine_mode);
 extern rtx plus_constant (machine_mode, rtx, HOST_WIDE_INT, bool = false);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index d4a9eda..e1e3346 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -3813,7 +3813,8 @@ label_is_jump_target_p (const_rtx label, const rtx_insn *jump_insn)
    be returned.  */
 
 int
-rtx_cost (rtx x, enum rtx_code outer_code, int opno, bool speed)
+rtx_cost (rtx x, machine_mode mode, enum rtx_code outer_code,
+	  int opno, bool speed)
 {
   int i, j;
   enum rtx_code code;
@@ -3824,9 +3825,12 @@ rtx_cost (rtx x, enum rtx_code outer_code, int opno, bool speed)
   if (x == 0)
     return 0;
 
+  if (GET_MODE (x) != VOIDmode)
+    mode = GET_MODE (x);
+
   /* A size N times larger than UNITS_PER_WORD likely needs N times as
      many insns, taking N times as long.  */
-  factor = GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD;
+  factor = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
   if (factor == 0)
     factor = 1;
 
@@ -3856,7 +3860,8 @@ rtx_cost (rtx x, enum rtx_code outer_code, int opno, bool speed)
     case SET:
       /* A SET doesn't have a mode, so let's look at the SET_DEST to get
 	 the mode for the factor.  */
-      factor = GET_MODE_SIZE (GET_MODE (SET_DEST (x))) / UNITS_PER_WORD;
+      mode = GET_MODE (SET_DEST (x));
+      factor = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
       if (factor == 0)
 	factor = 1;
       /* Pass through.  */
@@ -3873,12 +3878,12 @@ rtx_cost (rtx x, enum rtx_code outer_code, int opno, bool speed)
       total = 0;
       /* If we can't tie these modes, make this expensive.  The larger
 	 the mode, the more expensive it is.  */
-      if (! MODES_TIEABLE_P (GET_MODE (x), GET_MODE (SUBREG_REG (x))))
+      if (! MODES_TIEABLE_P (mode, GET_MODE (SUBREG_REG (x))))
 	return COSTS_N_INSNS (2 + factor);
       break;
 
     default:
-      if (targetm.rtx_costs (x, code, outer_code, opno, &total, speed))
+      if (targetm.rtx_costs (x, mode, outer_code, opno, &total, speed))
 	return total;
       break;
     }
@@ -3889,10 +3894,10 @@ rtx_cost (rtx x, enum rtx_code outer_code, int opno, bool speed)
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     if (fmt[i] == 'e')
-      total += rtx_cost (XEXP (x, i), code, i, speed);
+      total += rtx_cost (XEXP (x, i), mode, code, i, speed);
     else if (fmt[i] == 'E')
       for (j = 0; j < XVECLEN (x, i); j++)
-	total += rtx_cost (XVECEXP (x, i, j), code, i, speed);
+	total += rtx_cost (XVECEXP (x, i, j), mode, code, i, speed);
 
   return total;
 }
@@ -3901,11 +3906,11 @@ rtx_cost (rtx x, enum rtx_code outer_code, int opno, bool speed)
    costs for X, which is operand OPNO in an expression with code OUTER.  */
 
 void
-get_full_rtx_cost (rtx x, enum rtx_code outer, int opno,
+get_full_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer, int opno,
 		   struct full_rtx_costs *c)
 {
-  c->speed = rtx_cost (x, outer, opno, true);
-  c->size = rtx_cost (x, outer, opno, false);
+  c->speed = rtx_cost (x, mode, outer, opno, true);
+  c->size = rtx_cost (x, mode, outer, opno, false);
 }
 
 \f
@@ -3933,7 +3938,7 @@ address_cost (rtx x, machine_mode mode, addr_space_t as, bool speed)
 int
 default_address_cost (rtx x, machine_mode, addr_space_t, bool speed)
 {
-  return rtx_cost (x, MEM, 0, speed);
+  return rtx_cost (x, Pmode, MEM, 0, speed);
 }
 \f
 
@@ -4940,7 +4945,7 @@ insn_rtx_cost (rtx pat, bool speed)
   else
     return 0;
 
-  cost = set_src_cost (SET_SRC (set), speed);
+  cost = set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)), speed);
   return cost > 0 ? cost : COSTS_N_INSNS (1);
 }
 
diff --git a/gcc/auto-inc-dec.c b/gcc/auto-inc-dec.c
index 3241ed7..68f167a 100644
--- a/gcc/auto-inc-dec.c
+++ b/gcc/auto-inc-dec.c
@@ -494,9 +494,9 @@ attempt_change (rtx new_addr, rtx inc_reg)
   PUT_MODE (mem_tmp, mode);
   XEXP (mem_tmp, 0) = new_addr;
 
-  old_cost = (set_src_cost (mem, speed)
+  old_cost = (set_src_cost (mem, mode, speed)
 	      + set_rtx_cost (PATTERN (inc_insn.insn), speed));
-  new_cost = set_src_cost (mem_tmp, speed);
+  new_cost = set_src_cost (mem_tmp, mode, speed);
 
   /* The first item of business is to see if this is profitable.  */
   if (old_cost < new_cost)
diff --git a/gcc/calls.c b/gcc/calls.c
index d632881..df18e0c 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -924,8 +924,9 @@ precompute_register_parameters (int num_actuals, struct arg_data *args,
 		     || (GET_CODE (args[i].value) == SUBREG
 			 && REG_P (SUBREG_REG (args[i].value)))))
 		 && args[i].mode != BLKmode
-		 && set_src_cost (args[i].value, optimize_insn_for_speed_p ())
-		    > COSTS_N_INSNS (1)
+		 && (set_src_cost (args[i].value, args[i].mode,
+				   optimize_insn_for_speed_p ())
+		     > COSTS_N_INSNS (1))
 		 && ((*reg_parm_seen
 		      && targetm.small_register_classes_for_mode_p (args[i].mode))
 		     || optimize))
diff --git a/gcc/combine.c b/gcc/combine.c
index 171e51d..6f755a6 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -7053,15 +7053,16 @@ expand_compound_operation (rtx x)
 		     >> 1))
 	       == 0)))
     {
-      rtx temp = gen_rtx_ZERO_EXTEND (GET_MODE (x), XEXP (x, 0));
+      machine_mode mode = GET_MODE (x);
+      rtx temp = gen_rtx_ZERO_EXTEND (mode, XEXP (x, 0));
       rtx temp2 = expand_compound_operation (temp);
 
       /* Make sure this is a profitable operation.  */
-      if (set_src_cost (x, optimize_this_for_speed_p)
-          > set_src_cost (temp2, optimize_this_for_speed_p))
+      if (set_src_cost (x, mode, optimize_this_for_speed_p)
+          > set_src_cost (temp2, mode, optimize_this_for_speed_p))
        return temp2;
-      else if (set_src_cost (x, optimize_this_for_speed_p)
-               > set_src_cost (temp, optimize_this_for_speed_p))
+      else if (set_src_cost (x, mode, optimize_this_for_speed_p)
+               > set_src_cost (temp, mode, optimize_this_for_speed_p))
        return temp;
       else
        return x;
@@ -7487,8 +7488,8 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
 
 	  /* Prefer ZERO_EXTENSION, since it gives more information to
 	     backends.  */
-	  if (set_src_cost (temp, optimize_this_for_speed_p)
-	      <= set_src_cost (temp1, optimize_this_for_speed_p))
+	  if (set_src_cost (temp, mode, optimize_this_for_speed_p)
+	      <= set_src_cost (temp1, mode, optimize_this_for_speed_p))
 	    return temp;
 	  return temp1;
 	}
@@ -7673,8 +7674,8 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
 
 	  /* Prefer ZERO_EXTENSION, since it gives more information to
 	     backends.  */
-	  if (set_src_cost (temp1, optimize_this_for_speed_p)
-	      < set_src_cost (temp, optimize_this_for_speed_p))
+	  if (set_src_cost (temp1, pos_mode, optimize_this_for_speed_p)
+	      < set_src_cost (temp, pos_mode, optimize_this_for_speed_p))
 	    temp = temp1;
 	}
       pos_rtx = temp;
@@ -8446,8 +8447,8 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 
 	      y = simplify_gen_binary (AND, GET_MODE (x), XEXP (x, 0),
 				       gen_int_mode (cval, GET_MODE (x)));
-	      if (set_src_cost (y, optimize_this_for_speed_p)
-	          < set_src_cost (x, optimize_this_for_speed_p))
+	      if (set_src_cost (y, GET_MODE (x), optimize_this_for_speed_p)
+	          < set_src_cost (x, GET_MODE (x), optimize_this_for_speed_p))
 		x = y;
 	    }
 
@@ -9640,8 +9641,8 @@ distribute_and_simplify_rtx (rtx x, int n)
   tmp = apply_distributive_law (simplify_gen_binary (inner_code, mode,
 						     new_op0, new_op1));
   if (GET_CODE (tmp) != outer_code
-      && (set_src_cost (tmp, optimize_this_for_speed_p)
-	  < set_src_cost (x, optimize_this_for_speed_p)))
+      && (set_src_cost (tmp, mode, optimize_this_for_speed_p)
+	  < set_src_cost (x, mode, optimize_this_for_speed_p)))
     return tmp;
 
   return NULL_RTX;
diff --git a/gcc/cprop.c b/gcc/cprop.c
index 2596868..5402dab 100644
--- a/gcc/cprop.c
+++ b/gcc/cprop.c
@@ -759,11 +759,12 @@ try_replace_reg (rtx from, rtx to, rtx_insn *insn)
   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
   int old_cost = set ? set_rtx_cost (set, speed) : 0;
 
-  if ((note != 0
-      && REG_NOTE_KIND (note) == REG_EQUAL
-      && (GET_CODE (XEXP (note, 0)) == CONST
-	  || CONSTANT_P (XEXP (note, 0))))
-      || (set && CONSTANT_P (SET_SRC (set))))
+  if (!set
+      || CONSTANT_P (SET_SRC (set))
+      || (note != 0
+	  && REG_NOTE_KIND (note) == REG_EQUAL
+	  && (GET_CODE (XEXP (note, 0)) == CONST
+	      || CONSTANT_P (XEXP (note, 0)))))
     check_rtx_costs = false;
 
   /* Usually we substitute easy stuff, so we won't copy everything.
@@ -779,7 +780,7 @@ try_replace_reg (rtx from, rtx to, rtx_insn *insn)
 
   if (check_rtx_costs
       && CONSTANT_P (to)
-      && (set_rtx_cost (set, speed) > old_cost))
+      && set_rtx_cost (set, speed) > old_cost)
     {
       cancel_changes (0);
       return false;
diff --git a/gcc/cse.c b/gcc/cse.c
index 100c9c8..f49d5c0 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -477,8 +477,10 @@ struct table_elt
    || (HARD_REGISTER_NUM_P (N)						\
        && FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
 
-#define COST(X) (REG_P (X) ? 0 : notreg_cost (X, SET, 1))
-#define COST_IN(X, OUTER, OPNO) (REG_P (X) ? 0 : notreg_cost (X, OUTER, OPNO))
+#define COST(X, MODE)							\
+  (REG_P (X) ? 0 : notreg_cost (X, MODE, SET, 1))
+#define COST_IN(X, MODE, OUTER, OPNO)					\
+  (REG_P (X) ? 0 : notreg_cost (X, MODE, OUTER, OPNO))
 
 /* Get the number of times this register has been updated in this
    basic block.  */
@@ -554,7 +556,7 @@ static bitmap cse_ebb_live_in, cse_ebb_live_out;
 static sbitmap cse_visited_basic_blocks;
 
 static bool fixed_base_plus_p (rtx x);
-static int notreg_cost (rtx, enum rtx_code, int);
+static int notreg_cost (rtx, machine_mode, enum rtx_code, int);
 static int preferable (int, int, int, int);
 static void new_basic_block (void);
 static void make_new_qty (unsigned int, machine_mode);
@@ -731,19 +733,17 @@ preferable (int cost_a, int regcost_a, int cost_b, int regcost_b)
    from COST macro to keep it simple.  */
 
 static int
-notreg_cost (rtx x, enum rtx_code outer, int opno)
+notreg_cost (rtx x, machine_mode mode, enum rtx_code outer, int opno)
 {
   return ((GET_CODE (x) == SUBREG
 	   && REG_P (SUBREG_REG (x))
-	   && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
+	   && GET_MODE_CLASS (mode) == MODE_INT
 	   && GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_INT
-	   && (GET_MODE_SIZE (GET_MODE (x))
-	       < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+	   && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
 	   && subreg_lowpart_p (x)
-	   && TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (x),
-					     GET_MODE (SUBREG_REG (x))))
+	   && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (SUBREG_REG (x))))
 	  ? 0
-	  : rtx_cost (x, outer, opno, optimize_this_for_speed_p) * 2);
+	  : rtx_cost (x, mode, outer, opno, optimize_this_for_speed_p) * 2);
 }
 
 \f
@@ -1247,7 +1247,7 @@ insert_const_anchor (HOST_WIDE_INT anchor, rtx reg, HOST_WIDE_INT offs,
      don't prefer pseudos over hard regs so that we derive constants in
      argument registers from other argument registers rather than from the
      original pseudo that was used to synthesize the constant.  */
-  insert_with_costs (exp, elt, hash, mode, COST (reg), 1);
+  insert_with_costs (exp, elt, hash, mode, COST (reg, mode), 1);
 }
 
 /* The constant CST is equivalent to the register REG.  Create
@@ -1728,8 +1728,8 @@ static struct table_elt *
 insert (rtx x, struct table_elt *classp, unsigned int hash,
 	machine_mode mode)
 {
-  return
-    insert_with_costs (x, classp, hash, mode, COST (x), approx_reg_cost (x));
+  return insert_with_costs (x, classp, hash, mode,
+			    COST (x, mode), approx_reg_cost (x));
 }
 
 \f
@@ -3264,7 +3264,8 @@ fold_rtx (rtx x, rtx_insn *insn)
 	   argument.  */
 	if (const_arg != 0
 	    && const_arg != folded_arg
-	    && COST_IN (const_arg, code, i) <= COST_IN (folded_arg, code, i)
+	    && (COST_IN (const_arg, mode_arg, code, i)
+		<= COST_IN (folded_arg, mode_arg, code, i))
 
 	    /* It's not safe to substitute the operand of a conversion
 	       operator with a constant, as the conversion's identity
@@ -3391,7 +3392,7 @@ fold_rtx (rtx x, rtx_insn *insn)
 		  if (p != NULL)
 		    {
 		      cheapest_simplification = x;
-		      cheapest_cost = COST (x);
+		      cheapest_cost = COST (x, mode);
 
 		      for (p = p->first_same_value; p != NULL; p = p->next_same_value)
 			{
@@ -3411,7 +3412,7 @@ fold_rtx (rtx x, rtx_insn *insn)
 			  if (simp_result == NULL)
 			    continue;
 
-			  cost = COST (simp_result);
+			  cost = COST (simp_result, mode);
 			  if (cost < cheapest_cost)
 			    {
 			      cheapest_cost = cost;
@@ -5001,7 +5002,7 @@ cse_insn (rtx_insn *insn)
 	    src_cost = src_regcost = -1;
 	  else
 	    {
-	      src_cost = COST (src);
+	      src_cost = COST (src, mode);
 	      src_regcost = approx_reg_cost (src);
 	    }
 	}
@@ -5012,7 +5013,7 @@ cse_insn (rtx_insn *insn)
 	    src_eqv_cost = src_eqv_regcost = -1;
 	  else
 	    {
-	      src_eqv_cost = COST (src_eqv_here);
+	      src_eqv_cost = COST (src_eqv_here, mode);
 	      src_eqv_regcost = approx_reg_cost (src_eqv_here);
 	    }
 	}
@@ -5023,7 +5024,7 @@ cse_insn (rtx_insn *insn)
 	    src_folded_cost = src_folded_regcost = -1;
 	  else
 	    {
-	      src_folded_cost = COST (src_folded);
+	      src_folded_cost = COST (src_folded, mode);
 	      src_folded_regcost = approx_reg_cost (src_folded);
 	    }
 	}
@@ -5034,7 +5035,7 @@ cse_insn (rtx_insn *insn)
 	    src_related_cost = src_related_regcost = -1;
 	  else
 	    {
-	      src_related_cost = COST (src_related);
+	      src_related_cost = COST (src_related, mode);
 	      src_related_regcost = approx_reg_cost (src_related);
 
 	      /* If a const-anchor is used to synthesize a constant that
@@ -5347,7 +5348,7 @@ cse_insn (rtx_insn *insn)
 		  /* If we had a constant that is cheaper than what we are now
 		     setting SRC to, use that constant.  We ignored it when we
 		     thought we could make this into a no-op.  */
-		  if (src_const && COST (src_const) < COST (src)
+		  if (src_const && COST (src_const, mode) < COST (src, mode)
 		      && validate_change (insn, &SET_SRC (sets[i].rtl),
 					  src_const, 0))
 		    src = src_const;
diff --git a/gcc/dojump.c b/gcc/dojump.c
index b062a56..31ea8b9 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -205,8 +205,8 @@ prefer_and_bit_test (machine_mode mode, int bitnum)
   XEXP (XEXP (shift_test, 0), 1) = GEN_INT (bitnum);
 
   speed_p = optimize_insn_for_speed_p ();
-  return (rtx_cost (and_test, IF_THEN_ELSE, 0, speed_p)
-	  <= rtx_cost (shift_test, IF_THEN_ELSE, 0, speed_p));
+  return (rtx_cost (and_test, mode, IF_THEN_ELSE, 0, speed_p)
+	  <= rtx_cost (shift_test, mode, IF_THEN_ELSE, 0, speed_p));
 }
 
 /* Subroutine of do_jump, dealing with exploded comparisons of the type
diff --git a/gcc/dse.c b/gcc/dse.c
index 508ec00..29bbb4c 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -1843,7 +1843,8 @@ find_shift_sequence (int access_size,
 		  byte = subreg_lowpart_offset (read_mode, new_mode);
 		  ret = simplify_subreg (read_mode, ret, new_mode, byte);
 		  if (ret && CONSTANT_P (ret)
-		      && set_src_cost (ret, speed) <= COSTS_N_INSNS (1))
+		      && (set_src_cost (ret, read_mode, speed)
+			  <= COSTS_N_INSNS (1)))
 		    return ret;
 		}
 	    }
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 3f74908..895d11d 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -150,7 +150,8 @@ init_expmed_one_conv (struct init_expmed_rtl *all, machine_mode to_mode,
   which = (to_size < from_size ? all->trunc : all->zext);
 
   PUT_MODE (all->reg, from_mode);
-  set_convert_cost (to_mode, from_mode, speed, set_src_cost (which, speed));
+  set_convert_cost (to_mode, from_mode, speed,
+		    set_src_cost (which, to_mode, speed));
 }
 
 static void
@@ -179,15 +180,15 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
   PUT_MODE (all->zext, mode);
   PUT_MODE (all->trunc, mode);
 
-  set_add_cost (speed, mode, set_src_cost (all->plus, speed));
-  set_neg_cost (speed, mode, set_src_cost (all->neg, speed));
-  set_mul_cost (speed, mode, set_src_cost (all->mult, speed));
-  set_sdiv_cost (speed, mode, set_src_cost (all->sdiv, speed));
-  set_udiv_cost (speed, mode, set_src_cost (all->udiv, speed));
+  set_add_cost (speed, mode, set_src_cost (all->plus, mode, speed));
+  set_neg_cost (speed, mode, set_src_cost (all->neg, mode, speed));
+  set_mul_cost (speed, mode, set_src_cost (all->mult, mode, speed));
+  set_sdiv_cost (speed, mode, set_src_cost (all->sdiv, mode, speed));
+  set_udiv_cost (speed, mode, set_src_cost (all->udiv, mode, speed));
 
-  set_sdiv_pow2_cheap (speed, mode, (set_src_cost (all->sdiv_32, speed)
+  set_sdiv_pow2_cheap (speed, mode, (set_src_cost (all->sdiv_32, mode, speed)
 				     <= 2 * add_cost (speed, mode)));
-  set_smod_pow2_cheap (speed, mode, (set_src_cost (all->smod_32, speed)
+  set_smod_pow2_cheap (speed, mode, (set_src_cost (all->smod_32, mode, speed)
 				     <= 4 * add_cost (speed, mode)));
 
   set_shift_cost (speed, mode, 0, 0);
@@ -204,10 +205,13 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
       XEXP (all->shift, 1) = all->cint[m];
       XEXP (all->shift_mult, 1) = all->pow2[m];
 
-      set_shift_cost (speed, mode, m, set_src_cost (all->shift, speed));
-      set_shiftadd_cost (speed, mode, m, set_src_cost (all->shift_add, speed));
-      set_shiftsub0_cost (speed, mode, m, set_src_cost (all->shift_sub0, speed));
-      set_shiftsub1_cost (speed, mode, m, set_src_cost (all->shift_sub1, speed));
+      set_shift_cost (speed, mode, m, set_src_cost (all->shift, mode, speed));
+      set_shiftadd_cost (speed, mode, m, set_src_cost (all->shift_add, mode,
+						       speed));
+      set_shiftsub0_cost (speed, mode, m, set_src_cost (all->shift_sub0, mode,
+							speed));
+      set_shiftsub1_cost (speed, mode, m, set_src_cost (all->shift_sub1, mode,
+							speed));
     }
 
   if (SCALAR_INT_MODE_P (mode))
@@ -227,9 +231,9 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
 	  XEXP (all->wide_lshr, 1) = GEN_INT (mode_bitsize);
 
 	  set_mul_widen_cost (speed, wider_mode,
-			      set_src_cost (all->wide_mult, speed));
+			      set_src_cost (all->wide_mult, wider_mode, speed));
 	  set_mul_highpart_cost (speed, mode,
-				 set_src_cost (all->wide_trunc, speed));
+				 set_src_cost (all->wide_trunc, mode, speed));
 	}
     }
 }
@@ -271,7 +275,7 @@ init_expmed (void)
   for (speed = 0; speed < 2; speed++)
     {
       crtl->maybe_hot_insn_p = speed;
-      set_zero_cost (speed, set_src_cost (const0_rtx, speed));
+      set_zero_cost (speed, set_src_cost (const0_rtx, mode, speed));
 
       for (mode = MIN_MODE_INT; mode <= MAX_MODE_INT;
 	   mode = (machine_mode)(mode + 1))
@@ -3212,7 +3216,8 @@ expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
 	     Exclude cost of op0 from max_cost to match the cost
 	     calculation of the synth_mult.  */
 	  coeff = -(unsigned HOST_WIDE_INT) coeff;
-	  max_cost = (set_src_cost (gen_rtx_MULT (mode, fake_reg, op1), speed)
+	  max_cost = (set_src_cost (gen_rtx_MULT (mode, fake_reg, op1),
+				    mode, speed)
 		      - neg_cost (speed, mode));
 	  if (max_cost <= 0)
 	    goto skip_synth;
@@ -3237,7 +3242,7 @@ expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
 
       /* Exclude cost of op0 from max_cost to match the cost
 	 calculation of the synth_mult.  */
-      max_cost = set_src_cost (gen_rtx_MULT (mode, fake_reg, op1), speed);
+      max_cost = set_src_cost (gen_rtx_MULT (mode, fake_reg, op1), mode, speed);
       if (choose_mult_variant (mode, coeff, &algorithm, &variant, max_cost))
 	return expand_mult_const (mode, op0, coeff, target,
 				  &algorithm, variant);
@@ -3278,7 +3283,8 @@ mult_by_coeff_cost (HOST_WIDE_INT coeff, machine_mode mode, bool speed)
   enum mult_variant variant;
 
   rtx fake_reg = gen_raw_REG (mode, LAST_VIRTUAL_REGISTER + 1);
-  max_cost = set_src_cost (gen_rtx_MULT (mode, fake_reg, fake_reg), speed);
+  max_cost = set_src_cost (gen_rtx_MULT (mode, fake_reg, fake_reg),
+			   mode, speed);
   if (choose_mult_variant (mode, coeff, &algorithm, &variant, max_cost))
     return algorithm.cost.cost;
   else
@@ -3704,7 +3710,7 @@ expand_smod_pow2 (machine_mode mode, rtx op0, HOST_WIDE_INT d)
 
 	  temp = gen_rtx_LSHIFTRT (mode, result, shift);
 	  if (optab_handler (lshr_optab, mode) == CODE_FOR_nothing
-	      || (set_src_cost (temp, optimize_insn_for_speed_p ())
+	      || (set_src_cost (temp, mode, optimize_insn_for_speed_p ())
 		  > COSTS_N_INSNS (2)))
 	    {
 	      temp = expand_binop (mode, xor_optab, op0, signmask,
@@ -5508,7 +5514,7 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
 	  /* For the reverse comparison, use either an addition or a XOR.  */
           if (want_add
-	      && rtx_cost (GEN_INT (normalizep), PLUS, 1,
+	      && rtx_cost (GEN_INT (normalizep), mode, PLUS, 1,
 			   optimize_insn_for_speed_p ()) == 0)
 	    {
 	      tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
@@ -5519,7 +5525,7 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
 				     target, 0, OPTAB_WIDEN);
 	    }
           else if (!want_add
-	           && rtx_cost (trueval, XOR, 1,
+	           && rtx_cost (trueval, mode, XOR, 1,
 			        optimize_insn_for_speed_p ()) == 0)
 	    {
 	      tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
@@ -5611,7 +5617,7 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
       /* Again, for the reverse comparison, use either an addition or a XOR.  */
       if (want_add
-	  && rtx_cost (GEN_INT (normalizep), PLUS, 1,
+	  && rtx_cost (GEN_INT (normalizep), mode, PLUS, 1,
 		       optimize_insn_for_speed_p ()) == 0)
 	{
 	  tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
@@ -5622,7 +5628,7 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
 				target, 0, OPTAB_WIDEN);
 	}
       else if (!want_add
-	       && rtx_cost (trueval, XOR, 1,
+	       && rtx_cost (trueval, mode, XOR, 1,
 			    optimize_insn_for_speed_p ()) == 0)
 	{
 	  tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
diff --git a/gcc/expr.c b/gcc/expr.c
index 4eb1ab3..cbde497 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -3659,9 +3659,9 @@ compress_float_constant (rtx x, rtx y)
   REAL_VALUE_FROM_CONST_DOUBLE (r, y);
 
   if (targetm.legitimate_constant_p (dstmode, y))
-    oldcost = set_src_cost (y, speed);
+    oldcost = set_src_cost (y, orig_srcmode, speed);
   else
-    oldcost = set_src_cost (force_const_mem (dstmode, y), speed);
+    oldcost = set_src_cost (force_const_mem (dstmode, y), dstmode, speed);
 
   for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
        srcmode != orig_srcmode;
@@ -3690,7 +3690,7 @@ compress_float_constant (rtx x, rtx y)
 	    continue;
 	  /* This is valid, but may not be cheaper than the original. */
 	  newcost = set_src_cost (gen_rtx_FLOAT_EXTEND (dstmode, trunc_y),
-				  speed);
+				  dstmode, speed);
 	  if (oldcost < newcost)
 	    continue;
 	}
@@ -3699,7 +3699,7 @@ compress_float_constant (rtx x, rtx y)
 	  trunc_y = force_const_mem (srcmode, trunc_y);
 	  /* This is valid, but may not be cheaper than the original. */
 	  newcost = set_src_cost (gen_rtx_FLOAT_EXTEND (dstmode, trunc_y),
-				  speed);
+				  dstmode, speed);
 	  if (oldcost < newcost)
 	    continue;
 	  trunc_y = validize_mem (trunc_y);
diff --git a/gcc/fwprop.c b/gcc/fwprop.c
index b62ad3f..ef43ff3 100644
--- a/gcc/fwprop.c
+++ b/gcc/fwprop.c
@@ -411,7 +411,8 @@ should_replace_address (rtx old_rtx, rtx new_rtx, machine_mode mode,
      eliminating the most insns without additional costs, and it
      is the same that cse.c used to do.  */
   if (gain == 0)
-    gain = set_src_cost (new_rtx, speed) - set_src_cost (old_rtx, speed);
+    gain = (set_src_cost (new_rtx, VOIDmode, speed)
+	    - set_src_cost (old_rtx, VOIDmode, speed));
 
   return (gain > 0);
 }
@@ -959,7 +960,7 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx_insn *def_insn,
      multiple sets.  If so, assume the cost of the new instruction is
      not greater than the old one.  */
   if (set)
-    old_cost = set_src_cost (SET_SRC (set), speed);
+    old_cost = set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)), speed);
   if (dump_file)
     {
       fprintf (dump_file, "\nIn insn %d, replacing\n ", INSN_UID (insn));
@@ -980,7 +981,8 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx_insn *def_insn,
 
   else if (DF_REF_TYPE (use) == DF_REF_REG_USE
 	   && set
-	   && set_src_cost (SET_SRC (set), speed) > old_cost)
+	   && (set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)), speed)
+	       > old_cost))
     {
       if (dump_file)
 	fprintf (dump_file, "Changes to insn %d not profitable\n",
diff --git a/gcc/gcse.c b/gcc/gcse.c
index f1d3af9..144fa9f 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -474,7 +474,6 @@ static void hash_scan_insn (rtx_insn *, struct gcse_hash_table_d *);
 static void hash_scan_set (rtx, rtx_insn *, struct gcse_hash_table_d *);
 static void hash_scan_clobber (rtx, rtx_insn *, struct gcse_hash_table_d *);
 static void hash_scan_call (rtx, rtx_insn *, struct gcse_hash_table_d *);
-static int want_to_gcse_p (rtx, int *);
 static int oprs_unchanged_p (const_rtx, const rtx_insn *, int);
 static int oprs_anticipatable_p (const_rtx, const rtx_insn *);
 static int oprs_available_p (const_rtx, const rtx_insn *);
@@ -765,7 +764,7 @@ static basic_block current_bb;
    GCSE.  */
 
 static int
-want_to_gcse_p (rtx x, int *max_distance_ptr)
+want_to_gcse_p (rtx x, machine_mode mode, int *max_distance_ptr)
 {
 #ifdef STACK_REGS
   /* On register stack architectures, don't GCSE constants from the
@@ -816,7 +815,7 @@ want_to_gcse_p (rtx x, int *max_distance_ptr)
 
 	  gcc_assert (!optimize_function_for_speed_p (cfun)
 		      && optimize_function_for_size_p (cfun));
-	  cost = set_src_cost (x, 0);
+	  cost = set_src_cost (x, mode, 0);
 
 	  if (cost < COSTS_N_INSNS (GCSE_UNRESTRICTED_COST))
 	    {
@@ -1273,7 +1272,7 @@ hash_scan_set (rtx set, rtx_insn *insn, struct gcse_hash_table_d *table)
       if (note != 0
 	  && REG_NOTE_KIND (note) == REG_EQUAL
 	  && !REG_P (src)
-	  && want_to_gcse_p (XEXP (note, 0), NULL))
+	  && want_to_gcse_p (XEXP (note, 0), GET_MODE (dest), NULL))
 	src = XEXP (note, 0), set = gen_rtx_SET (dest, src);
 
       /* Only record sets of pseudo-regs in the hash table.  */
@@ -1287,7 +1286,7 @@ hash_scan_set (rtx set, rtx_insn *insn, struct gcse_hash_table_d *table)
 	     can't do the same thing at the rtl level.  */
 	  && !can_throw_internal (insn)
 	  /* Is SET_SRC something we want to gcse?  */
-	  && want_to_gcse_p (src, &max_distance)
+	  && want_to_gcse_p (src, GET_MODE (dest), &max_distance)
 	  /* Don't CSE a nop.  */
 	  && ! set_noop_p (set)
 	  /* Don't GCSE if it has attached REG_EQUIV note.
@@ -1319,43 +1318,42 @@ hash_scan_set (rtx set, rtx_insn *insn, struct gcse_hash_table_d *table)
      the REG stored in that memory. This makes it possible to remove
      redundant loads from due to stores to the same location.  */
   else if (flag_gcse_las && REG_P (src) && MEM_P (dest))
-      {
-        unsigned int regno = REGNO (src);
-	int max_distance = 0;
-
-	/* Only record sets of pseudo-regs in the hash table.  */
-        if (regno >= FIRST_PSEUDO_REGISTER
-	   /* Don't GCSE something if we can't do a reg/reg copy.  */
-	   && can_copy_p (GET_MODE (src))
-	   /* GCSE commonly inserts instruction after the insn.  We can't
-	      do that easily for EH edges so disable GCSE on these for now.  */
-	   && !can_throw_internal (insn)
-	   /* Is SET_DEST something we want to gcse?  */
-	   && want_to_gcse_p (dest, &max_distance)
-	   /* Don't CSE a nop.  */
-	   && ! set_noop_p (set)
-	   /* Don't GCSE if it has attached REG_EQUIV note.
-	      At this point this only function parameters should have
-	      REG_EQUIV notes and if the argument slot is used somewhere
-	      explicitly, it means address of parameter has been taken,
-	      so we should not extend the lifetime of the pseudo.  */
-	   && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0
-	       || ! MEM_P (XEXP (note, 0))))
-             {
-               /* Stores are never anticipatable.  */
-               int antic_p = 0;
-	       /* An expression is not available if its operands are
-	          subsequently modified, including this insn.  It's also not
-	          available if this is a branch, because we can't insert
-	          a set after the branch.  */
-               int avail_p = oprs_available_p (dest, insn)
-			     && ! JUMP_P (insn);
-
-	       /* Record the memory expression (DEST) in the hash table.  */
-	       insert_expr_in_table (dest, GET_MODE (dest), insn,
-				     antic_p, avail_p, max_distance, table);
-             }
-      }
+    {
+      unsigned int regno = REGNO (src);
+      int max_distance = 0;
+
+      /* Only record sets of pseudo-regs in the hash table.  */
+      if (regno >= FIRST_PSEUDO_REGISTER
+	  /* Don't GCSE something if we can't do a reg/reg copy.  */
+	  && can_copy_p (GET_MODE (src))
+	  /* GCSE commonly inserts instruction after the insn.  We can't
+	     do that easily for EH edges so disable GCSE on these for now.  */
+	  && !can_throw_internal (insn)
+	  /* Is SET_DEST something we want to gcse?  */
+	  && want_to_gcse_p (dest, GET_MODE (dest), &max_distance)
+	  /* Don't CSE a nop.  */
+	  && ! set_noop_p (set)
+	  /* Don't GCSE if it has attached REG_EQUIV note.
+	     At this point this only function parameters should have
+	     REG_EQUIV notes and if the argument slot is used somewhere
+	     explicitly, it means address of parameter has been taken,
+	     so we should not extend the lifetime of the pseudo.  */
+	  && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0
+	      || ! MEM_P (XEXP (note, 0))))
+	{
+	  /* Stores are never anticipatable.  */
+	  int antic_p = 0;
+	  /* An expression is not available if its operands are
+	     subsequently modified, including this insn.  It's also not
+	     available if this is a branch, because we can't insert
+	     a set after the branch.  */
+	  int avail_p = oprs_available_p (dest, insn) && ! JUMP_P (insn);
+
+	  /* Record the memory expression (DEST) in the hash table.  */
+	  insert_expr_in_table (dest, GET_MODE (dest), insn,
+				antic_p, avail_p, max_distance, table);
+	}
+    }
 }
 
 static void
diff --git a/gcc/hooks.c b/gcc/hooks.c
index 92a2141..0fb9add 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -333,12 +333,12 @@ hook_bool_uintp_uintp_false (unsigned int *a ATTRIBUTE_UNUSED,
 }
 
 bool
-hook_bool_rtx_int_int_int_intp_bool_false (rtx a ATTRIBUTE_UNUSED,
-					   int b ATTRIBUTE_UNUSED,
-					   int c ATTRIBUTE_UNUSED,
-					   int d ATTRIBUTE_UNUSED,
-					   int *e ATTRIBUTE_UNUSED,
-					   bool speed_p ATTRIBUTE_UNUSED)
+hook_bool_rtx_mode_int_int_intp_bool_false (rtx a ATTRIBUTE_UNUSED,
+					    machine_mode b ATTRIBUTE_UNUSED,
+					    int c ATTRIBUTE_UNUSED,
+					    int d ATTRIBUTE_UNUSED,
+					    int *e ATTRIBUTE_UNUSED,
+					    bool speed_p ATTRIBUTE_UNUSED)
 {
   return false;
 }
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 3d69f6d..c3d4bd3 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -55,8 +55,8 @@ extern bool hook_bool_rtx_insn_true (rtx_insn *);
 extern bool hook_bool_rtx_false (rtx);
 extern bool hook_bool_rtx_insn_int_false (rtx_insn *, int);
 extern bool hook_bool_uintp_uintp_false (unsigned int *, unsigned int *);
-extern bool hook_bool_rtx_int_int_int_intp_bool_false (rtx, int, int, int,
-						       int *, bool);
+extern bool hook_bool_rtx_mode_int_int_intp_bool_false (rtx, machine_mode,
+							int, int, int *, bool);
 extern bool hook_bool_tree_tree_false (tree, tree);
 extern bool hook_bool_tree_tree_true (tree, tree);
 extern bool hook_bool_tree_bool_false (tree, bool);
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 648965c..ca1f3a5 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -2238,7 +2238,7 @@ noce_try_sign_mask (struct noce_if_info *if_info)
      && (if_info->insn_b == NULL_RTX
 	 || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb));
   if (!(t_unconditional
-	|| (set_src_cost (t, optimize_bb_for_speed_p (if_info->test_bb))
+	|| (set_src_cost (t, mode, optimize_bb_for_speed_p (if_info->test_bb))
 	    < COSTS_N_INSNS (2))))
     return FALSE;
 
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c
index 38303f5..b5de0d7 100644
--- a/gcc/loop-doloop.c
+++ b/gcc/loop-doloop.c
@@ -662,7 +662,7 @@ doloop_optimize (struct loop *loop)
 
   max_cost
     = COSTS_N_INSNS (PARAM_VALUE (PARAM_MAX_ITERATIONS_COMPUTATION_COST));
-  if (set_src_cost (desc->niter_expr, optimize_loop_for_speed_p (loop))
+  if (set_src_cost (desc->niter_expr, mode, optimize_loop_for_speed_p (loop))
       > max_cost)
     {
       if (dump_file)
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 92d8e4c..d4e275b 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -737,7 +737,8 @@ create_new_invariant (struct def *def, rtx_insn *insn, bitmap depends_on,
     }
   else
     {
-      inv->cost = set_src_cost (SET_SRC (set), speed);
+      inv->cost = set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
+				speed);
       inv->cheap_address = false;
     }
 
diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
index bacb65f..eeff1aa 100644
--- a/gcc/lower-subreg.c
+++ b/gcc/lower-subreg.c
@@ -145,7 +145,7 @@ shift_cost (bool speed_p, struct cost_rtxes *rtxes, enum rtx_code code,
   PUT_MODE (rtxes->shift, mode);
   PUT_MODE (rtxes->source, mode);
   XEXP (rtxes->shift, 1) = GEN_INT (op1);
-  return set_src_cost (rtxes->shift, speed_p);
+  return set_src_cost (rtxes->shift, mode, speed_p);
 }
 
 /* For each X in the range [0, BITS_PER_WORD), set SPLITTING[X]
@@ -249,7 +249,7 @@ compute_costs (bool speed_p, struct cost_rtxes *rtxes)
       /* The only case here to check to see if moving the upper part with a
 	 zero is cheaper than doing the zext itself.  */
       PUT_MODE (rtxes->source, word_mode);
-      zext_cost = set_src_cost (rtxes->zext, speed_p);
+      zext_cost = set_src_cost (rtxes->zext, twice_word_mode, speed_p);
 
       if (LOG_COSTS)
 	fprintf (stderr, "%s %s: original cost %d, split cost %d + %d\n",
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 94739a9..f7efe23 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1368,8 +1368,8 @@ avoid_expensive_constant (machine_mode mode, optab binoptab,
   if (mode != VOIDmode
       && optimize
       && CONSTANT_P (x)
-      && (rtx_cost (x, optab_to_code (binoptab), opn, speed)
-	  > set_src_cost (x, speed)))
+      && (rtx_cost (x, mode, optab_to_code (binoptab), opn, speed)
+	  > set_src_cost (x, mode, speed)))
     {
       if (CONST_INT_P (x))
 	{
@@ -4050,12 +4050,12 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
 
   /* If we are optimizing, force expensive constants into a register.  */
   if (CONSTANT_P (x) && optimize
-      && (rtx_cost (x, COMPARE, 0, optimize_insn_for_speed_p ())
+      && (rtx_cost (x, mode, COMPARE, 0, optimize_insn_for_speed_p ())
           > COSTS_N_INSNS (1)))
     x = force_reg (mode, x);
 
   if (CONSTANT_P (y) && optimize
-      && (rtx_cost (y, COMPARE, 1, optimize_insn_for_speed_p ())
+      && (rtx_cost (y, mode, COMPARE, 1, optimize_insn_for_speed_p ())
           > COSTS_N_INSNS (1)))
     y = force_reg (mode, y);
 
@@ -8644,7 +8644,7 @@ lshift_cheap_p (bool speed_p)
     {
       rtx reg = gen_raw_REG (word_mode, 10000);
       int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
-			       speed_p);
+			       word_mode, speed_p);
       cheap[speed_p] = cost < COSTS_N_INSNS (3);
       init[speed_p] = true;
     }
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 704428a..667038f 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -299,7 +299,7 @@ reload_cse_simplify_set (rtx set, rtx_insn *insn)
     old_cost = register_move_cost (GET_MODE (src),
 				   REGNO_REG_CLASS (REGNO (src)), dclass);
   else
-    old_cost = set_src_cost (src, speed);
+    old_cost = set_src_cost (src, GET_MODE (SET_DEST (set)), speed);
 
   for (l = val->locs; l; l = l->next)
     {
@@ -334,7 +334,7 @@ reload_cse_simplify_set (rtx set, rtx_insn *insn)
 	      this_rtx = immed_wide_int_const (result, word_mode);
 	    }
 #endif
-	  this_cost = set_src_cost (this_rtx, speed);
+	  this_cost = set_src_cost (this_rtx, GET_MODE (SET_DEST (set)), speed);
 	}
       else if (REG_P (this_rtx))
 	{
@@ -342,7 +342,7 @@ reload_cse_simplify_set (rtx set, rtx_insn *insn)
 	  if (extend_op != UNKNOWN)
 	    {
 	      this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
-	      this_cost = set_src_cost (this_rtx, speed);
+	      this_cost = set_src_cost (this_rtx, word_mode, speed);
 	    }
 	  else
 #endif
@@ -585,10 +585,10 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
 		      && TEST_BIT (preferred, j)
 		      && reg_fits_class_p (testreg, rclass, 0, mode)
 		      && (!CONST_INT_P (recog_data.operand[i])
-			  || (set_src_cost (recog_data.operand[i],
+			  || (set_src_cost (recog_data.operand[i], mode,
 					    optimize_bb_for_speed_p
 					     (BLOCK_FOR_INSN (insn)))
-			      > set_src_cost (testreg,
+			      > set_src_cost (testreg, mode,
 					      optimize_bb_for_speed_p
 					       (BLOCK_FOR_INSN (insn))))))
 		    {
@@ -921,12 +921,13 @@ try_replace_in_use (struct reg_use *use, rtx reg, rtx src)
 	  && CONSTANT_P (XEXP (SET_SRC (new_set), 1)))
 	{
 	  rtx new_src;
-	  int old_cost = set_src_cost (SET_SRC (new_set), speed);
+	  machine_mode mode = GET_MODE (SET_DEST (new_set));
+	  int old_cost = set_src_cost (SET_SRC (new_set), mode, speed);
 
 	  gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg));
 	  new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src);
 
-	  if (set_src_cost (new_src, speed) <= old_cost
+	  if (set_src_cost (new_src, mode, speed) <= old_cost
 	      && validate_change (use_insn, &SET_SRC (new_set),
 				  new_src, 0))
 	    return true;
@@ -2024,7 +2025,7 @@ reload_cse_move2add (rtx_insn *first)
 
 			  get_full_set_rtx_cost (set, &oldcst);
 			  SET_SRC (set) = tem;
-			  get_full_set_src_cost (tem, &newcst);
+			  get_full_set_src_cost (tem, GET_MODE (reg), &newcst);
 			  SET_SRC (set) = old_src;
 			  costs_add_n_insns (&oldcst, 1);
 
diff --git a/gcc/reload1.c b/gcc/reload1.c
index a86084a..728dfb0 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -1647,7 +1647,9 @@ calculate_elim_costs_all_insns (void)
 		    {
 		      rtx t = eliminate_regs_1 (SET_SRC (set), VOIDmode, insn,
 						false, true);
-		      int cost = set_src_cost (t, optimize_bb_for_speed_p (bb));
+		      machine_mode mode = GET_MODE (SET_DEST (set));
+		      int cost = set_src_cost (t, mode,
+					       optimize_bb_for_speed_p (bb));
 		      int freq = REG_FREQ_FROM_BB (bb);
 
 		      reg_equiv_init_cost[regno] = cost * freq;
@@ -2519,7 +2521,8 @@ note_reg_elim_costly (const_rtx x, rtx insn)
 	{
 	  rtx t = reg_equiv_invariant (REGNO (x));
 	  rtx new_rtx = eliminate_regs_1 (t, Pmode, insn, true, true);
-	  int cost = set_src_cost (new_rtx, optimize_bb_for_speed_p (elim_bb));
+	  int cost = set_src_cost (new_rtx, Pmode,
+				   optimize_bb_for_speed_p (elim_bb));
 	  int freq = REG_FREQ_FROM_BB (elim_bb);
 
 	  if (cost != 0)
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index a5731e8..60acdb4 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -2094,8 +2094,8 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
 	      coeff = immed_wide_int_const (coeff0 + coeff1, mode);
 
 	      tem = simplify_gen_binary (MULT, mode, lhs, coeff);
-	      return set_src_cost (tem, speed) <= set_src_cost (orig, speed)
-		? tem : 0;
+	      return (set_src_cost (tem, mode, speed)
+		      <= set_src_cost (orig, mode, speed) ? tem : 0);
 	    }
 	}
 
@@ -2269,8 +2269,8 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
 	      coeff = immed_wide_int_const (coeff0 + negcoeff1, mode);
 
 	      tem = simplify_gen_binary (MULT, mode, lhs, coeff);
-	      return set_src_cost (tem, speed) <= set_src_cost (orig, speed)
-		? tem : 0;
+	      return (set_src_cost (tem, mode, speed)
+		      <= set_src_cost (orig, mode, speed) ? tem : 0);
 	    }
 	}
 
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index cb5f054..25d53ed 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -3293,7 +3293,7 @@ computation_cost (tree expr, bool speed)
     cost += address_cost (XEXP (rslt, 0), TYPE_MODE (type),
 			  TYPE_ADDR_SPACE (type), speed);
   else if (!REG_P (rslt))
-    cost += set_src_cost (rslt, speed);
+    cost += set_src_cost (rslt, TYPE_MODE (type), speed);
 
   return cost;
 }
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 3eb098e..9437286 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -2547,10 +2547,10 @@ optimize_range_tests_to_bit_test (enum tree_code opcode, int first, int length,
 						      GEN_INT (-m)), speed_p);
 	      rtx r = immed_wide_int_const (mask, word_mode);
 	      cost_diff += set_src_cost (gen_rtx_AND (word_mode, reg, r),
-					 speed_p);
+					 word_mode, speed_p);
 	      r = immed_wide_int_const (wi::lshift (mask, m), word_mode);
 	      cost_diff -= set_src_cost (gen_rtx_AND (word_mode, reg, r),
-					 speed_p);
+					 word_mode, speed_p);
 	      if (cost_diff > 0)
 		{
 		  mask = wi::lshift (mask, m);
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 3c1ca2c..a18b749 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -377,9 +377,11 @@ emit_case_bit_tests (gswitch *swtch, tree index_expr,
       for (i = 0; i < count; i++)
 	{
 	  rtx r = immed_wide_int_const (test[i].mask, word_mode);
-	  cost_diff += set_src_cost (gen_rtx_AND (word_mode, reg, r), speed_p);
+	  cost_diff += set_src_cost (gen_rtx_AND (word_mode, reg, r),
+				     word_mode, speed_p);
 	  r = immed_wide_int_const (wi::lshift (test[i].mask, m), word_mode);
-	  cost_diff -= set_src_cost (gen_rtx_AND (word_mode, reg, r), speed_p);
+	  cost_diff -= set_src_cost (gen_rtx_AND (word_mode, reg, r),
+				     word_mode, speed_p);
 	}
       if (cost_diff > 0)
 	{
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 17bae08..c9921c9 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -5180,7 +5180,7 @@ aarch64_shift_p (enum rtx_code code)
    operands where needed.  */
 
 static int
-aarch64_rtx_mult_cost (rtx x, int code, int outer, bool speed)
+aarch64_rtx_mult_cost (rtx x, enum rtx_code code, int outer, bool speed)
 {
   rtx op0, op1;
   const struct cpu_cost_table *extra_cost
@@ -5231,7 +5231,7 @@ aarch64_rtx_mult_cost (rtx x, int code, int outer, bool speed)
 	  if (is_extend)
 	    op0 = aarch64_strip_extend (op0);
 
-	  cost += rtx_cost (op0, GET_CODE (op0), 0, speed);
+	  cost += rtx_cost (op0, VOIDmode, code, 0, speed);
 
 	  return cost;
 	}
@@ -5251,8 +5251,8 @@ aarch64_rtx_mult_cost (rtx x, int code, int outer, bool speed)
 	  || (GET_CODE (op0) == SIGN_EXTEND
 	      && GET_CODE (op1) == SIGN_EXTEND))
 	{
-	  cost += rtx_cost (XEXP (op0, 0), MULT, 0, speed)
-		  + rtx_cost (XEXP (op1, 0), MULT, 1, speed);
+	  cost += rtx_cost (XEXP (op0, 0), VOIDmode, MULT, 0, speed);
+	  cost += rtx_cost (XEXP (op1, 0), VOIDmode, MULT, 1, speed);
 
 	  if (speed)
 	    {
@@ -5269,8 +5269,8 @@ aarch64_rtx_mult_cost (rtx x, int code, int outer, bool speed)
 
       /* This is either an integer multiply or a MADD.  In both cases
 	 we want to recurse and cost the operands.  */
-      cost += rtx_cost (op0, MULT, 0, speed)
-	      + rtx_cost (op1, MULT, 1, speed);
+      cost += rtx_cost (op0, mode, MULT, 0, speed);
+      cost += rtx_cost (op1, mode, MULT, 1, speed);
 
       if (speed)
 	{
@@ -5303,8 +5303,8 @@ aarch64_rtx_mult_cost (rtx x, int code, int outer, bool speed)
 	    cost += extra_cost->fp[mode == DFmode].mult;
 	}
 
-      cost += rtx_cost (op0, MULT, 0, speed)
-	      + rtx_cost (op1, MULT, 1, speed);
+      cost += rtx_cost (op0, mode, MULT, 0, speed);
+      cost += rtx_cost (op1, mode, MULT, 1, speed);
       return cost;
     }
 }
@@ -5328,7 +5328,7 @@ aarch64_address_cost (rtx x,
 	  /* This is a CONST or SYMBOL ref which will be split
 	     in a different way depending on the code model in use.
 	     Cost it through the generic infrastructure.  */
-	  int cost_symbol_ref = rtx_cost (x, MEM, 1, speed);
+	  int cost_symbol_ref = rtx_cost (x, Pmode, MEM, 1, speed);
 	  /* Divide through by the cost of one instruction to
 	     bring it to the same units as the address costs.  */
 	  cost_symbol_ref /= COSTS_N_INSNS (1);
@@ -5551,11 +5551,11 @@ aarch64_if_then_else_costs (rtx op0, rtx op1, rtx op2, int *cost, bool speed)
 		  /* TBZ/TBNZ/CBZ/CBNZ.  */
 		  if (GET_CODE (inner) == ZERO_EXTRACT)
 		    /* TBZ/TBNZ.  */
-		    *cost += rtx_cost (XEXP (inner, 0), ZERO_EXTRACT,
-			 	       0, speed);
-		else
-		  /* CBZ/CBNZ.  */
-		  *cost += rtx_cost (inner, cmpcode, 0, speed);
+		    *cost += rtx_cost (XEXP (inner, 0), VOIDmode,
+				       ZERO_EXTRACT, 0, speed);
+		  else
+		    /* CBZ/CBNZ.  */
+		    *cost += rtx_cost (inner, VOIDmode, cmpcode, 0, speed);
 
 	        return true;
 	      }
@@ -5579,8 +5579,8 @@ aarch64_if_then_else_costs (rtx op0, rtx op1, rtx op2, int *cost, bool speed)
           || (GET_CODE (op1) == PLUS && XEXP (op1, 1) == const1_rtx))
 	op1 = XEXP (op1, 0);
 
-      *cost += rtx_cost (op1, IF_THEN_ELSE, 1, speed);
-      *cost += rtx_cost (op2, IF_THEN_ELSE, 2, speed);
+      *cost += rtx_cost (op1, VOIDmode, IF_THEN_ELSE, 1, speed);
+      *cost += rtx_cost (op2, VOIDmode, IF_THEN_ELSE, 2, speed);
       return true;
     }
 
@@ -5591,13 +5591,13 @@ aarch64_if_then_else_costs (rtx op0, rtx op1, rtx op2, int *cost, bool speed)
 /* Calculate the cost of calculating X, storing it in *COST.  Result
    is true if the total cost of the operation has now been calculated.  */
 static bool
-aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
+aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 		   int param ATTRIBUTE_UNUSED, int *cost, bool speed)
 {
   rtx op0, op1, op2;
   const struct cpu_cost_table *extra_cost
     = aarch64_tune_params->insn_extra_cost;
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
 
   /* By default, assume that everything has equivalent cost to the
      cheapest instruction.  Any additional costs are applied as a delta
@@ -5632,12 +5632,12 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
 						     0, speed));
 	    }
 
-	  *cost += rtx_cost (op1, SET, 1, speed);
+	  *cost += rtx_cost (op1, mode, SET, 1, speed);
 	  return true;
 
 	case SUBREG:
 	  if (! REG_P (SUBREG_REG (op0)))
-	    *cost += rtx_cost (SUBREG_REG (op0), SET, 0, speed);
+	    *cost += rtx_cost (SUBREG_REG (op0), VOIDmode, SET, 0, speed);
 
 	  /* Fall through.  */
 	case REG:
@@ -5659,7 +5659,7 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
 	    }
           else
 	    /* Cost is just the cost of the RHS of the set.  */
-	    *cost += rtx_cost (op1, SET, 1, speed);
+	    *cost += rtx_cost (op1, mode, SET, 1, speed);
 	  return true;
 
 	case ZERO_EXTRACT:
@@ -5685,7 +5685,7 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
               /* BFM.  */
 	      if (speed)
 		*cost += extra_cost->alu.bfi;
-              *cost += rtx_cost (op1, (enum rtx_code) code, 1, speed);
+	      *cost += rtx_cost (op1, VOIDmode, (enum rtx_code) code, 1, speed);
             }
 
 	  return true;
@@ -5783,23 +5783,23 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
 	  return false;
 	}
 
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
-       {
+      if (GET_MODE_CLASS (mode) == MODE_INT)
+	{
           if (GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMPARE
               || GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMM_COMPARE)
             {
               /* CSETM.  */
-              *cost += rtx_cost (XEXP (op0, 0), NEG, 0, speed);
+	      *cost += rtx_cost (XEXP (op0, 0), VOIDmode, NEG, 0, speed);
               return true;
             }
 
 	  /* Cost this as SUB wzr, X.  */
-          op0 = CONST0_RTX (GET_MODE (x));
+          op0 = CONST0_RTX (mode);
           op1 = XEXP (x, 0);
           goto cost_minus;
         }
 
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
         {
           /* Support (neg(fma...)) as a single instruction only if
              sign of zeros is unimportant.  This matches the decision
@@ -5807,7 +5807,7 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
           if (GET_CODE (op0) == FMA && !HONOR_SIGNED_ZEROS (GET_MODE (op0)))
             {
 	      /* FNMADD.  */
-              *cost = rtx_cost (op0, NEG, 0, speed);
+	      *cost = rtx_cost (op0, mode, NEG, 0, speed);
               return true;
             }
 	  if (speed)
@@ -5838,6 +5838,7 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
 	  && GET_CODE (op0) == AND)
 	{
 	  x = op0;
+	  mode = GET_MODE (op0);
 	  goto cost_logic;
 	}
 
@@ -5847,9 +5848,10 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
 	     needs encoding in the cost tables.  */
 
           /* CC_ZESWPmode supports zero extend for free.  */
-          if (GET_MODE (x) == CC_ZESWPmode && GET_CODE (op0) == ZERO_EXTEND)
+          if (mode == CC_ZESWPmode && GET_CODE (op0) == ZERO_EXTEND)
             op0 = XEXP (op0, 0);
 
+	  mode = GET_MODE (op0);
           /* ANDS.  */
           if (GET_CODE (op0) == AND)
             {
@@ -5877,8 +5879,8 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
 	      if (speed)
 		*cost += extra_cost->alu.arith;
 
-              *cost += rtx_cost (op0, COMPARE, 0, speed);
-	      *cost += rtx_cost (XEXP (op1, 0), NEG, 1, speed);
+	      *cost += rtx_cost (op0, mode, COMPARE, 0, speed);
+	      *cost += rtx_cost (XEXP (op1, 0), mode, NEG, 1, speed);
               return true;
             }
 
@@ -5905,7 +5907,7 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
 
           if (CONST_DOUBLE_P (op1) && aarch64_float_const_zero_rtx_p (op1))
             {
-              *cost += rtx_cost (op0, COMPARE, 0, speed);
+	      *cost += rtx_cost (op0, VOIDmode, COMPARE, 0, speed);
               /* FCMP supports constant 0.0 for no extra cost. */
               return true;
             }
@@ -5934,7 +5936,7 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
 	op1 = XEXP (x, 1);
 
 cost_minus:
-	*cost += rtx_cost (op0, MINUS, 0, speed);
+	*cost += rtx_cost (op0, mode, MINUS, 0, speed);
 
 	/* Detect valid immediates.  */
 	if ((GET_MODE_CLASS (mode) == MODE_INT
@@ -5955,9 +5957,8 @@ cost_minus:
 	    if (speed)
 	      *cost += extra_cost->alu.extend_arith;
 
-	    *cost += rtx_cost (XEXP (XEXP (op1, 0), 0),
-			       (enum rtx_code) GET_CODE (op1),
-			       0, speed);
+	    *cost += rtx_cost (XEXP (XEXP (op1, 0), 0), VOIDmode,
+			       (enum rtx_code) GET_CODE (op1), 0, speed);
 	    return true;
 	  }
 
@@ -5974,7 +5975,7 @@ cost_minus:
 	    return true;
 	  }
 
-	*cost += rtx_cost (new_op1, MINUS, 1, speed);
+	*cost += rtx_cost (new_op1, VOIDmode, MINUS, 1, speed);
 
 	if (speed)
 	  {
@@ -6009,8 +6010,8 @@ cost_plus:
 	    || GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMM_COMPARE)
 	  {
 	    /* CSINC.  */
-	    *cost += rtx_cost (XEXP (op0, 0), PLUS, 0, speed);
-	    *cost += rtx_cost (op1, PLUS, 1, speed);
+	    *cost += rtx_cost (XEXP (op0, 0), mode, PLUS, 0, speed);
+	    *cost += rtx_cost (op1, mode, PLUS, 1, speed);
 	    return true;
 	  }
 
@@ -6018,7 +6019,7 @@ cost_plus:
 	    && CONST_INT_P (op1)
 	    && aarch64_uimm12_shift (INTVAL (op1)))
 	  {
-	    *cost += rtx_cost (op0, PLUS, 0, speed);
+	    *cost += rtx_cost (op0, mode, PLUS, 0, speed);
 
 	    if (speed)
 	      /* ADD (immediate).  */
@@ -6026,7 +6027,7 @@ cost_plus:
 	    return true;
 	  }
 
-	*cost += rtx_cost (op1, PLUS, 1, speed);
+	*cost += rtx_cost (op1, mode, PLUS, 1, speed);
 
 	/* Look for ADD (extended register).  */
         if (aarch64_rtx_arith_op_extract_p (op0, mode))
@@ -6034,9 +6035,8 @@ cost_plus:
 	    if (speed)
 	      *cost += extra_cost->alu.extend_arith;
 
-	    *cost += rtx_cost (XEXP (XEXP (op0, 0), 0),
-			       (enum rtx_code) GET_CODE (op0),
-			       0, speed);
+	    *cost += rtx_cost (XEXP (XEXP (op0, 0), 0), VOIDmode,
+			       (enum rtx_code) GET_CODE (op0), 0, speed);
 	    return true;
 	  }
 
@@ -6052,7 +6052,7 @@ cost_plus:
 	    return true;
 	  }
 
-	*cost += rtx_cost (new_op0, PLUS, 0, speed);
+	*cost += rtx_cost (new_op0, VOIDmode, PLUS, 0, speed);
 
 	if (speed)
 	  {
@@ -6104,8 +6104,8 @@ cost_plus:
 
       if (aarch64_extr_rtx_p (x, &op0, &op1))
         {
-          *cost += rtx_cost (op0, IOR, 0, speed)
-                   + rtx_cost (op1, IOR, 1, speed);
+	  *cost += rtx_cost (op0, mode, IOR, 0, speed);
+	  *cost += rtx_cost (op1, mode, IOR, 1, speed);
           if (speed)
             *cost += extra_cost->alu.shift;
 
@@ -6133,20 +6133,20 @@ cost_plus:
                                INTVAL (op1)) != 0)
         {
           /* This is a UBFM/SBFM.  */
-          *cost += rtx_cost (XEXP (op0, 0), ZERO_EXTRACT, 0, speed);
+	  *cost += rtx_cost (XEXP (op0, 0), mode, ZERO_EXTRACT, 0, speed);
 	  if (speed)
 	    *cost += extra_cost->alu.bfx;
           return true;
         }
 
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
+      if (GET_MODE_CLASS (mode) == MODE_INT)
 	{
 	  /* We possibly get the immediate for free, this is not
 	     modelled.  */
 	  if (CONST_INT_P (op1)
-	      && aarch64_bitmask_imm (INTVAL (op1), GET_MODE (x)))
+	      && aarch64_bitmask_imm (INTVAL (op1), mode))
 	    {
-	      *cost += rtx_cost (op0, (enum rtx_code) code, 0, speed);
+	      *cost += rtx_cost (op0, mode, (enum rtx_code) code, 0, speed);
 
 	      if (speed)
 		*cost += extra_cost->alu.logical;
@@ -6181,8 +6181,8 @@ cost_plus:
 		}
 
 	      /* In both cases we want to cost both operands.  */
-	      *cost += rtx_cost (new_op0, (enum rtx_code) code, 0, speed)
-		       + rtx_cost (op1, (enum rtx_code) code, 1, speed);
+	      *cost += rtx_cost (new_op0, mode, (enum rtx_code) code, 0, speed);
+	      *cost += rtx_cost (op1, mode, (enum rtx_code) code, 1, speed);
 
 	      return true;
 	    }
@@ -6203,7 +6203,7 @@ cost_plus:
       /* MVN-shifted-reg.  */
       if (op0 != x)
         {
-          *cost += rtx_cost (op0, (enum rtx_code) code, 0, speed);
+	  *cost += rtx_cost (op0, mode, (enum rtx_code) code, 0, speed);
 
           if (speed)
             *cost += extra_cost->alu.log_shift;
@@ -6219,8 +6219,8 @@ cost_plus:
           rtx newop1 = XEXP (op0, 1);
           rtx op0_stripped = aarch64_strip_shift (newop0);
 
-          *cost += rtx_cost (newop1, (enum rtx_code) code, 1, speed)
-                   + rtx_cost (op0_stripped, XOR, 0, speed);
+	  *cost += rtx_cost (newop1, mode, (enum rtx_code) code, 1, speed);
+	  *cost += rtx_cost (op0_stripped, mode, XOR, 0, speed);
 
           if (speed)
             {
@@ -6253,7 +6253,7 @@ cost_plus:
 	  && GET_MODE (op0) == SImode
 	  && outer == SET)
 	{
-	  int op_cost = rtx_cost (XEXP (x, 0), ZERO_EXTEND, 0, speed);
+	  int op_cost = rtx_cost (op0, VOIDmode, ZERO_EXTEND, 0, speed);
 
 	  if (!op_cost && speed)
 	    /* MOV.  */
@@ -6264,10 +6264,10 @@ cost_plus:
 
 	  return true;
 	}
-      else if (MEM_P (XEXP (x, 0)))
+      else if (MEM_P (op0))
 	{
 	  /* All loads can zero extend to any size for free.  */
-	  *cost = rtx_cost (XEXP (x, 0), ZERO_EXTEND, param, speed);
+	  *cost = rtx_cost (op0, VOIDmode, ZERO_EXTEND, param, speed);
 	  return true;
 	}
 
@@ -6337,7 +6337,7 @@ cost_plus:
               || GET_CODE (op0) == SIGN_EXTEND)
             op0 = XEXP (op0, 0);
 
-          *cost += rtx_cost (op0, ASHIFT, 0, speed);
+	  *cost += rtx_cost (op0, VOIDmode, ASHIFT, 0, speed);
           return true;
         }
       else
@@ -6376,7 +6376,7 @@ cost_plus:
 		*cost += extra_cost->alu.shift;
 	    }
 
-	  *cost += rtx_cost (op0, (enum rtx_code) code, 0, speed);
+	  *cost += rtx_cost (op0, mode, (enum rtx_code) code, 0, speed);
 	  return true;
 	}
       else
@@ -6446,7 +6446,7 @@ cost_plus:
 
       /* We can trust that the immediates used will be correct (there
 	 are no by-register forms), so we need only cost op0.  */
-      *cost += rtx_cost (XEXP (x, 0), (enum rtx_code) code, 0, speed);
+      *cost += rtx_cost (XEXP (x, 0), VOIDmode, (enum rtx_code) code, 0, speed);
       return true;
 
     case MULT:
@@ -6461,13 +6461,13 @@ cost_plus:
 	{
 	  if (VECTOR_MODE_P (mode))
 	    *cost += extra_cost->vect.alu;
-	  else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
-	    *cost += (extra_cost->mult[GET_MODE (x) == DImode].add
-		      + extra_cost->mult[GET_MODE (x) == DImode].idiv);
-	  else if (GET_MODE (x) == DFmode)
+	  else if (GET_MODE_CLASS (mode) == MODE_INT)
+	    *cost += (extra_cost->mult[mode == DImode].add
+		      + extra_cost->mult[mode == DImode].idiv);
+	  else if (mode == DFmode)
 	    *cost += (extra_cost->fp[1].mult
 		      + extra_cost->fp[1].div);
-	  else if (GET_MODE (x) == SFmode)
+	  else if (mode == SFmode)
 	    *cost += (extra_cost->fp[0].mult
 		      + extra_cost->fp[0].div);
 	}
@@ -6550,9 +6550,9 @@ cost_plus:
 
       /* If the remaining parameters are not registers,
          get the cost to put them into registers.  */
-      *cost += rtx_cost (op0, FMA, 0, speed);
-      *cost += rtx_cost (op1, FMA, 1, speed);
-      *cost += rtx_cost (op2, FMA, 2, speed);
+      *cost += rtx_cost (op0, mode, FMA, 0, speed);
+      *cost += rtx_cost (op1, mode, FMA, 1, speed);
+      *cost += rtx_cost (op2, mode, FMA, 2, speed);
       return true;
 
     case FLOAT:
@@ -6611,7 +6611,7 @@ cost_plus:
 	  else
 	    *cost += extra_cost->fp[GET_MODE (x) == DFmode].toint;
 	}
-      *cost += rtx_cost (x, (enum rtx_code) code, 0, speed);
+      *cost += rtx_cost (x, VOIDmode, (enum rtx_code) code, 0, speed);
       return true;
 
     case ABS:
@@ -6628,8 +6628,8 @@ cost_plus:
 	  /* FABD, which is analogous to FADD.  */
 	  if (GET_CODE (op0) == MINUS)
 	    {
-	      *cost += rtx_cost (XEXP (op0, 0), MINUS, 0, speed);
-			+ rtx_cost (XEXP (op0, 1), MINUS, 1, speed);
+	      *cost += rtx_cost (XEXP (op0, 0), mode, MINUS, 0, speed);
+	      *cost += rtx_cost (XEXP (op0, 1), mode, MINUS, 1, speed);
 	      if (speed)
 		*cost += extra_cost->fp[mode == DFmode].addsub;
 
@@ -6710,10 +6710,10 @@ cost_plus:
           /* UMULH/SMULH.  */
 	  if (speed)
 	    *cost += extra_cost->mult[mode == DImode].extend;
-          *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0),
-			     MULT, 0, speed);
-          *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0),
-			     MULT, 1, speed);
+	  *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0),
+			     mode, MULT, 0, speed);
+	  *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0),
+			     mode, MULT, 1, speed);
           return true;
         }
 
@@ -6733,10 +6733,10 @@ cost_plus:
    calculated for X.  This cost is stored in *COST.  Returns true
    if the total cost of X was calculated.  */
 static bool
-aarch64_rtx_costs_wrapper (rtx x, int code, int outer,
+aarch64_rtx_costs_wrapper (rtx x, machine_mode mode, int outer,
 		   int param, int *cost, bool speed)
 {
-  bool result = aarch64_rtx_costs (x, code, outer, param, cost, speed);
+  bool result = aarch64_rtx_costs (x, mode, outer, param, cost, speed);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 122f586..3e34e5e 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -1369,10 +1369,10 @@ alpha_legitimize_reload_address (rtx x,
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-alpha_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
+alpha_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total,
 		 bool speed)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   bool float_mode_p = FLOAT_MODE_P (mode);
   const struct alpha_rtx_cost_data *cost_data;
 
@@ -1437,9 +1437,9 @@ alpha_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
       else if (GET_CODE (XEXP (x, 0)) == MULT
 	       && const48_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
 	{
-	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0),
+	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0), mode,
 			      (enum rtx_code) outer_code, opno, speed)
-		    + rtx_cost (XEXP (x, 1),
+		    + rtx_cost (XEXP (x, 1), mode,
 				(enum rtx_code) outer_code, opno, speed)
 		    + COSTS_N_INSNS (1));
 	  return true;
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index d09520f..4ee3d1a 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -4115,9 +4115,11 @@ static void arc_file_start (void)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-	       int *total, bool speed)
+arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
+	       int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       /* Small integers are as cheap as registers.  */
@@ -4209,7 +4211,8 @@ arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	  if (CONSTANT_P (XEXP (x, 0)))
 	    {
 	      *total += (COSTS_N_INSNS (2)
-			 + rtx_cost (XEXP (x, 1), (enum rtx_code) code, 0, speed));
+			 + rtx_cost (XEXP (x, 1), mode, (enum rtx_code) code,
+				     0, speed));
 	      return true;
 	    }
 	  *total = COSTS_N_INSNS (1);
@@ -4251,8 +4254,8 @@ arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       if (GET_CODE (XEXP (x, 0)) == MULT
 	  && _2_4_8_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
 	{
-	  *total += (rtx_cost (XEXP (x, 1), PLUS, 0, speed)
-		     + rtx_cost (XEXP (XEXP (x, 0), 0), PLUS, 1, speed));
+	  *total += (rtx_cost (XEXP (x, 1), mode, PLUS, 0, speed)
+		     + rtx_cost (XEXP (XEXP (x, 0), 0), mode, PLUS, 1, speed));
 	  return true;
 	}
       return false;
@@ -4260,8 +4263,8 @@ arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       if (GET_CODE (XEXP (x, 1)) == MULT
 	  && _2_4_8_operand (XEXP (XEXP (x, 1), 1), VOIDmode))
 	{
-	  *total += (rtx_cost (XEXP (x, 0), PLUS, 0, speed)
-		     + rtx_cost (XEXP (XEXP (x, 1), 0), PLUS, 1, speed));
+	  *total += (rtx_cost (XEXP (x, 0), mode, PLUS, 0, speed)
+		     + rtx_cost (XEXP (XEXP (x, 1), 0), mode, PLUS, 1, speed));
 	  return true;
 	}
       return false;
@@ -4276,15 +4279,16 @@ arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	    /* btst / bbit0 / bbit1:
 	       Small integers and registers are free; everything else can
 	       be put in a register.  */
-	    *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
-		      + rtx_cost (XEXP (op0, 2), SET, 1, speed));
+	    mode = GET_MODE (XEXP (op0, 0));
+	    *total = (rtx_cost (XEXP (op0, 0), mode, SET, 1, speed)
+		      + rtx_cost (XEXP (op0, 2), mode, SET, 1, speed));
 	    return true;
 	  }
 	if (GET_CODE (op0) == AND && op1 == const0_rtx
 	    && satisfies_constraint_C1p (XEXP (op0, 1)))
 	  {
 	    /* bmsk.f */
-	    *total = rtx_cost (XEXP (op0, 0), SET, 1, speed);
+	    *total = rtx_cost (XEXP (op0, 0), VOIDmode, SET, 1, speed);
 	    return true;
 	  }
 	/* add.f  */
@@ -4293,8 +4297,9 @@ arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	    /* op0 might be constant, the inside of op1 is rather
 	       unlikely to be so.  So swapping the operands might lower
 	       the cost.  */
-	    *total = (rtx_cost (op0, PLUS, 1, speed)
-		      + rtx_cost (XEXP (op1, 0), PLUS, 0, speed));
+	    mode = GET_MODE (op0);
+	    *total = (rtx_cost (op0, mode, PLUS, 1, speed)
+		      + rtx_cost (XEXP (op1, 0), mode, PLUS, 0, speed));
 	  }
 	return false;
       }
@@ -4309,18 +4314,19 @@ arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	     be put in a register.  */
 	  rtx op0 = XEXP (x, 0);
 
-	  *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
-		    + rtx_cost (XEXP (op0, 2), SET, 1, speed));
+	  mode = GET_MODE (XEXP (op0, 0));
+	  *total = (rtx_cost (XEXP (op0, 0), mode, SET, 1, speed)
+		    + rtx_cost (XEXP (op0, 2), mode, SET, 1, speed));
 	  return true;
 	}
       /* Fall through.  */
     /* scc_insn expands into two insns.  */
     case GTU: case GEU: case LEU:
-      if (GET_MODE (x) == SImode)
+      if (mode == SImode)
 	*total += COSTS_N_INSNS (1);
       return false;
     case LTU: /* might use adc.  */
-      if (GET_MODE (x) == SImode)
+      if (mode == SImode)
 	*total += COSTS_N_INSNS (1) - 1;
       return false;
     default:
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index d794fc0..22c4104 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -189,7 +189,7 @@ static bool arm_slowmul_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, boo
 static bool arm_fastmul_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
 static bool arm_xscale_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
 static bool arm_9e_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
-static bool arm_rtx_costs (rtx, int, int, int, int *, bool);
+static bool arm_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int arm_address_cost (rtx, machine_mode, addr_space_t, bool);
 static int arm_register_move_cost (machine_mode, reg_class_t, reg_class_t);
 static int arm_memory_move_cost (machine_mode, reg_class_t, bool);
@@ -8302,7 +8302,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
       if (REG_P (XEXP (x, 1)))
 	*total = COSTS_N_INSNS (1); /* Need to subtract from 32 */
       else if (!CONST_INT_P (XEXP (x, 1)))
-	*total = rtx_cost (XEXP (x, 1), code, 1, speed);
+	*total = rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 
       /* Fall through */
     case ROTATERT:
@@ -8314,7 +8314,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 
       /* Fall through */
     case ASHIFT: case LSHIFTRT: case ASHIFTRT:
-      *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+      *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
       if (mode == DImode)
 	{
 	  *total += COSTS_N_INSNS (3);
@@ -8337,14 +8337,14 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	  if (CONST_INT_P (XEXP (x, 0))
 	      && const_ok_for_arm (INTVAL (XEXP (x, 0))))
 	    {
-	      *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	      *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	      return true;
 	    }
 
 	  if (CONST_INT_P (XEXP (x, 1))
 	      && const_ok_for_arm (INTVAL (XEXP (x, 1))))
 	    {
-	      *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+	      *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 	      return true;
 	    }
 
@@ -8361,14 +8361,14 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	      if (CONST_DOUBLE_P (XEXP (x, 0))
 		  && arm_const_double_rtx (XEXP (x, 0)))
 		{
-		  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+		  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 		  return true;
 		}
 
 	      if (CONST_DOUBLE_P (XEXP (x, 1))
 		  && arm_const_double_rtx (XEXP (x, 1)))
 		{
-		  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+		  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 		  return true;
 		}
 
@@ -8382,7 +8382,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
       if (CONST_INT_P (XEXP (x, 0))
 	  && const_ok_for_arm (INTVAL (XEXP (x, 0))))
 	{
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	  return true;
 	}
 
@@ -8391,8 +8391,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	  || subcode == LSHIFTRT
 	  || subcode == ROTATE || subcode == ROTATERT)
 	{
-	  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 1), 0), subcode, 0, speed);
+	  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 1), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
@@ -8400,23 +8400,24 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
       if (GET_CODE (XEXP (x, 0)) == MULT
 	  && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
 	{
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), code, 0, speed);
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, code, 0, speed);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	  return true;
 	}
 
       if (subcode == MULT
 	  && power_of_two_operand (XEXP (XEXP (x, 1), 1), SImode))
 	{
-	  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 1), 0), subcode, 0, speed);
+	  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 1), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
       if (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == RTX_COMPARE
 	  || GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == RTX_COMM_COMPARE)
 	{
-	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, speed);
 	  if (REG_P (XEXP (XEXP (x, 1), 0))
 	      && REGNO (XEXP (XEXP (x, 1), 0)) != CC_REGNUM)
 	    *total += COSTS_N_INSNS (1);
@@ -8432,9 +8433,9 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	      || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
 	{
 	  *total = COSTS_N_INSNS (1);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), GET_CODE (XEXP (x, 0)),
-			      0, speed);
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode,
+			      GET_CODE (XEXP (x, 0)), 0, speed);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	  return true;
 	}
 
@@ -8458,7 +8459,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	      if (CONST_DOUBLE_P (XEXP (x, 1))
 		  && arm_const_double_rtx (XEXP (x, 1)))
 		{
-		  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+		  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 		  return true;
 		}
 
@@ -8472,7 +8473,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
       if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_COMPARE
 	  || GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_COMM_COMPARE)
 	{
-	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 1), code, 1, speed);
+	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 1), mode, code,
+						 1, speed);
 	  if (REG_P (XEXP (XEXP (x, 0), 0))
 	      && REGNO (XEXP (XEXP (x, 0), 0)) != CC_REGNUM)
 	    *total += COSTS_N_INSNS (1);
@@ -8499,7 +8501,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	  if (CONST_INT_P (XEXP (x, 1))
 	      && const_ok_for_op (INTVAL (XEXP (x, 1)), code))
 	    {
-	      *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+	      *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 	      return true;
 	    }
 
@@ -8510,7 +8512,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
       if (CONST_INT_P (XEXP (x, 1))
 	  && const_ok_for_op (INTVAL (XEXP (x, 1)), code))
 	{
-	  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 	  return true;
 	}
       subcode = GET_CODE (XEXP (x, 0));
@@ -8518,16 +8520,16 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	  || subcode == LSHIFTRT
 	  || subcode == ROTATE || subcode == ROTATERT)
 	{
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
       if (subcode == MULT
 	  && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
 	{
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
@@ -8553,7 +8555,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	  && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
 	      || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND))
 	{
-	  *total = rtx_cost (XEXP (XEXP (x, 0), 0), LSHIFTRT, 0, speed);
+	  *total = rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, LSHIFTRT,
+			     0, speed);
 	  return true;
 	}
       *total = COSTS_N_INSNS (2); /* Plus the cost of the MULT */
@@ -8585,11 +8588,13 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	      || (subcode == MULT
 		  && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode)))
 	    {
-	      *total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
+	      *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode,
+				  0, speed);
 	      /* Register shifts cost an extra cycle.  */
 	      if (!CONST_INT_P (XEXP (XEXP (x, 0), 1)))
 		*total += COSTS_N_INSNS (1) + rtx_cost (XEXP (XEXP (x, 0), 1),
-							subcode, 1, speed);
+							mode, subcode,
+							1, speed);
 	      return true;
 	    }
 	}
@@ -8610,14 +8615,15 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	    && REG_P (XEXP (operand, 0))
 	    && REGNO (XEXP (operand, 0)) == CC_REGNUM))
 	*total += COSTS_N_INSNS (1);
-      *total += (rtx_cost (XEXP (x, 1), code, 1, speed)
-		 + rtx_cost (XEXP (x, 2), code, 2, speed));
+      *total += rtx_cost (XEXP (x, 1), VOIDmode, code, 1, speed);
+      *total += rtx_cost (XEXP (x, 2), VOIDmode, code, 2, speed);
       return true;
 
     case NE:
       if (mode == SImode && XEXP (x, 1) == const0_rtx)
 	{
-	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, speed);
 	  return true;
 	}
       goto scc_insn;
@@ -8626,7 +8632,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
       if ((!REG_P (XEXP (x, 0)) || REGNO (XEXP (x, 0)) != CC_REGNUM)
 	  && mode == SImode && XEXP (x, 1) == const0_rtx)
 	{
-	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, speed);
 	  return true;
 	}
       goto scc_insn;
@@ -8635,7 +8642,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
       if ((!REG_P (XEXP (x, 0)) || REGNO (XEXP (x, 0)) != CC_REGNUM)
 	  && mode == SImode && XEXP (x, 1) == const0_rtx)
 	{
-	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, speed);
 	  return true;
 	}
       goto scc_insn;
@@ -8676,7 +8684,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
       if (CONST_INT_P (XEXP (x, 1))
 	  && const_ok_for_op (INTVAL (XEXP (x, 1)), code))
 	{
-	  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed);
 	  return true;
 	}
 
@@ -8685,16 +8693,18 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	  || subcode == LSHIFTRT
 	  || subcode == ROTATE || subcode == ROTATERT)
 	{
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
+	  mode = GET_MODE (XEXP (x, 0));
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
       if (subcode == MULT
 	  && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
 	{
-	  *total += rtx_cost (XEXP (x, 1), code, 1, speed);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
+	  mode = GET_MODE (XEXP (x, 0));
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
 	  return true;
 	}
 
@@ -8704,10 +8714,10 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
     case UMAX:
     case SMIN:
     case SMAX:
-      *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code, 0, speed);
+      *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code, 0, speed);
       if (!CONST_INT_P (XEXP (x, 1))
 	  || !const_ok_for_arm (INTVAL (XEXP (x, 1))))
-	*total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	*total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
       return true;
 
     case ABS:
@@ -8784,7 +8794,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 
     case ZERO_EXTRACT:
     case SIGN_EXTRACT:
-      *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code, 0, speed);
+      mode = GET_MODE (XEXP (x, 0));
+      *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code, 0, speed);
       return true;
 
     case CONST_INT:
@@ -8809,7 +8820,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 
     case LO_SUM:
       *total = COSTS_N_INSNS (1);
-      *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+      *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
       return true;
 
     case CONST_DOUBLE:
@@ -8827,7 +8838,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
       if (TARGET_NEON && MEM_P (SET_DEST (x))
 	  && GET_CODE (SET_SRC (x)) == VEC_SELECT)
 	{
-	  *total = rtx_cost (SET_DEST (x), code, 0, speed);
+	  mode = GET_MODE (SET_DEST (x));
+	  *total = rtx_cost (SET_DEST (x), mode, code, 0, speed);
 	  if (!neon_vector_mem_operand (SET_DEST (x), 2, true))
 	    *total += COSTS_N_INSNS (1);
 	  return true;
@@ -8838,7 +8850,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	  && MEM_P (XEXP (XEXP (SET_SRC (x), 0), 0)))
 	{
 	  rtx mem = XEXP (XEXP (SET_SRC (x), 0), 0);
-	  *total = rtx_cost (mem, code, 0, speed);
+	  mode = GET_MODE (SET_DEST (x));
+	  *total = rtx_cost (mem, mode, code, 0, speed);
 	  if (!neon_vector_mem_operand (mem, 2, true))
 	    *total += COSTS_N_INSNS (1);
 	  return true;
@@ -9061,7 +9074,8 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
     case ROTATE:
       if (mode == SImode && REG_P (XEXP (x, 1)))
 	{
-	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code, 0, false);
+	  *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, false);
 	  return true;
 	}
       /* Fall through */
@@ -9071,15 +9085,17 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
     case ASHIFTRT:
       if (mode == DImode && CONST_INT_P (XEXP (x, 1)))
 	{
-	  *total = COSTS_N_INSNS (3) + rtx_cost (XEXP (x, 0), code, 0, false);
+	  *total = COSTS_N_INSNS (3) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, false);
 	  return true;
 	}
       else if (mode == SImode)
 	{
-	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code, 0, false);
+	  *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code,
+						 0, false);
 	  /* Slightly disparage register shifts, but not by much.  */
 	  if (!CONST_INT_P (XEXP (x, 1)))
-	    *total += 1 + rtx_cost (XEXP (x, 1), code, 1, false);
+	    *total += 1 + rtx_cost (XEXP (x, 1), mode, code, 1, false);
 	  return true;
 	}
 
@@ -9131,8 +9147,8 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
 	{
 	  *total = COSTS_N_INSNS (TARGET_THUMB2 ? 2 : 1);
-	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), code, 0, false);
-	  *total += rtx_cost (XEXP (x, 1), code, 1, false);
+	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, code, 0, false);
+	  *total += rtx_cost (XEXP (x, 1), mode, code, 1, false);
 	  return true;
 	}
 
@@ -9310,7 +9326,7 @@ arm_unspec_cost (rtx x, enum rtx_code /* outer_code */, bool speed_p, int *cost)
 	*cost += (ARM_NUM_REGS (GET_MODE (x)) * extra_cost->ldst.store
 		  + extra_cost->ldst.store_unaligned);
 
-      *cost += rtx_cost (XVECEXP (x, 0, 0), UNSPEC, 0, speed_p);
+      *cost += rtx_cost (XVECEXP (x, 0, 0), VOIDmode, UNSPEC, 0, speed_p);
 #ifdef NOT_YET
       *cost += arm_address_cost (XEXP (XVECEXP (x, 0, 0), 0), GET_MODE (x),
 				 ADDR_SPACE_GENERIC, speed_p);
@@ -9349,15 +9365,18 @@ arm_unspec_cost (rtx x, enum rtx_code /* outer_code */, bool speed_p, int *cost)
 	        if (shift_reg)						\
 		  {							\
 		    if (speed_p)					\
-		      *cost += extra_cost->alu.arith_shift_reg;	\
-		    *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);	\
+		      *cost += extra_cost->alu.arith_shift_reg;		\
+		    *cost += rtx_cost (shift_reg, GET_MODE (shift_reg),	\
+				       ASHIFT, 1, speed_p);		\
 		  }							\
 	        else if (speed_p)					\
-		  *cost += extra_cost->alu.arith_shift;		\
+		  *cost += extra_cost->alu.arith_shift;			\
 									\
-		  *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)	\
+		*cost += (rtx_cost (shift_op, GET_MODE (shift_op),	\
+				    ASHIFT, 0, speed_p)			\
 			  + rtx_cost (XEXP (x, 1 - IDX),		\
-			              OP, 1, speed_p));		\
+				      GET_MODE (shift_op),		\
+			              OP, 1, speed_p));			\
 	        return true;						\
 	      }								\
 	  }								\
@@ -9421,7 +9440,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	{
 	  /* Handle CONST_INT here, since the value doesn't have a mode
 	     and we would otherwise be unable to work out the true cost.  */
-	  *cost = rtx_cost (SET_DEST (x), SET, 0, speed_p);
+	  *cost = rtx_cost (SET_DEST (x), GET_MODE (SET_DEST (x)), SET,
+			    0, speed_p);
 	  outer_code = SET;
 	  /* Slightly lower the cost of setting a core reg to a constant.
 	     This helps break up chains and allows for better scheduling.  */
@@ -9528,7 +9548,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
       if (mode == SImode && REG_P (XEXP (x, 1)))
 	{
 	  *cost = (COSTS_N_INSNS (2)
-		   + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+		   + rtx_cost (XEXP (x, 0), mode, code, 0, speed_p));
 	  if (speed_p)
 	    *cost += extra_cost->alu.shift_reg;
 	  return true;
@@ -9541,7 +9561,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
       if (mode == DImode && CONST_INT_P (XEXP (x, 1)))
 	{
 	  *cost = (COSTS_N_INSNS (3)
-		   + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+		   + rtx_cost (XEXP (x, 0), mode, code, 0, speed_p));
 	  if (speed_p)
 	    *cost += 2 * extra_cost->alu.shift;
 	  return true;
@@ -9549,11 +9569,11 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
       else if (mode == SImode)
 	{
 	  *cost = (COSTS_N_INSNS (1)
-		   + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+		   + rtx_cost (XEXP (x, 0), mode, code, 0, speed_p));
 	  /* Slightly disparage register shifts at -Os, but not by much.  */
 	  if (!CONST_INT_P (XEXP (x, 1)))
 	    *cost += (speed_p ? extra_cost->alu.shift_reg : 1
-		      + rtx_cost (XEXP (x, 1), code, 1, speed_p));
+		      + rtx_cost (XEXP (x, 1), mode, code, 1, speed_p));
 	  return true;
 	}
       else if (GET_MODE_CLASS (mode) == MODE_INT
@@ -9562,12 +9582,12 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  if (code == ASHIFT)
 	    {
 	      *cost = (COSTS_N_INSNS (1)
-		       + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+		       + rtx_cost (XEXP (x, 0), mode, code, 0, speed_p));
 	      /* Slightly disparage register shifts at -Os, but not by
 	         much.  */
 	      if (!CONST_INT_P (XEXP (x, 1)))
 		*cost += (speed_p ? extra_cost->alu.shift_reg : 1
-			  + rtx_cost (XEXP (x, 1), code, 1, speed_p));
+			  + rtx_cost (XEXP (x, 1), mode, code, 1, speed_p));
 	    }
 	  else if (code == LSHIFTRT || code == ASHIFTRT)
 	    {
@@ -9577,12 +9597,12 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		  *cost = COSTS_N_INSNS (1);
 		  if (speed_p)
 		    *cost += extra_cost->alu.bfx;
-		  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 		}
 	      else
 		{
 		  *cost = COSTS_N_INSNS (2);
-		  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 		  if (speed_p)
 		    {
 		      if (CONST_INT_P (XEXP (x, 1)))
@@ -9599,7 +9619,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  else /* Rotates.  */
 	    {
 	      *cost = COSTS_N_INSNS (3 + !CONST_INT_P (XEXP (x, 1)));
-	      *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	      *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 	      if (speed_p)
 		{
 		  if (CONST_INT_P (XEXP (x, 1)))
@@ -9689,9 +9709,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      if (GET_CODE (mul_op0) == NEG)
 		mul_op0 = XEXP (mul_op0, 0);
 
-	      *cost += (rtx_cost (mul_op0, code, 0, speed_p)
-			+ rtx_cost (mul_op1, code, 0, speed_p)
-			+ rtx_cost (sub_op, code, 0, speed_p));
+	      *cost += (rtx_cost (mul_op0, mode, code, 0, speed_p)
+			+ rtx_cost (mul_op1, mode, code, 0, speed_p)
+			+ rtx_cost (sub_op, mode, code, 0, speed_p));
 
 	      return true;
 	    }
@@ -9724,13 +9744,13 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		{
 		  if (speed_p)
 		    *cost += extra_cost->alu.arith_shift_reg;
-		  *cost += rtx_cost (shift_by_reg, code, 0, speed_p);
+		  *cost += rtx_cost (shift_by_reg, mode, code, 0, speed_p);
 		}
 	      else if (speed_p)
 		*cost += extra_cost->alu.arith_shift;
 
-	      *cost += (rtx_cost (shift_op, code, 0, speed_p)
-			+ rtx_cost (non_shift_op, code, 0, speed_p));
+	      *cost += rtx_cost (shift_op, mode, code, 0, speed_p);
+	      *cost += rtx_cost (non_shift_op, mode, code, 0, speed_p);
 	      return true;
 	    }
 
@@ -9740,9 +9760,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      /* MLS.  */
 	      if (speed_p)
 		*cost += extra_cost->mult[0].add;
-	      *cost += (rtx_cost (XEXP (x, 0), MINUS, 0, speed_p)
-			+ rtx_cost (XEXP (XEXP (x, 1), 0), MULT, 0, speed_p)
-			+ rtx_cost (XEXP (XEXP (x, 1), 1), MULT, 1, speed_p));
+	      *cost += rtx_cost (XEXP (x, 0), mode, MINUS, 0, speed_p);
+	      *cost += rtx_cost (XEXP (XEXP (x, 1), 0), mode, MULT, 0, speed_p);
+	      *cost += rtx_cost (XEXP (XEXP (x, 1), 1), mode, MULT, 1, speed_p);
 	      return true;
 	    }
 
@@ -9754,7 +9774,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      *cost = COSTS_N_INSNS (insns);
 	      if (speed_p)
 		*cost += insns * extra_cost->alu.arith;
-	      *cost += rtx_cost (XEXP (x, 1), code, 1, speed_p);
+	      *cost += rtx_cost (XEXP (x, 1), mode, code, 1, speed_p);
 	      return true;
 	    }
 	  else if (speed_p)
@@ -9782,7 +9802,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 
 	  if (CONST_INT_P (XEXP (x, 0)))
 	    {
-	      *cost += rtx_cost (XEXP (x, 1), code, 1, speed_p);
+	      *cost += rtx_cost (XEXP (x, 1), mode, code, 1, speed_p);
 	      return true;
 	    }
 
@@ -9801,10 +9821,11 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		*cost += 2 * extra_cost->alu.arith;
 
 	      if (GET_CODE (op1) == ZERO_EXTEND)
-		*cost += rtx_cost (XEXP (op1, 0), ZERO_EXTEND, 0, speed_p);
+		*cost += rtx_cost (XEXP (op1, 0), VOIDmode, ZERO_EXTEND,
+				   0, speed_p);
 	      else
-		*cost += rtx_cost (op1, MINUS, 1, speed_p);
-	      *cost += rtx_cost (XEXP (XEXP (x, 0), 0), ZERO_EXTEND,
+		*cost += rtx_cost (op1, mode, MINUS, 1, speed_p);
+	      *cost += rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, ZERO_EXTEND,
 				 0, speed_p);
 	      return true;
 	    }
@@ -9812,9 +9833,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	    {
 	      if (speed_p)
 		*cost += extra_cost->alu.arith + extra_cost->alu.arith_shift;
-	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), SIGN_EXTEND,
+	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, SIGN_EXTEND,
 				  0, speed_p)
-			+ rtx_cost (XEXP (x, 1), MINUS, 1, speed_p));
+			+ rtx_cost (XEXP (x, 1), mode, MINUS, 1, speed_p));
 	      return true;
 	    }
 	  else if (GET_CODE (XEXP (x, 1)) == ZERO_EXTEND
@@ -9825,8 +9846,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 			  + (GET_CODE (XEXP (x, 1)) == ZERO_EXTEND
 			     ? extra_cost->alu.arith
 			     : extra_cost->alu.arith_shift));
-	      *cost += (rtx_cost (XEXP (x, 0), MINUS, 0, speed_p)
-			+ rtx_cost (XEXP (XEXP (x, 1), 0),
+	      *cost += (rtx_cost (XEXP (x, 0), mode, MINUS, 0, speed_p)
+			+ rtx_cost (XEXP (XEXP (x, 1), 0), VOIDmode,
 				    GET_CODE (XEXP (x, 1)), 0, speed_p));
 	      return true;
 	    }
@@ -9857,9 +9878,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      mul_op1 = XEXP (XEXP (x, 0), 1);
 	      add_op = XEXP (x, 1);
 
-	      *cost += (rtx_cost (mul_op0, code, 0, speed_p)
-			+ rtx_cost (mul_op1, code, 0, speed_p)
-			+ rtx_cost (add_op, code, 0, speed_p));
+	      *cost += (rtx_cost (mul_op0, mode, code, 0, speed_p)
+			+ rtx_cost (mul_op1, mode, code, 0, speed_p)
+			+ rtx_cost (add_op, mode, code, 0, speed_p));
 
 	      return true;
 	    }
@@ -9896,7 +9917,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		*cost += insns * extra_cost->alu.arith;
 	      /* Slightly penalize a narrow operation as the result may
 		 need widening.  */
-	      *cost += 1 + rtx_cost (XEXP (x, 0), PLUS, 0, speed_p);
+	      *cost += 1 + rtx_cost (XEXP (x, 0), mode, PLUS, 0, speed_p);
 	      return true;
 	    }
 
@@ -9921,9 +9942,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      /* UXTA[BH] or SXTA[BH].  */
 	      if (speed_p)
 		*cost += extra_cost->alu.extend_arith;
-	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), ZERO_EXTEND, 0,
-				  speed_p)
-			+ rtx_cost (XEXP (x, 1), PLUS, 0, speed_p));
+	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, ZERO_EXTEND,
+				  0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, PLUS, 0, speed_p));
 	      return true;
 	    }
 
@@ -9935,13 +9956,13 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		{
 		  if (speed_p)
 		    *cost += extra_cost->alu.arith_shift_reg;
-		  *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+		  *cost += rtx_cost (shift_reg, mode, ASHIFT, 1, speed_p);
 		}
 	      else if (speed_p)
 		*cost += extra_cost->alu.arith_shift;
 
-	      *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+	      *cost += (rtx_cost (shift_op, mode, ASHIFT, 0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed_p));
 	      return true;
 	    }
 	  if (GET_CODE (XEXP (x, 0)) == MULT)
@@ -9968,19 +9989,19 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		  /* SMLA[BT][BT].  */
 		  if (speed_p)
 		    *cost += extra_cost->mult[0].extend_add;
-		  *cost += (rtx_cost (XEXP (XEXP (mul_op, 0), 0),
+		  *cost += (rtx_cost (XEXP (XEXP (mul_op, 0), 0), mode,
 				      SIGN_EXTEND, 0, speed_p)
-			    + rtx_cost (XEXP (XEXP (mul_op, 1), 0),
+			    + rtx_cost (XEXP (XEXP (mul_op, 1), 0), mode,
 					SIGN_EXTEND, 0, speed_p)
-			    + rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+			    + rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed_p));
 		  return true;
 		}
 
 	      if (speed_p)
 		*cost += extra_cost->mult[0].add;
-	      *cost += (rtx_cost (XEXP (mul_op, 0), MULT, 0, speed_p)
-			+ rtx_cost (XEXP (mul_op, 1), MULT, 1, speed_p)
-			+ rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+	      *cost += (rtx_cost (XEXP (mul_op, 0), mode, MULT, 0, speed_p)
+			+ rtx_cost (XEXP (mul_op, 1), mode, MULT, 1, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed_p));
 	      return true;
 	    }
 	  if (CONST_INT_P (XEXP (x, 1)))
@@ -9991,7 +10012,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      *cost = COSTS_N_INSNS (insns);
 	      if (speed_p)
 		*cost += insns * extra_cost->alu.arith;
-	      *cost += rtx_cost (XEXP (x, 0), PLUS, 0, speed_p);
+	      *cost += rtx_cost (XEXP (x, 0), mode, PLUS, 0, speed_p);
 	      return true;
 	    }
 	  else if (speed_p)
@@ -10012,11 +10033,11 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      *cost = COSTS_N_INSNS (1);
 	      if (speed_p)
 		*cost += extra_cost->mult[1].extend_add;
-	      *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0),
+	      *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0), mode,
 				  ZERO_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (XEXP (XEXP (x, 0), 1), 0),
+			+ rtx_cost (XEXP (XEXP (XEXP (x, 0), 1), 0), mode,
 				    ZERO_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+			+ rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed_p));
 	      return true;
 	    }
 
@@ -10031,9 +10052,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 			     ? extra_cost->alu.arith
 			     : extra_cost->alu.arith_shift));
 
-	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), ZERO_EXTEND, 0,
-				  speed_p)
-			+ rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, ZERO_EXTEND,
+				  0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed_p));
 	      return true;
 	    }
 
@@ -10077,13 +10098,13 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		{
 		  if (speed_p)
 		    *cost += extra_cost->alu.log_shift_reg;
-		  *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+		  *cost += rtx_cost (shift_reg, mode, ASHIFT, 1, speed_p);
 		}
 	      else if (speed_p)
 		*cost += extra_cost->alu.log_shift;
 
-	      *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), code, 1, speed_p));
+	      *cost += (rtx_cost (shift_op, mode, ASHIFT, 0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, code, 1, speed_p));
 	      return true;
 	    }
 
@@ -10096,14 +10117,14 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      *cost = COSTS_N_INSNS (insns);
 	      if (speed_p)
 		*cost += insns * extra_cost->alu.logical;
-	      *cost += rtx_cost (op0, code, 0, speed_p);
+	      *cost += rtx_cost (op0, mode, code, 0, speed_p);
 	      return true;
 	    }
 
 	  if (speed_p)
 	    *cost += extra_cost->alu.logical;
-	  *cost += (rtx_cost (op0, code, 0, speed_p)
-		    + rtx_cost (XEXP (x, 1), code, 1, speed_p));
+	  *cost += (rtx_cost (op0, mode, code, 0, speed_p)
+		    + rtx_cost (XEXP (x, 1), mode, code, 1, speed_p));
 	  return true;
 	}
 
@@ -10124,8 +10145,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      if (speed_p)
 		*cost += 2 * extra_cost->alu.logical;
 
-	      *cost += (rtx_cost (XEXP (op0, 0), ZERO_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), code, 0, speed_p));
+	      *cost += (rtx_cost (XEXP (op0, 0), VOIDmode, ZERO_EXTEND,
+				  0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, code, 0, speed_p));
 	      return true;
 	    }
 	  else if (GET_CODE (op0) == SIGN_EXTEND)
@@ -10133,8 +10155,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      if (speed_p)
 		*cost += extra_cost->alu.logical + extra_cost->alu.log_shift;
 
-	      *cost += (rtx_cost (XEXP (op0, 0), SIGN_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), code, 0, speed_p));
+	      *cost += (rtx_cost (XEXP (op0, 0), VOIDmode, SIGN_EXTEND,
+				  0, speed_p)
+			+ rtx_cost (XEXP (x, 1), mode, code, 0, speed_p));
 	      return true;
 	    }
 
@@ -10162,8 +10185,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  if (speed_p)
 	    *cost += extra_cost->fp[mode != SFmode].mult;
 
-	  *cost += (rtx_cost (op0, MULT, 0, speed_p)
-		    + rtx_cost (XEXP (x, 1), MULT, 1, speed_p));
+	  *cost += (rtx_cost (op0, mode, MULT, 0, speed_p)
+		    + rtx_cost (XEXP (x, 1), mode, MULT, 1, speed_p));
 	  return true;
 	}
       else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
@@ -10193,8 +10216,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      /* SMUL[TB][TB].  */
 	      if (speed_p)
 		*cost += extra_cost->mult[0].extend;
-	      *cost += (rtx_cost (XEXP (x, 0), SIGN_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (x, 1), SIGN_EXTEND, 0, speed_p));
+	      *cost += rtx_cost (XEXP (x, 0), mode, SIGN_EXTEND, 0, speed_p);
+	      *cost += rtx_cost (XEXP (x, 1), mode, SIGN_EXTEND, 1, speed_p);
 	      return true;
 	    }
 	  if (speed_p)
@@ -10213,9 +10236,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      *cost = COSTS_N_INSNS (1);
 	      if (speed_p)
 		*cost += extra_cost->mult[1].extend;
-	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0),
+	      *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode,
 				  ZERO_EXTEND, 0, speed_p)
-			+ rtx_cost (XEXP (XEXP (x, 1), 0),
+			+ rtx_cost (XEXP (XEXP (x, 1), 0), VOIDmode,
 				    ZERO_EXTEND, 0, speed_p));
 	      return true;
 	    }
@@ -10253,7 +10276,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      if (speed_p)
 		*cost += (extra_cost->alu.log_shift
 			  + extra_cost->alu.arith_shift);
-	      *cost += rtx_cost (XEXP (XEXP (x, 0), 0), ABS, 0, speed_p);
+	      *cost += rtx_cost (XEXP (XEXP (x, 0), 0), mode, ABS, 0, speed_p);
 	      return true;
 	    }
 
@@ -10268,11 +10291,12 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		    && REGNO (XEXP (XEXP (x, 0), 0)) == CC_REGNUM
 		    && XEXP (XEXP (x, 0), 1) == const0_rtx))
 		{
+		  mode = GET_MODE (XEXP (XEXP (x, 0), 0));
 		  *cost += (COSTS_N_INSNS (1)
-			    + rtx_cost (XEXP (XEXP (x, 0), 0), COMPARE, 0,
-					speed_p)
-			    + rtx_cost (XEXP (XEXP (x, 0), 1), COMPARE, 1,
-					speed_p));
+			    + rtx_cost (XEXP (XEXP (x, 0), 0), mode, COMPARE,
+					0, speed_p)
+			    + rtx_cost (XEXP (XEXP (x, 0), 1), mode, COMPARE,
+					1, speed_p));
 		  if (speed_p)
 		    *cost += extra_cost->alu.arith;
 		}
@@ -10321,11 +10345,11 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		{
 		  if (speed_p)
 		    *cost += extra_cost->alu.log_shift_reg;
-		  *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+		  *cost += rtx_cost (shift_reg, mode, ASHIFT, 1, speed_p);
 		}
 	      else if (speed_p)
 		*cost += extra_cost->alu.log_shift;
-	      *cost += rtx_cost (shift_op, ASHIFT, 0, speed_p);
+	      *cost += rtx_cost (shift_op, mode, ASHIFT, 0, speed_p);
 	      return true;
 	    }
 
@@ -10351,10 +10375,10 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	    *cost = COSTS_N_INSNS (4);
 	    return true;
 	  }
-	int op1cost = rtx_cost (XEXP (x, 1), SET, 1, speed_p);
-	int op2cost = rtx_cost (XEXP (x, 2), SET, 1, speed_p);
+	int op1cost = rtx_cost (XEXP (x, 1), mode, SET, 1, speed_p);
+	int op2cost = rtx_cost (XEXP (x, 2), mode, SET, 1, speed_p);
 
-	*cost = rtx_cost (XEXP (x, 0), IF_THEN_ELSE, 0, speed_p);
+	*cost = rtx_cost (XEXP (x, 0), mode, IF_THEN_ELSE, 0, speed_p);
 	/* Assume that if one arm of the if_then_else is a register,
 	   that it will be tied with the result and eliminate the
 	   conditional insn.  */
@@ -10397,7 +10421,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 
 	      if (XEXP (x, 1) == CONST0_RTX (op0mode))
 		{
-		  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 0), op0mode, code, 0, speed_p);
 		  return true;
 		}
 
@@ -10428,7 +10452,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		       || (GET_CODE (XEXP (x, 0)) == SUBREG
 			   && REG_P (SUBREG_REG (XEXP (x, 0))))))
 		{
-		  *cost = rtx_cost (XEXP (x, 0), COMPARE, 0, speed_p);
+		  *cost = rtx_cost (XEXP (x, 0), op0mode, COMPARE, 0, speed_p);
 
 		  /* Multiply operations that set the flags are often
 		     significantly more expensive.  */
@@ -10453,14 +10477,15 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		  *cost = COSTS_N_INSNS (1);
 		  if (shift_reg != NULL)
 		    {
-		      *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+		      *cost += rtx_cost (shift_reg, op0mode, ASHIFT,
+					 1, speed_p);
 		      if (speed_p)
 			*cost += extra_cost->alu.arith_shift_reg;
 		    }
 		  else if (speed_p)
 		    *cost += extra_cost->alu.arith_shift;
-		  *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)
-			    + rtx_cost (XEXP (x, 1), COMPARE, 1, speed_p));
+		  *cost += rtx_cost (shift_op, op0mode, ASHIFT, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 1), op0mode, COMPARE, 1, speed_p);
 		  return true;
 		}
 
@@ -10470,7 +10495,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      if (CONST_INT_P (XEXP (x, 1))
 		  && const_ok_for_op (INTVAL (XEXP (x, 1)), COMPARE))
 		{
-		  *cost += rtx_cost (XEXP (x, 0), COMPARE, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 0), op0mode, COMPARE, 0, speed_p);
 		  return true;
 		}
 	      return false;
@@ -10563,7 +10588,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 		  *cost = COSTS_N_INSNS (3);
 		  break;
 		}
-	      *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	      *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 	      return true;
 	    }
 	  else
@@ -10572,7 +10597,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      if (CONST_INT_P (XEXP (x, 1))
 		  && const_ok_for_op (INTVAL (XEXP (x, 1)), COMPARE))
 		{
-		  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+		  *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 		  return true;
 		}
 
@@ -10623,7 +10648,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
       if ((arm_arch4 || GET_MODE (XEXP (x, 0)) == SImode)
 	  && MEM_P (XEXP (x, 0)))
 	{
-	  *cost = rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost = rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 
 	  if (mode == DImode)
 	    *cost += COSTS_N_INSNS (1);
@@ -10647,7 +10672,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	{
 	  /* We have SXTB/SXTH.  */
 	  *cost = COSTS_N_INSNS (1);
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  if (speed_p)
 	    *cost += extra_cost->alu.extend;
 	}
@@ -10655,7 +10680,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	{
 	  /* Needs two shifts.  */
 	  *cost = COSTS_N_INSNS (2);
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  if (speed_p)
 	    *cost += 2 * extra_cost->alu.shift;
 	}
@@ -10676,7 +10701,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	   || GET_MODE (XEXP (x, 0)) == QImode)
 	  && MEM_P (XEXP (x, 0)))
 	{
-	  *cost = rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost = rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 
 	  if (mode == DImode)
 	    *cost += COSTS_N_INSNS (1);  /* No speed penalty.  */
@@ -10700,7 +10725,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	{
 	  /* We have UXTB/UXTH.  */
 	  *cost = COSTS_N_INSNS (1);
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  if (speed_p)
 	    *cost += extra_cost->alu.extend;
 	}
@@ -10711,7 +10736,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	     shift may merge with a subsequent insn as a shifter
 	     op.  */
 	  *cost = COSTS_N_INSNS (2);
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  if (speed_p)
 	    *cost += 2 * extra_cost->alu.shift;
 	}
@@ -10855,7 +10880,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  *cost = COSTS_N_INSNS (1);
 	  if (speed_p)
 	    *cost += extra_cost->alu.log_shift;
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 	  return true;
 	}
       /* Fall through.  */
@@ -10879,10 +10904,10 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  *cost = COSTS_N_INSNS (1);
 	  if (speed_p)
 	    *cost += extra_cost->mult[1].extend;
-	  *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0), ZERO_EXTEND, 0,
-			      speed_p)
-		    + rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 1), ZERO_EXTEND,
-				0, speed_p));
+	  *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0), VOIDmode,
+			      ZERO_EXTEND, 0, speed_p)
+		    + rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 1), VOIDmode,
+				ZERO_EXTEND, 0, speed_p));
 	  return true;
 	}
       *cost = LIBCALL_COST (1);
@@ -10910,14 +10935,14 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  *cost = COSTS_N_INSNS (1);
 	  if (speed_p)
 	    *cost += extra_cost->alu.bfx;
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 	  return true;
 	}
       /* Without UBFX/SBFX, need to resort to shift operations.  */
       *cost = COSTS_N_INSNS (2);
       if (speed_p)
 	*cost += 2 * extra_cost->alu.shift;
-      *cost += rtx_cost (XEXP (x, 0), ASHIFT, 0, speed_p);
+      *cost += rtx_cost (XEXP (x, 0), mode, ASHIFT, 0, speed_p);
       return true;
 
     case FLOAT_EXTEND:
@@ -10935,7 +10960,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	      if (speed_p)
 		*cost += extra_cost->fp[0].widen;
 	    }
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  return true;
 	}
 
@@ -10948,7 +10973,7 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  *cost = COSTS_N_INSNS (1);
 	  if (speed_p)
 	    *cost += extra_cost->fp[mode == DFmode].narrow;
-	  *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+	  *cost += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed_p);
 	  return true;
 	  /* Vector modes?  */
 	}
@@ -10972,9 +10997,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
           if (GET_CODE (op2) == NEG)
             op2 = XEXP (op2, 0);
 
-          *cost += rtx_cost (op0, FMA, 0, speed_p);
-          *cost += rtx_cost (op1, FMA, 1, speed_p);
-          *cost += rtx_cost (op2, FMA, 2, speed_p);
+          *cost += rtx_cost (op0, mode, FMA, 0, speed_p);
+          *cost += rtx_cost (op1, mode, FMA, 1, speed_p);
+          *cost += rtx_cost (op2, mode, FMA, 2, speed_p);
 
           if (speed_p)
             *cost += extra_cost->fp[mode ==DFmode].fma;
@@ -10992,13 +11017,15 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  if (GET_MODE_CLASS (mode) == MODE_INT)
 	    {
 	      *cost = COSTS_N_INSNS (1);
+	      mode = GET_MODE (XEXP (x, 0));
 	      if (speed_p)
-		*cost += extra_cost->fp[GET_MODE (XEXP (x, 0)) == DFmode].toint;
+		*cost += extra_cost->fp[mode == DFmode].toint;
 	      /* Strip of the 'cost' of rounding towards zero.  */
 	      if (GET_CODE (XEXP (x, 0)) == FIX)
-		*cost += rtx_cost (XEXP (XEXP (x, 0), 0), code, 0, speed_p);
+		*cost += rtx_cost (XEXP (XEXP (x, 0), 0), mode, code,
+				   0, speed_p);
 	      else
-		*cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+		*cost += rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
 	      /* ??? Increase the cost to deal with transferring from
 		 FP -> CORE registers?  */
 	      return true;
@@ -11058,10 +11085,11 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 
 /* RTX costs when optimizing for size.  */
 static bool
-arm_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-	       int *total, bool speed)
+arm_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
+	       int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
   bool result;
+  int code = GET_CODE (x);
 
   if (TARGET_OLD_RTX_COSTS
       || (!current_tune->insn_extra_cost && !TARGET_NEW_GENERIC_COSTS))
@@ -11142,7 +11170,7 @@ arm_slowmul_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	    }
 
 	  *total = COSTS_N_INSNS (cost);
-	  *total += rtx_cost (XEXP (x, 0), code, 0, speed);
+	  *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
 	  return true;
 	}
 
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index f291cf9..9091012 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -174,7 +174,7 @@ static struct machine_function * avr_init_machine_status (void);
 
 /* Prototypes for hook implementors if needed before their implementation.  */
 
-static bool avr_rtx_costs (rtx, int, int, int, int*, bool);
+static bool avr_rtx_costs (rtx, machine_mode, int, int, int*, bool);
 
 
 /* Allocate registers from r25 to r8 for parameters for function calls.  */
@@ -2702,10 +2702,11 @@ avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
 
       if (set)
         fprintf (asm_out_file, "/* DEBUG: cost = %d.  */\n",
-                 set_src_cost (SET_SRC (set), optimize_insn_for_speed_p ()));
+                 set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
+			       optimize_insn_for_speed_p ()));
       else
         fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d.  */\n",
-                 rtx_cost (PATTERN (insn), INSN, 0,
+                 rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
                            optimize_insn_for_speed_p()));
     }
 }
@@ -9915,7 +9916,7 @@ avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
     }
 
   total = 0;
-  avr_rtx_costs (x, code, outer, opno, &total, speed);
+  avr_rtx_costs (x, mode, outer, opno, &total, speed);
   return total;
 }
 
@@ -9926,11 +9927,10 @@ avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
    In either case, *TOTAL contains the cost result.  */
 
 static bool
-avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
+avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
                  int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
-  enum rtx_code code = (enum rtx_code) codearg;
-  machine_mode mode = GET_MODE (x);
+  enum rtx_code code = GET_CODE (x);
   HOST_WIDE_INT val;
 
   switch (code)
@@ -9991,13 +9991,15 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
     case ZERO_EXTEND:
       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
 			      - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
-      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
+      *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
+				      code, 0, speed);
       return true;
 
     case SIGN_EXTEND:
       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
 			      - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
-      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
+      *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
+				      code, 0, speed);
       return true;
 
     case PLUS:
@@ -10703,13 +10705,15 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
 	case QImode:
 	  *total = COSTS_N_INSNS (1);
 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
-	    *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+	    *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
+					    1, speed);
 	  break;
 
         case HImode:
 	  *total = COSTS_N_INSNS (2);
 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
-            *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+            *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
+					    1, speed);
 	  else if (INTVAL (XEXP (x, 1)) != 0)
 	    *total += COSTS_N_INSNS (1);
           break;
@@ -10723,7 +10727,8 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
         case SImode:
           *total = COSTS_N_INSNS (4);
           if (GET_CODE (XEXP (x, 1)) != CONST_INT)
-            *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+            *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
+					    1, speed);
 	  else if (INTVAL (XEXP (x, 1)) != 0)
 	    *total += COSTS_N_INSNS (3);
           break;
@@ -10731,7 +10736,8 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
 	default:
 	  return false;
 	}
-      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
+      *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
+				      code, 0, speed);
       return true;
 
     case TRUNCATE:
@@ -10758,10 +10764,10 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
 /* Implement `TARGET_RTX_COSTS'.  */
 
 static bool
-avr_rtx_costs (rtx x, int codearg, int outer_code,
+avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	       int opno, int *total, bool speed)
 {
-  bool done = avr_rtx_costs_1 (x, codearg, outer_code,
+  bool done = avr_rtx_costs_1 (x, mode, outer_code,
                                opno, total, speed);
 
   if (avr_log.rtx_costs)
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 3b4b54e..f0e25ca 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -2801,10 +2801,10 @@ bfin_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 }
 
 static bool
-bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
-		bool speed)
+bfin_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
+		int *total, bool speed)
 {
-  enum rtx_code code = (enum rtx_code) code_i;
+  enum rtx_code code = GET_CODE (x);
   enum rtx_code outer_code = (enum rtx_code) outer_code_i;
   int cost2 = COSTS_N_INSNS (1);
   rtx op0, op1;
@@ -2843,7 +2843,7 @@ bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
     case PLUS:
       op0 = XEXP (x, 0);
       op1 = XEXP (x, 1);
-      if (GET_MODE (x) == SImode)
+      if (mode == SImode)
 	{
 	  if (GET_CODE (op0) == MULT
 	      && GET_CODE (XEXP (op0, 1)) == CONST_INT)
@@ -2852,35 +2852,36 @@ bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
 	      if (val == 2 || val == 4)
 		{
 		  *total = cost2;
-		  *total += rtx_cost (XEXP (op0, 0), outer_code, opno, speed);
-		  *total += rtx_cost (op1, outer_code, opno, speed);
+		  *total += rtx_cost (XEXP (op0, 0), mode, outer_code,
+				      opno, speed);
+		  *total += rtx_cost (op1, mode, outer_code, opno, speed);
 		  return true;
 		}
 	    }
 	  *total = cost2;
 	  if (GET_CODE (op0) != REG
 	      && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	    *total += set_src_cost (op0, speed);
+	    *total += set_src_cost (op0, mode, speed);
 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
 	 towards creating too many induction variables.  */
 	  if (!reg_or_7bit_operand (op1, SImode))
-	    *total += set_src_cost (op1, speed);
+	    *total += set_src_cost (op1, mode, speed);
 #endif
 	}
-      else if (GET_MODE (x) == DImode)
+      else if (mode == DImode)
 	{
 	  *total = 6 * cost2;
 	  if (GET_CODE (op1) != CONST_INT
 	      || !satisfies_constraint_Ks7 (op1))
-	    *total += rtx_cost (op1, PLUS, 1, speed);
+	    *total += rtx_cost (op1, mode, PLUS, 1, speed);
 	  if (GET_CODE (op0) != REG
 	      && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	    *total += rtx_cost (op0, PLUS, 0, speed);
+	    *total += rtx_cost (op0, mode, PLUS, 0, speed);
 	}
       return true;
 
     case MINUS:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	*total = 6 * cost2;
       else
 	*total = cost2;
@@ -2889,7 +2890,7 @@ bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
     case ASHIFT: 
     case ASHIFTRT:
     case LSHIFTRT:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	*total = 6 * cost2;
       else
 	*total = cost2;
@@ -2898,7 +2899,7 @@ bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
       op1 = XEXP (x, 1);
       if (GET_CODE (op0) != REG
 	  && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	*total += rtx_cost (op0, code, 0, speed);
+	*total += rtx_cost (op0, mode, code, 0, speed);
 
       return true;
 	  
@@ -2923,26 +2924,26 @@ bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
 
       if (GET_CODE (op0) != REG
 	  && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	*total += rtx_cost (op0, code, 0, speed);
+	*total += rtx_cost (op0, mode, code, 0, speed);
 
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	{
 	  *total = 2 * cost2;
 	  return true;
 	}
       *total = cost2;
-      if (GET_MODE (x) != SImode)
+      if (mode != SImode)
 	return true;
 
       if (code == AND)
 	{
 	  if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
-	    *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	    *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	}
       else
 	{
 	  if (! regorlog2_operand (XEXP (x, 1), SImode))
-	    *total += rtx_cost (XEXP (x, 1), code, 1, speed);
+	    *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
 	}
 
       return true;
@@ -2982,10 +2983,10 @@ bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
 
 	  if (GET_CODE (op0) != REG
 	      && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	    *total += rtx_cost (op0, MULT, 0, speed);
+	    *total += rtx_cost (op0, mode, MULT, 0, speed);
 	  if (GET_CODE (op1) != REG
 	      && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
-	    *total += rtx_cost (op1, MULT, 1, speed);
+	    *total += rtx_cost (op1, mode, MULT, 1, speed);
 	}
       return true;
 
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index 7088e45..41ceda2 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -6047,11 +6047,12 @@ shift_p (rtx x, enum rtx_code code, int amount)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
+c6x_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total,
 	       bool speed)
 {
   int cost2 = COSTS_N_INSNS (1);
   rtx op0, op1;
+  int code = GET_CODE (x);
 
   switch (code)
     {
@@ -6080,12 +6081,12 @@ c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
 
     case TRUNCATE:
       /* Recognize a mult_highpart operation.  */
-      if ((GET_MODE (x) == HImode || GET_MODE (x) == SImode)
+      if ((mode == HImode || mode == SImode)
 	  && GET_CODE (XEXP (x, 0)) == LSHIFTRT
-	  && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (GET_MODE (x))
+	  && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (mode)
 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
 	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-	  && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (GET_MODE (x)))
+	  && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode))
 	{
 	  rtx mul = XEXP (XEXP (x, 0), 0);
 	  rtx op0 = XEXP (mul, 0);
@@ -6095,15 +6096,16 @@ c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
 
 	  if ((code0 == code1
 	       && (code0 == SIGN_EXTEND || code0 == ZERO_EXTEND))
-	      || (GET_MODE (x) == HImode
+	      || (mode == HImode
 		  && code0 == ZERO_EXTEND && code1 == SIGN_EXTEND))
 	    {
-	      if (GET_MODE (x) == HImode)
+	      if (mode == HImode)
 		*total = COSTS_N_INSNS (2);
 	      else
 		*total = COSTS_N_INSNS (12);
-	      *total += rtx_cost (XEXP (op0, 0), code0, 0, speed);
-	      *total += rtx_cost (XEXP (op1, 0), code1, 0, speed);
+	      mode = GET_MODE (XEXP (op0, 0));
+	      *total += rtx_cost (XEXP (op0, 0), mode, code0, 0, speed);
+	      *total += rtx_cost (XEXP (op1, 0), mode, code1, 0, speed);
 	      return true;
 	    }
 	}
@@ -6112,7 +6114,7 @@ c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
     case ASHIFT:
     case ASHIFTRT:
     case LSHIFTRT:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	*total = COSTS_N_INSNS (CONSTANT_P (XEXP (x, 1)) ? 4 : 15);
       else
 	*total = COSTS_N_INSNS (1);
@@ -6123,16 +6125,16 @@ c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
       *total = COSTS_N_INSNS (1);
       op0 = code == PLUS ? XEXP (x, 0) : XEXP (x, 1);
       op1 = code == PLUS ? XEXP (x, 1) : XEXP (x, 0);
-      if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
-	  && INTEGRAL_MODE_P (GET_MODE (x))
+      if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+	  && INTEGRAL_MODE_P (mode)
 	  && GET_CODE (op0) == MULT
 	  && GET_CODE (XEXP (op0, 1)) == CONST_INT
 	  && (INTVAL (XEXP (op0, 1)) == 2
 	      || INTVAL (XEXP (op0, 1)) == 4
 	      || (code == PLUS && INTVAL (XEXP (op0, 1)) == 8)))
 	{
-	  *total += rtx_cost (XEXP (op0, 0), ASHIFT, 0, speed);
-	  *total += rtx_cost (op1, (enum rtx_code) code, 1, speed);
+	  *total += rtx_cost (XEXP (op0, 0), mode, ASHIFT, 0, speed);
+	  *total += rtx_cost (op1, mode, (enum rtx_code) code, 1, speed);
 	  return true;
 	}
       return false;
@@ -6140,21 +6142,21 @@ c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
     case MULT:
       op0 = XEXP (x, 0);
       op1 = XEXP (x, 1);
-      if (GET_MODE (x) == DFmode)
+      if (mode == DFmode)
 	{
 	  if (TARGET_FP)
 	    *total = COSTS_N_INSNS (speed ? 10 : 1);
 	  else
 	    *total = COSTS_N_INSNS (speed ? 200 : 4);
 	}
-      else if (GET_MODE (x) == SFmode)
+      else if (mode == SFmode)
 	{
 	  if (TARGET_FP)
 	    *total = COSTS_N_INSNS (speed ? 4 : 1);
 	  else
 	    *total = COSTS_N_INSNS (speed ? 100 : 4);
 	}
-      else if (GET_MODE (x) == DImode)
+      else if (mode == DImode)
 	{
 	  if (TARGET_MPY32
 	      && GET_CODE (op0) == GET_CODE (op1)
@@ -6169,7 +6171,7 @@ c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
 	    /* Maybe improve this laster.  */
 	    *total = COSTS_N_INSNS (20);
 	}
-      else if (GET_MODE (x) == SImode)
+      else if (mode == SImode)
 	{
 	  if (((GET_CODE (op0) == ZERO_EXTEND
 		|| GET_CODE (op0) == SIGN_EXTEND
@@ -6197,15 +6199,15 @@ c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
 	  else
 	    *total = COSTS_N_INSNS (6);
 	}
-      else if (GET_MODE (x) == HImode)
+      else if (mode == HImode)
 	*total = COSTS_N_INSNS (speed ? 2 : 1);
 
       if (GET_CODE (op0) != REG
 	  && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
-	*total += rtx_cost (op0, MULT, 0, speed);
+	*total += rtx_cost (op0, mode, MULT, 0, speed);
       if (op1 && GET_CODE (op1) != REG
 	  && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
-	*total += rtx_cost (op1, MULT, 1, speed);
+	*total += rtx_cost (op1, mode, MULT, 1, speed);
       return true;
 
     case UDIV:
@@ -6223,7 +6225,7 @@ c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
 	  && XEXP (op0, 1) == const0_rtx
 	  && rtx_equal_p (XEXP (x, 1), XEXP (op0, 0)))
 	{
-	  *total = rtx_cost (XEXP (x, 1), (enum rtx_code) outer_code,
+	  *total = rtx_cost (XEXP (x, 1), VOIDmode, (enum rtx_code) outer_code,
 			     opno, speed);
 	  return false;
 	}
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index ecddc8e..75ef3f7 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -153,7 +153,7 @@ static reg_class_t cris_preferred_reload_class (rtx, reg_class_t);
 
 static int cris_register_move_cost (machine_mode, reg_class_t, reg_class_t);
 static int cris_memory_move_cost (machine_mode, reg_class_t, bool);
-static bool cris_rtx_costs (rtx, int, int, int, int *, bool);
+static bool cris_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int cris_address_cost (rtx, machine_mode, addr_space_t, bool);
 static bool cris_pass_by_reference (cumulative_args_t, machine_mode,
 				    const_tree, bool);
@@ -2104,9 +2104,11 @@ cris_expand_return (bool on_stack)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-cris_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
-		bool speed)
+cris_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+		int *total, bool speed)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -2136,7 +2138,7 @@ cris_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
       return true;
 
     case CONST_DOUBLE:
-      if (x != CONST0_RTX (GET_MODE (x) == VOIDmode ? DImode : GET_MODE (x)))
+      if (x != CONST0_RTX (mode == VOIDmode ? DImode : mode))
 	*total = 12;
       else
         /* Make 0.0 cheap, else test-insns will not be used.  */
@@ -2198,9 +2200,9 @@ cris_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
 	  && !satisfies_constraint_I (XEXP (x, 1)))
 	{
 	  *total
-	    = (rtx_cost (XEXP (x, 0), (enum rtx_code) outer_code,
+	    = (rtx_cost (XEXP (x, 0), mode, (enum rtx_code) outer_code,
 			 opno, speed) + 2
-	       + 2 * GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))));
+	       + 2 * GET_MODE_NUNITS (mode));
 	  return true;
 	}
       return false;
@@ -2211,7 +2213,8 @@ cris_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
       /* fall through */
 
     case ZERO_EXTEND: case SIGN_EXTEND:
-      *total = rtx_cost (XEXP (x, 0), (enum rtx_code) outer_code, opno, speed);
+      *total = rtx_cost (XEXP (x, 0), VOIDmode, (enum rtx_code) outer_code,
+			 opno, speed);
       return true;
 
     default:
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index 60000bf..c5c5aff 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -772,9 +772,12 @@ epiphany_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-epiphany_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+epiphany_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		    int opno ATTRIBUTE_UNUSED,
 		    int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       /* Small integers in the right context are as cheap as registers.  */
@@ -815,7 +818,7 @@ epiphany_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return true;
 
     case COMPARE:
-      switch (GET_MODE (x))
+      switch (mode)
 	{
 	/* There are a number of single-insn combiner patterns that use
 	   the flag side effects of arithmetic.  */
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 46569ad..da36a13 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -383,8 +383,8 @@ static void frv_setup_incoming_varargs		(cumulative_args_t,
 						 tree, int *, int);
 static rtx frv_expand_builtin_saveregs		(void);
 static void frv_expand_builtin_va_start		(tree, rtx);
-static bool frv_rtx_costs			(rtx, int, int, int, int*,
-						 bool);
+static bool frv_rtx_costs			(rtx, machine_mode, int, int,
+						 int*, bool);
 static int frv_register_move_cost		(machine_mode,
 						 reg_class_t, reg_class_t);
 static int frv_memory_move_cost			(machine_mode,
@@ -9455,12 +9455,14 @@ frv_in_small_data_p (const_tree decl)
 \f
 static bool
 frv_rtx_costs (rtx x,
-               int code ATTRIBUTE_UNUSED,
-               int outer_code ATTRIBUTE_UNUSED,
+               machine_mode mode,
+               int outer_code,
 	       int opno ATTRIBUTE_UNUSED,
                int *total,
 	       bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   if (outer_code == MEM)
     {
       /* Don't differentiate between memory addresses.  All the ones
@@ -9498,16 +9500,16 @@ frv_rtx_costs (rtx x,
     case NOT:
     case NEG:
     case COMPARE:
-      if (GET_MODE (x) == SImode)
+      if (mode == SImode)
 	*total = COSTS_N_INSNS (1);
-      else if (GET_MODE (x) == DImode)
+      else if (mode == DImode)
         *total = COSTS_N_INSNS (2);
       else
         *total = COSTS_N_INSNS (3);
       return true;
 
     case MULT:
-      if (GET_MODE (x) == SImode)
+      if (mode == SImode)
         *total = COSTS_N_INSNS (2);
       else
         *total = COSTS_N_INSNS (6);	/* guess */
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 8a8ff53..c0f7935 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -1239,9 +1239,11 @@ h8300_shift_costs (rtx x)
 /* Worker function for TARGET_RTX_COSTS.  */
 
 static bool
-h8300_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-		 int *total, bool speed)
+h8300_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
+		 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
+  int code = GET_CODE (x);
+
   if (TARGET_H8300SX && outer_code == MEM)
     {
       /* Estimate the number of execution states needed to calculate
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index bd548a9..c17ea05 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -42088,13 +42088,12 @@ ix86_set_reg_reg_cost (machine_mode mode)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
-		bool speed)
+ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
+		int *total, bool speed)
 {
   rtx mask;
-  enum rtx_code code = (enum rtx_code) code_i;
+  enum rtx_code code = GET_CODE (x);
   enum rtx_code outer_code = (enum rtx_code) outer_code_i;
-  machine_mode mode = GET_MODE (x);
   const struct processor_costs *cost = speed ? ix86_cost : &ix86_size_cost;
 
   switch (code)
@@ -42225,7 +42224,7 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
 		  if (CONSTANT_P (XEXP (x, 1)))
 		    {
 		      *total = (cost->fabs
-				+ rtx_cost (XEXP (x, 0), code, 0, speed)
+				+ rtx_cost (XEXP (x, 0), mode, code, 0, speed)
 				+ (speed ? 2 : COSTS_N_BYTES (16)));
 		      return true;
 		    }
@@ -42281,18 +42280,18 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
         /* ??? SSE scalar/vector cost should be used here.  */
         /* ??? Bald assumption that fma has the same cost as fmul.  */
         *total = cost->fmul;
-	*total += rtx_cost (XEXP (x, 1), FMA, 1, speed);
+	*total += rtx_cost (XEXP (x, 1), mode, FMA, 1, speed);
 
         /* Negate in op0 or op2 is free: FMS, FNMA, FNMS.  */
 	sub = XEXP (x, 0);
 	if (GET_CODE (sub) == NEG)
 	  sub = XEXP (sub, 0);
-	*total += rtx_cost (sub, FMA, 0, speed);
+	*total += rtx_cost (sub, mode, FMA, 0, speed);
 
 	sub = XEXP (x, 2);
 	if (GET_CODE (sub) == NEG)
 	  sub = XEXP (sub, 0);
-	*total += rtx_cost (sub, FMA, 2, speed);
+	*total += rtx_cost (sub, mode, FMA, 2, speed);
 	return true;
       }
 
@@ -42382,8 +42381,8 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
 
   	  *total = (cost->mult_init[MODE_INDEX (mode)]
 		    + nbits * cost->mult_bit
-	            + rtx_cost (op0, outer_code, opno, speed)
-		    + rtx_cost (op1, outer_code, opno, speed));
+	            + rtx_cost (op0, mode, outer_code, opno, speed)
+		    + rtx_cost (op1, mode, outer_code, opno, speed));
 
           return true;
 	}
@@ -42417,11 +42416,12 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
 	      if (val == 2 || val == 4 || val == 8)
 		{
 		  *total = cost->lea;
-		  *total += rtx_cost (XEXP (XEXP (x, 0), 1),
+		  *total += rtx_cost (XEXP (XEXP (x, 0), 1), mode,
+				      outer_code, opno, speed);
+		  *total += rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0), mode,
 				      outer_code, opno, speed);
-		  *total += rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0),
+		  *total += rtx_cost (XEXP (x, 1), mode,
 				      outer_code, opno, speed);
-		  *total += rtx_cost (XEXP (x, 1), outer_code, opno, speed);
 		  return true;
 		}
 	    }
@@ -42432,20 +42432,22 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
 	      if (val == 2 || val == 4 || val == 8)
 		{
 		  *total = cost->lea;
-		  *total += rtx_cost (XEXP (XEXP (x, 0), 0),
+		  *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode,
+				      outer_code, opno, speed);
+		  *total += rtx_cost (XEXP (x, 1), mode,
 				      outer_code, opno, speed);
-		  *total += rtx_cost (XEXP (x, 1), outer_code, opno, speed);
 		  return true;
 		}
 	    }
 	  else if (GET_CODE (XEXP (x, 0)) == PLUS)
 	    {
 	      *total = cost->lea;
-	      *total += rtx_cost (XEXP (XEXP (x, 0), 0),
+	      *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode,
+				  outer_code, opno, speed);
+	      *total += rtx_cost (XEXP (XEXP (x, 0), 1), mode,
 				  outer_code, opno, speed);
-	      *total += rtx_cost (XEXP (XEXP (x, 0), 1),
+	      *total += rtx_cost (XEXP (x, 1), mode,
 				  outer_code, opno, speed);
-	      *total += rtx_cost (XEXP (x, 1), outer_code, opno, speed);
 	      return true;
 	    }
 	}
@@ -42478,9 +42480,9 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
 	  && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
 	{
 	  *total = (cost->add * 2
-		    + (rtx_cost (XEXP (x, 0), outer_code, opno, speed)
+		    + (rtx_cost (XEXP (x, 0), mode, outer_code, opno, speed)
 		       << (GET_MODE (XEXP (x, 0)) != DImode))
-		    + (rtx_cost (XEXP (x, 1), outer_code, opno, speed)
+		    + (rtx_cost (XEXP (x, 1), mode, outer_code, opno, speed)
 	               << (GET_MODE (XEXP (x, 1)) != DImode)));
 	  return true;
 	}
@@ -42528,9 +42530,11 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
 	{
 	  /* This kind of construct is implemented using test[bwl].
 	     Treat it as if we had an AND.  */
+	  mode = GET_MODE (XEXP (XEXP (x, 0), 0));
 	  *total = (cost->add
-		    + rtx_cost (XEXP (XEXP (x, 0), 0), outer_code, opno, speed)
-		    + rtx_cost (const1_rtx, outer_code, opno, speed));
+		    + rtx_cost (XEXP (XEXP (x, 0), 0), mode, outer_code,
+				opno, speed)
+		    + rtx_cost (const1_rtx, mode, outer_code, opno, speed));
 	  return true;
 	}
       return false;
@@ -42580,7 +42584,7 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
       /* This is masked instruction, assume the same cost,
 	 as nonmasked variant.  */
       if (TARGET_AVX512F && register_operand (mask, GET_MODE (mask)))
-	*total = rtx_cost (XEXP (x, 0), outer_code, opno, speed);
+	*total = rtx_cost (XEXP (x, 0), mode, outer_code, opno, speed);
       else
 	*total = cost->fabs;
       return true;
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 1cee14b..be3ea5f 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -240,7 +240,7 @@ static int ia64_register_move_cost (machine_mode, reg_class_t,
                                     reg_class_t);
 static int ia64_memory_move_cost (machine_mode mode, reg_class_t,
 				  bool);
-static bool ia64_rtx_costs (rtx, int, int, int, int *, bool);
+static bool ia64_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int ia64_unspec_may_trap_p (const_rtx, unsigned);
 static void fix_range (const char *);
 static struct machine_function * ia64_init_machine_status (void);
@@ -5597,9 +5597,12 @@ ia64_print_operand_punct_valid_p (unsigned char code)
 /* ??? This is incomplete.  */
 
 static bool
-ia64_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+ia64_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED,
 		int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -5643,9 +5646,9 @@ ia64_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
          which normally involves copies.  Plus there's the latency
          of the multiply itself, and the latency of the instructions to
          transfer integer regs to FP regs.  */
-      if (FLOAT_MODE_P (GET_MODE (x)))
+      if (FLOAT_MODE_P (mode))
 	*total = COSTS_N_INSNS (4);
-      else if (GET_MODE_SIZE (GET_MODE (x)) > 2)
+      else if (GET_MODE_SIZE (mode) > 2)
         *total = COSTS_N_INSNS (10);
       else
 	*total = COSTS_N_INSNS (2);
@@ -5653,7 +5656,7 @@ ia64_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 
     case PLUS:
     case MINUS:
-      if (FLOAT_MODE_P (GET_MODE (x)))
+      if (FLOAT_MODE_P (mode))
 	{
 	  *total = COSTS_N_INSNS (4);
 	  return true;
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index 518a6da..7193556 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -171,7 +171,7 @@ static bool iq2000_return_in_memory   (const_tree, const_tree);
 static void iq2000_setup_incoming_varargs (cumulative_args_t,
 					   machine_mode, tree, int *,
 					   int);
-static bool iq2000_rtx_costs          (rtx, int, int, int, int *, bool);
+static bool iq2000_rtx_costs          (rtx, machine_mode, int, int, int *, bool);
 static int  iq2000_address_cost       (rtx, machine_mode, addr_space_t,
 				       bool);
 static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT);
@@ -3308,11 +3308,11 @@ iq2000_legitimize_address (rtx xinsn, rtx old_x ATTRIBUTE_UNUSED,
 
 
 static bool
-iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+iq2000_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 		  int opno ATTRIBUTE_UNUSED, int * total,
 		  bool speed ATTRIBUTE_UNUSED)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
 
   switch (code)
     {
diff --git a/gcc/config/lm32/lm32.c b/gcc/config/lm32/lm32.c
index ba4782c..5f3a1e6 100644
--- a/gcc/config/lm32/lm32.c
+++ b/gcc/config/lm32/lm32.c
@@ -86,7 +86,7 @@ static bool lm32_in_small_data_p (const_tree);
 static void lm32_setup_incoming_varargs (cumulative_args_t cum,
 					 machine_mode mode, tree type,
 					 int *pretend_size, int no_rtl);
-static bool lm32_rtx_costs (rtx x, int code, int outer_code, int opno,
+static bool lm32_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
 			    int *total, bool speed);
 static bool lm32_can_eliminate (const int, const int);
 static bool
@@ -939,10 +939,10 @@ nonpic_symbol_mentioned_p (rtx x)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-lm32_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-		int *total, bool speed)
+lm32_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   bool small_mode;
 
   const int arithmetic_latency = 1;
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 10e53e4..40b9c5d 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -2229,9 +2229,11 @@ m32c_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS m32c_rtx_costs
 static bool
-m32c_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+m32c_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED,
 		int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
   switch (code)
     {
     case REG:
@@ -2299,7 +2301,7 @@ m32c_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 
     default:
       /* Reasonable default.  */
-      if (TARGET_A16 && GET_MODE(x) == SImode)
+      if (TARGET_A16 && mode == SImode)
 	*total += COSTS_N_INSNS (2);
       break;
     }
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index bf88ef2..4710a48 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -103,7 +103,7 @@ static bool m32r_function_value_regno_p (const unsigned int);
 static void m32r_setup_incoming_varargs (cumulative_args_t, machine_mode,
 					 tree, int *, int);
 static void init_idents (void);
-static bool m32r_rtx_costs (rtx, int, int, int, int *, bool speed);
+static bool m32r_rtx_costs (rtx, machine_mode, int, int, int *, bool speed);
 static int m32r_memory_move_cost (machine_mode, reg_class_t, bool);
 static bool m32r_pass_by_reference (cumulative_args_t, machine_mode,
 				    const_tree, bool);
@@ -1366,10 +1366,13 @@ m32r_memory_move_cost (machine_mode mode,
 }
 
 static bool
-m32r_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+m32r_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+		int outer_code ATTRIBUTE_UNUSED,
 		int opno ATTRIBUTE_UNUSED, int *total,
 		bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       /* Small integers are as cheap as registers.  4 byte values can be
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 3d81449..ab5615b 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -170,7 +170,7 @@ static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
 static bool m68k_ok_for_sibcall_p (tree, tree);
 static bool m68k_tls_symbol_p (rtx);
 static rtx m68k_legitimize_address (rtx, rtx, machine_mode);
-static bool m68k_rtx_costs (rtx, int, int, int, int *, bool);
+static bool m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 #if M68K_HONOR_TARGET_STRICT_ALIGNMENT
 static bool m68k_return_in_memory (const_tree, const_tree);
 #endif
@@ -2792,9 +2792,12 @@ const_int_cost (HOST_WIDE_INT i)
 }
 
 static bool
-m68k_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+m68k_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED,
 		int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -2851,7 +2854,7 @@ m68k_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 
     case PLUS:
       /* An lea costs about three times as much as a simple add.  */
-      if (GET_MODE (x) == SImode
+      if (mode == SImode
 	  && GET_CODE (XEXP (x, 1)) == REG
 	  && GET_CODE (XEXP (x, 0)) == MULT
 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
@@ -2907,9 +2910,9 @@ m68k_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
     case MULT:
       if ((GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
 	   || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
-	  && GET_MODE (x) == SImode)
+	  && mode == SImode)
         *total = COSTS_N_INSNS (MULW_COST);
-      else if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
+      else if (mode == QImode || mode == HImode)
         *total = COSTS_N_INSNS (MULW_COST);
       else
         *total = COSTS_N_INSNS (MULL_COST);
@@ -2919,7 +2922,7 @@ m68k_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
     case UDIV:
     case MOD:
     case UMOD:
-      if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
+      if (mode == QImode || mode == HImode)
         *total = COSTS_N_INSNS (DIVW_COST);	/* div.w */
       else if (TARGET_CF_HWDIV)
         *total = COSTS_N_INSNS (18);
diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c
index 9370902..5926fd9 100644
--- a/gcc/config/mcore/mcore.c
+++ b/gcc/config/mcore/mcore.c
@@ -141,7 +141,7 @@ static const char *mcore_strip_name_encoding	(const char *);
 static int        mcore_const_costs             (rtx, RTX_CODE);
 static int        mcore_and_cost                (rtx);
 static int        mcore_ior_cost                (rtx);
-static bool       mcore_rtx_costs		(rtx, int, int, int,
+static bool       mcore_rtx_costs		(rtx, machine_mode, int, int,
 						 int *, bool);
 static void       mcore_external_libcall	(rtx);
 static bool       mcore_return_in_memory	(const_tree, const_tree);
@@ -533,9 +533,12 @@ mcore_ior_cost (rtx x)
 }
 
 static bool
-mcore_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+mcore_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
+		 int opno ATTRIBUTE_UNUSED,
 		 int * total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c
index 5f710e2..616bbb9 100644
--- a/gcc/config/mep/mep.c
+++ b/gcc/config/mep/mep.c
@@ -238,7 +238,7 @@ static void mep_move_ready_insn (rtx_insn **, int, rtx_insn *);
 static int mep_sched_reorder (FILE *, int, rtx_insn **, int *, int);
 static rtx_insn *mep_make_bundle (rtx, rtx_insn *);
 static void mep_bundle_insns (rtx_insn *);
-static bool mep_rtx_cost (rtx, int, int, int, int *, bool);
+static bool mep_rtx_cost (rtx, machine_mode, int, int, int *, bool);
 static int mep_address_cost (rtx, machine_mode, addr_space_t, bool);
 static void mep_setup_incoming_varargs (cumulative_args_t, machine_mode,
 					tree, int *, int);
@@ -7128,10 +7128,13 @@ mep_expand_binary_intrinsic (int ATTRIBUTE_UNUSED immediate,
 }
 
 static bool
-mep_rtx_cost (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+mep_rtx_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+	      int outer_code ATTRIBUTE_UNUSED,
 	      int opno ATTRIBUTE_UNUSED, int *total,
 	      bool ATTRIBUTE_UNUSED speed_t)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 5ded8bc..29eebea 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -1238,11 +1238,11 @@ microblaze_expand_block_move (rtx dest, rtx src, rtx length, rtx align_rtx)
 }
 
 static bool
-microblaze_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+microblaze_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 		      int opno ATTRIBUTE_UNUSED, int *total,
 		      bool speed ATTRIBUTE_UNUSED)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
 
   switch (code)
     {
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index d427c0c..0e4b0d1 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -2436,7 +2436,7 @@ mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
   return mips_classify_address (&addr, x, mode, strict_p);
 }
 
-/* Return true if X is a legitimate $sp-based address for mode MDOE.  */
+/* Return true if X is a legitimate $sp-based address for mode MODE.  */
 
 bool
 mips_stack_address_p (rtx x, machine_mode mode)
@@ -3729,8 +3729,8 @@ mips_binary_cost (rtx x, int single_cost, int double_cost, bool speed)
   else
     cost = single_cost;
   return (cost
-	  + set_src_cost (XEXP (x, 0), speed)
-	  + rtx_cost (XEXP (x, 1), GET_CODE (x), 1, speed));
+	  + set_src_cost (XEXP (x, 0), GET_MODE (x), speed)
+	  + rtx_cost (XEXP (x, 1), GET_MODE (x), GET_CODE (x), 1, speed));
 }
 
 /* Return the cost of floating-point multiplications of mode MODE.  */
@@ -3831,10 +3831,10 @@ mips_set_reg_reg_cost (machine_mode mode)
 /* Implement TARGET_RTX_COSTS.  */
 
 static bool
-mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-		int *total, bool speed)
+mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   bool float_mode_p = FLOAT_MODE_P (mode);
   int cost;
   rtx addr;
@@ -3933,7 +3933,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	     for a word or doubleword operation, so we cannot rely on
 	     the result of mips_build_integer.  */
 	  else if (!TARGET_MIPS16
-		   && (outer_code == SET || mode == VOIDmode))
+		   && (outer_code == SET || GET_MODE (x) == VOIDmode))
 	    cost = 1;
 	  *total = COSTS_N_INSNS (cost);
 	  return true;
@@ -3979,7 +3979,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	  && UINTVAL (XEXP (x, 1)) == 0xffffffff)
 	{
 	  *total = (mips_zero_extend_cost (mode, XEXP (x, 0))
-		    + set_src_cost (XEXP (x, 0), speed));
+		    + set_src_cost (XEXP (x, 0), mode, speed));
 	  return true;
 	}
       if (ISA_HAS_CINS && CONST_INT_P (XEXP (x, 1)))
@@ -3989,7 +3989,8 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	      && CONST_INT_P (XEXP (op, 1))
 	      && mask_low_and_shift_p (mode, XEXP (x, 1), XEXP (op, 1), 32))
 	    {
-	      *total = COSTS_N_INSNS (1) + set_src_cost (XEXP (op, 0), speed);
+	      *total = COSTS_N_INSNS (1);
+	      *total += set_src_cost (XEXP (op, 0), mode, speed);
 	      return true;
 	    }
 	}
@@ -4001,8 +4002,8 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	{
 	  cost = GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1;
           *total = (COSTS_N_INSNS (cost)
-		    + set_src_cost (XEXP (XEXP (x, 0), 0), speed)
-		    + set_src_cost (XEXP (XEXP (x, 1), 0), speed));
+		    + set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
+		    + set_src_cost (XEXP (XEXP (x, 1), 0), mode, speed));
 	  return true;
 	}
 	    
@@ -4038,7 +4039,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
     case LO_SUM:
       /* Low-part immediates need an extended MIPS16 instruction.  */
       *total = (COSTS_N_INSNS (TARGET_MIPS16 ? 2 : 1)
-		+ set_src_cost (XEXP (x, 0), speed));
+		+ set_src_cost (XEXP (x, 0), mode, speed));
       return true;
 
     case LT:
@@ -4079,17 +4080,17 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	  if (GET_CODE (op0) == MULT && GET_CODE (XEXP (op0, 0)) == NEG)
 	    {
 	      *total = (mips_fp_mult_cost (mode)
-			+ set_src_cost (XEXP (XEXP (op0, 0), 0), speed)
-			+ set_src_cost (XEXP (op0, 1), speed)
-			+ set_src_cost (op1, speed));
+			+ set_src_cost (XEXP (XEXP (op0, 0), 0), mode, speed)
+			+ set_src_cost (XEXP (op0, 1), mode, speed)
+			+ set_src_cost (op1, mode, speed));
 	      return true;
 	    }
 	  if (GET_CODE (op1) == MULT)
 	    {
 	      *total = (mips_fp_mult_cost (mode)
-			+ set_src_cost (op0, speed)
-			+ set_src_cost (XEXP (op1, 0), speed)
-			+ set_src_cost (XEXP (op1, 1), speed));
+			+ set_src_cost (op0, mode, speed)
+			+ set_src_cost (XEXP (op1, 0), mode, speed)
+			+ set_src_cost (XEXP (op1, 1), mode, speed));
 	      return true;
 	    }
 	}
@@ -4119,8 +4120,8 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	  if (const_immlsa_operand (op2, mode))
 	    {
 	      *total = (COSTS_N_INSNS (1)
-			+ set_src_cost (XEXP (XEXP (x, 0), 0), speed)
-			+ set_src_cost (XEXP (x, 1), speed));
+			+ set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
+			+ set_src_cost (XEXP (x, 1), mode, speed));
 	      return true;
 	    }
 	}
@@ -4147,9 +4148,9 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	      && GET_CODE (XEXP (op, 0)) == MULT)
 	    {
 	      *total = (mips_fp_mult_cost (mode)
-			+ set_src_cost (XEXP (XEXP (op, 0), 0), speed)
-			+ set_src_cost (XEXP (XEXP (op, 0), 1), speed)
-			+ set_src_cost (XEXP (op, 1), speed));
+			+ set_src_cost (XEXP (XEXP (op, 0), 0), mode, speed)
+			+ set_src_cost (XEXP (XEXP (op, 0), 1), mode, speed)
+			+ set_src_cost (XEXP (op, 1), mode, speed));
 	      return true;
 	    }
 	}
@@ -4192,10 +4193,10 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	  if (outer_code == SQRT || GET_CODE (XEXP (x, 1)) == SQRT)
 	    /* An rsqrt<mode>a or rsqrt<mode>b pattern.  Count the
 	       division as being free.  */
-	    *total = set_src_cost (XEXP (x, 1), speed);
+	    *total = set_src_cost (XEXP (x, 1), mode, speed);
 	  else
 	    *total = (mips_fp_div_cost (mode)
-		      + set_src_cost (XEXP (x, 1), speed));
+		      + set_src_cost (XEXP (x, 1), mode, speed));
 	  return true;
 	}
       /* Fall through.  */
@@ -4223,7 +4224,8 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	      && CONST_INT_P (XEXP (x, 1))
 	      && exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
 	    {
-	      *total = COSTS_N_INSNS (2) + set_src_cost (XEXP (x, 0), speed);
+	      *total = COSTS_N_INSNS (2);
+	      *total += set_src_cost (XEXP (x, 0), mode, speed);
 	      return true;
 	    }
 	  *total = COSTS_N_INSNS (mips_idiv_insns ());
@@ -4246,7 +4248,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	  && GET_MODE (XEXP (x, 0)) == QImode
 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS)
 	{
-	  *total = set_src_cost (XEXP (XEXP (x, 0), 0), speed);
+	  *total = set_src_cost (XEXP (XEXP (x, 0), 0), VOIDmode, speed);
 	  return true;
 	}
       *total = mips_zero_extend_cost (mode, XEXP (x, 0));
@@ -4289,9 +4291,10 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	      if (ISA_HAS_R6DMUL
 		  && GET_CODE (op) == ZERO_EXTEND
 		  && GET_MODE (op) == DImode)
-		*total += rtx_cost (op, MULT, i, speed);
+		*total += rtx_cost (op, DImode, MULT, i, speed);
 	      else
-		*total += rtx_cost (XEXP (op, 0), GET_CODE (op), 0, speed);
+		*total += rtx_cost (XEXP (op, 0), VOIDmode, GET_CODE (op),
+				    0, speed);
 	    }
 
 	  return true;
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index 28b4a3e..0afcbfb 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -154,7 +154,7 @@ static void mmix_setup_incoming_varargs
   (cumulative_args_t, machine_mode, tree, int *, int);
 static void mmix_file_start (void);
 static void mmix_file_end (void);
-static bool mmix_rtx_costs (rtx, int, int, int, int *, bool);
+static bool mmix_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int mmix_register_move_cost (machine_mode,
 				    reg_class_t, reg_class_t);
 static rtx mmix_struct_value_rtx (tree, int);
@@ -1179,7 +1179,7 @@ mmix_reversible_cc_mode (machine_mode mode)
 
 static bool
 mmix_rtx_costs (rtx x ATTRIBUTE_UNUSED,
-		int code ATTRIBUTE_UNUSED,
+		machine_mode mode ATTRIBUTE_UNUSED,
 		int outer_code ATTRIBUTE_UNUSED,
 		int opno ATTRIBUTE_UNUSED,
 		int *total ATTRIBUTE_UNUSED,
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index 1e6c28f..b96ac1e 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -2232,7 +2232,7 @@ mn10300_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
       return speed ? 2 : 6;
 
     default:
-      return rtx_cost (x, MEM, 0, speed);
+      return rtx_cost (x, Pmode, MEM, 0, speed);
     }
 }
 
@@ -2346,13 +2346,14 @@ mn10300_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
    to represent cycles.  Size-relative costs are in bytes.  */
 
 static bool
-mn10300_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-		   int *ptotal, bool speed)
+mn10300_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		   int opno ATTRIBUTE_UNUSED, int *ptotal, bool speed)
 {
   /* This value is used for SYMBOL_REF etc where we want to pretend
      we have a full 32-bit constant.  */
   HOST_WIDE_INT i = 0x12345678;
   int total;
+  int code = GET_CODE (x);
 
   switch (code)
     {
@@ -2438,7 +2439,7 @@ mn10300_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	  i = INTVAL (XEXP (x, 1));
 	  if (i == 1 || i == 4)
 	    {
-	      total = 1 + rtx_cost (XEXP (x, 0), PLUS, 0, speed);
+	      total = 1 + rtx_cost (XEXP (x, 0), mode, PLUS, 0, speed);
 	      goto alldone;
 	    }
 	}
@@ -2494,7 +2495,7 @@ mn10300_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       break;
 
     case MEM:
-      total = mn10300_address_cost (XEXP (x, 0), GET_MODE (x),
+      total = mn10300_address_cost (XEXP (x, 0), mode,
 				    MEM_ADDR_SPACE (x), speed);
       if (speed)
 	total = COSTS_N_INSNS (2 + total);
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index b76fe93..90b3db1 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -1009,17 +1009,19 @@ msp430_legitimate_constant (machine_mode mode, rtx x)
 #undef  TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS msp430_rtx_costs
 
-static bool msp430_rtx_costs (rtx   x ATTRIBUTE_UNUSED,
-			      int   code,
-			      int   outer_code ATTRIBUTE_UNUSED,
-			      int   opno ATTRIBUTE_UNUSED,
-			      int * total,
-			      bool  speed ATTRIBUTE_UNUSED)
+static bool msp430_rtx_costs (rtx	   x ATTRIBUTE_UNUSED,
+			      machine_mode mode,
+			      int	   outer_code ATTRIBUTE_UNUSED,
+			      int	   opno ATTRIBUTE_UNUSED,
+			      int *	   total,
+			      bool	   speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case SIGN_EXTEND:
-      if (GET_MODE (x) == SImode && outer_code == SET)
+      if (mode == SImode && outer_code == SET)
 	{
 	  *total = COSTS_N_INSNS (4);
 	  return true;
diff --git a/gcc/config/nds32/nds32-cost.c b/gcc/config/nds32/nds32-cost.c
index d9bb307..c88eea3 100644
--- a/gcc/config/nds32/nds32-cost.c
+++ b/gcc/config/nds32/nds32-cost.c
@@ -72,12 +72,14 @@
 
 bool
 nds32_rtx_costs_impl (rtx x,
-		      int code,
+		      machine_mode mode ATTRIBUTE_UNUSED,
 		      int outer_code,
 		      int opno ATTRIBUTE_UNUSED,
 		      int *total,
 		      bool speed)
 {
+  int code = GET_CODE (x);
+
   /* According to 'speed', goto suitable cost model section.  */
   if (speed)
     goto performance_cost;
diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
index 620d897..199e703 100644
--- a/gcc/config/nds32/nds32-protos.h
+++ b/gcc/config/nds32/nds32-protos.h
@@ -144,7 +144,7 @@ extern bool nds32_isr_function_p (tree);
 
 /* Auxiliary functions for cost calculation.  */
 
-extern bool nds32_rtx_costs_impl (rtx, int, int, int, int *, bool);
+extern bool nds32_rtx_costs_impl (rtx, machine_mode, int, int, int *, bool);
 extern int nds32_address_cost_impl (rtx, machine_mode, addr_space_t, bool);
 
 /* ------------------------------------------------------------------------ */
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index 8623983..6472a89 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -2105,13 +2105,13 @@ nds32_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
    Refer to gcc/rtlanal.c for more information.  */
 static bool
 nds32_rtx_costs (rtx x,
-		 int code,
+		 machine_mode mode,
 		 int outer_code,
 		 int opno,
 		 int *total,
 		 bool speed)
 {
-  return nds32_rtx_costs_impl (x, code, outer_code, opno, total, speed);
+  return nds32_rtx_costs_impl (x, mode, outer_code, opno, total, speed);
 }
 
 static int
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index 608a4c3..500f7e6 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -1096,10 +1096,13 @@ nios2_simple_const_p (const_rtx cst)
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.  */
 static bool
-nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+nios2_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+		 int outer_code ATTRIBUTE_UNUSED,
 		 int opno ATTRIBUTE_UNUSED,
 		 int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       case CONST_INT:
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 2768486..9475b2e 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -111,7 +111,7 @@ static void fix_range (const char *);
 static int hppa_register_move_cost (machine_mode mode, reg_class_t,
 				    reg_class_t);
 static int hppa_address_cost (rtx, machine_mode mode, addr_space_t, bool);
-static bool hppa_rtx_costs (rtx, int, int, int, int *, bool);
+static bool hppa_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static inline rtx force_mode (machine_mode, rtx);
 static void pa_reorg (void);
 static void pa_combine_instructions (void);
@@ -1485,10 +1485,12 @@ hppa_address_cost (rtx X, machine_mode mode ATTRIBUTE_UNUSED,
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-hppa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+hppa_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED,
 		int *total, bool speed ATTRIBUTE_UNUSED)
 {
   int factor;
+  int code = GET_CODE (x);
 
   switch (code)
     {
@@ -1520,14 +1522,14 @@ hppa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return true;
 
     case MULT:
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
 	{
 	  *total = COSTS_N_INSNS (3);
 	  return true;
 	}
 
       /* A mode size N times larger than SImode needs O(N*N) more insns.  */
-      factor = GET_MODE_SIZE (GET_MODE (x)) / 4;
+      factor = GET_MODE_SIZE (mode) / 4;
       if (factor == 0)
 	factor = 1;
 
@@ -1538,7 +1540,7 @@ hppa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return true;
 
     case DIV:
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
 	{
 	  *total = COSTS_N_INSNS (14);
 	  return true;
@@ -1549,7 +1551,7 @@ hppa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
     case MOD:
     case UMOD:
       /* A mode size N times larger than SImode needs O(N*N) more insns.  */
-      factor = GET_MODE_SIZE (GET_MODE (x)) / 4;
+      factor = GET_MODE_SIZE (mode) / 4;
       if (factor == 0)
 	factor = 1;
 
@@ -1558,7 +1560,7 @@ hppa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 
     case PLUS: /* this includes shNadd insns */
     case MINUS:
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
 	{
 	  *total = COSTS_N_INSNS (3);
 	  return true;
@@ -1566,7 +1568,7 @@ hppa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 
       /* A size N times larger than UNITS_PER_WORD needs N times as
 	 many insns, taking N times as long.  */
-      factor = GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD;
+      factor = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
       if (factor == 0)
 	factor = 1;
       *total = factor * COSTS_N_INSNS (1);
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index 60d0635..145d43c 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -163,7 +163,7 @@ decode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
 
 static const char *singlemove_string (rtx *);
 static bool pdp11_assemble_integer (rtx, unsigned int, int);
-static bool pdp11_rtx_costs (rtx, int, int, int, int *, bool);
+static bool pdp11_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static bool pdp11_return_in_memory (const_tree, const_tree);
 static rtx pdp11_function_value (const_tree, const_tree, bool);
 static rtx pdp11_libcall_value (machine_mode, const_rtx);
@@ -915,10 +915,12 @@ pdp11_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
 }
 
 static bool
-pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+pdp11_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 		 int opno ATTRIBUTE_UNUSED, int *total,
 		 bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -977,9 +979,9 @@ pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
       return false;
 
     case SIGN_EXTEND:
-      if (GET_MODE (x) == HImode)
+      if (mode == HImode)
       	*total = COSTS_N_INSNS (1);
-      else if (GET_MODE (x) == SImode)
+      else if (mode == SImode)
 	*total = COSTS_N_INSNS (6);
       else
 	*total = COSTS_N_INSNS (2);
@@ -990,14 +992,14 @@ pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
     case ASHIFTRT:
       if (optimize_size)
         *total = COSTS_N_INSNS (1);
-      else if (GET_MODE (x) ==  QImode)
+      else if (mode ==  QImode)
         {
           if (GET_CODE (XEXP (x, 1)) != CONST_INT)
    	    *total = COSTS_N_INSNS (8); /* worst case */
           else
 	    *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
         }
-      else if (GET_MODE (x) == HImode)
+      else if (mode == HImode)
         {
           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
             {
@@ -1009,7 +1011,7 @@ pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
           else
             *total = COSTS_N_INSNS (10); /* worst case */
         }
-      else if (GET_MODE (x) == SImode)
+      else if (mode == SImode)
         {
           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
 	    *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index 33f4e64..99aaf63 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -4158,20 +4158,22 @@ rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
 #define TARGET_RTX_COSTS rl78_rtx_costs
 
 static bool
-rl78_rtx_costs (rtx   x,
-		int   code,
-		int   outer_code ATTRIBUTE_UNUSED,
-		int   opno ATTRIBUTE_UNUSED,
-		int * total,
-		bool  speed ATTRIBUTE_UNUSED)
+rl78_rtx_costs (rtx          x,
+		machine_mode mode,
+		int          outer_code ATTRIBUTE_UNUSED,
+		int          opno ATTRIBUTE_UNUSED,
+		int *        total,
+		bool         speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   if (code == IF_THEN_ELSE)
     {
       *total = COSTS_N_INSNS (10);
       return true;
     }
 
-  if (GET_MODE (x) == SImode)
+  if (mode == SImode)
     {
       switch (code)
 	{
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 56acc86..c7c24db 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1116,7 +1116,7 @@ static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
 static tree rs6000_builtin_vectorized_libmass (tree, tree, tree);
 static void rs6000_emit_set_long_const (rtx, HOST_WIDE_INT);
 static int rs6000_memory_move_cost (machine_mode, reg_class_t, bool);
-static bool rs6000_debug_rtx_costs (rtx, int, int, int, int *, bool);
+static bool rs6000_debug_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int rs6000_debug_address_cost (rtx, machine_mode, addr_space_t,
 				      bool);
 static int rs6000_debug_adjust_cost (rtx_insn *, rtx, rtx_insn *, int);
@@ -30637,10 +30637,10 @@ rs6000_xcoff_encode_section_info (tree decl, rtx rtl, int first)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-rs6000_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
-		  int *total, bool speed)
+rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		  int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
 
   switch (code)
     {
@@ -30961,16 +30961,16 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 /* Debug form of r6000_rtx_costs that is selected if -mdebug=cost.  */
 
 static bool
-rs6000_debug_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
-			bool speed)
+rs6000_debug_rtx_costs (rtx x, machine_mode mode, int outer_code,
+			int opno, int *total, bool speed)
 {
-  bool ret = rs6000_rtx_costs (x, code, outer_code, opno, total, speed);
+  bool ret = rs6000_rtx_costs (x, mode, outer_code, opno, total, speed);
 
   fprintf (stderr,
-	   "\nrs6000_rtx_costs, return = %s, code = %s, outer_code = %s, "
+	   "\nrs6000_rtx_costs, return = %s, mode = %s, outer_code = %s, "
 	   "opno = %d, total = %d, speed = %s, x:\n",
 	   ret ? "complete" : "scan inner",
-	   GET_RTX_NAME (code),
+	   GET_MODE_NAME (mode),
 	   GET_RTX_NAME (outer_code),
 	   opno,
 	   *total,
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 9807e64..b6f0ac4 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -3183,13 +3183,14 @@ s390_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
 /* Compute a (partial) cost for rtx X.  Return true if the complete
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.
-   CODE contains GET_CODE (x), OUTER_CODE contains the code
-   of the superexpression of x.  */
+   OUTER_CODE contains the code of the superexpression of x.  */
 
 static bool
-s390_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+s390_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED,
 		int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
   switch (code)
     {
     case CONST:
@@ -3220,7 +3221,7 @@ s390_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return false;
 
     case MULT:
-      switch (GET_MODE (x))
+      switch (mode)
 	{
 	case SImode:
 	  {
@@ -3279,7 +3280,7 @@ s390_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return false;
 
     case FMA:
-      switch (GET_MODE (x))
+      switch (mode)
 	{
 	case DFmode:
 	  *total = s390_cost->madbr;
@@ -3293,18 +3294,18 @@ s390_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       /* Negate in the third argument is free: FMSUB.  */
       if (GET_CODE (XEXP (x, 2)) == NEG)
 	{
-	  *total += (rtx_cost (XEXP (x, 0), FMA, 0, speed)
-		     + rtx_cost (XEXP (x, 1), FMA, 1, speed)
-		     + rtx_cost (XEXP (XEXP (x, 2), 0), FMA, 2, speed));
+	  *total += (rtx_cost (XEXP (x, 0), mode, FMA, 0, speed)
+		     + rtx_cost (XEXP (x, 1), mode, FMA, 1, speed)
+		     + rtx_cost (XEXP (XEXP (x, 2), 0), mode, FMA, 2, speed));
 	  return true;
 	}
       return false;
 
     case UDIV:
     case UMOD:
-      if (GET_MODE (x) == TImode) 	       /* 128 bit division */
+      if (mode == TImode) 	       /* 128 bit division */
 	*total = s390_cost->dlgr;
-      else if (GET_MODE (x) == DImode)
+      else if (mode == DImode)
 	{
 	  rtx right = XEXP (x, 1);
 	  if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */
@@ -3312,13 +3313,13 @@ s390_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	  else 	                               /* 64 by 64 bit division */
 	    *total = s390_cost->dlgr;
 	}
-      else if (GET_MODE (x) == SImode)         /* 32 bit division */
+      else if (mode == SImode)         /* 32 bit division */
 	*total = s390_cost->dlr;
       return false;
 
     case DIV:
     case MOD:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	{
 	  rtx right = XEXP (x, 1);
 	  if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */
@@ -3329,26 +3330,26 @@ s390_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	  else 	                               /* 64 by 64 bit division */
 	    *total = s390_cost->dsgr;
 	}
-      else if (GET_MODE (x) == SImode)         /* 32 bit division */
+      else if (mode == SImode)         /* 32 bit division */
 	*total = s390_cost->dlr;
-      else if (GET_MODE (x) == SFmode)
+      else if (mode == SFmode)
 	{
 	  *total = s390_cost->debr;
 	}
-      else if (GET_MODE (x) == DFmode)
+      else if (mode == DFmode)
 	{
 	  *total = s390_cost->ddbr;
 	}
-      else if (GET_MODE (x) == TFmode)
+      else if (mode == TFmode)
 	{
 	  *total = s390_cost->dxbr;
 	}
       return false;
 
     case SQRT:
-      if (GET_MODE (x) == SFmode)
+      if (mode == SFmode)
 	*total = s390_cost->sqebr;
-      else if (GET_MODE (x) == DFmode)
+      else if (mode == DFmode)
 	*total = s390_cost->sqdbr;
       else /* TFmode */
 	*total = s390_cost->sqxbr;
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index e5fcd768..026777b 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -282,7 +282,7 @@ static int addsubcosts (rtx);
 static int multcosts (rtx);
 static bool unspec_caller_rtx_p (rtx);
 static bool sh_cannot_copy_insn_p (rtx_insn *);
-static bool sh_rtx_costs (rtx, int, int, int, int *, bool);
+static bool sh_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int sh_address_cost (rtx, machine_mode, addr_space_t, bool);
 static int sh_pr_n_sets (void);
 static rtx sh_allocate_initial_value (rtx);
@@ -3270,7 +3270,7 @@ and_xor_ior_costs (rtx x, int code)
 	  || satisfies_constraint_J16 (XEXP (x, 1)))
 	return 1;
       else
-	return 1 + rtx_cost (XEXP (x, 1), AND, 1, !optimize_size);
+	return 1 + rtx_cost (XEXP (x, 1), GET_MODE (x), AND, 1, !optimize_size);
     }
 
   /* These constants are single cycle extu.[bw] instructions.  */
@@ -3410,9 +3410,12 @@ multcosts (rtx x ATTRIBUTE_UNUSED)
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.  */
 static bool
-sh_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+sh_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
+	      int opno ATTRIBUTE_UNUSED,
 	      int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
       /* The lower-subreg pass decides whether to split multi-word regs
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 995a769..62bb0ab 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -595,7 +595,7 @@ static rtx sparc_tls_get_addr (void);
 static rtx sparc_tls_got (void);
 static int sparc_register_move_cost (machine_mode,
 				     reg_class_t, reg_class_t);
-static bool sparc_rtx_costs (rtx, int, int, int, int *, bool);
+static bool sparc_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static rtx sparc_function_value (const_tree, const_tree, bool);
 static rtx sparc_libcall_value (machine_mode, const_rtx);
 static bool sparc_function_value_regno_p (const unsigned int);
@@ -10932,10 +10932,11 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
    ??? the latencies and then CSE will just use that.  */
 
 static bool
-sparc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+sparc_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		 int opno ATTRIBUTE_UNUSED,
 		 int *total, bool speed ATTRIBUTE_UNUSED)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   bool float_mode_p = FLOAT_MODE_P (mode);
 
   switch (code)
@@ -10959,7 +10960,7 @@ sparc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return true;
 
     case CONST_DOUBLE:
-      if (GET_MODE (x) == VOIDmode
+      if (mode == VOIDmode
 	  && ((CONST_DOUBLE_HIGH (x) == 0
 	       && CONST_DOUBLE_LOW (x) < 0x1000)
 	      || (CONST_DOUBLE_HIGH (x) == -1
@@ -11011,12 +11012,12 @@ sparc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	sub = XEXP (x, 0);
 	if (GET_CODE (sub) == NEG)
 	  sub = XEXP (sub, 0);
-	*total += rtx_cost (sub, FMA, 0, speed);
+	*total += rtx_cost (sub, mode, FMA, 0, speed);
 
 	sub = XEXP (x, 2);
 	if (GET_CODE (sub) == NEG)
 	  sub = XEXP (sub, 0);
-	*total += rtx_cost (sub, FMA, 2, speed);
+	*total += rtx_cost (sub, mode, FMA, 2, speed);
 	return true;
       }
 
@@ -11135,7 +11136,7 @@ sparc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 
     case IOR:
       /* Handle the NAND vector patterns.  */
-      if (sparc_vector_mode_supported_p (GET_MODE (x))
+      if (sparc_vector_mode_supported_p (mode)
 	  && GET_CODE (XEXP (x, 0)) == NOT
 	  && GET_CODE (XEXP (x, 1)) == NOT)
 	{
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 8f02ef8..e93c054 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -5243,11 +5243,11 @@ spu_asm_globalize_label (FILE * file, const char *name)
 }
 
 static bool
-spu_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+spu_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 	       int opno ATTRIBUTE_UNUSED, int *total,
 	       bool speed ATTRIBUTE_UNUSED)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   int cost = COSTS_N_INSNS (2);
 
   /* Folding to a CONST_VECTOR will use extra space but there might
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index d6247a0..52124a5 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -84,7 +84,6 @@ static void xstormy16_asm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
 
 static void xstormy16_init_builtins (void);
 static rtx xstormy16_expand_builtin (tree, rtx, rtx, machine_mode, int);
-static bool xstormy16_rtx_costs (rtx, int, int, int, int *, bool);
 static int xstormy16_address_cost (rtx, machine_mode, addr_space_t, bool);
 static bool xstormy16_return_in_memory (const_tree, const_tree);
 
@@ -95,10 +94,13 @@ static GTY(()) section *bss100_section;
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-xstormy16_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+xstormy16_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+		     int outer_code ATTRIBUTE_UNUSED,
 		     int opno ATTRIBUTE_UNUSED, int *total,
 		     bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index b778919..1a99908 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -557,9 +557,11 @@ tilegx_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 
 /* Implement TARGET_RTX_COSTS.  */
 static bool
-tilegx_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
-		  bool speed)
+tilegx_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+		  int *total, bool speed)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -626,9 +628,9 @@ tilegx_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
       if (GET_CODE (XEXP (x, 0)) == MULT
 	  && cint_248_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
 	{
-	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0),
+	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0), mode,
 			      (enum rtx_code) outer_code, opno, speed)
-		    + rtx_cost (XEXP (x, 1),
+		    + rtx_cost (XEXP (x, 1), mode,
 				(enum rtx_code) outer_code, opno, speed)
 		    + COSTS_N_INSNS (1));
 	  return true;
diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
index e1b5acd..a264950 100644
--- a/gcc/config/tilepro/tilepro.c
+++ b/gcc/config/tilepro/tilepro.c
@@ -499,9 +499,11 @@ tilepro_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p,
 
 /* Implement TARGET_RTX_COSTS.  */
 static bool
-tilepro_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
-		   bool speed)
+tilepro_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+		   int *total, bool speed)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -568,9 +570,9 @@ tilepro_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
       if (GET_CODE (XEXP (x, 0)) == MULT
 	  && cint_248_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
 	{
-	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0),
+	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0), mode,
 			      (enum rtx_code) outer_code, opno, speed)
-		    + rtx_cost (XEXP (x, 1),
+		    + rtx_cost (XEXP (x, 1), mode,
 				(enum rtx_code) outer_code, opno, speed)
 		    + COSTS_N_INSNS (1));
 	  return true;
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 490c19c..d412a6a 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -359,13 +359,10 @@ const_costs (rtx r, enum rtx_code c)
 }
 
 static bool
-v850_rtx_costs (rtx x,
-                int codearg,
-                int outer_code ATTRIBUTE_UNUSED,
-		int opno ATTRIBUTE_UNUSED,
-                int * total, bool speed)
+v850_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
-  enum rtx_code code = (enum rtx_code) codearg;
+  enum rtx_code code = GET_CODE (x);
 
   switch (code)
     {
@@ -389,9 +386,7 @@ v850_rtx_costs (rtx x,
 
     case MULT:
       if (TARGET_V850E
-	  && (   GET_MODE (x) == SImode
-	      || GET_MODE (x) == HImode
-	      || GET_MODE (x) == QImode))
+	  && (mode == SImode || mode == HImode || mode == QImode))
         {
 	  if (GET_CODE (XEXP (x, 1)) == REG)
 	    *total = 4;
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 811d058..27c1d2d 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -72,7 +72,7 @@ static void vax_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
 				 HOST_WIDE_INT, tree);
 static int vax_address_cost_1 (rtx);
 static int vax_address_cost (rtx, machine_mode, addr_space_t, bool);
-static bool vax_rtx_costs (rtx, int, int, int, int *, bool);
+static bool vax_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static rtx vax_function_arg (cumulative_args_t, machine_mode,
 			     const_tree, bool);
 static void vax_function_arg_advance (cumulative_args_t, machine_mode,
@@ -772,10 +772,11 @@ vax_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
    costs on a per cpu basis.  */
 
 static bool
-vax_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
+	       int opno ATTRIBUTE_UNUSED,
 	       int *total, bool speed ATTRIBUTE_UNUSED)
 {
-  machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
   int i = 0;				   /* may be modified in switch */
   const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
 
@@ -815,7 +816,7 @@ vax_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return true;
 
     case CONST_DOUBLE:
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
 	*total = vax_float_literal (x) ? 5 : 8;
       else
 	*total = ((CONST_DOUBLE_HIGH (x) == 0
@@ -1003,7 +1004,7 @@ vax_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	{
 	case CONST_INT:
 	  if ((unsigned HOST_WIDE_INT)INTVAL (op) > 63
-	      && GET_MODE (x) != QImode)
+	      && mode != QImode)
 	    *total += 1;	/* 2 on VAX 2 */
 	  break;
 	case CONST:
diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c
index 341666c..bccba5f 100644
--- a/gcc/config/visium/visium.c
+++ b/gcc/config/visium/visium.c
@@ -191,7 +191,7 @@ static int visium_register_move_cost (enum machine_mode, reg_class_t,
 
 static int visium_memory_move_cost (enum machine_mode, reg_class_t, bool);
 
-static bool visium_rtx_costs (rtx, int, int, int, int *, bool);
+static bool visium_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 
 static void visium_option_override (void);
 
@@ -1888,11 +1888,11 @@ visium_memory_move_cost (enum machine_mode mode,
 /* Return the relative costs of expression X.  */
 
 static bool
-visium_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+visium_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 		  int opno ATTRIBUTE_UNUSED, int *total,
 		  bool speed ATTRIBUTE_UNUSED)
 {
-  enum machine_mode mode = GET_MODE (x);
+  int code = GET_CODE (x);
 
   switch (code)
     {
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 5396bd5..1ec9b3e 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -150,7 +150,7 @@ static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
 							int) ATTRIBUTE_UNUSED;
 static section *xtensa_select_rtx_section (machine_mode, rtx,
 					   unsigned HOST_WIDE_INT);
-static bool xtensa_rtx_costs (rtx, int, int, int, int *, bool);
+static bool xtensa_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int xtensa_register_move_cost (machine_mode, reg_class_t,
 				      reg_class_t);
 static int xtensa_memory_move_cost (machine_mode, reg_class_t, bool);
@@ -3574,9 +3574,12 @@ xtensa_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		  int opno ATTRIBUTE_UNUSED,
 		  int *total, bool speed ATTRIBUTE_UNUSED)
 {
+  int code = GET_CODE (x);
+
   switch (code)
     {
     case CONST_INT:
@@ -3646,9 +3649,9 @@ xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
     case MEM:
       {
 	int num_words =
-	  (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) ?  2 : 1;
+	  (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ?  2 : 1;
 
-	if (memory_address_p (GET_MODE (x), XEXP ((x), 0)))
+	if (memory_address_p (mode, XEXP ((x), 0)))
 	  *total = COSTS_N_INSNS (num_words);
 	else
 	  *total = COSTS_N_INSNS (2*num_words);
@@ -3665,13 +3668,13 @@ xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return true;
 
     case NOT:
-      *total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 3 : 2);
+      *total = COSTS_N_INSNS (mode == DImode ? 3 : 2);
       return true;
 
     case AND:
     case IOR:
     case XOR:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	*total = COSTS_N_INSNS (2);
       else
 	*total = COSTS_N_INSNS (1);
@@ -3680,7 +3683,7 @@ xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
     case ASHIFT:
     case ASHIFTRT:
     case LSHIFTRT:
-      if (GET_MODE (x) == DImode)
+      if (mode == DImode)
 	*total = COSTS_N_INSNS (50);
       else
 	*total = COSTS_N_INSNS (1);
@@ -3688,10 +3691,9 @@ xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 
     case ABS:
       {
-	machine_mode xmode = GET_MODE (x);
-	if (xmode == SFmode)
+	if (mode == SFmode)
 	  *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
-	else if (xmode == DFmode)
+	else if (mode == DFmode)
 	  *total = COSTS_N_INSNS (50);
 	else
 	  *total = COSTS_N_INSNS (4);
@@ -3701,10 +3703,9 @@ xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
     case PLUS:
     case MINUS:
       {
-	machine_mode xmode = GET_MODE (x);
-	if (xmode == SFmode)
+	if (mode == SFmode)
 	  *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
-	else if (xmode == DFmode || xmode == DImode)
+	else if (mode == DFmode || mode == DImode)
 	  *total = COSTS_N_INSNS (50);
 	else
 	  *total = COSTS_N_INSNS (1);
@@ -3712,17 +3713,16 @@ xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       }
 
     case NEG:
-      *total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 4 : 2);
+      *total = COSTS_N_INSNS (mode == DImode ? 4 : 2);
       return true;
 
     case MULT:
       {
-	machine_mode xmode = GET_MODE (x);
-	if (xmode == SFmode)
+	if (mode == SFmode)
 	  *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 4 : 50);
-	else if (xmode == DFmode)
+	else if (mode == DFmode)
 	  *total = COSTS_N_INSNS (50);
-	else if (xmode == DImode)
+	else if (mode == DImode)
 	  *total = COSTS_N_INSNS (TARGET_MUL32_HIGH ? 10 : 50);
 	else if (TARGET_MUL32)
 	  *total = COSTS_N_INSNS (4);
@@ -3738,13 +3738,12 @@ xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
     case DIV:
     case MOD:
       {
-	machine_mode xmode = GET_MODE (x);
-	if (xmode == SFmode)
+	if (mode == SFmode)
 	  {
 	    *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_DIV ? 8 : 50);
 	    return true;
 	  }
-	else if (xmode == DFmode)
+	else if (mode == DFmode)
 	  {
 	    *total = COSTS_N_INSNS (50);
 	    return true;
@@ -3755,8 +3754,7 @@ xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
     case UDIV:
     case UMOD:
       {
-	machine_mode xmode = GET_MODE (x);
-	if (xmode == DImode)
+	if (mode == DImode)
 	  *total = COSTS_N_INSNS (50);
 	else if (TARGET_DIV32)
 	  *total = COSTS_N_INSNS (32);
@@ -3766,7 +3764,7 @@ xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       }
 
     case SQRT:
-      if (GET_MODE (x) == SFmode)
+      if (mode == SFmode)
 	*total = COSTS_N_INSNS (TARGET_HARD_FLOAT_SQRT ? 8 : 50);
       else
 	*total = COSTS_N_INSNS (50);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index a16cd92..3dc51c0 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -6357,7 +6357,7 @@ Define this macro if a non-short-circuit operation produced by
 @code{BRANCH_COST} is greater than or equal to the value 2.
 @end defmac
 
-@deftypefn {Target Hook} bool TARGET_RTX_COSTS (rtx @var{x}, int @var{code}, int @var{outer_code}, int @var{opno}, int *@var{total}, bool @var{speed})
+@deftypefn {Target Hook} bool TARGET_RTX_COSTS (rtx @var{x}, machine_mode @var{mode}, int @var{outer_code}, int @var{opno}, int *@var{total}, bool @var{speed})
 This target hook describes the relative costs of RTL expressions.
 
 The cost may depend on the precise form of the expression, which is
@@ -6368,8 +6368,8 @@ that @samp{GET_CODE (@var{y}) == @var{outer_code}} and such that
 either (a) @samp{XEXP (@var{y}, @var{opno}) == @var{x}} or
 (b) @samp{XVEC (@var{y}, @var{opno})} contains @var{x}.
 
-@var{code} is @var{x}'s expression code---redundant, since it can be
-obtained with @code{GET_CODE (@var{x})}.
+@var{mode} is @var{x}'s machine mode, or for cases like @code{const_int} that
+do not have a mode, the mode in which @var{x} is used.
 
 In implementing this hook, you can use the construct
 @code{COSTS_N_INSNS (@var{n})} to specify a cost equal to @var{n} fast

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] rtx_costs vs. const_int
  2015-06-15  3:50 [PATCH] rtx_costs vs. const_int Alan Modra
  2015-06-15 18:40 ` Segher Boessenkool
  2015-06-22  1:32 ` Alan Modra
@ 2015-07-06 22:42 ` Jeff Law
  2 siblings, 0 replies; 5+ messages in thread
From: Jeff Law @ 2015-07-06 22:42 UTC (permalink / raw)
  To: gcc-patches

On 06/14/2015 08:33 PM, Alan Modra wrote:
> This patch changes the targetm.rtx_costs interface to pass a mode
> parameter, and removes a redundant parameter.  The reason for the
> change is that powerpc and other backends need the mode that a
> const_int is used in to properly determine the cost.  For instance,
> (set (reg) (ior (reg) (const_int))) where const_int is 0xff..ffff0000
> can be implemented in one instruction on powerpc if the regs and
> constant are SImode, but not when DImode.
>
> Some backends work around this problem by calculating the cost of the
> entire expression under the IOR, which allows the mode of the
> const_int to be inferred.  This of course results in huge rtx_costs
> functions since you must inspect the operands of many rtx codes that
> take const_int operands.  Worse, it doesn't work for all calls to
> targetm.rtx_costs;  gcc doesn't always pass an entire insn, or even
> the complete right hand side of a SET, to rtx_costs.  One place this
> is seen is in expand, for example, emit_store_flag makes calls like
>    rtx_cost (GEN_INT (normalizep), PLUS, ...)
> This sort of thing seems like a fundamental requirement in expand
> where insns are being built.  cse also makes similar calls.  So
> rtx_cost must be able to handle sub-expressions of an insn.
>
> As to the patch itself, the bulk is mostly mechanical.  I haven't made
> any simplification to the arm, aarch64 and mips rtx_costs that might
> be possible with this interface change.  rtlanal.c:rtx_cost also needs
> a machine_mode parameter to deal with the expand rtl mentioned above,
> as do a few other rtx cost functions.  sub-rtx's in rtx_cost are
> summed in order rather than reverse order so that the mode from an
> earlier operand can be used for a later operand lacking a mode.  This
> is for ZERO_EXTEND and similar codes where the sub-rtx mode is
> different to the outer mode.  Canonicalization puts const_int operands
> after other operands.
>
> I moved some inline functions in rtl.h later in the file because an
> earlier patch iteration passed GET_MODE (SET_DEST (x)) as the mode in
> set_rtx_cost and get_full_set_rtx_cost.  That meant the inlines needed
> to be after the definition of SET_DEST.  Later I realized that
> rtx_cost needed to provide the mode for a SET anyway, so VOIDmode
> would do just as well in set_rtx_cost.  That means the inlines don't
> need to be moved, but their new location seems better.
>
> The patch also doesn't contain any real changes to the powerpc
> backend, and in fact produces worse code than before in cases where
> rldic should be allowed by combine.  A later patch will cure the
> powerpc regressions.
>
> The patch was tested by full powerpc64-linux and x86_64-linux
> regression testing, and building cross-compilers for aarch64-linux,
> alpha-linux, arc-elf, arm-linuxeabi, avr-elf, bfin-elf, cris-linux,
> epiphany-elf, frv-linux, h8300-linux, hppa-linux, ia64-linux,
> iq2000-elf, lm32-elf, m32c-elf, m32r-elf, m68k-linux, mcore-elf,
> mep-elf, microblaze-linux, mips64-linux, mmix, mn10300-elf,
> msp430-elf, nds32le-elf, pdp11-aout, rl78-elf, s390x-linux,
> sh64-linux, sparc64-linux, spu-elf, tic6x-elf, tilegx-linux,
> tilepro-linux, v850-elf, vax-linux, visium-elf, xstormy16-elf, and
> xtensa-linux.  I examined x86_64-linux gcc/*.o files and didn't see
> any unexpected changes.
>
> The testing showed some pre-existing bugs..
>
> arc-elf dies on attempting to assemble first libgcc file, due to gas
> not understanding the options being passed by gcc.  Apparently no one
> cared enough to push gas changes upstream.
>
> ia64-linux, m68k-linux, tilegx-linux and tilepro-linux have
> dependencies on include files, not solved by -Dinhibit_libc, so die
> building libgcc.  Can be solved by hand, but annoying.
>
> iq2000-elf: internal compiler error: in dwarf2out_var_location, at
> dwarf2out.c:22302.
>
> mep-elf: internal compiler error: in pre_and_rev_post_order_compute,
> at cfganal.c:1029
>
> s390x-linux doesn't build as a cross-compiler.  undefined reference to
> `s390_host_detect_local_cpu(int, char const**)'
>
> tic6x-elf hits gas errors: Error: inconsistent uses of .cfi_sections
>
> vax-linux: internal compiler error: Segmentation fault.  Due to trying
> to find MEM_ADDR_SPACE of a SUBREG in this insn predicate
>     && (REG_P (operands[1])
>         || ! mode_dependent_address_p (XEXP (operands[1], 0),
> 				      MEM_ADDR_SPACE (operands[1])))"
>
>
> 	* target.def (rtx_costs): Remove "code" param, add "mode".
> 	* rtl.h (rtx_cost, get_full_rtx_cost): Update prototype.
> 	(set_src_cost, get_full_set_src_cost): Likewise.  Move later in file.
> 	(set_rtx_cost, get_full_set_rtx_cost): Move later in file.
> 	* rtlanal.c (rtx_cost): Add "mode" parameter.  Update targetm.rtx_costs
> 	call.  Track mode when given in rtx.
> 	(get_full_rtx_cost): Add "mode" parameter.  Update rtx_cost calls.
> 	(default_address_cost): Pass Pmode to rtx_cost.
> 	(insn_rtx_cost): Pass dest mode of set to set_src_cost.
> 	* cprop.c (try_replace_reg): Ensure set_rtx_cost is not called
> 	with NULL set.
> 	* cse.c (COST, COST_IN): Add MODE param.  Update all uses.
> 	(notreg_cost): Add mode param.  Use it.
> 	* gcse.c (want_to_gcse_p): Delete forward declaration.  Add
> 	mode param and pass to set_src_cost.  Update all calls.
> 	(hash_scan_set): Formatting.
> 	* hooks.c (hook_bool_rtx_int_int_int_intp_bool_false): Delete.
> 	(hook_bool_rtx_mode_int_int_intp_bool_false): New function.
> 	* hooks.h: Ditto.
> 	* expmed.c (init_expmed_one_conv, init_expmed_one_mode,
> 	init_expmed, expand_mult, mult_by_coeff_cost, expand_smod_pow2,
> 	emit_store_flag): Update set_src_cost and rtx_cost calls.
> 	* auto-inc-dec.c (attempt_change): Likewise.
> 	* calls.c (precompute_register_parameters): Likewise.
> 	* combine.c (expand_compound_operation, make_extraction,
> 	force_to_mode, distribute_and_simplify_rtx): Likewise.
> 	* dojump.c (prefer_and_bit_test): Likewise.
> 	* dse.c (find_shift_sequence): Likewise.
> 	* expr.c (compress_float_constant): Likewise.
> 	* fwprop.c (should_replace_address, try_fwprop_subst): Likewise.
> 	* ifcvt.c (noce_try_sign_mask): Likewise.
> 	* loop-doloop.c (doloop_optimize): Likewise.
> 	* loop-invariant.c (create_new_invariant): Likewise.
> 	* lower-subreg.c (shift_cost, compute_costs): Likewise.
> 	* optabs.c (avoid_expensive_constant, prepare_cmp_insn,
> 	lshift_cheap_p): Likewise.
> 	* postreload.c (reload_cse_simplify_set, reload_cse_simplify_operands,
> 	try_replace_in_use, reload_cse_move2add): Likewise.
> 	* reload1.c (calculate_elim_costs_all_insns, note_reg_elim_costly):
> 	Likewise.
> 	* simplify-rtx.c (simplify_binary_operation_1): Likewise.
> 	* tree-ssa-loop-ivopts.c (computation_cost): Likewise.
> 	* tree-ssa-reassoc.c (optimize_range_tests_to_bit_test): Likewise.
> 	* tree-switch-conversion.c (emit_case_bit_tests): Likewise.
> 	* config/aarch64/aarch64.c (aarch64_rtx_costs): Delete "code" param,
> 	add "mode" param.  Use "mode: in place of GET_MODE (x).  Pass mode
> 	to rtx_cost calls.
> 	* config/alpha/alpha.c (alpha_rtx_costs): Likewise.
> 	* config/arc/arc.c (arc_rtx_costs): Likewise.
> 	* config/arm/arm.c (arm_rtx_costs): Likewise.
> 	* config/avr/avr.c (avr_rtx_costs, avr_rtx_costs_1): Likewise.
> 	* config/bfin/bfin.c (bfin_rtx_costs): Likewise.
> 	* config/c6x/c6x.c (c6x_rtx_costs): Likewise.
> 	* config/cris/cris.c (cris_rtx_costs): Likewise.
> 	* config/epiphany/epiphany.c (epiphany_rtx_costs): Likewise.
> 	* config/frv/frv.c (frv_rtx_costs): Likewise.
> 	* config/h8300/h8300.c (h8300_rtx_costs): Likewise.
> 	* config/i386/i386.c (ix86_rtx_costs): Likewise.
> 	* config/ia64/ia64.c (ia64_rtx_costs): Likewise.
> 	* config/iq2000/iq2000.c (iq2000_rtx_costs): Likewise.
> 	* config/lm32/lm32.c (lm32_rtx_costs): Likewise.
> 	* config/m32c/m32c.c (m32c_rtx_costs): Likewise.
> 	* config/m32r/m32r.c (m32r_rtx_costs): Likewise.
> 	* config/m68k/m68k.c (m68k_rtx_costs): Likewise.
> 	* config/mcore/mcore.c (mcore_rtx_costs): Likewise.
> 	* config/mep/mep.c (mep_rtx_cost): Likewise.
> 	* config/microblaze/microblaze.c (microblaze_rtx_costs): Likewise.
> 	* config/mips/mips.c (mips_rtx_costs): Likewise.
> 	* config/mmix/mmix.c (mmix_rtx_costs): Likewise.
> 	* config/mn10300/mn10300.c (mn10300_rtx_costs): Likewise.
> 	* config/msp430/msp430.c (msp430_rtx_costs): Likewise.
> 	* config/nds32/nds32-cost.c (nds32_rtx_costs_impl): Likewise.
> 	* config/nds32/nds32-protos.h (nds32_rtx_costs_impl): Likewise.
> 	* config/nds32/nds32.c (nds32_rtx_costs): Likewise.
> 	* config/nios2/nios2.c (nios2_rtx_costs): Likewise.
> 	* config/pa/pa.c (hppa_rtx_costs): Likewise.
> 	* config/pdp11/pdp11.c (pdp11_rtx_costs): Likewise.
> 	* config/rl78/rl78.c (rl78_rtx_costs): Likewise.
> 	* config/rs6000/rs6000.c (rs6000_rtx_costs): Likewise.
> 	* config/s390/s390.c (s390_rtx_costs): Likewise.
> 	* config/sh/sh.c (sh_rtx_costs): Likewise.
> 	* config/sparc/sparc.c (sparc_rtx_costs): Likewise.
> 	* config/spu/spu.c (spu_rtx_costs): Likewise.
> 	* config/stormy16/stormy16.c (xstormy16_rtx_costs): Likewise.
> 	* config/tilegx/tilegx.c (tilegx_rtx_costs): Likewise.
> 	* config/tilepro/tilepro.c (tilepro_rtx_costs): Likewise.
> 	* config/v850/v850.c (v850_rtx_costs): Likewise.
> 	* config/vax/vax.c (vax_rtx_costs): Likewise.
> 	* config/visium/visium.c (visium_rtx_costs): Likewise.
> 	* config/xtensa/xtensa.c (xtensa_rtx_costs): Likewise.
> 	* config/aarch64/aarch64.c (aarch64_rtx_mult_cost): Change type of
> 	"code" param, and pass as outer_code to first rtx_cost call.  Pass
> 	mode to rtx_cost calls.
> 	(aarch64_address_cost, aarch64_if_then_else_costs): Update rtx_cost
> 	calls.
> 	(aarch64_rtx_costs_wrapper): Update.
> 	* config/arm/arm.c (arm_rtx_costs_1, arm_size_rtx_costs,
> 	arm_unspec_cost, arm_new_rtx_costs, arm_slowmul_rtx_costs): Update
> 	rtx_cost calls.
> 	* config/avr/avr.c (avr_final_prescan_insn): Update set_src_cost
> 	and rtx_cost calls.
> 	(avr_operand_rtx_cost): Similarly.
> 	(avr_rtx_costs_1): Correct mode passed to avr_operand_rtx_cost
> 	for subexpressions of ZERO_EXTEND, SIGN_EXTEND and COMPARE.
> 	* config/mips/mips.c (mips_stack_address_p): Comment typo.
> 	(mips_binary_cost): Update rtx_cost and set_src_cost calls.
> 	(mips_rtx_costs): Use GET_MODE (x) to detect const_int.
> 	* config/mn10300/mn10300.c (mn10300_address_cost): Pass Pmode to
> 	rtx_cost.
> 	(mn10300_rtx_costs): Correct mode passed to mn10300_address_cost.
> 	* config/rs6000/rs6000.c (rs6000_debug_rtx_costs): Update.
> 	* config/sh/sh.c (and_xor_ior_costs): Update rtx_cost call.
> 	* doc/tm.texi: Regenerate.
So after all this, we're able to get the mode that a const_int will be 
used in.  That is goodness.

I just spot checked the mechanical stuff.  I'm going to assume that 
you'll address regressions in the ppc and help other maintainers with 
any questions they might have on how to address regressions in their ports.

OK as are any trivial updates necessary due to conflicts as the trunk is 
a moving target.

Jeff

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-07-06 22:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-15  3:50 [PATCH] rtx_costs vs. const_int Alan Modra
2015-06-15 18:40 ` Segher Boessenkool
2015-06-16  4:09   ` Alan Modra
2015-06-22  1:32 ` Alan Modra
2015-07-06 22:42 ` Jeff Law

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).