&thunderx2t99_prefetch_tune
};
-static const struct tune_params ares_tunings =
+static const struct tune_params neoversen1_tunings =
{
&cortexa57_extra_costs,
&generic_addrcost_table,
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req,
affects_type_identity, handler, exclude } */
- { "aarch64_vector_pcs", 0, 0, false, true, true, false, NULL, NULL },
+ { "aarch64_vector_pcs", 0, 0, false, true, true, true, NULL, NULL },
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
void
aarch64_emit_sve_pred_move (rtx dest, rtx pred, rtx src)
{
- emit_insn (gen_rtx_SET (dest, gen_rtx_UNSPEC (GET_MODE (dest),
- gen_rtvec (2, pred, src),
- UNSPEC_MERGE_PTRUE)));
+ expand_operand ops[3];
+ machine_mode mode = GET_MODE (dest);
+ create_output_operand (&ops[0], dest, mode);
+ create_input_operand (&ops[1], pred, GET_MODE(pred));
+ create_input_operand (&ops[2], src, mode);
+ expand_insn (code_for_aarch64_pred_mov (mode), 3, ops);
}
/* Expand a pre-RA SVE data move from SRC to DEST in which at least one
/* Given MODE and TYPE of a function argument, return the alignment in
bits. The idea is to suppress any stronger alignment requested by
- the user and opt for the natural alignment (specified in AAPCS64 \S 4.1).
- This is a helper function for local use only. */
+ the user and opt for the natural alignment (specified in AAPCS64 \S
+ 4.1). ABI_BREAK is set to true if the alignment was incorrectly
+ calculated in versions of GCC prior to GCC-9. This is a helper
+ function for local use only. */
static unsigned int
-aarch64_function_arg_alignment (machine_mode mode, const_tree type)
+aarch64_function_arg_alignment (machine_mode mode, const_tree type,
+ bool *abi_break)
{
+ *abi_break = false;
if (!type)
return GET_MODE_ALIGNMENT (mode);
return TYPE_ALIGN (TREE_TYPE (type));
unsigned int alignment = 0;
+ unsigned int bitfield_alignment = 0;
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
- alignment = std::max (alignment, DECL_ALIGN (field));
+ {
+ alignment = std::max (alignment, DECL_ALIGN (field));
+ if (DECL_BIT_FIELD_TYPE (field))
+ bitfield_alignment
+ = std::max (bitfield_alignment,
+ TYPE_ALIGN (DECL_BIT_FIELD_TYPE (field)));
+ }
+
+ if (bitfield_alignment > alignment)
+ {
+ *abi_break = true;
+ return bitfield_alignment;
+ }
return alignment;
}
int ncrn, nvrn, nregs;
bool allocate_ncrn, allocate_nvrn;
HOST_WIDE_INT size;
+ bool abi_break;
/* We need to do this once per argument. */
if (pcum->aapcs_arg_processed)
entirely general registers. */
if (allocate_ncrn && (ncrn + nregs <= NUM_ARG_REGS))
{
-
gcc_assert (nregs == 0 || nregs == 1 || nregs == 2);
/* C.8 if the argument has an alignment of 16 then the NGRN is
- rounded up to the next even number. */
+ rounded up to the next even number. */
if (nregs == 2
&& ncrn % 2
/* The == 16 * BITS_PER_UNIT instead of >= 16 * BITS_PER_UNIT
comparison is there because for > 16 * BITS_PER_UNIT
alignment nregs should be > 2 and therefore it should be
passed by reference rather than value. */
- && aarch64_function_arg_alignment (mode, type) == 16 * BITS_PER_UNIT)
+ && (aarch64_function_arg_alignment (mode, type, &abi_break)
+ == 16 * BITS_PER_UNIT))
{
+ if (abi_break && warn_psabi && currently_expanding_gimple_stmt)
+ inform (input_location, "parameter passing for argument of type "
+ "%qT changed in GCC 9.1", type);
++ncrn;
gcc_assert (ncrn + nregs <= NUM_ARG_REGS);
}
/* NREGS can be 0 when e.g. an empty structure is to be passed.
- A reg is still generated for it, but the caller should be smart
+ A reg is still generated for it, but the caller should be smart
enough not to use it. */
if (nregs == 0 || nregs == 1 || GET_MODE_CLASS (mode) == MODE_INT)
pcum->aapcs_reg = gen_rtx_REG (mode, R0_REGNUM + ncrn);
on_stack:
pcum->aapcs_stack_words = size / UNITS_PER_WORD;
- if (aarch64_function_arg_alignment (mode, type) == 16 * BITS_PER_UNIT)
- pcum->aapcs_stack_size = ROUND_UP (pcum->aapcs_stack_size,
- 16 / UNITS_PER_WORD);
+ if (aarch64_function_arg_alignment (mode, type, &abi_break)
+ == 16 * BITS_PER_UNIT)
+ {
+ int new_size = ROUND_UP (pcum->aapcs_stack_size, 16 / UNITS_PER_WORD);
+ if (pcum->aapcs_stack_size != new_size)
+ {
+ if (abi_break && warn_psabi && currently_expanding_gimple_stmt)
+ inform (input_location, "parameter passing for argument of type "
+ "%qT changed in GCC 9.1", type);
+ pcum->aapcs_stack_size = new_size;
+ }
+ }
return;
}
static unsigned int
aarch64_function_arg_boundary (machine_mode mode, const_tree type)
{
- unsigned int alignment = aarch64_function_arg_alignment (mode, type);
+ bool abi_break;
+ unsigned int alignment = aarch64_function_arg_alignment (mode, type,
+ &abi_break);
+ if (abi_break & warn_psabi)
+ inform (input_location, "parameter passing for argument of type "
+ "%qT changed in GCC 9.1", type);
+
return MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY);
}
rtx this_rtx, temp0, temp1, addr, funexp;
rtx_insn *insn;
+ if (aarch64_bti_enabled ())
+ emit_insn (gen_bti_c());
+
reload_completed = 1;
emit_note (NOTE_INSN_PROLOGUE_END);
/* Equality comparisons of short modes against zero can be performed
using the TST instruction with the appropriate bitmask. */
- if (y == const0_rtx && REG_P (x)
+ if (y == const0_rtx && (REG_P (x) || SUBREG_P (x))
&& (code == EQ || code == NE)
&& (mode_x == HImode || mode_x == QImode))
return CC_NZmode;
& ((HOST_WIDE_INT_1U << INTVAL (shft_amnt)) - 1)) == 0;
}
+/* Return true if the masks and a shift amount from an RTX of the form
+ ((x & MASK1) | ((y << SHIFT_AMNT) & MASK2)) are valid to combine into
+ a BFI instruction of mode MODE. See *arch64_bfi patterns. */
+
+bool
+aarch64_masks_and_shift_for_bfi_p (scalar_int_mode mode,
+ unsigned HOST_WIDE_INT mask1,
+ unsigned HOST_WIDE_INT shft_amnt,
+ unsigned HOST_WIDE_INT mask2)
+{
+ unsigned HOST_WIDE_INT t;
+
+ /* Verify that there is no overlap in what bits are set in the two masks. */
+ if (mask1 != ~mask2)
+ return false;
+
+ /* Verify that mask2 is not all zeros or ones. */
+ if (mask2 == 0 || mask2 == HOST_WIDE_INT_M1U)
+ return false;
+
+ /* The shift amount should always be less than the mode size. */
+ gcc_assert (shft_amnt < GET_MODE_BITSIZE (mode));
+
+ /* Verify that the mask being shifted is contiguous and would be in the
+ least significant bits after shifting by shft_amnt. */
+ t = mask2 + (HOST_WIDE_INT_1U << shft_amnt);
+ return (t == (t & -t));
+}
+
/* Calculate the cost of calculating X, storing it in *COST. Result
is true if the total cost of the operation has now been calculated. */
static bool
return flag->flag;
}
- error ("unknown flag passed in -moverride=%s (%s)", option_name, token);
+ error ("unknown flag passed in %<-moverride=%s%> (%s)", option_name, token);
return 0;
}
if (aarch64_stack_protector_guard == SSP_GLOBAL
&& opts->x_aarch64_stack_protector_guard_offset_str)
{
- error ("incompatible options -mstack-protector-guard=global and"
- "-mstack-protector-guard-offset=%qs",
+ error ("incompatible options %<-mstack-protector-guard=global%> and "
+ "%<-mstack-protector-guard-offset=%s%>",
aarch64_stack_protector_guard_offset_str);
}
&& !(opts->x_aarch64_stack_protector_guard_offset_str
&& opts->x_aarch64_stack_protector_guard_reg_str))
{
- error ("both -mstack-protector-guard-offset and "
- "-mstack-protector-guard-reg must be used "
- "with -mstack-protector-guard=sysreg");
+ error ("both %<-mstack-protector-guard-offset%> and "
+ "%<-mstack-protector-guard-reg%> must be used "
+ "with %<-mstack-protector-guard=sysreg%>");
}
if (opts->x_aarch64_stack_protector_guard_reg_str)
int probe_interval
= PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL);
if (guard_size != probe_interval)
- error ("stack clash guard size '%d' must be equal to probing interval "
- "'%d'", guard_size, probe_interval);
+ error ("stack clash guard size %<%d%> must be equal to probing interval "
+ "%<%d%>", guard_size, probe_interval);
/* Enable sw prefetching at specified optimization level for
CPUS that have prefetch. Lower optimization level threshold by 1
error ("missing cpu name in %<-mcpu=%s%>", str);
break;
case AARCH64_PARSE_INVALID_ARG:
- error ("unknown value %qs for -mcpu", str);
+ error ("unknown value %qs for %<-mcpu%>", str);
aarch64_print_hint_for_core (str);
break;
case AARCH64_PARSE_INVALID_FEATURE:
error ("missing arch name in %<-march=%s%>", str);
break;
case AARCH64_PARSE_INVALID_ARG:
- error ("unknown value %qs for -march", str);
+ error ("unknown value %qs for %<-march%>", str);
aarch64_print_hint_for_arch (str);
break;
case AARCH64_PARSE_INVALID_FEATURE:
error ("missing cpu name in %<-mtune=%s%>", str);
break;
case AARCH64_PARSE_INVALID_ARG:
- error ("unknown value %qs for -mtune", str);
+ error ("unknown value %qs for %<-mtune%>", str);
aarch64_print_hint_for_core (str);
break;
default:
{
if (selected_arch->arch != selected_cpu->arch)
{
- warning (0, "switch -mcpu=%s conflicts with -march=%s switch",
+ warning (0, "switch %<-mcpu=%s%> conflicts with %<-march=%s%> switch",
all_architectures[selected_cpu->arch].name,
selected_arch->name);
}
{
#ifdef TARGET_ENABLE_PAC_RET
aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
- aarch64_ra_sign_key = AARCH64_KEY_A;
#else
aarch64_ra_sign_scope = AARCH64_FUNCTION_NONE;
#endif
/* The compiler may have been configured with 2.23.* binutils, which does
not have support for ILP32. */
if (TARGET_ILP32)
- error ("assembler does not support -mabi=ilp32");
+ error ("assembler does not support %<-mabi=ilp32%>");
#endif
/* Convert -msve-vector-bits to a VG count. */
aarch64_sve_vg = aarch64_convert_sve_vector_bits (aarch64_sve_vector_bits);
if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
- sorry ("return address signing is only supported for -mabi=lp64");
+ sorry ("return address signing is only supported for %<-mabi=lp64%>");
/* Make sure we properly set up the explicit options. */
if ((aarch64_cpu_string && valid_cpu)
#endif
break;
case AARCH64_CMODEL_LARGE:
- sorry ("code model %qs with -f%s", "large",
+ sorry ("code model %qs with %<-f%s%>", "large",
opts->x_flag_pic > 1 ? "PIC" : "pic");
break;
default:
stack = build3 (COMPONENT_REF, TREE_TYPE (f_stack), unshare_expr (valist),
f_stack, NULL_TREE);
size = int_size_in_bytes (type);
- align = aarch64_function_arg_alignment (mode, type) / BITS_PER_UNIT;
+
+ bool abi_break;
+ align
+ = aarch64_function_arg_alignment (mode, type, &abi_break) / BITS_PER_UNIT;
dw_align = false;
adjust = 0;
nregs = rsize / UNITS_PER_WORD;
if (align > 8)
- dw_align = true;
+ {
+ if (abi_break && warn_psabi)
+ inform (input_location, "parameter passing for argument of type "
+ "%qT changed in GCC 9.1", type);
+ dw_align = true;
+ }
if (BLOCK_REG_PADDING (mode, type, 1) == PAD_DOWNWARD
&& size < UNITS_PER_WORD)
be set for non-predicate vectors of booleans. Modes are the most
direct way we have of identifying real SVE predicate types. */
return GET_MODE_CLASS (TYPE_MODE (type)) == MODE_VECTOR_BOOL ? 16 : 128;
- HOST_WIDE_INT align = tree_to_shwi (TYPE_SIZE (type));
- return MIN (align, 128);
+ return wi::umin (wi::to_wide (TYPE_SIZE (type)), 128).to_uhwi ();
}
/* Implement target hook TARGET_VECTORIZE_PREFERRED_VECTOR_ALIGNMENT. */
}
}
+/* Implement TARGET_COMP_TYPE_ATTRIBUTES */
+
+static int
+aarch64_comp_type_attributes (const_tree type1, const_tree type2)
+{
+ if (lookup_attribute ("aarch64_vector_pcs", TYPE_ATTRIBUTES (type1))
+ != lookup_attribute ("aarch64_vector_pcs", TYPE_ATTRIBUTES (type2)))
+ return 0;
+ return 1;
+}
+
+/* Implement TARGET_GET_MULTILIB_ABI_NAME */
+
+static const char *
+aarch64_get_multilib_abi_name (void)
+{
+ if (TARGET_BIG_END)
+ return TARGET_ILP32 ? "aarch64_be_ilp32" : "aarch64_be";
+ return TARGET_ILP32 ? "aarch64_ilp32" : "aarch64";
+}
+
/* Implement TARGET_STACK_PROTECT_GUARD. In case of a
global variable based guard use the default else
return a null tree. */
#undef TARGET_SIMD_CLONE_USABLE
#define TARGET_SIMD_CLONE_USABLE aarch64_simd_clone_usable
+#undef TARGET_COMP_TYPE_ATTRIBUTES
+#define TARGET_COMP_TYPE_ATTRIBUTES aarch64_comp_type_attributes
+
+#undef TARGET_GET_MULTILIB_ABI_NAME
+#define TARGET_GET_MULTILIB_ABI_NAME aarch64_get_multilib_abi_name
+
#if CHECKING_P
#undef TARGET_RUN_TARGET_SELFTESTS
#define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests