<s> static unsigned int aarch64_autovectorize_vector_modes ( vector_modes * modes , bool ) { static const machine_mode sve_modes [ ] = { VNx16QImode , VNx8QImode , VNx4QImode , VNx2QImode } ; static const machine_mode advsimd_modes [ ] = { V16QImode , V8QImode , V4HImode , V2SImode } ; unsigned int sve_i = TARGET_SVE ? 0 : ARRAY_SIZE ( sve_modes ) ; unsigned int advsimd_i = 0 ; while ( advsimd_i < ARRAY_SIZE ( advsimd_modes ) ) { if ( sve_i < ARRAY_SIZE ( sve_modes ) && maybe_gt ( GET_MODE_NUNITS ( sve_modes [ sve_i ] ) , GET_MODE_NUNITS ( advsimd_modes [ advsimd_i ] ) ) ) modes -> safe_push ( sve_modes [ sve_i ++ ] ) ; else modes -> safe_push ( advsimd_modes [ advsimd_i ++ ] ) ; } while ( sve_i < ARRAY_SIZE ( sve_modes ) ) modes -> safe_push ( sve_modes [ sve_i ++ ] ) ; unsigned int flags = 0 ; if ( TARGET_SVE && aarch64_sve_compare_costs ) flags |= VECT_COMPARE_COSTS ; return flags ; } </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 && contains_reg_of_mode [ GENERAL_REGS ] [ GET_MODE ( SUBREG_REG ( x ) ) ] ) 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_in , machine_mode mode ) { unsigned HOST_WIDE_INT val , tmp , mask , first_one , next_one ; int bits ; val = aarch64_replicate_bitmask_imm ( val_in , mode ) ; tmp = val + ( val & - val ) ; if ( tmp == ( tmp & - tmp ) ) return ( val + 1 ) > 1 ; if ( mode == SImode ) val = ( val << 32 ) | ( val & 0xffffffff ) ; if ( val & 1 ) val = ~ val ; first_one = val & - val ; tmp = val & ( val + first_one ) ; if ( tmp == 0 ) return true ; next_one = tmp & - tmp ; bits = clz_hwi ( first_one ) - clz_hwi ( next_one ) ; mask = val ^ tmp ; if ( ( mask >> bits ) != 0 || bits != ( bits & - bits ) ) return false ; return val == mask * bitmask_imm_mul [ __builtin_clz ( bits ) - 26 ] ; } </s>

Return true if val is a valid bitmask immediate .


<s> static rtx aarch64_bit_representation ( rtx x ) { if ( CONST_DOUBLE_P ( x ) ) x = gen_lowpart ( int_mode_for_mode ( GET_MODE ( x ) ) . require ( ) , x ) ; return x ; } </s>

If X is a CONST_DOUBLE , return its bit representation as a constant integer , otherwise return X unmodified .


<s> int aarch64_branch_cost ( bool speed_p , bool predictable_p ) { const struct cpu_branch_cost * branch_costs = aarch64_tune_params . branch_costs ; if ( ! speed_p || predictable_p ) return branch_costs -> predictable ; else return branch_costs -> unpredictable ; } </s>

Return the cost of a branch . If SPEED_P is true then the compiler is optimizing for speed . If PREDICTABLE_P is true then the branch is predicted to be taken .


<s> bool aarch64_bti_enabled ( void ) { return ( aarch64_enable_bti == 1 ) ; } </s>

Return TRUE if Branch Target Identification Mechanism is enabled .


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 tree aarch64_builtin_decl ( unsigned int code , bool initialize_p ) { unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT ; switch ( code & AARCH64_BUILTIN_CLASS ) { case AARCH64_BUILTIN_GENERAL : return aarch64_general_builtin_decl ( subcode , initialize_p ) ; case AARCH64_BUILTIN_SVE : return aarch64_sve :: builtin_decl ( subcode , initialize_p ) ; } gcc_unreachable ( ) ; } </s>


<s> static tree aarch64_builtin_reciprocal ( tree fndecl ) { machine_mode mode = TYPE_MODE ( TREE_TYPE ( fndecl ) ) ; if ( ! use_rsqrt_p ( mode ) ) return NULL_TREE ; unsigned int code = DECL_MD_FUNCTION_CODE ( fndecl ) ; unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT ; switch ( code & AARCH64_BUILTIN_CLASS ) { case AARCH64_BUILTIN_GENERAL : return aarch64_general_builtin_rsqrt ( subcode ) ; case AARCH64_BUILTIN_SVE : return NULL_TREE ; } gcc_unreachable ( ) ; } </s>

Function to decide when to use the approximate reciprocal square root builtin .


Return true if the vector misalignment factor is supported by the target .


<s> static int aarch64_builtin_vectorization_cost ( enum vect_cost_for_stmt type_of_cost , tree vectype , int misalign ATTRIBUTE_UNUSED ) { unsigned elements ; const cpu_vector_cost * costs = aarch64_tune_params . vec_costs ; bool fp = false ; if ( vectype != NULL ) fp = FLOAT_TYPE_P ( vectype ) ; switch ( type_of_cost ) { case scalar_stmt : return fp ? costs -> scalar_fp_stmt_cost : costs -> scalar_int_stmt_cost ; case scalar_load : return costs -> scalar_load_cost ; case scalar_store : return costs -> scalar_store_cost ; case vector_stmt : return fp ? costs -> vec_fp_stmt_cost : costs -> vec_int_stmt_cost ; case vector_load : return costs -> vec_align_load_cost ; case vector_store : return costs -> vec_store_cost ; case vec_to_scalar : return costs -> vec_to_scalar_cost ; case scalar_to_vec : return costs -> scalar_to_vec_cost ; case unaligned_load : case vector_gather_load : return costs -> vec_unalign_load_cost ; case unaligned_store : case vector_scatter_store : return costs -> vec_unalign_store_cost ; case cond_branch_taken : return costs -> cond_taken_branch_cost ; case cond_branch_not_taken : return costs -> cond_not_taken_branch_cost ; case vec_perm : return costs -> vec_permute_cost ; case vec_promote_demote : return fp ? costs -> vec_fp_stmt_cost : costs -> vec_int_stmt_cost ; case vec_construct : elements = estimated_poly_value ( TYPE_VECTOR_SUBPARTS ( vectype ) ) ; return elements / 2 + 1 ; default : gcc_unreachable ( ) ; } } </s>


<s> static bool aarch64_can_change_mode_class ( machine_mode from , machine_mode to , reg_class_t ) { unsigned int from_flags = aarch64_classify_vector_mode ( from ) ; unsigned int to_flags = aarch64_classify_vector_mode ( to ) ; bool from_sve_p = ( from_flags & VEC_ANY_SVE ) ; bool to_sve_p = ( to_flags & VEC_ANY_SVE ) ; bool from_partial_sve_p = from_sve_p && ( from_flags & VEC_PARTIAL ) ; bool to_partial_sve_p = to_sve_p && ( to_flags & VEC_PARTIAL ) ; bool from_pred_p = ( from_flags & VEC_SVE_PRED ) ; bool to_pred_p = ( to_flags & VEC_SVE_PRED ) ; if ( from_pred_p != to_pred_p ) return false ; if ( from_partial_sve_p != to_partial_sve_p ) return false ; if ( from_partial_sve_p && ( aarch64_sve_container_bits ( from ) != aarch64_sve_container_bits ( to ) || GET_MODE_UNIT_SIZE ( from ) != GET_MODE_UNIT_SIZE ( to ) ) ) return false ; if ( maybe_ne ( BITS_PER_SVE_VECTOR , 128u ) ) { if ( from_sve_p && ! to_sve_p && maybe_gt ( GET_MODE_BITSIZE ( to ) , 128 ) ) return false ; if ( to_sve_p && ! from_sve_p && maybe_gt ( GET_MODE_BITSIZE ( from ) , 128 ) ) return false ; } if ( BYTES_BIG_ENDIAN ) { if ( from_sve_p != to_sve_p ) return false ; if ( from_sve_p && GET_MODE_UNIT_SIZE ( from ) != GET_MODE_UNIT_SIZE ( to ) ) return false ; } return true ; } </s>


<s> bool aarch64_can_const_movi_rtx_p ( rtx x , machine_mode mode ) { if ( ! TARGET_SIMD ) return false ; machine_mode vmode ; scalar_int_mode imode ; unsigned HOST_WIDE_INT ival ; if ( GET_CODE ( x ) == CONST_DOUBLE && SCALAR_FLOAT_MODE_P ( mode ) ) { if ( ! aarch64_reinterpret_float_as_int ( x , & ival ) ) return false ; if ( aarch64_float_const_zero_rtx_p ( x ) ) return true ; imode = int_mode_for_mode ( mode ) . require ( ) ; } else if ( GET_CODE ( x ) == CONST_INT && is_a < scalar_int_mode > ( mode , & imode ) ) ival = INTVAL ( x ) ; else return false ; int width = GET_MODE_BITSIZE ( imode ) == 64 ? 128 : 64 ; vmode = aarch64_simd_container_mode ( imode , width ) ; rtx v_op = aarch64_simd_gen_const_vector_dup ( vmode , ival ) ; return aarch64_simd_valid_immediate ( v_op , NULL ) ; } </s>

Return TRUE if rtx X is immediate constant that fits in a single MOVI immediate operation .


<s> static bool aarch64_can_inline_p ( tree caller , tree callee ) { tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET ( caller ) ; tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET ( callee ) ; struct cl_target_option * caller_opts = TREE_TARGET_OPTION ( caller_tree ? caller_tree : target_option_default_node ) ; struct cl_target_option * callee_opts = TREE_TARGET_OPTION ( callee_tree ? callee_tree : target_option_default_node ) ; if ( ( caller_opts -> x_aarch64_isa_flags & callee_opts -> x_aarch64_isa_flags ) != callee_opts -> x_aarch64_isa_flags ) return false ; if ( ( TARGET_STRICT_ALIGN_P ( caller_opts -> x_target_flags ) != TARGET_STRICT_ALIGN_P ( callee_opts -> x_target_flags ) ) && ! ( ! TARGET_STRICT_ALIGN_P ( callee_opts -> x_target_flags ) && TARGET_STRICT_ALIGN_P ( caller_opts -> x_target_flags ) ) ) return false ; bool always_inline = lookup_attribute ( "always_inline" , DECL_ATTRIBUTES ( callee ) ) ; if ( always_inline ) return true ; if ( caller_opts -> x_aarch64_cmodel_var != callee_opts -> x_aarch64_cmodel_var ) return false ; if ( caller_opts -> x_aarch64_tls_dialect != callee_opts -> x_aarch64_tls_dialect ) return false ; if ( ! aarch64_tribools_ok_for_inlining_p ( caller_opts -> x_aarch64_fix_a53_err835769 , callee_opts -> x_aarch64_fix_a53_err835769 , 2 , TARGET_FIX_ERR_A53_835769_DEFAULT ) ) return false ; if ( ! aarch64_tribools_ok_for_inlining_p ( caller_opts -> x_aarch64_fix_a53_err843419 , callee_opts -> x_aarch64_fix_a53_err843419 , 2 , TARGET_FIX_ERR_A53_843419 ) ) return false ; if ( ! aarch64_tribools_ok_for_inlining_p ( caller_opts -> x_flag_omit_leaf_frame_pointer , callee_opts -> x_flag_omit_leaf_frame_pointer , 2 , 1 ) ) return false ; if ( callee_opts -> x_aarch64_override_tune_string != NULL && caller_opts -> x_aarch64_override_tune_string == NULL ) return false ; if ( callee_opts -> x_aarch64_override_tune_string && caller_opts -> x_aarch64_override_tune_string && ( strcmp ( callee_opts -> x_aarch64_override_tune_string , caller_opts -> x_aarch64_override_tune_string ) != 0 ) ) return false ; return true ; } </s>

Implement TARGET_CAN_INLINE_P . Decide whether it is valid to inline CALLEE into CALLER based on target-specific info . Make sure that the caller and callee have compatible architectural features . Then go through the other possible target attributes and see if they can block inlining . Try not to reject always_inline callees unless they are incompatible architecturally .


Constant pools are per function only when PC relative literal loads are true or we are in the large memory model .


<s> static unsigned int aarch64_case_values_threshold ( void ) { if ( optimize > 2 && selected_cpu -> tune -> max_case_values != 0 ) return selected_cpu -> tune -> max_case_values ; else return optimize_size ? default_case_values_threshold ( ) : 17 ; } </s>


