<s> bool aarch64_high_bits_all_ones_p ( HOST_WIDE_INT i ) { return exact_log2 ( - i ) != HOST_WIDE_INT_M1 ; } </s>

Return true if I 's bits are consecutive ones from the MSB .


<s> int aarch64_host_wide_int_compare ( const void * x , const void * y ) { return wi :: cmps ( * ( ( const HOST_WIDE_INT * ) x ) , * ( ( const HOST_WIDE_INT * ) y ) ) ; } </s>

Taking X and Y to be HOST_WIDE_INT pointers , return the result of a comparison between the two .


<s> static bool aarch64_if_then_else_costs ( rtx op0 , rtx op1 , rtx op2 , int * cost , bool speed ) { rtx inner ; rtx comparator ; enum rtx_code cmpcode ; const struct cpu_cost_table * extra_cost = aarch64_tune_params . insn_extra_cost ; if ( COMPARISON_P ( op0 ) ) { inner = XEXP ( op0 , 0 ) ; comparator = XEXP ( op0 , 1 ) ; cmpcode = GET_CODE ( op0 ) ; } else { inner = op0 ; comparator = const0_rtx ; cmpcode = NE ; } if ( GET_CODE ( op1 ) == PC || GET_CODE ( op2 ) == PC ) { if ( GET_MODE_CLASS ( GET_MODE ( inner ) ) == MODE_CC ) return true ; else { if ( cmpcode == NE || cmpcode == EQ ) { if ( comparator == const0_rtx ) { if ( GET_CODE ( inner ) == ZERO_EXTRACT ) * cost += rtx_cost ( XEXP ( inner , 0 ) , VOIDmode , ZERO_EXTRACT , 0 , speed ) ; else * cost += rtx_cost ( inner , VOIDmode , cmpcode , 0 , speed ) ; return true ; } if ( register_operand ( inner , VOIDmode ) && aarch64_imm24 ( comparator , VOIDmode ) ) { * cost += COSTS_N_INSNS ( 2 ) ; if ( speed ) * cost += extra_cost -> alu . arith * 2 ; return true ; } } else if ( cmpcode == LT || cmpcode == GE ) { if ( comparator == const0_rtx ) return true ; } } } else if ( GET_MODE_CLASS ( GET_MODE ( inner ) ) == MODE_CC ) { if ( GET_CODE ( op1 ) == COMPARE ) { if ( XEXP ( op1 , 1 ) == const0_rtx ) * cost += 1 ; if ( speed ) { machine_mode mode = GET_MODE ( XEXP ( op1 , 0 ) ) ; const struct cpu_cost_table * extra_cost = aarch64_tune_params . insn_extra_cost ; if ( GET_MODE_CLASS ( mode ) == MODE_INT ) * cost += extra_cost -> alu . arith ; else * cost += extra_cost -> fp [ mode == DFmode ] . compare ; } return true ; } if ( GET_CODE ( op1 ) == NEG || GET_CODE ( op1 ) == NOT || ( GET_CODE ( op1 ) == PLUS && XEXP ( op1 , 1 ) == const1_rtx ) ) op1 = XEXP ( op1 , 0 ) ; else if ( GET_CODE ( op1 ) == ZERO_EXTEND && GET_CODE ( op2 ) == ZERO_EXTEND ) { op1 = XEXP ( op1 , 0 ) ; op2 = XEXP ( op2 , 0 ) ; } * cost += rtx_cost ( op1 , VOIDmode , IF_THEN_ELSE , 1 , speed ) ; * cost += rtx_cost ( op2 , VOIDmode , IF_THEN_ELSE , 2 , speed ) ; return true ; } return false ; } </s>

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


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


<s> const predefined_function_abi & aarch64_insn_callee_abi ( const rtx_insn * insn ) { rtx pat = PATTERN ( insn ) ; gcc_assert ( GET_CODE ( pat ) == PARALLEL ) ; rtx unspec = XVECEXP ( pat , 0 , 1 ) ; gcc_assert ( GET_CODE ( unspec ) == UNSPEC && XINT ( unspec , 1 ) == UNSPEC_CALLEE_ABI ) ; return function_abis [ INTVAL ( XVECEXP ( unspec , 0 , 0 ) ) ] ; } </s>


<s> static bool aarch64_integer_truncation_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 lhs_type = TREE_TYPE ( gimple_assign_lhs ( assign ) ) ; tree rhs_type = TREE_TYPE ( gimple_assign_rhs1 ( assign ) ) ; return ( INTEGRAL_TYPE_P ( lhs_type ) && INTEGRAL_TYPE_P ( rhs_type ) && TYPE_PRECISION ( lhs_type ) < TYPE_PRECISION ( rhs_type ) ) ; } </s>

Return true if STMT_INFO is an integer truncation .


"operation not permitted on type %<bfloat16_t%>"

"cannot combine GNU and SVE vectors in a binary operation"

Return the diagnostic message string if the binary operation OP is not permitted on TYPE1 and TYPE2 , NULL otherwise .


"invalid conversion from type %<bfloat16_t%>"

"invalid conversion to type %<bfloat16_t%>"

Return the diagnostic message string if conversion from FROMTYPE to TOTYPE is not allowed , NULL otherwise .


Return the diagnostic message string if the unary operation OP is not permitted on TYPE , NULL otherwise .


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

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


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

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


<s> bool aarch64_is_long_call_p ( rtx sym ) { return aarch64_decl_is_long_call_p ( SYMBOL_REF_DECL ( sym ) ) ; } </s>

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


<s> bool aarch64_is_noplt_call_p ( rtx sym ) { const_tree decl = SYMBOL_REF_DECL ( sym ) ; if ( flag_pic && decl && ( ! flag_plt || lookup_attribute ( "noplt" , DECL_ATTRIBUTES ( decl ) ) ) && ! targetm . binds_local_p ( decl ) ) return true ; return false ; } </s>

Return true if calls to symbol-ref SYM should not go through plt stubs .


<s> int aarch64_ldrstr_offset_compare ( const void * x , const void * y ) { const rtx * operands_1 = ( const rtx * ) x ; const rtx * operands_2 = ( const rtx * ) y ; rtx mem_1 , mem_2 , base , offset_1 , offset_2 ; if ( MEM_P ( operands_1 [ 0 ] ) ) mem_1 = operands_1 [ 0 ] ; else mem_1 = operands_1 [ 1 ] ; if ( MEM_P ( operands_2 [ 0 ] ) ) mem_2 = operands_2 [ 0 ] ; else mem_2 = operands_2 [ 1 ] ; extract_base_offset_in_addr ( mem_1 , & base , & offset_1 ) ; extract_base_offset_in_addr ( mem_2 , & base , & offset_2 ) ; gcc_assert ( offset_1 != NULL_RTX && offset_2 != NULL_RTX ) ; return wi :: cmps ( INTVAL ( offset_1 ) , INTVAL ( offset_2 ) ) ; } </s>

Taking X and Y to be pairs of RTX , one pointing to a MEM rtx and the other pointing to a REG rtx containing an offset , compare the offsets of the two pairs . Return : 1 iff offset ( X ) > offset ( Y ) 0 iff offset ( X ) == offset ( Y ) -1 iff offset ( X ) < offset ( Y )


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

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


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

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


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

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


<s> static bool aarch64_legitimize_address_displacement ( rtx * offset1 , rtx * offset2 , poly_int64 orig_offset , machine_mode mode ) { HOST_WIDE_INT size ; if ( GET_MODE_SIZE ( mode ) . is_constant ( & size ) ) { HOST_WIDE_INT const_offset , second_offset ; const_offset = orig_offset . coeffs [ 0 ] - orig_offset . coeffs [ 1 ] ; if ( mode == TImode || mode == TFmode ) second_offset = ( ( const_offset + 0x100 ) & 0x1f8 ) - 0x100 ; else if ( ( const_offset & ( size - 1 ) ) != 0 ) second_offset = ( ( const_offset + 0x100 ) & 0x1ff ) - 0x100 ; else second_offset = const_offset & ( size < 4 ? 0xfff : 0x3ffc ) ; if ( second_offset == 0 || known_eq ( orig_offset , second_offset ) ) return false ; * offset1 = gen_int_mode ( orig_offset - second_offset , Pmode ) ; * offset2 = gen_int_mode ( second_offset , Pmode ) ; return true ; } else { unsigned int vec_flags = aarch64_classify_vector_mode ( mode ) ; machine_mode step_mode = ( vec_flags & VEC_STRUCT ) != 0 ? SVE_BYTE_MODE : mode ; HOST_WIDE_INT factor = GET_MODE_SIZE ( step_mode ) . coeffs [ 1 ] ; HOST_WIDE_INT vnum = orig_offset . coeffs [ 1 ] / factor ; if ( vec_flags & VEC_SVE_DATA ) vnum = ( ( vnum + 128 ) & 255 ) - 128 ; else vnum = ( ( vnum + 256 ) & 511 ) - 256 ; if ( vnum == 0 ) return false ; poly_int64 second_offset = GET_MODE_SIZE ( step_mode ) * vnum ; if ( known_eq ( second_offset , orig_offset ) ) return false ; * offset1 = gen_int_mode ( orig_offset - second_offset , Pmode ) ; * offset2 = gen_int_mode ( second_offset , Pmode ) ; return true ; } } </s>

Split an out-of-range address displacement into a base and offset . Use 4KB range for 1- and 2-byte accesses and a 16KB range otherwise to increase opportunities for sharing the base address of different sizes . For unaligned accesses and TI/TF mode use the signed 9-bit range .


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

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


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

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


<s> static const char * aarch64_mangle_type ( const_tree type ) { if ( lang_hooks . types_compatible_p ( CONST_CAST_TREE ( type ) , va_list_type ) ) return "St9__va_list" ; if ( TREE_CODE ( type ) == REAL_TYPE && TYPE_PRECISION ( type ) == 16 ) { if ( TYPE_MODE ( type ) == BFmode ) return "u6__bf16" ; else return "Dh" ; } if ( TYPE_NAME ( type ) != NULL ) { const char * res ; if ( ( res = aarch64_general_mangle_builtin_type ( type ) ) || ( res = aarch64_sve :: mangle_builtin_type ( type ) ) ) return res ; } return NULL ; } </s>


