mirror of git://gcc.gnu.org/git/gcc.git
xtensa: Change the splitting of D[IF]mode constant assignments to be implemented in xt_largeconst instead of define_split
This patch moves the process of splitting D[IF]mode constant assignments into SImode ones from the define_split implementation after reloading to processing within the "xt_largeconst" target-specific pass. It also converts SFmode constant assignments into bit-equivalent SImode ones. This allows these assignments to be processed by the "constantsynth" optimization, which will be reimplemented later. gcc/ChangeLog: * config/xtensa/xtensa-protos.h (xtensa_split_DI_reg_imm): Remove. * config/xtensa/xtensa.cc (xtensa_split_DI_reg_imm): Remove. (split_DI_SF_DF_const): New worker function. (do_largeconst): Add a call to split_DI_SF_DF_const() to the insn enumeration loop. * config/xtensa/xtensa.md (movdi): Remove split code when the source is constant. (movdi_internal): Add a new constraint pair (a, Y) to the second of the existing constraint alternatives. (The auxiliary define_split for movdi_internal): Remove.
This commit is contained in:
parent
4864f24c86
commit
b6af5f46e3
|
@ -59,7 +59,6 @@ extern char *xtensa_emit_sibcall (int, rtx *);
|
|||
extern bool xtensa_tls_referenced_p (rtx);
|
||||
extern enum rtx_code xtensa_shlrd_which_direction (rtx, rtx);
|
||||
extern bool xtensa_postreload_completed_p (void);
|
||||
extern void xtensa_split_DI_reg_imm (rtx *);
|
||||
extern char *xtensa_bswapsi2_output (rtx_insn *, const char *);
|
||||
|
||||
#ifdef TREE_CODE
|
||||
|
|
|
@ -2633,27 +2633,6 @@ xtensa_postreload_completed_p (void)
|
|||
}
|
||||
|
||||
|
||||
/* Split a DImode pair of reg (operand[0]) and const_int (operand[1]) into
|
||||
two SImode pairs, the low-part (operands[0] and [1]) and the high-part
|
||||
(operands[2] and [3]). */
|
||||
|
||||
void
|
||||
xtensa_split_DI_reg_imm (rtx *operands)
|
||||
{
|
||||
rtx lowpart, highpart;
|
||||
|
||||
if (WORDS_BIG_ENDIAN)
|
||||
split_double (operands[1], &highpart, &lowpart);
|
||||
else
|
||||
split_double (operands[1], &lowpart, &highpart);
|
||||
|
||||
operands[3] = highpart;
|
||||
operands[2] = gen_highpart (SImode, operands[0]);
|
||||
operands[1] = lowpart;
|
||||
operands[0] = gen_lowpart (SImode, operands[0]);
|
||||
}
|
||||
|
||||
|
||||
/* Return the asm output string of bswapsi2_internal insn pattern.
|
||||
It does this by scanning backwards for the BB from the specified insn,
|
||||
and if an another bswapsi2_internal is found, it omits the instruction
|
||||
|
@ -5892,6 +5871,102 @@ FPreg_neg_scaled_simm12b (rtx_insn *insn)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Split DI/SF/DFmode constant assignments into pairs of SImode ones. This
|
||||
is also the pre-processing for constantsynth optimization that follows
|
||||
immediately after.
|
||||
|
||||
Note that all constant values and assignments are treated as SImode
|
||||
because:
|
||||
|
||||
- Synthesis methods rely on SImode operations
|
||||
- SImode assignments may be shorter
|
||||
- More opportunity for sharing literal pool entries
|
||||
|
||||
This behavior would be acceptable if TARGET_CAN_CHANGE_MODE_CLASS always
|
||||
returned true (the current and default configuration). */
|
||||
|
||||
static bool
|
||||
split_DI_SF_DF_const (rtx_insn *insn)
|
||||
{
|
||||
rtx pat, dest, src, dest0, dest1, src0, src1, src0c, src1c;
|
||||
int regno;
|
||||
|
||||
if (GET_CODE (pat = PATTERN (insn)) != SET
|
||||
|| ! REG_P (dest = SET_DEST (pat)) || ! GP_REG_P (regno = REGNO (dest)))
|
||||
return false;
|
||||
|
||||
/* It is more efficient to assign SFmode literal constants using their
|
||||
bit-equivalent SImode ones, thus we convert them so. */
|
||||
src = avoid_constant_pool_reference (SET_SRC (pat));
|
||||
if (GET_MODE (dest) == SFmode
|
||||
&& CONST_DOUBLE_P (src) && GET_MODE (src) == SFmode)
|
||||
{
|
||||
long l;
|
||||
REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (src), l);
|
||||
src0 = GEN_INT ((int32_t)l), dest0 = gen_rtx_REG (SImode, regno);
|
||||
if (dump_file)
|
||||
{
|
||||
fputs ("split_DI_SF_DF_const: ", dump_file);
|
||||
dump_value_slim (dump_file, src, 0);
|
||||
fprintf (dump_file,
|
||||
"f -> " HOST_WIDE_INT_PRINT_DEC " ("
|
||||
HOST_WIDE_INT_PRINT_HEX ")\n",
|
||||
INTVAL (src0), INTVAL (src0));
|
||||
}
|
||||
src0c = NULL_RTX;
|
||||
if (!TARGET_CONST16 && !TARGET_AUTO_LITPOOLS
|
||||
&& ! xtensa_simm12b (INTVAL (src0)))
|
||||
src0c = src0, src0 = force_const_mem (SImode, src0);
|
||||
remove_reg_equal_equiv_notes (insn);
|
||||
validate_change (insn, &PATTERN (insn), gen_rtx_SET (dest0, src0), 0);
|
||||
if (src0c)
|
||||
add_reg_note (insn, REG_EQUIV, copy_rtx (src0c));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Splitting a D[IF]mode literal constant into two with split_double()
|
||||
results in a pair of CONST_INTs, so they are assigned in SImode
|
||||
regardless of the original source mode. */
|
||||
if ((GET_MODE (dest) == DImode && CONST_INT_P (src))
|
||||
|| (GET_MODE (dest) == DFmode
|
||||
&& CONST_DOUBLE_P (src) && GET_MODE (src) == DFmode))
|
||||
{
|
||||
dest0 = gen_rtx_REG (SImode, regno);
|
||||
dest1 = gen_rtx_REG (SImode, regno + 1);
|
||||
split_double (src, &src0, &src1);
|
||||
if (dump_file)
|
||||
{
|
||||
fputs ("split_DI_SF_DF_const: ", dump_file);
|
||||
dump_value_slim (dump_file, src, 0);
|
||||
fprintf (dump_file,
|
||||
" -> " HOST_WIDE_INT_PRINT_DEC " ("
|
||||
HOST_WIDE_INT_PRINT_HEX "), "
|
||||
HOST_WIDE_INT_PRINT_DEC " ("
|
||||
HOST_WIDE_INT_PRINT_HEX ")\n",
|
||||
INTVAL (src0), INTVAL (src0),
|
||||
INTVAL (src1), INTVAL (src1));
|
||||
}
|
||||
src1c = src0c = NULL_RTX;
|
||||
if (!TARGET_CONST16 && !TARGET_AUTO_LITPOOLS)
|
||||
{
|
||||
if (! xtensa_simm12b (INTVAL (src0)))
|
||||
src0c = src0, src0 = force_const_mem (SImode, src0);
|
||||
if (! xtensa_simm12b (INTVAL (src1)))
|
||||
src1c = src1, src1 = force_const_mem (SImode, src1);
|
||||
}
|
||||
remove_reg_equal_equiv_notes (insn);
|
||||
validate_change (insn, &PATTERN (insn), gen_rtx_SET (dest0, src0), 0);
|
||||
if (src0c)
|
||||
add_reg_note (insn, REG_EQUIV, copy_rtx (src0c));
|
||||
insn = emit_insn_after (gen_rtx_SET (dest1, src1), insn);
|
||||
if (src1c)
|
||||
add_reg_note (insn, REG_EQUIV, copy_rtx (src1c));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Replace the source of [SH]Imode allocation whose value does not fit
|
||||
into signed 12 bits with a reference to litpool entry. */
|
||||
|
||||
|
@ -5956,6 +6031,11 @@ do_largeconst (void)
|
|||
bool optimize_enabled = optimize && !optimize_debug;
|
||||
rtx_insn *insn;
|
||||
|
||||
/* Verify the legitimacy of replacing constant assignments in
|
||||
DI/SF/DFmode with those in SImode. */
|
||||
gcc_assert (targetm.can_change_mode_class
|
||||
== hook_bool_mode_mode_reg_class_t_true);
|
||||
|
||||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
if (NONJUMP_INSN_P (insn))
|
||||
{
|
||||
|
@ -5970,6 +6050,12 @@ do_largeconst (void)
|
|||
fit into signed 12 bits with a reference to litpool entry. */
|
||||
if (replacing_required)
|
||||
litpool_set_src (insn);
|
||||
|
||||
/* Split DI/SF/DFmode constant assignments into pairs of SImode
|
||||
ones. This is also the pre-processing for constantsynth opti-
|
||||
mization that follows immediately after. */
|
||||
if (replacing_required)
|
||||
split_DI_SF_DF_const (insn);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1219,22 +1219,8 @@
|
|||
(match_operand:DI 1 "general_operand" ""))]
|
||||
""
|
||||
{
|
||||
if (CONSTANT_P (operands[1]))
|
||||
{
|
||||
/* Split in halves if 64-bit Const-to-Reg moves
|
||||
because of offering further optimization opportunities. */
|
||||
if (register_operand (operands[0], DImode))
|
||||
{
|
||||
rtx ops[4] = { operands[0], operands[1] };
|
||||
xtensa_split_DI_reg_imm (ops);
|
||||
emit_move_insn (ops[0], ops[1]);
|
||||
emit_move_insn (ops[2], ops[3]);
|
||||
DONE;
|
||||
}
|
||||
|
||||
if (!TARGET_CONST16)
|
||||
operands[1] = force_const_mem (DImode, operands[1]);
|
||||
}
|
||||
if (!TARGET_CONST16 && CONSTANT_P (operands[1]))
|
||||
operands[1] = force_const_mem (DImode, operands[1]);
|
||||
|
||||
if (!register_operand (operands[0], DImode)
|
||||
&& !register_operand (operands[1], DImode))
|
||||
|
@ -1244,8 +1230,8 @@
|
|||
})
|
||||
|
||||
(define_insn_and_split "movdi_internal"
|
||||
[(set (match_operand:DI 0 "nonimmed_operand" "=a,W,a,a,U")
|
||||
(match_operand:DI 1 "move_operand" "r,i,T,U,r"))]
|
||||
[(set (match_operand:DI 0 "nonimmed_operand" "=a,a,W,a,a,U")
|
||||
(match_operand:DI 1 "move_operand" "r,Y,i,T,U,r"))]
|
||||
"register_operand (operands[0], DImode)
|
||||
|| register_operand (operands[1], DImode)"
|
||||
"#"
|
||||
|
@ -1260,22 +1246,9 @@
|
|||
std::swap (operands[2], operands[3]);
|
||||
}
|
||||
}
|
||||
[(set_attr "type" "move,move,load,load,store")
|
||||
[(set_attr "type" "move,load,move,load,load,store")
|
||||
(set_attr "mode" "DI")
|
||||
(set_attr "length" "6,12,6,6,6")])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand")
|
||||
(match_operand:DI 1 "const_int_operand"))]
|
||||
"!TARGET_CONST16
|
||||
&& ! xtensa_postreload_completed_p ()"
|
||||
[(set (match_dup 0)
|
||||
(match_dup 1))
|
||||
(set (match_dup 2)
|
||||
(match_dup 3))]
|
||||
{
|
||||
xtensa_split_DI_reg_imm (operands);
|
||||
})
|
||||
(set_attr "length" "6,6,12,6,6,6")])
|
||||
|
||||
;; 32-bit Integer moves
|
||||
|
||||
|
|
Loading…
Reference in New Issue