Commit 5b6c6a8e authored by geoffk's avatar geoffk
Browse files

* config/rs6000/rs6000.c (rs6000_emit_move): New function.

* config/rs6000/rs6000-proto.h: Prototype rs6000_emit_move.
* config/rs6000/rs6000.md (movsi): Use rs6000_emit_move.
(movhi): Likewise.
(movqi): Likewise.
(movdf): Likewise.
(movsf): Likewise.
(movdi): Likewise.
(movti): Likewise.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@34852 138bc75d-0d04-0410-961f-82ee72b054a4
parent 2182a646
2000-07-03 Geoff Keating <geoffk@cygnus.com>
 
* config/rs6000/rs6000.c (rs6000_emit_move): New function.
* config/rs6000/rs6000-proto.h: Prototype rs6000_emit_move.
* config/rs6000/rs6000.md (movsi): Use rs6000_emit_move.
(movhi): Likewise.
(movqi): Likewise.
(movdf): Likewise.
(movsf): Likewise.
(movdi): Likewise.
(movti): Likewise.
* expmed.c (expand_mult_highpart): Use op1 instead of wide_op1 when
mode instead of wider_mode is being used.
 
......
......@@ -97,6 +97,7 @@ extern int mtcrf_operation PARAMS ((rtx, enum machine_mode));
extern int lmw_operation PARAMS ((rtx, enum machine_mode));
extern struct rtx_def *create_TOC_reference PARAMS ((rtx));
extern void rs6000_emit_eh_toc_restore PARAMS ((rtx));
extern void rs6000_emit_move PARAMS ((rtx, rtx, enum machine_mode));
extern rtx rs6000_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
extern void rs6000_select_rtx_section PARAMS ((enum machine_mode, rtx));
#endif /* RTX_CODE */
......
......@@ -1458,8 +1458,277 @@ rs6000_legitimize_address (x, oldx, mode)
else
return NULL_RTX;
}
/* Emit a move from SOURCE to DEST in mode MODE. */
void
rs6000_emit_move (dest, source, mode)
rtx dest;
rtx source;
enum machine_mode mode;
{
rtx operands[2];
operands[0] = dest;
operands[1] = source;
/* Sanity checks. Check that we get CONST_DOUBLE only when we should. */
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& ! FLOAT_MODE_P (mode)
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
{
/* FIXME. This should never happen. */
/* Since it seems that it does, do the safe thing and convert
to a CONST_INT. */
operands[1] =
GEN_INT (trunc_int_for_mode (CONST_DOUBLE_LOW (operands[1]), mode));
}
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& ! FLOAT_MODE_P (mode)
&& ((CONST_DOUBLE_HIGH (operands[1]) == 0
&& CONST_DOUBLE_LOW (operands[1]) >= 0)
|| (CONST_DOUBLE_HIGH (operands[1]) == -1
&& CONST_DOUBLE_LOW (operands[1]) < 0)))
abort ();
if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
operands[1] = force_reg (mode, operands[1]);
if (mode == SFmode && ! TARGET_POWERPC && TARGET_HARD_FLOAT)
{
int regnum = true_regnum (operands[1]);
/* regnum may be -1 in which case the test below will fail. */
/* If operands[1] is a register, on POWER it may have
double-precision data in it, so truncate it to single
precision. */
if (FP_REGNO_P (regnum) || regnum >= FIRST_PSEUDO_REGISTER)
{
rtx newreg;
newreg = (no_new_pseudos ? operands[1] : gen_reg_rtx (mode));
emit_insn (gen_aux_truncdfsf2 (newreg, operands[1]));
operands[1] = newreg;
}
}
/* Only a tiny bit of handling for CONSTANT_P_RTX is necessary. */
if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
{
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
return;
}
/* FIXME: In the long term, this switch statement should go away
and be replaced by a sequence of tests based on things like
mode == Pmode. */
switch (mode)
{
case HImode:
case QImode:
if (CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != CONST_INT)
{
operands[1] = force_const_mem (mode, operands[1]);
if (! memory_address_p (mode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], mode,
XEXP (operands[1], 0));
}
break;
case DFmode:
case SFmode:
if (CONSTANT_P (operands[1])
&& ! easy_fp_constant (operands[1], mode))
{
operands[1] = force_const_mem (mode, operands[1]);
if (! memory_address_p (mode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], mode,
XEXP (operands[1], 0));
}
break;
case SImode:
/* Use default pattern for address of ELF small data */
if (TARGET_ELF
&& (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
&& (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST)
&& small_data_operand (operands[1], SImode))
{
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
return;
}
if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
&& flag_pic == 1 && got_operand (operands[1], SImode))
{
emit_insn (gen_movsi_got (operands[0], operands[1]));
return;
}
if (TARGET_ELF && TARGET_NO_TOC && ! TARGET_64BIT
&& ! flag_pic
&& CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != HIGH
&& GET_CODE (operands[1]) != CONST_INT)
{
rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (SImode));
/* If this is a function address on -mcall-aixdesc,
convert it to the address of the descriptor. */
if (DEFAULT_ABI == ABI_AIX
&& GET_CODE (operands[1]) == SYMBOL_REF
&& XSTR (operands[1], 0)[0] == '.')
{
const char *name = XSTR (operands[1], 0);
rtx new_ref;
while (*name == '.')
name++;
new_ref = gen_rtx_SYMBOL_REF (Pmode, name);
CONSTANT_POOL_ADDRESS_P (new_ref)
= CONSTANT_POOL_ADDRESS_P (operands[1]);
SYMBOL_REF_FLAG (new_ref) = SYMBOL_REF_FLAG (operands[1]);
SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
operands[1] = new_ref;
}
emit_insn (gen_elf_high (target, operands[1]));
emit_insn (gen_elf_low (operands[0], target, operands[1]));
return;
}
if (CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != CONST_INT
&& GET_CODE (operands[1]) != HIGH
&& ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
&& ! TOC_RELATIVE_EXPR_P (operands[1]))
{
/* Emit a USE operation so that the constant isn't deleted if
expensive optimizations are turned on because nobody
references it. This should only be done for operands that
contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
This should not be done for operands that contain LABEL_REFs.
For now, we just handle the obvious case. */
if (GET_CODE (operands[1]) != LABEL_REF)
emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
/* If we are to limit the number of things we put in the TOC and
this is a symbol plus a constant we can add in one insn,
just put the symbol in the TOC and add the constant. Don't do
this if reload is in progress. */
if (GET_CODE (operands[1]) == CONST
&& TARGET_NO_SUM_IN_TOC && ! reload_in_progress
&& GET_CODE (XEXP (operands[1], 0)) == PLUS
&& add_operand (XEXP (XEXP (operands[1], 0), 1), SImode)
&& (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
|| GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
&& ! side_effects_p (operands[0]))
{
rtx sym = force_const_mem (SImode, XEXP (XEXP (operands[1], 0), 0));
rtx other = XEXP (XEXP (operands[1], 0), 1);
emit_insn (gen_addsi3 (operands[0], force_reg (SImode, sym), other));
return;
}
operands[1] = force_const_mem (SImode, operands[1]);
if (TARGET_TOC
&& CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
XEXP (operands[1], 0))))
{
operands[1] = gen_rtx_MEM (SImode,
create_TOC_reference (XEXP (operands[1], 0)));
MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();
RTX_UNCHANGING_P (operands[1]) = 1;
}
if (! memory_address_p (SImode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], SImode,
XEXP (operands[1], 0));
}
break;
case DImode:
if (TARGET_64BIT
&& CONSTANT_P (operands[1])
#if HOST_BITS_PER_WIDE_INT == 32
&& GET_CODE (operands[1]) != CONST_INT
#endif
&& ! easy_fp_constant (operands[1], DImode)
&& ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
&& ! TOC_RELATIVE_EXPR_P (operands[1]))
{
/* Emit a USE operation so that the constant isn't deleted if
expensive optimizations are turned on because nobody
references it. This should only be done for operands that
contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
This should not be done for operands that contain LABEL_REFs.
For now, we just handle the obvious case. */
if (GET_CODE (operands[1]) != LABEL_REF)
emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
/* If we are to limit the number of things we put in the TOC and
this is a symbol plus a constant we can add in one insn,
just put the symbol in the TOC and add the constant. Don't do
this if reload is in progress. */
if (GET_CODE (operands[1]) == CONST
&& TARGET_NO_SUM_IN_TOC && ! reload_in_progress
&& GET_CODE (XEXP (operands[1], 0)) == PLUS
&& add_operand (XEXP (XEXP (operands[1], 0), 1), DImode)
&& (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
|| GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
&& ! side_effects_p (operands[0]))
{
rtx sym = force_const_mem (DImode, XEXP (XEXP (operands[1], 0), 0));
rtx other = XEXP (XEXP (operands[1], 0), 1);
emit_insn (gen_adddi3 (operands[0], force_reg (DImode, sym), other));
return;
}
operands[1] = force_const_mem (DImode, operands[1]);
if (TARGET_TOC
&& CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
XEXP (operands[1], 0))))
{
operands[1] = gen_rtx_MEM (DImode,
create_TOC_reference (XEXP (operands[1], 0)));
MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();
RTX_UNCHANGING_P (operands[1]) = 1;
}
if (! memory_address_p (DImode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], DImode,
XEXP (operands[1], 0));
}
break;
case TImode:
if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) != REG
&& ! reload_in_progress)
operands[0] = change_address (operands[0], TImode,
copy_addr_to_reg (XEXP (operands[0], 0)));
if (GET_CODE (operands[1]) == MEM
&& GET_CODE (XEXP (operands[1], 0)) != REG
&& ! reload_in_progress)
operands[1] = change_address (operands[1], TImode,
copy_addr_to_reg (XEXP (operands[1], 0)));
break;
default:
abort ();
}
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
}
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
......
......@@ -7434,123 +7434,7 @@
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "any_operand" ""))]
""
"
{
if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
operands[1] = force_reg (SImode, operands[1]);
/* Convert a move of a CONST_DOUBLE into a CONST_INT */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
/* Only a tiny bit of handling for CONSTANT_P_RTX is necessary. */
if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
{
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
DONE;
}
/* Use default pattern for address of ELF small data */
if (TARGET_ELF
&& (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
&& (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST)
&& small_data_operand (operands[1], SImode))
{
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
DONE;
}
if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
&& flag_pic == 1 && got_operand (operands[1], SImode))
{
emit_insn (gen_movsi_got (operands[0], operands[1]));
DONE;
}
if (TARGET_ELF && TARGET_NO_TOC && ! TARGET_64BIT
&& ! flag_pic
&& CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != HIGH
&& GET_CODE (operands[1]) != CONST_INT)
{
rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (SImode));
/* If this is a function address on -mcall-aixdesc,
convert it to the address of the descriptor. */
if (DEFAULT_ABI == ABI_AIX
&& GET_CODE (operands[1]) == SYMBOL_REF
&& XSTR (operands[1], 0)[0] == '.')
{
const char *name = XSTR (operands[1], 0);
rtx new_ref;
while (*name == '.')
name++;
new_ref = gen_rtx_SYMBOL_REF (Pmode, name);
CONSTANT_POOL_ADDRESS_P (new_ref)
= CONSTANT_POOL_ADDRESS_P (operands[1]);
SYMBOL_REF_FLAG (new_ref) = SYMBOL_REF_FLAG (operands[1]);
SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
operands[1] = new_ref;
}
emit_insn (gen_elf_high (target, operands[1]));
emit_insn (gen_elf_low (operands[0], target, operands[1]));
DONE;
}
if (CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != CONST_INT
&& GET_CODE (operands[1]) != HIGH
&& ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
&& ! TOC_RELATIVE_EXPR_P (operands[1]))
{
/* Emit a USE operation so that the constant isn't deleted if
expensive optimizations are turned on because nobody
references it. This should only be done for operands that
contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
This should not be done for operands that contain LABEL_REFs.
For now, we just handle the obvious case. */
if (GET_CODE (operands[1]) != LABEL_REF)
emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
/* If we are to limit the number of things we put in the TOC and
this is a symbol plus a constant we can add in one insn,
just put the symbol in the TOC and add the constant. Don't do
this if reload is in progress. */
if (GET_CODE (operands[1]) == CONST
&& TARGET_NO_SUM_IN_TOC && ! reload_in_progress
&& GET_CODE (XEXP (operands[1], 0)) == PLUS
&& add_operand (XEXP (XEXP (operands[1], 0), 1), SImode)
&& (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
|| GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
&& ! side_effects_p (operands[0]))
{
rtx sym = force_const_mem (SImode, XEXP (XEXP (operands[1], 0), 0));
rtx other = XEXP (XEXP (operands[1], 0), 1);
emit_insn (gen_addsi3 (operands[0], force_reg (SImode, sym), other));
DONE;
}
operands[1] = force_const_mem (SImode, operands[1]);
if (TARGET_TOC
&& CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
XEXP (operands[1], 0))))
{
operands[1] = gen_rtx_MEM (SImode,
create_TOC_reference (XEXP (operands[1], 0)));
MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();
RTX_UNCHANGING_P (operands[1]) = 1;
}
if (! memory_address_p (SImode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], SImode,
XEXP (operands[1], 0));
}
}")
"{ rs6000_emit_move (operands[0], operands[1], SImode); DONE; }")
(define_insn "*movsi_internal1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h")
......@@ -7620,21 +7504,7 @@
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "any_operand" ""))]
""
"
{
if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
operands[1] = force_reg (HImode, operands[1]);
if (CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != CONST_INT)
{
operands[1] = force_const_mem (HImode, operands[1]);
if (! memory_address_p (HImode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], HImode,
XEXP (operands[1], 0));
}
}")
"{ rs6000_emit_move (operands[0], operands[1], HImode); DONE; }")
(define_insn ""
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
......@@ -7656,21 +7526,7 @@
[(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "any_operand" ""))]
""
"
{
if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
operands[1] = force_reg (QImode, operands[1]);
if (CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != CONST_INT)
{
operands[1] = force_const_mem (QImode, operands[1]);
if (! memory_address_p (QImode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], QImode,
XEXP (operands[1], 0));
}
}")
"{ rs6000_emit_move (operands[0], operands[1], QImode); DONE; }")
(define_insn ""
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
......@@ -7723,49 +7579,7 @@
[(set (match_operand:SF 0 "nonimmediate_operand" "")
(match_operand:SF 1 "any_operand" ""))]
""
"
{
/* If we are called from reload, we might be getting a SUBREG of a hard
reg. So expand it. */
if (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
&& REGNO (SUBREG_REG (operands[0])) < FIRST_PSEUDO_REGISTER
&& (! REG_FUNCTION_VALUE_P (SUBREG_REG (operands[0]))
|| ! rtx_equal_function_value_matters))
operands[0] = alter_subreg (operands[0]);
if (GET_CODE (operands[1]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[1])) == REG
&& REGNO (SUBREG_REG (operands[1])) < FIRST_PSEUDO_REGISTER)
operands[1] = alter_subreg (operands[1]);
if (GET_CODE (operands[0]) == MEM)
{
/* If operands[1] is a register, it may have double-precision data
in it, so truncate it to single precision. We need not do
this for POWERPC. */
if (! TARGET_POWERPC && TARGET_HARD_FLOAT
&& GET_CODE (operands[1]) == REG
&& (FP_REGNO_P (REGNO (operands[1]))
|| REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER))
{
rtx newreg = (no_new_pseudos ? operands[1] : gen_reg_rtx (SFmode));
emit_insn (gen_aux_truncdfsf2 (newreg, operands[1]));
operands[1] = newreg;
}
operands[1] = force_reg (SFmode, operands[1]);
}
if (CONSTANT_P (operands[1]) && TARGET_HARD_FLOAT
&& ! easy_fp_constant (operands[1], SFmode))
{
operands[1] = force_const_mem (SFmode, operands[1]);
if (! memory_address_p (SFmode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], SFmode,
XEXP (operands[1], 0));
}
}")
"{ rs6000_emit_move (operands[0], operands[1], SFmode); DONE; }")
(define_split
[(set (match_operand:SF 0 "gpc_reg_operand" "")
......@@ -7831,20 +7645,7 @@
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(match_operand:DF 1 "any_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (DFmode, operands[1]);
if (CONSTANT_P (operands[1]) && ! easy_fp_constant (operands[1], DFmode))
{
operands[1] = force_const_mem (DFmode, operands[1]);
if (! memory_address_p (DFmode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], DFmode,
XEXP (operands[1], 0));
}
}")
"{ rs6000_emit_move (operands[0], operands[1], DFmode); DONE; }")
(define_split
[(set (match_operand:DF 0 "gpc_reg_operand" "")
......@@ -8100,87 +7901,7 @@
[(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "any_operand" ""))]
""
"
{
if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
operands[1] = force_reg (DImode, operands[1]);
/* Convert a move of a CONST_DOUBLE into a CONST_INT
only if sign-extended lower-half for 32-bit host. */
if (GET_CODE (operands[1]) == CONST_DOUBLE
#if HOST_BITS_PER_WIDE_INT == 32
&& ((CONST_DOUBLE_HIGH (operands[1]) == 0
&& (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
|| (CONST_DOUBLE_HIGH (operands[1]) == (HOST_WIDE_INT) 0xffffffff
&& (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))
#endif
)
operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
/* Only a tiny bit of handling for CONSTANT_P_RTX is necessary. */
if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
{
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
DONE;
}
if (TARGET_64BIT
&& CONSTANT_P (operands[1])
#if HOST_BITS_PER_WIDE_INT == 32
&& GET_CODE (operands[1]) != CONST_INT
#endif
&& ! easy_fp_constant (operands[1], DImode)
&& ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
&& ! TOC_RELATIVE_EXPR_P (operands[1]))
{
/* Emit a USE operation so that the constant isn't deleted if
expensive optimizations are turned on because nobody
references it. This should only be done for operands that
contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
This should not be done for operands that contain LABEL_REFs.
For now, we just handle the obvious case. */
if (GET_CODE (operands[1]) != LABEL_REF)
emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
/* If we are to limit the number of things we put in the TOC and
this is a symbol plus a constant we can add in one insn,
just put the symbol in the TOC and add the constant. Don't do
this if reload is in progress. */
if (GET_CODE (operands[1]) == CONST
&& TARGET_NO_SUM_IN_TOC && ! reload_in_progress
&& GET_CODE (XEXP (operands[1], 0)) == PLUS
&& add_operand (XEXP (XEXP (operands[1], 0), 1), DImode)
&& (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
|| GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
&& ! side_effects_p (operands[0]))
{
rtx sym = force_const_mem (DImode, XEXP (XEXP (operands[1], 0), 0));
rtx other = XEXP (XEXP (operands[1], 0), 1);
emit_insn (gen_adddi3 (operands[0], force_reg (DImode, sym), other));
DONE;
}
operands[1] = force_const_mem (DImode, operands[1]);
if (TARGET_TOC
&& CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
XEXP (operands[1], 0))))
{
operands[1] = gen_rtx_MEM (DImode,
create_TOC_reference (XEXP (operands[1], 0)));
MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();
RTX_UNCHANGING_P (operands[1]) = 1;
}
if (! memory_address_p (DImode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], DImode,
XEXP (operands[1], 0));
}
}")
"{ rs6000_emit_move (operands[0], operands[1], DImode); DONE; }")
(define_insn "*movdi_internal32"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m,r,r,r,r,r")
......@@ -8526,23 +8247,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
(match_operand:TI 1 "general_operand" ""))
(clobber (scratch:SI))])]
"TARGET_STRING || TARGET_POWERPC64"
"
{
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (TImode, operands[1]);
if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) != REG
&& ! reload_in_progress)
operands[0] = change_address (operands[0], TImode,
copy_addr_to_reg (XEXP (operands[0], 0)));
if (GET_CODE (operands[1]) == MEM
&& GET_CODE (XEXP (operands[1], 0)) != REG
&& ! reload_in_progress)
operands[1] = change_address (operands[1], TImode,
copy_addr_to_reg (XEXP (operands[1], 0)));
}")
"{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }")
;; We say that MQ is clobbered in the last alternative because the first
;; alternative would never get used otherwise since it would need a reload
......
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