<s> bool aarch64_masks_and_shift_for_bfi_p ( scalar_int_mode mode , unsigned HOST_WIDE_INT mask1 , unsigned HOST_WIDE_INT shft_amnt , unsigned HOST_WIDE_INT mask2 ) { unsigned HOST_WIDE_INT t ; if ( mask1 != ~ mask2 ) return false ; if ( mask2 == 0 || mask2 == HOST_WIDE_INT_M1U ) return false ; gcc_assert ( shft_amnt < GET_MODE_BITSIZE ( mode ) ) ; t = mask2 + ( HOST_WIDE_INT_1U << shft_amnt ) ; return ( t == ( t & - t ) ) ; } </s>

Return true if the masks and a shift amount from an RTX of the form ( ( x & MASK1 ) | ( ( y < < SHIFT_AMNT ) & MASK2 ) ) are valid to combine into a BFI instruction of mode MODE . See * arch64_bfi patterns .


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

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


<s> rtx aarch64_mask_from_zextract_ops ( rtx width , rtx pos ) { gcc_assert ( CONST_INT_P ( width ) ) ; gcc_assert ( CONST_INT_P ( pos ) ) ; unsigned HOST_WIDE_INT mask = ( ( unsigned HOST_WIDE_INT ) 1 << UINTVAL ( width ) ) - 1 ; return GEN_INT ( mask << UINTVAL ( pos ) ) ; } </s>

Return the bitmask CONST_INT to select the bits required by a zero extract operation of width WIDTH at bit position POS .


<s> bool aarch64_member_type_forces_blk ( const_tree field_or_array , machine_mode mode ) { const_tree type = TREE_TYPE ( field_or_array ) ; unsigned int num_zr , num_pr ; if ( aarch64_sve :: builtin_type_p ( type , & num_zr , & num_pr ) && num_pr != 0 ) { if ( TREE_CODE ( field_or_array ) == ARRAY_TYPE ) return ! simple_cst_equal ( TYPE_SIZE ( field_or_array ) , TYPE_SIZE ( type ) ) ; return mode == VOIDmode ; } return default_member_type_forces_blk ( field_or_array , mode ) ; } </s>


<s> static bool aarch64_modes_tieable_p ( machine_mode mode1 , machine_mode mode2 ) { if ( GET_MODE_CLASS ( mode1 ) == GET_MODE_CLASS ( mode2 ) ) return true ; if ( aarch64_vector_data_mode_p ( mode1 ) && aarch64_vector_data_mode_p ( mode2 ) ) return true ; if ( aarch64_vector_mode_supported_p ( mode1 ) || aarch64_vector_mode_supported_p ( mode2 ) ) return true ; return false ; } </s>

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


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

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


<s> bool aarch64_mov128_immediate ( rtx imm ) { if ( GET_CODE ( imm ) == CONST_INT ) return true ; gcc_assert ( CONST_WIDE_INT_NUNITS ( imm ) == 2 ) ; rtx lo = GEN_INT ( CONST_WIDE_INT_ELT ( imm , 0 ) ) ; rtx hi = GEN_INT ( CONST_WIDE_INT_ELT ( imm , 1 ) ) ; return aarch64_internal_mov_immediate ( NULL_RTX , lo , false , DImode ) + aarch64_internal_mov_immediate ( NULL_RTX , hi , false , DImode ) <= 4 ; } </s>

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


<s> bool aarch64_move_imm ( HOST_WIDE_INT val , machine_mode mode ) { scalar_int_mode int_mode ; if ( ! is_a < scalar_int_mode > ( mode , & int_mode ) ) return false ; if ( aarch64_movw_imm ( val , int_mode ) || aarch64_movw_imm ( ~ val , int_mode ) ) return 1 ; return aarch64_bitmask_imm ( val , int_mode ) ; } </s>

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


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

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


<s> int aarch64_movk_shift ( const wide_int_ref & and_val , const wide_int_ref & ior_val ) { unsigned int precision = and_val . get_precision ( ) ; unsigned HOST_WIDE_INT mask = 0xffff ; for ( unsigned int shift = 0 ; shift < precision ; shift += 16 ) { if ( and_val == ~ mask && ( ior_val & mask ) == ior_val ) return shift ; mask <<= 16 ; } return - 1 ; } </s>

Test whether : X = ( X & AND_VAL ) | IOR_VAL ; can be implemented using : MOVK X , # ( IOR_VAL > > shift ) , LSL # shift Return the shift if so , otherwise return -1 .


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

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


<s> static bool aarch64_needs_frame_chain ( void ) { if ( frame_pointer_needed || crtl -> calls_eh_return ) return true ; bool is_leaf = crtl -> is_leaf && ! df_regs_ever_live_p ( LR_REGNUM ) ; if ( flag_omit_leaf_frame_pointer && is_leaf ) return false ; return aarch64_use_frame_pointer ; } </s>

Determine whether a frame chain needs to be generated .


<s> static unsigned aarch64_next_callee_save ( unsigned regno , unsigned limit ) { while ( regno <= limit && ! aarch64_register_saved_on_entry ( regno ) ) regno ++ ; return regno ; } </s>

Return the next register up from REGNO up to LIMIT for the callee to save .


<s> bool aarch64_offset_7bit_signed_scaled_p ( machine_mode mode , poly_int64 offset ) { HOST_WIDE_INT multiple ; return ( constant_multiple_p ( offset , GET_MODE_SIZE ( mode ) , & multiple ) && IN_RANGE ( multiple , - 64 , 63 ) ) ; } </s>

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


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

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


<s> static unsigned int aarch64_offset_temporaries ( bool add_p , poly_int64 offset ) { if ( add_p && aarch64_sve_addvl_addpl_immediate_p ( offset ) ) return 0 ; unsigned int count = 0 ; HOST_WIDE_INT factor = offset . coeffs [ 1 ] ; HOST_WIDE_INT constant = offset . coeffs [ 0 ] - factor ; poly_int64 poly_offset ( factor , factor ) ; if ( add_p && aarch64_sve_addvl_addpl_immediate_p ( poly_offset ) ) count += 1 ; else if ( factor != 0 ) { factor = abs ( factor ) ; if ( factor > 16 * ( factor & - factor ) ) return 2 ; count += 1 ; } return count + aarch64_add_offset_1_temporaries ( constant ) ; } </s>

Return the number of temporary registers that aarch64_add_offset would need to move OFFSET into a register or add OFFSET to a register ; ADD_P is true if we want the latter rather than the former .


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

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


<s> static bool aarch64_optab_supported_p ( int op , machine_mode mode1 , machine_mode , optimization_type opt_type ) { switch ( op ) { case rsqrt_optab : return opt_type == OPTIMIZE_FOR_SPEED && use_rsqrt_p ( mode1 ) ; default : return true ; } } </s>

Implement the TARGET_OPTAB_SUPPORTED_P hook .


aarch64
"%*sselected tune = %s\n"
""
"%*sselected arch = %s%s\n"
""


<s> static void aarch64_option_restore ( struct gcc_options * opts , struct cl_target_option * ptr ) { opts -> x_explicit_tune_core = ptr -> x_explicit_tune_core ; selected_tune = aarch64_get_tune_cpu ( ptr -> x_explicit_tune_core ) ; opts -> x_explicit_arch = ptr -> x_explicit_arch ; selected_arch = aarch64_get_arch ( ptr -> x_explicit_arch ) ; opts -> x_aarch64_override_tune_string = ptr -> x_aarch64_override_tune_string ; opts -> x_aarch64_branch_protection_string = ptr -> x_aarch64_branch_protection_string ; if ( opts -> x_aarch64_branch_protection_string ) { aarch64_parse_branch_protection ( opts -> x_aarch64_branch_protection_string , NULL ) ; } aarch64_override_options_internal ( opts ) ; } </s>

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


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


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

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


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

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


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

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


<s>
const
char
*
aarch64_output_probe_sve_stack_clash
(
rtx
base
,
rtx
adjustment
,
rtx
min_probe_threshold
,
rtx
guard_size
)
{
gcc_assert
(
flag_stack_clash_protection
)
;
gcc_assert
(
CONST_INT_P
(
min_probe_threshold
)
&&
CONST_INT_P
(
guard_size
)
)
;
gcc_assert
(
INTVAL
(
guard_size
)
>
INTVAL
(
min_probe_threshold
)
)
;
HOST_WIDE_INT
residual_probe_guard
=
INTVAL
(
min_probe_threshold
)
;
residual_probe_guard
=
aarch64_clamp_to_uimm12_shift
(
residual_probe_guard
)
;
rtx
probe_offset_value_rtx
=
gen_int_mode
(
residual_probe_guard
,
Pmode
)
;
gcc_assert
(
INTVAL
(
min_probe_threshold
)
>=
residual_probe_guard
)
;
gcc_assert
(
aarch64_uimm12_shift
(
residual_probe_guard
)
)
;
static
int
labelno
=
0
;
char
loop_start_lab
[
32
]
;
char
loop_end_lab
[
32
]
;
rtx
xops
[
2
]
;
ASM_GENERATE_INTERNAL_LABEL
(
loop_start_lab
,
"SVLPSPL"
,
labelno
)
;
ASM_GENERATE_INTERNAL_LABEL
(
loop_end_lab
,
"SVLPEND"
,
labelno
++
)
;
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
loop_start_lab
)
;
xops
[
0
]
=
adjustment
;
xops
[
1
]
=
probe_offset_value_rtx
;
output_asm_insn
(
"cmp\t%0, %1"
,
xops
)
;
fputs
(
"\tb.lt\t"
,
asm_out_file
)
;
assemble_name_raw
(
asm_out_file
,
loop_end_lab
)
;
fputc
(
'\n'
,
asm_out_file
)
;
xops
[
0
]
=
base
;
xops
[
1
]
=
probe_offset_value_rtx
;
output_asm_insn
(
"sub\t%0, %0, %1"
,
xops
)
;
xops
[
1
]
=
const0_rtx
;
output_asm_insn
(
"str\txzr, [%0, %1]"
,
xops
)
;
xops
[
0
]
=
adjustment
;
xops
[
1
]
=
probe_offset_value_rtx
;
output_asm_insn
(
"sub\t%0, %0, %1"
,
xops
)
;
fputs
(
"\tb\t"
,
asm_out_file
)
;
assemble_name_raw
(
asm_out_file
,
loop_start_lab
)
;
fputc
(
'\n'
,
asm_out_file
)
;
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
loop_end_lab
)
;
xops
[
0
]
=
base
;
xops
[
1
]
=
adjustment
;
output_asm_insn
(
"sub\t%0, %0, %1"
,
xops
)
;
return
""
;
}
</s>

