Commit b4f50fd4 by Ramana Radhakrishnan Committed by Ramana Radhakrishnan

[AArch64] Handle literal pools for functions > 1 MiB in size.

    

This patch fixes the issue in PR63304 where we have
functions that are > 1MiB. The idea is to use adrp / ldr or adrp / add
instructions to address the literal pools under the use of a command line
option. I would like to turn this on by default on trunk but keep this
disabled by default for the release branches in order to get some
serious testing for this feature while it bakes on trunk.

As a follow-up I would like to try and see if estimate_num_insns or
something else can give us a heuristic to turn this on for "large" functions.
After all the number of incidences of this are quite low in real life,
so may be we should look to restrict this use as much as possible on the
grounds that this code generation implies an extra integer register for
addressing for every floating point and vector constant and I don't think
that's great in code that already may have high register pressure.

Tested on aarch64-none-elf with no regressions. A previous
version was bootstrapped and regression tested.

Applied to trunk.

regards
Ramana

2015-09-14  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>

    	PR target/63304
    	* config/aarch64/aarch64.c (aarch64_expand_mov_immediate): Handle
    	nopcrelative_literal_loads.
    	(aarch64_classify_address): Likewise.
    	(aarch64_constant_pool_reload_icode): Define.
    	(aarch64_secondary_reload): Handle secondary reloads for
    	literal pools.
    	(aarch64_override_options): Handle nopcrelative_literal_loads.
    	(aarch64_classify_symbol): Handle nopcrelative_literal_loads.
    	* config/aarch64/aarch64.md (aarch64_reload_movcp<GPF_TF:mode><P:mode>):
    	Define.
    	(aarch64_reload_movcp<VALL:mode><P:mode>): Likewise.
    	* config/aarch64/aarch64.opt (mpc-relative-literal-loads): New option.
    	* config/aarch64/predicates.md (aarch64_constant_pool_symref): New
    	predicate.
    	* doc/invoke.texi (mpc-relative-literal-loads): Document.