<s> static bool aarch64_cheap_mult_shift_p ( rtx x ) { rtx op0 , op1 ; op0 = XEXP ( x , 0 ) ; op1 = XEXP ( x , 1 ) ; if ( ! ( aarch64_tune_params . extra_tuning_flags & AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND ) ) return false ; if ( GET_CODE ( op0 ) == SIGN_EXTEND ) return false ; if ( GET_CODE ( x ) == ASHIFT && CONST_INT_P ( op1 ) && UINTVAL ( op1 ) <= 4 ) return true ; if ( GET_CODE ( x ) != MULT || ! CONST_INT_P ( op1 ) ) return false ; HOST_WIDE_INT l2 = exact_log2 ( INTVAL ( op1 ) ) ; if ( l2 > 0 && l2 <= 4 ) return true ; return false ; } </s>

Return true iff X is a cheap shift without a sign extend .


Check whether X is a VEC_SERIES-like constant that starts at 0 and has a step in the range of INDEX . Return the index expression if so , otherwise return null .


<s> static HOST_WIDE_INT aarch64_clamp_to_uimm12_shift ( HOST_WIDE_INT val ) { gcc_assert ( ( val & 0xffffff ) == val ) ; if ( ( ( val & 0xfff ) << 0 ) == val ) return val ; return val & ( 0xfff << 12 ) ; } </s>

Returns the nearest value to VAL that will fit as a 12-bit unsigned immediate that can be created with a left shift of 0 or 12 .