Emit the probe loop for doing stack clash probes and stack adjustments for SVE . This emits probes from BASE to BASE - ADJUSTMENT based on a guard size of GUARD_SIZE . When a probe is emitted it is done at most MIN_PROBE_THRESHOLD bytes from the current BASE at an interval of at most MIN_PROBE_THRESHOLD . By the end of this function BASE = BASE - ADJUSTMENT .


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

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


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

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


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

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


<s> char * aarch64_output_sve_cnt_pat_immediate ( const char * prefix , const char * operands , rtx * cnt_pat ) { aarch64_svpattern pattern = ( aarch64_svpattern ) INTVAL ( cnt_pat [ 0 ] ) ; unsigned int nelts_per_vq = INTVAL ( cnt_pat [ 1 ] ) ; unsigned int factor = INTVAL ( cnt_pat [ 2 ] ) * nelts_per_vq ; return aarch64_output_sve_cnt_immediate ( prefix , operands , pattern , factor , nelts_per_vq ) ; } </s>

Return the asm string for an instruction with a CNT-like vector size operand ( a vector pattern followed by a multiplier in the range [ 1 , 16 ] ) . PREFIX is the mnemonic without the size suffix and OPERANDS is the first part of the operands template ( the part that comes before the vector size itself ) . CNT_PAT [ 0 .. 2 ] are the operands of the UNSPEC_SVE_CNT_PAT ; see aarch64_sve_cnt_pat for details .


<s>
char
*
aarch64_output_sve_mov_immediate
(
rtx
const_vector
)
{
static
char
templ
[
40
]
;
struct
simd_immediate_info
info
;
char
element_char
;
bool
is_valid
=
aarch64_simd_valid_immediate
(
const_vector
,
&
info
)
;
gcc_assert
(
is_valid
)
;
element_char
=
sizetochar
(
GET_MODE_BITSIZE
(
info
.
elt_mode
)
)
;
machine_mode
vec_mode
=
GET_MODE
(
const_vector
)
;
if
(
aarch64_sve_pred_mode_p
(
vec_mode
)
)
{
static
char
buf
[
sizeof
(
"ptrue\t%0.N, vlNNNNN"
)
]
;
if
(
info
.
insn
==
simd_immediate_info
::
MOV
)
{
gcc_assert
(
info
.
u
.
mov
.
value
==
const0_rtx
)
;
snprintf
(
buf
,
sizeof
(
buf
)
,
"pfalse\t%%0.b"
)
;
}
else
{
gcc_assert
(
info
.
insn
==
simd_immediate_info
::
PTRUE
)
;
unsigned
int
total_bytes
;
if
(
info
.
u
.
pattern
==
AARCH64_SV_ALL
&&
BYTES_PER_SVE_VECTOR
.
is_constant
(
&
total_bytes
)
)
snprintf
(
buf
,
sizeof
(
buf
)
,
"ptrue\t%%0.%c, vl%d"
,
element_char
,
total_bytes
/
GET_MODE_SIZE
(
info
.
elt_mode
)
)
;
else
snprintf
(
buf
,
sizeof
(
buf
)
,
"ptrue\t%%0.%c, %s"
,
element_char
,
svpattern_token
(
info
.
u
.
pattern
)
)
;
}
return
buf
;
}
if
(
info
.
insn
==
simd_immediate_info
::
INDEX
)
{
snprintf
(
templ
,
sizeof
(
templ
)
,
"index\t%%0.%c, #"
HOST_WIDE_INT_PRINT_DEC
", #"
HOST_WIDE_INT_PRINT_DEC
,
element_char
,
INTVAL
(
info
.
u
.
index
.
base
)
,
INTVAL
(
info
.
u
.
index
.
step
)
)
;
return
templ
;
}
if
(
GET_MODE_CLASS
(
info
.
elt_mode
)
==
MODE_FLOAT
)
{
if
(
aarch64_float_const_zero_rtx_p
(
info
.
u
.
mov
.
value
)
)
info
.
u
.
mov
.
value
=
GEN_INT
(
0
)
;
else
{
const
int
buf_size
=
20
;
char
float_buf
[
buf_size
]
=
{
}
;
real_to_decimal_for_mode
(
float_buf
,
CONST_DOUBLE_REAL_VALUE
(
info
.
u
.
mov
.
value
)
,
buf_size
,
buf_size
,
1
,
info
.
elt_mode
)
;
snprintf
(
templ
,
sizeof
(
templ
)
,
"fmov\t%%0.%c, #%s"
,
element_char
,
float_buf
)
;
return
templ
;
}
}
snprintf
(
templ
,
sizeof
(
templ
)
,
"mov\t%%0.%c, #"
HOST_WIDE_INT_PRINT_DEC
,
element_char
,
INTVAL
(
info
.
u
.
mov
.
value
)
)
;
return
templ
;
}
</s>

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


<s>
char
*
aarch64_output_sve_prefetch
(
const
char
*
mnemonic
,
rtx
prfop_rtx
,
const
char
*
suffix
)
{
static
char
buffer
[
128
]
;
aarch64_svprfop
prfop
=
(
aarch64_svprfop
)
INTVAL
(
prfop_rtx
)
;
unsigned
int
written
=
snprintf
(
buffer
,
sizeof
(
buffer
)
,
"%s\t%s, %s"
,
mnemonic
,
svprfop_token
(
prfop
)
,
suffix
)
;
gcc_assert
(
written
<
sizeof
(
buffer
)
)
;
return
buffer
;
}
</s>

Return the assembly string for an SVE prefetch operation with mnemonic MNEMONIC , given that PRFOP_RTX is the prefetch operation and that SUFFIX is the format for the remaining operands .


<s>
char
*
aarch64_output_sve_ptrues
(
rtx
const_unspec
)
{
static
char
templ
[
40
]
;
struct
simd_immediate_info
info
;
bool
is_valid
=
aarch64_simd_valid_immediate
(
const_unspec
,
&
info
)
;
gcc_assert
(
is_valid
&&
info
.
insn
==
simd_immediate_info
::
PTRUE
)
;
char
element_char
=
sizetochar
(
GET_MODE_BITSIZE
(
info
.
elt_mode
)
)
;
snprintf
(
templ
,
sizeof
(
templ
)
,
"ptrues\t%%0.%c, %s"
,
element_char
,
svpattern_token
(
info
.
u
.
pattern
)
)
;
return
templ
;
}
</s>

Return the asm template for a PTRUES . CONST_UNSPEC is the aarch64_sve_ptrue_svpattern_immediate that describes the predicate pattern .


<s> char * aarch64_output_sve_scalar_inc_dec ( rtx offset ) { poly_int64 offset_value = rtx_to_poly_int64 ( offset ) ; gcc_assert ( offset_value . coeffs [ 0 ] == offset_value . coeffs [ 1 ] ) ; if ( offset_value . coeffs [ 1 ] > 0 ) return aarch64_output_sve_cnt_immediate ( "inc" , "%x0" , AARCH64_SV_ALL , offset_value . coeffs [ 1 ] , 0 ) ; else return aarch64_output_sve_cnt_immediate ( "dec" , "%x0" , AARCH64_SV_ALL , - offset_value . coeffs [ 1 ] , 0 ) ; } </s>

Return the asm string for adding SVE INC/DEC immediate OFFSET to operand 0 .


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

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


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

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

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


<s> static void aarch64_override_options_after_change ( void ) { aarch64_override_options_after_change_1 ( & global_options ) ; } </s>


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

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


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

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


<s>
static
unsigned
int
aarch64_parse_boolean_options
(
const
char
*
option
,
const
struct
aarch64_flag_desc
*
flags
,
unsigned
int
initial_state
,
const
char
*
option_name
)
{
const
char
separator
=
'.'
;
const
char
*
specs
=
option
;
const
char
*
ntoken
=
option
;
unsigned
int
found_flags
=
initial_state
;
while
(
(
ntoken
=
strchr
(
specs
,
separator
)
)
)
{
size_t
token_length
=
ntoken
specs
;
unsigned
token_ops
=
aarch64_parse_one_option_token
(
specs
,
token_length
,
flags
,
option_name
)
;
if
(
!
token_ops
)
found_flags
=
0
;
found_flags
|=
token_ops
;
specs
=
++
ntoken
;
}
if
(
!
(
*
specs
)
)
{
error
(
"%s string ill-formed\n"
,
option_name
)
;
return
0
;
}
size_t
token_length
=
strlen
(
specs
)
;
unsigned
token_ops
=
aarch64_parse_one_option_token
(
specs
,
token_length
,
flags
,
option_name
)
;
if
(
!
token_ops
)
found_flags
=
0
;
found_flags
|=
token_ops
;
return
found_flags
;
}
</s>

Parse OPTION which is a comma-separated list of flags to enable . FLAGS gives the list of flags we understand , INITIAL_STATE gives any default state we inherit from the CPU tuning structures . OPTION_NAME gives the top-level option we are parsing in the -moverride string , for use in error messages .


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

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


<s> static void aarch64_parse_fuse_string ( const char * fuse_string , struct tune_params * tune ) { tune -> fusible_ops = aarch64_parse_boolean_options ( fuse_string , aarch64_fusible_pairs , tune -> fusible_ops , "fuse=" ) ; } </s>

Support for overriding instruction fusion .


"unknown flag passed in %<-moverride=%s%> (%s)"

Parse TOKEN , which has length LENGTH to see if it is an option described in FLAG . If it is , return the index bit for that fusion type . If not , error ( printing OPTION_NAME ) and return zero .


