aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/aarch64/aarch64.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/aarch64/aarch64.c')
-rw-r--r--gcc/config/aarch64/aarch64.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index fbee64dde..889d19e40 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -686,43 +686,57 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
unsigned HOST_WIDE_INT val;
bool subtargets;
rtx subtarget;
- rtx base, offset;
int one_match, zero_match;
gcc_assert (mode == SImode || mode == DImode);
- /* If we have (const (plus symbol offset)), and that expression cannot
- be forced into memory, load the symbol first and add in the offset. */
- split_const (imm, &base, &offset);
- if (offset != const0_rtx
- && (targetm.cannot_force_const_mem (mode, imm)
- || (can_create_pseudo_p ())))
- {
- base = aarch64_force_temporary (dest, base);
- aarch64_emit_move (dest, aarch64_add_offset (mode, NULL, base, INTVAL (offset)));
- return;
- }
-
/* Check on what type of symbol it is. */
- if (GET_CODE (base) == SYMBOL_REF || GET_CODE (base) == LABEL_REF)
+ if (GET_CODE (imm) == SYMBOL_REF
+ || GET_CODE (imm) == LABEL_REF
+ || GET_CODE (imm) == CONST)
{
- rtx mem;
- switch (aarch64_classify_symbol (base, SYMBOL_CONTEXT_ADR))
+ rtx mem, base, offset;
+ enum aarch64_symbol_type sty;
+
+ /* If we have (const (plus symbol offset)), separate out the offset
+ before we start classifying the symbol. */
+ split_const (imm, &base, &offset);
+
+ sty = aarch64_classify_symbol (base, SYMBOL_CONTEXT_ADR);
+ switch (sty)
{
case SYMBOL_FORCE_TO_MEM:
- mem = force_const_mem (mode, imm);
+ if (offset != const0_rtx
+ && targetm.cannot_force_const_mem (mode, imm))
+ {
+ gcc_assert(can_create_pseudo_p ());
+ base = aarch64_force_temporary (dest, base);
+ base = aarch64_add_offset (mode, NULL, base, INTVAL (offset));
+ aarch64_emit_move (dest, base);
+ return;
+ }
+ mem = force_const_mem (mode, imm);
gcc_assert (mem);
emit_insn (gen_rtx_SET (VOIDmode, dest, mem));
return;
- case SYMBOL_SMALL_TLSGD:
- case SYMBOL_SMALL_TLSDESC:
- case SYMBOL_SMALL_GOTTPREL:
- case SYMBOL_SMALL_TPREL:
+ case SYMBOL_SMALL_TLSGD:
+ case SYMBOL_SMALL_TLSDESC:
+ case SYMBOL_SMALL_GOTTPREL:
case SYMBOL_SMALL_GOT:
+ if (offset != const0_rtx)
+ {
+ gcc_assert(can_create_pseudo_p ());
+ base = aarch64_force_temporary (dest, base);
+ base = aarch64_add_offset (mode, NULL, base, INTVAL (offset));
+ aarch64_emit_move (dest, base);
+ return;
+ }
+ /* FALLTHRU */
+
+ case SYMBOL_SMALL_TPREL:
case SYMBOL_SMALL_ABSOLUTE:
- aarch64_load_symref_appropriately
- (dest, imm, aarch64_classify_symbol (base, SYMBOL_CONTEXT_ADR));
+ aarch64_load_symref_appropriately (dest, imm, sty);
return;
default:
@@ -730,7 +744,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
}
}
- if ((CONST_INT_P (imm) && aarch64_move_imm (INTVAL (imm), mode)))
+ if (CONST_INT_P (imm) && aarch64_move_imm (INTVAL (imm), mode))
{
emit_insn (gen_rtx_SET (VOIDmode, dest, imm));
return;