<s> enum aarch64_symbol_type aarch64_classify_symbol ( rtx x , HOST_WIDE_INT offset ) { 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_SPIC : case AARCH64_CMODEL_SMALL_PIC : case AARCH64_CMODEL_SMALL : return SYMBOL_SMALL_ABSOLUTE ; default : gcc_unreachable ( ) ; } } if ( GET_CODE ( x ) == SYMBOL_REF ) { if ( aarch64_tls_symbol_p ( x ) ) return aarch64_classify_tls_symbol ( x ) ; switch ( aarch64_cmodel ) { case AARCH64_CMODEL_TINY : if ( SYMBOL_REF_WEAK ( x ) && ! aarch64_symbol_binds_local_p ( x ) ) return SYMBOL_FORCE_TO_MEM ; if ( ! ( IN_RANGE ( offset , - 0x10000 , 0x10000 ) || offset_within_block_p ( x , offset ) ) ) return SYMBOL_FORCE_TO_MEM ; return SYMBOL_TINY_ABSOLUTE ; case AARCH64_CMODEL_SMALL : if ( SYMBOL_REF_WEAK ( x ) && ! aarch64_symbol_binds_local_p ( x ) ) return SYMBOL_FORCE_TO_MEM ; if ( ! ( IN_RANGE ( offset , - 0x100000 , 0x100000 ) || offset_within_block_p ( x , offset ) ) ) 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_SPIC : case AARCH64_CMODEL_SMALL_PIC : if ( ! aarch64_symbol_binds_local_p ( x ) ) return ( aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC ? SYMBOL_SMALL_GOT_28K : SYMBOL_SMALL_GOT_4G ) ; return SYMBOL_SMALL_ABSOLUTE ; case AARCH64_CMODEL_LARGE : if ( ! aarch64_pcrelative_literal_loads && CONSTANT_POOL_ADDRESS_P ( x ) ) return SYMBOL_SMALL_ABSOLUTE ; else return SYMBOL_FORCE_TO_MEM ; 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 ) { rtx offset ; split_const ( x , & x , & offset ) ; return aarch64_classify_symbol ( x , INTVAL ( offset ) ) ; } </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 : switch ( aarch64_cmodel ) { case AARCH64_CMODEL_TINY : case AARCH64_CMODEL_TINY_PIC : return SYMBOL_TINY_TLSIE ; default : return SYMBOL_SMALL_TLSIE ; } case TLS_MODEL_LOCAL_EXEC : if ( aarch64_tls_size == 12 ) return SYMBOL_TLSLE12 ; else if ( aarch64_tls_size == 24 ) return SYMBOL_TLSLE24 ; else if ( aarch64_tls_size == 32 ) return SYMBOL_TLSLE32 ; else if ( aarch64_tls_size == 48 ) return SYMBOL_TLSLE48 ; else gcc_unreachable ( ) ; 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 unsigned int aarch64_classify_vector_mode ( machine_mode mode ) { if ( aarch64_advsimd_struct_mode_p ( mode ) ) return VEC_ADVSIMD | VEC_STRUCT ; if ( aarch64_sve_pred_mode_p ( mode ) ) return VEC_SVE_PRED ; switch ( mode ) { case E_VNx2QImode : case E_VNx4QImode : case E_VNx8QImode : case E_VNx2HImode : case E_VNx4HImode : case E_VNx2SImode : case E_VNx2HFmode : case E_VNx4HFmode : case E_VNx2SFmode : return TARGET_SVE ? VEC_SVE_DATA | VEC_PARTIAL : 0 ; case E_VNx16QImode : case E_VNx8HImode : case E_VNx4SImode : case E_VNx2DImode : case E_VNx8BFmode : case E_VNx8HFmode : case E_VNx4SFmode : case E_VNx2DFmode : return TARGET_SVE ? VEC_SVE_DATA : 0 ; case E_VNx32QImode : case E_VNx16HImode : case E_VNx8SImode : case E_VNx4DImode : case E_VNx16BFmode : case E_VNx16HFmode : case E_VNx8SFmode : case E_VNx4DFmode : case E_VNx48QImode : case E_VNx24HImode : case E_VNx12SImode : case E_VNx6DImode : case E_VNx24BFmode : case E_VNx24HFmode : case E_VNx12SFmode : case E_VNx6DFmode : case E_VNx64QImode : case E_VNx32HImode : case E_VNx16SImode : case E_VNx8DImode : case E_VNx32BFmode : case E_VNx32HFmode : case E_VNx16SFmode : case E_VNx8DFmode : return TARGET_SVE ? VEC_SVE_DATA | VEC_STRUCT : 0 ; case E_V8QImode : case E_V4HImode : case E_V2SImode : case E_V4HFmode : case E_V4BFmode : case E_V2SFmode : case E_V1DFmode : case E_V16QImode : case E_V8HImode : case E_V4SImode : case E_V2DImode : case E_V8HFmode : case E_V8BFmode : case E_V4SFmode : case E_V2DFmode : return TARGET_SIMD ? VEC_ADVSIMD : 0 ; default : return 0 ; } } </s>

Return a set of flags describing the vector properties of mode MODE . Ignore modes that are not supported by the current target .


<s> static sbitmap aarch64_components_for_bb ( basic_block bb ) { bitmap in = DF_LIVE_IN ( bb ) ; bitmap gen = & DF_LIVE_BB_INFO ( bb ) -> gen ; bitmap kill = & DF_LIVE_BB_INFO ( bb ) -> kill ; sbitmap components = sbitmap_alloc ( LAST_SAVED_REGNUM + 1 ) ; bitmap_clear ( components ) ; function_abi_aggregator callee_abis ; rtx_insn * insn ; FOR_BB_INSNS ( bb , insn ) if ( CALL_P ( insn ) ) callee_abis . note_callee_abi ( insn_callee_abi ( insn ) ) ; HARD_REG_SET extra_caller_saves = callee_abis . caller_save_regs ( * crtl -> abi ) ; for ( unsigned regno = 0 ; regno <= LAST_SAVED_REGNUM ; regno ++ ) if ( ! fixed_regs [ regno ] && ! crtl -> abi -> clobbers_full_reg_p ( regno ) && ( TEST_HARD_REG_BIT ( extra_caller_saves , regno ) || bitmap_bit_p ( in , regno ) || bitmap_bit_p ( gen , regno ) || bitmap_bit_p ( kill , regno ) ) ) { bitmap_set_bit ( components , regno ) ; poly_int64 offset = cfun -> machine -> frame . reg_offset [ regno ] ; unsigned regno2 = multiple_p ( offset , 16 ) ? regno + 1 : regno - 1 ; if ( regno2 <= LAST_SAVED_REGNUM ) { poly_int64 offset2 = cfun -> machine -> frame . reg_offset [ regno2 ] ; if ( regno < regno2 ? known_eq ( offset + 8 , offset2 ) : multiple_p ( offset2 , 16 ) && known_eq ( offset2 + 8 , offset ) ) bitmap_set_bit ( components , regno2 ) ; } } return components ; } </s>


<s> static bool aarch64_composite_type_p ( const_tree type , machine_mode mode ) { if ( aarch64_short_vector_p ( type , mode ) ) return false ; 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> static int aarch64_compute_pressure_classes ( reg_class * classes ) { int i = 0 ; classes [ i ++ ] = GENERAL_REGS ; classes [ i ++ ] = FP_REGS ; classes [ i ++ ] = PR_LO_REGS ; classes [ i ++ ] = PR_HI_REGS ; return i ; } </s>


<s> static HOST_WIDE_INT aarch64_constant_alignment ( const_tree exp , HOST_WIDE_INT align ) { if ( TREE_CODE ( exp ) == STRING_CST && ! optimize_size ) return MAX ( align , BITS_PER_WORD ) ; return align ; } </s>

Implement TARGET_CONSTANT_ALIGNMENT . Make strings word-aligned so that strcpy from constants will be faster .


<s> static bool aarch64_const_vec_all_in_range_p ( rtx vec , HOST_WIDE_INT minval , HOST_WIDE_INT maxval ) { if ( GET_CODE ( vec ) != CONST_VECTOR || GET_MODE_CLASS ( GET_MODE ( vec ) ) != MODE_VECTOR_INT ) return false ; int nunits ; if ( ! CONST_VECTOR_STEPPED_P ( vec ) ) nunits = const_vector_encoded_nelts ( vec ) ; else if ( ! CONST_VECTOR_NUNITS ( vec ) . is_constant ( & nunits ) ) return false ; for ( int i = 0 ; i < nunits ; i ++ ) { rtx vec_elem = CONST_VECTOR_ELT ( vec , i ) ; if ( ! CONST_INT_P ( vec_elem ) || ! IN_RANGE ( INTVAL ( vec_elem ) , minval , maxval ) ) return false ; } return true ; } </s>

Return true if VEC is a constant in which every element is in the range [ MINVAL , MAXVAL ] . The elements do not need to have the same value .


<s> static rtx aarch64_convert_mult_to_shift ( rtx value , rtx_code & code ) { if ( GET_CODE ( value ) != CONST_VECTOR ) return NULL_RTX ; rtx_vector_builder builder ; if ( ! builder . new_unary_operation ( GET_MODE ( value ) , value , false ) ) return NULL_RTX ; scalar_mode int_mode = GET_MODE_INNER ( GET_MODE ( value ) ) ; int negate = - 1 ; unsigned int encoded_nelts = const_vector_encoded_nelts ( value ) ; for ( unsigned int i = 0 ; i < encoded_nelts ; ++ i ) { rtx elt = CONST_VECTOR_ENCODED_ELT ( value , i ) ; if ( ! CONST_SCALAR_INT_P ( elt ) ) return NULL_RTX ; rtx_mode_t val ( elt , int_mode ) ; wide_int pow2 = wi :: neg ( val ) ; if ( val != pow2 ) { if ( negate == ! wi :: neg_p ( val ) ) return NULL_RTX ; negate = wi :: neg_p ( val ) ; if ( ! negate ) pow2 = val ; } int shift = wi :: exact_log2 ( pow2 ) ; if ( shift < 0 ) return NULL_RTX ; builder . quick_push ( gen_int_mode ( shift , int_mode ) ) ; } if ( negate == - 1 ) code = PLUS ; else if ( negate == 1 ) code = code == PLUS ? MINUS : PLUS ; return builder . build ( ) ; } </s>

Check whether VALUE is a vector constant in which every element is either a power of 2 or a negated power of 2 . If so , return a constant vector of log2s , and flip CODE between PLUS and MINUS if VALUE contains negated powers of 2 . Return NULL_RTX otherwise .


<s> rtx aarch64_convert_sve_data_to_pred ( rtx target , machine_mode mode , rtx src ) { machine_mode src_mode = GET_MODE ( src ) ; return aarch64_sve_emit_int_cmp ( target , mode , NE , src_mode , src , CONST0_RTX ( src_mode ) ) ; } </s>

Use a comparison to convert integer vector SRC into MODE , which is the corresponding SVE predicate mode . Use TARGET for the result if it 's nonnull and convenient .


<s> static poly_uint16 aarch64_convert_sve_vector_bits ( aarch64_sve_vector_bits_enum value ) { if ( value == SVE_SCALABLE || ( value == SVE_128 && BYTES_BIG_ENDIAN ) ) return poly_uint16 ( 2 , 2 ) ; else return ( int ) value / 64 ; } </s>

Return the VG value associated with -msve-vector-bits= value VALUE .


Copy one MODE sized block from SRC to DST , then progress SRC and DST by MODE bytes .


<s> static machine_mode aarch64_c_mode_for_suffix ( char suffix ) { if ( suffix == 'q' ) return TFmode ; return VOIDmode ; } </s>


<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 ; else if ( PR_REGNUM_P ( regno ) ) return AARCH64_DWARF_P0 + regno - P0_REGNUM ; else if ( regno == VG_REGNUM ) return AARCH64_DWARF_VG ; return DWARF_FRAME_REGISTERS ; } </s>

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


Implement ASM_DECLARE_FUNCTION_NAME . Output the ISA features used by the function fndecl .

aarch64
"\t.arch %s\n"
"\t"
".tune %s\n"
"function"


<s> static bool aarch64_decl_is_long_call_p ( const_tree decl ATTRIBUTE_UNUSED ) { return false ; } </s>

Return true if calls to DECL should be treated as long-calls ( ie called via a register ) .


<s> static void aarch64_disqualify_components ( sbitmap , edge , sbitmap , bool ) { } </s>


<s> static unsigned int aarch64_dwarf_poly_indeterminate_value ( unsigned int i , unsigned int * factor , int * offset ) { gcc_assert ( i == 1 ) ; * factor = 2 ; * offset = 1 ; return AARCH64_DWARF_VG ; } </s>

Implement the TARGET_DWARF_POLY_INDETERMINATE_VALUE hook .


<s> rtx aarch64_eh_return_handler_rtx ( void ) { rtx tmp = gen_frame_mem ( Pmode , plus_constant ( Pmode , hard_frame_pointer_rtx , UNITS_PER_WORD ) ) ; MEM_VOLATILE_P ( tmp ) = true ; return tmp ; } </s>

Implement EH_RETURN_HANDLER_RTX . EH returns need to either return normally or return to a previous frame after unwinding . An EH return uses a single shared return sequence . The epilogue is exactly like a normal epilogue except that it has an extra input register ( EH_RETURN_STACKADJ_RTX ) which contains the stack adjustment that must be applied after the frame has been destroyed . An extra label is inserted before the epilogue which initializes this register to zero , and this is the entry point for a normal return . An actual EH return updates the return address , initializes the stack adjustment and jumps directly into the epilogue ( bypassing the zeroing of the adjustment ) . Since the return address is typically saved on the stack when a function makes a call , the saved LR must be updated outside the epilogue . This poses problems as the store is generated well before the epilogue , so the offset of LR is not known yet . Also optimizations will remove the store as it appears dead , even after the epilogue is generated ( as the base or offset for loading LR is different in many cases ) . To avoid these problems this implementation forces the frame pointer in eh_return functions so that the location of LR is fixed and known early . It also marks the store volatile , so no optimization is permitted to remove the store .


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

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


<s> bool aarch64_emit_approx_sqrt ( rtx dst , rtx src , bool recp ) { machine_mode mode = GET_MODE ( dst ) ; if ( GET_MODE_INNER ( mode ) == HFmode ) { gcc_assert ( ! recp ) ; return false ; } if ( ! recp ) { if ( ! ( flag_mlow_precision_sqrt || ( aarch64_tune_params . approx_modes -> sqrt & AARCH64_APPROX_MODE ( mode ) ) ) ) return false ; if ( ! flag_finite_math_only || flag_trapping_math || ! flag_unsafe_math_optimizations || optimize_function_for_size_p ( cfun ) ) return false ; } else gcc_assert ( use_rsqrt_p ( mode ) ) ; rtx pg = NULL_RTX ; if ( aarch64_sve_mode_p ( mode ) ) pg = aarch64_ptrue_reg ( aarch64_sve_pred_mode ( mode ) ) ; machine_mode mmsk = ( VECTOR_MODE_P ( mode ) ? related_int_vector_mode ( mode ) . require ( ) : int_mode_for_mode ( mode ) . require ( ) ) ; rtx xmsk = NULL_RTX ; if ( ! recp ) { rtx zero = CONST0_RTX ( mode ) ; if ( pg ) { xmsk = gen_reg_rtx ( GET_MODE ( pg ) ) ; rtx hint = gen_int_mode ( SVE_KNOWN_PTRUE , SImode ) ; emit_insn ( gen_aarch64_pred_fcm ( UNSPEC_COND_FCMNE , mode , xmsk , pg , hint , src , zero ) ) ; } else { xmsk = gen_reg_rtx ( mmsk ) ; emit_insn ( gen_rtx_SET ( xmsk , gen_rtx_NEG ( mmsk , gen_rtx_EQ ( mmsk , src , zero ) ) ) ) ; } } rtx xdst = gen_reg_rtx ( mode ) ; emit_insn ( gen_aarch64_rsqrte ( mode , xdst , src ) ) ; int iterations = ( GET_MODE_INNER ( mode ) == DFmode ) ? 3 : 2 ; if ( ( recp && flag_mrecip_low_precision_sqrt ) || ( ! recp && flag_mlow_precision_sqrt ) ) iterations -- ; rtx x1 = gen_reg_rtx ( mode ) ; while ( iterations -- ) { rtx x2 = gen_reg_rtx ( mode ) ; aarch64_emit_mult ( x2 , pg , xdst , xdst ) ; emit_insn ( gen_aarch64_rsqrts ( mode , x1 , src , x2 ) ) ; if ( iterations > 0 ) aarch64_emit_mult ( xdst , pg , xdst , x1 ) ; } if ( ! recp ) { if ( pg ) emit_insn ( gen_cond ( UNSPEC_COND_FMUL , mode , xdst , xmsk , xdst , src , CONST0_RTX ( mode ) ) ) ; else { rtx xtmp = gen_reg_rtx ( mmsk ) ; emit_set_insn ( xtmp , gen_rtx_AND ( mmsk , gen_rtx_NOT ( mmsk , xmsk ) , gen_rtx_SUBREG ( mmsk , xdst , 0 ) ) ) ; emit_move_insn ( xdst , gen_rtx_SUBREG ( mode , xtmp , 0 ) ) ; aarch64_emit_mult ( xdst , pg , xdst , src ) ; } } aarch64_emit_mult ( dst , pg , xdst , x1 ) ; return true ; } </s>

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


<s> static void aarch64_emit_binop ( rtx dest , optab binoptab , rtx op0 , rtx op1 ) { rtx tmp = expand_binop ( GET_MODE ( dest ) , binoptab , op0 , op1 , dest , 0 , OPTAB_DIRECT ) ; if ( dest != tmp ) emit_move_insn ( dest , tmp ) ; } </s>

Apply BINOPTAB to OP0 and OP1 and store the result in DEST .


<s> void aarch64_emit_call_insn ( rtx pat ) { rtx insn = emit_call_insn ( pat ) ; rtx * fusage = & CALL_INSN_FUNCTION_USAGE ( insn ) ; clobber_reg ( fusage , gen_rtx_REG ( word_mode , IP0_REGNUM ) ) ; clobber_reg ( fusage , gen_rtx_REG ( word_mode , IP1_REGNUM ) ) ; } </s>

Emit call insn with PAT and do aarch64-specific handling .


<s> static bool aarch64_emit_cfi_for_reg_p ( unsigned int regno ) { return ( GP_REGNUM_P ( regno ) || ! default_function_abi . clobbers_full_reg_p ( regno ) ) ; } </s>

Return true if we should emit CFI for register REGNO .


<s> static void aarch64_emit_epilogue_components ( sbitmap components ) { aarch64_process_components ( components , false ) ; } </s>


<s> static void aarch64_emit_load_exclusive ( machine_mode mode , rtx rval , rtx mem , rtx model_rtx ) { if ( mode == TImode ) emit_insn ( gen_aarch64_load_exclusive_pair ( gen_lowpart ( DImode , rval ) , gen_highpart ( DImode , rval ) , mem , model_rtx ) ) ; else emit_insn ( gen_aarch64_load_exclusive ( mode , rval , mem , model_rtx ) ) ; } </s>


<s> static rtx aarch64_emit_move ( rtx dest , rtx src ) { return ( can_create_pseudo_p ( ) ? emit_move_insn ( dest , src ) : emit_move_insn_1 ( dest , src ) ) ; } </s>

Emit a move from SRC to DEST . Assume that the move expanders can handle all moves if ! can_create_pseudo_p ( ) . The distinction is important because , unlike emit_move_insn , the move expanders know how to force Pmode objects into the constant pool even when the constant pool address is not itself legitimate .


<s> static void aarch64_emit_mult ( rtx dst , rtx ptrue , rtx src1 , rtx src2 ) { if ( ptrue ) emit_insn ( gen_aarch64_pred ( UNSPEC_COND_FMUL , GET_MODE ( dst ) , dst , ptrue , src1 , src2 , gen_int_mode ( SVE_RELAXED_GP , SImode ) ) ) ; else emit_set_insn ( dst , gen_rtx_MULT ( GET_MODE ( dst ) , src1 , src2 ) ) ; } </s>

Emit code to perform the floating-point operation : DST = SRC1 * SRC2 where all three operands are already known to be registers . If the operation is an SVE one , PTRUE is a suitable all-true predicate .


<s> static void aarch64_emit_post_barrier ( enum memmodel model ) { const enum memmodel base_model = memmodel_base ( model ) ; if ( is_mm_sync ( model ) && ( base_model == MEMMODEL_ACQUIRE || base_model == MEMMODEL_ACQ_REL || base_model == MEMMODEL_SEQ_CST ) ) { emit_insn ( gen_mem_thread_fence ( GEN_INT ( MEMMODEL_SEQ_CST ) ) ) ; } } </s>

Emit a barrier , that is appropriate for memory model MODEL , at the end of a sequence implementing an atomic operation .


<s>
static
void
aarch64_emit_probe_stack_range
(
HOST_WIDE_INT
first
,
poly_int64
poly_size
)
{
HOST_WIDE_INT
size
;
if
(
!
poly_size
.
is_constant
(
&
size
)
)
{
sorry
(
"stack probes for SVE frames"
)
;
return
;
}
rtx
reg1
=
gen_rtx_REG
(
Pmode
,
PROBE_STACK_FIRST_REG
)
;
gcc_assert
(
(
first
%
ARITH_FACTOR
)
==
0
)
;
if
(
size
<=
PROBE_INTERVAL
)
{
const
HOST_WIDE_INT
base
=
ROUND_UP
(
size
,
ARITH_FACTOR
)
;
emit_set_insn
(
reg1
,
plus_constant
(
Pmode
,
stack_pointer_rtx
,
(
first
+
base
)
)
)
;
emit_stack_probe
(
plus_constant
(
Pmode
,
reg1
,
base
size
)
)
;
}
else
if
(
size
<=
4
*
PROBE_INTERVAL
)
{
HOST_WIDE_INT
i
,
rem
;
emit_set_insn
(
reg1
,
plus_constant
(
Pmode
,
stack_pointer_rtx
,
(
first
+
PROBE_INTERVAL
)
)
)
;
emit_stack_probe
(
reg1
)
;
for
(
i
=
2
*
PROBE_INTERVAL
;
i
<
size
;
i
+=
PROBE_INTERVAL
)
{
emit_set_insn
(
reg1
,
plus_constant
(
Pmode
,
reg1
,
PROBE_INTERVAL
)
)
;
emit_stack_probe
(
reg1
)
;
}
rem
=
size
(
i
PROBE_INTERVAL
)
;
if
(
rem
>
256
)
{
const
HOST_WIDE_INT
base
=
ROUND_UP
(
rem
,
ARITH_FACTOR
)
;
emit_set_insn
(
reg1
,
plus_constant
(
Pmode
,
reg1
,
base
)
)
;
emit_stack_probe
(
plus_constant
(
Pmode
,
reg1
,
base
rem
)
)
;
}
else
emit_stack_probe
(
plus_constant
(
Pmode
,
reg1
,
rem
)
)
;
}
else
{
rtx
reg2
=
gen_rtx_REG
(
Pmode
,
PROBE_STACK_SECOND_REG
)
;
HOST_WIDE_INT
rounded_size
=
size
&
PROBE_INTERVAL
;
emit_set_insn
(
reg1
,
plus_constant
(
Pmode
,
stack_pointer_rtx
,
first
)
)
;
HOST_WIDE_INT
adjustment
=
(
first
+
rounded_size
)
;
if
(
!
aarch64_uimm12_shift
(
adjustment
)
)
{
aarch64_internal_mov_immediate
(
reg2
,
GEN_INT
(
adjustment
)
,
true
,
Pmode
)
;
emit_set_insn
(
reg2
,
gen_rtx_PLUS
(
Pmode
,
stack_pointer_rtx
,
reg2
)
)
;
}
else
emit_set_insn
(
reg2
,
plus_constant
(
Pmode
,
stack_pointer_rtx
,
adjustment
)
)
;
emit_insn
(
gen_probe_stack_range
(
reg1
,
reg1
,
reg2
)
)
;
if
(
size
!=
rounded_size
)
{
HOST_WIDE_INT
rem
=
size
rounded_size
;
if
(
rem
>
256
)
{
const
HOST_WIDE_INT
base
=
ROUND_UP
(
rem
,
ARITH_FACTOR
)
;
emit_set_insn
(
reg2
,
plus_constant
(
Pmode
,
reg2
,
base
)
)
;
emit_stack_probe
(
plus_constant
(
Pmode
,
reg2
,
base
rem
)
)
;
}
else
emit_stack_probe
(
plus_constant
(
Pmode
,
reg2
,
rem
)
)
;
}
}
emit_insn
(
gen_blockage
(
)
)
;
}
</s>

Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE , inclusive . These are offsets from the current stack pointer .


<s> static void aarch64_emit_prologue_components ( sbitmap components ) { aarch64_process_components ( components , true ) ; } </s>


<s> static rtx aarch64_emit_set_immediate ( rtx target , rtx_vector_builder & builder ) { rtx src = builder . build ( ) ; target = aarch64_target_reg ( target , GET_MODE ( src ) ) ; emit_insn ( gen_rtx_SET ( target , src ) ) ; return target ; } </s>

Return a register that contains the constant in BUILDER , given that the constant is a legitimate move operand . Use TARGET as the register if it is nonnull and convenient .


<s> static void aarch64_emit_store_exclusive ( machine_mode mode , rtx bval , rtx mem , rtx rval , rtx model_rtx ) { if ( mode == TImode ) emit_insn ( gen_aarch64_store_exclusive_pair ( bval , mem , operand_subword ( rval , 0 , 0 , TImode ) , operand_subword ( rval , 1 , 0 , TImode ) , model_rtx ) ) ; else emit_insn ( gen_aarch64_store_exclusive ( mode , bval , mem , rval , model_rtx ) ) ; } </s>


<s> static void aarch64_emit_sve_fp_cond ( rtx target , rtx_code code , rtx pred , bool known_ptrue_p , rtx op0 , rtx op1 ) { rtx flag = gen_int_mode ( known_ptrue_p , SImode ) ; rtx unspec = gen_rtx_UNSPEC ( GET_MODE ( pred ) , gen_rtvec ( 4 , pred , flag , op0 , op1 ) , aarch64_unspec_cond_code ( code ) ) ; emit_set_insn ( target , unspec ) ; } </s>

Emit : ( set TARGET ( unspec [ PRED KNOWN_PTRUE_P OP0 OP1 ] UNSPEC_COND_ < X > ) ) where < X > is the operation associated with comparison CODE . KNOWN_PTRUE_P is true if PRED is known to be a PTRUE .


<s> static void aarch64_emit_sve_invert_fp_cond ( rtx target , rtx_code code , rtx pred , bool known_ptrue_p , rtx op0 , rtx op1 ) { machine_mode pred_mode = GET_MODE ( pred ) ; rtx tmp = gen_reg_rtx ( pred_mode ) ; aarch64_emit_sve_fp_cond ( tmp , code , pred , known_ptrue_p , op0 , op1 ) ; aarch64_emit_unop ( target , one_cmpl_optab , tmp ) ; } </s>

Emit the SVE equivalent of : ( set TMP ( unspec [ PRED KNOWN_PTRUE_P OP0 OP1 ] UNSPEC_COND_ < X > ) ) ( set TARGET ( not TMP ) ) where < X > is the operation associated with comparison CODE . KNOWN_PTRUE_P is true if PRED is known to be a PTRUE .


Emit the SVE equivalent of : ( set TMP1 ( unspec [ PRED KNOWN_PTRUE_P OP0 OP1 ] UNSPEC_COND_ < X1 > ) ) ( set TMP2 ( unspec [ PRED KNOWN_PTRUE_P OP0 OP1 ] UNSPEC_COND_ < X2 > ) ) ( set TARGET ( ior : PRED_MODE TMP1 TMP2 ) ) where < Xi > is the operation associated with comparison CODEi . KNOWN_PTRUE_P is true if PRED is known to be a PTRUE .


<s> void aarch64_emit_sve_pred_move ( rtx dest , rtx pred , rtx src ) { expand_operand ops [ 3 ] ; machine_mode mode = GET_MODE ( dest ) ; create_output_operand ( & ops [ 0 ] , dest , mode ) ; create_input_operand ( & ops [ 1 ] , pred , GET_MODE ( pred ) ) ; create_input_operand ( & ops [ 2 ] , src , mode ) ; temporary_volatile_ok v ( true ) ; expand_insn ( code_for_aarch64_pred_mov ( mode ) , 3 , ops ) ; } </s>

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


<s> static void aarch64_emit_unlikely_jump ( rtx insn ) { rtx_insn * jump = emit_jump_insn ( insn ) ; add_reg_br_prob_note ( jump , profile_probability :: very_unlikely ( ) ) ; } </s>

Mark the previous jump instruction as unlikely .


<s> static void aarch64_emit_unop ( rtx dest , optab unoptab , rtx op ) { rtx tmp = expand_unop ( GET_MODE ( dest ) , unoptab , op , dest , 0 ) ; if ( dest != tmp ) emit_move_insn ( dest , tmp ) ; } </s>

Apply UNOPTAB to OP and store the result in DEST .


<s> static bool aarch64_empty_mask_is_expensive ( unsigned ) { return false ; } </s>


<s> rtx aarch64_endian_lane_rtx ( machine_mode mode , unsigned int n ) { return gen_int_mode ( ENDIAN_LANE_N ( GET_MODE_NUNITS ( mode ) , n ) , SImode ) ; } </s>

Peform endian correction on lane number N , which indexes a vector of mode MODE , and return the result as an SImode rtx .


<s> int aarch64_epilogue_uses ( int regno ) { if ( epilogue_completed ) { if ( regno == LR_REGNUM ) return 1 ; } return 0 ; } </s>

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


<s> static HOST_WIDE_INT aarch64_estimated_poly_value ( poly_int64 val ) { enum aarch64_sve_vector_bits_enum width_source = aarch64_tune_params . sve_width ; if ( width_source == SVE_SCALABLE ) return default_estimated_poly_value ( val ) ; HOST_WIDE_INT over_128 = width_source - 128 ; return val . coeffs [ 0 ] + val . coeffs [ 1 ] * over_128 / 128 ; } </s>

Implement TARGET_ESTIMATED_POLY_VALUE . Look into the tuning structure for an estimate . KIND specifies the type of requested estimate : min , max or likely . For cores with a known SVE width all three estimates are the same . For generic SVE tuning we want to distinguish the maximum estimate from the minimum and likely ones . The likely estimate is the same as the minimum in that case to give a conservative behavior of auto-vectorizing with SVE when it is a win even for 128-bit SVE . When SVE width information is available VAL.coeffs [ 1 ] is multiplied by the number of VQ chunks over the initial Advanced SIMD 128 bits .


<s> static bool aarch64_evpc_ext ( struct expand_vec_perm_d * d ) { HOST_WIDE_INT location ; rtx offset ; if ( d -> vec_flags == VEC_SVE_PRED || ! d -> perm [ 0 ] . is_constant ( & location ) || ! d -> perm . series_p ( 0 , 1 , location , 1 ) ) return false ; if ( d -> testing_p ) return true ; if ( BYTES_BIG_ENDIAN && location != 0 && d -> vec_flags == VEC_ADVSIMD ) { std :: swap ( d -> op0 , d -> op1 ) ; location = d -> perm . length ( ) . to_constant ( ) - location ; } offset = GEN_INT ( location ) ; emit_set_insn ( d -> target , gen_rtx_UNSPEC ( d -> vmode , gen_rtvec ( 3 , d -> op0 , d -> op1 , offset ) , UNSPEC_EXT ) ) ; return true ; } </s>


<s> static bool aarch64_evpc_rev_global ( struct expand_vec_perm_d * d ) { poly_uint64 nelt = d -> perm . length ( ) ; if ( ! d -> one_vector_p || d -> vec_flags == VEC_ADVSIMD ) return false ; if ( ! d -> perm . series_p ( 0 , 1 , nelt - 1 , - 1 ) ) return false ; if ( d -> testing_p ) return true ; rtx src = gen_rtx_UNSPEC ( d -> vmode , gen_rtvec ( 1 , d -> op0 ) , UNSPEC_REV ) ; emit_set_insn ( d -> target , src ) ; return true ; } </s>

Recognize patterns for the REV insn , which reverses elements within a full vector .


<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 ) ) return false ; size = ( diff + 1 ) * GET_MODE_UNIT_SIZE ( d -> vmode ) ; if ( size == 8 ) { unspec = UNSPEC_REV64 ; pred_mode = VNx2BImode ; } else if ( size == 4 ) { unspec = UNSPEC_REV32 ; pred_mode = VNx4BImode ; } else if ( size == 2 ) { 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 ) { machine_mode int_mode = aarch64_sve_int_mode ( pred_mode ) ; rtx target = gen_reg_rtx ( int_mode ) ; if ( BYTES_BIG_ENDIAN ) emit_insn ( gen_aarch64_sve_reinterpret ( int_mode , target , d -> op0 ) ) ; else { int unspec = aarch64_sve_rev_unspec ( d -> vmode ) ; rtx pred = aarch64_ptrue_reg ( pred_mode ) ; emit_insn ( gen_aarch64_pred ( unspec , int_mode , target , pred , gen_lowpart ( int_mode , d -> op0 ) ) ) ; } emit_move_insn ( d -> target , gen_lowpart ( d -> vmode , target ) ) ; 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 .


<s> static bool aarch64_evpc_sel ( struct expand_vec_perm_d * d ) { machine_mode vmode = d -> vmode ; int unit_size = GET_MODE_UNIT_SIZE ( vmode ) ; if ( d -> vec_flags != VEC_SVE_DATA || unit_size > 8 ) return false ; int n_patterns = d -> perm . encoding ( ) . npatterns ( ) ; poly_int64 vec_len = d -> perm . length ( ) ; for ( int i = 0 ; i < n_patterns ; ++ i ) if ( ! known_eq ( d -> perm [ i ] , i ) && ! known_eq ( d -> perm [ i ] , vec_len + i ) ) return false ; for ( int i = n_patterns ; i < n_patterns * 2 ; i ++ ) if ( ! d -> perm . series_p ( i , n_patterns , i , n_patterns ) && ! d -> perm . series_p ( i , n_patterns , vec_len + i , n_patterns ) ) return false ; if ( d -> testing_p ) return true ; machine_mode pred_mode = aarch64_sve_pred_mode ( vmode ) ; rtx_vector_builder builder ( pred_mode , n_patterns , 2 ) ; for ( int i = 0 ; i < n_patterns * 2 ; i ++ ) { rtx elem = known_eq ( d -> perm [ i ] , i ) ? CONST1_RTX ( BImode ) : CONST0_RTX ( BImode ) ; builder . quick_push ( elem ) ; } rtx const_vec = builder . build ( ) ; rtx pred = force_reg ( pred_mode , const_vec ) ; emit_insn ( gen_vcond_mask ( vmode , vmode , d -> target , d -> op0 , d -> op1 , pred ) ) ; return true ; } </s>

Try to implement D using SVE SEL instruction .


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

Try to implement D using an SVE TBL instruction .


<s> static bool aarch64_evpc_trn ( struct expand_vec_perm_d * d ) { HOST_WIDE_INT odd ; poly_uint64 nelt = d -> perm . length ( ) ; rtx out , in0 , in1 , x ; machine_mode vmode = d -> vmode ; if ( GET_MODE_UNIT_SIZE ( vmode ) > 8 ) return false ; if ( ! d -> perm [ 0 ] . is_constant ( & odd ) || ( odd != 0 && odd != 1 ) || ! d -> perm . series_p ( 0 , 2 , odd , 2 ) || ! d -> perm . series_p ( 1 , 2 , nelt + odd , 2 ) ) return false ; if ( d -> testing_p ) return true ; in0 = d -> op0 ; in1 = d -> op1 ; if ( BYTES_BIG_ENDIAN && d -> vec_flags == VEC_ADVSIMD ) { x = in0 , in0 = in1 , in1 = x ; odd = ! odd ; } out = d -> target ; emit_set_insn ( out , gen_rtx_UNSPEC ( vmode , gen_rtvec ( 2 , in0 , in1 ) , odd ? UNSPEC_TRN2 : UNSPEC_TRN1 ) ) ; return true ; } </s>

Recognize patterns suitable for the TRN instructions .


<s> static bool aarch64_evpc_uzp ( struct expand_vec_perm_d * d ) { HOST_WIDE_INT odd ; rtx out , in0 , in1 , x ; machine_mode vmode = d -> vmode ; if ( GET_MODE_UNIT_SIZE ( vmode ) > 8 ) return false ; if ( ! d -> perm [ 0 ] . is_constant ( & odd ) || ( odd != 0 && odd != 1 ) || ! d -> perm . series_p ( 0 , 1 , odd , 2 ) ) return false ; if ( d -> testing_p ) return true ; in0 = d -> op0 ; in1 = d -> op1 ; if ( BYTES_BIG_ENDIAN && d -> vec_flags == VEC_ADVSIMD ) { x = in0 , in0 = in1 , in1 = x ; odd = ! odd ; } out = d -> target ; emit_set_insn ( out , gen_rtx_UNSPEC ( vmode , gen_rtvec ( 2 , in0 , in1 ) , odd ? UNSPEC_UZP2 : UNSPEC_UZP1 ) ) ; return true ; } </s>

Recognize patterns suitable for the UZP instructions .


<s> static bool aarch64_evpc_zip ( struct expand_vec_perm_d * d ) { unsigned int high ; poly_uint64 nelt = d -> perm . length ( ) ; rtx out , in0 , in1 , x ; machine_mode vmode = d -> vmode ; if ( GET_MODE_UNIT_SIZE ( vmode ) > 8 ) return false ; poly_uint64 first = d -> perm [ 0 ] ; if ( ( maybe_ne ( first , 0U ) && maybe_ne ( first * 2 , nelt ) ) || ! d -> perm . series_p ( 0 , 2 , first , 1 ) || ! d -> perm . series_p ( 1 , 2 , first + nelt , 1 ) ) return false ; high = maybe_ne ( first , 0U ) ; if ( d -> testing_p ) return true ; in0 = d -> op0 ; in1 = d -> op1 ; if ( BYTES_BIG_ENDIAN && d -> vec_flags == VEC_ADVSIMD ) { x = in0 , in0 = in1 , in1 = x ; high = ! high ; } out = d -> target ; emit_set_insn ( out , gen_rtx_UNSPEC ( vmode , gen_rtvec ( 2 , in0 , in1 ) , high ? UNSPEC_ZIP2 : UNSPEC_ZIP1 ) ) ; return true ; } </s>

Recognize patterns suitable for the ZIP instructions .


<s> static enum flt_eval_method aarch64_excess_precision ( enum excess_precision_type type ) { switch ( type ) { case EXCESS_PRECISION_TYPE_FAST : case EXCESS_PRECISION_TYPE_STANDARD : return ( TARGET_FP_F16INST ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 : FLT_EVAL_METHOD_PROMOTE_TO_FLOAT ) ; case EXCESS_PRECISION_TYPE_IMPLICIT : return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 ; default : gcc_unreachable ( ) ; } return FLT_EVAL_METHOD_UNPREDICTABLE ; } </s>

Set the value of FLT_EVAL_METHOD . ISO/IEC TS 18661-3 defines two values that we 'd like to make use of : 0 : evaluate all operations and constants , whose semantic type has at most the range and precision of type float , to the range and precision of float ; evaluate all other operations and constants to the range and precision of the semantic type ; N , where _FloatN is a supported interchange floating type evaluate all operations and constants , whose semantic type has at most the range and precision of _FloatN type , to the range and precision of the _FloatN type ; evaluate all other operations and constants to the range and precision of the semantic type ; If we have the ARMv8.2-A extensions then we support _Float16 in native precision , so we should set this to 16 . Otherwise , we support the type , but want to evaluate expressions in float precision , so set this to 0 .


<s> static rtx aarch64_expand_builtin ( tree exp , rtx target , rtx , machine_mode , int ignore ) { tree fndecl = TREE_OPERAND ( CALL_EXPR_FN ( exp ) , 0 ) ; unsigned int code = DECL_MD_FUNCTION_CODE ( fndecl ) ; unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT ; switch ( code & AARCH64_BUILTIN_CLASS ) { case AARCH64_BUILTIN_GENERAL : return aarch64_general_expand_builtin ( subcode , exp , target , ignore ) ; case AARCH64_BUILTIN_SVE : return aarch64_sve :: expand_builtin ( subcode , exp , target ) ; } gcc_unreachable ( ) ; } </s>


<s> static void aarch64_expand_builtin_va_start ( tree valist , rtx nextarg ATTRIBUTE_UNUSED ) { const CUMULATIVE_ARGS * cum ; tree f_stack , f_grtop , f_vrtop , f_groff , f_vroff ; tree stack , grtop , vrtop , groff , vroff ; tree t ; int gr_save_area_size = cfun -> va_list_gpr_size ; int vr_save_area_size = cfun -> va_list_fpr_size ; int vr_offset ; cum = & crtl -> args . info ; if ( cfun -> va_list_gpr_size ) gr_save_area_size = MIN ( ( NUM_ARG_REGS - cum -> aapcs_ncrn ) * UNITS_PER_WORD , cfun -> va_list_gpr_size ) ; if ( cfun -> va_list_fpr_size ) vr_save_area_size = MIN ( ( NUM_FP_ARG_REGS - cum -> aapcs_nvrn ) * UNITS_PER_VREG , cfun -> va_list_fpr_size ) ; if ( ! TARGET_FLOAT ) { gcc_assert ( cum -> aapcs_nvrn == 0 ) ; vr_save_area_size = 0 ; } f_stack = TYPE_FIELDS ( va_list_type_node ) ; f_grtop = DECL_CHAIN ( f_stack ) ; f_vrtop = DECL_CHAIN ( f_grtop ) ; f_groff = DECL_CHAIN ( f_vrtop ) ; f_vroff = DECL_CHAIN ( f_groff ) ; stack = build3 ( COMPONENT_REF , TREE_TYPE ( f_stack ) , valist , f_stack , NULL_TREE ) ; grtop = build3 ( COMPONENT_REF , TREE_TYPE ( f_grtop ) , valist , f_grtop , NULL_TREE ) ; vrtop = build3 ( COMPONENT_REF , TREE_TYPE ( f_vrtop ) , valist , f_vrtop , NULL_TREE ) ; groff = build3 ( COMPONENT_REF , TREE_TYPE ( f_groff ) , valist , f_groff , NULL_TREE ) ; vroff = build3 ( COMPONENT_REF , TREE_TYPE ( f_vroff ) , valist , f_vroff , NULL_TREE ) ; t = make_tree ( TREE_TYPE ( stack ) , virtual_incoming_args_rtx ) ; if ( cum -> aapcs_stack_size > 0 ) t = fold_build_pointer_plus_hwi ( t , cum -> aapcs_stack_size * UNITS_PER_WORD ) ; t = build2 ( MODIFY_EXPR , TREE_TYPE ( stack ) , stack , t ) ; expand_expr ( t , const0_rtx , VOIDmode , EXPAND_NORMAL ) ; t = make_tree ( TREE_TYPE ( grtop ) , virtual_incoming_args_rtx ) ; t = build2 ( MODIFY_EXPR , TREE_TYPE ( grtop ) , grtop , t ) ; expand_expr ( t , const0_rtx , VOIDmode , EXPAND_NORMAL ) ; t = make_tree ( TREE_TYPE ( vrtop ) , virtual_incoming_args_rtx ) ; vr_offset = ROUND_UP ( gr_save_area_size , STACK_BOUNDARY / BITS_PER_UNIT ) ; if ( vr_offset ) t = fold_build_pointer_plus_hwi ( t , - vr_offset ) ; t = build2 ( MODIFY_EXPR , TREE_TYPE ( vrtop ) , vrtop , t ) ; expand_expr ( t , const0_rtx , VOIDmode , EXPAND_NORMAL ) ; t = build2 ( MODIFY_EXPR , TREE_TYPE ( groff ) , groff , build_int_cst ( TREE_TYPE ( groff ) , - gr_save_area_size ) ) ; expand_expr ( t , const0_rtx , VOIDmode , EXPAND_NORMAL ) ; t = build2 ( MODIFY_EXPR , TREE_TYPE ( vroff ) , vroff , build_int_cst ( TREE_TYPE ( vroff ) , - vr_save_area_size ) ) ; expand_expr ( t , const0_rtx , VOIDmode , EXPAND_NORMAL ) ; } </s>


<s> void aarch64_expand_call ( rtx result , rtx mem , rtx callee_abi , bool sibcall ) { rtx call , callee , tmp ; rtvec vec ; machine_mode mode ; gcc_assert ( MEM_P ( mem ) ) ; callee = XEXP ( mem , 0 ) ; mode = GET_MODE ( callee ) ; gcc_assert ( mode == Pmode ) ; if ( SYMBOL_REF_P ( callee ) ? ( aarch64_is_long_call_p ( callee ) || aarch64_is_noplt_call_p ( callee ) ) : ! REG_P ( callee ) ) XEXP ( mem , 0 ) = force_reg ( mode , callee ) ; call = gen_rtx_CALL ( VOIDmode , mem , const0_rtx ) ; if ( result != NULL_RTX ) call = gen_rtx_SET ( result , call ) ; if ( sibcall ) tmp = ret_rtx ; else tmp = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( Pmode , LR_REGNUM ) ) ; gcc_assert ( CONST_INT_P ( callee_abi ) ) ; callee_abi = gen_rtx_UNSPEC ( DImode , gen_rtvec ( 1 , callee_abi ) , UNSPEC_CALLEE_ABI ) ; vec = gen_rtvec ( 3 , call , callee_abi , tmp ) ; call = gen_rtx_PARALLEL ( VOIDmode , vec ) ; aarch64_emit_call_insn ( call ) ; } </s>

This function is used by the call expanders of the machine description . RESULT is the register in which the result is returned . It 's NULL for `` call '' and `` sibcall '' . MEM is the location of the function call . SIBCALL indicates whether this function call is normal call or sibling call . It will generate different pattern accordingly .


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


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


<s> void aarch64_expand_subvti ( rtx op0 , rtx low_dest , rtx low_in1 , rtx low_in2 , rtx high_dest , rtx high_in1 , rtx high_in2 , bool unsigned_p ) { if ( low_in2 == const0_rtx ) { low_dest = low_in1 ; high_in2 = force_reg ( DImode , high_in2 ) ; if ( unsigned_p ) emit_insn ( gen_subdi3_compare1 ( high_dest , high_in1 , high_in2 ) ) ; else emit_insn ( gen_subvdi_insn ( high_dest , high_in1 , high_in2 ) ) ; } else { if ( aarch64_plus_immediate ( low_in2 , DImode ) ) emit_insn ( gen_subdi3_compare1_imm ( low_dest , low_in1 , low_in2 , GEN_INT ( - INTVAL ( low_in2 ) ) ) ) ; else { low_in2 = force_reg ( DImode , low_in2 ) ; emit_insn ( gen_subdi3_compare1 ( low_dest , low_in1 , low_in2 ) ) ; } high_in2 = force_reg ( DImode , high_in2 ) ; if ( unsigned_p ) emit_insn ( gen_usubdi3_carryinC ( high_dest , high_in1 , high_in2 ) ) ; else emit_insn ( gen_subdi3_carryinV ( high_dest , high_in1 , high_in2 ) ) ; } emit_move_insn ( gen_lowpart ( DImode , op0 ) , low_dest ) ; emit_move_insn ( gen_highpart ( DImode , op0 ) , high_dest ) ; } </s>

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


<s> static rtx aarch64_expand_sve_const_pred ( rtx target , rtx_vector_builder & builder ) { if ( rtx res = aarch64_expand_sve_const_pred_1 ( target , builder , true ) ) return res ; if ( builder . full_nelts ( ) . is_constant ( ) ) if ( rtx mem = force_const_mem ( VNx16BImode , builder . build ( ) ) ) { target = aarch64_target_reg ( target , VNx16BImode ) ; emit_move_insn ( target , mem ) ; return target ; } rtx_vector_builder int_builder ( VNx16QImode , builder . npatterns ( ) , builder . nelts_per_pattern ( ) ) ; for ( unsigned int i = 0 ; i < builder . encoded_nelts ( ) ; ++ i ) int_builder . quick_push ( INTVAL ( builder . elt ( i ) ) ? constm1_rtx : const0_rtx ) ; return aarch64_convert_sve_data_to_pred ( target , VNx16BImode , int_builder . build ( ) ) ; } </s>

Return an SVE predicate register that contains the VNx16BImode constant in BUILDER , without going through the move expanders . The returned register can have whatever mode seems most natural given the contents of BUILDER . Use TARGET for the result if convenient .


<s> static rtx aarch64_expand_sve_const_pred_1 ( rtx target , rtx_vector_builder & builder , bool allow_recurse_p ) { if ( builder . encoded_nelts ( ) == 1 ) return aarch64_emit_set_immediate ( target , builder ) ; unsigned int elt_size = aarch64_widest_sve_pred_elt_size ( builder ) ; if ( int vl = aarch64_partial_ptrue_length ( builder , elt_size ) ) { machine_mode mode = aarch64_sve_pred_mode ( elt_size ) . require ( ) ; if ( aarch64_svpattern_for_vl ( mode , vl ) != AARCH64_NUM_SVPATTERNS ) return aarch64_emit_set_immediate ( target , builder ) ; return aarch64_sve_move_pred_via_while ( target , mode , vl ) ; } if ( ! allow_recurse_p ) return NULL_RTX ; if ( INTVAL ( builder . elt ( 0 ) ) == 0 ) if ( rtx res = aarch64_expand_sve_const_pred_eor ( target , builder , elt_size ) ) return res ; for ( unsigned int i = elt_size ; i <= 8 ; i *= 2 ) if ( rtx res = aarch64_expand_sve_const_pred_trn ( target , builder , elt_size , i ) ) return res ; return NULL_RTX ; } </s>