From-SVN: r227748
parent 641f1ab4
2015-09-14 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
PR target/63304
* config/aarch64/aarch64.c (aarch64_expand_mov_immediate): Handle
nopcrelative_literal_loads.
(aarch64_classify_address): Likewise.
(aarch64_constant_pool_reload_icode): Define.
(aarch64_secondary_reload): Handle secondary reloads for
literal pools.
(aarch64_override_options): Handle nopcrelative_literal_loads.
(aarch64_classify_symbol): Handle nopcrelative_literal_loads.
* config/aarch64/aarch64.md (aarch64_reload_movcp<GPF_TF:mode><P:mode>):
Define.
(aarch64_reload_movcp<VALL:mode><P:mode>): Likewise.
* config/aarch64/aarch64.opt (mpc-relative-literal-loads): New option.
* config/aarch64/predicates.md (aarch64_constant_pool_symref): New
predicate.
* doc/invoke.texi (mpc-relative-literal-loads): Document.
2015-09-14 John David Anglin <danglin@gcc.gnu.org>
PR middle-end/67401
......
......@@ -1734,11 +1734,27 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
aarch64_emit_move (dest, base);
return;
}
mem = force_const_mem (ptr_mode, imm);
gcc_assert (mem);
/* If we aren't generating PC relative literals, then
we need to expand the literal pool access carefully.
This is something that needs to be done in a number
of places, so could well live as a separate function. */
if (nopcrelative_literal_loads)
{
gcc_assert (can_create_pseudo_p ());
base = gen_reg_rtx (ptr_mode);
aarch64_expand_mov_immediate (base, XEXP (mem, 0));
mem = gen_rtx_MEM (ptr_mode, base);
}
if (mode != ptr_mode)
mem = gen_rtx_ZERO_EXTEND (mode, mem);
emit_insn (gen_rtx_SET (dest, mem));
return;
case SYMBOL_SMALL_TLSGD:
......@@ -3854,9 +3870,10 @@ aarch64_classify_address (struct aarch64_address_info *info,
rtx sym, addend;
split_const (x, &sym, &addend);
return (GET_CODE (sym) == LABEL_REF
|| (GET_CODE (sym) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (sym)));
return ((GET_CODE (sym) == LABEL_REF
|| (GET_CODE (sym) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (sym)
&& !nopcrelative_literal_loads)));
}
return false;
......@@ -5039,12 +5056,69 @@ aarch64_legitimize_reload_address (rtx *x_p,
}
/* Return the reload icode required for a constant pool in mode. */
static enum insn_code
aarch64_constant_pool_reload_icode (machine_mode mode)
{
switch (mode)
{
case SFmode:
return CODE_FOR_aarch64_reload_movcpsfdi;
case DFmode:
return CODE_FOR_aarch64_reload_movcpdfdi;
case TFmode:
return CODE_FOR_aarch64_reload_movcptfdi;
case V8QImode:
return CODE_FOR_aarch64_reload_movcpv8qidi;
case V16QImode:
return CODE_FOR_aarch64_reload_movcpv16qidi;
case V4HImode:
return CODE_FOR_aarch64_reload_movcpv4hidi;
case V8HImode:
return CODE_FOR_aarch64_reload_movcpv8hidi;
case V2SImode:
return CODE_FOR_aarch64_reload_movcpv2sidi;
case V4SImode:
return CODE_FOR_aarch64_reload_movcpv4sidi;
case V2DImode:
return CODE_FOR_aarch64_reload_movcpv2didi;
case V2DFmode:
return CODE_FOR_aarch64_reload_movcpv2dfdi;
default:
gcc_unreachable ();
}
gcc_unreachable ();
}
static reg_class_t
aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
reg_class_t rclass,
machine_mode mode,
secondary_reload_info *sri)
{
/* If we have to disable direct literal pool loads and stores because the
function is too big, then we need a scratch register. */
if (MEM_P (x) && GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)
&& (SCALAR_FLOAT_MODE_P (GET_MODE (x))
|| targetm.vector_mode_supported_p (GET_MODE (x)))
&& nopcrelative_literal_loads)
{
sri->icode = aarch64_constant_pool_reload_icode (mode);
return NO_REGS;
}
/* Without the TARGET_SIMD instructions we cannot move a Q register
to a Q register directly. We need a scratch. */
if (REG_P (x) && (mode == TFmode || mode == TImode) && mode == GET_MODE (x)
......@@ -7693,6 +7767,24 @@ aarch64_override_options_after_change_1 (struct gcc_options *opts)
if (opts->x_align_functions <= 0)
opts->x_align_functions = aarch64_tune_params.function_align;
}
/* If nopcrelative_literal_loads is set on the command line, this
implies that the user asked for PC relative literal loads. */
if (nopcrelative_literal_loads == 1)
nopcrelative_literal_loads = 0;
/* If it is not set on the command line, we default to no
pc relative literal loads. */
if (nopcrelative_literal_loads == 2)
nopcrelative_literal_loads = 1;
/* In the tiny memory model it makes no sense
to disallow non PC relative literal pool loads
as many other things will break anyway. */
if (nopcrelative_literal_loads
&& (aarch64_cmodel == AARCH64_CMODEL_TINY
|| aarch64_cmodel == AARCH64_CMODEL_TINY_PIC))
nopcrelative_literal_loads = 0;
}
/* 'Unpack' up the internal tuning structs and update the options
......@@ -8884,7 +8976,16 @@ aarch64_classify_symbol (rtx x, rtx offset,
if (GET_CODE (x) == SYMBOL_REF)
{
if (aarch64_cmodel == AARCH64_CMODEL_LARGE)
return SYMBOL_FORCE_TO_MEM;
{
/* This is alright even in PIC code as the constant
pool reference is always PC relative and within
the same translation unit. */
if (nopcrelative_literal_loads
&& CONSTANT_POOL_ADDRESS_P (x))
return SYMBOL_SMALL_ABSOLUTE;
else
return SYMBOL_FORCE_TO_MEM;
}
if (aarch64_tls_symbol_p (x))
return aarch64_classify_tls_symbol (x);
......
......@@ -4415,6 +4415,32 @@
;; -------------------------------------------------------------------
;; Reload support
;; -------------------------------------------------------------------
;; Reload Scalar Floating point modes from constant pool.
;; The AArch64 port doesn't have __int128 constant move support.
(define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
[(set (match_operand:GPF_TF 0 "register_operand" "=w")
(mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
(clobber (match_operand:P 2 "register_operand" "=&r"))]
"TARGET_FLOAT && nopcrelative_literal_loads"
{
aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
DONE;
}
)
;; Reload Vector modes from constant pool.
(define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
[(set (match_operand:VALL 0 "register_operand" "=w")
(mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
(clobber (match_operand:P 2 "register_operand" "=&r"))]
"TARGET_FLOAT && nopcrelative_literal_loads"
{
aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
DONE;
}
)
(define_expand "aarch64_reload_mov<mode>"
[(set (match_operand:TX 0 "register_operand" "=w")
......
......@@ -144,3 +144,7 @@ Enum(aarch64_abi) String(ilp32) Value(AARCH64_ABI_ILP32)
EnumValue
Enum(aarch64_abi) String(lp64) Value(AARCH64_ABI_LP64)
mpc-relative-literal-loads
Target Report Save Var(nopcrelative_literal_loads) Init(2) Save
PC relative literal loads.
......@@ -44,6 +44,9 @@
;; Double vector modes.
(define_mode_iterator VDF [V2SF V4HF])
;; Iterator for all scalar floating point modes (SF, DF and TF)
(define_mode_iterator GPF_TF [SF DF TF])
;; Integer vector modes.
(define_mode_iterator VDQ_I [V8QI V16QI V4HI V8HI V2SI V4SI V2DI])
......
......@@ -362,3 +362,7 @@
(define_predicate "aarch64_simd_shift_imm_bitsize_di"
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 0, 64)")))
(define_predicate "aarch64_constant_pool_symref"
(and (match_code "symbol_ref")
(match_test "CONSTANT_POOL_ADDRESS_P (op)")))
......@@ -12449,6 +12449,14 @@ for @var{string} in this option are not guaranteed to be consistent
across releases.
This option is only intended to be useful when developing GCC.
@item -mpc-relative-literal-loads
@opindex mpcrelativeliteralloads
Enable PC relative literal loads. If this option is used, literal
pools are assumed to have a range of up to 1MiB and an appropriate
instruction sequence is used. This option has no impact when used
with @option{-mcmodel=tiny}.
@end table
@subsubsection @option{-march} and @option{-mcpu} Feature Modifiers
......
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