summaryrefslogtreecommitdiff
path: root/gcc/lower-subreg.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-02-21 21:28:03 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-02-21 21:28:03 +0000
commit4d5cf08ac5097410d0c851951b01cd2a7c154696 (patch)
tree9cb1c904450cc59578754dc59ceb7a22a2090f50 /gcc/lower-subreg.c
parentded1a5565642f65d3f1b97137b078ad3dd4bd383 (diff)
downloadgcc-4d5cf08ac5097410d0c851951b01cd2a7c154696.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@196214 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/lower-subreg.c')
-rw-r--r--gcc/lower-subreg.c56
1 files changed, 41 insertions, 15 deletions
diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
index 228d3a28eae..05927e13b08 100644
--- a/gcc/lower-subreg.c
+++ b/gcc/lower-subreg.c
@@ -57,9 +57,9 @@ along with GCC; see the file COPYING3. If not see
to do this.
This pass only splits moves with modes that are wider than
- word_mode and ASHIFTs, LSHIFTRTs and ZERO_EXTENDs with integer
- modes that are twice the width of word_mode. The latter could be
- generalized if there was a need to do this, but the trend in
+ word_mode and ASHIFTs, LSHIFTRTs, ASHIFTRTs and ZERO_EXTENDs with
+ integer modes that are twice the width of word_mode. The latter
+ could be generalized if there was a need to do this, but the trend in
architectures is to not need this.
There are two useful preprocessor defines for use by maintainers:
@@ -152,7 +152,7 @@ compute_splitting_shift (bool speed_p, struct cost_rtxes *rtxes,
bool *splitting, enum rtx_code code,
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++)
{
@@ -163,13 +163,20 @@ compute_splitting_shift (bool speed_p, struct cost_rtxes *rtxes,
else
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)
fprintf (stderr, "%s %s by %d: original cost %d, split cost %d + %d\n",
GET_MODE_NAME (twice_word_mode), GET_RTX_NAME (code),
- i + BITS_PER_WORD, wide_cost, narrow_cost,
- word_move_zero_cost);
+ i + BITS_PER_WORD, wide_cost, narrow_cost, upper_cost);
- if (FORCE_LOWERING || wide_cost >= narrow_cost + word_move_zero_cost)
+ if (FORCE_LOWERING || wide_cost >= narrow_cost + upper_cost)
splitting[i] = true;
}
}
@@ -248,6 +255,9 @@ compute_costs (bool speed_p, struct cost_rtxes *rtxes)
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);
}
}
@@ -1153,6 +1163,7 @@ find_decomposable_shift_zext (rtx insn, bool speed_p)
op = SET_SRC (set);
if (GET_CODE (op) != ASHIFT
&& GET_CODE (op) != LSHIFTRT
+ && GET_CODE (op) != ASHIFTRT
&& GET_CODE (op) != ZERO_EXTEND)
return false;
@@ -1173,6 +1184,8 @@ find_decomposable_shift_zext (rtx insn, bool speed_p)
{
bool *splitting = (GET_CODE (op) == ASHIFT
? choices[speed_p].splitting_ashift
+ : GET_CODE (op) == ASHIFTRT
+ ? choices[speed_p].splitting_ashiftrt
: choices[speed_p].splitting_lshiftrt);
if (!CONST_INT_P (XEXP (op, 1))
|| !IN_RANGE (INTVAL (XEXP (op, 1)), BITS_PER_WORD,
@@ -1200,7 +1213,7 @@ resolve_shift_zext (rtx insn)
rtx op;
rtx op_operand;
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;
set = single_set (insn);
@@ -1210,6 +1223,7 @@ resolve_shift_zext (rtx insn)
op = SET_SRC (set);
if (GET_CODE (op) != ASHIFT
&& GET_CODE (op) != LSHIFTRT
+ && GET_CODE (op) != ASHIFTRT
&& GET_CODE (op) != ZERO_EXTEND)
return NULL_RTX;
@@ -1223,7 +1237,8 @@ resolve_shift_zext (rtx insn)
/* 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
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
&& GET_MODE_SIZE (GET_MODE (op_operand)) > UNITS_PER_WORD)
@@ -1243,12 +1258,17 @@ resolve_shift_zext (rtx insn)
dest_reg = simplify_gen_subreg_concatn (word_mode, SET_DEST (set),
GET_MODE (SET_DEST (set)),
offset1);
- dest_zero = simplify_gen_subreg_concatn (word_mode, SET_DEST (set),
- GET_MODE (SET_DEST (set)),
- offset2);
+ dest_upper = simplify_gen_subreg_concatn (word_mode, SET_DEST (set),
+ GET_MODE (SET_DEST (set)),
+ offset2);
src_reg = simplify_gen_subreg_concatn (word_mode, op_operand,
GET_MODE (op_operand),
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)
{
int shift_count = INTVAL (XEXP (op, 1));
@@ -1257,12 +1277,17 @@ resolve_shift_zext (rtx insn)
LSHIFT_EXPR : RSHIFT_EXPR,
word_mode, src_reg,
shift_count - BITS_PER_WORD,
- dest_reg, 1);
+ dest_reg, GET_CODE (op) != ASHIFTRT);
}
if (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 ();
end_sequence ();
@@ -1328,7 +1353,8 @@ dump_choices (bool speed_p, const char *description)
GET_MODE_NAME (twice_word_mode));
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");
}