Subroutine of aarch64_expand_sve_const_pred . Try to load the VNx16BI constant in BUILDER into an SVE predicate register . Return the register on success , otherwise return null . Use TARGET for the register if nonnull and convenient . ALLOW_RECURSE_P is true if we can use methods that would call this function recursively .


<s> static rtx aarch64_expand_sve_const_pred_eor ( rtx target , rtx_vector_builder & builder , unsigned int elt_size ) { rtx_vector_builder inv_builder ( VNx16BImode , builder . npatterns ( ) , builder . nelts_per_pattern ( ) ) ; for ( unsigned int i = 0 ; i < builder . encoded_nelts ( ) ; ++ i ) if ( ( i & ( elt_size - 1 ) ) == 0 && INTVAL ( builder . elt ( i ) ) == 0 ) inv_builder . quick_push ( const1_rtx ) ; else inv_builder . quick_push ( const0_rtx ) ; inv_builder . finalize ( ) ; rtx inv = aarch64_expand_sve_const_pred_1 ( NULL_RTX , inv_builder , false ) ; if ( ! inv ) return NULL_RTX ; rtx mask = aarch64_ptrue_all ( elt_size ) ; mask = force_reg ( VNx16BImode , mask ) ; inv = gen_lowpart ( VNx16BImode , inv ) ; target = aarch64_target_reg ( target , VNx16BImode ) ; emit_insn ( gen_aarch64_pred_z ( XOR , VNx16BImode , target , mask , inv , mask ) ) ; 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 by inverting every element at a multiple of ELT_SIZE and EORing the result with an ELT_SIZE PTRUE . Return a register that contains the constant on success , otherwise return null . Use TARGET as the register if it is nonnull and convenient .


<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 , mode ) ; emit_insn ( gen_aarch64_sve ( UNSPEC_TRN1 , mode , target , gen_lowpart ( mode , a ) , gen_lowpart ( mode , b ) ) ) ; 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> rtx aarch64_expand_sve_dupq ( rtx target , machine_mode mode , rtx src ) { machine_mode src_mode = GET_MODE ( src ) ; gcc_assert ( GET_MODE_INNER ( mode ) == GET_MODE_INNER ( src_mode ) ) ; insn_code icode = ( BYTES_BIG_ENDIAN ? code_for_aarch64_vec_duplicate_vq_be ( mode ) : code_for_aarch64_vec_duplicate_vq_le ( mode ) ) ; unsigned int i = 0 ; expand_operand ops [ 3 ] ; create_output_operand ( & ops [ i ++ ] , target , mode ) ; create_output_operand ( & ops [ i ++ ] , src , src_mode ) ; if ( BYTES_BIG_ENDIAN ) { unsigned int nelts_per_vq = 128 / GET_MODE_UNIT_BITSIZE ( mode ) ; rtx sel = aarch64_gen_stepped_int_parallel ( nelts_per_vq , nelts_per_vq - 1 , - 1 ) ; create_fixed_operand ( & ops [ i ++ ] , sel ) ; } expand_insn ( icode , i , ops ) ; return ops [ 0 ] . value ; } </s>

Duplicate 128-bit Advanced SIMD vector SRC so that it fills an SVE register of mode MODE . Use TARGET for the result if it 's nonnull and convenient . The two vector modes must have the same element mode . The behavior is to duplicate architectural lane N of SRC into architectural lanes N + I * STEP of the result . On big-endian targets , architectural lane 0 of an Advanced SIMD vector is the last element of the vector in memory layout , so for big-endian targets this operation has the effect of reversing SRC before duplicating it . Callers need to account for this .


<s> static bool aarch64_expand_sve_ld1rq ( rtx dest , rtx src ) { src = force_const_mem ( GET_MODE ( src ) , src ) ; if ( ! src ) return false ; if ( ! aarch64_sve_ld1rq_operand_p ( src ) ) { rtx addr = force_reg ( Pmode , XEXP ( src , 0 ) ) ; src = replace_equiv_address ( src , addr ) ; } machine_mode mode = GET_MODE ( dest ) ; machine_mode pred_mode = aarch64_sve_pred_mode ( mode ) ; rtx ptrue = aarch64_ptrue_reg ( pred_mode ) ; emit_insn ( gen_aarch64_sve_ld1rq ( mode , dest , src , ptrue ) ) ; return true ; } </s>

Try to force 128-bit vector value SRC into memory and use LD1RQ to fetch the memory image into DEST . Return true on success .


<s> void aarch64_expand_sve_mem_move ( rtx dest , rtx src , machine_mode pred_mode ) { machine_mode mode = GET_MODE ( dest ) ; rtx ptrue = aarch64_ptrue_reg ( pred_mode ) ; if ( ! register_operand ( src , mode ) && ! register_operand ( dest , mode ) ) { rtx tmp = gen_reg_rtx ( mode ) ; if ( MEM_P ( src ) ) aarch64_emit_sve_pred_move ( tmp , ptrue , src ) ; else emit_move_insn ( tmp , src ) ; src = tmp ; } aarch64_emit_sve_pred_move ( dest , ptrue , src ) ; } </s>

Expand a pre-RA SVE data move from SRC to DEST in which at least one operand is in memory . In this case we need to use the predicated LD1 and ST1 instead of LDR and STR , both for correctness on big-endian targets and because LD1 and ST1 support a wider range of addressing modes . PRED_MODE is the mode of the predicate . See the comment at the head of aarch64-sve.md for details about the big-endian handling .


<s> void aarch64_expand_sve_vcond ( machine_mode data_mode , machine_mode cmp_mode , rtx * ops ) { machine_mode pred_mode = aarch64_get_mask_mode ( cmp_mode ) . require ( ) ; rtx pred = gen_reg_rtx ( pred_mode ) ; if ( FLOAT_MODE_P ( cmp_mode ) ) { if ( aarch64_expand_sve_vec_cmp_float ( pred , GET_CODE ( ops [ 3 ] ) , ops [ 4 ] , ops [ 5 ] , true ) ) std :: swap ( ops [ 1 ] , ops [ 2 ] ) ; } else aarch64_expand_sve_vec_cmp_int ( pred , GET_CODE ( ops [ 3 ] ) , ops [ 4 ] , ops [ 5 ] ) ; if ( ! aarch64_sve_reg_or_dup_imm ( ops [ 1 ] , data_mode ) ) ops [ 1 ] = force_reg ( data_mode , ops [ 1 ] ) ; if ( register_operand ( ops [ 1 ] , data_mode ) || ! aarch64_simd_reg_or_zero ( ops [ 2 ] , data_mode ) ) ops [ 2 ] = force_reg ( data_mode , ops [ 2 ] ) ; rtvec vec = gen_rtvec ( 3 , pred , ops [ 1 ] , ops [ 2 ] ) ; emit_set_insn ( ops [ 0 ] , gen_rtx_UNSPEC ( data_mode , vec , UNSPEC_SEL ) ) ; } </s>

Expand an SVE vcond pattern with operands OPS . DATA_MODE is the mode of the data being selected and CMP_MODE is the mode of the values being compared .


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

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


<s> void aarch64_expand_sve_vec_cmp_int ( rtx target , rtx_code code , rtx op0 , rtx op1 ) { machine_mode pred_mode = GET_MODE ( target ) ; machine_mode data_mode = GET_MODE ( op0 ) ; rtx res = aarch64_sve_emit_int_cmp ( target , pred_mode , code , data_mode , op0 , op1 ) ; if ( ! rtx_equal_p ( target , res ) ) emit_move_insn ( target , res ) ; } </s>

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


<s> void aarch64_expand_sve_vec_perm ( rtx target , rtx op0 , rtx op1 , rtx sel ) { machine_mode data_mode = GET_MODE ( target ) ; machine_mode sel_mode = GET_MODE ( sel ) ; int nunits = GET_MODE_NUNITS ( sel_mode ) . to_constant ( ) ; rtx sel_reg = force_reg ( sel_mode , sel ) ; if ( GET_CODE ( sel ) == CONST_VECTOR && aarch64_const_vec_all_in_range_p ( sel , 0 , nunits - 1 ) ) { emit_unspec2 ( target , UNSPEC_TBL , op0 , sel_reg ) ; return ; } if ( rtx_equal_p ( op0 , op1 ) ) { rtx max_sel = aarch64_simd_gen_const_vector_dup ( sel_mode , nunits - 1 ) ; rtx sel_mod = expand_simple_binop ( sel_mode , AND , sel_reg , max_sel , NULL , 0 , OPTAB_DIRECT ) ; emit_unspec2 ( target , UNSPEC_TBL , op0 , sel_mod ) ; return ; } rtx res0 = gen_reg_rtx ( data_mode ) ; rtx res1 = gen_reg_rtx ( data_mode ) ; rtx neg_num_elems = aarch64_simd_gen_const_vector_dup ( sel_mode , - nunits ) ; if ( GET_CODE ( sel ) != CONST_VECTOR || ! aarch64_const_vec_all_in_range_p ( sel , 0 , 2 * nunits - 1 ) ) { rtx max_sel = aarch64_simd_gen_const_vector_dup ( sel_mode , 2 * nunits - 1 ) ; sel_reg = expand_simple_binop ( sel_mode , AND , sel_reg , max_sel , NULL , 0 , OPTAB_DIRECT ) ; } emit_unspec2 ( res0 , UNSPEC_TBL , op0 , sel_reg ) ; rtx sel_sub = expand_simple_binop ( sel_mode , PLUS , sel_reg , neg_num_elems , NULL , 0 , OPTAB_DIRECT ) ; emit_unspec2 ( res1 , UNSPEC_TBL , op1 , sel_sub ) ; if ( GET_MODE_CLASS ( data_mode ) == MODE_VECTOR_INT ) emit_insn ( gen_rtx_SET ( target , gen_rtx_IOR ( data_mode , res0 , res1 ) ) ) ; else emit_unspec2 ( target , UNSPEC_IORF , res0 , res1 ) ; } </s>

Expand an SVE vec_perm with the given operands .


