Skip to content

Commit

Permalink
2017-07-28 Tamar Christina <tamar.christina@arm.com>
Browse files Browse the repository at this point in the history
	* config/aarch64/aarch64.c
	(aarch64_simd_container_mode): Add prototype.
	(aarch64_expand_mov_immediate): Add HI support.
	(aarch64_reinterpret_float_as_int, aarch64_float_const_rtx_p: New.
	(aarch64_can_const_movi_rtx_p): New.
	(aarch64_preferred_reload_class):
	Remove restrictions of using FP registers for certain SIMD operations.
	(aarch64_rtx_costs): Added new cost for CONST_DOUBLE moves.
	(aarch64_valid_floating_const): Add integer move validation.
	(aarch64_simd_imm_scalar_p): Remove.
	(aarch64_output_scalar_simd_mov_immediate): Generalize function.
	(aarch64_legitimate_constant_p): Expand list of supported cases.
	* config/aarch64/aarch64-protos.h
	(aarch64_float_const_rtx_p, aarch64_can_const_movi_rtx_p): New.
	(aarch64_reinterpret_float_as_int): New.
	(aarch64_simd_imm_scalar_p): Remove.
	* config/aarch64/constraints.md (Uvi): New.
	(Dd): Split into Ds and new Dd.
	* config/aarch64/aarch64.md (*movsi_aarch64):
	Add SIMD mov case.
	(*movdi_aarch64): Add SIMD mov case.

From-SVN: r250672
  • Loading branch information
TamarChristinaArm authored and Tamar Christina committed Jul 28, 2017
1 parent 39ff50c commit a217096
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 46 deletions.
24 changes: 24 additions & 0 deletions gcc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
2017-07-28 Tamar Christina <tamar.christina@arm.com>

* config/aarch64/aarch64.c
(aarch64_simd_container_mode): Add prototype.
(aarch64_expand_mov_immediate): Add HI support.
(aarch64_reinterpret_float_as_int, aarch64_float_const_rtx_p: New.
(aarch64_can_const_movi_rtx_p): New.
(aarch64_preferred_reload_class):
Remove restrictions of using FP registers for certain SIMD operations.
(aarch64_rtx_costs): Added new cost for CONST_DOUBLE moves.
(aarch64_valid_floating_const): Add integer move validation.
(aarch64_simd_imm_scalar_p): Remove.
(aarch64_output_scalar_simd_mov_immediate): Generalize function.
(aarch64_legitimate_constant_p): Expand list of supported cases.
* config/aarch64/aarch64-protos.h
(aarch64_float_const_rtx_p, aarch64_can_const_movi_rtx_p): New.
(aarch64_reinterpret_float_as_int): New.
(aarch64_simd_imm_scalar_p): Remove.
* config/aarch64/constraints.md (Uvi): New.
(Dd): Split into Ds and new Dd.
* config/aarch64/aarch64.md (*movsi_aarch64):
Add SIMD mov case.
(*movdi_aarch64): Add SIMD mov case.

2017-07-28 Bin Cheng <bin.cheng@arm.com>

* tree-predcom.c: (struct chain): Handle store-store chain in which
Expand Down
4 changes: 3 additions & 1 deletion gcc/config/aarch64/aarch64-protos.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,15 @@ unsigned HOST_WIDE_INT aarch64_and_split_imm2 (HOST_WIDE_INT val_in);
bool aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode);
int aarch64_branch_cost (bool, bool);
enum aarch64_symbol_type aarch64_classify_symbolic_expression (rtx);
bool aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode);
bool aarch64_const_vec_all_same_int_p (rtx, HOST_WIDE_INT);
bool aarch64_constant_address_p (rtx);
bool aarch64_emit_approx_div (rtx, rtx, rtx);
bool aarch64_emit_approx_sqrt (rtx, rtx, bool);
void aarch64_expand_call (rtx, rtx, bool);
bool aarch64_expand_movmem (rtx *);
bool aarch64_float_const_zero_rtx_p (rtx);
bool aarch64_float_const_rtx_p (rtx);
bool aarch64_function_arg_regno_p (unsigned);
bool aarch64_fusion_enabled_p (enum aarch64_fusion_pairs);
bool aarch64_gen_movmemqi (rtx *);
Expand All @@ -351,9 +353,9 @@ bool aarch64_pad_arg_upward (machine_mode, const_tree);
bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
bool aarch64_regno_ok_for_base_p (int, bool);
bool aarch64_regno_ok_for_index_p (int, bool);
bool aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *fail);
bool aarch64_simd_check_vect_par_cnst_half (rtx op, machine_mode mode,
bool high);
bool aarch64_simd_imm_scalar_p (rtx x, machine_mode mode);
bool aarch64_simd_imm_zero_p (rtx, machine_mode);
bool aarch64_simd_scalar_immediate_valid_for_move (rtx, machine_mode);
bool aarch64_simd_shift_imm_p (rtx, machine_mode, bool);
Expand Down
191 changes: 155 additions & 36 deletions gcc/config/aarch64/aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ static bool aarch64_builtin_support_vector_misalignment (machine_mode mode,
const_tree type,
int misalignment,
bool is_packed);
static machine_mode
aarch64_simd_container_mode (machine_mode mode, unsigned width);