<s>
void
aarch64_parse_one_override_token
(
const
char
*
token
,
size_t
length
,
struct
tune_params
*
tune
)
{
const
struct
aarch64_tuning_override_function
*
fn
=
aarch64_tuning_override_functions
;
const
char
*
option_part
=
strchr
(
token
,
'='
)
;
if
(
!
option_part
)
{
error
(
"tuning string missing in option (%s)"
,
token
)
;
return
;
}
length
=
option_part
token
;
option_part
++
;
for
(
;
fn
->
name
!=
;
fn
++
)
{
if
(
!
strncmp
(
fn
->
name
,
token
,
length
)
)
{
fn
->
parse_override
(
option_part
,
tune
)
;
return
;
}
}
error
(
"unknown tuning option (%s)"
,
token
)
;
return
;
}
</s>

Parse TOKEN , which has length LENGTH to see if it is a tuning option we understand . If it is , extract the option string and handoff to the appropriate function .

aarch64
"tuning string missing in option (%s)"
"unknown tuning option (%s)"


<s> static void aarch64_parse_override_string ( const char * input_string , struct tune_params * tune ) { const char separator = ':' ; size_t string_length = strlen ( input_string ) + 1 ; char * string_root = ( char * ) xmalloc ( sizeof ( * string_root ) * string_length ) ; char * string = string_root ; strncpy ( string , input_string , string_length ) ; string [ string_length - 1 ] = '\0' ; char * ntoken = string ; while ( ( ntoken = strchr ( string , separator ) ) ) { size_t token_length = ntoken - string ; * ntoken = '\0' ; aarch64_parse_one_override_token ( string , token_length , tune ) ; string = ++ ntoken ; } aarch64_parse_one_override_token ( string , strlen ( string ) , tune ) ; free ( string_root ) ; } </s>

Parse STRING looking for options in the format : string : : option : string option : : name=substring name : : { a-z } substring : : defined by option .


<s>
static
void
aarch64_parse_sve_width_string
(
const
char
*
tune_string
,
struct
tune_params
*
tune
)
{
int
width
=
1
;
int
n
=
sscanf
(
tune_string
,
"%d"
,
&
width
)
;
if
(
n
==
EOF
)
{
error
(
"invalid format for sve_width"
)
;
return
;
}
switch
(
width
)
{
case
SVE_128
:
case
SVE_256
:
case
SVE_512
:
case
SVE_1024
:
case
SVE_2048
:
break
;
default
:
error
(
"invalid sve_width value: %d"
,
width
)
;
}
tune
->
sve_width
=
(
enum
aarch64_sve_vector_bits_enum
)
width
;
}
</s>

Parse the sve_width tuning moverride string in TUNE_STRING . Accept the valid SVE vector widths allowed by aarch64_sve_vector_bits_enum and use it to override sve_width in TUNE .


<s> static enum aarch64_parse_opt_result aarch64_parse_tune ( const char * to_parse , const struct processor * * res ) { const struct processor * cpu ; for ( cpu = all_cores ; cpu -> name != NULL ; cpu ++ ) { if ( strcmp ( cpu -> name , to_parse ) == 0 ) { * res = cpu ; return AARCH64_PARSE_OK ; } } return AARCH64_PARSE_INVALID_ARG ; } </s>


<s> static void aarch64_parse_tune_string ( const char * tune_string , struct tune_params * tune ) { tune -> extra_tuning_flags = aarch64_parse_boolean_options ( tune_string , aarch64_tuning_flags , tune -> extra_tuning_flags , "tune=" ) ; } </s>

Support for overriding other tuning flags .


<s> int aarch64_partial_ptrue_length ( rtx_vector_builder & builder , unsigned int elt_size ) { if ( builder . nelts_per_pattern ( ) == 3 ) return 0 ; unsigned int nelts = builder . encoded_nelts ( ) ; unsigned int i = 0 ; for ( ; i < nelts ; i += elt_size ) if ( INTVAL ( builder . elt ( i ) ) == 0 ) break ; unsigned int vl = i / elt_size ; if ( i == nelts ) return - 1 ; if ( builder . nelts_per_pattern ( ) != 2 ) return 0 ; if ( i > builder . npatterns ( ) && maybe_ne ( nelts , builder . full_nelts ( ) ) ) return 0 ; for ( ; i < nelts ; i += elt_size ) if ( INTVAL ( builder . elt ( i ) ) != 0 ) return 0 ; return vl ; } </s>

BUILDER is a predicate constant of mode VNx16BI . Consider the value that the constant would have with predicate element size ELT_SIZE ( ignoring the upper bits in each element ) and return : * -1 if all bits are set * N if the predicate has N leading set bits followed by all clear bits * 0 if the predicate does not have any of these forms .


<s>
static
bool
aarch64_pass_by_reference
(
cumulative_args_t
pcum_v
,
const
function_arg_info
&
arg
)
{
CUMULATIVE_ARGS
*
pcum
=
get_cumulative_args
(
pcum_v
)
;
if
(
!
arg
.
type
)
return
aarch64_pass_by_reference_1
(
pcum
,
arg
)
;
pure_scalable_type_info
pst_info
;
switch
(
pst_info
.
analyze
(
arg
.
type
)
)
{
case
pure_scalable_type_info
::
IS_PST
:
if
(
pcum
&&
!
pcum
->
silent_p
&&
!
TARGET_SVE
)
fatal_error
(
input_location
,
"arguments of type %qT require"
" the SVE ISA extension"
,
arg
.
type
)
;
return
(
!
arg
.
named
||
pcum
->
aapcs_nvrn
+
pst_info
.
num_zr
(
)
>
NUM_FP_ARG_REGS
||
pcum
->
aapcs_nprn
+
pst_info
.
num_pr
(
)
>
NUM_PR_ARG_REGS
)
;
case
pure_scalable_type_info
::
DOESNT_MATTER
:
gcc_assert
(
aarch64_pass_by_reference_1
(
pcum
,
arg
)
)
;
return
true
;
case
pure_scalable_type_info
::
NO_ABI_IDENTITY
:
case
pure_scalable_type_info
::
ISNT_PST
:
return
aarch64_pass_by_reference_1
(
pcum
,
arg
)
;
}
gcc_unreachable
(
)
;
}
</s>

aarch64
"arguments of type %qT require"
" the SVE ISA extension"


<s> static bool aarch64_pass_by_reference_1 ( CUMULATIVE_ARGS * pcum , const function_arg_info & arg ) { HOST_WIDE_INT size ; machine_mode dummymode ; int nregs ; if ( arg . mode == BLKmode && arg . type ) size = int_size_in_bytes ( arg . type ) ; else size = GET_MODE_SIZE ( arg . mode ) . to_constant ( ) ; if ( arg . aggregate_type_p ( ) ) size = int_size_in_bytes ( arg . type ) ; if ( size < 0 ) return true ; if ( aarch64_vfp_is_call_or_return_candidate ( arg . mode , arg . type , & dummymode , & nregs , NULL , ! pcum || pcum -> silent_p ) ) return false ; return size > 2 * UNITS_PER_WORD ; } </s>

Subroutine of aarch64_pass_by_reference for arguments that are not passed in SVE registers .


<s> rtx aarch64_pfalse_reg ( machine_mode mode ) { gcc_assert ( GET_MODE_CLASS ( mode ) == MODE_VECTOR_BOOL ) ; rtx reg = force_reg ( VNx16BImode , CONST0_RTX ( VNx16BImode ) ) ; return gen_lowpart ( mode , reg ) ; } </s>

Return an all-false predicate register of mode MODE .


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

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


<s> void aarch64_post_cfi_startproc ( FILE * f , tree ignored ATTRIBUTE_UNUSED ) { if ( cfun -> machine -> frame . laid_out && aarch64_return_address_signing_enabled ( ) && aarch64_ra_sign_key == AARCH64_KEY_B ) asm_fprintf ( f , "\t.cfi_b_key_frame\n" ) ; } </s>

Triggered after a .cfi_startproc directive is emitted into the assembly file . Used to output the .cfi_b_key_frame directive when signing the current function with the B key .


<s> static tree aarch64_preferred_else_value ( unsigned , tree , unsigned int nops , tree * ops ) { return nops == 3 ? ops [ 2 ] : ops [ 0 ] ; } </s>

Implement TARGET_PREFERRED_ELSE_VALUE . For binary operations , prefer to use the first arithmetic operand as the else value if the else value does n't matter , since that exactly matches the SVE destructive merging form . For ternary operations we could either pick the first operand and use FMAD-like instructions or the last operand and use FMLA-like instructions ; the latter seems more natural .


<s> static machine_mode aarch64_preferred_simd_mode ( scalar_mode mode ) { poly_int64 bits = TARGET_SVE ? BITS_PER_SVE_VECTOR : 128 ; return aarch64_simd_container_mode ( mode , bits ) ; } </s>

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


<s> bool aarch64_prepare_sve_cond_int_fma ( rtx * operands , rtx_code code ) { machine_mode mode = GET_MODE ( operands [ 0 ] ) ; if ( rtx shifts = aarch64_convert_mult_to_shift ( operands [ 3 ] , code ) ) { rtx product = expand_binop ( mode , vashl_optab , operands [ 2 ] , shifts , NULL_RTX , true , OPTAB_DIRECT ) ; emit_insn ( gen_cond ( code , mode , operands [ 0 ] , operands [ 1 ] , operands [ 4 ] , product , operands [ 5 ] ) ) ; return true ; } operands [ 3 ] = force_reg ( mode , operands [ 3 ] ) ; return false ; } </s>

Likewise , but for a conditional pattern .


<s> bool aarch64_prepare_sve_int_fma ( rtx * operands , rtx_code code ) { machine_mode mode = GET_MODE ( operands [ 0 ] ) ; if ( rtx shifts = aarch64_convert_mult_to_shift ( operands [ 2 ] , code ) ) { rtx product = expand_binop ( mode , vashl_optab , operands [ 1 ] , shifts , NULL_RTX , true , OPTAB_DIRECT ) ; force_expand_binop ( mode , code == PLUS ? add_optab : sub_optab , operands [ 3 ] , product , operands [ 0 ] , true , OPTAB_DIRECT ) ; return true ; } operands [ 2 ] = force_reg ( mode , operands [ 2 ] ) ; return false ; } </s>

Prepare for an integer SVE multiply-add or multiply-subtract pattern ; CODE is PLUS for the former and MINUS for the latter . OPERANDS is the operands array , in the same order as for fma_optab . Return true if the function emitted all the necessary instructions , false if the caller should generate the pattern normally with the new OPERANDS array .


<s> static rtx_insn * aarch64_prev_real_insn ( rtx_insn * insn ) { if ( ! insn ) return NULL ; do { insn = prev_real_insn ( insn ) ; } while ( insn && recog_memoized ( insn ) < 0 ) ; return insn ; } </s>

Find the first rtx_insn before insn that will generate an assembly instruction .


<s> inline static void aarch64_print_hint_for_arch ( const char * str ) { aarch64_print_hint_for_core_or_arch ( str , true ) ; } </s>

Print a hint with a suggestion for an architecture name that most closely resembles what the user passed in STR .


<s> inline static void aarch64_print_hint_for_core ( const char * str ) { aarch64_print_hint_for_core_or_arch ( str , false ) ; } </s>

Print a hint with a suggestion for a core name that most closely resembles what the user passed in STR .


<s>
static
void
aarch64_print_hint_for_core_or_arch
(
const
char
*
str
,
bool
arch
)
{
auto_vec
<
const
char
*
>
candidates
;
const
struct
processor
*
entry
=
arch
all_architectures
:
all_cores
;
for
(
;
entry
->
name
!=
;
entry
++
)
candidates
.
safe_push
(
entry
->
name
)
;
if
(
arch
)
candidates
.
safe_push
(
"native"
)
;
char
*
s
;
const
char
*
hint
=
candidates_list_and_hint
(
str
,
s
,
candidates
)
;
if
(
hint
)
inform
(
input_location
,
"valid arguments are: %s;"
" did you mean %qs?"
,
s
,
hint
)
;
else
inform
(
input_location
,
"valid arguments are: %s"
,
s
)
;
XDELETEVEC
(
s
)
;
}
</s>

Print a hint with a suggestion for a core or architecture name that most closely resembles what the user passed in STR . ARCH is true if the user is asking for an architecture name . ARCH is false if the user is asking for a core name .

aarch64
"native"
"valid arguments are: %s;"
" did you mean %qs?"
"valid arguments are: %s"


<s>
void
aarch64_print_hint_for_extensions
(
const
std
::
string
&
str
)
{
auto_vec
<
const
char
*
>
candidates
;
aarch64_get_all_extension_candidates
(
&
candidates
)
;
char
*
s
;
const
char
*
hint
=
candidates_list_and_hint
(
str
.
c_str
(
)
,
s
,
candidates
)
;
if
(
hint
)
inform
(
input_location
,
"valid arguments are: %s;"
" did you mean %qs?"
,
s
,
hint
)
;
else
inform
(
input_location
,
"valid arguments are: %s;"
,
s
)
;
XDELETEVEC
(
s
)
;
}
</s>

Print a hint with a suggestion for an extension name that most closely resembles what the user passed in STR .

aarch64
"valid arguments are: %s;"
" did you mean %qs?"
"valid arguments are: %s;"


<s> static void aarch64_print_operand_address ( FILE * f , machine_mode mode , rtx x ) { if ( ! aarch64_print_address_internal ( f , mode , x , ADDR_QUERY_ANY ) ) output_addr_const ( f , x ) ; } </s>

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


<s>
void
aarch64_print_patchable_function_entry
(
FILE
*
file
,
unsigned
HOST_WIDE_INT
patch_area_size
,
bool
record_p
)
{
if
(
cfun
->
machine
->
label_is_assembled
&&
aarch64_bti_enabled
(
)
&&
!
cgraph_node
::
get
(
cfun
->
decl
)
->
only_called_directly_p
(
)
)
{
rtx_insn
*
insn
=
next_real_nondebug_insn
(
get_insns
(
)
)
;
if
(
insn
&&
INSN_P
(
insn
)
&&
GET_CODE
(
PATTERN
(
insn
)
)
==
UNSPEC_VOLATILE
&&
XINT
(
PATTERN
(
insn
)
,
1
)
==
UNSPECV_BTI_C
)
delete_insn
(
insn
)
;
asm_fprintf
(
file
,
"\thint\t34 // bti c\n"
)
;
}
default_print_patchable_function_entry
(
file
,
patch_area_size
,
record_p
)
;
}
</s>

Implement PRINT_PATCHABLE_FUNCTION_ENTRY . Check if the patch area is after the function label and emit a BTI if necessary .


<s> static bool aarch64_print_vector_float_operand ( FILE * f , rtx x , bool negate ) { rtx elt ; if ( ! const_vec_duplicate_p ( x , & elt ) ) return false ; REAL_VALUE_TYPE r = * CONST_DOUBLE_REAL_VALUE ( elt ) ; if ( negate ) r = real_value_negate ( & r ) ; if ( real_equal ( & r , & dconst0 ) ) asm_fprintf ( f , "0.0" ) ; else if ( real_equal ( & r , & dconst2 ) ) asm_fprintf ( f , "2.0" ) ; else if ( real_equal ( & r , & dconst1 ) ) asm_fprintf ( f , "1.0" ) ; else if ( real_equal ( & r , & dconsthalf ) ) asm_fprintf ( f , "0.5" ) ; else { const int buf_size = 20 ; char float_buf [ buf_size ] = { '\0' } ; real_to_decimal_for_mode ( float_buf , & r , buf_size , buf_size , 1 , GET_MODE ( elt ) ) ; asm_fprintf ( f , "%s" , float_buf ) ; } return true ; } </s>

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


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

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

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

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

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


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

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

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

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


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

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


<s> static tree aarch64_promoted_type ( const_tree t ) { if ( SCALAR_FLOAT_TYPE_P ( t ) && TYPE_MAIN_VARIANT ( t ) == aarch64_fp16_type_node ) return float_type_node ; return NULL_TREE ; } </s>

Implement TARGET_PROMOTED_TYPE to promote __fp16 to float .


<s> rtx aarch64_ptrue_all ( unsigned int elt_size ) { rtx_vector_builder builder ( VNx16BImode , elt_size , 1 ) ; builder . quick_push ( const1_rtx ) ; for ( unsigned int i = 1 ; i < elt_size ; ++ i ) builder . quick_push ( const0_rtx ) ; return builder . build ( ) ; } </s>

Return a VNx16BImode constant in which every sequence of ELT_SIZE bits has the lowest bit set and the upper bits clear . This is the VNx16BImode equivalent of a PTRUE for controlling elements of ELT_SIZE bytes . However , because the constant is VNx16BImode , all bits are significant , even the upper zeros .


<s> opt_machine_mode aarch64_ptrue_all_mode ( rtx x ) { gcc_assert ( GET_MODE ( x ) == VNx16BImode ) ; if ( GET_CODE ( x ) != CONST_VECTOR || ! CONST_VECTOR_DUPLICATE_P ( x ) || ! CONST_INT_P ( CONST_VECTOR_ENCODED_ELT ( x , 0 ) ) || INTVAL ( CONST_VECTOR_ENCODED_ELT ( x , 0 ) ) == 0 ) return opt_machine_mode ( ) ; unsigned int nelts = const_vector_encoded_nelts ( x ) ; for ( unsigned int i = 1 ; i < nelts ; ++ i ) if ( CONST_VECTOR_ENCODED_ELT ( x , i ) != const0_rtx ) return opt_machine_mode ( ) ; return aarch64_sve_pred_mode ( nelts ) ; } </s>

If VNx16BImode rtx X is a canonical PTRUE for a predicate mode , return that predicate mode , otherwise return opt_machine_mode ( ) .


<s> rtx aarch64_ptrue_reg ( machine_mode mode ) { gcc_assert ( GET_MODE_CLASS ( mode ) == MODE_VECTOR_BOOL ) ; rtx reg = force_reg ( VNx16BImode , CONSTM1_RTX ( VNx16BImode ) ) ; return gen_lowpart ( mode , reg ) ; } </s>

Return an all-true predicate register of mode MODE .