<s> void aarch64_expand_vec_perm ( rtx target , rtx op0 , rtx op1 , rtx sel , unsigned int nelt ) { machine_mode vmode = GET_MODE ( target ) ; 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> static void aarch64_expand_vec_perm_1 ( rtx target , rtx op0 , rtx op1 , rtx sel ) { machine_mode vmode = GET_MODE ( target ) ; bool one_vector_p = rtx_equal_p ( op0 , op1 ) ; gcc_checking_assert ( vmode == V8QImode || vmode == V16QImode ) ; gcc_checking_assert ( GET_MODE ( op0 ) == vmode ) ; gcc_checking_assert ( GET_MODE ( op1 ) == vmode ) ; gcc_checking_assert ( GET_MODE ( sel ) == vmode ) ; gcc_checking_assert ( TARGET_SIMD ) ; if ( one_vector_p ) { if ( vmode == V8QImode ) { rtx pair = gen_reg_rtx ( V16QImode ) ; emit_insn ( gen_aarch64_combinev8qi ( pair , op0 , op0 ) ) ; emit_insn ( gen_aarch64_tbl1v8qi ( target , pair , sel ) ) ; } else { emit_insn ( gen_aarch64_tbl1v16qi ( target , op0 , sel ) ) ; } } else { rtx pair ; if ( vmode == V8QImode ) { pair = gen_reg_rtx ( V16QImode ) ; emit_insn ( gen_aarch64_combinev8qi ( pair , op0 , op1 ) ) ; emit_insn ( gen_aarch64_tbl1v8qi ( target , pair , sel ) ) ; } else { pair = gen_reg_rtx ( OImode ) ; emit_insn ( gen_aarch64_combinev16qi ( pair , op0 , op1 ) ) ; emit_insn ( gen_aarch64_tbl2v16qi ( target , pair , sel ) ) ; } } } </s>


<s> static void aarch64_expand_vec_series ( rtx dest , rtx base , rtx step ) { machine_mode mode = GET_MODE ( dest ) ; scalar_mode inner = GET_MODE_INNER ( mode ) ; if ( ! aarch64_sve_index_immediate_p ( base ) ) base = force_reg ( inner , base ) ; if ( ! aarch64_sve_index_immediate_p ( step ) ) step = force_reg ( inner , step ) ; emit_set_insn ( dest , gen_rtx_VEC_SERIES ( mode , base , step ) ) ; } </s>


<s> static bool aarch64_extending_load_p ( 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 = 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 rtx aarch64_extend_bitfield_pattern_p ( rtx x ) { rtx_code outer_code = GET_CODE ( x ) ; machine_mode outer_mode = GET_MODE ( x ) ; if ( outer_code != ZERO_EXTEND && outer_code != SIGN_EXTEND && outer_mode != SImode && outer_mode != DImode ) return NULL_RTX ; rtx inner = XEXP ( x , 0 ) ; rtx_code inner_code = GET_CODE ( inner ) ; machine_mode inner_mode = GET_MODE ( inner ) ; rtx op = NULL_RTX ; switch ( inner_code ) { case ASHIFT : if ( CONST_INT_P ( XEXP ( inner , 1 ) ) && ( inner_mode == QImode || inner_mode == HImode ) ) op = XEXP ( inner , 0 ) ; break ; case LSHIFTRT : if ( outer_code == ZERO_EXTEND && CONST_INT_P ( XEXP ( inner , 1 ) ) && ( inner_mode == QImode || inner_mode == HImode ) ) op = XEXP ( inner , 0 ) ; break ; case ASHIFTRT : if ( outer_code == SIGN_EXTEND && CONST_INT_P ( XEXP ( inner , 1 ) ) && ( inner_mode == QImode || inner_mode == HImode ) ) op = XEXP ( inner , 0 ) ; break ; default : break ; } return op ; } </s>

Check whether X is a bitfield operation of the form shift + extend that maps down to a UBFIZ/SBFIZ/UBFX/SBFX instruction . If so , return the operand to which the bitfield operation is applied . Otherwise return NULL_RTX .


<s> static bool aarch64_extr_rtx_p ( rtx x , rtx * res_op0 , rtx * res_op1 ) { rtx op0 , op1 ; scalar_int_mode mode ; if ( ! is_a < scalar_int_mode > ( GET_MODE ( x ) , & mode ) ) return false ; * res_op0 = NULL_RTX ; * res_op1 = NULL_RTX ; if ( GET_CODE ( x ) != IOR ) return false ; op0 = XEXP ( x , 0 ) ; op1 = XEXP ( x , 1 ) ; if ( ( GET_CODE ( op0 ) == ASHIFT && GET_CODE ( op1 ) == LSHIFTRT ) || ( GET_CODE ( op1 ) == ASHIFT && GET_CODE ( op0 ) == LSHIFTRT ) ) { if ( GET_CODE ( op1 ) == ASHIFT ) std :: swap ( op0 , op1 ) ; if ( ! CONST_INT_P ( XEXP ( op0 , 1 ) ) || ! CONST_INT_P ( XEXP ( op1 , 1 ) ) ) return false ; unsigned HOST_WIDE_INT shft_amnt_0 = UINTVAL ( XEXP ( op0 , 1 ) ) ; unsigned HOST_WIDE_INT shft_amnt_1 = UINTVAL ( XEXP ( op1 , 1 ) ) ; if ( shft_amnt_0 < GET_MODE_BITSIZE ( mode ) && shft_amnt_0 + shft_amnt_1 == GET_MODE_BITSIZE ( mode ) ) { * res_op0 = XEXP ( op0 , 0 ) ; * res_op1 = XEXP ( op1 , 0 ) ; return true ; } } return false ; } </s>

Return true iff X is an rtx that will match an extr instruction i.e . as described in the * extr < mode > 5_insn family of patterns . OP0 and OP1 will be set to the operands of the shifts involved on success and will be NULL_RTX otherwise .


"\tnop // between mem op and mult-accumulate\n"


<s> static bool aarch64_fixed_condition_code_regs ( unsigned int * p1 , unsigned int * p2 ) { * p1 = CC_REGNUM ; * p2 = INVALID_REGNUM ; return true ; } </s>

Return the fixed registers used for condition codes .


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

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


<s> 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 ( GET_CODE ( x ) == CONST_DOUBLE && 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> bool aarch64_float_const_zero_rtx_p ( rtx x ) { if ( GET_MODE ( x ) == VOIDmode ) return false ; if ( REAL_VALUE_MINUS_ZERO ( * CONST_DOUBLE_REAL_VALUE ( x ) ) ) return ! HONOR_SIGNED_ZEROS ( GET_MODE ( x ) ) ; return real_equal ( CONST_DOUBLE_REAL_VALUE ( x ) , & dconst0 ) ; } </s>

Return TRUE if rtx X is immediate constant 0.0


<s> static const predefined_function_abi & aarch64_fntype_abi ( const_tree fntype ) { if ( lookup_attribute ( "aarch64_vector_pcs" , TYPE_ATTRIBUTES ( fntype ) ) ) return aarch64_simd_abi ( ) ; if ( aarch64_returns_value_in_sve_regs_p ( fntype ) || aarch64_takes_arguments_in_sve_regs_p ( fntype ) ) return aarch64_sve_abi ( ) ; return default_function_abi ; } </s>


<s> static tree aarch64_fold_builtin ( tree fndecl , int nargs , tree * args , bool ) { unsigned int code = DECL_MD_FUNCTION_CODE ( fndecl ) ; unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT ; tree type = TREE_TYPE ( TREE_TYPE ( fndecl ) ) ; switch ( code & AARCH64_BUILTIN_CLASS ) { case AARCH64_BUILTIN_GENERAL : return aarch64_general_fold_builtin ( subcode , type , nargs , args ) ; case AARCH64_BUILTIN_SVE : return NULL_TREE ; } gcc_unreachable ( ) ; } </s>


<s> HOST_WIDE_INT aarch64_fold_sve_cnt_pat ( aarch64_svpattern pattern , unsigned int nelts_per_vq ) { unsigned int vl , const_vg ; if ( pattern >= AARCH64_SV_VL1 && pattern <= AARCH64_SV_VL8 ) vl = 1 + ( pattern - AARCH64_SV_VL1 ) ; else if ( pattern >= AARCH64_SV_VL16 && pattern <= AARCH64_SV_VL256 ) vl = 16 << ( pattern - AARCH64_SV_VL16 ) ; else if ( aarch64_sve_vg . is_constant ( & const_vg ) ) { unsigned int nelts = ( const_vg / 2 ) * nelts_per_vq ; switch ( pattern ) { case AARCH64_SV_POW2 : return 1 << floor_log2 ( nelts ) ; case AARCH64_SV_MUL4 : return nelts & - 4 ; case AARCH64_SV_MUL3 : return ( nelts / 3 ) * 3 ; case AARCH64_SV_ALL : return nelts ; default : gcc_unreachable ( ) ; } } else return - 1 ; poly_uint64 nelts_all = exact_div ( aarch64_sve_vg , 2 ) * nelts_per_vq ; if ( known_le ( vl , nelts_all ) ) return vl ; if ( known_gt ( vl , nelts_all ) ) return 0 ; return - 1 ; } </s>

Check whether we can calculate the number of elements in PATTERN at compile time , given that there are NELTS_PER_VQ elements per 128-bit block . Return the value if so , otherwise return -1 .


<s> int aarch64_fpconst_pow2_recip ( rtx x ) { REAL_VALUE_TYPE r0 ; if ( ! CONST_DOUBLE_P ( x ) ) return - 1 ; r0 = * CONST_DOUBLE_REAL_VALUE ( x ) ; if ( exact_real_inverse ( DFmode , & r0 ) && ! REAL_VALUE_NEGATIVE ( r0 ) ) { int ret = exact_log2 ( real_to_integer ( & r0 ) ) ; if ( ret >= 1 && ret <= 32 ) return ret ; } return - 1 ; } </s>

If X is a positive CONST_DOUBLE with a value that is the reciprocal of a power of 2 ( i.e 1/2^n ) return the number of float bits . e.g . for x== ( 1/2^n ) return n. Otherwise return -1 .


<s> int aarch64_fpconst_pow_of_2 ( rtx x ) { const REAL_VALUE_TYPE * r ; if ( ! CONST_DOUBLE_P ( x ) ) return - 1 ; r = CONST_DOUBLE_REAL_VALUE ( x ) ; if ( REAL_VALUE_NEGATIVE ( * r ) || REAL_VALUE_ISNAN ( * r ) || REAL_VALUE_ISINF ( * r ) || ! real_isinteger ( r , DFmode ) ) return - 1 ; return exact_log2 ( real_to_integer ( r ) ) ; } </s>

If X is a positive CONST_DOUBLE with a value that is a power of 2 return the log2 of that value . Otherwise return -1 .


<s> opt_machine_mode aarch64_full_sve_mode ( scalar_mode mode ) { switch ( mode ) { case E_DFmode : return VNx2DFmode ; case E_SFmode : return VNx4SFmode ; case E_HFmode : return VNx8HFmode ; case E_BFmode : return VNx8BFmode ; case E_DImode : return VNx2DImode ; case E_SImode : return VNx4SImode ; case E_HImode : return VNx8HImode ; case E_QImode : return VNx16QImode ; default : return opt_machine_mode ( ) ; } } </s>

Return the full-width SVE vector mode for element mode MODE , if one exists .


<s> static unsigned int aarch64_function_arg_alignment ( machine_mode mode , const_tree type , bool * abi_break ) { * abi_break = false ; 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 = true ; 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 pad_direction aarch64_function_arg_padding ( machine_mode mode , const_tree type ) { if ( ! BYTES_BIG_ENDIAN ) return PAD_UPWARD ; 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 PAD_DOWNWARD ; return PAD_UPWARD ; } </s>

Implement TARGET_FUNCTION_ARG_PADDING . 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 .


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_FLOAT ; 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> bool aarch64_fusion_enabled_p ( enum aarch64_fusion_pairs op ) { return ( aarch64_tune_params . fusible_ops & op ) != 0 ; } </s>

Return true iff the instruction fusion described by OP is enabled .


<s> rtx aarch64_gen_compare_reg ( RTX_CODE code , rtx x , rtx y ) { machine_mode cmp_mode = GET_MODE ( x ) ; machine_mode cc_mode ; rtx cc_reg ; if ( cmp_mode == TImode ) { gcc_assert ( code == NE ) ; cc_mode = CCmode ; cc_reg = gen_rtx_REG ( cc_mode , CC_REGNUM ) ; rtx x_lo = operand_subword ( x , 0 , 0 , TImode ) ; rtx y_lo = operand_subword ( y , 0 , 0 , TImode ) ; emit_set_insn ( cc_reg , gen_rtx_COMPARE ( cc_mode , x_lo , y_lo ) ) ; rtx x_hi = operand_subword ( x , 1 , 0 , TImode ) ; rtx y_hi = operand_subword ( y , 1 , 0 , TImode ) ; emit_insn ( gen_ccmpccdi ( cc_reg , cc_reg , x_hi , y_hi , gen_rtx_EQ ( cc_mode , cc_reg , const0_rtx ) , GEN_INT ( AARCH64_EQ ) ) ) ; } else { cc_mode = SELECT_CC_MODE ( code , x , y ) ; cc_reg = gen_rtx_REG ( cc_mode , CC_REGNUM ) ; emit_set_insn ( cc_reg , gen_rtx_COMPARE ( cc_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_compare_reg_maybe_ze ( RTX_CODE code , rtx x , rtx y , machine_mode y_mode ) { if ( y_mode == E_QImode || y_mode == E_HImode ) { if ( CONST_INT_P ( y ) ) { y = GEN_INT ( INTVAL ( y ) & GET_MODE_MASK ( y_mode ) ) ; y_mode = SImode ; } else { rtx t , cc_reg ; machine_mode cc_mode ; t = gen_rtx_ZERO_EXTEND ( SImode , y ) ; t = gen_rtx_COMPARE ( CC_SWPmode , t , x ) ; cc_mode = CC_SWPmode ; cc_reg = gen_rtx_REG ( cc_mode , CC_REGNUM ) ; emit_set_insn ( cc_reg , t ) ; return cc_reg ; } } if ( ! aarch64_plus_operand ( y , y_mode ) ) y = force_reg ( y_mode , y ) ; return aarch64_gen_compare_reg ( code , x , y ) ; } </s>

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


<s> const char * aarch64_gen_far_branch ( rtx * operands , int pos_label , const char * dest , const char * branch_format ) { rtx_code_label * tmp_label = gen_label_rtx ( ) ; char label_buf [ 256 ] ; char buffer [ 128 ] ; ASM_GENERATE_INTERNAL_LABEL ( label_buf , dest , CODE_LABEL_NUMBER ( tmp_label ) ) ; const char * label_ptr = targetm . strip_name_encoding ( label_buf ) ; rtx dest_label = operands [ pos_label ] ; operands [ pos_label ] = tmp_label ; snprintf ( buffer , sizeof ( buffer ) , "%s%s" , branch_format , label_ptr ) ; output_asm_insn ( buffer , operands ) ; snprintf ( buffer , sizeof ( buffer ) , "b\t%%l%d\n%s:" , pos_label , label_ptr ) ; operands [ pos_label ] = dest_label ; output_asm_insn ( buffer , operands ) ; return "" ; } </s>

Generate code to enable conditional branches in functions over 1 MiB .


<s> static rtx aarch64_gen_loadwb_pair ( machine_mode mode , rtx base , rtx reg , rtx reg2 , HOST_WIDE_INT adjustment ) { switch ( mode ) { case E_DImode : return gen_loadwb_pairdi_di ( base , base , reg , reg2 , GEN_INT ( adjustment ) , GEN_INT ( UNITS_PER_WORD ) ) ; case E_DFmode : return gen_loadwb_pairdf_di ( base , base , reg , reg2 , GEN_INT ( adjustment ) , GEN_INT ( UNITS_PER_WORD ) ) ; case E_TFmode : return gen_loadwb_pairtf_di ( base , base , reg , reg2 , GEN_INT ( adjustment ) , GEN_INT ( UNITS_PER_VREG ) ) ; 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 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 ) ; 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> rtx aarch64_gen_stepped_int_parallel ( unsigned int nelts , int base , int step ) { rtvec vec = rtvec_alloc ( nelts ) ; for ( unsigned int i = 0 ; i < nelts ; ++ i ) RTVEC_ELT ( vec , i ) = gen_int_mode ( base + i * step , DImode ) ; return gen_rtx_PARALLEL ( VOIDmode , vec ) ; } </s>

Return a PARALLEL containing NELTS elements , with element I equal to BASE + I * STEP .


<s> static rtx aarch64_gen_storewb_pair ( machine_mode mode , rtx base , rtx reg , rtx reg2 , HOST_WIDE_INT adjustment ) { switch ( mode ) { case E_DImode : return gen_storewb_pairdi_di ( base , base , reg , reg2 , GEN_INT ( - adjustment ) , GEN_INT ( UNITS_PER_WORD - adjustment ) ) ; case E_DFmode : return gen_storewb_pairdf_di ( base , base , reg , reg2 , GEN_INT ( - adjustment ) , GEN_INT ( UNITS_PER_WORD - adjustment ) ) ; case E_TFmode : return gen_storewb_pairtf_di ( base , base , reg , reg2 , GEN_INT ( - adjustment ) , GEN_INT ( UNITS_PER_VREG - 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 E_DImode : return gen_store_pair_dw_didi ( mem1 , reg1 , mem2 , reg2 ) ; case E_DFmode : return gen_store_pair_dw_dfdf ( mem1 , reg1 , mem2 , reg2 ) ; case E_TFmode : return gen_store_pair_dw_tftf ( 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> void aarch64_gen_unlikely_cbranch ( enum rtx_code code , machine_mode cc_mode , rtx label_ref ) { rtx x ; x = gen_rtx_fmt_ee ( code , VOIDmode , gen_rtx_REG ( cc_mode , CC_REGNUM ) , const0_rtx ) ; x = gen_rtx_IF_THEN_ELSE ( VOIDmode , x , gen_rtx_LABEL_REF ( VOIDmode , label_ref ) , pc_rtx ) ; aarch64_emit_unlikely_jump ( gen_rtx_SET ( pc_rtx , x ) ) ; } </s>

Generate RTL for a conditional branch with rtx comparison CODE in mode CC_MODE . The destination of the unlikely conditional branch is LABEL_REF .


<s> static const struct processor * aarch64_get_arch ( enum aarch64_arch arch ) { if ( arch != aarch64_no_arch ) return & all_architectures [ arch ] ; const struct processor * cpu = & all_cores [ TARGET_CPU_DEFAULT & 0x3f ] ; return & all_architectures [ cpu -> arch ] ; } </s>

Return the architecture corresponding to the enum ARCH . If it does n't specify a valid architecture , return the default .


<s> static opt_machine_mode aarch64_get_mask_mode ( machine_mode mode ) { unsigned int vec_flags = aarch64_classify_vector_mode ( mode ) ; if ( vec_flags & VEC_SVE_DATA ) return aarch64_sve_pred_mode ( mode ) ; return default_get_mask_mode ( mode ) ; } </s>


<s> static const char * aarch64_get_multilib_abi_name ( void ) { if ( TARGET_BIG_END ) return TARGET_ILP32 ? "aarch64_be_ilp32" : "aarch64_be" ; return TARGET_ILP32 ? "aarch64_ilp32" : "aarch64" ; } </s>


<s> static unsigned int aarch64_get_next_set_bit ( sbitmap bmp , unsigned int start ) { unsigned int nbits = SBITMAP_SIZE ( bmp ) ; if ( start == nbits ) return start ; gcc_assert ( start < nbits ) ; for ( unsigned int i = start ; i < nbits ; i ++ ) if ( bitmap_bit_p ( bmp , i ) ) return i ; return nbits ; } </s>

Return the next set bit in BMP from START onwards . Return the total number of bits in BMP if no set bit is found at or after START .


<s> static fixed_size_mode aarch64_get_reg_raw_mode ( int regno ) { if ( TARGET_SVE && FP_REGNUM_P ( regno ) ) return as_a < fixed_size_mode > ( V16QImode ) ; return default_get_reg_raw_mode ( regno ) ; } </s>


<s> static sbitmap aarch64_get_separate_components ( void ) { sbitmap components = sbitmap_alloc ( LAST_SAVED_REGNUM + 1 ) ; bitmap_clear ( components ) ; for ( unsigned regno = 0 ; regno <= LAST_SAVED_REGNUM ; regno ++ ) if ( aarch64_register_saved_on_entry ( regno ) ) { machine_mode mode = aarch64_reg_save_mode ( regno ) ; if ( mode == VNx2DImode && BYTES_BIG_ENDIAN ) continue ; poly_int64 offset = cfun -> machine -> frame . reg_offset [ regno ] ; if ( flag_stack_clash_protection && maybe_ne ( cfun -> machine -> frame . below_hard_fp_saved_regs_size , 0 ) && known_eq ( offset , 0 ) ) continue ; if ( frame_pointer_needed ) offset -= cfun -> machine -> frame . below_hard_fp_saved_regs_size ; else offset += crtl -> outgoing_args_size ; if ( aarch64_sve_mode_p ( mode ) ? offset_9bit_signed_scaled_p ( mode , offset ) : offset_12bit_unsigned_scaled_p ( mode , offset ) ) bitmap_set_bit ( components , regno ) ; } if ( frame_pointer_needed ) bitmap_clear_bit ( components , HARD_FRAME_POINTER_REGNUM ) ; if ( cfun -> machine -> frame . spare_pred_reg != INVALID_REGNUM ) bitmap_clear_bit ( components , cfun -> machine -> frame . spare_pred_reg ) ; unsigned reg1 = cfun -> machine -> frame . wb_candidate1 ; unsigned reg2 = cfun -> machine -> frame . wb_candidate2 ; if ( reg2 != INVALID_REGNUM ) bitmap_clear_bit ( components , reg2 ) ; if ( reg1 != INVALID_REGNUM ) bitmap_clear_bit ( components , reg1 ) ; bitmap_clear_bit ( components , LR_REGNUM ) ; bitmap_clear_bit ( components , SP_REGNUM ) ; return components ; } </s>


<s> static bool aarch64_get_sve_pred_bits ( rtx_vector_builder & builder , rtx x ) { if ( GET_CODE ( x ) != CONST_VECTOR ) return false ; unsigned int factor = vector_element_size ( GET_MODE_NUNITS ( VNx16BImode ) , GET_MODE_NUNITS ( GET_MODE ( x ) ) ) ; unsigned int npatterns = CONST_VECTOR_NPATTERNS ( x ) * factor ; unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN ( x ) ; builder . new_vector ( VNx16BImode , npatterns , nelts_per_pattern ) ; unsigned int nelts = const_vector_encoded_nelts ( x ) ; for ( unsigned int i = 0 ; i < nelts ; ++ i ) { rtx elt = CONST_VECTOR_ENCODED_ELT ( x , i ) ; if ( ! CONST_INT_P ( elt ) ) return false ; builder . quick_push ( elt ) ; for ( unsigned int j = 1 ; j < factor ; ++ j ) builder . quick_push ( const0_rtx ) ; } builder . finalize ( ) ; return true ; } </s>

Return true if predicate value X is a constant in which every element is a CONST_INT . When returning true , describe X in BUILDER as a VNx16BI value , i.e . as a predicate in which all bits are significant .


<s> static const struct processor * aarch64_get_tune_cpu ( enum aarch64_processor cpu ) { if ( cpu != aarch64_none ) return & all_cores [ cpu ] ; return & all_cores [ TARGET_CPU_DEFAULT & 0x3f ] ; } </s>

Return the CPU corresponding to the enum CPU . If it does n't specify a cpu , return the default .


<s> static bool aarch64_gimple_fold_builtin ( gimple_stmt_iterator * gsi ) { gcall * stmt = as_a < gcall * > ( gsi_stmt ( * gsi ) ) ; tree fndecl = gimple_call_fndecl ( stmt ) ; unsigned int code = DECL_MD_FUNCTION_CODE ( fndecl ) ; unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT ; gimple * new_stmt = NULL ; switch ( code & AARCH64_BUILTIN_CLASS ) { case AARCH64_BUILTIN_GENERAL : new_stmt = aarch64_general_gimple_fold_builtin ( subcode , stmt ) ; break ; case AARCH64_BUILTIN_SVE : new_stmt = aarch64_sve :: gimple_fold_builtin ( subcode , gsi , stmt ) ; break ; } if ( ! new_stmt ) return false ; gsi_replace ( gsi , new_stmt , true ) ; return true ; } </s>


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

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

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

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


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

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

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


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

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


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

Handle the argument STR to the tune= target attribute . PRAGMA_OR_ATTR is used in potential error messages .


<s> machine_mode aarch64_hard_regno_caller_save_mode ( unsigned regno , unsigned , machine_mode mode ) { if ( PR_REGNUM_P ( regno ) ) return mode ; if ( known_ge ( GET_MODE_SIZE ( mode ) , 4 ) ) return mode ; else return SImode ; } </s>


<s> static bool aarch64_hard_regno_call_part_clobbered ( unsigned int abi_id , unsigned int regno , machine_mode mode ) { if ( FP_REGNUM_P ( regno ) && abi_id != ARM_PCS_SVE ) { poly_int64 per_register_size = GET_MODE_SIZE ( mode ) ; unsigned int nregs = hard_regno_nregs ( regno , mode ) ; if ( nregs > 1 ) per_register_size = exact_div ( per_register_size , nregs ) ; if ( abi_id == ARM_PCS_SIMD || abi_id == ARM_PCS_TLSDESC ) return maybe_gt ( per_register_size , 16 ) ; return maybe_gt ( per_register_size , 8 ) ; } return false ; } </s>

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


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


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