<s> static sbitmap aarch64_get_separate_components ( void ) { aarch64_layout_frame ( ) ; sbitmap components = sbitmap_alloc ( LAST_SAVED_REGNUM + 1 ) ; bitmap_clear ( components ) ; for ( unsigned regno = 0 ; regno <= LAST_SAVED_REGNUM ; regno ++ ) if ( aarch64_register_saved_on_entry ( regno ) ) { poly_int64 offset = cfun -> machine -> frame . reg_offset [ regno ] ; if ( ! frame_pointer_needed ) offset += cfun -> machine -> frame . frame_size - cfun -> machine -> frame . hard_fp_offset ; if ( offset_12bit_unsigned_scaled_p ( DImode , offset ) ) bitmap_set_bit ( components , regno ) ; } if ( frame_pointer_needed ) bitmap_clear_bit ( components , HARD_FRAME_POINTER_REGNUM ) ; unsigned reg1 = cfun -> machine -> frame . wb_candidate1 ; unsigned reg2 = cfun -> machine -> frame . wb_candidate2 ; if ( reg2 != INVALID_REGNUM ) bitmap_clear_bit ( components , reg2 ) ; if ( reg1 != INVALID_REGNUM ) bitmap_clear_bit ( components , reg1 ) ; bitmap_clear_bit ( components , LR_REGNUM ) ; bitmap_clear_bit ( components , SP_REGNUM ) ; return components ; } </s>


"missing name in %<target(\"arch=\")%> pragma or attribute"

"invalid name (\"%s\") in %<target(\"arch=\")%> pragma or attribute"

"invalid value (\"%s\") in %<target()%> pragma or attribute"

Handle the ARCH_STR argument to the arch= target attribute . PRAGMA_OR_ATTR is used in potential error messages .


"missing name in %<target(\"cpu=\")%> pragma or attribute"

"invalid name (\"%s\") in %<target(\"cpu=\")%> pragma or attribute"

Handle the argument CPU_STR to the cpu= target attribute . PRAGMA_OR_ATTR is used in potential error messages .


"missing value in %<target()%> pragma or attribute"

Parse an architecture extensions target attribute string specified in STR . For example `` +fp+nosimd '' . Show any errors if needed . Return TRUE if successful . Update aarch64_isa_flags to reflect the ISA features modified . PRAGMA_OR_ATTR is used in potential error messages .


<s> static bool aarch64_hard_regno_call_part_clobbered ( unsigned int regno , machine_mode mode ) { return FP_REGNUM_P ( regno ) && maybe_gt ( GET_MODE_SIZE ( mode ) , 8 ) ; } </s>

Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED . The callee only saves the lower 64 bits of a 128-bit register . Tell the compiler the callee clobbers the top 64 bits when restoring the bottom 64 bits .


<s> static bool aarch64_hard_regno_mode_ok ( unsigned regno , machine_mode mode ) { if ( GET_MODE_CLASS ( mode ) == MODE_CC ) return regno == CC_REGNUM ; if ( regno == VG_REGNUM ) return mode == DImode ; unsigned int vec_flags = aarch64_classify_vector_mode ( mode ) ; if ( vec_flags & VEC_SVE_PRED ) return PR_REGNUM_P ( regno ) ; if ( PR_REGNUM_P ( regno ) ) return 0 ; if ( regno == SP_REGNUM ) return mode == Pmode || mode == ptr_mode ; if ( regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM ) return mode == Pmode ; if ( GP_REGNUM_P ( regno ) && known_le ( GET_MODE_SIZE ( mode ) , 16 ) ) return true ; if ( FP_REGNUM_P ( regno ) ) { if ( vec_flags & VEC_STRUCT ) return end_hard_regno ( mode , regno ) - 1 <= V31_REGNUM ; else return ! VECTOR_MODE_P ( mode ) || vec_flags != 0 ; } return false ; } </s>


<s> static unsigned int aarch64_hard_regno_nregs ( unsigned regno , machine_mode mode ) { HOST_WIDE_INT lowest_size = constant_lower_bound ( GET_MODE_SIZE ( mode ) ) ; switch ( aarch64_regno_regclass ( regno ) ) { case FP_REGS : case FP_LO_REGS : if ( aarch64_sve_data_mode_p ( mode ) ) return exact_div ( GET_MODE_SIZE ( mode ) , BYTES_PER_SVE_VECTOR ) . to_constant ( ) ; return CEIL ( lowest_size , UNITS_PER_VREG ) ; case PR_REGS : case PR_LO_REGS : case PR_HI_REGS : return 1 ; default : return CEIL ( lowest_size , UNITS_PER_WORD ) ; } gcc_unreachable ( ) ; } </s>


<s> static reg_class_t aarch64_ira_change_pseudo_allocno_class ( int regno , reg_class_t allocno_class , reg_class_t best_class ) { machine_mode mode ; if ( allocno_class != ALL_REGS ) return allocno_class ; if ( best_class != ALL_REGS ) return best_class ; mode = PSEUDO_REGNO_MODE ( regno ) ; return FLOAT_MODE_P ( mode ) || VECTOR_MODE_P ( mode ) ? FP_REGS : GENERAL_REGS ; } </s>

Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS . The register allocator chooses ALL_REGS if FP_REGS and GENERAL_REGS have the same cost even if ALL_REGS has a much larger cost . ALL_REGS is also used if the cost of both FP_REGS and GENERAL_REGS is lower than the memory cost ( in this case the best class is the lowest cost one ) . Using ALL_REGS irrespectively of its cost results in bad allocations with many redundant int < - > FP moves which are expensive on various cores . To avoid this we do n't allow ALL_REGS as the allocno class , but force a decision between FP_REGS and GENERAL_REGS . We use the allocno class if it is n't ALL_REGS . Similarly , use the best class if it is n't ALL_REGS . Otherwise set the allocno class depending on the mode . The result of this is that it is no longer inefficient to have a higher memory move cost than the register move cost .


<s> bool aarch64_mask_and_shift_for_ubfiz_p ( scalar_int_mode mode , rtx mask , rtx shft_amnt ) { return CONST_INT_P ( mask ) && CONST_INT_P ( shft_amnt ) && INTVAL ( shft_amnt ) < GET_MODE_BITSIZE ( mode ) && exact_log2 ( ( INTVAL ( mask ) >> INTVAL ( shft_amnt ) ) + 1 ) >= 0 && ( INTVAL ( mask ) & ( ( 1 << INTVAL ( shft_amnt ) ) - 1 ) ) == 0 ; } </s>

Return true if the mask and a shift amount from an RTX of the form ( x < < SHFT_AMNT ) & MASK are valid to combine into a UBFIZ instruction of mode MODE . See the * andim_ashift < mode > _bfiz pattern .


<s> static bool aarch64_mode_valid_for_sched_fusion_p ( machine_mode mode ) { return mode == SImode || mode == DImode || mode == SFmode || mode == DFmode || ( aarch64_vector_mode_supported_p ( mode ) && known_eq ( GET_MODE_SIZE ( mode ) , 8 ) ) ; } </s>

Return true if MODE is one of the modes for which we support LDP/STP operations .


<s> bool aarch64_operands_ok_for_ldpstp ( rtx * operands , bool load , machine_mode mode ) { HOST_WIDE_INT offval_1 , offval_2 , msize ; enum reg_class rclass_1 , rclass_2 ; rtx mem_1 , mem_2 , reg_1 , reg_2 , base_1 , base_2 , offset_1 , offset_2 ; if ( load ) { mem_1 = operands [ 1 ] ; mem_2 = operands [ 3 ] ; reg_1 = operands [ 0 ] ; reg_2 = operands [ 2 ] ; gcc_assert ( REG_P ( reg_1 ) && REG_P ( reg_2 ) ) ; if ( REGNO ( reg_1 ) == REGNO ( reg_2 ) ) return false ; } else { mem_1 = operands [ 0 ] ; mem_2 = operands [ 2 ] ; reg_1 = operands [ 1 ] ; reg_2 = operands [ 3 ] ; } if ( MEM_VOLATILE_P ( mem_1 ) || MEM_VOLATILE_P ( mem_2 ) ) return false ; if ( mode == SImode && ( aarch64_tune_params . extra_tuning_flags & AARCH64_EXTRA_TUNE_SLOW_UNALIGNED_LDPW ) && ! optimize_size && MEM_ALIGN ( mem_1 ) < 8 * BITS_PER_UNIT ) return false ; extract_base_offset_in_addr ( mem_1 , & base_1 , & offset_1 ) ; if ( base_1 == NULL_RTX || offset_1 == NULL_RTX ) return false ; extract_base_offset_in_addr ( mem_2 , & base_2 , & offset_2 ) ; if ( base_2 == NULL_RTX || offset_2 == NULL_RTX ) return false ; if ( ! rtx_equal_p ( base_1 , base_2 ) ) return false ; offval_1 = INTVAL ( offset_1 ) ; offval_2 = INTVAL ( offset_2 ) ; msize = GET_MODE_SIZE ( mode ) . to_constant ( ) ; if ( offval_1 != ( offval_2 + msize ) && offval_2 != ( offval_1 + msize ) ) return false ; if ( load ) { if ( reg_mentioned_p ( reg_1 , mem_1 ) ) return false ; if ( offval_1 > offval_2 && reg_mentioned_p ( reg_2 , mem_2 ) ) return false ; } if ( REG_P ( reg_1 ) && FP_REGNUM_P ( REGNO ( reg_1 ) ) ) rclass_1 = FP_REGS ; else rclass_1 = GENERAL_REGS ; if ( REG_P ( reg_2 ) && FP_REGNUM_P ( REGNO ( reg_2 ) ) ) rclass_2 = FP_REGS ; else rclass_2 = GENERAL_REGS ; if ( rclass_1 != rclass_2 ) return false ; return true ; } </s>

Given OPERANDS of consecutive load/store , check if we can merge them into ldp/stp . LOAD is true if they are load instructions . MODE is the mode of memory operands .


<s> static void aarch64_output_mi_thunk ( FILE * file , tree thunk ATTRIBUTE_UNUSED , HOST_WIDE_INT delta , HOST_WIDE_INT vcall_offset , tree function ) { int this_regno = R0_REGNUM ; rtx this_rtx , temp0 , temp1 , addr , funexp ; rtx_insn * insn ; reload_completed = 1 ; emit_note ( NOTE_INSN_PROLOGUE_END ) ; this_rtx = gen_rtx_REG ( Pmode , this_regno ) ; temp0 = gen_rtx_REG ( Pmode , IP0_REGNUM ) ; temp1 = gen_rtx_REG ( Pmode , IP1_REGNUM ) ; if ( vcall_offset == 0 ) aarch64_add_offset ( Pmode , this_rtx , this_rtx , delta , temp1 , temp0 , false ) ; else { gcc_assert ( ( vcall_offset & ( POINTER_BYTES - 1 ) ) == 0 ) ; addr = this_rtx ; if ( delta != 0 ) { if ( delta >= - 256 && delta < 256 ) addr = gen_rtx_PRE_MODIFY ( Pmode , this_rtx , plus_constant ( Pmode , this_rtx , delta ) ) ; else aarch64_add_offset ( Pmode , this_rtx , this_rtx , delta , temp1 , temp0 , false ) ; } if ( Pmode == ptr_mode ) aarch64_emit_move ( temp0 , gen_rtx_MEM ( ptr_mode , addr ) ) ; else aarch64_emit_move ( temp0 , gen_rtx_ZERO_EXTEND ( Pmode , gen_rtx_MEM ( ptr_mode , addr ) ) ) ; if ( vcall_offset >= - 256 && vcall_offset < 4096 * POINTER_BYTES ) addr = plus_constant ( Pmode , temp0 , vcall_offset ) ; else { aarch64_internal_mov_immediate ( temp1 , GEN_INT ( vcall_offset ) , true , Pmode ) ; addr = gen_rtx_PLUS ( Pmode , temp0 , temp1 ) ; } if ( Pmode == ptr_mode ) aarch64_emit_move ( temp1 , gen_rtx_MEM ( ptr_mode , addr ) ) ; else aarch64_emit_move ( temp1 , gen_rtx_SIGN_EXTEND ( Pmode , gen_rtx_MEM ( ptr_mode , addr ) ) ) ; emit_insn ( gen_add2_insn ( this_rtx , temp1 ) ) ; } if ( ! TREE_USED ( function ) ) { assemble_external ( function ) ; TREE_USED ( function ) = 1 ; } funexp = XEXP ( DECL_RTL ( function ) , 0 ) ; funexp = gen_rtx_MEM ( FUNCTION_MODE , funexp ) ; insn = emit_call_insn ( gen_sibcall ( funexp , const0_rtx , NULL_RTX ) ) ; SIBLING_CALL_P ( insn ) = 1 ; insn = get_insns ( ) ; shorten_branches ( insn ) ; final_start_function ( insn , file , 1 ) ; final ( insn , file , 1 ) ; final_end_function ( ) ; reload_completed = 0 ; } </s>

Output code to add DELTA to the first argument , and then jump to FUNCTION . Used for C++ multiple inheritance .


<s>
char
*
aarch64_output_ptrue
(
machine_mode
mode
,
char
suffix
)
{
unsigned
int
nunits
;
static
char
buf
[
sizeof
(
"ptrue\t%0.N, vlNNNNN"
)
]
;
if
(
GET_MODE_NUNITS
(
mode
)
.
is_constant
(
&
nunits
)
)
snprintf
(
buf
,
sizeof
(
buf
)
,
"ptrue\t%%0.%c, vl%d"
,
suffix
,
nunits
)
;
else
snprintf
(
buf
,
sizeof
(
buf
)
,
"ptrue\t%%0.%c, all"
,
suffix
)
;
return
buf
;
}
</s>

Return the asm format for a PTRUE instruction whose destination has mode MODE . SUFFIX is the element size suffix .

aarch64
"ptrue\t%0.N, vlNNNNN"
"ptrue\t%%0.%c, vl%d"
"ptrue\t%%0.%c, all"


<s>
char
*
aarch64_output_simd_mov_immediate
(
rtx
const_vector
,
unsigned
width
,
enum
simd_immediate_check
which
)
{
bool
is_valid
;
static
char
templ
[
40
]
;
const
char
*
mnemonic
;
const
char
*
shift_op
;
unsigned
int
lane_count
=
0
;
char
element_char
;
struct
simd_immediate_info
info
;
is_valid
=
aarch64_simd_valid_immediate
(
const_vector
,
&
info
,
which
)
;
gcc_assert
(
is_valid
)
;
element_char
=
sizetochar
(
GET_MODE_BITSIZE
(
info
.
elt_mode
)
)
;
lane_count
=
width
/
GET_MODE_BITSIZE
(
info
.
elt_mode
)
;
if
(
GET_MODE_CLASS
(
info
.
elt_mode
)
==
MODE_FLOAT
)
{
gcc_assert
(
info
.
shift
==
0
&&
info
.
insn
==
simd_immediate_info
::
MOV
)
;
if
(
aarch64_float_const_zero_rtx_p
(
info
.
value
)
)
info
.
value
=
GEN_INT
(
0
)
;
else
{
const
unsigned
int
buf_size
=
20
;
char
float_buf
[
buf_size
]
=
{
'\0'
}
;
real_to_decimal_for_mode
(
float_buf
,
CONST_DOUBLE_REAL_VALUE
(
info
.
value
)
,
buf_size
,
buf_size
,
1
,
info
.
elt_mode
)
;
if
(
lane_count
==
1
)
snprintf
(
templ
,
sizeof
(
templ
)
,
"fmov\t%%d0, %s"
,
float_buf
)
;
else
snprintf
(
templ
,
sizeof
(
templ
)
,
"fmov\t%%0.%d%c, %s"
,
lane_count
,
element_char
,
float_buf
)
;
return
templ
;
}
}
gcc_assert
(
CONST_INT_P
(
info
.
value
)
)
;
if
(
which
==
AARCH64_CHECK_MOV
)
{
mnemonic
=
info
.
insn
==
simd_immediate_info
::
MVN
"mvni"
:
"movi"
;
shift_op
=
info
.
modifier
==
simd_immediate_info
::
MSL
"msl"
:
"lsl"
;
if
(
lane_count
==
1
)
snprintf
(
templ
,
sizeof
(
templ
)
,
"%s\t%%d0, "
HOST_WIDE_INT_PRINT_HEX
,
mnemonic
,
UINTVAL
(
info
.
value
)
)
;
else
if
(
info
.
shift
)
snprintf
(
templ
,
sizeof
(
templ
)
,
"%s\t%%0.%d%c, "
HOST_WIDE_INT_PRINT_HEX
", %s %d"
,
mnemonic
,
lane_count
,
element_char
,
UINTVAL
(
info
.
value
)
,
shift_op
,
info
.
shift
)
;
else
snprintf
(
templ
,
sizeof
(
templ
)
,
"%s\t%%0.%d%c, "
HOST_WIDE_INT_PRINT_HEX
,
mnemonic
,
lane_count
,
element_char
,
UINTVAL
(
info
.
value
)
)
;
}
else
{
mnemonic
=
info
.
insn
==
simd_immediate_info
::
MVN
"bic"
:
"orr"
;
if
(
info
.
shift
)
snprintf
(
templ
,
sizeof
(
templ
)
,
"%s\t%%0.%d%c, #"
HOST_WIDE_INT_PRINT_DEC
", %s #%d"
,
mnemonic
,
lane_count
,
element_char
,
UINTVAL
(
info
.
value
)
,
"lsl"
,
info
.
shift
)
;
else
snprintf
(
templ
,
sizeof
(
templ
)
,
"%s\t%%0.%d%c, #"
HOST_WIDE_INT_PRINT_DEC
,
mnemonic
,
lane_count
,
element_char
,
UINTVAL
(
info
.
value
)
)
;
}
return
templ
;
}
</s>

Returns the string with the instruction for AdvSIMD MOVI , MVNI , ORR or BIC immediate with a CONST_VECTOR of MODE and WIDTH . WHICH selects whether to output MOVI/MVNI , ORR or BIC immediate .


<s>
char
*
aarch64_output_sve_addvl_addpl
(
rtx
dest
,
rtx
base
,
rtx
offset
)
{
static
char
buffer
[
sizeof
(
"addpl\t%x0, %x1, #-"
)
+
3
*
sizeof
(
int
)
]
;
poly_int64
offset_value
=
rtx_to_poly_int64
(
offset
)
;
gcc_assert
(
aarch64_sve_addvl_addpl_immediate_p
(
offset_value
)
)
;
if
(
rtx_equal_p
(
dest
,
base
)
&&
GP_REGNUM_P
(
REGNO
(
dest
)
)
)
{
if
(
aarch64_sve_cnt_immediate_p
(
offset_value
)
)
return
aarch64_output_sve_cnt_immediate
(
"inc"
,
"%x0"
,
offset_value
.
coeffs
[
1
]
,
0
)
;
if
(
aarch64_sve_cnt_immediate_p
(
offset_value
)
)
return
aarch64_output_sve_cnt_immediate
(
"dec"
,
"%x0"
,
offset_value
.
coeffs
[
1
]
,
0
)
;
}
int
factor
=
offset_value
.
coeffs
[
1
]
;
if
(
(
factor
&
15
)
==
0
)
snprintf
(
buffer
,
sizeof
(
buffer
)
,
"addvl\t%%x0, %%x1, #%d"
,
factor
/
16
)
;
else
snprintf
(
buffer
,
sizeof
(
buffer
)
,
"addpl\t%%x0, %%x1, #%d"
,
factor
/
2
)
;
return
buffer
;
}
</s>

Return the asm string for adding ADDVL or ADDPL immediate X to operand 1 and storing the result in operand 0 .


<s> char * aarch64_output_sve_cnt_immediate ( const char * prefix , const char * operands , rtx x ) { poly_int64 value = rtx_to_poly_int64 ( x ) ; gcc_assert ( aarch64_sve_cnt_immediate_p ( value ) ) ; return aarch64_output_sve_cnt_immediate ( prefix , operands , value . coeffs [ 1 ] , 0 ) ; } </s>

Return the asm string for an instruction with a CNT-like vector size operand ( a vector pattern followed by a multiplier in the range [ 1 , 16 ] ) . PREFIX is the mnemonic without the size suffix and OPERANDS is the first part of the operands template ( the part that comes before the vector size itself ) . X is the value of the vector size operand , as a polynomial integer rtx .


<s> char * aarch64_output_sve_inc_dec_immediate ( const char * operands , rtx x ) { int factor ; unsigned int nelts_per_vq ; if ( ! aarch64_sve_inc_dec_immediate_p ( x , & factor , & nelts_per_vq ) ) gcc_unreachable ( ) ; if ( factor < 0 ) return aarch64_output_sve_cnt_immediate ( "dec" , operands , - factor , nelts_per_vq ) ; else return aarch64_output_sve_cnt_immediate ( "inc" , operands , factor , nelts_per_vq ) ; } </s>

Return the asm template for an SVE vector INC or DEC instruction . OPERANDS gives the operands before the vector count and X is the value of the vector count operand itself .


<s>
char
*
aarch64_output_sve_mov_immediate
(
rtx
const_vector
)
{
static
char
templ
[
40
]
;
struct
simd_immediate_info
info
;
char
element_char
;
bool
is_valid
=
aarch64_simd_valid_immediate
(
const_vector
,
&
info
)
;
gcc_assert
(
is_valid
)
;
element_char
=
sizetochar
(
GET_MODE_BITSIZE
(
info
.
elt_mode
)
)
;
if
(
info
.
step
)
{
snprintf
(
templ
,
sizeof
(
templ
)
,
"index\t%%0.%c, #"
HOST_WIDE_INT_PRINT_DEC
", #"
HOST_WIDE_INT_PRINT_DEC
,
element_char
,
INTVAL
(
info
.
value
)
,
INTVAL
(
info
.
step
)
)
;
return
templ
;
}
if
(
GET_MODE_CLASS
(
info
.
elt_mode
)
==
MODE_FLOAT
)
{
if
(
aarch64_float_const_zero_rtx_p
(
info
.
value
)
)
info
.
value
=
GEN_INT
(
0
)
;
else
{
const
int
buf_size
=
20
;
char
float_buf
[
buf_size
]
=
{
}
;
real_to_decimal_for_mode
(
float_buf
,
CONST_DOUBLE_REAL_VALUE
(
info
.
value
)
,
buf_size
,
buf_size
,
1
,
info
.
elt_mode
)
;
snprintf
(
templ
,
sizeof
(
templ
)
,
"fmov\t%%0.%c, #%s"
,
element_char
,
float_buf
)
;
return
templ
;
}
}
snprintf
(
templ
,
sizeof
(
templ
)
,
"mov\t%%0.%c, #"
HOST_WIDE_INT_PRINT_DEC
,
element_char
,
INTVAL
(
info
.
value
)
)
;
return
templ
;
}
</s>

Return the output string to use for moving immediate CONST_VECTOR into an SVE register .


"switch -mcpu=%s conflicts with -march=%s switch"

"assembler does not support -mabi=ilp32"

"return address signing is only supported for -mabi=lp64"


<s> void aarch64_override_options_internal ( struct gcc_options * opts ) { aarch64_tune_flags = selected_tune -> flags ; aarch64_tune = selected_tune -> sched_core ; aarch64_tune_params = * ( selected_tune -> tune ) ; aarch64_architecture_version = selected_arch -> architecture_version ; if ( opts -> x_aarch64_override_tune_string ) aarch64_parse_override_string ( opts -> x_aarch64_override_tune_string , & aarch64_tune_params ) ; if ( opts -> x_flag_strict_volatile_bitfields < 0 && abi_version_at_least ( 2 ) ) opts -> x_flag_strict_volatile_bitfields = 1 ; initialize_aarch64_code_model ( opts ) ; initialize_aarch64_tls_size ( opts ) ; int queue_depth = 0 ; switch ( aarch64_tune_params . autoprefetcher_model ) { case tune_params :: AUTOPREFETCHER_OFF : queue_depth = - 1 ; break ; case tune_params :: AUTOPREFETCHER_WEAK : queue_depth = 0 ; break ; case tune_params :: AUTOPREFETCHER_STRONG : queue_depth = max_insn_queue_index + 1 ; break ; default : gcc_unreachable ( ) ; } maybe_set_param_value ( PARAM_SCHED_AUTOPREF_QUEUE_DEPTH , queue_depth , opts -> x_param_values , global_options_set . x_param_values ) ; if ( aarch64_tune_params . prefetch -> num_slots > 0 ) maybe_set_param_value ( PARAM_SIMULTANEOUS_PREFETCHES , aarch64_tune_params . prefetch -> num_slots , opts -> x_param_values , global_options_set . x_param_values ) ; if ( aarch64_tune_params . prefetch -> l1_cache_size >= 0 ) maybe_set_param_value ( PARAM_L1_CACHE_SIZE , aarch64_tune_params . prefetch -> l1_cache_size , opts -> x_param_values , global_options_set . x_param_values ) ; if ( aarch64_tune_params . prefetch -> l1_cache_line_size >= 0 ) maybe_set_param_value ( PARAM_L1_CACHE_LINE_SIZE , aarch64_tune_params . prefetch -> l1_cache_line_size , opts -> x_param_values , global_options_set . x_param_values ) ; if ( aarch64_tune_params . prefetch -> l2_cache_size >= 0 ) maybe_set_param_value ( PARAM_L2_CACHE_SIZE , aarch64_tune_params . prefetch -> l2_cache_size , opts -> x_param_values , global_options_set . x_param_values ) ; maybe_set_param_value ( PARAM_SCHED_PRESSURE_ALGORITHM , SCHED_PRESSURE_MODEL , opts -> x_param_values , global_options_set . x_param_values ) ; if ( opts -> x_flag_prefetch_loop_arrays < 0 && ! opts -> x_optimize_size && aarch64_tune_params . prefetch -> default_opt_level >= 0 && opts -> x_optimize >= aarch64_tune_params . prefetch -> default_opt_level ) opts -> x_flag_prefetch_loop_arrays = 1 ; aarch64_override_options_after_change_1 ( opts ) ; } </s>

'Unpack ' up the internal tuning structs and update the options in OPTS . The caller must have set up selected_tune and selected_arch as all the other target-specific codegen decisions are derived from them .


<s> bool aarch64_pad_reg_upward ( machine_mode mode , const_tree type , bool first ATTRIBUTE_UNUSED ) { if ( BYTES_BIG_ENDIAN && aarch64_composite_type_p ( type , mode ) ) { HOST_WIDE_INT size ; if ( type ) size = int_size_in_bytes ( type ) ; else size = GET_MODE_SIZE ( mode ) . to_constant ( ) ; if ( size < 2 * UNITS_PER_WORD ) return true ; } return ! BYTES_BIG_ENDIAN ; } </s>

Similarly , for use by BLOCK_REG_PADDING ( MODE , TYPE , FIRST ) . It specifies padding for the last ( may also be the only ) element of a block move between registers and memory . If assuming the block is in the memory , padding upward means that the last element is padded after its highest significant byte , while in downward padding , the last element is padded at the its least significant byte side . Small aggregates and small complex types are always padded upwards . We do n't need to worry about homogeneous floating-point or short-vector aggregates ; their move is not affected by the padding direction determined here . Regardless of endianness , each element of such an aggregate is put in the least significant bits of a fp/simd register . Return ! BYTES_BIG_ENDIAN if the least significant byte of the register has useful data , and return the opposite if the most significant byte does .


<s> static bool aarch64_pass_by_reference ( cumulative_args_t pcum ATTRIBUTE_UNUSED , machine_mode mode , const_tree type , bool named ATTRIBUTE_UNUSED ) { HOST_WIDE_INT size ; machine_mode dummymode ; int nregs ; if ( mode == BLKmode && type ) size = int_size_in_bytes ( type ) ; else size = GET_MODE_SIZE ( mode ) . to_constant ( ) ; if ( type && AGGREGATE_TYPE_P ( type ) ) { size = int_size_in_bytes ( type ) ; } if ( size < 0 ) return true ; if ( aarch64_vfp_is_call_or_return_candidate ( mode , type , & dummymode , & nregs , NULL ) ) return false ; return size > 2 * UNITS_PER_WORD ; } </s>


<s> static void aarch64_pop_regs ( unsigned regno1 , unsigned regno2 , HOST_WIDE_INT adjustment , rtx * cfi_ops ) { machine_mode mode = ( regno1 <= R30_REGNUM ) ? E_DImode : E_DFmode ; rtx reg1 = gen_rtx_REG ( mode , regno1 ) ; * cfi_ops = alloc_reg_note ( REG_CFA_RESTORE , reg1 , * cfi_ops ) ; if ( regno2 == INVALID_REGNUM ) { rtx mem = plus_constant ( Pmode , stack_pointer_rtx , adjustment ) ; mem = gen_rtx_POST_MODIFY ( Pmode , stack_pointer_rtx , mem ) ; emit_move_insn ( reg1 , gen_frame_mem ( mode , mem ) ) ; } else { rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; * cfi_ops = alloc_reg_note ( REG_CFA_RESTORE , reg2 , * cfi_ops ) ; emit_insn ( aarch64_gen_loadwb_pair ( mode , stack_pointer_rtx , reg1 , reg2 , adjustment ) ) ; } } </s>

Pop the two registers numbered REGNO1 , REGNO2 from the stack , adjusting it afterwards by ADJUSTMENT and writing the appropriate REG_CFA_RESTORE notes into CFI_OPS .


<s> static bool aarch64_print_ldpstp_address ( FILE * f , machine_mode mode , rtx x ) { return aarch64_print_address_internal ( f , mode , x , ADDR_QUERY_LDP_STP ) ; } </s>

Print address ' x ' of a LDP/STP with mode 'mode ' .


<s> static bool aarch64_print_vector_float_operand ( FILE * f , rtx x , bool negate ) { rtx elt ; if ( ! const_vec_duplicate_p ( x , & elt ) ) return false ; REAL_VALUE_TYPE r = * CONST_DOUBLE_REAL_VALUE ( elt ) ; if ( negate ) r = real_value_negate ( & r ) ; if ( real_equal ( & r , & dconst0 ) ) asm_fprintf ( f , "0.0" ) ; else if ( real_equal ( & r , & dconst1 ) ) asm_fprintf ( f , "1.0" ) ; else if ( real_equal ( & r , & dconsthalf ) ) asm_fprintf ( f , "0.5" ) ; else return false ; return true ; } </s>

Print floating-point vector immediate operand X to F , negating it first if NEGATE is true . Return true on success , false if it is n't a constant we can handle .