/* Major revision number of the ARM Architecture implemented by the target. */
unsigned aarch64_architecture_version;
Expand Down Expand Up @@ -4677,6 +4679,69 @@ aarch64_legitimize_address_displacement (rtx *disp, rtx *off, machine_mode mode)
return true;
}

/* Return the binary representation of floating point constant VALUE in INTVAL.
If the value cannot be converted, return false without setting INTVAL.
The conversion is done in the given MODE. */
bool
aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *intval)
{

/* We make a general exception for 0. */
if (aarch64_float_const_zero_rtx_p (value))
{
*intval = 0;
return true;
}

machine_mode mode = GET_MODE (value);
if (GET_CODE (value) != CONST_DOUBLE
|| !SCALAR_FLOAT_MODE_P (mode)
|| GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT
/* Only support up to DF mode. */
|| GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (DFmode))
return false;

unsigned HOST_WIDE_INT ival = 0;

long res[2];
real_to_target (res,
CONST_DOUBLE_REAL_VALUE (value),
REAL_MODE_FORMAT (mode));

ival = zext_hwi (res[0], 32);
if (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (DFmode))
ival |= (zext_hwi (res[1], 32) << 32);

*intval = ival;
return true;
}

/* Return TRUE if rtx X is an immediate constant that can be moved using a
single MOV(+MOVK) followed by an FMOV. */
bool
aarch64_float_const_rtx_p (rtx x)
{
machine_mode mode = GET_MODE (x);
if (mode == VOIDmode)
return false;

/* Determine whether it's cheaper to write float constants as
mov/movk pairs over ldr/adrp pairs. */
unsigned HOST_WIDE_INT ival;

if (GET_CODE (x) == CONST_DOUBLE
&& SCALAR_FLOAT_MODE_P (mode)
&& aarch64_reinterpret_float_as_int (x, &ival))
{
machine_mode imode = mode == HFmode ? SImode : int_mode_for_mode (mode);
int num_instr = aarch64_internal_mov_immediate
(NULL_RTX, gen_int_mode (ival, imode), false, imode);
return num_instr < 3;
}

return false;
}

/* Return TRUE if rtx X is immediate constant 0.0 */
bool
aarch64_float_const_zero_rtx_p (rtx x)
Expand All @@ -4689,6 +4754,49 @@ aarch64_float_const_zero_rtx_p (rtx x)
return real_equal (CONST_DOUBLE_REAL_VALUE (x), &dconst0);
}

/* Return TRUE if rtx X is immediate constant that fits in a single
MOVI immediate operation. */
bool
aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode)
{
if (!TARGET_SIMD)
return false;

/* We make a general exception for 0. */
if (aarch64_float_const_zero_rtx_p (x))
return true;

machine_mode vmode, imode;
unsigned HOST_WIDE_INT ival;

if (GET_CODE (x) == CONST_DOUBLE
&& SCALAR_FLOAT_MODE_P (mode))
{
if (!aarch64_reinterpret_float_as_int (x, &ival))
return false;

imode = int_mode_for_mode (mode);
}
else if (GET_CODE (x) == CONST_INT
&& SCALAR_INT_MODE_P (mode))
{
imode = mode;
ival = INTVAL (x);
}
else
return false;

/* use a 64 bit mode for everything except for DI/DF mode, where we use
a 128 bit vector mode. */
int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64;

vmode = aarch64_simd_container_mode (imode, width);
rtx v_op = aarch64_simd_gen_const_vector_dup (vmode, ival);

return aarch64_simd_valid_immediate (v_op, vmode, false, NULL);
}


/* Return the fixed registers used for condition codes. */

static bool
Expand Down Expand Up @@ -5883,12 +5991,6 @@ aarch64_preferred_reload_class (rtx x, reg_class_t regclass)
return NO_REGS;
}

/* If it's an integer immediate that MOVI can't handle, then
FP_REGS is not an option, so we return NO_REGS instead. */
if (CONST_INT_P (x) && reg_class_subset_p (regclass, FP_REGS)
&& !aarch64_simd_imm_scalar_p (x, GET_MODE (x)))
return NO_REGS;

/* Register eliminiation can result in a request for
SP+constant->FP_REGS. We cannot support such operations which
use SP as source and an FP_REG as destination, so reject out
Expand Down Expand Up @@ -6838,6 +6940,25 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
return true;

case CONST_DOUBLE:

/* First determine number of instructions to do the move
as an integer constant. */
if (!aarch64_float_const_representable_p (x)
&& !aarch64_can_const_movi_rtx_p (x, mode)
&& aarch64_float_const_rtx_p (x))
{
unsigned HOST_WIDE_INT ival;
bool succeed = aarch64_reinterpret_float_as_int (x, &ival);
gcc_assert (succeed);

machine_mode imode = mode == HFmode ? SImode
: int_mode_for_mode (mode);
int ncost = aarch64_internal_mov_immediate
(NULL_RTX, gen_int_mode (ival, imode), false, imode);
*cost += COSTS_N_INSNS (ncost);
return true;
}

if (speed)
{
/* mov[df,sf]_aarch64. */
Expand Down Expand Up @@ -10182,18 +10303,16 @@ aarch64_legitimate_pic_operand_p (rtx x)
/* Return true if X holds either a quarter-precision or
floating-point +0.0 constant. */
static bool
aarch64_valid_floating_const (machine_mode mode, rtx x)
aarch64_valid_floating_const (rtx x)
{
if (!CONST_DOUBLE_P (x))
return false;

if (aarch64_float_const_zero_rtx_p (x))
/* This call determines which constants can be used in mov<mode>
as integer moves instead of constant loads. */
if (aarch64_float_const_rtx_p (x))
return true;

/* We only handle moving 0.0 to a TFmode register. */
if (!(mode == SFmode || mode == DFmode))
return false;

return aarch64_float_const_representable_p (x);
}

Expand All @@ -10205,11 +10324,15 @@ aarch64_legitimate_constant_p (machine_mode mode, rtx x)
if (TARGET_SIMD && aarch64_vect_struct_mode_p (mode))
return false;

/* This could probably go away because
we now decompose CONST_INTs according to expand_mov_immediate. */
/* For these cases we never want to use a literal load.
As such we have to prevent the compiler from forcing these
to memory. */
if ((GET_CODE (x) == CONST_VECTOR
&& aarch64_simd_valid_immediate (x, mode, false, NULL))
|| CONST_INT_P (x) || aarch64_valid_floating_const (mode, x))
|| CONST_INT_P (x)
|| aarch64_valid_floating_const (x)
|| aarch64_can_const_movi_rtx_p (x, mode)
|| aarch64_float_const_rtx_p (x))
return !targetm.cannot_force_const_mem (mode, x);

if (GET_CODE (x) == HIGH
Expand Down Expand Up @@ -11491,23 +11614,6 @@ aarch64_mask_from_zextract_ops (rtx width, rtx pos)
return GEN_INT (mask << UINTVAL (pos));
}

bool
aarch64_simd_imm_scalar_p (rtx x, machine_mode mode ATTRIBUTE_UNUSED)
{
HOST_WIDE_INT imm = INTVAL (x);
int i;

for (i = 0; i < 8; i++)
{
unsigned int byte = imm & 0xff;
if (byte != 0xff && byte != 0)
return false;
imm >>= 8;
}

return true;
}

bool
aarch64_mov_operand_p (rtx x, machine_mode mode)
{
Expand Down Expand Up @@ -12899,15 +13005,28 @@ aarch64_output_simd_mov_immediate (rtx const_vector,
}

char*
aarch64_output_scalar_simd_mov_immediate (rtx immediate,
machine_mode mode)
aarch64_output_scalar_simd_mov_immediate (rtx immediate, machine_mode mode)
{

/* If a floating point number was passed and we desire to use it in an
integer mode do the conversion to integer. */
if (CONST_DOUBLE_P (immediate) && GET_MODE_CLASS (mode) == MODE_INT)
{
unsigned HOST_WIDE_INT ival;
if (!aarch64_reinterpret_float_as_int (immediate, &ival))
gcc_unreachable ();
immediate = gen_int_mode (ival, mode);
}

machine_mode vmode;
/* use a 64 bit mode for everything except for DI/DF mode, where we use
a 128 bit vector mode. */
int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64;

gcc_assert (!VECTOR_MODE_P (mode));
vmode = aarch64_simd_container_mode (mode, 64);
vmode = aarch64_simd_container_mode (mode, width);
rtx v_op = aarch64_simd_gen_const_vector_dup (vmode, INTVAL (immediate));
return aarch64_output_simd_mov_immediate (v_op, vmode, 64);
return aarch64_output_simd_mov_immediate (v_op, vmode, width);
}

/* Split operands into moves from op[1] + op[2] into op[0]. */
Expand Down
16 changes: 9 additions & 7 deletions gcc/config/aarch64/aarch64.md
Original file line number Diff line number Diff line change
Expand Up @@ -920,8 +920,8 @@
)

(define_insn_and_split "*movsi_aarch64"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w,r,*w")
(match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w"))]
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w, r,*w,w")
(match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Ds"))]
"(register_operand (operands[0], SImode)
|| aarch64_reg_or_zero (operands[1], SImode))"
"@
Expand All @@ -938,17 +938,19 @@
adrp\\t%x0, %A1
fmov\\t%s0, %w1
fmov\\t%w0, %s1
fmov\\t%s0, %s1"
"CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
fmov\\t%s0, %s1
* return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
"CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
&& REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
[(const_int 0)]
"{
aarch64_expand_mov_immediate (operands[0], operands[1]);
DONE;
}"
[(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
adr,adr,f_mcr,f_mrc,fmov")
(set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
adr,adr,f_mcr,f_mrc,fmov,neon_move")
(set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
(set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
)

(define_insn_and_split "*movdi_aarch64"
Expand All @@ -971,7 +973,7 @@
fmov\\t%d0, %x1
fmov\\t%x0, %d1
fmov\\t%d0, %d1
movi\\t%d0, %1"
* return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);"
"(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
&& REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
[(const_int 0)]
Expand Down
18 changes: 16 additions & 2 deletions gcc/config/aarch64/constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@
(and (match_code "const_double")
(match_test "aarch64_float_const_representable_p (op)")))

(define_constraint "Uvi"
"A floating point constant which can be used with a\
MOVI immediate operation."
(and (match_code "const_double")
(match_test "aarch64_can_const_movi_rtx_p (op, GET_MODE (op))")))

(define_constraint "Dn"
"@internal
A constraint that matches vector of immediates."
Expand Down Expand Up @@ -220,9 +226,17 @@

(define_constraint "Dd"
"@internal
A constraint that matches an immediate operand valid for AdvSIMD scalar."
A constraint that matches an integer immediate operand valid\
for AdvSIMD scalar operations in DImode."
(and (match_code "const_int")
(match_test "aarch64_can_const_movi_rtx_p (op, DImode)")))

(define_constraint "Ds"
"@internal
A constraint that matches an integer immediate operand valid\
for AdvSIMD scalar operations in SImode."
(and (match_code "const_int")
(match_test "aarch64_simd_imm_scalar_p (op, GET_MODE (op))")))
(match_test "aarch64_can_const_movi_rtx_p (op, SImode)")))

(define_address_constraint "Dp"
"@internal
Expand Down

0 comments on commit a217096

Please sign in to comment.