+ if (LOG_COSTS)
+ fprintf (stderr, "%s move: from zero cost %d, from reg cost %d\n",
+ GET_MODE_NAME (word_mode), word_move_zero_cost, word_move_cost);
+
+ for (i = 0; i < MAX_MACHINE_MODE; i++)
+ {
+ machine_mode mode = (machine_mode) i;
+ unsigned int size, factor;
+ if (interesting_mode_p (mode, &size, &factor) && factor > 1)
+ {
+ unsigned int mode_move_cost;
+
+ PUT_MODE (rtxes->target, mode);
+ PUT_MODE (rtxes->source, mode);
+ mode_move_cost = set_rtx_cost (rtxes->set, speed_p);
+
+ if (LOG_COSTS)
+ fprintf (stderr, "%s move: original cost %d, split cost %d * %d\n",
+ GET_MODE_NAME (mode), mode_move_cost,
+ word_move_cost, factor);
+
+ if (FORCE_LOWERING || mode_move_cost >= word_move_cost * factor)
+ {
+ choices[speed_p].move_modes_to_split[i] = true;
+ choices[speed_p].something_to_do = true;
+ }
+ }
+ }
+
+ /* For the moves and shifts, the only case that is checked is one
+ where the mode of the target is an integer mode twice the width
+ of the word_mode.
+
+ If it is not profitable to split a double word move then do not
+ even consider the shifts or the zero extension. */
+ if (choices[speed_p].move_modes_to_split[(int) twice_word_mode])
+ {
+ int zext_cost;
+
+ /* 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, twice_word_mode, speed_p);
+
+ if (LOG_COSTS)
+ fprintf (stderr, "%s %s: original cost %d, split cost %d + %d\n",
+ GET_MODE_NAME (twice_word_mode), GET_RTX_NAME (ZERO_EXTEND),
+ zext_cost, word_move_cost, word_move_zero_cost);
+
+ if (FORCE_LOWERING || zext_cost >= word_move_cost + word_move_zero_cost)
+ choices[speed_p].splitting_zext = true;
+
+ compute_splitting_shift (speed_p, rtxes,
+ choices[speed_p].splitting_ashift, ASHIFT,
+ word_move_zero_cost, word_move_cost);
+ compute_splitting_shift (speed_p, rtxes,
+ choices[speed_p].splitting_lshiftrt, LSHIFTRT,
+ word_move_zero_cost, word_move_cost);
+ compute_splitting_shift (speed_p, rtxes,
+ choices[speed_p].splitting_ashiftrt, ASHIFTRT,
+ word_move_zero_cost, word_move_cost);
+ }
+}
+
+/* Do one-per-target initialisation. This involves determining
+ which operations on the machine are profitable. If none are found,
+ then the pass just returns when called. */
+
+void
+init_lower_subreg (void)
+{
+ struct cost_rtxes rtxes;
+
+ memset (this_target_lower_subreg, 0, sizeof (*this_target_lower_subreg));
+
+ twice_word_mode = GET_MODE_2XWIDER_MODE (word_mode).require ();
+
+ rtxes.target = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
+ rtxes.source = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 2);
+ rtxes.set = gen_rtx_SET (rtxes.target, rtxes.source);
+ rtxes.zext = gen_rtx_ZERO_EXTEND (twice_word_mode, rtxes.source);
+ rtxes.shift = gen_rtx_ASHIFT (twice_word_mode, rtxes.source, const0_rtx);
+
+ if (LOG_COSTS)
+ fprintf (stderr, "\nSize costs\n==========\n\n");
+ compute_costs (false, &rtxes);
+
+ if (LOG_COSTS)
+ fprintf (stderr, "\nSpeed costs\n===========\n\n");
+ compute_costs (true, &rtxes);
+}