Commit d7fde18c by Jakub Jelinek Committed by Jakub Jelinek

re PR rtl-optimization/50339 (suboptimal register allocation for abs(__int128_t))

	PR rtl-optimization/50339
	* lower-subreg.h (struct lower_subreg_choices): Add splitting_ashiftrt
	field.
	* lower-subreg.c (compute_splitting_shift): Handle ASHIFTRT.
	(compute_costs): Call compute_splitting_shift also for ASHIFTRT
	into splitting_ashiftrt field.
	(find_decomposable_shift_zext, resolve_shift_zext): Handle also
	ASHIFTRT.
	(dump_choices): Fix up printing LSHIFTRT choices, print ASHIFTRT
	choices.

From-SVN: r196214
parent 6aad4455
2013-02-21 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/50339
* lower-subreg.h (struct lower_subreg_choices): Add splitting_ashiftrt
field.
* lower-subreg.c (compute_splitting_shift): Handle ASHIFTRT.
(compute_costs): Call compute_splitting_shift also for ASHIFTRT
into splitting_ashiftrt field.
(find_decomposable_shift_zext, resolve_shift_zext): Handle also
ASHIFTRT.
(dump_choices): Fix up printing LSHIFTRT choices, print ASHIFTRT
choices.
2013-02-20 Aldy Hernandez <aldyh@redhat.com> 2013-02-20 Aldy Hernandez <aldyh@redhat.com>
PR middle-end/56108 PR middle-end/56108
......
...@@ -57,9 +57,9 @@ along with GCC; see the file COPYING3. If not see ...@@ -57,9 +57,9 @@ along with GCC; see the file COPYING3. If not see
to do this. to do this.
This pass only splits moves with modes that are wider than This pass only splits moves with modes that are wider than
word_mode and ASHIFTs, LSHIFTRTs and ZERO_EXTENDs with integer word_mode and ASHIFTs, LSHIFTRTs, ASHIFTRTs and ZERO_EXTENDs with
modes that are twice the width of word_mode. The latter could be integer modes that are twice the width of word_mode. The latter
generalized if there was a need to do this, but the trend in could be generalized if there was a need to do this, but the trend in
architectures is to not need this. architectures is to not need this.
There are two useful preprocessor defines for use by maintainers: There are two useful preprocessor defines for use by maintainers:
...@@ -152,7 +152,7 @@ compute_splitting_shift (bool speed_p, struct cost_rtxes *rtxes, ...@@ -152,7 +152,7 @@ compute_splitting_shift (bool speed_p, struct cost_rtxes *rtxes,
bool *splitting, enum rtx_code code, bool *splitting, enum rtx_code code,
int word_move_zero_cost, int word_move_cost) int word_move_zero_cost, int word_move_cost)
{ {
int wide_cost, narrow_cost, i; int wide_cost, narrow_cost, upper_cost, i;
for (i = 0; i < BITS_PER_WORD; i++) for (i = 0; i < BITS_PER_WORD; i++)
{ {
...@@ -163,13 +163,20 @@ compute_splitting_shift (bool speed_p, struct cost_rtxes *rtxes, ...@@ -163,13 +163,20 @@ compute_splitting_shift (bool speed_p, struct cost_rtxes *rtxes,
else else
narrow_cost = shift_cost (speed_p, rtxes, code, word_mode, i); narrow_cost = shift_cost (speed_p, rtxes, code, word_mode, i);
if (code != ASHIFTRT)
upper_cost = word_move_zero_cost;
else if (i == BITS_PER_WORD - 1)
upper_cost = word_move_cost;
else
upper_cost = shift_cost (speed_p, rtxes, code, word_mode,
BITS_PER_WORD - 1);
if (LOG_COSTS) if (LOG_COSTS)
fprintf (stderr, "%s %s by %d: original cost %d, split cost %d + %d\n", fprintf (stderr, "%s %s by %d: original cost %d, split cost %d + %d\n",
GET_MODE_NAME (twice_word_mode), GET_RTX_NAME (code), GET_MODE_NAME (twice_word_mode), GET_RTX_NAME (code),
i + BITS_PER_WORD, wide_cost, narrow_cost, i + BITS_PER_WORD, wide_cost, narrow_cost, upper_cost);
word_move_zero_cost);
if (FORCE_LOWERING || wide_cost >= narrow_cost + word_move_zero_cost) if (FORCE_LOWERING || wide_cost >= narrow_cost + upper_cost)
splitting[i] = true; splitting[i] = true;
} }
} }
...@@ -248,6 +255,9 @@ compute_costs (bool speed_p, struct cost_rtxes *rtxes) ...@@ -248,6 +255,9 @@ compute_costs (bool speed_p, struct cost_rtxes *rtxes)
compute_splitting_shift (speed_p, rtxes, compute_splitting_shift (speed_p, rtxes,
choices[speed_p].splitting_lshiftrt, LSHIFTRT, choices[speed_p].splitting_lshiftrt, LSHIFTRT,
word_move_zero_cost, word_move_cost); 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);
} }
} }
...@@ -1153,6 +1163,7 @@ find_decomposable_shift_zext (rtx insn, bool speed_p) ...@@ -1153,6 +1163,7 @@ find_decomposable_shift_zext (rtx insn, bool speed_p)
op = SET_SRC (set); op = SET_SRC (set);
if (GET_CODE (op) != ASHIFT if (GET_CODE (op) != ASHIFT
&& GET_CODE (op) != LSHIFTRT && GET_CODE (op) != LSHIFTRT
&& GET_CODE (op) != ASHIFTRT
&& GET_CODE (op) != ZERO_EXTEND) && GET_CODE (op) != ZERO_EXTEND)
return false; return false;
...@@ -1173,6 +1184,8 @@ find_decomposable_shift_zext (rtx insn, bool speed_p) ...@@ -1173,6 +1184,8 @@ find_decomposable_shift_zext (rtx insn, bool speed_p)
{ {
bool *splitting = (GET_CODE (op) == ASHIFT bool *splitting = (GET_CODE (op) == ASHIFT
? choices[speed_p].splitting_ashift ? choices[speed_p].splitting_ashift
: GET_CODE (op) == ASHIFTRT
? choices[speed_p].splitting_ashiftrt
: choices[speed_p].splitting_lshiftrt); : choices[speed_p].splitting_lshiftrt);
if (!CONST_INT_P (XEXP (op, 1)) if (!CONST_INT_P (XEXP (op, 1))
|| !IN_RANGE (INTVAL (XEXP (op, 1)), BITS_PER_WORD, || !IN_RANGE (INTVAL (XEXP (op, 1)), BITS_PER_WORD,
...@@ -1200,7 +1213,7 @@ resolve_shift_zext (rtx insn) ...@@ -1200,7 +1213,7 @@ resolve_shift_zext (rtx insn)
rtx op; rtx op;
rtx op_operand; rtx op_operand;
rtx insns; rtx insns;
rtx src_reg, dest_reg, dest_zero; rtx src_reg, dest_reg, dest_upper, upper_src = NULL_RTX;
int src_reg_num, dest_reg_num, offset1, offset2, src_offset; int src_reg_num, dest_reg_num, offset1, offset2, src_offset;
set = single_set (insn); set = single_set (insn);
...@@ -1210,6 +1223,7 @@ resolve_shift_zext (rtx insn) ...@@ -1210,6 +1223,7 @@ resolve_shift_zext (rtx insn)
op = SET_SRC (set); op = SET_SRC (set);
if (GET_CODE (op) != ASHIFT if (GET_CODE (op) != ASHIFT
&& GET_CODE (op) != LSHIFTRT && GET_CODE (op) != LSHIFTRT
&& GET_CODE (op) != ASHIFTRT
&& GET_CODE (op) != ZERO_EXTEND) && GET_CODE (op) != ZERO_EXTEND)
return NULL_RTX; return NULL_RTX;
...@@ -1223,7 +1237,8 @@ resolve_shift_zext (rtx insn) ...@@ -1223,7 +1237,8 @@ resolve_shift_zext (rtx insn)
/* src_reg_num is the number of the word mode register which we /* src_reg_num is the number of the word mode register which we
are operating on. For a left shift and a zero_extend on little are operating on. For a left shift and a zero_extend on little
endian machines this is register 0. */ endian machines this is register 0. */
src_reg_num = GET_CODE (op) == LSHIFTRT ? 1 : 0; src_reg_num = (GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFTRT)
? 1 : 0;
if (WORDS_BIG_ENDIAN if (WORDS_BIG_ENDIAN
&& GET_MODE_SIZE (GET_MODE (op_operand)) > UNITS_PER_WORD) && GET_MODE_SIZE (GET_MODE (op_operand)) > UNITS_PER_WORD)
...@@ -1243,12 +1258,17 @@ resolve_shift_zext (rtx insn) ...@@ -1243,12 +1258,17 @@ resolve_shift_zext (rtx insn)
dest_reg = simplify_gen_subreg_concatn (word_mode, SET_DEST (set), dest_reg = simplify_gen_subreg_concatn (word_mode, SET_DEST (set),
GET_MODE (SET_DEST (set)), GET_MODE (SET_DEST (set)),
offset1); offset1);
dest_zero = simplify_gen_subreg_concatn (word_mode, SET_DEST (set), dest_upper = simplify_gen_subreg_concatn (word_mode, SET_DEST (set),
GET_MODE (SET_DEST (set)), GET_MODE (SET_DEST (set)),
offset2); offset2);
src_reg = simplify_gen_subreg_concatn (word_mode, op_operand, src_reg = simplify_gen_subreg_concatn (word_mode, op_operand,
GET_MODE (op_operand), GET_MODE (op_operand),
src_offset); src_offset);
if (GET_CODE (op) == ASHIFTRT
&& INTVAL (XEXP (op, 1)) != 2 * BITS_PER_WORD - 1)
upper_src = expand_shift (RSHIFT_EXPR, word_mode, copy_rtx (src_reg),
BITS_PER_WORD - 1, NULL_RTX, 0);
if (GET_CODE (op) != ZERO_EXTEND) if (GET_CODE (op) != ZERO_EXTEND)
{ {
int shift_count = INTVAL (XEXP (op, 1)); int shift_count = INTVAL (XEXP (op, 1));
...@@ -1257,12 +1277,17 @@ resolve_shift_zext (rtx insn) ...@@ -1257,12 +1277,17 @@ resolve_shift_zext (rtx insn)
LSHIFT_EXPR : RSHIFT_EXPR, LSHIFT_EXPR : RSHIFT_EXPR,
word_mode, src_reg, word_mode, src_reg,
shift_count - BITS_PER_WORD, shift_count - BITS_PER_WORD,
dest_reg, 1); dest_reg, GET_CODE (op) != ASHIFTRT);
} }
if (dest_reg != src_reg) if (dest_reg != src_reg)
emit_move_insn (dest_reg, src_reg); emit_move_insn (dest_reg, src_reg);
emit_move_insn (dest_zero, CONST0_RTX (word_mode)); if (GET_CODE (op) != ASHIFTRT)
emit_move_insn (dest_upper, CONST0_RTX (word_mode));
else if (INTVAL (XEXP (op, 1)) == 2 * BITS_PER_WORD - 1)
emit_move_insn (dest_upper, copy_rtx (src_reg));
else
emit_move_insn (dest_upper, upper_src);
insns = get_insns (); insns = get_insns ();
end_sequence (); end_sequence ();
...@@ -1328,7 +1353,8 @@ dump_choices (bool speed_p, const char *description) ...@@ -1328,7 +1353,8 @@ dump_choices (bool speed_p, const char *description)
GET_MODE_NAME (twice_word_mode)); GET_MODE_NAME (twice_word_mode));
dump_shift_choices (ASHIFT, choices[speed_p].splitting_ashift); dump_shift_choices (ASHIFT, choices[speed_p].splitting_ashift);
dump_shift_choices (LSHIFTRT, choices[speed_p].splitting_ashift); dump_shift_choices (LSHIFTRT, choices[speed_p].splitting_lshiftrt);
dump_shift_choices (ASHIFTRT, choices[speed_p].splitting_ashiftrt);
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
......
...@@ -34,6 +34,7 @@ struct lower_subreg_choices { ...@@ -34,6 +34,7 @@ struct lower_subreg_choices {
should be split. */ should be split. */
bool splitting_ashift[MAX_BITS_PER_WORD]; bool splitting_ashift[MAX_BITS_PER_WORD];
bool splitting_lshiftrt[MAX_BITS_PER_WORD]; bool splitting_lshiftrt[MAX_BITS_PER_WORD];
bool splitting_ashiftrt[MAX_BITS_PER_WORD];
/* True if there is at least one mode that is worth splitting. */ /* True if there is at least one mode that is worth splitting. */
bool something_to_do; bool something_to_do;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment