<s> static bool aarch64_evpc_reencode ( struct expand_vec_perm_d * d ) { expand_vec_perm_d newd ; unsigned HOST_WIDE_INT nelt ; if ( d -> vec_flags != VEC_ADVSIMD ) return false ; poly_uint64 vec_bits = GET_MODE_BITSIZE ( d -> vmode ) ; unsigned int new_elt_bits = GET_MODE_UNIT_BITSIZE ( d -> vmode ) * 2 ; auto new_elt_mode = int_mode_for_size ( new_elt_bits , false ) . require ( ) ; machine_mode new_mode = aarch64_simd_container_mode ( new_elt_mode , vec_bits ) ; if ( new_mode == word_mode ) return false ; nelt = d -> perm . length ( ) . to_constant ( ) ; vec_perm_builder newpermconst ; newpermconst . new_vector ( nelt / 2 , nelt / 2 , 1 ) ; for ( unsigned int i = 0 ; i < nelt ; i += 2 ) { poly_int64 elt0 = d -> perm [ i ] ; poly_int64 elt1 = d -> perm [ i + 1 ] ; poly_int64 newelt ; if ( ! multiple_p ( elt0 , 2 , & newelt ) || maybe_ne ( elt0 + 1 , elt1 ) ) return false ; newpermconst . quick_push ( newelt . to_constant ( ) ) ; } newpermconst . finalize ( ) ; newd . vmode = new_mode ; newd . vec_flags = VEC_ADVSIMD ; newd . target = d -> target ? gen_lowpart ( new_mode , d -> target ) : NULL ; newd . op0 = d -> op0 ? gen_lowpart ( new_mode , d -> op0 ) : NULL ; newd . op1 = d -> op1 ? gen_lowpart ( new_mode , d -> op1 ) : NULL ; newd . testing_p = d -> testing_p ; newd . one_vector_p = d -> one_vector_p ; newd . perm . new_vector ( newpermconst , newd . one_vector_p ? 1 : 2 , nelt / 2 ) ; return aarch64_expand_vec_perm_const_1 ( & newd ) ; } </s>

Try to re-encode the PERM constant so it combines odd and even elements . This rewrites constants such as { 0 , 1 , 4 , 5 } /V4SF to { 0 , 2 } /V2DI . We retry with this new constant with the full suite of patterns .


<s> static bool aarch64_evpc_rev_local ( struct expand_vec_perm_d * d ) { HOST_WIDE_INT diff ; unsigned int i , size , unspec ; machine_mode pred_mode ; if ( d -> vec_flags == VEC_SVE_PRED || ! d -> one_vector_p || ! d -> perm [ 0 ] . is_constant ( & diff ) || ! diff ) return false ; if ( d -> vec_flags & VEC_SVE_DATA ) size = ( diff + 1 ) * aarch64_sve_container_bits ( d -> vmode ) ; else size = ( diff + 1 ) * GET_MODE_UNIT_BITSIZE ( d -> vmode ) ; if ( size == 64 ) { unspec = UNSPEC_REV64 ; pred_mode = VNx2BImode ; } else if ( size == 32 ) { unspec = UNSPEC_REV32 ; pred_mode = VNx4BImode ; } else if ( size == 16 ) { unspec = UNSPEC_REV16 ; pred_mode = VNx8BImode ; } else return false ; unsigned int step = diff + 1 ; for ( i = 0 ; i < step ; ++ i ) if ( ! d -> perm . series_p ( i , step , diff - i , step ) ) return false ; if ( d -> testing_p ) return true ; if ( d -> vec_flags & VEC_SVE_DATA ) { rtx pred = aarch64_ptrue_reg ( pred_mode ) ; emit_insn ( gen_aarch64_sve_revbhw ( d -> vmode , pred_mode , d -> target , pred , d -> op0 ) ) ; return true ; } rtx src = gen_rtx_UNSPEC ( d -> vmode , gen_rtvec ( 1 , d -> op0 ) , unspec ) ; emit_set_insn ( d -> target , src ) ; return true ; } </s>

Recognize patterns for the REV { 64,32,16 } insns , which reverse elements within each 64-bit , 32-bit or 16-bit granule .


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


Expand setmem , as if from a __builtin_memset . Return true if we succeed , otherwise return false .


<s> static rtx aarch64_expand_sve_const_pred_trn ( rtx target , rtx_vector_builder & builder , unsigned int elt_size , unsigned int permute_size ) { unsigned int a_elt_size = GET_MODE_SIZE ( DImode ) ; unsigned int b_elt_size = GET_MODE_SIZE ( DImode ) ; for ( unsigned int i = 0 ; i < builder . encoded_nelts ( ) ; i += elt_size ) if ( INTVAL ( builder . elt ( i ) ) != 0 ) { if ( i & permute_size ) b_elt_size |= i - permute_size ; else a_elt_size |= i ; } a_elt_size &= - a_elt_size ; b_elt_size &= - b_elt_size ; rtx_vector_builder a_builder ( VNx16BImode , builder . npatterns ( ) , builder . nelts_per_pattern ( ) ) ; rtx_vector_builder b_builder ( VNx16BImode , builder . npatterns ( ) , builder . nelts_per_pattern ( ) ) ; unsigned int nelts = builder . encoded_nelts ( ) ; for ( unsigned int i = 0 ; i < nelts ; ++ i ) if ( i & ( elt_size - 1 ) ) { a_builder . quick_push ( const0_rtx ) ; b_builder . quick_push ( const0_rtx ) ; } else if ( ( i & permute_size ) == 0 ) { a_builder . quick_push ( builder . elt ( i ) ) ; b_builder . quick_push ( builder . elt ( i + permute_size ) ) ; } else { if ( a_elt_size > permute_size ) a_builder . quick_push ( const0_rtx ) ; else a_builder . quick_push ( a_builder . elt ( i - a_elt_size ) ) ; if ( b_elt_size > permute_size ) b_builder . quick_push ( const0_rtx ) ; else b_builder . quick_push ( b_builder . elt ( i - b_elt_size ) ) ; } a_builder . finalize ( ) ; b_builder . finalize ( ) ; rtx_insn * last = get_last_insn ( ) ; rtx a = aarch64_expand_sve_const_pred_1 ( NULL_RTX , a_builder , false ) ; if ( ! a ) return NULL_RTX ; rtx b = a ; if ( a_builder != b_builder ) { b = aarch64_expand_sve_const_pred_1 ( NULL_RTX , b_builder , false ) ; if ( ! b ) { delete_insns_since ( last ) ; return NULL_RTX ; } } machine_mode mode = aarch64_sve_pred_mode ( permute_size ) . require ( ) ; target = aarch64_target_reg ( target , GET_MODE ( a ) ) ; rtx type_reg = CONST0_RTX ( mode ) ; emit_insn ( gen_aarch64_sve_trn1_conv ( mode , target , a , b , type_reg ) ) ; return target ; } </s>

BUILDER is a constant predicate in which the index of every set bit is a multiple of ELT_SIZE ( which is < = 8 ) . Try to load the constant using a TRN1 of size PERMUTE_SIZE , which is > = ELT_SIZE . Return the register on success , otherwise return null . Use TARGET as the register if nonnull and convenient .


<s> static rtx aarch64_expand_sve_const_vector_sel ( rtx target , rtx src ) { gcc_assert ( CONST_VECTOR_NELTS_PER_PATTERN ( src ) == 2 ) ; machine_mode mode = GET_MODE ( src ) ; machine_mode pred_mode = aarch64_sve_pred_mode ( mode ) ; unsigned int npatterns = CONST_VECTOR_NPATTERNS ( src ) ; if ( aarch64_svpattern_for_vl ( pred_mode , npatterns ) == AARCH64_NUM_SVPATTERNS ) return NULL_RTX ; rtx_vector_builder pred_builder ( pred_mode , npatterns , 2 ) ; rtx_vector_builder true_builder ( mode , npatterns , 1 ) ; rtx_vector_builder false_builder ( mode , npatterns , 1 ) ; for ( unsigned int i = 0 ; i < npatterns ; ++ i ) { true_builder . quick_push ( CONST_VECTOR_ENCODED_ELT ( src , i ) ) ; pred_builder . quick_push ( CONST1_RTX ( BImode ) ) ; } for ( unsigned int i = 0 ; i < npatterns ; ++ i ) { false_builder . quick_push ( CONST_VECTOR_ENCODED_ELT ( src , i + npatterns ) ) ; pred_builder . quick_push ( CONST0_RTX ( BImode ) ) ; } expand_operand ops [ 4 ] ; create_output_operand ( & ops [ 0 ] , target , mode ) ; create_input_operand ( & ops [ 1 ] , true_builder . build ( ) , mode ) ; create_input_operand ( & ops [ 2 ] , false_builder . build ( ) , mode ) ; create_input_operand ( & ops [ 3 ] , pred_builder . build ( ) , pred_mode ) ; expand_insn ( code_for_vcond_mask ( mode , mode ) , 4 , ops ) ; return target ; } </s>

SRC is an SVE CONST_VECTOR that contains N `` foreground '' values followed by N `` background '' values . Try to move it into TARGET using : PTRUE PRED. < T > , VL < N > MOV TRUE. < T > , # < foreground > MOV FALSE. < T > , # < background > SEL TARGET. < T > , PRED. < T > , TRUE. < T > , FALSE. < T > The PTRUE is always a single instruction but the MOVs might need a longer sequence . If the background value is zero ( as it often is ) , the sequence can sometimes collapse to a PTRUE followed by a zero-predicated move . Return the target on success , otherwise return null .


<s> static bool aarch64_extending_load_p ( class vec_info * vinfo , stmt_vec_info stmt_info ) { gassign * assign = dyn_cast < gassign * > ( stmt_info -> stmt ) ; if ( ! assign || ! CONVERT_EXPR_CODE_P ( gimple_assign_rhs_code ( assign ) ) ) return false ; tree rhs = gimple_assign_rhs1 ( stmt_info -> stmt ) ; tree lhs_type = TREE_TYPE ( gimple_assign_lhs ( assign ) ) ; tree rhs_type = TREE_TYPE ( rhs ) ; if ( ! INTEGRAL_TYPE_P ( lhs_type ) || ! INTEGRAL_TYPE_P ( rhs_type ) || TYPE_PRECISION ( lhs_type ) <= TYPE_PRECISION ( rhs_type ) ) return false ; stmt_vec_info def_stmt_info = vinfo -> lookup_def ( rhs ) ; return ( def_stmt_info && STMT_VINFO_DATA_REF ( def_stmt_info ) && DR_IS_READ ( STMT_VINFO_DATA_REF ( def_stmt_info ) ) ) ; } </s>

Return true if STMT_INFO extends the result of a load .


<s> static void aarch64_finish_cost ( void * data , unsigned * prologue_cost , unsigned * body_cost , unsigned * epilogue_cost ) { auto * costs = static_cast < aarch64_vector_costs * > ( data ) ; * prologue_cost = costs -> region [ vect_prologue ] ; * body_cost = costs -> region [ vect_body ] ; * epilogue_cost = costs -> region [ vect_epilogue ] ; if ( costs -> is_loop && costs -> vec_flags && aarch64_use_new_vector_costs_p ( ) ) * body_cost = aarch64_adjust_body_cost ( costs , * body_cost ) ; } </s>


<s> bool aarch64_float_const_rtx_p ( rtx x ) { machine_mode mode = GET_MODE ( x ) ; if ( mode == VOIDmode ) return false ; unsigned HOST_WIDE_INT ival ; if ( CONST_DOUBLE_P ( x ) && SCALAR_FLOAT_MODE_P ( mode ) && aarch64_reinterpret_float_as_int ( x , & ival ) ) { scalar_int_mode imode = ( mode == HFmode ? SImode : int_mode_for_mode ( mode ) . require ( ) ) ; int num_instr = aarch64_internal_mov_immediate ( NULL_RTX , gen_int_mode ( ival , imode ) , false , imode ) ; return num_instr < 3 ; } return false ; } </s>

Return TRUE if rtx X is an immediate constant that can be moved using a single MOV ( +MOVK ) followed by an FMOV .


<s> static unsigned int aarch64_function_arg_alignment ( machine_mode mode , const_tree type , unsigned int * abi_break ) { * abi_break = 0 ; if ( ! type ) return GET_MODE_ALIGNMENT ( mode ) ; if ( integer_zerop ( TYPE_SIZE ( type ) ) ) return 0 ; gcc_assert ( TYPE_MODE ( type ) == mode ) ; if ( ! AGGREGATE_TYPE_P ( type ) ) return TYPE_ALIGN ( TYPE_MAIN_VARIANT ( type ) ) ; if ( TREE_CODE ( type ) == ARRAY_TYPE ) return TYPE_ALIGN ( TREE_TYPE ( type ) ) ; unsigned int alignment = 0 ; unsigned int bitfield_alignment = 0 ; for ( tree field = TYPE_FIELDS ( type ) ; field ; field = DECL_CHAIN ( field ) ) if ( TREE_CODE ( field ) == FIELD_DECL ) { alignment = std :: max ( alignment , DECL_ALIGN ( field ) ) ; if ( DECL_BIT_FIELD_TYPE ( field ) ) bitfield_alignment = std :: max ( bitfield_alignment , TYPE_ALIGN ( DECL_BIT_FIELD_TYPE ( field ) ) ) ; } if ( bitfield_alignment > alignment ) { * abi_break = alignment ; return bitfield_alignment ; } return alignment ; } </s>

Given MODE and TYPE of a function argument , return the alignment in bits . The idea is to suppress any stronger alignment requested by the user and opt for the natural alignment ( specified in AAPCS64 \S 4.1 ) . This is a helper function for local use only .


"parameter passing for argument of type "

Implement FUNCTION_ARG_BOUNDARY . Every parameter gets at least PARM_BOUNDARY bits of alignment , but will be given anything up to STACK_BOUNDARY bits if the type requires it . This makes sure that both before and after the layout of each argument , the Next Stacked Argument Address ( NSAA ) will have a minimum alignment of 8 bytes .


<s> static rtx aarch64_gen_load_pair ( machine_mode mode , rtx reg1 , rtx mem1 , rtx reg2 , rtx mem2 ) { switch ( mode ) { case E_DImode : return gen_load_pair_dw_didi ( reg1 , mem1 , reg2 , mem2 ) ; case E_DFmode : return gen_load_pair_dw_dfdf ( reg1 , mem1 , reg2 , mem2 ) ; case E_TFmode : return gen_load_pair_dw_tftf ( reg1 , mem1 , reg2 , mem2 ) ; case E_V4SImode : return gen_load_pairv4siv4si ( reg1 , mem1 , reg2 , mem2 ) ; default : gcc_unreachable ( ) ; } } </s>

Generate and regurn a load pair isntruction of mode MODE to load register REG1 from MEM1 and register REG2 from MEM2 .


Generate and return a store pair instruction of mode MODE to store register REG1 to MEM1 and register REG2 to MEM2 .


<s> bool aarch64_harden_sls_blr_p ( void ) { return aarch64_sls_hardening & SLS_BLR ; } </s>

Return whether we should mitigatate Straight Line Speculation for the BLR instruction .


<s> bool aarch64_harden_sls_retbr_p ( void ) { return aarch64_sls_hardening & SLS_RETBR ; } </s>

Return whether we should mitigatate Straight Line Speculation for the RET and BR instructions .


<s> static void aarch64_init_builtins ( ) { aarch64_general_init_builtins ( ) ; aarch64_sve :: init_builtins ( ) ; SUBTARGET_INIT_BUILTINS ; } </s>


<s> void * aarch64_init_cost ( class loop * ) { return new aarch64_vector_costs ; } </s>


<s> static unsigned int aarch64_in_loop_reduction_latency ( vec_info * vinfo , stmt_vec_info stmt_info , tree vectype , unsigned int vec_flags ) { const cpu_vector_cost * vec_costs = aarch64_tune_params . vec_costs ; const sve_vec_cost * sve_costs = nullptr ; if ( vec_flags & VEC_ANY_SVE ) sve_costs = aarch64_tune_params . vec_costs -> sve ; if ( sve_costs ) { unsigned int latency = aarch64_sve_in_loop_reduction_latency ( vinfo , stmt_info , vectype , sve_costs ) ; if ( latency ) return latency ; } if ( vec_flags == 0 ) { if ( FLOAT_TYPE_P ( vectype ) ) return vec_costs -> scalar_fp_stmt_cost ; return vec_costs -> scalar_int_stmt_cost ; } const simd_vec_cost * simd_costs = aarch64_simd_vec_costs_for_flags ( vec_flags ) ; if ( FLOAT_TYPE_P ( vectype ) ) return simd_costs -> fp_stmt_cost ; return simd_costs -> int_stmt_cost ; } </s>

STMT_INFO describes a loop-carried operation in the original scalar code that we are considering implementing as a reduction . Return one of the following values , depending on VEC_FLAGS : - If VEC_FLAGS is zero , return the loop carry latency of the original scalar operation . - If VEC_FLAGS & VEC_ADVSIMD , return the loop carry latency of the the Advanced SIMD implementation . - If VEC_FLAGS & VEC_ANY_SVE , return the loop carry latency of the SVE implementation . VECTYPE is the type of vector that the vectorizer is considering using for STMT_INFO , which might be different from the type of vector described by VEC_FLAGS .


<s> static bool aarch64_is_reduction ( stmt_vec_info stmt_info ) { return ( STMT_VINFO_REDUC_DEF ( stmt_info ) || VECTORIZABLE_CYCLE_DEF ( STMT_VINFO_DEF_TYPE ( stmt_info ) ) ) ; } </s>

Return true if STMT_INFO represents part of a reduction .


<s> static int aarch64_ld234_st234_vectors ( vect_cost_for_stmt kind , stmt_vec_info stmt_info ) { if ( ( kind == vector_load || kind == unaligned_load || kind == vector_store || kind == unaligned_store ) && STMT_VINFO_DATA_REF ( stmt_info ) ) { stmt_info = DR_GROUP_FIRST_ELEMENT ( stmt_info ) ; if ( stmt_info && STMT_VINFO_MEMORY_ACCESS_TYPE ( stmt_info ) == VMAT_LOAD_STORE_LANES ) return DR_GROUP_SIZE ( stmt_info ) ; } return 0 ; } </s>

Return true if an access of kind KIND for STMT_INFO represents one vector of an LD [ 234 ] or ST [ 234 ] operation . Return the total number of vectors ( 2 , 3 or 4 ) if so , otherwise return a value outside that range .


<s> static bool aarch64_legitimate_constant_p ( machine_mode mode , rtx x ) { if ( CONST_INT_P ( x ) || ( CONST_DOUBLE_P ( x ) && GET_MODE_CLASS ( mode ) == MODE_FLOAT ) ) return true ; if ( ! GET_MODE_SIZE ( mode ) . is_constant ( ) ) return aarch64_simd_valid_immediate ( x , NULL ) ; if ( GET_CODE ( x ) == CONST_VECTOR ) return ! targetm . cannot_force_const_mem ( mode , x ) ; unsigned int vec_flags = aarch64_classify_vector_mode ( mode ) ; if ( vec_flags == ( VEC_ADVSIMD | VEC_STRUCT ) ) return false ; if ( GET_CODE ( x ) == HIGH ) x = XEXP ( x , 0 ) ; poly_int64 offset ; if ( poly_int_rtx_p ( x , & offset ) ) return aarch64_offset_temporaries ( false , offset ) <= 1 ; x = strip_offset_and_salt ( x , & offset ) ; if ( ! offset . is_constant ( ) && aarch64_offset_temporaries ( true , offset ) > 0 ) return false ; if ( maybe_ne ( offset , 0 ) && SYMBOL_REF_P ( x ) && SYMBOL_REF_ANCHOR_P ( x ) ) return false ; if ( SYMBOL_REF_P ( x ) && ! SYMBOL_REF_TLS_MODEL ( x ) ) return true ; if ( LABEL_REF_P ( x ) ) return true ; return false ; } </s>

Implement TARGET_LEGITIMATE_CONSTANT_P hook . Return true for constants that should be rematerialized rather than spilled .


<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 ( mask ) > 0 && UINTVAL ( shft_amnt ) < GET_MODE_BITSIZE ( mode ) && exact_log2 ( ( UINTVAL ( mask ) >> UINTVAL ( shft_amnt ) ) + 1 ) >= 0 && ( UINTVAL ( mask ) & ( ( HOST_WIDE_INT_1U << UINTVAL ( 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> bool aarch64_mov128_immediate ( rtx imm ) { if ( CONST_INT_P ( imm ) ) return true ; gcc_assert ( CONST_WIDE_INT_NUNITS ( imm ) == 2 ) ; rtx lo = GEN_INT ( CONST_WIDE_INT_ELT ( imm , 0 ) ) ; rtx hi = GEN_INT ( CONST_WIDE_INT_ELT ( imm , 1 ) ) ; return aarch64_internal_mov_immediate ( NULL_RTX , lo , false , DImode ) + aarch64_internal_mov_immediate ( NULL_RTX , hi , false , DImode ) <= 4 ; } </s>

Return whether imm is a 128-bit immediate which is simple enough to expand inline .


<s> static bool aarch64_multiply_add_p ( vec_info * vinfo , stmt_vec_info stmt_info ) { gassign * assign = dyn_cast < gassign * > ( stmt_info -> stmt ) ; if ( ! assign ) return false ; tree_code code = gimple_assign_rhs_code ( assign ) ; if ( code != PLUS_EXPR && code != MINUS_EXPR ) return false ; if ( CONSTANT_CLASS_P ( gimple_assign_rhs1 ( assign ) ) || CONSTANT_CLASS_P ( gimple_assign_rhs2 ( assign ) ) ) return false ; for ( int i = 1 ; i < 3 ; ++ i ) { tree rhs = gimple_op ( assign , i ) ; if ( TREE_CODE ( rhs ) != SSA_NAME ) continue ; stmt_vec_info def_stmt_info = vinfo -> lookup_def ( rhs ) ; if ( ! def_stmt_info || STMT_VINFO_DEF_TYPE ( def_stmt_info ) != vect_internal_def ) continue ; gassign * rhs_assign = dyn_cast < gassign * > ( def_stmt_info -> stmt ) ; if ( ! rhs_assign || gimple_assign_rhs_code ( rhs_assign ) != MULT_EXPR ) continue ; return true ; } return false ; } </s>

Return true if STMT_INFO is the second part of a two-statement multiply-add or multiply-subtract sequence that might be suitable for fusing into a single instruction .


<s> static char * aarch64_offload_options ( void ) { if ( TARGET_ILP32 ) return xstrdup ( "-foffload-abi=ilp32" ) ; else return xstrdup ( "-foffload-abi=lp64" ) ; } </s>

Implement the TARGET_OFFLOAD_OPTIONS hook .


<s> static void aarch64_option_restore ( struct gcc_options * opts , struct gcc_options * , struct cl_target_option * ptr ) { opts -> x_explicit_arch = ptr -> x_explicit_arch ; selected_arch = aarch64_get_arch ( ptr -> x_explicit_arch ) ; opts -> x_explicit_tune_core = ptr -> x_explicit_tune_core ; if ( opts -> x_explicit_tune_core == aarch64_none && opts -> x_explicit_arch != aarch64_no_arch ) selected_tune = & all_cores [ selected_arch -> ident ] ; else selected_tune = aarch64_get_tune_cpu ( ptr -> x_explicit_tune_core ) ; opts -> x_aarch64_override_tune_string = ptr -> x_aarch64_override_tune_string ; opts -> x_aarch64_branch_protection_string = ptr -> x_aarch64_branch_protection_string ; if ( opts -> x_aarch64_branch_protection_string ) { aarch64_parse_branch_protection ( opts -> x_aarch64_branch_protection_string , NULL ) ; } aarch64_override_options_internal ( opts ) ; } </s>

Implements TARGET_OPTION_RESTORE . Restore the backend codegen decisions using the information saved in PTR .


<s> static void aarch64_option_save ( struct cl_target_option * ptr , struct gcc_options * opts , struct gcc_options * ) { ptr -> x_aarch64_override_tune_string = opts -> x_aarch64_override_tune_string ; ptr -> x_aarch64_branch_protection_string = opts -> x_aarch64_branch_protection_string ; } </s>


<s> static bool aarch64_option_valid_attribute_p ( tree fndecl , tree , tree args , int ) { struct cl_target_option cur_target ; bool ret ; tree old_optimize ; tree new_target , new_optimize ; tree existing_target = DECL_FUNCTION_SPECIFIC_TARGET ( fndecl ) ; if ( ! existing_target && args == current_target_pragma ) { DECL_FUNCTION_SPECIFIC_TARGET ( fndecl ) = target_option_current_node ; return true ; } tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION ( fndecl ) ; old_optimize = build_optimization_node ( & global_options , & global_options_set ) ; func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION ( fndecl ) ; if ( func_optimize && func_optimize != old_optimize ) cl_optimization_restore ( & global_options , & global_options_set , TREE_OPTIMIZATION ( func_optimize ) ) ; cl_target_option_save ( & cur_target , & global_options , & global_options_set ) ; if ( existing_target ) { struct cl_target_option * existing_options = TREE_TARGET_OPTION ( existing_target ) ; if ( existing_options ) cl_target_option_restore ( & global_options , & global_options_set , existing_options ) ; } else cl_target_option_restore ( & global_options , & global_options_set , TREE_TARGET_OPTION ( target_option_current_node ) ) ; ret = aarch64_process_target_attr ( args ) ; if ( ret ) { aarch64_override_options_internal ( & global_options ) ; if ( TARGET_SIMD ) { tree saved_current_target_pragma = current_target_pragma ; current_target_pragma = NULL ; aarch64_init_simd_builtins ( ) ; current_target_pragma = saved_current_target_pragma ; } new_target = build_target_option_node ( & global_options , & global_options_set ) ; } else new_target = NULL ; new_optimize = build_optimization_node ( & global_options , & global_options_set ) ; if ( fndecl && ret ) { DECL_FUNCTION_SPECIFIC_TARGET ( fndecl ) = new_target ; if ( old_optimize != new_optimize ) DECL_FUNCTION_SPECIFIC_OPTIMIZATION ( fndecl ) = new_optimize ; } cl_target_option_restore ( & global_options , & global_options_set , & cur_target ) ; if ( old_optimize != new_optimize ) cl_optimization_restore ( & global_options , & global_options_set , TREE_OPTIMIZATION ( old_optimize ) ) ; return ret ; } </s>

Implement TARGET_OPTION_VALID_ATTRIBUTE_P . This is used to process attribute ( ( target ( `` ... '' ) ) ) .


<s> static bool aarch64_output_addr_const_extra ( FILE * file , rtx x ) { if ( GET_CODE ( x ) == UNSPEC && XINT ( x , 1 ) == UNSPEC_SALT_ADDR ) { output_addr_const ( file , XVECEXP ( x , 0 , 0 ) ) ; return true ; } return false ; } </s>


"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 machine_mode aarch64_preferred_simd_mode ( scalar_mode mode ) { if ( TARGET_SVE && aarch64_cmp_autovec_modes ( VNx16QImode , V16QImode ) ) return aarch64_full_sve_mode ( mode ) . else_mode ( word_mode ) ; if ( TARGET_SIMD ) return aarch64_vq_mode ( mode ) . else_mode ( word_mode ) ; return word_mode ; } </s>

Return 128-bit container as the preferred SIMD mode for MODE .


Decide whether to use the unrolling heuristic described above aarch64_vector_costs : :unrolled_advsimd_niters , updating that field if so . LOOP_VINFO describes the loop that we 're vectorizing and COSTS are the costs that we 're calculating for it .


<s> static int aarch64_reduc_type ( vec_info * vinfo , stmt_vec_info stmt_info ) { if ( loop_vec_info loop_vinfo = dyn_cast < loop_vec_info > ( vinfo ) ) if ( STMT_VINFO_REDUC_DEF ( stmt_info ) ) { stmt_vec_info reduc_info = info_for_reduction ( loop_vinfo , stmt_info ) ; return int ( STMT_VINFO_REDUC_TYPE ( reduc_info ) ) ; } return - 1 ; } </s>

If STMT_INFO describes a reduction , return the type of reduction it describes , otherwise return -1 .


<s> enum reg_class aarch64_regno_regclass ( unsigned regno ) { if ( STUB_REGNUM_P ( regno ) ) return STUB_REGS ; 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_LO8_REGNUM_P ( regno ) ? FP_LO8_REGS : 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 ; if ( regno == FFR_REGNUM || regno == FFRT_REGNUM ) return FFR_REGS ; return NO_REGS ; } </s>


<s> bool aarch64_reinterpret_float_as_int ( rtx value , unsigned HOST_WIDE_INT * intval ) { if ( aarch64_float_const_zero_rtx_p ( value ) ) { * intval = 0 ; return true ; } scalar_float_mode mode ; if ( ! CONST_DOUBLE_P ( value ) || ! is_a < scalar_float_mode > ( GET_MODE ( value ) , & mode ) || GET_MODE_BITSIZE ( mode ) > HOST_BITS_PER_WIDE_INT || GET_MODE_BITSIZE ( mode ) > GET_MODE_BITSIZE ( DFmode ) ) return false ; unsigned HOST_WIDE_INT ival = 0 ; long res [ 2 ] ; real_to_target ( res , CONST_DOUBLE_REAL_VALUE ( value ) , REAL_MODE_FORMAT ( mode ) ) ; if ( mode == DFmode ) { int order = BYTES_BIG_ENDIAN ? 1 : 0 ; ival = zext_hwi ( res [ order ] , 32 ) ; ival |= ( zext_hwi ( res [ 1 - order ] , 32 ) << 32 ) ; } else ival = zext_hwi ( res [ 0 ] , 32 ) ; * intval = ival ; return true ; } </s>

Return the binary representation of floating point constant VALUE in INTVAL . If the value can not be converted , return false without setting INTVAL . The conversion is done in the given MODE .


<s> rtx aarch64_return_addr ( int count , rtx frame ATTRIBUTE_UNUSED ) { if ( count != 0 ) return const0_rtx ; return aarch64_return_addr_rtx ( ) ; } </s>

Implement RETURN_ADDR_RTX . We do not support moving back to a previous frame .


<s> bool aarch64_return_address_signing_enabled ( void ) { gcc_assert ( cfun -> machine -> frame . laid_out ) ; if ( crtl -> calls_eh_return ) return false ; return ( aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL || ( aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF && known_ge ( cfun -> machine -> frame . reg_offset [ LR_REGNUM ] , 0 ) ) ) ; } </s>

Return TRUE if return address signing should be enabled for the current function , otherwise return FALSE .


<s> rtx aarch64_return_addr_rtx ( void ) { rtx val = get_hard_reg_initial_val ( Pmode , LR_REGNUM ) ; rtx lr = gen_rtx_REG ( Pmode , LR_REGNUM ) ; emit_move_insn ( lr , val ) ; emit_insn ( GEN_FCN ( CODE_FOR_xpaclri ) ( ) ) ; return lr ; } </s>


<s> static bool aarch64_rtx_arith_op_extract_p ( rtx x ) { if ( GET_CODE ( x ) == SIGN_EXTEND || GET_CODE ( x ) == ZERO_EXTEND ) return REG_P ( XEXP ( x , 0 ) ) ; return false ; } </s>

Return true if X is a zero or sign extract usable in an ADD or SUB ( extended register ) instruction .


<s> static void aarch64_set_current_function ( tree fndecl ) { if ( ! fndecl || fndecl == aarch64_previous_fndecl ) return ; tree old_tree = ( aarch64_previous_fndecl ? DECL_FUNCTION_SPECIFIC_TARGET ( aarch64_previous_fndecl ) : NULL_TREE ) ; tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET ( fndecl ) ; if ( ! new_tree && old_tree ) new_tree = target_option_default_node ; if ( old_tree == new_tree ) return ; aarch64_previous_fndecl = fndecl ; cl_target_option_restore ( & global_options , & global_options_set , TREE_TARGET_OPTION ( new_tree ) ) ; aarch64_save_restore_target_globals ( new_tree ) ; } </s>

Implement TARGET_SET_CURRENT_FUNCTION . Unpack the codegen decisions like tuning and ISA features from the DECL_FUNCTION_SPECIFIC_TARGET of the function , if such exists . This function may be called multiple times on a single function so use aarch64_previous_fndecl to avoid setting up identical state .


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 .


"GCC does not currently support mixed size types "

"GCC does not currently support return type %qT "

"unsupported return type %qT for %<simd%> functions"

"GCC does not currently support argument type %qT "

"GCC does not currently support simdlen %wd for type %qT"


<s> static const simd_vec_cost * aarch64_simd_vec_costs ( tree vectype ) { const cpu_vector_cost * costs = aarch64_tune_params . vec_costs ; if ( vectype != NULL && aarch64_sve_mode_p ( TYPE_MODE ( vectype ) ) && costs -> sve != NULL ) return costs -> sve ; return costs -> advsimd ; } </s>

Return the appropriate SIMD costs for vectors of type VECTYPE .


<s> static const simd_vec_cost * aarch64_simd_vec_costs_for_flags ( unsigned int flags ) { const cpu_vector_cost * costs = aarch64_tune_params . vec_costs ; if ( ( flags & VEC_ANY_SVE ) && costs -> sve ) return costs -> sve ; return costs -> advsimd ; } </s>

Return the appropriate SIMD costs for vectors with VEC_ * flags FLAGS .


<s> const char * aarch64_sls_barrier ( int mitigation_required ) { return mitigation_required ? ( TARGET_SB ? "sb" : "dsb\tsy\n\tisb" ) : "" ; } </s>

Helper function for straight line speculation . Return what barrier should be emitted for straight line speculation mitigation . When not mitigating against straight line speculation this function returns an empty string . When mitigating against straight line speculation , use : * SB when the v8.5-A SB extension is enabled . * DSB+ISB otherwise .


<s> rtx aarch64_sls_create_blr_label ( int regnum ) { gcc_assert ( STUB_REGNUM_P ( regnum ) ) ; if ( optimize_function_for_size_p ( cfun ) ) { aarch64_sls_shared_thunks_needed = true ; const char * thunk_name = indirect_symbol_names [ regnum ] ; if ( aarch64_sls_shared_thunks [ regnum ] == NULL ) { tree decl = build_decl ( BUILTINS_LOCATION , FUNCTION_DECL , get_identifier ( thunk_name ) , build_function_type_list ( void_type_node , NULL_TREE ) ) ; DECL_RESULT ( decl ) = build_decl ( BUILTINS_LOCATION , RESULT_DECL , NULL_TREE , void_type_node ) ; TREE_PUBLIC ( decl ) = 1 ; TREE_STATIC ( decl ) = 1 ; DECL_IGNORED_P ( decl ) = 1 ; DECL_ARTIFICIAL ( decl ) = 1 ; make_decl_one_only ( decl , DECL_ASSEMBLER_NAME ( decl ) ) ; resolve_unique_section ( decl , 0 , false ) ; aarch64_sls_shared_thunks [ regnum ] = decl ; } return gen_rtx_SYMBOL_REF ( Pmode , thunk_name ) ; } if ( cfun -> machine -> call_via [ regnum ] == NULL ) cfun -> machine -> call_via [ regnum ] = gen_rtx_LABEL_REF ( Pmode , gen_label_rtx ( ) ) ; return cfun -> machine -> call_via [ regnum ] ; } </s>

Function to create a BLR thunk . This thunk is used to mitigate straight line speculation . Instead of a simple BLR that can be speculated past , we emit a BL to this thunk , and this thunk contains a BR to the relevant register . These thunks have the relevant speculation barries put after their indirect branch so that speculation is blocked . We use such a thunk so the speculation barriers are kept off the architecturally executed path in order to reduce the performance overhead . When optimizing for size we use stubs shared by the linked object . When optimizing for performance we emit stubs for each function in the hope that the branch predictor can better train on jumps specific for a given function .


<s> void aarch64_sls_emit_blr_function_thunks ( FILE * out_file ) { if ( ! aarch64_harden_sls_blr_p ( ) ) return ; bool any_functions_emitted = false ; section * save_text_section = in_section ; switch_to_section ( function_section ( current_function_decl ) ) ; for ( int regnum = 0 ; regnum < 30 ; ++ regnum ) { rtx specu_label = cfun -> machine -> call_via [ regnum ] ; if ( specu_label == NULL ) continue ; targetm . asm_out . print_operand ( out_file , specu_label , 0 ) ; asm_fprintf ( out_file , ":\n" ) ; aarch64_sls_emit_function_stub ( out_file , regnum ) ; any_functions_emitted = true ; } if ( any_functions_emitted ) asm_fprintf ( out_file , "\t%s\n" , aarch64_sls_barrier ( true ) ) ; switch_to_section ( save_text_section ) ; } </s>

Emit all BLR stubs for this particular function . Here we emit all the BLR stubs needed for the current function . Since we emit these stubs in a consecutive block we know there will be no speculation gadgets between each stub , and hence we only emit a speculation barrier at the end of the stub sequences . This is called in the TARGET_ASM_FUNCTION_EPILOGUE hook .


<s>
static
void
aarch64_sls_emit_function_stub
(
FILE
*
out_file
,
int
regnum
)
{
asm_fprintf
(
out_file
,
"\tmov\tx16, x%d\n"
,
regnum
)
;
asm_fprintf
(
out_file
,
"\tbr\tx16\n"
)
;
}
</s>

Helper function for aarch64_sls_emit_blr_function_thunks and aarch64_sls_emit_shared_blr_thunks below .


<s> void aarch64_sls_emit_shared_blr_thunks ( FILE * out_file ) { if ( ! aarch64_sls_shared_thunks_needed ) return ; for ( int regnum = 0 ; regnum < 30 ; ++ regnum ) { tree decl = aarch64_sls_shared_thunks [ regnum ] ; if ( ! decl ) continue ; const char * name = indirect_symbol_names [ regnum ] ; switch_to_section ( get_named_section ( decl , NULL , 0 ) ) ; ASM_OUTPUT_ALIGN ( out_file , 2 ) ; targetm . asm_out . globalize_label ( out_file , name ) ; targetm . asm_out . assemble_visibility ( decl , VISIBILITY_HIDDEN ) ; ASM_OUTPUT_TYPE_DIRECTIVE ( out_file , name , "function" ) ; ASM_OUTPUT_LABEL ( out_file , name ) ; aarch64_sls_emit_function_stub ( out_file , regnum ) ; asm_fprintf ( out_file , "\tdsb\tsy\n\tisb\n" ) ; ASM_DECLARE_FUNCTION_SIZE ( out_file , name , decl ) ; } } </s>

Emit shared BLR stubs for the current compilation unit . Over the course of compiling this unit we may have converted some BLR instructions to a BL to a shared stub function . This is where we emit those stub functions . This function is for the stubs shared between different functions in this compilation unit . We share when optimizing for size instead of speed . This function is called through the TARGET_ASM_FILE_END hook .


<s> bool aarch64_split_128bit_move_p ( rtx dst , rtx src ) { if ( FP_REGNUM_P ( REGNO ( dst ) ) ) return REG_P ( src ) && ! FP_REGNUM_P ( REGNO ( src ) ) ; return true ; } </s>

Return true if we should split a move from 128-bit value SRC to 128-bit register DEST .


<s> rtx aarch64_stack_protect_canary_mem ( machine_mode mode , rtx decl_rtl , aarch64_salt_type salt_type ) { rtx addr ; if ( aarch64_stack_protector_guard == SSP_GLOBAL ) { gcc_assert ( MEM_P ( decl_rtl ) ) ; addr = XEXP ( decl_rtl , 0 ) ; poly_int64 offset ; rtx base = strip_offset_and_salt ( addr , & offset ) ; if ( ! SYMBOL_REF_P ( base ) ) return decl_rtl ; rtvec v = gen_rtvec ( 2 , base , GEN_INT ( salt_type ) ) ; addr = gen_rtx_UNSPEC ( Pmode , v , UNSPEC_SALT_ADDR ) ; addr = gen_rtx_CONST ( Pmode , addr ) ; addr = plus_constant ( Pmode , addr , offset ) ; } else { rtx salt = GEN_INT ( salt_type ) ; addr = gen_reg_rtx ( mode ) ; if ( mode == DImode ) emit_insn ( gen_reg_stack_protect_address_di ( addr , salt ) ) ; else { emit_insn ( gen_reg_stack_protect_address_si ( addr , salt ) ) ; addr = convert_memory_address ( Pmode , addr ) ; } addr = plus_constant ( Pmode , addr , aarch64_stack_protector_guard_offset ) ; } return gen_rtx_MEM ( mode , force_reg ( Pmode , addr ) ) ; } </s>

Return the MEM rtx that provides the canary value that should be used for stack-smashing protection . MODE is the mode of the memory . For SSP_GLOBAL , DECL_RTL is the MEM rtx for the canary variable ( __stack_chk_guard ) , otherwise it has no useful value . SALT_TYPE indicates whether the caller is performing a SET or a TEST operation .


<s> static rtx aarch64_strip_extend ( rtx x , bool strip_shift ) { scalar_int_mode mode ; rtx op = x ; if ( ! is_a < scalar_int_mode > ( GET_MODE ( op ) , & mode ) ) return op ; if ( GET_CODE ( op ) == AND && GET_CODE ( XEXP ( op , 0 ) ) == MULT && CONST_INT_P ( XEXP ( XEXP ( op , 0 ) , 1 ) ) && CONST_INT_P ( XEXP ( op , 1 ) ) && aarch64_uxt_size ( exact_log2 ( INTVAL ( XEXP ( XEXP ( op , 0 ) , 1 ) ) ) , INTVAL ( XEXP ( op , 1 ) ) ) != 0 ) return XEXP ( XEXP ( op , 0 ) , 0 ) ; if ( strip_shift && GET_CODE ( op ) == ASHIFT && CONST_INT_P ( XEXP ( op , 1 ) ) && ( ( unsigned HOST_WIDE_INT ) INTVAL ( XEXP ( op , 1 ) ) ) <= 4 ) op = XEXP ( op , 0 ) ; if ( GET_CODE ( op ) == ZERO_EXTEND || GET_CODE ( op ) == SIGN_EXTEND ) op = XEXP ( op , 0 ) ; if ( op != x ) return op ; return x ; } </s>

Helper function for rtx cost calculation . Strip an extend expression from X . Returns the inner operand if successful , or the original expression on failure . We deal with a number of possible canonicalization variations here .


<s> static unsigned int aarch64_sve_adjust_stmt_cost ( class vec_info * vinfo , vect_cost_for_stmt kind , stmt_vec_info stmt_info , tree vectype , unsigned int stmt_cost ) { if ( kind == vector_stmt && aarch64_extending_load_p ( vinfo , stmt_info ) ) stmt_cost = 0 ; if ( kind == vector_stmt && aarch64_integer_truncation_p ( stmt_info ) ) stmt_cost = 0 ; if ( STMT_VINFO_GROUPED_ACCESS ( stmt_info ) ) { stmt_vec_info first = DR_GROUP_FIRST_ELEMENT ( stmt_info ) ; unsigned int count = DR_GROUP_SIZE ( first ) - DR_GROUP_GAP ( first ) ; unsigned int elt_bits = GET_MODE_UNIT_BITSIZE ( TYPE_MODE ( vectype ) ) ; if ( multiple_p ( count * elt_bits , 256 ) && aarch64_advsimd_ldp_stp_p ( kind , stmt_info ) ) stmt_cost *= 2 ; } return stmt_cost ; } </s>

STMT_COST is the cost calculated by aarch64_builtin_vectorization_cost for STMT_INFO , which has cost kind KIND and which when vectorized would operate on vector type VECTYPE . Adjust the cost as necessary for SVE targets .


<s> bool aarch64_sve_float_arith_immediate_p ( rtx x , bool negate_p ) { rtx elt ; REAL_VALUE_TYPE r ; if ( ! const_vec_duplicate_p ( x , & elt ) || ! CONST_DOUBLE_P ( elt ) ) return false ; r = * CONST_DOUBLE_REAL_VALUE ( elt ) ; if ( negate_p ) r = real_value_negate ( & r ) ; if ( real_equal ( & r , & dconst1 ) ) return true ; if ( real_equal ( & r , & dconsthalf ) ) return true ; return false ; } </s>

Return true if X is a valid immediate operand for an SVE FADD or FSUB instruction . Negate X first if NEGATE_P is true .


<s> bool aarch64_sve_float_mul_immediate_p ( rtx x ) { rtx elt ; return ( const_vec_duplicate_p ( x , & elt ) && CONST_DOUBLE_P ( elt ) && ( real_equal ( CONST_DOUBLE_REAL_VALUE ( elt ) , & dconsthalf ) || real_equal ( CONST_DOUBLE_REAL_VALUE ( elt ) , & dconst2 ) ) ) ; } </s>

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


<s> static unsigned int aarch64_sve_in_loop_reduction_latency ( vec_info * vinfo , stmt_vec_info stmt_info , tree vectype , const sve_vec_cost * sve_costs ) { switch ( aarch64_reduc_type ( vinfo , stmt_info ) ) { case EXTRACT_LAST_REDUCTION : return sve_costs -> clast_cost ; case FOLD_LEFT_REDUCTION : switch ( GET_MODE_INNER ( TYPE_MODE ( vectype ) ) ) { case E_HFmode : case E_BFmode : return sve_costs -> fadda_f16_cost ; case E_SFmode : return sve_costs -> fadda_f32_cost ; case E_DFmode : return sve_costs -> fadda_f64_cost ; default : break ; } break ; } return 0 ; } </s>

We are considering implementing STMT_INFO using SVE vector type VECTYPE . If STMT_INFO is an in-loop reduction that SVE supports directly , return its latency in cycles , otherwise return zero . SVE_COSTS specifies the latencies of the relevant instructions .


<s> static bool aarch64_sve_only_stmt_p ( stmt_vec_info stmt_info , tree vectype ) { if ( ! aarch64_sve_mode_p ( TYPE_MODE ( vectype ) ) ) return false ; if ( STMT_VINFO_DATA_REF ( stmt_info ) ) { if ( STMT_VINFO_GATHER_SCATTER_P ( stmt_info ) ) return true ; if ( auto * call = dyn_cast < gcall * > ( stmt_info -> stmt ) ) if ( gimple_call_internal_p ( call ) && internal_fn_mask_index ( gimple_call_internal_fn ( call ) ) >= 0 ) return true ; } auto * assign = dyn_cast < gassign * > ( stmt_info -> stmt ) ; if ( assign && gimple_assign_rhs_code ( assign ) == MULT_EXPR && GET_MODE_INNER ( TYPE_MODE ( vectype ) ) == DImode && ! integer_pow2p ( gimple_assign_rhs2 ( assign ) ) ) return true ; return false ; } </s>

Return true if the vectorized form of STMT_INFO is something that is only possible when using SVE instead of Advanced SIMD . VECTYPE is the type of the vector that STMT_INFO is operating on .


<s> bool aarch64_sve_prefetch_operand_p ( rtx op , machine_mode mode ) { struct aarch64_address_info addr ; if ( ! aarch64_classify_address ( & addr , op , mode , false , ADDR_QUERY_ANY ) ) return false ; if ( addr . type == ADDRESS_REG_IMM ) return offset_6bit_signed_scaled_p ( mode , addr . const_offset ) ; return addr . type == ADDRESS_REG_REG ; } </s>

Return true if OP is a valid address for an SVE PRF [ BHWD ] instruction , addressing memory of mode MODE .


<s> static bool aarch64_tls_symbol_p ( rtx x ) { if ( ! TARGET_HAVE_TLS ) return false ; x = strip_salt ( x ) ; if ( ! SYMBOL_REF_P ( x ) ) return false ; return SYMBOL_REF_TLS_MODEL ( x ) != 0 ; } </s>

Return true if SYMBOL_REF X is thread local


<s> static bool aarch64_use_new_vector_costs_p ( ) { return ( aarch64_tune_params . extra_tuning_flags & AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS ) ; } </s>

Return true if the current CPU should use the new costs defined in GCC 11 . This should be removed for GCC 12 and above , with the costs applying to all CPUs instead .


"invalid argument given to %<-mharden-sls=%>"

"%<%s%> must be by itself for %<-mharden-sls=%>"

"invalid argument %<%s%> for %<-mharden-sls=%>"

As of yet we only allow setting these options globally , in the future we may allow setting them per function .


<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 ( sel . ninputs ( ) == 1 || ( 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 ? force_reg ( vmode , op0 ) : NULL_RTX ; if ( op0 == op1 ) d . op1 = d . op0 ; else d . op1 = op1 ? force_reg ( vmode , op1 ) : NULL_RTX ; 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>
void
aarch64_sve_op_count
::
dump
(
)
const
{
aarch64_vec_op_count
::
dump
(
)
;
dump_printf_loc
(
MSG_NOTE
,
vect_location
,
"  predicate operations = %d\n"
,
pred_ops
)
;
}
</s>


<s> static enum sched_fusion_type fusion_load_store ( rtx_insn * insn , rtx * base , rtx * offset ) { rtx x , dest , src ; enum sched_fusion_type fusion = SCHED_FUSION_LD ; gcc_assert ( INSN_P ( insn ) ) ; x = PATTERN ( insn ) ; if ( GET_CODE ( x ) != SET ) return SCHED_FUSION_NONE ; src = SET_SRC ( x ) ; dest = SET_DEST ( x ) ; machine_mode dest_mode = GET_MODE ( dest ) ; if ( ! aarch64_mode_valid_for_sched_fusion_p ( dest_mode ) ) return SCHED_FUSION_NONE ; if ( GET_CODE ( src ) == SIGN_EXTEND ) { fusion = SCHED_FUSION_LD_SIGN_EXTEND ; src = XEXP ( src , 0 ) ; if ( ! MEM_P ( src ) || GET_MODE ( src ) != SImode ) return SCHED_FUSION_NONE ; } else if ( GET_CODE ( src ) == ZERO_EXTEND ) { fusion = SCHED_FUSION_LD_ZERO_EXTEND ; src = XEXP ( src , 0 ) ; if ( ! MEM_P ( src ) || GET_MODE ( src ) != SImode ) return SCHED_FUSION_NONE ; } if ( MEM_P ( src ) && REG_P ( dest ) ) extract_base_offset_in_addr ( src , base , offset ) ; else if ( MEM_P ( dest ) && ( REG_P ( src ) || src == const0_rtx ) ) { fusion = SCHED_FUSION_ST ; extract_base_offset_in_addr ( dest , base , offset ) ; } else return SCHED_FUSION_NONE ; if ( * base == NULL_RTX || * offset == NULL_RTX ) fusion = SCHED_FUSION_NONE ; return fusion ; } </s>

If INSN is a load or store of address in the form of [ base+offset ] , extract the two parts and set to BASE and OFFSET . IS_LOAD is set to TRUE if it 's a load . Return TRUE if INSN is such an instruction , otherwise return FALSE .


<s> static inline bool offset_6bit_signed_scaled_p ( machine_mode mode , poly_int64 offset ) { HOST_WIDE_INT multiple ; return ( constant_multiple_p ( offset , GET_MODE_SIZE ( mode ) , & multiple ) && IN_RANGE ( multiple , - 32 , 31 ) ) ; } </s>

Return true if OFFSET is a signed 6-bit value multiplied by the size of MODE .


<s> static rtx strip_offset_and_salt ( rtx addr , poly_int64 * offset ) { return strip_salt ( strip_offset ( addr , offset ) ) ; } </s>

Like strip_offset , but also strip any UNSPEC_SALT_ADDR from the expression .


<s> static rtx strip_salt ( rtx x ) { rtx search = x ; if ( GET_CODE ( search ) == CONST ) search = XEXP ( search , 0 ) ; if ( GET_CODE ( search ) == UNSPEC && XINT ( search , 1 ) == UNSPEC_SALT_ADDR ) x = XVECEXP ( search , 0 , 0 ) ; return x ; } </s>

If X is an UNSPEC_SALT_ADDR expression , return the address that it wraps , otherwise return X itself .


<s> static enum tls_model tls_symbolic_operand_type ( rtx addr ) { enum tls_model tls_kind = TLS_MODEL_NONE ; poly_int64 offset ; addr = strip_offset_and_salt ( addr , & offset ) ; if ( SYMBOL_REF_P ( addr ) ) tls_kind = SYMBOL_REF_TLS_MODEL ( addr ) ; return tls_kind ; } </s>

Return the TLS model to use for SYMBOL .


<s> static rtx aarch64_add_offset ( machine_mode mode , rtx temp , rtx reg , HOST_WIDE_INT offset ) { if ( ! aarch64_plus_immediate ( GEN_INT ( offset ) , mode ) ) { rtx high ; high = GEN_INT ( offset ) ; offset = 0 ; high = aarch64_force_temporary ( mode , temp , high ) ; reg = aarch64_force_temporary ( mode , temp , gen_rtx_PLUS ( mode , high , reg ) ) ; } return plus_constant ( mode , reg , offset ) ; } </s>

Set DEST to SRC + 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 if ! FRAME_RELATED_P 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 . TEMP2 , if nonnull , is a second temporary register that does n't overlap either DEST or REG . 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 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 ( where == vect_body && stmt_info && stmt_in_inner_loop_p ( stmt_info ) ) { loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO ( stmt_info ) ; struct loop * loop = LOOP_VINFO_LOOP ( loop_info ) ; unsigned nest_level = loop_depth ( loop ) ; count *= nest_level ; } retval = ( unsigned ) ( count * stmt_cost ) ; cost [ where ] += retval ; } return retval ; } </s>


<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 ) && ( 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 ) { return ( HOST_WIDE_INT_1 << 36 ) ; } </s>

Implement the TARGET_ASAN_SHADOW_OFFSET hook .


<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 : 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> static unsigned int aarch64_autovectorize_vector_sizes ( void ) { return ( 16 | 8 ) ; } </s>

Return a list of possible vector sizes for the vectorizer to iterate over .


<s> static bool aarch64_base_register_rtx_p ( rtx x , bool strict_p ) { if ( ! strict_p && GET_CODE ( x ) == SUBREG ) x = SUBREG_REG ( x ) ; return ( REG_P ( x ) && aarch64_regno_ok_for_base_p ( REGNO ( x ) , strict_p ) ) ; } </s>

Return true if X is a valid base register for mode MODE . STRICT_P is true if REG_OK_STRICT is in effect .


<s> bool aarch64_bitmask_imm ( HOST_WIDE_INT val , machine_mode mode ) { if ( GET_MODE_SIZE ( mode ) < 8 ) { val &= ( HOST_WIDE_INT ) 0xffffffff ; val |= val << 32 ; } return bsearch ( & val , aarch64_bitmasks , AARCH64_NUM_BITMASKS , sizeof ( aarch64_bitmasks [ 0 ] ) , aarch64_bitmasks_cmp ) != NULL ; } </s>

Return true if val is a valid bitmask immediate .


Implement TARGET_BUILD_BUILTIN_VA_LIST . Return the type to use as __builtin_va_list . AAPCS64 \S 7.1.4 requires that va_list be a typedef for a type defined as : struct __va_list { void * __stack ; void * __gr_top ; void * __vr_top ; int __gr_offs ; int __vr_offs ; } ;


<s> static int aarch64_build_constant ( int regnum , HOST_WIDE_INT val , bool generate ) { int insns = 0 ; if ( aarch64_bitmask_imm ( val , DImode ) ) { if ( generate ) emit_move_insn ( gen_rtx_REG ( Pmode , regnum ) , GEN_INT ( val ) ) ; insns = 1 ; } else { int i ; int ncount = 0 ; int zcount = 0 ; HOST_WIDE_INT valp = val >> 16 ; HOST_WIDE_INT valm ; HOST_WIDE_INT tval ; for ( i = 16 ; i < 64 ; i += 16 ) { valm = ( valp & 0xffff ) ; if ( valm != 0 ) ++ zcount ; if ( valm != 0xffff ) ++ ncount ; valp >>= 16 ; } if ( ncount < zcount ) { if ( generate ) emit_move_insn ( gen_rtx_REG ( Pmode , regnum ) , GEN_INT ( val | ~ ( HOST_WIDE_INT ) 0xffff ) ) ; tval = 0xffff ; insns ++ ; } else { if ( generate ) emit_move_insn ( gen_rtx_REG ( Pmode , regnum ) , GEN_INT ( val & 0xffff ) ) ; tval = 0 ; insns ++ ; } val >>= 16 ; for ( i = 16 ; i < 64 ; i += 16 ) { if ( ( val & 0xffff ) != tval ) { if ( generate ) emit_insn ( gen_insv_immdi ( gen_rtx_REG ( Pmode , regnum ) , GEN_INT ( i ) , GEN_INT ( val & 0xffff ) ) ) ; insns ++ ; } val >>= 16 ; } } return insns ; } </s>

Possibly output code to build up a constant in a register . For the benefit of the costs infrastructure , returns the number of instructions which would be emitted . GENERATE inhibits or enables code generation .


<s> enum aarch64_symbol_type aarch64_classify_symbol ( rtx x , rtx offset , enum aarch64_symbol_context context ATTRIBUTE_UNUSED ) { if ( GET_CODE ( x ) == LABEL_REF ) { switch ( aarch64_cmodel ) { case AARCH64_CMODEL_LARGE : return SYMBOL_FORCE_TO_MEM ; case AARCH64_CMODEL_TINY_PIC : case AARCH64_CMODEL_TINY : return SYMBOL_TINY_ABSOLUTE ; case AARCH64_CMODEL_SMALL_PIC : case AARCH64_CMODEL_SMALL : return SYMBOL_SMALL_ABSOLUTE ; default : gcc_unreachable ( ) ; } } if ( GET_CODE ( x ) == SYMBOL_REF ) { if ( aarch64_cmodel == AARCH64_CMODEL_LARGE ) return SYMBOL_FORCE_TO_MEM ; if ( aarch64_tls_symbol_p ( x ) ) return aarch64_classify_tls_symbol ( x ) ; switch ( aarch64_cmodel ) { case AARCH64_CMODEL_TINY : if ( SYMBOL_REF_WEAK ( x ) || INTVAL ( offset ) < - 1048575 || INTVAL ( offset ) > 1048575 ) return SYMBOL_FORCE_TO_MEM ; return SYMBOL_TINY_ABSOLUTE ; case AARCH64_CMODEL_SMALL : if ( SYMBOL_REF_WEAK ( x ) || ! IN_RANGE ( INTVAL ( offset ) , HOST_WIDE_INT_C ( - 4294967263 ) , HOST_WIDE_INT_C ( 4294967264 ) ) ) return SYMBOL_FORCE_TO_MEM ; return SYMBOL_SMALL_ABSOLUTE ; case AARCH64_CMODEL_TINY_PIC : if ( ! aarch64_symbol_binds_local_p ( x ) ) return SYMBOL_TINY_GOT ; return SYMBOL_TINY_ABSOLUTE ; case AARCH64_CMODEL_SMALL_PIC : if ( ! aarch64_symbol_binds_local_p ( x ) ) return SYMBOL_SMALL_GOT ; return SYMBOL_SMALL_ABSOLUTE ; default : gcc_unreachable ( ) ; } } return SYMBOL_FORCE_TO_MEM ; } </s>

Return the method that should be used to access SYMBOL_REF or LABEL_REF X .


<s> enum aarch64_symbol_type aarch64_classify_symbolic_expression ( rtx x , enum aarch64_symbol_context context ) { rtx offset ; split_const ( x , & x , & offset ) ; return aarch64_classify_symbol ( x , offset , context ) ; } </s>

Classify the base of symbolic expression X , given that X appears in context CONTEXT .


<s> enum aarch64_symbol_type aarch64_classify_tls_symbol ( rtx x ) { enum tls_model tls_kind = tls_symbolic_operand_type ( x ) ; switch ( tls_kind ) { case TLS_MODEL_GLOBAL_DYNAMIC : case TLS_MODEL_LOCAL_DYNAMIC : return TARGET_TLS_DESC ? SYMBOL_SMALL_TLSDESC : SYMBOL_SMALL_TLSGD ; case TLS_MODEL_INITIAL_EXEC : return SYMBOL_SMALL_GOTTPREL ; case TLS_MODEL_LOCAL_EXEC : return SYMBOL_SMALL_TPREL ; case TLS_MODEL_EMULATED : case TLS_MODEL_NONE : return SYMBOL_FORCE_TO_MEM ; default : gcc_unreachable ( ) ; } } </s>

Classify a TLS symbol into one of the TLS kinds .


<s> static bool aarch64_composite_type_p ( const_tree type , machine_mode mode ) { if ( type && ( AGGREGATE_TYPE_P ( type ) || TREE_CODE ( type ) == COMPLEX_TYPE ) ) return true ; if ( mode == BLKmode || GET_MODE_CLASS ( mode ) == MODE_COMPLEX_FLOAT || GET_MODE_CLASS ( mode ) == MODE_COMPLEX_INT ) return true ; return false ; } </s>

Return TRUE if the type , as described by TYPE and MODE , is a composite type as described in AAPCS64 \S 4.3 . This includes aggregate , union and array types . The C99 floating-point complex types are also considered as composite types , according to AAPCS64 \S 7.1.1 . The complex integer types , which are GCC extensions and out of the scope of AAPCS64 , are treated as composite types here as well . Note that MODE itself is not sufficient in determining whether a type is such a composite type or not . This is because stor-layout.c : compute_record_mode may have already changed the MODE ( BLKmode ) of a RECORD_TYPE TYPE to some other mode . For example , a structure with only one field may have its MODE set to the mode of the field . Also an integer mode whose size matches the size of the RECORD_TYPE type may be used to substitute the original mode ( i.e . BLKmode ) in certain circumstances . In other words , MODE can not be solely relied on .


<s> unsigned aarch64_dbx_register_number ( unsigned regno ) { if ( GP_REGNUM_P ( regno ) ) return AARCH64_DWARF_R0 + regno - R0_REGNUM ; else if ( regno == SP_REGNUM ) return AARCH64_DWARF_SP ; else if ( FP_REGNUM_P ( regno ) ) return AARCH64_DWARF_V0 + regno - V0_REGNUM ; return DWARF_FRAME_REGISTERS ; } </s>

Provide a mapping from gcc register numbers to dwarf register numbers .


<s> static void aarch64_emit_load_exclusive ( machine_mode mode , rtx rval , rtx mem , rtx model_rtx ) { rtx ( * gen ) ( rtx , rtx , rtx ) ; switch ( mode ) { case QImode : gen = gen_aarch64_load_exclusiveqi ; break ; case HImode : gen = gen_aarch64_load_exclusivehi ; break ; case SImode : gen = gen_aarch64_load_exclusivesi ; break ; case DImode : gen = gen_aarch64_load_exclusivedi ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen ( rval , mem , model_rtx ) ) ; } </s>


<s> static void aarch64_emit_store_exclusive ( machine_mode mode , rtx bval , rtx rval , rtx mem , rtx model_rtx ) { rtx ( * gen ) ( rtx , rtx , rtx , rtx ) ; switch ( mode ) { case QImode : gen = gen_aarch64_store_exclusiveqi ; break ; case HImode : gen = gen_aarch64_store_exclusivehi ; break ; case SImode : gen = gen_aarch64_store_exclusivesi ; break ; case DImode : gen = gen_aarch64_store_exclusivedi ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen ( bval , rval , mem , model_rtx ) ) ; } </s>


<s> static void aarch64_emit_unlikely_jump ( rtx insn ) { int very_unlikely = REG_BR_PROB_BASE / 100 - 1 ; insn = emit_jump_insn ( insn ) ; add_int_reg_note ( insn , REG_BR_PROB , very_unlikely ) ; } </s>

Mark the previous jump instruction as unlikely .


<s> static bool aarch64_evpc_ext ( struct expand_vec_perm_d * d ) { unsigned int i , nelt = d -> nelt ; rtx ( * gen ) ( rtx , rtx , rtx , rtx ) ; rtx offset ; unsigned int location = d -> perm [ 0 ] ; for ( i = 1 ; i < nelt ; i ++ ) { unsigned int required = location + i ; if ( d -> one_vector_p ) { required &= ( nelt - 1 ) ; } if ( d -> perm [ i ] != required ) return false ; } switch ( d -> vmode ) { case V16QImode : gen = gen_aarch64_extv16qi ; break ; case V8QImode : gen = gen_aarch64_extv8qi ; break ; case V4HImode : gen = gen_aarch64_extv4hi ; break ; case V8HImode : gen = gen_aarch64_extv8hi ; break ; case V2SImode : gen = gen_aarch64_extv2si ; break ; case V4SImode : gen = gen_aarch64_extv4si ; break ; case V2SFmode : gen = gen_aarch64_extv2sf ; break ; case V4SFmode : gen = gen_aarch64_extv4sf ; break ; case V2DImode : gen = gen_aarch64_extv2di ; break ; case V2DFmode : gen = gen_aarch64_extv2df ; break ; default : return false ; } if ( d -> testing_p ) return true ; if ( BYTES_BIG_ENDIAN && ( location != 0 ) ) { std :: swap ( d -> op0 , d -> op1 ) ; location = nelt - location ; } offset = GEN_INT ( location ) ; emit_insn ( gen ( d -> target , d -> op0 , d -> op1 , offset ) ) ; return true ; } </s>


<s> static bool aarch64_evpc_rev ( struct expand_vec_perm_d * d ) { unsigned int i , j , diff , nelt = d -> nelt ; rtx ( * gen ) ( rtx , rtx ) ; if ( ! d -> one_vector_p ) return false ; diff = d -> perm [ 0 ] ; switch ( diff ) { case 7 : switch ( d -> vmode ) { case V16QImode : gen = gen_aarch64_rev64v16qi ; break ; case V8QImode : gen = gen_aarch64_rev64v8qi ; break ; default : return false ; } break ; case 3 : switch ( d -> vmode ) { case V16QImode : gen = gen_aarch64_rev32v16qi ; break ; case V8QImode : gen = gen_aarch64_rev32v8qi ; break ; case V8HImode : gen = gen_aarch64_rev64v8hi ; break ; case V4HImode : gen = gen_aarch64_rev64v4hi ; break ; default : return false ; } break ; case 1 : switch ( d -> vmode ) { case V16QImode : gen = gen_aarch64_rev16v16qi ; break ; case V8QImode : gen = gen_aarch64_rev16v8qi ; break ; case V8HImode : gen = gen_aarch64_rev32v8hi ; break ; case V4HImode : gen = gen_aarch64_rev32v4hi ; break ; case V4SImode : gen = gen_aarch64_rev64v4si ; break ; case V2SImode : gen = gen_aarch64_rev64v2si ; break ; case V4SFmode : gen = gen_aarch64_rev64v4sf ; break ; case V2SFmode : gen = gen_aarch64_rev64v2sf ; break ; default : return false ; } break ; default : return false ; } for ( i = 0 ; i < nelt ; i += diff + 1 ) for ( j = 0 ; j <= diff ; j += 1 ) { gcc_assert ( i + j < nelt ) ; if ( d -> perm [ i + j ] != i + diff - j ) return false ; } if ( d -> testing_p ) return true ; emit_insn ( gen ( d -> target , d -> op0 ) ) ; return true ; } </s>


<s> static bool aarch64_evpc_trn ( struct expand_vec_perm_d * d ) { unsigned int i , odd , mask , nelt = d -> nelt ; rtx out , in0 , in1 , x ; rtx ( * gen ) ( rtx , rtx , rtx ) ; machine_mode vmode = d -> vmode ; if ( GET_MODE_UNIT_SIZE ( vmode ) > 8 ) return false ; if ( d -> perm [ 0 ] == 0 ) odd = 0 ; else if ( d -> perm [ 0 ] == 1 ) odd = 1 ; else return false ; mask = ( d -> one_vector_p ? nelt - 1 : 2 * nelt - 1 ) ; for ( i = 0 ; i < nelt ; i += 2 ) { if ( d -> perm [ i ] != i + odd ) return false ; if ( d -> perm [ i + 1 ] != ( ( i + nelt + odd ) & mask ) ) return false ; } if ( d -> testing_p ) return true ; in0 = d -> op0 ; in1 = d -> op1 ; if ( BYTES_BIG_ENDIAN ) { x = in0 , in0 = in1 , in1 = x ; odd = ! odd ; } out = d -> target ; if ( odd ) { switch ( vmode ) { case V16QImode : gen = gen_aarch64_trn2v16qi ; break ; case V8QImode : gen = gen_aarch64_trn2v8qi ; break ; case V8HImode : gen = gen_aarch64_trn2v8hi ; break ; case V4HImode : gen = gen_aarch64_trn2v4hi ; break ; case V4SImode : gen = gen_aarch64_trn2v4si ; break ; case V2SImode : gen = gen_aarch64_trn2v2si ; break ; case V2DImode : gen = gen_aarch64_trn2v2di ; break ; case V4SFmode : gen = gen_aarch64_trn2v4sf ; break ; case V2SFmode : gen = gen_aarch64_trn2v2sf ; break ; case V2DFmode : gen = gen_aarch64_trn2v2df ; break ; default : return false ; } } else { switch ( vmode ) { case V16QImode : gen = gen_aarch64_trn1v16qi ; break ; case V8QImode : gen = gen_aarch64_trn1v8qi ; break ; case V8HImode : gen = gen_aarch64_trn1v8hi ; break ; case V4HImode : gen = gen_aarch64_trn1v4hi ; break ; case V4SImode : gen = gen_aarch64_trn1v4si ; break ; case V2SImode : gen = gen_aarch64_trn1v2si ; break ; case V2DImode : gen = gen_aarch64_trn1v2di ; break ; case V4SFmode : gen = gen_aarch64_trn1v4sf ; break ; case V2SFmode : gen = gen_aarch64_trn1v2sf ; break ; case V2DFmode : gen = gen_aarch64_trn1v2df ; break ; default : return false ; } } emit_insn ( gen ( out , in0 , in1 ) ) ; return true ; } </s>

Recognize patterns suitable for the TRN instructions .


<s> static bool aarch64_evpc_uzp ( struct expand_vec_perm_d * d ) { unsigned int i , odd , mask , nelt = d -> nelt ; rtx out , in0 , in1 , x ; rtx ( * gen ) ( rtx , rtx , rtx ) ; machine_mode vmode = d -> vmode ; if ( GET_MODE_UNIT_SIZE ( vmode ) > 8 ) return false ; if ( d -> perm [ 0 ] == 0 ) odd = 0 ; else if ( d -> perm [ 0 ] == 1 ) odd = 1 ; else return false ; mask = ( d -> one_vector_p ? nelt - 1 : 2 * nelt - 1 ) ; for ( i = 0 ; i < nelt ; i ++ ) { unsigned elt = ( i * 2 + odd ) & mask ; if ( d -> perm [ i ] != elt ) return false ; } if ( d -> testing_p ) return true ; in0 = d -> op0 ; in1 = d -> op1 ; if ( BYTES_BIG_ENDIAN ) { x = in0 , in0 = in1 , in1 = x ; odd = ! odd ; } out = d -> target ; if ( odd ) { switch ( vmode ) { case V16QImode : gen = gen_aarch64_uzp2v16qi ; break ; case V8QImode : gen = gen_aarch64_uzp2v8qi ; break ; case V8HImode : gen = gen_aarch64_uzp2v8hi ; break ; case V4HImode : gen = gen_aarch64_uzp2v4hi ; break ; case V4SImode : gen = gen_aarch64_uzp2v4si ; break ; case V2SImode : gen = gen_aarch64_uzp2v2si ; break ; case V2DImode : gen = gen_aarch64_uzp2v2di ; break ; case V4SFmode : gen = gen_aarch64_uzp2v4sf ; break ; case V2SFmode : gen = gen_aarch64_uzp2v2sf ; break ; case V2DFmode : gen = gen_aarch64_uzp2v2df ; break ; default : return false ; } } else { switch ( vmode ) { case V16QImode : gen = gen_aarch64_uzp1v16qi ; break ; case V8QImode : gen = gen_aarch64_uzp1v8qi ; break ; case V8HImode : gen = gen_aarch64_uzp1v8hi ; break ; case V4HImode : gen = gen_aarch64_uzp1v4hi ; break ; case V4SImode : gen = gen_aarch64_uzp1v4si ; break ; case V2SImode : gen = gen_aarch64_uzp1v2si ; break ; case V2DImode : gen = gen_aarch64_uzp1v2di ; break ; case V4SFmode : gen = gen_aarch64_uzp1v4sf ; break ; case V2SFmode : gen = gen_aarch64_uzp1v2sf ; break ; case V2DFmode : gen = gen_aarch64_uzp1v2df ; break ; default : return false ; } } emit_insn ( gen ( out , in0 , in1 ) ) ; return true ; } </s>

Recognize patterns suitable for the UZP instructions .


<s> static bool aarch64_evpc_zip ( struct expand_vec_perm_d * d ) { unsigned int i , high , mask , nelt = d -> nelt ; rtx out , in0 , in1 , x ; rtx ( * gen ) ( rtx , rtx , rtx ) ; machine_mode vmode = d -> vmode ; if ( GET_MODE_UNIT_SIZE ( vmode ) > 8 ) return false ; high = nelt / 2 ; if ( d -> perm [ 0 ] == high ) ; else if ( d -> perm [ 0 ] == 0 ) high = 0 ; else return false ; mask = ( d -> one_vector_p ? nelt - 1 : 2 * nelt - 1 ) ; for ( i = 0 ; i < nelt / 2 ; i ++ ) { unsigned elt = ( i + high ) & mask ; if ( d -> perm [ i * 2 ] != elt ) return false ; elt = ( elt + nelt ) & mask ; if ( d -> perm [ i * 2 + 1 ] != elt ) return false ; } if ( d -> testing_p ) return true ; in0 = d -> op0 ; in1 = d -> op1 ; if ( BYTES_BIG_ENDIAN ) { x = in0 , in0 = in1 , in1 = x ; high = ! high ; } out = d -> target ; if ( high ) { switch ( vmode ) { case V16QImode : gen = gen_aarch64_zip2v16qi ; break ; case V8QImode : gen = gen_aarch64_zip2v8qi ; break ; case V8HImode : gen = gen_aarch64_zip2v8hi ; break ; case V4HImode : gen = gen_aarch64_zip2v4hi ; break ; case V4SImode : gen = gen_aarch64_zip2v4si ; break ; case V2SImode : gen = gen_aarch64_zip2v2si ; break ; case V2DImode : gen = gen_aarch64_zip2v2di ; break ; case V4SFmode : gen = gen_aarch64_zip2v4sf ; break ; case V2SFmode : gen = gen_aarch64_zip2v2sf ; break ; case V2DFmode : gen = gen_aarch64_zip2v2df ; break ; default : return false ; } } else { switch ( vmode ) { case V16QImode : gen = gen_aarch64_zip1v16qi ; break ; case V8QImode : gen = gen_aarch64_zip1v8qi ; break ; case V8HImode : gen = gen_aarch64_zip1v8hi ; break ; case V4HImode : gen = gen_aarch64_zip1v4hi ; break ; case V4SImode : gen = gen_aarch64_zip1v4si ; break ; case V2SImode : gen = gen_aarch64_zip1v2si ; break ; case V2DImode : gen = gen_aarch64_zip1v2di ; break ; case V4SFmode : gen = gen_aarch64_zip1v4sf ; break ; case V2SFmode : gen = gen_aarch64_zip1v2sf ; break ; case V2DFmode : gen = gen_aarch64_zip1v2df ; break ; default : return false ; } } emit_insn ( gen ( out , in0 , in1 ) ) ; return true ; } </s>

Recognize patterns suitable for the ZIP instructions .


"%qs and floating point or vector arguments"


<s> void aarch64_expand_compare_and_swap ( rtx operands [ ] ) { rtx bval , rval , mem , oldval , newval , is_weak , mod_s , mod_f , x ; machine_mode mode , cmp_mode ; rtx ( * gen ) ( rtx , rtx , rtx , rtx , rtx , rtx , rtx ) ; 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 ) ; cmp_mode = mode ; if ( INTVAL ( mod_f ) == MEMMODEL_ACQUIRE && INTVAL ( mod_s ) == MEMMODEL_RELEASE ) mod_s = GEN_INT ( MEMMODEL_ACQ_REL ) ; switch ( mode ) { case QImode : case HImode : cmp_mode = SImode ; rval = gen_reg_rtx ( SImode ) ; oldval = convert_modes ( SImode , mode , oldval , true ) ; case SImode : case DImode : if ( ! aarch64_plus_operand ( oldval , mode ) ) oldval = force_reg ( cmp_mode , oldval ) ; break ; default : gcc_unreachable ( ) ; } switch ( mode ) { case QImode : gen = gen_atomic_compare_and_swapqi_1 ; break ; case HImode : gen = gen_atomic_compare_and_swaphi_1 ; break ; case SImode : gen = gen_atomic_compare_and_swapsi_1 ; break ; case DImode : gen = gen_atomic_compare_and_swapdi_1 ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen ( rval , mem , oldval , newval , is_weak , mod_s , mod_f ) ) ; if ( mode == QImode || mode == HImode ) emit_move_insn ( operands [ 1 ] , gen_lowpart ( mode , rval ) ) ; x = gen_rtx_REG ( CCmode , CC_REGNUM ) ; x = gen_rtx_EQ ( SImode , x , const0_rtx ) ; emit_insn ( gen_rtx_SET ( VOIDmode , bval , x ) ) ; } </s>


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


<s> void aarch64_expand_mov_immediate ( rtx dest , rtx imm ) { machine_mode mode = GET_MODE ( dest ) ; gcc_assert ( mode == SImode || mode == DImode ) ; if ( GET_CODE ( imm ) == SYMBOL_REF || GET_CODE ( imm ) == LABEL_REF || GET_CODE ( imm ) == CONST ) { rtx mem , base , offset ; enum aarch64_symbol_type sty ; split_const ( imm , & base , & offset ) ; sty = aarch64_classify_symbol ( base , offset , SYMBOL_CONTEXT_ADR ) ; switch ( sty ) { case SYMBOL_FORCE_TO_MEM : if ( offset != const0_rtx && targetm . cannot_force_const_mem ( mode , imm ) ) { gcc_assert ( can_create_pseudo_p ( ) ) ; base = aarch64_force_temporary ( mode , dest , base ) ; base = aarch64_add_offset ( mode , NULL , base , INTVAL ( offset ) ) ; aarch64_emit_move ( dest , base ) ; return ; } mem = force_const_mem ( ptr_mode , imm ) ; gcc_assert ( mem ) ; if ( mode != ptr_mode ) mem = gen_rtx_ZERO_EXTEND ( mode , mem ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , mem ) ) ; return ; case SYMBOL_SMALL_TLSGD : case SYMBOL_SMALL_TLSDESC : case SYMBOL_SMALL_GOTTPREL : case SYMBOL_SMALL_GOT : case SYMBOL_TINY_GOT : if ( offset != const0_rtx ) { gcc_assert ( can_create_pseudo_p ( ) ) ; base = aarch64_force_temporary ( mode , dest , base ) ; base = aarch64_add_offset ( mode , NULL , base , INTVAL ( offset ) ) ; aarch64_emit_move ( dest , base ) ; return ; } case SYMBOL_SMALL_TPREL : case SYMBOL_SMALL_ABSOLUTE : case SYMBOL_TINY_ABSOLUTE : aarch64_load_symref_appropriately ( dest , imm , sty ) ; return ; default : gcc_unreachable ( ) ; } } if ( ! CONST_INT_P ( imm ) ) { if ( GET_CODE ( imm ) == HIGH ) emit_insn ( gen_rtx_SET ( VOIDmode , dest , imm ) ) ; else { rtx mem = force_const_mem ( mode , imm ) ; gcc_assert ( mem ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , mem ) ) ; } return ; } aarch64_internal_mov_immediate ( dest , imm , true , GET_MODE ( dest ) ) ; } </s>

Set DEST to immediate IMM . For SVE vector modes , GEN_VEC_DUPLICATE is a pattern that can be used to set DEST to a replicated scalar element .


<s> void aarch64_expand_vector_init ( rtx target , rtx vals ) { machine_mode mode = GET_MODE ( target ) ; machine_mode inner_mode = GET_MODE_INNER ( mode ) ; int n_elts = GET_MODE_NUNITS ( mode ) ; int n_var = 0 , one_var = - 1 ; bool all_same = true ; rtx x , mem ; int i ; x = XVECEXP ( vals , 0 , 0 ) ; if ( ! CONST_INT_P ( x ) && ! CONST_DOUBLE_P ( x ) ) n_var = 1 , one_var = 0 ; for ( i = 1 ; i < n_elts ; ++ i ) { x = XVECEXP ( vals , 0 , i ) ; if ( ! CONST_INT_P ( x ) && ! CONST_DOUBLE_P ( x ) ) ++ n_var , one_var = i ; if ( ! rtx_equal_p ( x , XVECEXP ( vals , 0 , 0 ) ) ) all_same = false ; } if ( n_var == 0 ) { rtx constant = aarch64_simd_make_constant ( vals ) ; if ( constant != NULL_RTX ) { emit_move_insn ( target , constant ) ; return ; } } if ( all_same ) { x = copy_to_mode_reg ( inner_mode , XVECEXP ( vals , 0 , 0 ) ) ; aarch64_emit_move ( target , gen_rtx_VEC_DUPLICATE ( mode , x ) ) ; return ; } if ( n_var == 1 ) { rtx copy = copy_rtx ( vals ) ; rtx index = GEN_INT ( one_var ) ; enum insn_code icode ; XVECEXP ( copy , 0 , one_var ) = XVECEXP ( vals , 0 , one_var ^ 1 ) ; aarch64_expand_vector_init ( target , copy ) ; x = copy_to_mode_reg ( inner_mode , XVECEXP ( vals , 0 , one_var ) ) ; icode = optab_handler ( vec_set_optab , mode ) ; gcc_assert ( icode != CODE_FOR_nothing ) ; emit_insn ( GEN_FCN ( icode ) ( target , x , index ) ) ; return ; } mem = assign_stack_temp ( mode , GET_MODE_SIZE ( mode ) ) ; for ( i = 0 ; i < n_elts ; i ++ ) emit_move_insn ( adjust_address_nv ( mem , inner_mode , i * GET_MODE_SIZE ( inner_mode ) ) , XVECEXP ( vals , 0 , i ) ) ; emit_move_insn ( target , mem ) ; } </s>

Expand a vector initialisation sequence , such that TARGET is initialised to contain VALS .


<s> void aarch64_expand_vec_perm ( rtx target , rtx op0 , rtx op1 , rtx sel ) { machine_mode vmode = GET_MODE ( target ) ; unsigned int nelt = GET_MODE_NUNITS ( vmode ) ; bool one_vector_p = rtx_equal_p ( op0 , op1 ) ; rtx mask ; mask = aarch64_simd_gen_const_vector_dup ( vmode , one_vector_p ? nelt - 1 : 2 * nelt - 1 ) ; sel = expand_simple_binop ( vmode , AND , sel , mask , NULL , 0 , OPTAB_LIB_WIDEN ) ; if ( BYTES_BIG_ENDIAN ) { if ( ! one_vector_p ) mask = aarch64_simd_gen_const_vector_dup ( vmode , nelt - 1 ) ; sel = expand_simple_binop ( vmode , XOR , sel , mask , NULL , 0 , OPTAB_LIB_WIDEN ) ; } aarch64_expand_vec_perm_1 ( target , op0 , op1 , sel ) ; } </s>

Expand a vec_perm with the operands given by TARGET , OP0 , OP1 and SEL . NELT is the number of elements in the vector .


<s> bool aarch64_expand_vec_perm_const ( rtx target , rtx op0 , rtx op1 , rtx sel ) { struct expand_vec_perm_d d ; int i , nelt , which ; d . target = target ; d . op0 = op0 ; d . op1 = op1 ; d . vmode = GET_MODE ( target ) ; gcc_assert ( VECTOR_MODE_P ( d . vmode ) ) ; d . nelt = nelt = GET_MODE_NUNITS ( d . vmode ) ; d . testing_p = false ; for ( i = which = 0 ; i < nelt ; ++ i ) { rtx e = XVECEXP ( sel , 0 , i ) ; int ei = INTVAL ( e ) & ( 2 * nelt - 1 ) ; which |= ( ei < nelt ? 1 : 2 ) ; d . perm [ i ] = ei ; } switch ( which ) { default : gcc_unreachable ( ) ; case 3 : d . one_vector_p = false ; if ( ! rtx_equal_p ( op0 , op1 ) ) break ; case 2 : for ( i = 0 ; i < nelt ; ++ i ) d . perm [ i ] &= nelt - 1 ; d . op0 = op1 ; d . one_vector_p = true ; break ; case 1 : d . op1 = op0 ; d . one_vector_p = true ; break ; } return aarch64_expand_vec_perm_const_1 ( & d ) ; } </s>


<s> rtx aarch64_final_eh_return_addr ( void ) { HOST_WIDE_INT fp_offset ; aarch64_layout_frame ( ) ; fp_offset = cfun -> machine -> frame . frame_size - cfun -> machine -> frame . hard_fp_offset ; if ( cfun -> machine -> frame . reg_offset [ LR_REGNUM ] < 0 ) return gen_rtx_REG ( DImode , LR_REGNUM ) ; if ( frame_pointer_needed ) { if ( fp_offset ) return gen_frame_mem ( DImode , plus_constant ( Pmode , hard_frame_pointer_rtx , UNITS_PER_WORD ) ) ; else return gen_frame_mem ( DImode , plus_constant ( Pmode , stack_pointer_rtx , UNITS_PER_WORD ) ) ; } return gen_frame_mem ( DImode , plus_constant ( Pmode , stack_pointer_rtx , fp_offset + cfun -> machine -> frame . saved_regs_size - 2 * UNITS_PER_WORD ) ) ; } </s>

Return the place to copy the exception unwinding return address to . This will probably be a stack slot , but could ( in theory be the return register ) .


<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 ) return false ; REAL_VALUE_FROM_CONST_DOUBLE ( r , 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 . elt ( 0 ) != 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> bool aarch64_float_const_zero_rtx_p ( rtx x ) { REAL_VALUE_TYPE r ; if ( GET_MODE ( x ) == VOIDmode ) return false ; REAL_VALUE_FROM_CONST_DOUBLE ( r , x ) ; if ( REAL_VALUE_MINUS_ZERO ( r ) ) return ! HONOR_SIGNED_ZEROS ( GET_MODE ( x ) ) ; return REAL_VALUES_EQUAL ( r , dconst0 ) ; } </s>

Return TRUE if rtx X is immediate constant 0.0


<s> static unsigned int aarch64_function_arg_alignment ( machine_mode mode , const_tree type ) { unsigned int alignment ; if ( type ) { if ( ! integer_zerop ( TYPE_SIZE ( type ) ) ) { if ( TYPE_MODE ( type ) == mode ) alignment = TYPE_ALIGN ( type ) ; else alignment = GET_MODE_ALIGNMENT ( mode ) ; } else alignment = 0 ; } else alignment = GET_MODE_ALIGNMENT ( mode ) ; return alignment ; } </s>

Given MODE and TYPE of a function argument , return the alignment in bits . The idea is to suppress any stronger alignment requested by the user and opt for the natural alignment ( specified in AAPCS64 \S 4.1 ) . This is a helper function for local use only .


<s> static unsigned int aarch64_function_arg_boundary ( machine_mode mode , const_tree type ) { unsigned int alignment = aarch64_function_arg_alignment ( mode , type ) ; if ( alignment < PARM_BOUNDARY ) alignment = PARM_BOUNDARY ; if ( alignment > STACK_BOUNDARY ) alignment = STACK_BOUNDARY ; return alignment ; } </s>

Implement FUNCTION_ARG_BOUNDARY . Every parameter gets at least PARM_BOUNDARY bits of alignment , but will be given anything up to STACK_BOUNDARY bits if the type requires it . This makes sure that both before and after the layout of each argument , the Next Stacked Argument Address ( NSAA ) will have a minimum alignment of 8 bytes .


<s> static rtx aarch64_function_value ( const_tree type , const_tree func , bool outgoing ATTRIBUTE_UNUSED ) { machine_mode mode ; int unsignedp ; int count ; machine_mode ag_mode ; mode = TYPE_MODE ( type ) ; if ( INTEGRAL_TYPE_P ( type ) ) mode = promote_function_mode ( type , mode , & unsignedp , func , 1 ) ; if ( aarch64_return_in_msb ( type ) ) { HOST_WIDE_INT size = int_size_in_bytes ( type ) ; if ( size % UNITS_PER_WORD != 0 ) { size += UNITS_PER_WORD - size % UNITS_PER_WORD ; mode = mode_for_size ( size * BITS_PER_UNIT , MODE_INT , 0 ) ; } } if ( aarch64_vfp_is_call_or_return_candidate ( mode , type , & ag_mode , & count , NULL ) ) { if ( ! aarch64_composite_type_p ( type , mode ) ) { gcc_assert ( count == 1 && mode == ag_mode ) ; return gen_rtx_REG ( mode , V0_REGNUM ) ; } else { int i ; rtx par ; par = gen_rtx_PARALLEL ( mode , rtvec_alloc ( count ) ) ; for ( i = 0 ; i < count ; i ++ ) { rtx tmp = gen_rtx_REG ( ag_mode , V0_REGNUM + i ) ; tmp = gen_rtx_EXPR_LIST ( VOIDmode , tmp , GEN_INT ( i * GET_MODE_SIZE ( ag_mode ) ) ) ; XVECEXP ( par , 0 , i ) = tmp ; } return par ; } } else return gen_rtx_REG ( mode , R0_REGNUM ) ; } </s>

Implement TARGET_FUNCTION_VALUE . Define how to find the value returned by a function .


<s> static bool aarch64_function_value_regno_p ( const unsigned int regno ) { if ( regno == R0_REGNUM || regno == R1_REGNUM ) return true ; if ( regno >= V0_REGNUM && regno < V0_REGNUM + HA_MAX_NUM_FLDS ) return ! TARGET_GENERAL_REGS_ONLY ; return false ; } </s>

Implements TARGET_FUNCTION_VALUE_REGNO_P . Return true if REGNO is the number of a hard register in which the values of called function may come back .


<s> rtx aarch64_gen_compare_reg ( RTX_CODE code , rtx x , rtx y ) { machine_mode mode = SELECT_CC_MODE ( code , x , y ) ; rtx cc_reg = gen_rtx_REG ( mode , CC_REGNUM ) ; emit_set_insn ( cc_reg , gen_rtx_COMPARE ( mode , x , y ) ) ; return cc_reg ; } </s>

X and Y are two things to compare using CODE . Emit the compare insn and return the rtx for register 0 in the proper mode .


<s> static rtx aarch64_gen_loadwb_pair ( machine_mode mode , rtx base , rtx reg , rtx reg2 , HOST_WIDE_INT adjustment ) { switch ( mode ) { case DImode : return gen_loadwb_pairdi_di ( base , base , reg , reg2 , GEN_INT ( adjustment ) , GEN_INT ( UNITS_PER_WORD ) ) ; case DFmode : return gen_loadwb_pairdf_di ( base , base , reg , reg2 , GEN_INT ( adjustment ) , GEN_INT ( UNITS_PER_WORD ) ) ; default : gcc_unreachable ( ) ; } } </s>

Load the pair of register REG , REG2 of mode MODE from stack location BASE , adjusting it by ADJUSTMENT afterwards .


<s> static rtx aarch64_gen_load_pair ( machine_mode mode , rtx reg1 , rtx mem1 , rtx reg2 , rtx mem2 ) { switch ( mode ) { case DImode : return gen_load_pairdi ( reg1 , mem1 , reg2 , mem2 ) ; case DFmode : return gen_load_pairdf ( reg1 , mem1 , reg2 , mem2 ) ; default : gcc_unreachable ( ) ; } } </s>

Generate and regurn a load pair isntruction of mode MODE to load register REG1 from MEM1 and register REG2 from MEM2 .


<s> static rtx aarch64_gen_storewb_pair ( machine_mode mode , rtx base , rtx reg , rtx reg2 , HOST_WIDE_INT adjustment ) { switch ( mode ) { case DImode : return gen_storewb_pairdi_di ( base , base , reg , reg2 , GEN_INT ( - adjustment ) , GEN_INT ( UNITS_PER_WORD - adjustment ) ) ; case DFmode : return gen_storewb_pairdf_di ( base , base , reg , reg2 , GEN_INT ( - adjustment ) , GEN_INT ( UNITS_PER_WORD - adjustment ) ) ; default : gcc_unreachable ( ) ; } } </s>

Generate and return an instruction to store the pair of registers REG and REG2 of mode MODE to location BASE with write-back adjusting the stack location BASE by ADJUSTMENT .


<s> static rtx aarch64_gen_store_pair ( machine_mode mode , rtx mem1 , rtx reg1 , rtx mem2 , rtx reg2 ) { switch ( mode ) { case DImode : return gen_store_pairdi ( mem1 , reg1 , mem2 , reg2 ) ; case DFmode : return gen_store_pairdf ( mem1 , reg1 , mem2 , reg2 ) ; default : gcc_unreachable ( ) ; } } </s>

Generate and return a store pair instruction of mode MODE to store register REG1 to MEM1 and register REG2 to MEM2 .


<s> machine_mode aarch64_hard_regno_caller_save_mode ( unsigned regno , unsigned nregs , machine_mode mode ) { if ( nregs == 1 && GET_MODE_SIZE ( mode ) <= 16 ) { if ( GET_MODE_SIZE ( mode ) >= 4 ) return mode ; else return SImode ; } else return choose_hard_reg_mode ( regno , nregs , false ) ; } </s>


<s> int aarch64_hard_regno_mode_ok ( unsigned regno , machine_mode mode ) { if ( GET_MODE_CLASS ( mode ) == MODE_CC ) return regno == CC_REGNUM ; 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 ) && ! aarch64_vect_struct_mode_p ( mode ) ) return 1 ; if ( FP_REGNUM_P ( regno ) ) { if ( aarch64_vect_struct_mode_p ( mode ) ) return ( regno + aarch64_hard_regno_nregs ( regno , mode ) - 1 ) <= V31_REGNUM ; else return 1 ; } return 0 ; } </s>


<s> int aarch64_hard_regno_nregs ( unsigned regno , machine_mode mode ) { switch ( aarch64_regno_regclass ( regno ) ) { case FP_REGS : case FP_LO_REGS : return ( GET_MODE_SIZE ( mode ) + UNITS_PER_VREG - 1 ) / UNITS_PER_VREG ; default : return ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ; } gcc_unreachable ( ) ; } </s>


<s> static bool aarch64_if_then_else_costs ( rtx op0 , rtx op1 , rtx op2 , int * cost , bool speed ) { rtx inner ; rtx comparator ; enum rtx_code cmpcode ; if ( COMPARISON_P ( op0 ) ) { inner = XEXP ( op0 , 0 ) ; comparator = XEXP ( op0 , 1 ) ; cmpcode = GET_CODE ( op0 ) ; } else { inner = op0 ; comparator = const0_rtx ; cmpcode = NE ; } if ( GET_CODE ( op1 ) == PC || GET_CODE ( op2 ) == PC ) { if ( GET_MODE_CLASS ( GET_MODE ( inner ) ) == MODE_CC ) return true ; else { if ( cmpcode == NE || cmpcode == EQ ) { if ( comparator == const0_rtx ) { if ( GET_CODE ( inner ) == ZERO_EXTRACT ) * cost += rtx_cost ( XEXP ( inner , 0 ) , ZERO_EXTRACT , 0 , speed ) ; else * cost += rtx_cost ( inner , cmpcode , 0 , speed ) ; return true ; } } else if ( cmpcode == LT || cmpcode == GE ) { if ( comparator == const0_rtx ) return true ; } } } else if ( GET_MODE_CLASS ( GET_MODE ( inner ) ) == MODE_CC ) { if ( GET_CODE ( op1 ) == NEG || GET_CODE ( op1 ) == NOT || ( GET_CODE ( op1 ) == PLUS && XEXP ( op1 , 1 ) == const1_rtx ) ) op1 = XEXP ( op1 , 0 ) ; * cost += rtx_cost ( op1 , IF_THEN_ELSE , 1 , speed ) ; * cost += rtx_cost ( op2 , IF_THEN_ELSE , 2 , speed ) ; return true ; } return false ; } </s>

Calculate the cost of calculating ( if_then_else ( OP0 ) ( OP1 ) ( OP2 ) ) , storing it in * COST . Result is true if the total cost of the operation has now been calculated .


<s> bool aarch64_is_extend_from_extract ( machine_mode mode , rtx mult_imm , rtx extract_imm ) { HOST_WIDE_INT mult_val , extract_val ; if ( ! CONST_INT_P ( mult_imm ) || ! CONST_INT_P ( extract_imm ) ) return false ; mult_val = INTVAL ( mult_imm ) ; extract_val = INTVAL ( extract_imm ) ; if ( extract_val > 8 && extract_val < GET_MODE_BITSIZE ( mode ) && exact_log2 ( extract_val & ~ 7 ) > 0 && ( extract_val & 7 ) <= 4 && mult_val == ( 1 << ( extract_val & 7 ) ) ) return true ; return false ; } </s>

Return true if the offsets to a zero/sign-extract operation represent an expression that matches an extend operation . The operands represent the paramters from ( extract : MODE ( mult ( reg ) ( MULT_IMM ) ) ( EXTRACT_IMM ) ( const_int 0 ) ) .


<s> static bool aarch64_legitimate_address_hook_p ( machine_mode mode , rtx x , bool strict_p ) { struct aarch64_address_info addr ; return aarch64_classify_address ( & addr , x , mode , MEM , strict_p ) ; } </s>

Return TRUE if X is a legitimate address for accessing memory in mode MODE .


<s> bool aarch64_legitimate_address_p ( machine_mode mode , rtx x , RTX_CODE outer_code , bool strict_p ) { struct aarch64_address_info addr ; return aarch64_classify_address ( & addr , x , mode , outer_code , strict_p ) ; } </s>

Return TRUE if X is a legitimate address for accessing memory in mode MODE . OUTER_CODE will be PARALLEL if this is a load/store pair operation .


<s> static bool aarch64_legitimate_constant_p ( machine_mode mode , rtx x ) { if ( TARGET_SIMD && aarch64_vect_struct_mode_p ( mode ) ) return false ; if ( ( GET_CODE ( x ) == CONST_VECTOR && aarch64_simd_valid_immediate ( x , mode , false , NULL ) ) || CONST_INT_P ( x ) || aarch64_valid_floating_const ( mode , x ) ) return ! targetm . cannot_force_const_mem ( mode , x ) ; if ( GET_CODE ( x ) == HIGH && aarch64_valid_symref ( XEXP ( x , 0 ) , GET_MODE ( XEXP ( x , 0 ) ) ) ) return true ; return aarch64_constant_address_p ( x ) ; } </s>

Implement TARGET_LEGITIMATE_CONSTANT_P hook . Return true for constants that should be rematerialized rather than spilled .


<s> static bool aarch64_macro_fusion_p ( void ) { return aarch64_tune_params -> fuseable_ops != AARCH64_FUSE_NOTHING ; } </s>

Implement TARGET_SCHED_MACRO_FUSION_P . Return true if target supports instruction fusion of some sort .


<s> bool aarch64_madd_needs_nop ( rtx_insn * insn ) { enum attr_type attr_type ; rtx_insn * prev ; rtx body ; if ( ! aarch64_fix_a53_err835769 ) return false ; if ( recog_memoized ( insn ) < 0 ) return false ; attr_type = get_attr_type ( insn ) ; if ( ! is_madd_op ( attr_type ) ) return false ; prev = aarch64_prev_real_insn ( insn ) ; extract_constrain_insn_cached ( insn ) ; if ( ! prev || ! has_memory_op ( prev ) ) return false ; body = single_set ( prev ) ; if ( GET_MODE ( recog_data . operand [ 0 ] ) == DImode && ( ! body || ! dep_between_memop_and_curr ( body ) ) ) return true ; return false ; } </s>

When working around the Cortex-A53 erratum 835769 , given rtx_insn INSN , return true if it is a 64-bit multiply-accumulate instruction and has a preceding memory instruction such that a NOP should be inserted between them .


<s> static const char * aarch64_mangle_type ( const_tree type ) { if ( lang_hooks . types_compatible_p ( CONST_CAST_TREE ( type ) , va_list_type ) ) return "St9__va_list" ; if ( TYPE_NAME ( type ) != NULL ) return aarch64_mangle_builtin_type ( type ) ; return NULL ; } </s>


<s> bool aarch64_modes_tieable_p ( machine_mode mode1 , machine_mode mode2 ) { if ( GET_MODE_CLASS ( mode1 ) == GET_MODE_CLASS ( mode2 ) ) return true ; if ( TARGET_SIMD && aarch64_vector_mode_p ( mode1 ) && aarch64_vector_mode_p ( mode2 ) ) return true ; return false ; } </s>

Implement MODES_TIEABLE_P . In principle we should always return true . However due to issues with register allocation it is preferable to avoid tieing integer scalar and FP scalar modes . Executing integer operations in general registers is better than treating them as scalar vector operations . This reduces latency and avoids redundant int < - > FP moves . So tie modes if they are either the same class , or vector modes with other vector modes , vector structs or any scalar mode .


<s> bool aarch64_move_imm ( HOST_WIDE_INT val , machine_mode mode ) { if ( aarch64_movw_imm ( val , mode ) || aarch64_movw_imm ( ~ val , mode ) ) return 1 ; return aarch64_bitmask_imm ( val , mode ) ; } </s>

Return true if val is an immediate that can be loaded into a register in a single instruction .


<s> static rtx aarch64_move_pointer ( rtx pointer , int amount ) { rtx next = plus_constant ( Pmode , XEXP ( pointer , 0 ) , amount ) ; return adjust_automodify_address ( pointer , GET_MODE ( pointer ) , next , amount ) ; } </s>

Return a new RTX holding the result of moving POINTER forward by AMOUNT bytes .


<s> static bool aarch64_movw_imm ( HOST_WIDE_INT val , machine_mode mode ) { if ( GET_MODE_SIZE ( mode ) > 4 ) { if ( ( val & ( ( ( HOST_WIDE_INT ) 0xffff ) << 32 ) ) == val || ( val & ( ( ( HOST_WIDE_INT ) 0xffff ) << 48 ) ) == val ) return 1 ; } else { val &= ( HOST_WIDE_INT ) 0xffffffff ; } return ( ( val & ( ( ( HOST_WIDE_INT ) 0xffff ) << 0 ) ) == val || ( val & ( ( ( HOST_WIDE_INT ) 0xffff ) << 16 ) ) == val ) ; } </s>

Return true if val is an immediate that can be loaded into a register by a MOVZ instruction .


<s> bool aarch64_offset_7bit_signed_scaled_p ( machine_mode mode , HOST_WIDE_INT offset ) { return ( offset >= - 64 * GET_MODE_SIZE ( mode ) && offset < 64 * GET_MODE_SIZE ( mode ) && offset % GET_MODE_SIZE ( mode ) == 0 ) ; } </s>

Return true if OFFSET is a signed 7-bit value multiplied by the size of MODE .


<s> bool aarch64_operands_ok_for_ldpstp ( rtx * operands , bool load , enum 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 ; 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 ) ; 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 ) ; if ( vcall_offset == 0 ) aarch64_add_constant ( this_regno , IP1_REGNUM , delta ) ; else { gcc_assert ( ( vcall_offset & ( POINTER_BYTES - 1 ) ) == 0 ) ; this_rtx = gen_rtx_REG ( Pmode , this_regno ) ; temp0 = gen_rtx_REG ( Pmode , IP0_REGNUM ) ; temp1 = gen_rtx_REG ( Pmode , IP1_REGNUM ) ; 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_constant ( this_regno , IP1_REGNUM , delta ) ; } 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 { ( void ) aarch64_build_constant ( IP1_REGNUM , vcall_offset , true ) ; 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_simd_mov_immediate
(
rtx
const_vector
,
machine_mode
mode
,
unsigned
width
)
{
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
=
{
NULL_RTX
,
0
,
0
,
false
,
false
}
;
is_valid
=
aarch64_simd_valid_immediate
(
const_vector
,
mode
,
false
,
&
info
)
;
gcc_assert
(
is_valid
)
;
element_char
=
sizetochar
(
info
.
element_width
)
;
lane_count
=
width
/
info
.
element_width
;
mode
=
GET_MODE_INNER
(
mode
)
;
if
(
mode
==
SFmode
||
mode
==
DFmode
)
{
gcc_assert
(
info
.
shift
==
0
&&
!
info
.
mvn
)
;
if
(
aarch64_float_const_zero_rtx_p
(
info
.
value
)
)
info
.
value
=
GEN_INT
(
0
)
;
else
{
REAL_VALUE_TYPE
r
;
REAL_VALUE_FROM_CONST_DOUBLE
(
r
,
info
.
value
)
;
char
float_buf
[
buf_size
]
=
{
'\0'
}
;
real_to_decimal_for_mode
(
float_buf
,
&
r
,
buf_size
,
buf_size
,
1
,
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
;
}
}
mnemonic
=
info
.
mvn
"mvni"
:
"movi"
;
shift_op
=
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
)
)
;
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 .


"Assembler does not support -mabi=ilp32"


<s> static void aarch64_override_options_after_change ( void ) { if ( flag_omit_frame_pointer ) flag_omit_leaf_frame_pointer = false ; else if ( flag_omit_leaf_frame_pointer ) flag_omit_frame_pointer = true ; } </s>


<s> bool aarch64_pad_arg_upward ( machine_mode mode , const_tree type ) { if ( ! BYTES_BIG_ENDIAN ) return true ; if ( type ? ( INTEGRAL_TYPE_P ( type ) || SCALAR_FLOAT_TYPE_P ( type ) || POINTER_TYPE_P ( type ) ) : ( SCALAR_INT_MODE_P ( mode ) || SCALAR_FLOAT_MODE_P ( mode ) ) ) return false ; return true ; } </s>

For use by FUNCTION_ARG_PADDING ( MODE , TYPE ) . Return true if an argument passed on the stack should be padded upwards , i.e . if the least-significant byte of the stack slot has useful data . Small aggregate types are placed in the lowest memory address . The related parameter passing rules are B.4 , C.3 , C.5 and C.14 .


<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 = ( type ? int_size_in_bytes ( type ) : GET_MODE_SIZE ( mode ) ) ; 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 .


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

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
void
aarch64_parse_cpu
(
void
)
{
char
*
ext
;
const
struct
processor
*
cpu
;
char
*
str
=
(
char
*
)
alloca
(
strlen
(
aarch64_cpu_string
)
+
1
)
;
size_t
len
;
strcpy
(
str
,
aarch64_cpu_string
)
;
ext
=
strchr
(
str
,
'+'
)
;
if
(
ext
!=
)
len
=
ext
str
;
else
len
=
strlen
(
str
)
;
if
(
len
==
0
)
{
error
(
"missing cpu name in -mcpu=%qs"
,
str
)
;
return
;
}
for
(
cpu
=
all_cores
;
cpu
->
name
!=
;
cpu
++
)
{
if
(
strlen
(
cpu
->
name
)
==
len
&&
strncmp
(
cpu
->
name
,
str
,
len
)
==
0
)
{
selected_cpu
=
cpu
;
aarch64_isa_flags
=
selected_cpu
->
flags
;
if
(
ext
!=
)
{
aarch64_parse_extension
(
ext
)
;
}
return
;
}
}
error
(
"unknown value %qs for -mcpu"
,
str
)
;
return
;
}
</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_parse_extension
(
char
*
str
)
{
const
struct
aarch64_option_extension
*
opt
=
;
int
adding_ext
=
1
;
while
(
str
!=
&&
*
str
!=
0
)
{
char
*
ext
;
size_t
len
;
str
++
;
ext
=
strchr
(
str
,
'+'
)
;
if
(
ext
!=
)
len
=
ext
str
;
else
len
=
strlen
(
str
)
;
if
(
len
>=
2
&&
strncmp
(
str
,
"no"
,
2
)
==
0
)
{
adding_ext
=
0
;
len
-=
2
;
str
+=
2
;
}
else
if
(
len
>
0
)
adding_ext
=
1
;
if
(
len
==
0
)
{
error
(
"missing feature modifier after %qs"
,
adding_ext
"+"
:
"+no"
)
;
return
;
}
for
(
opt
=
all_extensions
;
opt
->
name
!=
;
opt
++
)
{
if
(
strlen
(
opt
->
name
)
==
len
&&
strncmp
(
opt
->
name
,
str
,
len
)
==
0
)
{
if
(
adding_ext
)
aarch64_isa_flags
|=
opt
->
flags_on
;
else
aarch64_isa_flags
&=
~
(
opt
->
flags_off
)
;
break
;
}
}
if
(
opt
->
name
==
)
{
error
(
"unknown feature modifier %qs"
,
str
)
;
return
;
}
str
=
ext
;
}
;
return
;
}
</s>

Parse the architecture extension string .


<s>
static
void
aarch64_parse_tune
(
void
)
{
const
struct
processor
*
cpu
;
char
*
str
=
(
char
*
)
alloca
(
strlen
(
aarch64_tune_string
)
+
1
)
;
strcpy
(
str
,
aarch64_tune_string
)
;
for
(
cpu
=
all_cores
;
cpu
->
name
!=
;
cpu
++
)
{
if
(
strcmp
(
cpu
->
name
,
str
)
==
0
)
{
selected_tune
=
cpu
;
return
;
}
}
error
(
"unknown value %qs for -mtune"
,
str
)
;
return
;
}
</s>


<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 ; size = ( mode == BLKmode && type ) ? int_size_in_bytes ( type ) : ( int ) GET_MODE_SIZE ( mode ) ; 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 machine_mode aarch64_preferred_simd_mode ( machine_mode mode ) { return aarch64_simd_container_mode ( mode , 128 ) ; } </s>

Return 128-bit container as the preferred SIMD mode for MODE .


<s> aarch64_print_operand_address ( STREAM , X ) { \ rtx fun , lr ; \ lr = get_hard_reg_initial_val ( Pmode , LR_REGNUM ) ; \ fun = gen_rtx_SYMBOL_REF ( Pmode , MCOUNT_NAME ) ; \ emit_library_call ( fun , LCT_NORMAL , VOIDmode , 1 , lr , Pmode ) ; \ } </s>

Print address ' x ' of a memory access with mode 'mode ' .


<s> static rtx aarch64_progress_pointer ( rtx pointer ) { HOST_WIDE_INT amount = GET_MODE_SIZE ( GET_MODE ( pointer ) ) ; return aarch64_move_pointer ( pointer , amount ) ; } </s>

Return a new RTX holding the result of moving POINTER forward by the size of the mode it points to .