<s> static void aarch64_pushwb_single_reg ( machine_mode mode , unsigned regno , HOST_WIDE_INT adjustment ) { rtx base_rtx = stack_pointer_rtx ; rtx insn , reg , mem ; reg = gen_rtx_REG ( mode , regno ) ; mem = gen_rtx_PRE_MODIFY ( Pmode , base_rtx , plus_constant ( Pmode , base_rtx , - adjustment ) ) ; mem = gen_frame_mem ( mode , mem ) ; insn = emit_move_insn ( mem , reg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } </s>

Push the register number REGNO of mode MODE to the stack with write-back adjusting the stack by ADJUSTMENT .


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

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


<s> static int aarch64_reassociation_width ( unsigned opc , machine_mode mode ) { if ( VECTOR_MODE_P ( mode ) ) return aarch64_tune_params . vec_reassoc_width ; if ( INTEGRAL_MODE_P ( mode ) ) return aarch64_tune_params . int_reassoc_width ; if ( FLOAT_MODE_P ( mode ) && opc != PLUS_EXPR ) return aarch64_tune_params . fp_reassoc_width ; return 1 ; } </s>

Return the reassociation width of treeop OPC with mode MODE .


<s> static bool aarch64_register_saved_on_entry ( int regno ) { return known_ge ( cfun -> machine -> frame . reg_offset [ regno ] , 0 ) ; } </s>

Return true if the register REGNO is saved on entry to the current function .


<s> poly_uint64 aarch64_regmode_natural_size ( machine_mode mode ) { if ( ! aarch64_sve_vg . is_constant ( ) ) { unsigned int vec_flags = aarch64_classify_vector_mode ( mode ) ; if ( vec_flags & VEC_SVE_PRED ) return BYTES_PER_SVE_PRED ; if ( vec_flags & VEC_SVE_DATA ) return BYTES_PER_SVE_VECTOR ; } return UNITS_PER_WORD ; } </s>


<s> bool aarch64_regno_ok_for_base_p ( int regno , bool strict_p ) { if ( ! HARD_REGISTER_NUM_P ( regno ) ) { if ( ! strict_p ) return true ; if ( ! reg_renumber ) return false ; regno = reg_renumber [ regno ] ; } return ( GP_REGNUM_P ( regno ) || regno == SP_REGNUM || regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM ) ; } </s>

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


<s> bool aarch64_regno_ok_for_index_p ( int regno , bool strict_p ) { if ( ! HARD_REGISTER_NUM_P ( regno ) ) { if ( ! strict_p ) return true ; if ( ! reg_renumber ) return false ; regno = reg_renumber [ regno ] ; } return GP_REGNUM_P ( regno ) ; } </s>

Return true if register REGNO is a valid index register . STRICT_P is true if REG_OK_STRICT is in effect .


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


<s> static machine_mode aarch64_reg_save_mode ( unsigned int regno ) { if ( GP_REGNUM_P ( regno ) ) return DImode ; if ( FP_REGNUM_P ( regno ) ) switch ( crtl -> abi -> id ( ) ) { case ARM_PCS_AAPCS64 : return DFmode ; case ARM_PCS_SIMD : return TFmode ; case ARM_PCS_SVE : if ( aarch64_emit_cfi_for_reg_p ( regno ) ) return VNx2DImode ; return VNx16QImode ; case ARM_PCS_TLSDESC : case ARM_PCS_UNKNOWN : break ; } if ( PR_REGNUM_P ( regno ) ) return VNx16BImode ; gcc_unreachable ( ) ; } </s>

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


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

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


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

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


<s> static unsigned HOST_WIDE_INT aarch64_replicate_bitmask_imm ( unsigned HOST_WIDE_INT val , machine_mode mode ) { unsigned int size = GET_MODE_UNIT_PRECISION ( mode ) ; while ( size < 64 ) { val &= ( HOST_WIDE_INT_1U << size ) - 1 ; val |= val << size ; size *= 2 ; } return val ; } </s>

VAL is a value with the inner mode of MODE . Replicate it to fill a 64-bit ( DImode ) integer .


"this operation requires the SVE ISA extension"

"you can enable SVE using the command-line"

" option %<-march%>, or by using the %<target%>"

Report when we try to do something that requires SVE when SVE is disabled . This is an error of last resort and is n't very high-quality . It usually involves attempts to measure the vector length in some way .


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

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


<s> static bool aarch64_returns_value_in_sve_regs_p ( const_tree fntype ) { tree return_type = TREE_TYPE ( fntype ) ; pure_scalable_type_info pst_info ; switch ( pst_info . analyze ( return_type ) ) { case pure_scalable_type_info :: IS_PST : return ( pst_info . num_zr ( ) <= NUM_FP_ARG_REGS && pst_info . num_pr ( ) <= NUM_PR_ARG_REGS ) ; case pure_scalable_type_info :: DOESNT_MATTER : gcc_assert ( aarch64_return_in_memory_1 ( return_type ) ) ; return false ; case pure_scalable_type_info :: NO_ABI_IDENTITY : case pure_scalable_type_info :: ISNT_PST : return false ; } gcc_unreachable ( ) ; } </s>

Return true if a function with type FNTYPE returns its value in SVE vector or predicate registers .


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

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


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

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


<s> static bool aarch64_return_in_memory ( const_tree type , const_tree fndecl ATTRIBUTE_UNUSED ) { pure_scalable_type_info pst_info ; switch ( pst_info . analyze ( type ) ) { case pure_scalable_type_info :: IS_PST : return ( pst_info . num_zr ( ) > NUM_FP_ARG_REGS || pst_info . num_pr ( ) > NUM_PR_ARG_REGS ) ; case pure_scalable_type_info :: DOESNT_MATTER : gcc_assert ( aarch64_return_in_memory_1 ( type ) ) ; return true ; case pure_scalable_type_info :: NO_ABI_IDENTITY : case pure_scalable_type_info :: ISNT_PST : return aarch64_return_in_memory_1 ( type ) ; } gcc_unreachable ( ) ; } </s>

Implement TARGET_RETURN_IN_MEMORY . If the type T of the result of a function is such that void func ( T arg ) would require that arg be passed as a value in a register ( or set of registers ) according to the parameter passing rules , then the result is returned in the same registers as would be used for such an argument .


<s> static bool aarch64_return_in_memory_1 ( const_tree type ) { HOST_WIDE_INT size ; machine_mode ag_mode ; int count ; if ( ! AGGREGATE_TYPE_P ( type ) && TREE_CODE ( type ) != COMPLEX_TYPE && TREE_CODE ( type ) != VECTOR_TYPE ) return false ; if ( aarch64_vfp_is_call_or_return_candidate ( TYPE_MODE ( type ) , type , & ag_mode , & count , NULL , false ) ) return false ; size = int_size_in_bytes ( type ) ; return ( size < 0 || size > 2 * UNITS_PER_WORD ) ; } </s>

Subroutine for aarch64_return_in_memory for types that are not returned in SVE registers .


<s> static bool aarch64_return_in_msb ( const_tree valtype ) { machine_mode dummy_mode ; int dummy_int ; if ( ! BYTES_BIG_ENDIAN ) return false ; if ( ! aarch64_composite_type_p ( valtype , TYPE_MODE ( valtype ) ) || int_size_in_bytes ( valtype ) <= 0 || int_size_in_bytes ( valtype ) > 16 ) return false ; if ( aarch64_vfp_is_call_or_return_candidate ( TYPE_MODE ( valtype ) , valtype , & dummy_mode , & dummy_int , NULL , false ) ) return false ; pure_scalable_type_info pst_info ; if ( pst_info . analyze_registers ( valtype ) ) return false ; return true ; } </s>

Return TRUE if VALTYPE is padded to its least significant bits .


<s> rtx aarch64_reverse_mask ( machine_mode mode , unsigned int nunits ) { rtx mask ; rtvec v = rtvec_alloc ( 16 ) ; unsigned int i , j ; unsigned int usize = GET_MODE_UNIT_SIZE ( mode ) ; gcc_assert ( BYTES_BIG_ENDIAN ) ; gcc_assert ( AARCH64_VALID_SIMD_QREG_MODE ( mode ) ) ; for ( i = 0 ; i < nunits ; i ++ ) for ( j = 0 ; j < usize ; j ++ ) RTVEC_ELT ( v , i * usize + j ) = GEN_INT ( ( i + 1 ) * usize - 1 - j ) ; mask = gen_rtx_CONST_VECTOR ( V16QImode , v ) ; return force_reg ( V16QImode , mask ) ; } </s>

Generate a byte permute mask for a register of mode MODE , which has NUNITS units .


<s> static bool aarch64_rtx_arith_op_extract_p ( rtx x , scalar_int_mode mode ) { if ( GET_CODE ( x ) == SIGN_EXTRACT || GET_CODE ( x ) == ZERO_EXTRACT ) { rtx op0 = XEXP ( x , 0 ) ; rtx op1 = XEXP ( x , 1 ) ; rtx op2 = XEXP ( x , 2 ) ; if ( GET_CODE ( op0 ) == MULT && CONST_INT_P ( op1 ) && op2 == const0_rtx && CONST_INT_P ( XEXP ( op0 , 1 ) ) && aarch64_is_extend_from_extract ( mode , XEXP ( op0 , 1 ) , op1 ) ) { return true ; } } else if ( GET_CODE ( x ) == SIGN_EXTEND || GET_CODE ( x ) == ZERO_EXTEND ) return REG_P ( XEXP ( x , 0 ) ) ; return false ; } </s>

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


<s>
static
bool
aarch64_rtx_costs_wrapper
(
rtx
x
,
machine_mode
mode
,
int
outer
,
int
param
,
int
*
cost
,
bool
speed
)
{
bool
result
=
aarch64_rtx_costs
(
x
,
mode
,
outer
,
param
,
cost
,
speed
)
;
if
(
dump_file
&&
flag_aarch64_verbose_cost
)
{
print_rtl_single
(
dump_file
,
x
)
;
fprintf
(
dump_file
,
"\n%s cost: %d (%s)\n"
,
speed
"Hot"
:
"Cold"
,
*
cost
,
result
"final"
:
"partial"
)
;
}
return
result
;
}
</s>

Wrapper around aarch64_rtx_costs , dumps the partial , or total cost calculated for X . This cost is stored in * COST . Returns true if the total cost of X was calculated .

aarch64
"\n%s cost: %d (%s)\n"
"Hot"
"Cold"
"final"
"partial"


<s> static void aarch64_run_selftests ( void ) { aarch64_test_loading_full_dump ( ) ; } </s>


<s> void aarch64_save_restore_target_globals ( tree new_tree ) { if ( TREE_TARGET_GLOBALS ( new_tree ) ) restore_target_globals ( TREE_TARGET_GLOBALS ( new_tree ) ) ; else if ( new_tree == target_option_default_node ) restore_target_globals ( & default_target_globals ) ; else TREE_TARGET_GLOBALS ( new_tree ) = save_target_globals_default_opts ( ) ; } </s>

Restore or save the TREE_TARGET_GLOBALS from or to NEW_TREE . Used by aarch64_set_current_function and aarch64_pragma_target_parse to make sure optab availability predicates are recomputed when necessary .


<s> static bool aarch64_scalar_mode_supported_p ( scalar_mode mode ) { return ( mode == HFmode ? true : default_scalar_mode_supported_p ( mode ) ) ; } </s>

Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE if MODE is HFmode , and punt to the generic implementation otherwise .


<s> static int aarch64_sched_adjust_priority ( rtx_insn * insn , int priority ) { rtx x = PATTERN ( insn ) ; if ( GET_CODE ( x ) == SET ) { x = SET_SRC ( x ) ; if ( GET_CODE ( x ) == UNSPEC && XINT ( x , 1 ) == UNSPEC_SHA1H ) return priority + 10 ; } return priority ; } </s>

Implement the TARGET_SCHED_ADJUST_PRIORITY hook . Adjust priority of sha1h instructions so they are scheduled before other SHA1 instructions .


<s> static bool aarch64_sched_can_speculate_insn ( rtx_insn * insn ) { switch ( get_attr_type ( insn ) ) { case TYPE_SDIV : case TYPE_UDIV : case TYPE_FDIVS : case TYPE_FDIVD : case TYPE_FSQRTS : case TYPE_FSQRTD : case TYPE_NEON_FP_SQRT_S : case TYPE_NEON_FP_SQRT_D : case TYPE_NEON_FP_SQRT_S_Q : case TYPE_NEON_FP_SQRT_D_Q : case TYPE_NEON_FP_DIV_S : case TYPE_NEON_FP_DIV_D : case TYPE_NEON_FP_DIV_S_Q : case TYPE_NEON_FP_DIV_D_Q : return false ; default : return true ; } } </s>

Implement TARGET_SCHED_CAN_SPECULATE_INSN . Return true if INSN can be scheduled for speculative execution . Reject the long-running division and square-root instructions .


<s> static void aarch64_sched_fusion_priority ( rtx_insn * insn , int max_pri , int * fusion_pri , int * pri ) { int tmp , off_val ; rtx base , offset ; enum sched_fusion_type fusion ; gcc_assert ( INSN_P ( insn ) ) ; tmp = max_pri - 1 ; fusion = fusion_load_store ( insn , & base , & offset ) ; if ( fusion == SCHED_FUSION_NONE ) { * pri = tmp ; * fusion_pri = tmp ; return ; } * fusion_pri = tmp - fusion * FIRST_PSEUDO_REGISTER - REGNO ( base ) ; tmp /= 2 ; off_val = ( int ) ( INTVAL ( offset ) ) ; if ( off_val >= 0 ) tmp -= ( off_val & 0xfffff ) ; else tmp += ( ( - off_val ) & 0xfffff ) ; * pri = tmp ; return ; } </s>

Implement the TARGET_SCHED_FUSION_PRIORITY hook . Currently we only support to fuse ldr or str instructions , so FUSION_PRI and PRI are only calculated for these instructions . For other instruction , FUSION_PRI and PRI are simply set to MAX_PRI - 1 . In the future , other type instruction fusion can be added by returning different priorities . It 's important that irrelevant instructions get the largest FUSION_PRI .


<s> static int aarch64_sched_issue_rate ( void ) { return aarch64_tune_params . issue_rate ; } </s>

Return the number of instructions that can be issued per cycle .


<s> static int aarch64_sched_variable_issue ( FILE * , int , rtx_insn * insn , int more ) { if ( DEBUG_INSN_P ( insn ) ) return more ; rtx_code code = GET_CODE ( PATTERN ( insn ) ) ; if ( code == USE || code == CLOBBER ) return more ; if ( get_attr_type ( insn ) == TYPE_NO_INSN ) return more ; return more - 1 ; } </s>


<s> static void aarch64_select_early_remat_modes ( sbitmap modes ) { for ( int i = 0 ; i < NUM_MACHINE_MODES ; ++ i ) if ( aarch64_sve_mode_p ( ( machine_mode ) i ) ) bitmap_set_bit ( modes , i ) ; } </s>


Select appropriate section for constants depending on where we place literal pools .


<s> static void aarch64_setup_incoming_varargs ( cumulative_args_t cum_v , const function_arg_info & arg , int * pretend_size ATTRIBUTE_UNUSED , int no_rtl ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; CUMULATIVE_ARGS local_cum ; int gr_saved = cfun -> va_list_gpr_size ; int vr_saved = cfun -> va_list_fpr_size ; local_cum = * cum ; aarch64_function_arg_advance ( pack_cumulative_args ( & local_cum ) , arg ) ; if ( cfun -> va_list_gpr_size ) gr_saved = MIN ( NUM_ARG_REGS - local_cum . aapcs_ncrn , cfun -> va_list_gpr_size / UNITS_PER_WORD ) ; if ( cfun -> va_list_fpr_size ) vr_saved = MIN ( NUM_FP_ARG_REGS - local_cum . aapcs_nvrn , cfun -> va_list_fpr_size / UNITS_PER_VREG ) ; if ( ! TARGET_FLOAT ) { gcc_assert ( local_cum . aapcs_nvrn == 0 ) ; vr_saved = 0 ; } if ( ! no_rtl ) { if ( gr_saved > 0 ) { rtx ptr , mem ; ptr = plus_constant ( Pmode , virtual_incoming_args_rtx , - gr_saved * UNITS_PER_WORD ) ; mem = gen_frame_mem ( BLKmode , ptr ) ; set_mem_alias_set ( mem , get_varargs_alias_set ( ) ) ; move_block_from_reg ( local_cum . aapcs_ncrn + R0_REGNUM , mem , gr_saved ) ; } if ( vr_saved > 0 ) { machine_mode mode = TImode ; int off , i , vr_start ; off = - ROUND_UP ( gr_saved * UNITS_PER_WORD , STACK_BOUNDARY / BITS_PER_UNIT ) ; off -= vr_saved * UNITS_PER_VREG ; vr_start = V0_REGNUM + local_cum . aapcs_nvrn ; for ( i = 0 ; i < vr_saved ; ++ i ) { rtx ptr , mem ; ptr = plus_constant ( Pmode , virtual_incoming_args_rtx , off ) ; mem = gen_frame_mem ( mode , ptr ) ; set_mem_alias_set ( mem , get_varargs_alias_set ( ) ) ; aarch64_emit_move ( mem , gen_rtx_REG ( mode , vr_start + i ) ) ; off += UNITS_PER_VREG ; } } } cfun -> machine -> frame . saved_varargs_size = ( ROUND_UP ( gr_saved * UNITS_PER_WORD , STACK_BOUNDARY / BITS_PER_UNIT ) + vr_saved * UNITS_PER_VREG ) ; } </s>


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

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


<s> static void aarch64_set_handled_components ( sbitmap components ) { for ( unsigned regno = 0 ; regno <= LAST_SAVED_REGNUM ; regno ++ ) if ( bitmap_bit_p ( components , regno ) ) cfun -> machine -> reg_is_wrapped_separately [ regno ] = true ; } </s>


<s> static bool aarch64_shift_p ( enum rtx_code code ) { return code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT ; } </s>

Return true iff CODE is a shift supported in combination with arithmetic instructions .


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


<s> static const predefined_function_abi & aarch64_simd_abi ( void ) { predefined_function_abi & simd_abi = function_abis [ ARM_PCS_SIMD ] ; if ( ! simd_abi . initialized_p ( ) ) { HARD_REG_SET full_reg_clobbers = default_function_abi . full_reg_clobbers ( ) ; for ( int regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( FP_SIMD_SAVED_REGNUM_P ( regno ) ) CLEAR_HARD_REG_BIT ( full_reg_clobbers , regno ) ; simd_abi . initialize ( ARM_PCS_SIMD , full_reg_clobbers ) ; } return simd_abi ; } </s>


<s> int aarch64_simd_attr_length_rglist ( machine_mode mode ) { return ( GET_MODE_SIZE ( mode ) . to_constant ( ) / UNITS_PER_VREG ) * 4 ; } </s>

Compute and return the length of aarch64_simd_reglist < mode > , where < mode > is one of VSTRUCT modes : OI , CI , EI , or XI .


<s> bool aarch64_simd_check_vect_par_cnst_half ( rtx op , machine_mode mode , bool high ) { int nelts ; if ( ! VECTOR_MODE_P ( mode ) || ! GET_MODE_NUNITS ( mode ) . is_constant ( & nelts ) ) return false ; rtx ideal = aarch64_simd_vect_par_cnst_half ( mode , nelts , high ) ; HOST_WIDE_INT count_op = XVECLEN ( op , 0 ) ; HOST_WIDE_INT count_ideal = XVECLEN ( ideal , 0 ) ; int i = 0 ; if ( count_op != count_ideal ) return false ; for ( i = 0 ; i < count_ideal ; i ++ ) { rtx elt_op = XVECEXP ( op , 0 , i ) ; rtx elt_ideal = XVECEXP ( ideal , 0 , i ) ; if ( ! CONST_INT_P ( elt_op ) || INTVAL ( elt_ideal ) != INTVAL ( elt_op ) ) return false ; } return true ; } </s>

Check OP for validity as a PARALLEL RTX vector with elements numbering the lanes of either the high ( HIGH == TRUE ) or low lanes , from the perspective of the architecture . See the diagram above aarch64_simd_vect_par_cnst_half for more details .


<s> static void aarch64_simd_clone_adjust ( struct cgraph_node * node ) { tree t = TREE_TYPE ( node -> decl ) ; TYPE_ATTRIBUTES ( t ) = make_attribute ( "aarch64_vector_pcs" , "default" , TYPE_ATTRIBUTES ( t ) ) ; } </s>


"GCC does not currently support mixed size types "

"GCC does not currently support return type %qT "

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

"GCC does not currently support argument type %qT "

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


<s> static int aarch64_simd_clone_usable ( struct cgraph_node * node ) { switch ( node -> simdclone -> vecsize_mangle ) { case 'n' : if ( ! TARGET_SIMD ) return - 1 ; return 0 ; default : gcc_unreachable ( ) ; } } </s>


<s> static machine_mode aarch64_simd_container_mode ( scalar_mode mode , poly_int64 width ) { if ( TARGET_SVE && maybe_ne ( width , 128 ) && known_eq ( width , BITS_PER_SVE_VECTOR ) ) return aarch64_full_sve_mode ( mode ) . else_mode ( word_mode ) ; gcc_assert ( known_eq ( width , 64 ) || known_eq ( width , 128 ) ) ; if ( TARGET_SIMD ) { if ( known_eq ( width , 128 ) ) return aarch64_vq_mode ( mode ) . else_mode ( word_mode ) ; else switch ( mode ) { case E_SFmode : return V2SFmode ; case E_HFmode : return V4HFmode ; case E_BFmode : return V4BFmode ; case E_SImode : return V2SImode ; case E_HImode : return V4HImode ; case E_QImode : return V8QImode ; default : break ; } } return word_mode ; } </s>

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


<s> static rtx aarch64_simd_dup_constant ( rtx vals ) { machine_mode mode = GET_MODE ( vals ) ; machine_mode inner_mode = GET_MODE_INNER ( mode ) ; rtx x ; if ( ! const_vec_duplicate_p ( vals , & x ) ) return NULL_RTX ; x = copy_to_mode_reg ( inner_mode , x ) ; return gen_vec_duplicate ( mode , x ) ; } </s>

If VALS is a vector constant that can be loaded into a register using DUP , generate instructions to do so and return an RTX to assign to the register . Otherwise return NULL_RTX .


<s> void aarch64_simd_emit_reg_reg_move ( rtx * operands , machine_mode mode , unsigned int count ) { unsigned int i ; int rdest = REGNO ( operands [ 0 ] ) ; int rsrc = REGNO ( operands [ 1 ] ) ; if ( ! reg_overlap_mentioned_p ( operands [ 0 ] , operands [ 1 ] ) || rdest < rsrc ) for ( i = 0 ; i < count ; i ++ ) emit_move_insn ( gen_rtx_REG ( mode , rdest + i ) , gen_rtx_REG ( mode , rsrc + i ) ) ; else for ( i = 0 ; i < count ; i ++ ) emit_move_insn ( gen_rtx_REG ( mode , rdest + count - i - 1 ) , gen_rtx_REG ( mode , rsrc + count - i - 1 ) ) ; } </s>

Emit a register copy from operand to operand , taking care not to early-clobber source registers in the process . COUNT is the number of components into which the copy needs to be decomposed .


<s> rtx aarch64_simd_gen_const_vector_dup ( machine_mode mode , HOST_WIDE_INT val ) { rtx c = gen_int_mode ( val , GET_MODE_INNER ( mode ) ) ; return gen_const_vec_duplicate ( mode , c ) ; } </s>


<s>
void
aarch64_simd_lane_bounds
(
rtx
operand
,
HOST_WIDE_INT
low
,
HOST_WIDE_INT
high
,
const_tree
exp
)
{
HOST_WIDE_INT
lane
;
gcc_assert
(
CONST_INT_P
(
operand
)
)
;
lane
=
INTVAL
(
operand
)
;
if
(
lane
<
low
||
lane
>=
high
)
{
if
(
exp
)
error
(
"%Klane %wd out of range %wd - %wd"
,
exp
,
lane
,
low
,
high
1
)
;
else
error
(
"lane %wd out of range %wd - %wd"
,
lane
,
low
,
high
1
)
;
}
}
</s>

Bounds-check lanes . Ensure OPERAND lies between LOW ( inclusive ) and HIGH ( exclusive ) .


<s> static rtx aarch64_simd_make_constant ( rtx vals ) { machine_mode mode = GET_MODE ( vals ) ; rtx const_dup ; rtx const_vec = NULL_RTX ; int n_const = 0 ; int i ; if ( GET_CODE ( vals ) == CONST_VECTOR ) const_vec = vals ; else if ( GET_CODE ( vals ) == PARALLEL ) { int n_elts = XVECLEN ( vals , 0 ) ; for ( i = 0 ; i < n_elts ; ++ i ) { rtx x = XVECEXP ( vals , 0 , i ) ; if ( CONST_INT_P ( x ) || CONST_DOUBLE_P ( x ) ) n_const ++ ; } if ( n_const == n_elts ) const_vec = gen_rtx_CONST_VECTOR ( mode , XVEC ( vals , 0 ) ) ; } else gcc_unreachable ( ) ; if ( const_vec != NULL_RTX && aarch64_simd_valid_immediate ( const_vec , NULL ) ) return const_vec ; else if ( ( const_dup = aarch64_simd_dup_constant ( vals ) ) != NULL_RTX ) return const_dup ; else if ( const_vec != NULL_RTX ) return const_vec ; else return NULL_RTX ; } </s>

Generate code to load VALS , which is a PARALLEL containing only constants ( for vec_init ) or CONST_VECTOR , efficiently into a register . Returns an RTX to copy into the register , or NULL_RTX for a PARALLEL that can not be converted into a CONST_VECTOR .


<s> bool aarch64_simd_mem_operand_p ( rtx op ) { return MEM_P ( op ) && ( GET_CODE ( XEXP ( op , 0 ) ) == POST_INC || REG_P ( XEXP ( op , 0 ) ) ) ; } </s>

Return TRUE if OP is a valid vector addressing mode .


Check OP is a legal scalar immediate for the MOVI instruction .


<s> bool aarch64_simd_shift_imm_p ( rtx x , machine_mode mode , bool left ) { x = unwrap_const_vec_duplicate ( x ) ; if ( ! CONST_INT_P ( x ) ) return false ; int bit_width = GET_MODE_UNIT_SIZE ( mode ) * BITS_PER_UNIT ; if ( left ) return IN_RANGE ( INTVAL ( x ) , 0 , bit_width - 1 ) ; else return IN_RANGE ( INTVAL ( x ) , 1 , bit_width ) ; } </s>

Check of immediate shift constants are within range .


<s> static HOST_WIDE_INT aarch64_simd_vector_alignment ( const_tree type ) { if ( GET_MODE_CLASS ( TYPE_MODE ( type ) ) == MODE_VECTOR_BOOL ) return 16 ; widest_int min_size = constant_lower_bound ( wi :: to_poly_widest ( TYPE_SIZE ( type ) ) ) ; return wi :: umin ( min_size , 128 ) . to_uhwi ( ) ; } </s>

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


<s> rtx aarch64_simd_vect_par_cnst_half ( machine_mode mode , int nunits , bool high ) { rtvec v = rtvec_alloc ( nunits / 2 ) ; int high_base = nunits / 2 ; int low_base = 0 ; int base ; rtx t1 ; int i ; if ( BYTES_BIG_ENDIAN ) base = high ? low_base : high_base ; else base = high ? high_base : low_base ; for ( i = 0 ; i < nunits / 2 ; i ++ ) RTVEC_ELT ( v , i ) = GEN_INT ( base + i ) ; t1 = gen_rtx_PARALLEL ( mode , v ) ; return t1 ; } </s>

Construct and return a PARALLEL RTX vector with elements numbering the lanes of either the high ( HIGH == TRUE ) or low ( HIGH == FALSE ) half of the vector - from the perspective of the architecture . This does not line up with GCC 's perspective on lane numbers , so we end up with different masks depending on our target endian-ness . The diagram below may help . We must draw the distinction when building masks which select one half of the vector . An instruction selecting architectural low-lanes for a big-endian target , must be described using a mask selecting GCC high-lanes . Big-Endian Little-EndianGCC 0 1 2 3 3 2 1 0 | x | x | x | x | | x | x | x | x |Architecture 3 2 1 0 3 2 1 0Low Mask : { 2 , 3 } { 0 , 1 } High Mask : { 0 , 1 } { 2 , 3 }


Return true if at least one possible value of type TYPE includes at least one object of Pure Scalable Type , in the sense of the AAPCS64 . This is a relatively expensive test for some types , so it should generally be made as late as possible .


<s> static rtx aarch64_speculation_safe_value ( machine_mode mode , rtx result , rtx val , rtx failval ) { if ( ! aarch64_track_speculation ) return default_speculation_safe_value ( mode , result , val , failval ) ; if ( ! REG_P ( val ) ) val = copy_to_mode_reg ( mode , val ) ; if ( ! aarch64_reg_or_zero ( failval , mode ) ) failval = copy_to_mode_reg ( mode , failval ) ; emit_insn ( gen_despeculate_copy ( mode , result , val , failval ) ) ; return result ; } </s>

Override the default target speculation_safe_value .


<s> void aarch64_split_128bit_move ( rtx dst , rtx src ) { rtx dst_lo , dst_hi ; rtx src_lo , src_hi ; machine_mode mode = GET_MODE ( dst ) ; gcc_assert ( mode == TImode || mode == TFmode ) ; gcc_assert ( ! ( side_effects_p ( src ) || side_effects_p ( dst ) ) ) ; gcc_assert ( mode == GET_MODE ( src ) || GET_MODE ( src ) == VOIDmode ) ; if ( REG_P ( dst ) && REG_P ( src ) ) { int src_regno = REGNO ( src ) ; int dst_regno = REGNO ( dst ) ; if ( FP_REGNUM_P ( dst_regno ) && GP_REGNUM_P ( src_regno ) ) { src_lo = gen_lowpart ( word_mode , src ) ; src_hi = gen_highpart ( word_mode , src ) ; emit_insn ( gen_aarch64_movlow_di ( mode , dst , src_lo ) ) ; emit_insn ( gen_aarch64_movhigh_di ( mode , dst , src_hi ) ) ; return ; } else if ( GP_REGNUM_P ( dst_regno ) && FP_REGNUM_P ( src_regno ) ) { dst_lo = gen_lowpart ( word_mode , dst ) ; dst_hi = gen_highpart ( word_mode , dst ) ; emit_insn ( gen_aarch64_movdi_low ( mode , dst_lo , src ) ) ; emit_insn ( gen_aarch64_movdi_high ( mode , dst_hi , src ) ) ; return ; } } dst_lo = gen_lowpart ( word_mode , dst ) ; dst_hi = gen_highpart ( word_mode , dst ) ; src_lo = gen_lowpart ( word_mode , src ) ; src_hi = gen_highpart_mode ( word_mode , mode , src ) ; if ( reg_overlap_mentioned_p ( dst_lo , src_hi ) ) { aarch64_emit_move ( dst_hi , src_hi ) ; aarch64_emit_move ( dst_lo , src_lo ) ; } else { aarch64_emit_move ( dst_lo , src_lo ) ; aarch64_emit_move ( dst_hi , src_hi ) ; } } </s>

Split a 128-bit move operation into two 64-bit move operations , taking care to handle partial overlap of register to register copies . Special cases are needed when moving between GP regs and FP regs . SRC can be a register , constant or memory ; DST a register or memory . If either operand is memory it must not have any side effects .


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

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


<s> void aarch64_split_add_offset ( scalar_int_mode mode , rtx dest , rtx src , rtx offset_rtx , rtx temp1 , rtx temp2 ) { aarch64_add_offset ( mode , dest , src , rtx_to_poly_int64 ( offset_rtx ) , temp1 , temp2 , false ) ; } </s>

Like aarch64_add_offset , but the offset is given as an rtx rather than a poly_int64 .


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