<s> static void aarch64_process_components ( sbitmap components , bool prologue_p ) { rtx ptr_reg = gen_rtx_REG ( Pmode , frame_pointer_needed ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM ) ; unsigned last_regno = SBITMAP_SIZE ( components ) ; unsigned regno = aarch64_get_next_set_bit ( components , R0_REGNUM ) ; rtx_insn * insn = NULL ; while ( regno != last_regno ) { machine_mode mode = GP_REGNUM_P ( regno ) ? E_DImode : E_DFmode ; rtx reg = gen_rtx_REG ( mode , regno ) ; poly_int64 offset = cfun -> machine -> frame . reg_offset [ regno ] ; if ( ! frame_pointer_needed ) offset += cfun -> machine -> frame . frame_size - cfun -> machine -> frame . hard_fp_offset ; rtx addr = plus_constant ( Pmode , ptr_reg , offset ) ; rtx mem = gen_frame_mem ( mode , addr ) ; rtx set = prologue_p ? gen_rtx_SET ( mem , reg ) : gen_rtx_SET ( reg , mem ) ; unsigned regno2 = aarch64_get_next_set_bit ( components , regno + 1 ) ; if ( regno2 == last_regno ) { insn = emit_insn ( set ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; if ( prologue_p ) add_reg_note ( insn , REG_CFA_OFFSET , copy_rtx ( set ) ) ; else add_reg_note ( insn , REG_CFA_RESTORE , reg ) ; break ; } poly_int64 offset2 = cfun -> machine -> frame . reg_offset [ regno2 ] ; if ( ! satisfies_constraint_Ump ( mem ) || GP_REGNUM_P ( regno ) != GP_REGNUM_P ( regno2 ) || maybe_ne ( ( offset2 - cfun -> machine -> frame . reg_offset [ regno ] ) , GET_MODE_SIZE ( mode ) ) ) { insn = emit_insn ( set ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; if ( prologue_p ) add_reg_note ( insn , REG_CFA_OFFSET , copy_rtx ( set ) ) ; else add_reg_note ( insn , REG_CFA_RESTORE , reg ) ; regno = regno2 ; continue ; } rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; if ( ! frame_pointer_needed ) offset2 += cfun -> machine -> frame . frame_size - cfun -> machine -> frame . hard_fp_offset ; rtx addr2 = plus_constant ( Pmode , ptr_reg , offset2 ) ; rtx mem2 = gen_frame_mem ( mode , addr2 ) ; rtx set2 = prologue_p ? gen_rtx_SET ( mem2 , reg2 ) : gen_rtx_SET ( reg2 , mem2 ) ; if ( prologue_p ) insn = emit_insn ( aarch64_gen_store_pair ( mode , mem , reg , mem2 , reg2 ) ) ; else insn = emit_insn ( aarch64_gen_load_pair ( mode , reg , mem , reg2 , mem2 ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; if ( prologue_p ) { add_reg_note ( insn , REG_CFA_OFFSET , set ) ; add_reg_note ( insn , REG_CFA_OFFSET , set2 ) ; } else { add_reg_note ( insn , REG_CFA_RESTORE , reg ) ; add_reg_note ( insn , REG_CFA_RESTORE , reg2 ) ; } regno = aarch64_get_next_set_bit ( components , regno2 + 1 ) ; } } </s>

Do the work for aarch64_emit_prologue_components and aarch64_emit_epilogue_components . COMPONENTS is the bitmap of registers to save/restore , PROLOGUE_P indicates whether to emit the prologue sequence for these components or the epilogue sequence . That is , it determines whether we should emit stores or loads and what kind of CFA notes to attach to the insns . Otherwise the logic for the two sequences is very similar .


"malformed %<target()%> pragma or attribute"

"pragma or attribute %<target(\"%s\")%> does not accept an argument"

"pragma or attribute %<target(\"%s\")%> does not allow a negated form"

"pragma or attribute %<target(\"%s=%s\")%> is not valid"

Parse ARG_STR which contains the definition of one target attribute . Show appropriate errors if any or return true if the attribute is valid . PRAGMA_OR_ATTR holds the string to use in error messages about whether we 're processing a target attribute or pragma .


"attribute %<target%> argument not a string"

"pragma or attribute %<target(\"%s\")%> is not valid"

"malformed %<target(\"%s\")%> pragma or attribute"

Parse the tree in ARGS that contains the target attribute information and update the global target options space . PRAGMA_OR_ATTR is a string to be used in error messages , specifying whether this is processing a target attribute or a target pragma .


<s> static void aarch64_push_regs ( unsigned regno1 , unsigned regno2 , HOST_WIDE_INT adjustment ) { rtx_insn * insn ; machine_mode mode = ( regno1 <= R30_REGNUM ) ? E_DImode : E_DFmode ; if ( regno2 == INVALID_REGNUM ) return aarch64_pushwb_single_reg ( mode , regno1 , adjustment ) ; rtx reg1 = gen_rtx_REG ( mode , regno1 ) ; rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; insn = emit_insn ( aarch64_gen_storewb_pair ( mode , stack_pointer_rtx , reg1 , reg2 , adjustment ) ) ; RTX_FRAME_RELATED_P ( XVECEXP ( PATTERN ( insn ) , 0 , 2 ) ) = 1 ; RTX_FRAME_RELATED_P ( XVECEXP ( PATTERN ( insn ) , 0 , 1 ) ) = 1 ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } </s>

Push registers numbered REGNO1 and REGNO2 to the stack , adjusting the stack pointer by ADJUSTMENT .


<s> enum reg_class aarch64_regno_regclass ( unsigned regno ) { if ( GP_REGNUM_P ( regno ) ) return GENERAL_REGS ; if ( regno == SP_REGNUM ) return STACK_REG ; if ( regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM ) return POINTER_REGS ; if ( FP_REGNUM_P ( regno ) ) return FP_LO_REGNUM_P ( regno ) ? FP_LO_REGS : FP_REGS ; if ( PR_REGNUM_P ( regno ) ) return PR_LO_REGNUM_P ( regno ) ? PR_LO_REGS : PR_HI_REGS ; return NO_REGS ; } </s>


<s> static rtx aarch64_replace_reg_mode ( rtx x , machine_mode mode ) { if ( GET_MODE ( x ) == mode ) return x ; x = shallow_copy_rtx ( x ) ; set_mode_and_regno ( x , mode , REGNO ( x ) ) ; return x ; } </s>

Return a copy of X with mode MODE , without changing its other attributes . Unlike gen_lowpart , this does n't care whether the mode change is valid .


<s> static void aarch64_restore_callee_saves ( machine_mode mode , poly_int64 start_offset , unsigned start , unsigned limit , bool skip_wb , rtx * cfi_ops ) { rtx base_rtx = stack_pointer_rtx ; unsigned regno ; unsigned regno2 ; poly_int64 offset ; for ( regno = aarch64_next_callee_save ( start , limit ) ; regno <= limit ; regno = aarch64_next_callee_save ( regno + 1 , limit ) ) { if ( cfun -> machine -> reg_is_wrapped_separately [ regno ] ) continue ; rtx reg , mem ; if ( skip_wb && ( regno == cfun -> machine -> frame . wb_candidate1 || regno == cfun -> machine -> frame . wb_candidate2 ) ) continue ; reg = gen_rtx_REG ( mode , regno ) ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno ] ; mem = gen_frame_mem ( mode , plus_constant ( Pmode , base_rtx , offset ) ) ; regno2 = aarch64_next_callee_save ( regno + 1 , limit ) ; if ( regno2 <= limit && ! cfun -> machine -> reg_is_wrapped_separately [ regno2 ] && ( ( cfun -> machine -> frame . reg_offset [ regno ] + UNITS_PER_WORD ) == cfun -> machine -> frame . reg_offset [ regno2 ] ) ) { rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; rtx mem2 ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno2 ] ; mem2 = gen_frame_mem ( mode , plus_constant ( Pmode , base_rtx , offset ) ) ; emit_insn ( aarch64_gen_load_pair ( mode , reg , mem , reg2 , mem2 ) ) ; * cfi_ops = alloc_reg_note ( REG_CFA_RESTORE , reg2 , * cfi_ops ) ; regno = regno2 ; } else emit_move_insn ( reg , mem ) ; * cfi_ops = alloc_reg_note ( REG_CFA_RESTORE , reg , * cfi_ops ) ; } } </s>

Emit code to restore the callee registers of mode MODE from register number START up to and including LIMIT . Restore from the stack offset START_OFFSET , skipping any write-back candidates if SKIP_WB is true . Write the appropriate REG_CFA_RESTORE notes into CFI_OPS .


<s> static void aarch64_save_callee_saves ( machine_mode mode , poly_int64 start_offset , unsigned start , unsigned limit , bool skip_wb ) { rtx_insn * insn ; unsigned regno ; unsigned regno2 ; for ( regno = aarch64_next_callee_save ( start , limit ) ; regno <= limit ; regno = aarch64_next_callee_save ( regno + 1 , limit ) ) { rtx reg , mem ; poly_int64 offset ; if ( skip_wb && ( regno == cfun -> machine -> frame . wb_candidate1 || regno == cfun -> machine -> frame . wb_candidate2 ) ) continue ; if ( cfun -> machine -> reg_is_wrapped_separately [ regno ] ) continue ; reg = gen_rtx_REG ( mode , regno ) ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno ] ; mem = gen_frame_mem ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; regno2 = aarch64_next_callee_save ( regno + 1 , limit ) ; if ( regno2 <= limit && ! cfun -> machine -> reg_is_wrapped_separately [ regno2 ] && ( ( cfun -> machine -> frame . reg_offset [ regno ] + UNITS_PER_WORD ) == cfun -> machine -> frame . reg_offset [ regno2 ] ) ) { rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; rtx mem2 ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno2 ] ; mem2 = gen_frame_mem ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; insn = emit_insn ( aarch64_gen_store_pair ( mode , mem , reg , mem2 , reg2 ) ) ; RTX_FRAME_RELATED_P ( XVECEXP ( PATTERN ( insn ) , 0 , 1 ) ) = 1 ; regno = regno2 ; } else insn = emit_move_insn ( mem , reg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } } </s>

Emit code to save the callee-saved registers from register number START to LIMIT to the stack at the location starting at offset START_OFFSET , skipping any write-back candidates if SKIP_WB is true .


<s> static void aarch64_select_early_remat_modes ( sbitmap modes ) { for ( int i = 0 ; i < NUM_MACHINE_MODES ; ++ i ) { machine_mode mode = ( machine_mode ) i ; unsigned int vec_flags = aarch64_classify_vector_mode ( mode ) ; if ( vec_flags & VEC_ANY_SVE ) bitmap_set_bit ( modes , i ) ; } } </s>


<s> static bool aarch64_short_vector_p ( const_tree type , machine_mode mode ) { poly_int64 size = - 1 ; if ( type && TREE_CODE ( type ) == VECTOR_TYPE ) size = int_size_in_bytes ( type ) ; else if ( GET_MODE_CLASS ( mode ) == MODE_VECTOR_INT || GET_MODE_CLASS ( mode ) == MODE_VECTOR_FLOAT ) size = GET_MODE_SIZE ( mode ) ; return known_eq ( size , 8 ) || known_eq ( size , 16 ) ; } </s>

Return TRUE if the type , as described by TYPE and MODE , is a short vector type as described in AAPCS64 \S 4.1.2 . See the comment above aarch64_composite_type_p for the notes on MODE .


<s> static machine_mode aarch64_simd_container_mode ( scalar_mode mode , poly_int64 width ) { if ( TARGET_SVE && known_eq ( width , BITS_PER_SVE_VECTOR ) ) switch ( mode ) { case E_DFmode : return VNx2DFmode ; case E_SFmode : return VNx4SFmode ; case E_HFmode : return VNx8HFmode ; case E_DImode : return VNx2DImode ; case E_SImode : return VNx4SImode ; case E_HImode : return VNx8HImode ; case E_QImode : return VNx16QImode ; default : return word_mode ; } gcc_assert ( known_eq ( width , 64 ) || known_eq ( width , 128 ) ) ; if ( TARGET_SIMD ) { if ( known_eq ( width , 128 ) ) switch ( mode ) { case E_DFmode : return V2DFmode ; case E_SFmode : return V4SFmode ; case E_HFmode : return V8HFmode ; case E_SImode : return V4SImode ; case E_HImode : return V8HImode ; case E_QImode : return V16QImode ; case E_DImode : return V2DImode ; default : break ; } else switch ( mode ) { case E_SFmode : return V2SFmode ; case E_HFmode : return V4HFmode ; case E_SImode : return V2SImode ; case E_HImode : return V4HImode ; case E_QImode : return V8QImode ; default : break ; } } return word_mode ; } </s>

Return appropriate SIMD container for MODE within a vector of WIDTH bits .


<s> static HOST_WIDE_INT aarch64_simd_vector_alignment ( const_tree type ) { if ( TREE_CODE ( TYPE_SIZE ( type ) ) != INTEGER_CST ) 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 ) ; } </s>

Implement target hook TARGET_VECTOR_ALIGNMENT . The AAPCS64 sets the maximum alignment of a vector to 128 bits .


<s> void aarch64_split_compare_and_swap ( rtx operands [ ] ) { rtx rval , mem , oldval , newval , scratch ; machine_mode mode ; bool is_weak ; rtx_code_label * label1 , * label2 ; rtx x , cond ; enum memmodel model ; rtx model_rtx ; rval = operands [ 0 ] ; mem = operands [ 1 ] ; oldval = operands [ 2 ] ; newval = operands [ 3 ] ; is_weak = ( operands [ 4 ] != const0_rtx ) ; model_rtx = operands [ 5 ] ; scratch = operands [ 7 ] ; mode = GET_MODE ( mem ) ; model = memmodel_from_int ( INTVAL ( model_rtx ) ) ; bool strong_zero_p = ! is_weak && oldval == const0_rtx ; label1 = NULL ; if ( ! is_weak ) { label1 = gen_label_rtx ( ) ; emit_label ( label1 ) ; } label2 = gen_label_rtx ( ) ; if ( is_mm_sync ( model ) ) aarch64_emit_load_exclusive ( mode , rval , mem , GEN_INT ( MEMMODEL_RELAXED ) ) ; else aarch64_emit_load_exclusive ( mode , rval , mem , model_rtx ) ; if ( strong_zero_p ) { x = gen_rtx_NE ( VOIDmode , rval , const0_rtx ) ; x = gen_rtx_IF_THEN_ELSE ( VOIDmode , x , gen_rtx_LABEL_REF ( Pmode , label2 ) , pc_rtx ) ; aarch64_emit_unlikely_jump ( gen_rtx_SET ( pc_rtx , x ) ) ; } else { cond = aarch64_gen_compare_reg ( NE , rval , oldval ) ; x = gen_rtx_NE ( VOIDmode , cond , const0_rtx ) ; x = gen_rtx_IF_THEN_ELSE ( VOIDmode , x , gen_rtx_LABEL_REF ( Pmode , label2 ) , pc_rtx ) ; aarch64_emit_unlikely_jump ( gen_rtx_SET ( pc_rtx , x ) ) ; } aarch64_emit_store_exclusive ( mode , scratch , mem , newval , model_rtx ) ; if ( ! is_weak ) { x = gen_rtx_NE ( VOIDmode , scratch , const0_rtx ) ; x = gen_rtx_IF_THEN_ELSE ( VOIDmode , x , gen_rtx_LABEL_REF ( Pmode , label1 ) , pc_rtx ) ; aarch64_emit_unlikely_jump ( gen_rtx_SET ( pc_rtx , x ) ) ; } else { cond = gen_rtx_REG ( CCmode , CC_REGNUM ) ; x = gen_rtx_COMPARE ( CCmode , scratch , const0_rtx ) ; emit_insn ( gen_rtx_SET ( cond , x ) ) ; } emit_label ( label2 ) ; if ( strong_zero_p ) { cond = gen_rtx_REG ( CCmode , CC_REGNUM ) ; x = gen_rtx_COMPARE ( CCmode , rval , const0_rtx ) ; emit_insn ( gen_rtx_SET ( cond , x ) ) ; } if ( is_mm_sync ( model ) ) aarch64_emit_post_barrier ( model ) ; } </s>


<s> void aarch64_split_simd_combine ( rtx dst , rtx src1 , rtx src2 ) { machine_mode src_mode = GET_MODE ( src1 ) ; machine_mode dst_mode = GET_MODE ( dst ) ; gcc_assert ( VECTOR_MODE_P ( dst_mode ) ) ; gcc_assert ( register_operand ( dst , dst_mode ) && register_operand ( src1 , src_mode ) && register_operand ( src2 , src_mode ) ) ; rtx ( * gen ) ( rtx , rtx , rtx ) ; switch ( src_mode ) { case E_V8QImode : gen = gen_aarch64_simd_combinev8qi ; break ; case E_V4HImode : gen = gen_aarch64_simd_combinev4hi ; break ; case E_V2SImode : gen = gen_aarch64_simd_combinev2si ; break ; case E_V4HFmode : gen = gen_aarch64_simd_combinev4hf ; break ; case E_V2SFmode : gen = gen_aarch64_simd_combinev2sf ; break ; case E_DImode : gen = gen_aarch64_simd_combinedi ; break ; case E_DFmode : gen = gen_aarch64_simd_combinedf ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen ( dst , src1 , src2 ) ) ; return ; } </s>


<s> void aarch64_split_simd_move ( rtx dst , rtx src ) { machine_mode src_mode = GET_MODE ( src ) ; machine_mode dst_mode = GET_MODE ( dst ) ; gcc_assert ( VECTOR_MODE_P ( dst_mode ) ) ; if ( REG_P ( dst ) && REG_P ( src ) ) { rtx ( * gen ) ( rtx , rtx ) ; gcc_assert ( VECTOR_MODE_P ( src_mode ) ) ; switch ( src_mode ) { case E_V16QImode : gen = gen_aarch64_split_simd_movv16qi ; break ; case E_V8HImode : gen = gen_aarch64_split_simd_movv8hi ; break ; case E_V4SImode : gen = gen_aarch64_split_simd_movv4si ; break ; case E_V2DImode : gen = gen_aarch64_split_simd_movv2di ; break ; case E_V8HFmode : gen = gen_aarch64_split_simd_movv8hf ; break ; case E_V4SFmode : gen = gen_aarch64_split_simd_movv4sf ; break ; case E_V2DFmode : gen = gen_aarch64_split_simd_movv2df ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen ( dst , src ) ) ; return ; } } </s>


<s> void aarch64_split_sve_subreg_move ( rtx dest , rtx ptrue , rtx src ) { machine_mode mode_with_wider_elts = GET_MODE ( dest ) ; machine_mode mode_with_narrower_elts = GET_MODE ( src ) ; if ( GET_MODE_UNIT_SIZE ( mode_with_wider_elts ) < GET_MODE_UNIT_SIZE ( mode_with_narrower_elts ) ) std :: swap ( mode_with_wider_elts , mode_with_narrower_elts ) ; unsigned int wider_bytes = GET_MODE_UNIT_SIZE ( mode_with_wider_elts ) ; unsigned int unspec ; if ( wider_bytes == 8 ) unspec = UNSPEC_REV64 ; else if ( wider_bytes == 4 ) unspec = UNSPEC_REV32 ; else if ( wider_bytes == 2 ) unspec = UNSPEC_REV16 ; else gcc_unreachable ( ) ; machine_mode pred_mode = aarch64_sve_pred_mode ( wider_bytes ) . require ( ) ; ptrue = gen_lowpart ( pred_mode , ptrue ) ; dest = aarch64_replace_reg_mode ( dest , mode_with_narrower_elts ) ; src = aarch64_replace_reg_mode ( src , mode_with_narrower_elts ) ; src = gen_rtx_UNSPEC ( mode_with_narrower_elts , gen_rtvec ( 1 , src ) , unspec ) ; src = gen_rtx_UNSPEC ( mode_with_narrower_elts , gen_rtvec ( 2 , ptrue , src ) , UNSPEC_MERGE_PTRUE ) ; emit_insn ( gen_rtx_SET ( dest , src ) ) ; } </s>

Split a * aarch64_sve_mov < mode > _subreg_be pattern with the given operands .


<s> static inline void aarch64_sub_sp ( rtx temp1 , rtx temp2 , poly_int64 delta , bool frame_related_p ) { aarch64_add_offset ( Pmode , stack_pointer_rtx , stack_pointer_rtx , - delta , temp1 , temp2 , frame_related_p ) ; } </s>

Subtract DELTA from the stack pointer , marking the instructions frame-related if FRAME_RELATED_P . TEMP1 is available as a temporary if nonnull .


<s> bool aarch64_sve_arith_immediate_p ( rtx x , bool negate_p ) { rtx elt ; if ( ! const_vec_duplicate_p ( x , & elt ) || ! CONST_INT_P ( elt ) ) return false ; HOST_WIDE_INT val = INTVAL ( elt ) ; if ( negate_p ) val = - val ; val &= GET_MODE_MASK ( GET_MODE_INNER ( GET_MODE ( x ) ) ) ; if ( val & 0xff ) return IN_RANGE ( val , 0 , 0xff ) ; return IN_RANGE ( val , 0 , 0xff00 ) ; } </s>

Return true if X is a valid immediate for the SVE ADD and SUB instructions . Negate X first if NEGATE_P is true .


<s> bool aarch64_sve_cmp_immediate_p ( rtx x , bool signed_p ) { rtx elt ; return ( const_vec_duplicate_p ( x , & elt ) && CONST_INT_P ( elt ) && ( signed_p ? IN_RANGE ( INTVAL ( elt ) , - 16 , 15 ) : IN_RANGE ( INTVAL ( elt ) , 0 , 127 ) ) ) ; } </s>

Return true if X is a valid immediate operand for an SVE CMP instruction . SIGNED_P says whether the operand is signed rather than unsigned .


<s> static bool aarch64_sve_cmp_operand_p ( rtx_code op_code , rtx x ) { if ( register_operand ( x , VOIDmode ) ) return true ; switch ( op_code ) { case LTU : case LEU : case GEU : case GTU : return aarch64_sve_cmp_immediate_p ( x , false ) ; case LT : case LE : case GE : case GT : case NE : case EQ : return aarch64_sve_cmp_immediate_p ( x , true ) ; default : gcc_unreachable ( ) ; } } </s>

Return true if X is a valid second operand for the SVE instruction that implements integer comparison OP_CODE .


<s> bool aarch64_sve_dup_immediate_p ( rtx x ) { rtx elt ; if ( ! const_vec_duplicate_p ( x , & elt ) || ! CONST_INT_P ( elt ) ) return false ; HOST_WIDE_INT val = INTVAL ( elt ) ; if ( val & 0xff ) return IN_RANGE ( val , - 0x80 , 0x7f ) ; return IN_RANGE ( val , - 0x8000 , 0x7f00 ) ; } </s>

Return true if X is a valid immediate for the SVE DUP and CPY instructions .


<s> bool aarch64_sve_float_mul_immediate_p ( rtx x ) { rtx elt ; return ( const_vec_duplicate_p ( x , & elt ) && GET_CODE ( elt ) == CONST_DOUBLE && real_equal ( CONST_DOUBLE_REAL_VALUE ( elt ) , & dconsthalf ) ) ; } </s>

Return true if X is a valid immediate operand for an SVE FMUL instruction .


<s> bool aarch64_sve_inc_dec_immediate_p ( rtx x ) { return aarch64_sve_inc_dec_immediate_p ( x , NULL , NULL ) ; } </s>

Return true if X is a valid immediate for an SVE vector INC or DEC instruction .


<s> static unsigned int aarch64_unspec_cond_code ( rtx_code code ) { switch ( code ) { case NE : return UNSPEC_COND_NE ; case EQ : return UNSPEC_COND_EQ ; case LT : return UNSPEC_COND_LT ; case GT : return UNSPEC_COND_GT ; case LE : return UNSPEC_COND_LE ; case GE : return UNSPEC_COND_GE ; case LTU : return UNSPEC_COND_LO ; case GTU : return UNSPEC_COND_HI ; case LEU : return UNSPEC_COND_LS ; case GEU : return UNSPEC_COND_HS ; case UNORDERED : return UNSPEC_COND_UO ; default : gcc_unreachable ( ) ; } } </s>

Return the UNSPEC_COND_ * code for comparison CODE .


<s> bool aarch64_use_return_insn_p ( void ) { if ( ! reload_completed ) return false ; if ( crtl -> profile ) return false ; aarch64_layout_frame ( ) ; return known_eq ( cfun -> machine -> frame . frame_size , 0 ) ; } </s>

Return TRUE if we can use a simple_return insn . This function checks whether the callee saved stack is empty , which means no restore actions are need . The pro_and_epilogue will use this to check whether shrink-wrapping opt is feasible .


<s> static bool aarch64_vectorize_vec_perm_const ( machine_mode vmode , rtx target , rtx op0 , rtx op1 , const vec_perm_indices & sel ) { struct expand_vec_perm_d d ; if ( op0 && rtx_equal_p ( op0 , op1 ) ) d . one_vector_p = true ; else if ( sel . all_from_input_p ( 0 ) ) { d . one_vector_p = true ; op1 = op0 ; } else if ( sel . all_from_input_p ( 1 ) ) { d . one_vector_p = true ; op0 = op1 ; } else d . one_vector_p = false ; d . perm . new_vector ( sel . encoding ( ) , d . one_vector_p ? 1 : 2 , sel . nelts_per_input ( ) ) ; d . vmode = vmode ; d . vec_flags = aarch64_classify_vector_mode ( d . vmode ) ; d . target = target ; d . op0 = op0 ; d . op1 = op1 ; d . testing_p = ! target ; if ( ! d . testing_p ) return aarch64_expand_vec_perm_const_1 ( & d ) ; rtx_insn * last = get_last_insn ( ) ; bool ret = aarch64_expand_vec_perm_const_1 ( & d ) ; gcc_assert ( last == get_last_insn ( ) ) ; return ret ; } </s>


<s> static recpe_type get_recpe_type ( machine_mode mode ) { switch ( mode ) { case E_SFmode : return ( gen_aarch64_frecpesf ) ; case E_V2SFmode : return ( gen_aarch64_frecpev2sf ) ; case E_V4SFmode : return ( gen_aarch64_frecpev4sf ) ; case E_DFmode : return ( gen_aarch64_frecpedf ) ; case E_V2DFmode : return ( gen_aarch64_frecpev2df ) ; default : gcc_unreachable ( ) ; } } </s>

Select reciprocal initial estimate insn depending on machine mode .


<s> static recps_type get_recps_type ( machine_mode mode ) { switch ( mode ) { case E_SFmode : return ( gen_aarch64_frecpssf ) ; case E_V2SFmode : return ( gen_aarch64_frecpsv2sf ) ; case E_V4SFmode : return ( gen_aarch64_frecpsv4sf ) ; case E_DFmode : return ( gen_aarch64_frecpsdf ) ; case E_V2DFmode : return ( gen_aarch64_frecpsv2df ) ; default : gcc_unreachable ( ) ; } } </s>

Select reciprocal series step insn depending on machine mode .


<s> static rsqrte_type get_rsqrte_type ( machine_mode mode ) { switch ( mode ) { case E_DFmode : return gen_aarch64_rsqrtedf ; case E_SFmode : return gen_aarch64_rsqrtesf ; case E_V2DFmode : return gen_aarch64_rsqrtev2df ; case E_V2SFmode : return gen_aarch64_rsqrtev2sf ; case E_V4SFmode : return gen_aarch64_rsqrtev4sf ; default : gcc_unreachable ( ) ; } } </s>

Select reciprocal square root initial estimate insn depending on machine mode .


<s> static rsqrts_type get_rsqrts_type ( machine_mode mode ) { switch ( mode ) { case E_DFmode : return gen_aarch64_rsqrtsdf ; case E_SFmode : return gen_aarch64_rsqrtssf ; case E_V2DFmode : return gen_aarch64_rsqrtsv2df ; case E_V2SFmode : return gen_aarch64_rsqrtsv2sf ; case E_V4SFmode : return gen_aarch64_rsqrtsv4sf ; default : gcc_unreachable ( ) ; } } </s>

Select reciprocal square root series step insn depending on machine mode .


<s> static inline bool offset_9bit_signed_unscaled_p ( machine_mode mode ATTRIBUTE_UNUSED , poly_int64 offset ) { HOST_WIDE_INT const_offset ; return ( offset . is_constant ( & const_offset ) && IN_RANGE ( const_offset , - 256 , 255 ) ) ; } </s>

Return true if OFFSET is a signed 9-bit value .


<s> static sbitmap aarch64_components_for_bb ( basic_block bb ) { bitmap in = DF_LIVE_IN ( bb ) ; bitmap gen = & DF_LIVE_BB_INFO ( bb ) -> gen ; bitmap kill = & DF_LIVE_BB_INFO ( bb ) -> kill ; bool simd_function = aarch64_simd_decl_p ( cfun -> decl ) ; sbitmap components = sbitmap_alloc ( LAST_SAVED_REGNUM + 1 ) ; bitmap_clear ( components ) ; for ( unsigned regno = 0 ; regno <= LAST_SAVED_REGNUM ; regno ++ ) if ( ( ! call_used_regs [ regno ] || ( simd_function && FP_SIMD_SAVED_REGNUM_P ( regno ) ) ) && ( bitmap_bit_p ( in , regno ) || bitmap_bit_p ( gen , regno ) || bitmap_bit_p ( kill , regno ) ) ) { unsigned regno2 , offset , offset2 ; bitmap_set_bit ( components , regno ) ; offset = cfun -> machine -> frame . reg_offset [ regno ] ; regno2 = ( ( offset & 8 ) == 0 ) ? regno + 1 : regno - 1 ; if ( regno2 <= LAST_SAVED_REGNUM ) { offset2 = cfun -> machine -> frame . reg_offset [ regno2 ] ; if ( ( offset & ~ 8 ) == ( offset2 & ~ 8 ) ) bitmap_set_bit ( components , regno2 ) ; } } return components ; } </s>


<s> bool aarch64_emit_approx_div ( rtx quo , rtx num , rtx den ) { machine_mode mode = GET_MODE ( quo ) ; if ( GET_MODE_INNER ( mode ) == HFmode ) return false ; bool use_approx_division_p = ( flag_mlow_precision_div || ( aarch64_tune_params . approx_modes -> division & AARCH64_APPROX_MODE ( mode ) ) ) ; if ( ! flag_finite_math_only || flag_trapping_math || ! flag_unsafe_math_optimizations || optimize_function_for_size_p ( cfun ) || ! use_approx_division_p ) return false ; if ( ! TARGET_SIMD && VECTOR_MODE_P ( mode ) ) return false ; rtx xrcp = gen_reg_rtx ( mode ) ; emit_insn ( gen_aarch64_frecpe ( mode , xrcp , den ) ) ; int iterations = ( GET_MODE_INNER ( mode ) == DFmode ) ? 3 : 2 ; if ( flag_mlow_precision_div ) iterations -- ; rtx xtmp = gen_reg_rtx ( mode ) ; while ( iterations -- ) { emit_insn ( gen_aarch64_frecps ( mode , xtmp , xrcp , den ) ) ; if ( iterations > 0 ) emit_set_insn ( xrcp , gen_rtx_MULT ( mode , xrcp , xtmp ) ) ; } if ( num != CONST1_RTX ( mode ) ) { rtx xnum = force_reg ( mode , num ) ; emit_set_insn ( xrcp , gen_rtx_MULT ( mode , xrcp , xnum ) ) ; } emit_set_insn ( quo , gen_rtx_MULT ( mode , xrcp , xtmp ) ) ; return true ; } </s>

Emit the instruction sequence to compute the approximation for the division of NUM by DEN in QUO and return whether the sequence was emitted or not .


<s> bool aarch64_emit_approx_sqrt ( rtx dst , rtx src , bool recp ) { machine_mode mode = GET_MODE ( dst ) ; if ( GET_MODE_INNER ( mode ) == HFmode ) { gcc_assert ( ! recp ) ; return false ; } if ( ! recp ) { if ( ! ( flag_mlow_precision_sqrt || ( aarch64_tune_params . approx_modes -> sqrt & AARCH64_APPROX_MODE ( mode ) ) ) ) return false ; if ( flag_finite_math_only || flag_trapping_math || ! flag_unsafe_math_optimizations || optimize_function_for_size_p ( cfun ) ) return false ; } else gcc_assert ( use_rsqrt_p ( mode ) ) ; machine_mode mmsk = mode_for_int_vector ( mode ) . require ( ) ; rtx xmsk = gen_reg_rtx ( mmsk ) ; if ( ! recp ) emit_insn ( gen_rtx_SET ( xmsk , gen_rtx_NEG ( mmsk , gen_rtx_EQ ( mmsk , src , CONST0_RTX ( mode ) ) ) ) ) ; rtx xdst = gen_reg_rtx ( mode ) ; emit_insn ( gen_aarch64_rsqrte ( mode , xdst , src ) ) ; int iterations = ( GET_MODE_INNER ( mode ) == DFmode ) ? 3 : 2 ; if ( ( recp && flag_mrecip_low_precision_sqrt ) || ( ! recp && flag_mlow_precision_sqrt ) ) iterations -- ; rtx x1 = gen_reg_rtx ( mode ) ; while ( iterations -- ) { rtx x2 = gen_reg_rtx ( mode ) ; emit_set_insn ( x2 , gen_rtx_MULT ( mode , xdst , xdst ) ) ; emit_insn ( gen_aarch64_rsqrts ( mode , x1 , src , x2 ) ) ; if ( iterations > 0 ) emit_set_insn ( xdst , gen_rtx_MULT ( mode , xdst , x1 ) ) ; } if ( ! recp ) { rtx xtmp = gen_reg_rtx ( mmsk ) ; emit_set_insn ( xtmp , gen_rtx_AND ( mmsk , gen_rtx_NOT ( mmsk , xmsk ) , gen_rtx_SUBREG ( mmsk , xdst , 0 ) ) ) ; emit_move_insn ( xdst , gen_rtx_SUBREG ( mode , xtmp , 0 ) ) ; emit_set_insn ( xdst , gen_rtx_MULT ( mode , xdst , src ) ) ; } emit_set_insn ( dst , gen_rtx_MULT ( mode , xdst , x1 ) ) ; return true ; } </s>

Emit instruction sequence to compute either the approximate square root or its approximate reciprocal , depending on the flag RECP , and return whether the sequence was emitted or not .


<s> static void aarch64_emit_load_exclusive ( machine_mode mode , rtx rval , rtx mem , rtx model_rtx ) { emit_insn ( gen_aarch64_load_exclusive ( mode , rval , mem , model_rtx ) ) ; } </s>


<s> static void aarch64_emit_store_exclusive ( machine_mode mode , rtx bval , rtx rval , rtx mem , rtx model_rtx ) { emit_insn ( gen_aarch64_store_exclusive ( mode , bval , rval , mem , model_rtx ) ) ; } </s>


<s> static void aarch64_emit_sve_inverted_cond ( rtx target , rtx ptrue , rtx_code code , rtx op0 , rtx op1 ) { machine_mode pred_mode = GET_MODE ( ptrue ) ; rtx tmp = gen_reg_rtx ( pred_mode ) ; aarch64_emit_sve_ptrue_op ( tmp , ptrue , gen_rtx_fmt_ee ( code , pred_mode , op0 , op1 ) ) ; aarch64_emit_unop ( target , one_cmpl_optab , tmp ) ; } </s>

Emit the SVE equivalent of : ( set TMP ( CODE OP0 OP1 ) ) ( set TARGET ( not TMP ) ) PTRUE is an all-true predicate with the same mode as TARGET .


Emit the SVE equivalent of : ( set TMP1 ( CODE1 OP0 OP1 ) ) ( set TMP2 ( CODE2 OP0 OP1 ) ) ( set TARGET ( ior : PRED_MODE TMP1 TMP2 ) ) PTRUE is an all-true predicate with the same mode as TARGET .


<s> static void aarch64_emit_sve_predicated_cond ( rtx target , rtx_code code , rtx pred , rtx op0 , rtx op1 ) { rtx unspec = gen_rtx_UNSPEC ( GET_MODE ( pred ) , gen_rtvec ( 3 , pred , op0 , op1 ) , aarch64_unspec_cond_code ( code ) ) ; emit_set_insn ( target , unspec ) ; } </s>

Emit : ( set TARGET ( unspec [ PRED OP0 OP1 ] UNSPEC_COND_ < X > ) ) where < X > is the operation associated with comparison CODE . This form of instruction is used when ( and ( CODE OP0 OP1 ) PRED ) would have different semantics , such as when PRED might not be all-true and when comparing inactive lanes could have side effects .


<s> void aarch64_emit_sve_pred_move ( rtx dest , rtx pred , rtx src ) { 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 ) ; } </s>

Emit an SVE predicated move from SRC to DEST . PRED is a predicate that is known to contain PTRUE .


<s> static void aarch64_emit_sve_ptrue_op ( rtx target , rtx ptrue , rtx op ) { rtx unspec = gen_rtx_UNSPEC ( GET_MODE ( target ) , gen_rtvec ( 2 , ptrue , op ) , UNSPEC_MERGE_PTRUE ) ; rtx_insn * insn = emit_set_insn ( target , unspec ) ; set_unique_reg_note ( insn , REG_EQUAL , copy_rtx ( op ) ) ; } </s>

Use predicated SVE instructions to implement the equivalent of : ( set TARGET OP ) given that PTRUE is an all-true predicate of the appropriate mode .


<s> static void aarch64_emit_sve_ptrue_op_cc ( rtx target , rtx ptrue , rtx op ) { rtx unspec = gen_rtx_UNSPEC ( GET_MODE ( target ) , gen_rtvec ( 2 , ptrue , op ) , UNSPEC_MERGE_PTRUE ) ; rtx_insn * insn = emit_insn ( gen_set_clobber_cc ( target , unspec ) ) ; set_unique_reg_note ( insn , REG_EQUAL , copy_rtx ( op ) ) ; } </s>

Likewise , but also clobber the condition codes .


<s> int aarch64_epilogue_uses ( int regno ) { if ( epilogue_completed ) { if ( regno == LR_REGNUM ) return 1 ; if ( aarch64_simd_decl_p ( cfun -> decl ) && FP_SIMD_SAVED_REGNUM_P ( regno ) ) return 1 ; } return 0 ; } </s>

Return 1 if the register is used by the epilogue . We need to say the return register is used , but only after epilogue generation is complete . Note that in the case of sibcalls , the values `` used by the epilogue '' are considered live at the start of the called function . For SIMD functions we need to return 1 for FP registers that are saved and restored by a function but are not zero in call_used_regs . If we do not do this optimizations may remove the restore of the register .


<s> static bool aarch64_evpc_sve_tbl ( struct expand_vec_perm_d * d ) { unsigned HOST_WIDE_INT nelt ; if ( ! d -> one_vector_p && ! d -> perm . length ( ) . is_constant ( & nelt ) ) return false ; if ( d -> testing_p ) return true ; machine_mode sel_mode = mode_for_int_vector ( d -> vmode ) . require ( ) ; rtx sel = vec_perm_indices_to_rtx ( sel_mode , d -> perm ) ; if ( d -> one_vector_p ) emit_unspec2 ( d -> target , UNSPEC_TBL , d -> op0 , force_reg ( sel_mode , sel ) ) ; else aarch64_expand_sve_vec_perm ( d -> target , d -> op0 , d -> op1 , sel ) ; return true ; } </s>

Try to implement D using an SVE TBL instruction .


<s> void aarch64_expand_compare_and_swap ( rtx operands [ ] ) { rtx bval , rval , mem , oldval , newval , is_weak , mod_s , mod_f , x , cc_reg ; machine_mode mode , r_mode ; bval = operands [ 0 ] ; rval = operands [ 1 ] ; mem = operands [ 2 ] ; oldval = operands [ 3 ] ; newval = operands [ 4 ] ; is_weak = operands [ 5 ] ; mod_s = operands [ 6 ] ; mod_f = operands [ 7 ] ; mode = GET_MODE ( mem ) ; if ( is_mm_acquire ( memmodel_from_int ( INTVAL ( mod_f ) ) ) && is_mm_release ( memmodel_from_int ( INTVAL ( mod_s ) ) ) ) mod_s = GEN_INT ( MEMMODEL_ACQ_REL ) ; r_mode = mode ; if ( mode == QImode || mode == HImode ) { r_mode = SImode ; rval = gen_reg_rtx ( r_mode ) ; } if ( TARGET_LSE ) { if ( reg_overlap_mentioned_p ( rval , oldval ) ) rval = copy_to_mode_reg ( r_mode , oldval ) ; else emit_move_insn ( rval , gen_lowpart ( r_mode , oldval ) ) ; emit_insn ( gen_aarch64_compare_and_swap_lse ( mode , rval , mem , newval , mod_s ) ) ; cc_reg = aarch64_gen_compare_reg_maybe_ze ( NE , rval , oldval , mode ) ; } else { insn_code code = code_for_aarch64_compare_and_swap ( mode ) ; if ( ! insn_data [ code ] . operand [ 2 ] . predicate ( oldval , mode ) ) oldval = force_reg ( mode , oldval ) ; emit_insn ( GEN_FCN ( code ) ( rval , mem , oldval , newval , is_weak , mod_s , mod_f ) ) ; cc_reg = gen_rtx_REG ( CCmode , CC_REGNUM ) ; } if ( r_mode != mode ) rval = gen_lowpart ( mode , rval ) ; emit_move_insn ( operands [ 1 ] , rval ) ; x = gen_rtx_EQ ( SImode , cc_reg , const0_rtx ) ; emit_insn ( gen_rtx_SET ( bval , x ) ) ; } </s>


Expand movmem , as if from a __builtin_memcpy . Return true if we succeed , otherwise return false .


Generate RTL for 128-bit ( TImode ) subtraction with overflow . OP0 represents the TImode destination operand 0 LOW_DEST represents the low half ( DImode ) of TImode operand 0 LOW_IN1 represents the low half ( DImode ) of TImode operand 1 LOW_IN2 represents the low half ( DImode ) of TImode operand 2 HIGH_DEST represents the high half ( DImode ) of TImode operand 0 HIGH_IN1 represents the high half ( DImode ) of TImode operand 1 HIGH_IN2 represents the high half ( DImode ) of TImode operand 2 UNSIGNED_P is true if the operation is being performed on unsigned values .


<s> bool aarch64_expand_sve_vec_cmp_float ( rtx target , rtx_code code , rtx op0 , rtx op1 , bool can_invert_p ) { machine_mode pred_mode = GET_MODE ( target ) ; machine_mode data_mode = GET_MODE ( op0 ) ; rtx ptrue = force_reg ( pred_mode , CONSTM1_RTX ( pred_mode ) ) ; switch ( code ) { case UNORDERED : op1 = force_reg ( data_mode , op1 ) ; case LT : case LE : case GT : case GE : case EQ : case NE : { rtx cond = gen_rtx_fmt_ee ( code , pred_mode , op0 , op1 ) ; aarch64_emit_sve_ptrue_op ( target , ptrue , cond ) ; return false ; } case LTGT : aarch64_emit_sve_or_conds ( target , LT , GT , ptrue , op0 , op1 ) ; return false ; case UNEQ : if ( ! flag_trapping_math ) { op1 = force_reg ( data_mode , op1 ) ; aarch64_emit_sve_or_conds ( target , UNORDERED , EQ , ptrue , op0 , op1 ) ; return false ; } case UNLT : case UNLE : case UNGT : case UNGE : if ( flag_trapping_math ) { rtx ordered = gen_reg_rtx ( pred_mode ) ; op1 = force_reg ( data_mode , op1 ) ; aarch64_emit_sve_inverted_cond ( ordered , ptrue , UNORDERED , op0 , op1 ) ; if ( code == UNEQ ) code = NE ; else code = reverse_condition_maybe_unordered ( code ) ; if ( can_invert_p ) { aarch64_emit_sve_predicated_cond ( target , code , ordered , op0 , op1 ) ; return true ; } rtx tmp = gen_reg_rtx ( pred_mode ) ; aarch64_emit_sve_predicated_cond ( tmp , code , ordered , op0 , op1 ) ; aarch64_emit_unop ( target , one_cmpl_optab , tmp ) ; return false ; } break ; case ORDERED : op1 = force_reg ( data_mode , op1 ) ; break ; default : gcc_unreachable ( ) ; } code = reverse_condition_maybe_unordered ( code ) ; if ( can_invert_p ) { rtx cond = gen_rtx_fmt_ee ( code , pred_mode , op0 , op1 ) ; aarch64_emit_sve_ptrue_op ( target , ptrue , cond ) ; return true ; } aarch64_emit_sve_inverted_cond ( target , ptrue , code , op0 , op1 ) ; return false ; } </s>

Expand an SVE floating-point comparison : TARGET = CODE ( OP0 , OP1 ) If CAN_INVERT_P is true , the caller can also handle inverted results ; return true if the result is in fact inverted .


<s> void aarch64_expand_sve_vec_cmp_int ( rtx target , rtx_code code , rtx op0 , rtx op1 ) { machine_mode pred_mode = GET_MODE ( target ) ; machine_mode data_mode = GET_MODE ( op0 ) ; if ( ! aarch64_sve_cmp_operand_p ( code , op1 ) ) op1 = force_reg ( data_mode , op1 ) ; rtx ptrue = force_reg ( pred_mode , CONSTM1_RTX ( pred_mode ) ) ; rtx cond = gen_rtx_fmt_ee ( code , pred_mode , op0 , op1 ) ; aarch64_emit_sve_ptrue_op_cc ( target , ptrue , cond ) ; } </s>

Expand an SVE integer comparison : TARGET = CODE ( OP0 , OP1 ) .


<s> bool aarch64_float_const_representable_p ( rtx x ) { int point_pos = 2 * HOST_BITS_PER_WIDE_INT - 1 ; int exponent ; unsigned HOST_WIDE_INT mantissa , mask ; REAL_VALUE_TYPE r , m ; bool fail ; if ( ! CONST_DOUBLE_P ( x ) ) return false ; if ( GET_MODE ( x ) == VOIDmode || ( GET_MODE ( x ) == HFmode && ! TARGET_FP_F16INST ) ) return false ; r = * CONST_DOUBLE_REAL_VALUE ( x ) ; if ( REAL_VALUE_ISINF ( r ) || REAL_VALUE_ISNAN ( r ) || REAL_VALUE_MINUS_ZERO ( r ) ) return false ; r = real_value_abs ( & r ) ; exponent = REAL_EXP ( & r ) ; real_ldexp ( & m , & r , point_pos - exponent ) ; wide_int w = real_to_integer ( & m , & fail , HOST_BITS_PER_WIDE_INT * 2 ) ; if ( w . ulow ( ) != 0 ) return false ; mantissa = w . elt ( 1 ) ; point_pos -= HOST_BITS_PER_WIDE_INT ; mask = ( ( unsigned HOST_WIDE_INT ) 1 << ( point_pos - 5 ) ) - 1 ; if ( ( mantissa & mask ) != 0 ) return false ; mantissa >>= point_pos - 5 ; if ( mantissa == 0 ) return false ; mantissa &= ~ ( 1 << 4 ) ; gcc_assert ( mantissa <= 15 ) ; exponent = 5 - exponent ; return ( exponent >= 0 && exponent <= 7 ) ; } </s>

Return true iff X can be represented by a quarter-precision floating point immediate operand X . Note , we can not represent 0.0 .


<s> static rtx aarch64_gen_compare_reg_maybe_ze ( RTX_CODE code , rtx x , rtx y , machine_mode y_mode ) { if ( y_mode == E_QImode || y_mode == E_HImode ) { if ( CONST_INT_P ( y ) ) y = GEN_INT ( INTVAL ( y ) & GET_MODE_MASK ( y_mode ) ) ; else { rtx t , cc_reg ; machine_mode cc_mode ; t = gen_rtx_ZERO_EXTEND ( SImode , y ) ; t = gen_rtx_COMPARE ( CC_SWPmode , t , x ) ; cc_mode = CC_SWPmode ; cc_reg = gen_rtx_REG ( cc_mode , CC_REGNUM ) ; emit_set_insn ( cc_reg , t ) ; return cc_reg ; } } return aarch64_gen_compare_reg ( code , x , y ) ; } </s>

Similarly , but maybe zero-extend Y if Y_MODE < SImode .


<s> static sbitmap aarch64_get_separate_components ( void ) { sbitmap components = sbitmap_alloc ( LAST_SAVED_REGNUM + 1 ) ; bitmap_clear ( components ) ; for ( unsigned regno = 0 ; regno <= LAST_SAVED_REGNUM ; regno ++ ) if ( aarch64_register_saved_on_entry ( regno ) ) { poly_int64 offset = cfun -> machine -> frame . reg_offset [ regno ] ; if ( ! frame_pointer_needed ) offset += cfun -> machine -> frame . frame_size - cfun -> machine -> frame . hard_fp_offset ; if ( offset_12bit_unsigned_scaled_p ( DImode , offset ) ) bitmap_set_bit ( components , regno ) ; } if ( frame_pointer_needed ) bitmap_clear_bit ( components , HARD_FRAME_POINTER_REGNUM ) ; unsigned reg1 = cfun -> machine -> frame . wb_candidate1 ; unsigned reg2 = cfun -> machine -> frame . wb_candidate2 ; if ( reg2 != INVALID_REGNUM ) bitmap_clear_bit ( components , reg2 ) ; if ( reg1 != INVALID_REGNUM ) bitmap_clear_bit ( components , reg1 ) ; bitmap_clear_bit ( components , LR_REGNUM ) ; bitmap_clear_bit ( components , SP_REGNUM ) ; return components ; } </s>


"missing value in %<target()%> pragma or attribute"

"invalid feature modifier %s of value (\"%s\") in "

Parse an architecture extensions target attribute string specified in STR . For example `` +fp+nosimd '' . Show any errors if needed . Return TRUE if successful . Update aarch64_isa_flags to reflect the ISA features modified . PRAGMA_OR_ATTR is used in potential error messages .


<s> static bool aarch64_hard_regno_call_part_clobbered ( rtx_insn * insn , unsigned int regno , machine_mode mode ) { bool simd_p = insn && CALL_P ( insn ) && aarch64_simd_call_p ( insn ) ; return FP_REGNUM_P ( regno ) && maybe_gt ( GET_MODE_SIZE ( mode ) , simd_p ? 16 : 8 ) ; } </s>

Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED . The callee only saves the lower 64 bits of a 128-bit register . Tell the compiler the callee clobbers the top 64 bits when restoring the bottom 64 bits .


<s> static bool aarch64_hard_regno_mode_ok ( unsigned regno , machine_mode mode ) { if ( GET_MODE_CLASS ( mode ) == MODE_CC ) return regno == CC_REGNUM ; if ( regno == VG_REGNUM ) return mode == DImode ; unsigned int vec_flags = aarch64_classify_vector_mode ( mode ) ; if ( vec_flags & VEC_SVE_PRED ) return PR_REGNUM_P ( regno ) ; if ( PR_REGNUM_P ( regno ) ) return 0 ; if ( regno == SP_REGNUM ) return mode == Pmode || mode == ptr_mode ; if ( regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM ) return mode == Pmode ; if ( GP_REGNUM_P ( regno ) ) { if ( known_le ( GET_MODE_SIZE ( mode ) , 8 ) ) return true ; else if ( known_le ( GET_MODE_SIZE ( mode ) , 16 ) ) return ( regno & 1 ) == 0 ; } else if ( FP_REGNUM_P ( regno ) ) { if ( vec_flags & VEC_STRUCT ) return end_hard_regno ( mode , regno ) - 1 <= V31_REGNUM ; else return ! VECTOR_MODE_P ( mode ) || vec_flags != 0 ; } return false ; } </s>


<s> static void aarch64_output_mi_thunk ( FILE * file , tree thunk ATTRIBUTE_UNUSED , HOST_WIDE_INT delta , HOST_WIDE_INT vcall_offset , tree function ) { int this_regno = R0_REGNUM ; 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 ) ; this_rtx = gen_rtx_REG ( Pmode , this_regno ) ; temp0 = gen_rtx_REG ( Pmode , EP0_REGNUM ) ; temp1 = gen_rtx_REG ( Pmode , EP1_REGNUM ) ; if ( vcall_offset == 0 ) aarch64_add_offset ( Pmode , this_rtx , this_rtx , delta , temp1 , temp0 , false ) ; else { gcc_assert ( ( vcall_offset & ( POINTER_BYTES - 1 ) ) == 0 ) ; addr = this_rtx ; if ( delta != 0 ) { if ( delta >= - 256 && delta < 256 ) addr = gen_rtx_PRE_MODIFY ( Pmode , this_rtx , plus_constant ( Pmode , this_rtx , delta ) ) ; else aarch64_add_offset ( Pmode , this_rtx , this_rtx , delta , temp1 , temp0 , false ) ; } if ( Pmode == ptr_mode ) aarch64_emit_move ( temp0 , gen_rtx_MEM ( ptr_mode , addr ) ) ; else aarch64_emit_move ( temp0 , gen_rtx_ZERO_EXTEND ( Pmode , gen_rtx_MEM ( ptr_mode , addr ) ) ) ; if ( vcall_offset >= - 256 && vcall_offset < 4096 * POINTER_BYTES ) addr = plus_constant ( Pmode , temp0 , vcall_offset ) ; else { aarch64_internal_mov_immediate ( temp1 , GEN_INT ( vcall_offset ) , true , Pmode ) ; addr = gen_rtx_PLUS ( Pmode , temp0 , temp1 ) ; } if ( Pmode == ptr_mode ) aarch64_emit_move ( temp1 , gen_rtx_MEM ( ptr_mode , addr ) ) ; else aarch64_emit_move ( temp1 , gen_rtx_SIGN_EXTEND ( Pmode , gen_rtx_MEM ( ptr_mode , addr ) ) ) ; emit_insn ( gen_add2_insn ( this_rtx , temp1 ) ) ; } if ( ! TREE_USED ( function ) ) { assemble_external ( function ) ; TREE_USED ( function ) = 1 ; } funexp = XEXP ( DECL_RTL ( function ) , 0 ) ; funexp = gen_rtx_MEM ( FUNCTION_MODE , funexp ) ; insn = emit_call_insn ( gen_sibcall ( funexp , const0_rtx , NULL_RTX ) ) ; SIBLING_CALL_P ( insn ) = 1 ; insn = get_insns ( ) ; shorten_branches ( insn ) ; final_start_function ( insn , file , 1 ) ; final ( insn , file , 1 ) ; final_end_function ( ) ; reload_completed = 0 ; } </s>

Output code to add DELTA to the first argument , and then jump to FUNCTION . Used for C++ multiple inheritance .


<s>
const
char
*
aarch64_output_probe_stack_range
(
rtx
reg1
,
rtx
reg2
)
{
static
int
labelno
=
0
;
char
loop_lab
[
32
]
;
rtx
xops
[
2
]
;
ASM_GENERATE_INTERNAL_LABEL
(
loop_lab
,
"LPSRL"
,
labelno
++
)
;
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
loop_lab
)
;
HOST_WIDE_INT
stack_clash_probe_interval
=
1
<<
PARAM_VALUE
(
PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE
)
;
xops
[
0
]
=
reg1
;
HOST_WIDE_INT
interval
;
if
(
flag_stack_clash_protection
)
interval
=
stack_clash_probe_interval
;
else
interval
=
PROBE_INTERVAL
;
gcc_assert
(
aarch64_uimm12_shift
(
interval
)
)
;
xops
[
1
]
=
GEN_INT
(
interval
)
;
output_asm_insn
(
"sub\t%0, %0, %1"
,
xops
)
;
if
(
flag_stack_clash_protection
)
xops
[
1
]
=
GEN_INT
(
STACK_CLASH_CALLER_GUARD
)
;
else
xops
[
1
]
=
CONST0_RTX
(
GET_MODE
(
xops
[
1
]
)
)
;
output_asm_insn
(
"str\txzr, [%0, %1]"
,
xops
)
;
xops
[
1
]
=
reg2
;
output_asm_insn
(
"cmp\t%0, %1"
,
xops
)
;
fputs
(
"\tb.ne\t"
,
asm_out_file
)
;
assemble_name_raw
(
asm_out_file
,
loop_lab
)
;
fputc
(
'\n'
,
asm_out_file
)
;
return
""
;
}
</s>

Probe a range of stack addresses from REG1 to REG2 inclusive . These are absolute addresses .


"switch %<-mcpu=%s%> conflicts with %<-march=%s%> switch"

"assembler does not support %<-mabi=ilp32%>"

"return address signing is only supported for %<-mabi=lp64%>"


<s> static enum aarch64_parse_opt_result aarch64_parse_arch ( const char * to_parse , const struct processor * * res , unsigned long * isa_flags , std :: string * invalid_extension ) { const char * ext ; const struct processor * arch ; size_t len ; ext = strchr ( to_parse , '+' ) ; if ( ext != NULL ) len = ext - to_parse ; else len = strlen ( to_parse ) ; if ( len == 0 ) return AARCH64_PARSE_MISSING_ARG ; for ( arch = all_architectures ; arch -> name != NULL ; arch ++ ) { if ( strlen ( arch -> name ) == len && strncmp ( arch -> name , to_parse , len ) == 0 ) { unsigned long isa_temp = arch -> flags ; if ( ext != NULL ) { enum aarch64_parse_opt_result ext_res = aarch64_parse_extension ( ext , & isa_temp , invalid_extension ) ; if ( ext_res != AARCH64_PARSE_OK ) return ext_res ; } * res = arch ; * isa_flags = isa_temp ; return AARCH64_PARSE_OK ; } } return AARCH64_PARSE_INVALID_ARG ; } </s>

Parse the TO_PARSE string and put the architecture struct that it selects into RES and the architectural features into ISA_FLAGS . Return an aarch64_parse_opt_result describing the parse result . If there is an error parsing , RES and ISA_FLAGS are left unchanged .


<s> static enum aarch64_parse_opt_result aarch64_parse_cpu ( const char * to_parse , const struct processor * * res , unsigned long * isa_flags , std :: string * invalid_extension ) { const char * ext ; const struct processor * cpu ; size_t len ; ext = strchr ( to_parse , '+' ) ; if ( ext != NULL ) len = ext - to_parse ; else len = strlen ( to_parse ) ; if ( len == 0 ) return AARCH64_PARSE_MISSING_ARG ; for ( cpu = all_cores ; cpu -> name != NULL ; cpu ++ ) { if ( strlen ( cpu -> name ) == len && strncmp ( cpu -> name , to_parse , len ) == 0 ) { unsigned long isa_temp = cpu -> flags ; if ( ext != NULL ) { enum aarch64_parse_opt_result ext_res = aarch64_parse_extension ( ext , & isa_temp , invalid_extension ) ; if ( ext_res != AARCH64_PARSE_OK ) return ext_res ; } * res = cpu ; * isa_flags = isa_temp ; return AARCH64_PARSE_OK ; } } return AARCH64_PARSE_INVALID_ARG ; } </s>

Parse the TO_PARSE string and put the result tuning in RES and the architecture flags in ISA_FLAGS . Return an aarch64_parse_opt_result describing the parse result . If there is an error parsing , RES and ISA_FLAGS are left unchanged .


<s> static void aarch64_pop_regs ( unsigned regno1 , unsigned regno2 , HOST_WIDE_INT adjustment , rtx * cfi_ops ) { machine_mode mode = aarch64_reg_save_mode ( cfun -> decl , regno1 ) ; rtx reg1 = gen_rtx_REG ( mode , regno1 ) ; * cfi_ops = alloc_reg_note ( REG_CFA_RESTORE , reg1 , * cfi_ops ) ; if ( regno2 == INVALID_REGNUM ) { rtx mem = plus_constant ( Pmode , stack_pointer_rtx , adjustment ) ; mem = gen_rtx_POST_MODIFY ( Pmode , stack_pointer_rtx , mem ) ; emit_move_insn ( reg1 , gen_frame_mem ( mode , mem ) ) ; } else { rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; * cfi_ops = alloc_reg_note ( REG_CFA_RESTORE , reg2 , * cfi_ops ) ; emit_insn ( aarch64_gen_loadwb_pair ( mode , stack_pointer_rtx , reg1 , reg2 , adjustment ) ) ; } } </s>

Pop the two registers numbered REGNO1 , REGNO2 from the stack , adjusting it afterwards by ADJUSTMENT and writing the appropriate REG_CFA_RESTORE notes into CFI_OPS .


<s> static void aarch64_push_regs ( unsigned regno1 , unsigned regno2 , HOST_WIDE_INT adjustment ) { rtx_insn * insn ; machine_mode mode = aarch64_reg_save_mode ( cfun -> decl , regno1 ) ; if ( regno2 == INVALID_REGNUM ) return aarch64_pushwb_single_reg ( mode , regno1 , adjustment ) ; rtx reg1 = gen_rtx_REG ( mode , regno1 ) ; rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; insn = emit_insn ( aarch64_gen_storewb_pair ( mode , stack_pointer_rtx , reg1 , reg2 , adjustment ) ) ; RTX_FRAME_RELATED_P ( XVECEXP ( PATTERN ( insn ) , 0 , 2 ) ) = 1 ; RTX_FRAME_RELATED_P ( XVECEXP ( PATTERN ( insn ) , 0 , 1 ) ) = 1 ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } </s>

Push registers numbered REGNO1 and REGNO2 to the stack , adjusting the stack pointer by ADJUSTMENT .


<s> static machine_mode aarch64_reg_save_mode ( tree fndecl , unsigned regno ) { return GP_REGNUM_P ( regno ) ? E_DImode : ( aarch64_simd_decl_p ( fndecl ) ? E_TFmode : E_DFmode ) ; } </s>

Return the mode a register save/restore should use . DImode for integer registers , DFmode for FP registers in non-SIMD functions ( they only save the bottom half of a 128 bit register ) , or TFmode for FP registers in SIMD functions .


Implement TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS . If INSN calls a function that uses the SIMD ABI , take advantage of the extra call-preserved registers that the ABI provides .


<s> static void aarch64_restore_callee_saves ( machine_mode mode , poly_int64 start_offset , unsigned start , unsigned limit , bool skip_wb , rtx * cfi_ops ) { rtx base_rtx = stack_pointer_rtx ; unsigned regno ; unsigned regno2 ; poly_int64 offset ; for ( regno = aarch64_next_callee_save ( start , limit ) ; regno <= limit ; regno = aarch64_next_callee_save ( regno + 1 , limit ) ) { if ( cfun -> machine -> reg_is_wrapped_separately [ regno ] ) continue ; rtx reg , mem ; int offset_diff ; if ( skip_wb && ( regno == cfun -> machine -> frame . wb_candidate1 || regno == cfun -> machine -> frame . wb_candidate2 ) ) continue ; reg = gen_rtx_REG ( mode , regno ) ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno ] ; mem = gen_frame_mem ( mode , plus_constant ( Pmode , base_rtx , offset ) ) ; regno2 = aarch64_next_callee_save ( regno + 1 , limit ) ; offset_diff = cfun -> machine -> frame . reg_offset [ regno2 ] - cfun -> machine -> frame . reg_offset [ regno ] ; if ( regno2 <= limit && ! cfun -> machine -> reg_is_wrapped_separately [ regno2 ] && known_eq ( GET_MODE_SIZE ( mode ) , offset_diff ) ) { rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; rtx mem2 ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno2 ] ; mem2 = gen_frame_mem ( mode , plus_constant ( Pmode , base_rtx , offset ) ) ; emit_insn ( aarch64_gen_load_pair ( mode , reg , mem , reg2 , mem2 ) ) ; * cfi_ops = alloc_reg_note ( REG_CFA_RESTORE , reg2 , * cfi_ops ) ; regno = regno2 ; } else emit_move_insn ( reg , mem ) ; * cfi_ops = alloc_reg_note ( REG_CFA_RESTORE , reg , * cfi_ops ) ; } } </s>

Emit code to restore the callee registers of mode MODE from register number START up to and including LIMIT . Restore from the stack offset START_OFFSET , skipping any write-back candidates if SKIP_WB is true . Write the appropriate REG_CFA_RESTORE notes into CFI_OPS .


<s> static void aarch64_save_callee_saves ( machine_mode mode , poly_int64 start_offset , unsigned start , unsigned limit , bool skip_wb ) { rtx_insn * insn ; unsigned regno ; unsigned regno2 ; for ( regno = aarch64_next_callee_save ( start , limit ) ; regno <= limit ; regno = aarch64_next_callee_save ( regno + 1 , limit ) ) { rtx reg , mem ; poly_int64 offset ; int offset_diff ; if ( skip_wb && ( regno == cfun -> machine -> frame . wb_candidate1 || regno == cfun -> machine -> frame . wb_candidate2 ) ) continue ; if ( cfun -> machine -> reg_is_wrapped_separately [ regno ] ) continue ; reg = gen_rtx_REG ( mode , regno ) ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno ] ; mem = gen_frame_mem ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; regno2 = aarch64_next_callee_save ( regno + 1 , limit ) ; offset_diff = cfun -> machine -> frame . reg_offset [ regno2 ] - cfun -> machine -> frame . reg_offset [ regno ] ; if ( regno2 <= limit && ! cfun -> machine -> reg_is_wrapped_separately [ regno2 ] && known_eq ( GET_MODE_SIZE ( mode ) , offset_diff ) ) { rtx reg2 = gen_rtx_REG ( mode , regno2 ) ; rtx mem2 ; offset = start_offset + cfun -> machine -> frame . reg_offset [ regno2 ] ; mem2 = gen_frame_mem ( mode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; insn = emit_insn ( aarch64_gen_store_pair ( mode , mem , reg , mem2 , reg2 ) ) ; RTX_FRAME_RELATED_P ( XVECEXP ( PATTERN ( insn ) , 0 , 1 ) ) = 1 ; regno = regno2 ; } else insn = emit_move_insn ( mem , reg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } } </s>

Emit code to save the callee-saved registers from register number START to LIMIT to the stack at the location starting at offset START_OFFSET , skipping any write-back candidates if SKIP_WB is true .


<s> static bool aarch64_simd_call_p ( rtx_insn * insn ) { rtx symbol ; rtx call ; tree fndecl ; gcc_assert ( CALL_P ( insn ) ) ; call = get_call_rtx_from ( insn ) ; symbol = XEXP ( XEXP ( call , 0 ) , 0 ) ; if ( GET_CODE ( symbol ) != SYMBOL_REF ) return false ; fndecl = SYMBOL_REF_DECL ( symbol ) ; if ( ! fndecl ) return false ; return aarch64_simd_decl_p ( fndecl ) ; } </s>

Return true if the instruction is a call to a SIMD function , false if it is not a SIMD function or if we do not know anything about the function .


<s> static bool aarch64_simd_decl_p ( tree fndecl ) { tree fntype ; if ( fndecl == NULL ) return false ; fntype = TREE_TYPE ( fndecl ) ; if ( fntype == NULL ) return false ; if ( lookup_attribute ( "aarch64_vector_pcs" , TYPE_ATTRIBUTES ( fntype ) ) != NULL ) return true ; return false ; } </s>

Return true if this is a definition of a vectorized simd function .


<s> static HOST_WIDE_INT aarch64_simd_vector_alignment ( const_tree type ) { if ( TREE_CODE ( TYPE_SIZE ( type ) ) != INTEGER_CST ) return GET_MODE_CLASS ( TYPE_MODE ( type ) ) == MODE_VECTOR_BOOL ? 16 : 128 ; return wi :: umin ( wi :: to_wide ( TYPE_SIZE ( type ) ) , 128 ) . to_uhwi ( ) ; } </s>

Implement target hook TARGET_VECTOR_ALIGNMENT . The AAPCS64 sets the maximum alignment of a vector to 128 bits .


<s> void aarch64_split_atomic_op ( enum rtx_code code , rtx old_out , rtx new_out , rtx mem , rtx value , rtx model_rtx , rtx cond ) { machine_mode mode = GET_MODE ( mem ) ; machine_mode wmode = ( mode == DImode ? DImode : SImode ) ; const enum memmodel model = memmodel_from_int ( INTVAL ( model_rtx ) ) ; const bool is_sync = is_mm_sync ( model ) ; rtx_code_label * label ; rtx x ; label = gen_label_rtx ( ) ; emit_label ( label ) ; if ( new_out ) new_out = gen_lowpart ( wmode , new_out ) ; if ( old_out ) old_out = gen_lowpart ( wmode , old_out ) ; else old_out = new_out ; value = simplify_gen_subreg ( wmode , value , mode , 0 ) ; if ( is_sync ) aarch64_emit_load_exclusive ( mode , old_out , mem , GEN_INT ( MEMMODEL_RELAXED ) ) ; else aarch64_emit_load_exclusive ( mode , old_out , mem , model_rtx ) ; switch ( code ) { case SET : new_out = value ; break ; case NOT : x = gen_rtx_AND ( wmode , old_out , value ) ; emit_insn ( gen_rtx_SET ( new_out , x ) ) ; x = gen_rtx_NOT ( wmode , new_out ) ; emit_insn ( gen_rtx_SET ( new_out , x ) ) ; break ; case MINUS : if ( CONST_INT_P ( value ) ) { value = GEN_INT ( - INTVAL ( value ) ) ; code = PLUS ; } default : x = gen_rtx_fmt_ee ( code , wmode , old_out , value ) ; emit_insn ( gen_rtx_SET ( new_out , x ) ) ; break ; } aarch64_emit_store_exclusive ( mode , cond , mem , gen_lowpart ( mode , new_out ) , model_rtx ) ; if ( aarch64_track_speculation ) { rtx cc_reg = aarch64_gen_compare_reg ( NE , cond , const0_rtx ) ; x = gen_rtx_NE ( GET_MODE ( cc_reg ) , cc_reg , const0_rtx ) ; } else x = gen_rtx_NE ( VOIDmode , cond , const0_rtx ) ; x = gen_rtx_IF_THEN_ELSE ( VOIDmode , x , gen_rtx_LABEL_REF ( Pmode , label ) , pc_rtx ) ; aarch64_emit_unlikely_jump ( gen_rtx_SET ( pc_rtx , x ) ) ; if ( is_sync ) aarch64_emit_post_barrier ( model ) ; } </s>


<s> void aarch64_split_compare_and_swap ( rtx operands [ ] ) { rtx rval , mem , oldval , newval , scratch ; machine_mode mode ; bool is_weak ; rtx_code_label * label1 , * label2 ; rtx x , cond ; enum memmodel model ; rtx model_rtx ; rval = operands [ 0 ] ; mem = operands [ 1 ] ; oldval = operands [ 2 ] ; newval = operands [ 3 ] ; is_weak = ( operands [ 4 ] != const0_rtx ) ; model_rtx = operands [ 5 ] ; scratch = operands [ 7 ] ; mode = GET_MODE ( mem ) ; model = memmodel_from_int ( INTVAL ( model_rtx ) ) ; bool strong_zero_p = ! is_weak && oldval == const0_rtx ; label1 = NULL ; if ( ! is_weak ) { label1 = gen_label_rtx ( ) ; emit_label ( label1 ) ; } label2 = gen_label_rtx ( ) ; if ( is_mm_sync ( model ) ) aarch64_emit_load_exclusive ( mode , rval , mem , GEN_INT ( MEMMODEL_RELAXED ) ) ; else aarch64_emit_load_exclusive ( mode , rval , mem , model_rtx ) ; if ( strong_zero_p ) { if ( aarch64_track_speculation ) { rtx cc_reg = aarch64_gen_compare_reg ( NE , rval , const0_rtx ) ; x = gen_rtx_NE ( GET_MODE ( cc_reg ) , cc_reg , const0_rtx ) ; } else x = gen_rtx_NE ( VOIDmode , rval , const0_rtx ) ; x = gen_rtx_IF_THEN_ELSE ( VOIDmode , x , gen_rtx_LABEL_REF ( Pmode , label2 ) , pc_rtx ) ; aarch64_emit_unlikely_jump ( gen_rtx_SET ( pc_rtx , x ) ) ; } else { cond = aarch64_gen_compare_reg_maybe_ze ( NE , rval , oldval , mode ) ; x = gen_rtx_NE ( VOIDmode , cond , const0_rtx ) ; x = gen_rtx_IF_THEN_ELSE ( VOIDmode , x , gen_rtx_LABEL_REF ( Pmode , label2 ) , pc_rtx ) ; aarch64_emit_unlikely_jump ( gen_rtx_SET ( pc_rtx , x ) ) ; } aarch64_emit_store_exclusive ( mode , scratch , mem , newval , model_rtx ) ; if ( ! is_weak ) { if ( aarch64_track_speculation ) { rtx cc_reg = aarch64_gen_compare_reg ( NE , scratch , const0_rtx ) ; x = gen_rtx_NE ( GET_MODE ( cc_reg ) , cc_reg , const0_rtx ) ; } else x = gen_rtx_NE ( VOIDmode , scratch , const0_rtx ) ; x = gen_rtx_IF_THEN_ELSE ( VOIDmode , x , gen_rtx_LABEL_REF ( Pmode , label1 ) , pc_rtx ) ; aarch64_emit_unlikely_jump ( gen_rtx_SET ( pc_rtx , x ) ) ; } else { cond = gen_rtx_REG ( CCmode , CC_REGNUM ) ; x = gen_rtx_COMPARE ( CCmode , scratch , const0_rtx ) ; emit_insn ( gen_rtx_SET ( cond , x ) ) ; } emit_label ( label2 ) ; if ( strong_zero_p ) { cond = gen_rtx_REG ( CCmode , CC_REGNUM ) ; x = gen_rtx_COMPARE ( CCmode , rval , const0_rtx ) ; emit_insn ( gen_rtx_SET ( cond , x ) ) ; } if ( is_mm_sync ( model ) ) aarch64_emit_post_barrier ( model ) ; } </s>


<s> static unsigned int aarch64_unspec_cond_code ( rtx_code code ) { switch ( code ) { case NE : return UNSPEC_COND_NE ; case EQ : return UNSPEC_COND_EQ ; case LT : return UNSPEC_COND_LT ; case GT : return UNSPEC_COND_GT ; case LE : return UNSPEC_COND_LE ; case GE : return UNSPEC_COND_GE ; default : gcc_unreachable ( ) ; } } </s>

Return the UNSPEC_COND_ * code for comparison CODE .


<s> bool aarch64_use_simple_return_insn_p ( void ) { if ( aarch64_simd_decl_p ( cfun -> decl ) && ! crtl -> is_leaf ) return false ; return true ; } </s>

Return false for non-leaf SIMD functions in order to avoid shrink-wrapping them . Doing this will lose the necessary save/restore of FP registers .


"invalid feature modifier %qs in %<-march=%s%>"

Validate a command-line -march option . Parse the arch and extensions ( if any ) specified in STR and throw errors if appropriate . Put the results , if they are valid , in RES and ISA_FLAGS . Return whether the option is valid .


"invalid feature modifier %qs in %<-mcpu=%s%>"

Validate a command-line -mcpu option . Parse the cpu and extensions ( if any ) specified in STR and throw errors if appropriate . Put the results if they are valid in RES and ISA_FLAGS . Return whether the option is valid .


<s>
static
void
initialize_aarch64_code_model
(
struct
gcc_options
*
opts
)
{
if
(
opts
->
x_flag_pic
)
{
switch
(
opts
->
x_aarch64_cmodel_var
)
{
case
AARCH64_CMODEL_TINY
:
aarch64_cmodel
=
AARCH64_CMODEL_TINY_PIC
;
break
;
case
AARCH64_CMODEL_SMALL
:
aarch64_cmodel
=
(
flag_pic
==
2
AARCH64_CMODEL_SMALL_PIC
:
AARCH64_CMODEL_SMALL_SPIC
)
;
aarch64_cmodel
=
AARCH64_CMODEL_SMALL_PIC
;
break
;
case
AARCH64_CMODEL_LARGE
:
sorry
(
"code model %qs with %<-f%s%>"
,
"large"
,
opts
->
x_flag_pic
>
1
"PIC"
:
"pic"
)
;
break
;
default
:
gcc_unreachable
(
)
;
}
}
else
aarch64_cmodel
=
opts
->
x_aarch64_cmodel_var
;
}
</s>

A checking mechanism for the implementation of the various code models .


<s> bool aarch64_address_valid_for_prefetch_p ( rtx x , bool strict_p ) { struct aarch64_address_info addr ; bool res = aarch64_classify_address ( & addr , x , DImode , strict_p ) ; if ( ! res ) return false ; return addr . type != ADDRESS_REG_WB ; } </s>

Return true if the address X is valid for a PRFM instruction . STRICT_P is true if we should do strict checking with aarch64_classify_address .


<s> void aarch64_addti_scratch_regs ( rtx op1 , rtx op2 , rtx * low_dest , rtx * low_in1 , rtx * low_in2 , rtx * high_dest , rtx * high_in1 , rtx * high_in2 ) { * low_dest = gen_reg_rtx ( DImode ) ; * low_in1 = gen_lowpart ( DImode , op1 ) ; * low_in2 = simplify_gen_subreg ( DImode , op2 , TImode , subreg_lowpart_offset ( DImode , TImode ) ) ; * high_dest = gen_reg_rtx ( DImode ) ; * high_in1 = gen_highpart ( DImode , op1 ) ; * high_in2 = simplify_gen_subreg ( DImode , op2 , TImode , subreg_highpart_offset ( DImode , TImode ) ) ; } </s>

Generate DImode scratch registers for 128-bit ( TImode ) addition . OP1 represents the TImode destination operand 1 OP2 represents the TImode destination operand 2 LOW_DEST represents the low half ( DImode ) of TImode operand 0 LOW_IN1 represents the low half ( DImode ) of TImode operand 1 LOW_IN2 represents the low half ( DImode ) of TImode operand 2 HIGH_DEST represents the high half ( DImode ) of TImode operand 0 HIGH_IN1 represents the high half ( DImode ) of TImode operand 1 HIGH_IN2 represents the high half ( DImode ) of TImode operand 2 .


<s> static void aarch64_add_cfa_expression ( rtx_insn * insn , rtx reg , rtx base , poly_int64 offset ) { rtx mem = gen_frame_mem ( GET_MODE ( reg ) , plus_constant ( Pmode , base , offset ) ) ; add_reg_note ( insn , REG_CFA_EXPRESSION , gen_rtx_SET ( mem , reg ) ) ; } </s>

Add a REG_CFA_EXPRESSION note to INSN to say that register REG is saved at BASE + OFFSET .


<s> static void aarch64_add_offset_1 ( scalar_int_mode mode , rtx dest , rtx src , HOST_WIDE_INT offset , rtx temp1 , bool frame_related_p , bool emit_move_imm ) { gcc_assert ( emit_move_imm || temp1 != NULL_RTX ) ; gcc_assert ( temp1 == NULL_RTX || ! reg_overlap_mentioned_p ( temp1 , src ) ) ; unsigned HOST_WIDE_INT moffset = absu_hwi ( offset ) ; rtx_insn * insn ; if ( ! moffset ) { if ( ! rtx_equal_p ( dest , src ) ) { insn = emit_insn ( gen_rtx_SET ( dest , src ) ) ; RTX_FRAME_RELATED_P ( insn ) = frame_related_p ; } return ; } if ( aarch64_uimm12_shift ( moffset ) ) { insn = emit_insn ( gen_add3_insn ( dest , src , GEN_INT ( offset ) ) ) ; RTX_FRAME_RELATED_P ( insn ) = frame_related_p ; return ; } if ( moffset < 0x1000000 && ( ( ! temp1 && ! can_create_pseudo_p ( ) ) || ! aarch64_move_imm ( moffset , mode ) ) ) { HOST_WIDE_INT low_off = moffset & 0xfff ; low_off = offset < 0 ? - low_off : low_off ; insn = emit_insn ( gen_add3_insn ( dest , src , GEN_INT ( low_off ) ) ) ; RTX_FRAME_RELATED_P ( insn ) = frame_related_p ; insn = emit_insn ( gen_add2_insn ( dest , GEN_INT ( offset - low_off ) ) ) ; RTX_FRAME_RELATED_P ( insn ) = frame_related_p ; return ; } if ( emit_move_imm ) { gcc_assert ( temp1 != NULL_RTX || can_create_pseudo_p ( ) ) ; temp1 = aarch64_force_temporary ( mode , temp1 , gen_int_mode ( moffset , mode ) ) ; } insn = emit_insn ( offset < 0 ? gen_sub3_insn ( dest , src , temp1 ) : gen_add3_insn ( dest , src , temp1 ) ) ; if ( frame_related_p ) { RTX_FRAME_RELATED_P ( insn ) = frame_related_p ; rtx adj = plus_constant ( mode , src , offset ) ; add_reg_note ( insn , REG_CFA_ADJUST_CFA , gen_rtx_SET ( dest , adj ) ) ; } } </s>

A subroutine of aarch64_add_offset . Set DEST to SRC + OFFSET for a non-polynomial OFFSET . MODE is the mode of the addition . FRAME_RELATED_P is true if the RTX_FRAME_RELATED flag should be set and CFA adjustments added to the generated instructions . TEMP1 , if nonnull , is a register of mode MODE that can be used as a temporary if register allocation is already complete . This temporary register may overlap DEST but must not overlap SRC . If TEMP1 is known to hold abs ( OFFSET ) , EMIT_MOVE_IMM can be set to false to avoid emitting the immediate again . Since this function may be used to adjust the stack pointer , we must ensure that it can not cause transient stack deallocation ( for example by first incrementing SP and then decrementing when adjusting by a large immediate ) .


<s> static unsigned int aarch64_add_offset_1_temporaries ( HOST_WIDE_INT offset ) { return abs_hwi ( offset ) < 0x1000000 ? 0 : 1 ; } </s>

Return the number of temporary registers that aarch64_add_offset_1 would need to add OFFSET to a register .


<s> int aarch64_add_offset_temporaries ( rtx x ) { poly_int64 offset ; if ( ! poly_int_rtx_p ( x , & offset ) ) return - 1 ; return aarch64_offset_temporaries ( true , offset ) ; } </s>

If X can be represented as a poly_int64 , return the number of temporaries that are required to add it to a register . Return -1 otherwise .


<s> static inline void aarch64_add_sp ( rtx temp1 , rtx temp2 , poly_int64 delta , bool emit_move_imm ) { aarch64_add_offset ( Pmode , stack_pointer_rtx , stack_pointer_rtx , delta , temp1 , temp2 , true , emit_move_imm ) ; } </s>

Add DELTA to the stack pointer , marking the instructions frame-related . TEMP1 is available as a temporary if nonnull . EMIT_MOVE_IMM is false if TEMP1 already contains abs ( DELTA ) .


<s> static unsigned aarch64_add_stmt_cost ( void * data , int count , enum vect_cost_for_stmt kind , struct _stmt_vec_info * stmt_info , int misalign , enum vect_cost_model_location where ) { unsigned * cost = ( unsigned * ) data ; unsigned retval = 0 ; if ( flag_vect_cost_model ) { tree vectype = stmt_info ? stmt_vectype ( stmt_info ) : NULL_TREE ; int stmt_cost = aarch64_builtin_vectorization_cost ( kind , vectype , misalign ) ; if ( stmt_info && vectype && aarch64_sve_mode_p ( TYPE_MODE ( vectype ) ) ) stmt_cost = aarch64_sve_adjust_stmt_cost ( kind , stmt_info , vectype , stmt_cost ) ; if ( where == vect_body && stmt_info && stmt_in_inner_loop_p ( stmt_info ) ) count *= 50 ; retval = ( unsigned ) ( count * stmt_cost ) ; cost [ where ] += retval ; } return retval ; } </s>


<s> static inline void aarch64_adjust_sve_callee_save_base ( machine_mode mode , rtx & base_rtx , rtx & anchor_reg , poly_int64 & offset , rtx & ptrue ) { if ( maybe_ge ( offset , 8 * GET_MODE_SIZE ( mode ) ) ) { poly_int64 anchor_offset = 16 * GET_MODE_SIZE ( mode ) ; if ( ! anchor_reg ) { anchor_reg = gen_rtx_REG ( Pmode , STACK_CLASH_SVE_CFA_REGNUM ) ; emit_insn ( gen_add3_insn ( anchor_reg , base_rtx , gen_int_mode ( anchor_offset , Pmode ) ) ) ; } base_rtx = anchor_reg ; offset -= anchor_offset ; } if ( ! ptrue ) { int pred_reg = cfun -> machine -> frame . spare_pred_reg ; emit_move_insn ( gen_rtx_REG ( VNx16BImode , pred_reg ) , CONSTM1_RTX ( VNx16BImode ) ) ; ptrue = gen_rtx_REG ( VNx2BImode , pred_reg ) ; } } </s>

The caller is going to use ST1D or LD1D to save or restore an SVE register in mode MODE at BASE_RTX + OFFSET , where OFFSET is in the range [ 1 , 16 ] * GET_MODE_SIZE ( MODE ) . Prepare for this by : ( 1 ) updating BASE_RTX + OFFSET so that it is a legitimate ST1D or LD1D address ( 2 ) setting PRED to a valid predicate register for the ST1D or LD1D , if the variable is n't already nonnull ( 1 ) is needed when OFFSET is in the range [ 8 , 16 ] * GET_MODE_SIZE ( MODE ) . Handle this case using a temporary base register that is suitable for all offsets in that range . Use ANCHOR_REG as this base register if it is nonnull , otherwise create a new register and store it in ANCHOR_REG .


<s> static bool aarch64_advsimd_ldp_stp_p ( enum vect_cost_for_stmt kind , stmt_vec_info stmt_info ) { switch ( kind ) { case vector_load : case vector_store : case unaligned_load : case unaligned_store : break ; default : return false ; } if ( aarch64_tune_params . extra_tuning_flags & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS ) return false ; return is_gimple_assign ( stmt_info -> stmt ) ; } </s>

Return true if creating multiple copies of STMT_INFO for Advanced SIMD vectors would produce a series of LDP or STP operations . KIND is the kind of statement that STMT_INFO represents .


<s> static bool aarch64_advsimd_struct_mode_p ( machine_mode mode ) { return ( TARGET_SIMD && ( mode == OImode || mode == CImode || mode == XImode ) ) ; } </s>

Return true if MODE is any of the Advanced SIMD structure modes .


<s> static bool aarch64_advsimd_valid_immediate ( unsigned HOST_WIDE_INT val64 , simd_immediate_info * info , enum simd_immediate_check which ) { unsigned int val32 = val64 & 0xffffffff ; unsigned int val16 = val64 & 0xffff ; unsigned int val8 = val64 & 0xff ; if ( val32 == ( val64 >> 32 ) ) { if ( ( which & AARCH64_CHECK_ORR ) != 0 && aarch64_advsimd_valid_immediate_hs ( val32 , info , which , simd_immediate_info :: MOV ) ) return true ; if ( ( which & AARCH64_CHECK_BIC ) != 0 && aarch64_advsimd_valid_immediate_hs ( ~ val32 , info , which , simd_immediate_info :: MVN ) ) return true ; if ( which == AARCH64_CHECK_MOV && val16 == ( val32 >> 16 ) && val8 == ( val16 >> 8 ) ) { if ( info ) * info = simd_immediate_info ( QImode , val8 ) ; return true ; } } if ( which == AARCH64_CHECK_MOV ) { unsigned int i ; for ( i = 0 ; i < 64 ; i += 8 ) { unsigned char byte = ( val64 >> i ) & 0xff ; if ( byte != 0 && byte != 0xff ) break ; } if ( i == 64 ) { if ( info ) * info = simd_immediate_info ( DImode , val64 ) ; return true ; } } return false ; } </s>

Return true if replicating VAL64 is a valid immediate for the Advanced SIMD operation described by WHICH . If INFO is nonnull , use it to describe valid immediates .


<s> static bool aarch64_advsimd_valid_immediate_hs ( unsigned int val32 , simd_immediate_info * info , enum simd_immediate_check which , simd_immediate_info :: insn_type insn ) { for ( unsigned int shift = 0 ; shift < 32 ; shift += 8 ) if ( ( val32 & ( 0xff << shift ) ) == val32 ) { if ( info ) * info = simd_immediate_info ( SImode , val32 >> shift , insn , simd_immediate_info :: LSL , shift ) ; return true ; } unsigned int imm16 = val32 & 0xffff ; if ( imm16 == ( val32 >> 16 ) ) for ( unsigned int shift = 0 ; shift < 16 ; shift += 8 ) if ( ( imm16 & ( 0xff << shift ) ) == imm16 ) { if ( info ) * info = simd_immediate_info ( HImode , imm16 >> shift , insn , simd_immediate_info :: LSL , shift ) ; return true ; } if ( which == AARCH64_CHECK_MOV ) for ( unsigned int shift = 8 ; shift < 24 ; shift += 8 ) { unsigned int low = ( 1 << shift ) - 1 ; if ( ( ( val32 & ( 0xff << shift ) ) | low ) == val32 ) { if ( info ) * info = simd_immediate_info ( SImode , val32 >> shift , insn , simd_immediate_info :: MSL , shift ) ; return true ; } } return false ; } </s>

Return true if replicating VAL32 is a valid 2-byte or 4-byte immediate for the Advanced SIMD operation described by WHICH and INSN . If INFO is nonnull , use it to describe valid immediates .


<s> static HOST_WIDE_INT aarch64_anchor_offset ( HOST_WIDE_INT offset , HOST_WIDE_INT size , machine_mode mode ) { if ( size > 16 ) return ( offset + 0x400 ) & ~ 0x7f0 ; if ( offset & ( size - 1 ) ) { if ( mode == BLKmode ) return ( offset + 512 ) & ~ 0x3ff ; return ( offset + 0x100 ) & ~ 0x1ff ; } if ( IN_RANGE ( offset , - 256 , 0 ) ) return 0 ; if ( mode == TImode || mode == TFmode ) return ( offset + 0x100 ) & ~ 0x1ff ; return offset & ( ~ 0xfff * size ) ; } </s>

OFFSET is an address offset for mode MODE , which has SIZE bytes . If OFFSET is out of range , return an offset of an anchor point that is in range . Return 0 otherwise .


<s> bool aarch64_and_bitmask_imm ( unsigned HOST_WIDE_INT val_in , machine_mode mode ) { scalar_int_mode int_mode ; if ( ! is_a < scalar_int_mode > ( mode , & int_mode ) ) return false ; if ( aarch64_bitmask_imm ( val_in , int_mode ) ) return false ; if ( aarch64_move_imm ( val_in , int_mode ) ) return false ; unsigned HOST_WIDE_INT imm2 = aarch64_and_split_imm2 ( val_in ) ; return aarch64_bitmask_imm ( imm2 , int_mode ) ; } </s>

Return true if VAL_IN is a valid 'and ' bitmask immediate .


Create mask of ones , covering the lowest to highest bits set in VAL_IN . Assumed precondition : VAL_IN Is not zero .


Create constant where bits outside of lowest bit set to highest bit set are set to 1 .


<s> static opt_machine_mode aarch64_array_mode ( machine_mode mode , unsigned HOST_WIDE_INT nelems ) { if ( aarch64_classify_vector_mode ( mode ) == VEC_SVE_DATA && IN_RANGE ( nelems , 2 , 4 ) ) return mode_for_vector ( GET_MODE_INNER ( mode ) , GET_MODE_NUNITS ( mode ) * nelems ) ; return opt_machine_mode ( ) ; } </s>

Implement target hook TARGET_ARRAY_MODE .


<s> static bool aarch64_array_mode_supported_p ( machine_mode mode , unsigned HOST_WIDE_INT nelems ) { if ( TARGET_SIMD && ( AARCH64_VALID_SIMD_QREG_MODE ( mode ) || AARCH64_VALID_SIMD_DREG_MODE ( mode ) ) && ( nelems >= 2 && nelems <= 4 ) ) return true ; return false ; } </s>

Implement target hook TARGET_ARRAY_MODE_SUPPORTED_P .


<s> static unsigned HOST_WIDE_INT aarch64_asan_shadow_offset ( void ) { if ( TARGET_ILP32 ) return ( HOST_WIDE_INT_1 << 29 ) ; else return ( HOST_WIDE_INT_1 << 36 ) ; } </s>

Implement the TARGET_ASAN_SHADOW_OFFSET hook .


<s> void aarch64_asm_output_alias ( FILE * stream , const tree decl , const tree target ) { const char * name = XSTR ( XEXP ( DECL_RTL ( decl ) , 0 ) , 0 ) ; const char * value = IDENTIFIER_POINTER ( target ) ; aarch64_asm_output_variant_pcs ( stream , decl , name ) ; ASM_OUTPUT_DEF ( stream , name , value ) ; } </s>

Implement ASM_OUTPUT_DEF_FROM_DECLS . Output .variant_pcs for aliases .


<s> void aarch64_asm_output_external ( FILE * stream , tree decl , const char * name ) { default_elf_asm_output_external ( stream , decl , name ) ; aarch64_asm_output_variant_pcs ( stream , decl , name ) ; } </s>

Implement ASM_OUTPUT_EXTERNAL . Output .variant_pcs for undefined function symbol references .


<s> static void aarch64_asm_output_variant_pcs ( FILE * stream , const tree decl , const char * name ) { if ( TREE_CODE ( decl ) == FUNCTION_DECL ) { arm_pcs pcs = ( arm_pcs ) fndecl_abi ( decl ) . id ( ) ; if ( pcs == ARM_PCS_SIMD || pcs == ARM_PCS_SVE ) { fprintf ( stream , "\t.variant_pcs\t" ) ; assemble_name ( stream , name ) ; fprintf ( stream , "\n" ) ; } } } </s>

Output .variant_pcs for aarch64_vector_pcs function symbols .


<s> int aarch64_asm_preferred_eh_data_format ( int code ATTRIBUTE_UNUSED , int global ) { int type ; switch ( aarch64_cmodel ) { case AARCH64_CMODEL_TINY : case AARCH64_CMODEL_TINY_PIC : case AARCH64_CMODEL_SMALL : case AARCH64_CMODEL_SMALL_PIC : case AARCH64_CMODEL_SMALL_SPIC : type = DW_EH_PE_sdata4 ; break ; default : type = DW_EH_PE_sdata8 ; break ; } return ( global ? DW_EH_PE_indirect : 0 ) | DW_EH_PE_pcrel | type ; } </s>

Select a format to encode pointers in exception handling data .


<s> rtx aarch64_atomic_ool_func ( machine_mode mode , rtx model_rtx , const atomic_ool_names * names ) { memmodel model = memmodel_base ( INTVAL ( model_rtx ) ) ; int mode_idx , model_idx ; switch ( mode ) { case E_QImode : mode_idx = 0 ; break ; case E_HImode : mode_idx = 1 ; break ; case E_SImode : mode_idx = 2 ; break ; case E_DImode : mode_idx = 3 ; break ; case E_TImode : mode_idx = 4 ; break ; default : gcc_unreachable ( ) ; } switch ( model ) { case MEMMODEL_RELAXED : model_idx = 0 ; break ; case MEMMODEL_CONSUME : case MEMMODEL_ACQUIRE : model_idx = 1 ; break ; case MEMMODEL_RELEASE : model_idx = 2 ; break ; case MEMMODEL_ACQ_REL : case MEMMODEL_SEQ_CST : model_idx = 3 ; break ; default : gcc_unreachable ( ) ; } return init_one_libfunc_visibility ( names -> str [ mode_idx ] [ model_idx ] , VISIBILITY_HIDDEN ) ; } </s>

We store the names of the various atomic helpers in a 5x4 array . Return the libcall function given MODE , MODEL and NAMES .