<s> static int ix86_builtin_vectorization_cost ( enum vect_cost_for_stmt type_of_cost , tree vectype , int ) { bool fp = false ; machine_mode mode = TImode ; int index ; if ( vectype != NULL ) { fp = FLOAT_TYPE_P ( vectype ) ; mode = TYPE_MODE ( vectype ) ; } switch ( type_of_cost ) { case scalar_stmt : return fp ? ix86_cost -> addss : COSTS_N_INSNS ( 1 ) ; case scalar_load : return COSTS_N_INSNS ( fp ? ix86_cost -> sse_load [ 0 ] : ix86_cost -> int_load [ 2 ] ) / 2 ; case scalar_store : return COSTS_N_INSNS ( fp ? ix86_cost -> sse_store [ 0 ] : ix86_cost -> int_store [ 2 ] ) / 2 ; case vector_stmt : return ix86_vec_cost ( mode , fp ? ix86_cost -> addss : ix86_cost -> sse_op ) ; case vector_load : index = sse_store_index ( mode ) ; if ( index < 0 ) index = 2 ; return COSTS_N_INSNS ( ix86_cost -> sse_load [ index ] ) / 2 ; case vector_store : index = sse_store_index ( mode ) ; if ( index < 0 ) index = 2 ; return COSTS_N_INSNS ( ix86_cost -> sse_store [ index ] ) / 2 ; case vec_to_scalar : case scalar_to_vec : return ix86_vec_cost ( mode , ix86_cost -> sse_op ) ; case unaligned_load : index = sse_store_index ( mode ) ; if ( index < 0 ) index = 2 ; return COSTS_N_INSNS ( ix86_cost -> sse_unaligned_load [ index ] ) / 2 ; case unaligned_store : index = sse_store_index ( mode ) ; if ( index < 0 ) index = 2 ; return COSTS_N_INSNS ( ix86_cost -> sse_unaligned_store [ index ] ) / 2 ; case vector_gather_load : return ix86_vec_cost ( mode , COSTS_N_INSNS ( ix86_cost -> gather_static + ix86_cost -> gather_per_elt * TYPE_VECTOR_SUBPARTS ( vectype ) ) / 2 ) ; case vector_scatter_store : return ix86_vec_cost ( mode , COSTS_N_INSNS ( ix86_cost -> scatter_static + ix86_cost -> scatter_per_elt * TYPE_VECTOR_SUBPARTS ( vectype ) ) / 2 ) ; case cond_branch_taken : return ix86_cost -> cond_taken_branch_cost ; case cond_branch_not_taken : return ix86_cost -> cond_not_taken_branch_cost ; case vec_perm : case vec_promote_demote : return ix86_vec_cost ( mode , ix86_cost -> sse_op ) ; case vec_construct : { int n = TYPE_VECTOR_SUBPARTS ( vectype ) ; if ( GET_MODE_BITSIZE ( mode ) <= 128 ) return ( n - 1 ) * ix86_cost -> sse_op ; else if ( GET_MODE_BITSIZE ( mode ) == 256 ) return ( ( n - 2 ) * ix86_cost -> sse_op + ix86_vec_cost ( mode , ix86_cost -> addss ) ) ; else if ( GET_MODE_BITSIZE ( mode ) == 512 ) return ( ( n - 4 ) * ix86_cost -> sse_op + 3 * ix86_vec_cost ( mode , ix86_cost -> addss ) ) ; gcc_unreachable ( ) ; } default : gcc_unreachable ( ) ; } } </s>


<s> void ix86_call_abi_override ( const_tree fndecl ) { cfun -> machine -> call_abi = ix86_function_abi ( fndecl ) ; } </s>

Implementation of call abi switching target hook . Specific to FNDECL the specific call register sets are set . See also ix86_conditional_register_usage for more details .


<s> bool ix86_call_use_plt_p ( rtx call_op ) { if ( SYMBOL_REF_LOCAL_P ( call_op ) ) { if ( SYMBOL_REF_DECL ( call_op ) && TREE_CODE ( SYMBOL_REF_DECL ( call_op ) ) == FUNCTION_DECL ) { cgraph_node * node = cgraph_node :: get ( SYMBOL_REF_DECL ( call_op ) ) ; if ( node && node -> ifunc_resolver ) return true ; } return false ; } return true ; } </s>

Return true if the function is called via PLT .


<s> static bool ix86_cannot_force_const_mem ( machine_mode mode , rtx x ) { switch ( GET_CODE ( x ) ) { CASE_CONST_ANY : return false ; default : break ; } return ! ix86_legitimate_constant_p ( mode , x ) ; } </s>

Determine if it 's legal to put X into the constant pool . This is not possible for the address of thread-local symbols , which is checked above .


<s> static void ix86_canonicalize_comparison ( int * code , rtx * op0 , rtx * op1 , bool op0_preserve_value ) { if ( ! op0_preserve_value && GET_CODE ( * op0 ) == FLOAT && MEM_P ( XEXP ( * op0 , 0 ) ) && REG_P ( * op1 ) ) { enum rtx_code scode = swap_condition ( ( enum rtx_code ) * code ) ; if ( ix86_fp_compare_code_to_integer ( scode ) != UNKNOWN ) { std :: swap ( * op0 , * op1 ) ; * code = ( int ) scode ; } } } </s>

Canonicalize a comparison from one we do n't have to one we do have .


<s>
static
tree
ix86_canonical_va_list_type
(
tree
type
)
{
if
(
TARGET_64BIT
)
{
if
(
lookup_attribute
(
"ms_abi va_list"
,
TYPE_ATTRIBUTES
(
type
)
)
)
return
ms_va_list_type_node
;
if
(
(
TREE_CODE
(
type
)
==
ARRAY_TYPE
&&
integer_zerop
(
array_type_nelts
(
type
)
)
)
||
POINTER_TYPE_P
(
type
)
)
{
tree
elem_type
=
TREE_TYPE
(
type
)
;
if
(
TREE_CODE
(
elem_type
)
==
RECORD_TYPE
&&
lookup_attribute
(
"sysv_abi va_list"
,
TYPE_ATTRIBUTES
(
elem_type
)
)
)
return
sysv_va_list_type_node
;
}
return
NULL_TREE
;
}
return
std_canonical_va_list_type
(
type
)
;
}
</s>

Returns the canonical va_list type specified by TYPE . If there is no valid TYPE provided , it return NULL_TREE .

i386
"ms_abi va_list"
"sysv_abi va_list"


<s> static bool ix86_can_change_mode_class ( machine_mode from , machine_mode to , reg_class_t regclass ) { if ( from == to ) return true ; if ( MAYBE_FLOAT_CLASS_P ( regclass ) ) return false ; if ( MAYBE_SSE_CLASS_P ( regclass ) || MAYBE_MMX_CLASS_P ( regclass ) ) { int mov_size = MAYBE_SSE_CLASS_P ( regclass ) && TARGET_SSE2 ? 2 : 4 ; if ( GET_MODE_SIZE ( from ) < mov_size ) return false ; } return true ; } </s>


<s> static bool ix86_can_eliminate ( const int from , const int to ) { if ( stack_realign_fp ) return ( ( from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM ) || ( from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM ) ) ; else return to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true ; } </s>

Given FROM and TO register numbers , say whether this elimination is allowed . If stack alignment is needed , we can only replace argument pointer with hard frame pointer , or replace frame pointer with stack pointer . Otherwise , frame pointer elimination is automatically handled and all other eliminations are valid .


<s> static bool ix86_can_inline_p ( tree caller , tree callee ) { tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET ( caller ) ; tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET ( callee ) ; unsigned HOST_WIDE_INT always_inline_safe_mask = ( MASK_USE_8BIT_IDIV | MASK_ACCUMULATE_OUTGOING_ARGS | MASK_NO_ALIGN_STRINGOPS | MASK_AVX256_SPLIT_UNALIGNED_LOAD | MASK_AVX256_SPLIT_UNALIGNED_STORE | MASK_CLD | MASK_NO_FANCY_MATH_387 | MASK_IEEE_FP | MASK_INLINE_ALL_STRINGOPS | MASK_INLINE_STRINGOPS_DYNAMICALLY | MASK_RECIP | MASK_STACK_PROBE | MASK_STV | MASK_TLS_DIRECT_SEG_REFS | MASK_VZEROUPPER | MASK_NO_PUSH_ARGS | MASK_OMIT_LEAF_FRAME_POINTER ) ; if ( ! callee_tree ) callee_tree = target_option_default_node ; if ( ! caller_tree ) caller_tree = target_option_default_node ; if ( callee_tree == caller_tree ) return true ; struct cl_target_option * caller_opts = TREE_TARGET_OPTION ( caller_tree ) ; struct cl_target_option * callee_opts = TREE_TARGET_OPTION ( callee_tree ) ; bool ret = false ; bool always_inline = ( DECL_DISREGARD_INLINE_LIMITS ( callee ) && lookup_attribute ( "always_inline" , DECL_ATTRIBUTES ( callee ) ) ) ; if ( TARGET_GENERAL_REGS_ONLY_P ( callee_opts -> x_ix86_target_flags ) ) always_inline_safe_mask |= MASK_80387 ; cgraph_node * callee_node = cgraph_node :: get ( callee ) ; if ( ( ( caller_opts -> x_ix86_isa_flags & callee_opts -> x_ix86_isa_flags ) != callee_opts -> x_ix86_isa_flags ) || ( ( caller_opts -> x_ix86_isa_flags2 & callee_opts -> x_ix86_isa_flags2 ) != callee_opts -> x_ix86_isa_flags2 ) ) ret = false ; else if ( ( ! always_inline && caller_opts -> x_target_flags != callee_opts -> x_target_flags ) || ( caller_opts -> x_target_flags & ~ always_inline_safe_mask ) != ( callee_opts -> x_target_flags & ~ always_inline_safe_mask ) ) ret = false ; else if ( caller_opts -> arch != callee_opts -> arch ) ret = false ; else if ( ! always_inline && caller_opts -> tune != callee_opts -> tune ) ret = false ; else if ( caller_opts -> x_ix86_fpmath != callee_opts -> x_ix86_fpmath && ( ! ipa_fn_summaries || ipa_fn_summaries -> get ( callee_node ) == NULL || ipa_fn_summaries -> get ( callee_node ) -> fp_expressions ) ) ret = false ; else if ( ! always_inline && caller_opts -> branch_cost != callee_opts -> branch_cost ) ret = false ; else ret = true ; return ret ; } </s>

Hook to determine if one function can safely inline another .


<s> bool ix86_can_use_return_insn_p ( void ) { if ( ix86_function_ms_hook_prologue ( current_function_decl ) ) return false ; if ( ix86_function_naked ( current_function_decl ) ) return false ; if ( ! reload_completed || frame_pointer_needed || cfun -> machine -> func_type != TYPE_NORMAL ) return 0 ; if ( crtl -> args . pops_args && crtl -> args . size >= 32768 ) return 0 ; struct ix86_frame & frame = cfun -> machine -> frame ; return ( frame . stack_pointer_offset == UNITS_PER_WORD && ( frame . nregs + frame . nsseregs ) == 0 ) ; } </s>

Return 1 if it is appropriate to emit ` ret ' instructions in the body of a function . Do this only if the epilogue is simple , needing a couple of insns . Prior to reloading , we ca n't tell how many registers must be saved , so return 0 then . Return 0 if there is no frame marker to de-allocate .


<s> static machine_mode ix86_cc_modes_compatible ( machine_mode m1 , machine_mode m2 ) { if ( m1 == m2 ) return m1 ; if ( GET_MODE_CLASS ( m1 ) != MODE_CC || GET_MODE_CLASS ( m2 ) != MODE_CC ) return VOIDmode ; if ( ( m1 == CCGCmode && m2 == CCGOCmode ) || ( m1 == CCGOCmode && m2 == CCGCmode ) ) return CCGCmode ; if ( ( m1 == CCNOmode && m2 == CCGOCmode ) || ( m1 == CCGOCmode && m2 == CCNOmode ) ) return CCNOmode ; if ( m1 == CCZmode && ( m2 == CCGCmode || m2 == CCGOCmode || m2 == CCNOmode ) ) return m2 ; else if ( m2 == CCZmode && ( m1 == CCGCmode || m1 == CCGOCmode || m1 == CCNOmode ) ) return m1 ; switch ( m1 ) { default : gcc_unreachable ( ) ; case E_CCmode : case E_CCGCmode : case E_CCGOCmode : case E_CCNOmode : case E_CCAmode : case E_CCCmode : case E_CCOmode : case E_CCPmode : case E_CCSmode : case E_CCZmode : switch ( m2 ) { default : return VOIDmode ; case E_CCmode : case E_CCGCmode : case E_CCGOCmode : case E_CCNOmode : case E_CCAmode : case E_CCCmode : case E_CCOmode : case E_CCPmode : case E_CCSmode : case E_CCZmode : return CCmode ; } case E_CCFPmode : return VOIDmode ; } } </s>

If two condition code modes are compatible , return a condition code mode which is compatible with both . Otherwise , return VOIDmode .


<s> enum calling_abi ix86_cfun_abi ( void ) { return cfun ? cfun -> machine -> call_abi : ix86_abi ; } </s>

Returns value SYSV_ABI , MS_ABI dependent on cfun , specifying the call abi used .


<s> static bool ix86_check_avx_upper_register ( const_rtx exp ) { return ( SSE_REG_P ( exp ) && ! EXT_REX_SSE_REG_P ( exp ) && GET_MODE_BITSIZE ( GET_MODE ( exp ) ) > 128 ) ; } </s>

Check if a 256bit or 512 bit AVX register is referenced inside of EXP .


<s> static void ix86_check_avx_upper_stores ( rtx dest , const_rtx , void * data ) { if ( ix86_check_avx_upper_register ( dest ) ) { bool * used = ( bool * ) data ; * used = true ; } } </s>

Check if a 256bit or 512bit AVX register is referenced in stores .


<s> bool ix86_check_movabs ( rtx insn , int opnum ) { rtx set , mem ; set = PATTERN ( insn ) ; if ( GET_CODE ( set ) == PARALLEL ) set = XVECEXP ( set , 0 , 0 ) ; gcc_assert ( GET_CODE ( set ) == SET ) ; mem = XEXP ( set , opnum ) ; while ( SUBREG_P ( mem ) ) mem = SUBREG_REG ( mem ) ; gcc_assert ( MEM_P ( mem ) ) ; return volatile_ok || ! MEM_VOLATILE_P ( mem ) ; } </s>

Return nonzero if OPNUM 's MEM should be matched in movabs * patterns .


<s> bool ix86_check_no_addr_space ( rtx insn ) { subrtx_var_iterator :: array_type array ; FOR_EACH_SUBRTX_VAR ( iter , array , PATTERN ( insn ) , ALL ) { rtx x = * iter ; if ( MEM_P ( x ) && ! ADDR_SPACE_GENERIC_P ( MEM_ADDR_SPACE ( x ) ) ) return false ; } return true ; } </s>

Return false if INSN contains a MEM with a non-default address space .


<s> static bool ix86_class_likely_spilled_p ( reg_class_t rclass ) { switch ( rclass ) { case AREG : case DREG : case CREG : case BREG : case AD_REGS : case SIREG : case DIREG : case SSE_FIRST_REG : case FP_TOP_REG : case FP_SECOND_REG : return true ; default : break ; } return false ; } </s>


<s> static unsigned char ix86_class_max_nregs ( reg_class_t rclass , machine_mode mode ) { if ( MAYBE_INTEGER_CLASS_P ( rclass ) ) { if ( mode == XFmode ) return ( TARGET_64BIT ? 2 : 3 ) ; else if ( mode == XCmode ) return ( TARGET_64BIT ? 4 : 6 ) ; else return CEIL ( GET_MODE_SIZE ( mode ) , UNITS_PER_WORD ) ; } else { if ( COMPLEX_MODE_P ( mode ) ) return 2 ; else return 1 ; } } </s>

Implement the TARGET_CLASS_MAX_NREGS hook . On the 80386 , this is the size of MODE in words , except in the FP regs , where a single reg is always enough .


<s> static bool ix86_compat_aligned_value_p ( const_tree type ) { machine_mode mode = TYPE_MODE ( type ) ; if ( ( ( TARGET_SSE && SSE_REG_MODE_P ( mode ) ) || mode == TDmode || mode == TFmode || mode == TCmode ) && ( ! TYPE_USER_ALIGN ( type ) || TYPE_ALIGN ( type ) > 128 ) ) return true ; if ( TYPE_ALIGN ( type ) < 128 ) return false ; if ( AGGREGATE_TYPE_P ( type ) ) { switch ( TREE_CODE ( type ) ) { case RECORD_TYPE : case UNION_TYPE : case QUAL_UNION_TYPE : { tree field ; for ( field = TYPE_FIELDS ( type ) ; field ; field = DECL_CHAIN ( field ) ) { if ( TREE_CODE ( field ) == FIELD_DECL && ix86_compat_aligned_value_p ( TREE_TYPE ( field ) ) ) return true ; } break ; } case ARRAY_TYPE : if ( ix86_compat_aligned_value_p ( TREE_TYPE ( type ) ) ) return true ; break ; default : gcc_unreachable ( ) ; } } return false ; } </s>

Return true when TYPE should be 128bit aligned for 32bit argument passing ABI . XXX : This function is obsolete and is only used for checking psABI compatibility with previous versions of GCC .


<s> static unsigned int ix86_compat_function_arg_boundary ( machine_mode mode , const_tree type , unsigned int align ) { if ( ! TARGET_64BIT && mode != TDmode && mode != TFmode ) { if ( ! type ) { if ( ! ( TARGET_SSE && SSE_REG_MODE_P ( mode ) ) ) align = PARM_BOUNDARY ; } else { if ( ! ix86_compat_aligned_value_p ( type ) ) align = PARM_BOUNDARY ; } } if ( align > BIGGEST_ALIGNMENT ) align = BIGGEST_ALIGNMENT ; return align ; } </s>

Return the alignment boundary for MODE and TYPE with alignment ALIGN . XXX : This function is obsolete and is only used for checking psABI compatibility with previous versions of GCC .


Return 0 if the attributes for two types are incompatible , 1 if they are compatible , and 2 if they are nearly compatible ( which causes a warning to be generated ) .


<s> static void ix86_conditional_register_usage ( void ) { int i , c_mask ; if ( cfun && cfun -> machine -> no_caller_saved_registers ) for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) if ( ! fixed_regs [ i ] && ! ix86_function_value_regno_p ( i ) ) call_used_regs [ i ] = 0 ; if ( ! TARGET_64BIT ) { for ( i = FIRST_REX_INT_REG ; i <= LAST_REX_INT_REG ; i ++ ) CLEAR_HARD_REG_BIT ( accessible_reg_set , i ) ; for ( i = FIRST_REX_SSE_REG ; i <= LAST_REX_SSE_REG ; i ++ ) CLEAR_HARD_REG_BIT ( accessible_reg_set , i ) ; for ( i = FIRST_EXT_REX_SSE_REG ; i <= LAST_EXT_REX_SSE_REG ; i ++ ) CLEAR_HARD_REG_BIT ( accessible_reg_set , i ) ; } c_mask = CALL_USED_REGISTERS_MASK ( TARGET_64BIT_MS_ABI ) ; CLEAR_HARD_REG_SET ( reg_class_contents [ ( int ) CLOBBERED_REGS ] ) ; for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) { if ( call_used_regs [ i ] > 1 ) call_used_regs [ i ] = ! ! ( call_used_regs [ i ] & c_mask ) ; if ( TEST_HARD_REG_BIT ( reg_class_contents [ ( int ) GENERAL_REGS ] , i ) && call_used_regs [ i ] ) SET_HARD_REG_BIT ( reg_class_contents [ ( int ) CLOBBERED_REGS ] , i ) ; } if ( ! TARGET_MMX ) accessible_reg_set &= ~ reg_class_contents [ MMX_REGS ] ; if ( ! TARGET_SSE ) accessible_reg_set &= ~ reg_class_contents [ ALL_SSE_REGS ] ; if ( ! ( TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 ) ) accessible_reg_set &= ~ reg_class_contents [ FLOAT_REGS ] ; if ( ! TARGET_AVX512F ) { for ( i = FIRST_EXT_REX_SSE_REG ; i <= LAST_EXT_REX_SSE_REG ; i ++ ) CLEAR_HARD_REG_BIT ( accessible_reg_set , i ) ; accessible_reg_set &= ~ reg_class_contents [ ALL_MASK_REGS ] ; } } </s>

Update register usage after having seen the compiler flags .


<s> static HOST_WIDE_INT ix86_constant_alignment ( const_tree exp , HOST_WIDE_INT align ) { if ( TREE_CODE ( exp ) == REAL_CST || TREE_CODE ( exp ) == VECTOR_CST || TREE_CODE ( exp ) == INTEGER_CST ) { machine_mode mode = TYPE_MODE ( TREE_TYPE ( exp ) ) ; HOST_WIDE_INT mode_align = ix86_static_rtx_alignment ( mode ) ; return MAX ( mode_align , align ) ; } else if ( ! optimize_size && TREE_CODE ( exp ) == STRING_CST && TREE_STRING_LENGTH ( exp ) >= 31 && align < BITS_PER_WORD ) return BITS_PER_WORD ; return align ; } </s>

Compute the alignment given to a constant that is being placed in memory . EXP is the constant and ALIGN is the alignment that the object would ordinarily have . The value of this function is used instead of that alignment to align the object .


<s> static bool ix86_const_not_ok_for_debug_p ( rtx x ) { if ( GET_CODE ( x ) == UNSPEC && XINT ( x , 1 ) != UNSPEC_GOTOFF ) return true ; if ( SYMBOL_REF_P ( x ) && strcmp ( XSTR ( x , 0 ) , GOT_SYMBOL_NAME ) == 0 ) return true ; return false ; } </s>

Return true if X should n't be emitted into the debug info . Disallow UNSPECs other than @ gotoff - we ca n't emit _GLOBAL_OFFSET_TABLE_ symbol easily into the .debug_info section , so we need not to delegitimize , but instead assemble as @ gotoff . Disallow _GLOBAL_OFFSET_TABLE_ SYMBOL_REF - the assembler magically assembles that as _GLOBAL_OFFSET_TABLE_- . expression .


<s> static bool ix86_contains_aligned_value_p ( const_tree type ) { machine_mode mode = TYPE_MODE ( type ) ; if ( mode == XFmode || mode == XCmode ) return false ; if ( TYPE_ALIGN ( type ) < 128 ) return false ; if ( AGGREGATE_TYPE_P ( type ) ) { switch ( TREE_CODE ( type ) ) { case RECORD_TYPE : case UNION_TYPE : case QUAL_UNION_TYPE : { tree field ; for ( field = TYPE_FIELDS ( type ) ; field ; field = DECL_CHAIN ( field ) ) { if ( TREE_CODE ( field ) == FIELD_DECL && ix86_contains_aligned_value_p ( TREE_TYPE ( field ) ) ) return true ; } break ; } case ARRAY_TYPE : if ( ix86_contains_aligned_value_p ( TREE_TYPE ( type ) ) ) return true ; break ; default : gcc_unreachable ( ) ; } } else return TYPE_ALIGN ( type ) >= 128 ; return false ; } </s>

Return true when TYPE should be 128bit aligned for 32bit argument passing ABI .


<s> static int ix86_count_insn ( basic_block bb ) { edge e ; edge_iterator ei ; int min_prev_count ; min_prev_count = 4 ; FOR_EACH_EDGE ( e , ei , bb -> preds ) { edge prev_e ; edge_iterator prev_ei ; if ( e -> src == ENTRY_BLOCK_PTR_FOR_FN ( cfun ) ) { min_prev_count = 0 ; break ; } FOR_EACH_EDGE ( prev_e , prev_ei , e -> src -> preds ) { if ( prev_e -> src == ENTRY_BLOCK_PTR_FOR_FN ( cfun ) ) { int count = ix86_count_insn_bb ( e -> src ) ; if ( count < min_prev_count ) min_prev_count = count ; break ; } } } if ( min_prev_count < 4 ) min_prev_count += ix86_count_insn_bb ( bb ) ; return min_prev_count ; } </s>

Count the minimum number of instructions in code path in BB . Return 4 if the number of instructions > = 4 .


<s> static int ix86_count_insn_bb ( basic_block bb ) { rtx_insn * insn ; int insn_count = 0 ; FOR_BB_INSNS ( bb , insn ) { if ( JUMP_P ( insn ) && ANY_RETURN_P ( PATTERN ( insn ) ) ) break ; if ( NONDEBUG_INSN_P ( insn ) && GET_CODE ( PATTERN ( insn ) ) != USE && GET_CODE ( PATTERN ( insn ) ) != CLOBBER ) { insn_count ++ ; if ( insn_count >= 4 ) return insn_count ; } } return insn_count ; } </s>

Count the minimum number of instructions in BB . Return 4 if the number of instructions > = 4 .


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


<s> int ix86_data_alignment ( tree type , unsigned int align , bool opt ) { unsigned int max_align_compat = MIN ( 256 , MAX_OFILE_ALIGNMENT ) ; unsigned int max_align = MIN ( ( unsigned ) ix86_tune_cost -> prefetch_block * 8 , MAX_OFILE_ALIGNMENT ) ; if ( max_align < BITS_PER_WORD ) max_align = BITS_PER_WORD ; switch ( ix86_align_data_type ) { case ix86_align_data_type_abi : opt = false ; break ; case ix86_align_data_type_compat : max_align = BITS_PER_WORD ; break ; case ix86_align_data_type_cacheline : break ; } if ( TARGET_IAMCU ) align = iamcu_alignment ( type , align ) ; if ( opt && AGGREGATE_TYPE_P ( type ) && TYPE_SIZE ( type ) && TREE_CODE ( TYPE_SIZE ( type ) ) == INTEGER_CST ) { if ( wi :: geu_p ( wi :: to_wide ( TYPE_SIZE ( type ) ) , max_align_compat ) && align < max_align_compat ) align = max_align_compat ; if ( wi :: geu_p ( wi :: to_wide ( TYPE_SIZE ( type ) ) , max_align ) && align < max_align ) align = max_align ; } if ( TARGET_64BIT ) { if ( ( opt ? AGGREGATE_TYPE_P ( type ) : TREE_CODE ( type ) == ARRAY_TYPE ) && TYPE_SIZE ( type ) && TREE_CODE ( TYPE_SIZE ( type ) ) == INTEGER_CST && wi :: geu_p ( wi :: to_wide ( TYPE_SIZE ( type ) ) , 128 ) && align < 128 ) return 128 ; } if ( ! opt ) return align ; if ( TREE_CODE ( type ) == ARRAY_TYPE ) { if ( TYPE_MODE ( TREE_TYPE ( type ) ) == DFmode && align < 64 ) return 64 ; if ( ALIGN_MODE_128 ( TYPE_MODE ( TREE_TYPE ( type ) ) ) && align < 128 ) return 128 ; } else if ( TREE_CODE ( type ) == COMPLEX_TYPE ) { if ( TYPE_MODE ( type ) == DCmode && align < 64 ) return 64 ; if ( ( TYPE_MODE ( type ) == XCmode || TYPE_MODE ( type ) == TCmode ) && align < 128 ) return 128 ; } else if ( ( TREE_CODE ( type ) == RECORD_TYPE || TREE_CODE ( type ) == UNION_TYPE || TREE_CODE ( type ) == QUAL_UNION_TYPE ) && TYPE_FIELDS ( type ) ) { if ( DECL_MODE ( TYPE_FIELDS ( type ) ) == DFmode && align < 64 ) return 64 ; if ( ALIGN_MODE_128 ( DECL_MODE ( TYPE_FIELDS ( type ) ) ) && align < 128 ) return 128 ; } else if ( TREE_CODE ( type ) == REAL_TYPE || TREE_CODE ( type ) == VECTOR_TYPE || TREE_CODE ( type ) == INTEGER_TYPE ) { if ( TYPE_MODE ( type ) == DFmode && align < 64 ) return 64 ; if ( ALIGN_MODE_128 ( TYPE_MODE ( type ) ) && align < 128 ) return 128 ; } return align ; } </s>

Compute the alignment for a static variable . TYPE is the data type , and ALIGN is the alignment that the object would ordinarily have . The value of this function is used instead of that alignment to align the object .


<s> static rtx ix86_delegitimize_address ( rtx x ) { return ix86_delegitimize_address_1 ( x , false ) ; } </s>

In the name of slightly smaller debug output , and to cater to general assembler lossage , recognize PIC+GOTOFF and turn it back into a direct symbol reference . On Darwin , this is necessary to avoid a crash , because Darwin has a different PIC label for each routine but the DWARF debugging information is not associated with any particular routine , so it 's necessary to remove references to the PIC label from RTL stored by the DWARF output code .


<s> static rtx ix86_delegitimize_tls_address ( rtx orig_x ) { rtx x = orig_x , unspec ; struct ix86_address addr ; if ( ! TARGET_TLS_DIRECT_SEG_REFS ) return orig_x ; if ( MEM_P ( x ) ) x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) != PLUS || GET_MODE ( x ) != Pmode ) return orig_x ; if ( ix86_decompose_address ( x , & addr ) == 0 || addr . seg != DEFAULT_TLS_SEG_REG || addr . disp == NULL_RTX || GET_CODE ( addr . disp ) != CONST ) return orig_x ; unspec = XEXP ( addr . disp , 0 ) ; if ( GET_CODE ( unspec ) == PLUS && CONST_INT_P ( XEXP ( unspec , 1 ) ) ) unspec = XEXP ( unspec , 0 ) ; if ( GET_CODE ( unspec ) != UNSPEC || XINT ( unspec , 1 ) != UNSPEC_NTPOFF ) return orig_x ; x = XVECEXP ( unspec , 0 , 0 ) ; gcc_assert ( GET_CODE ( x ) == SYMBOL_REF ) ; if ( unspec != XEXP ( addr . disp , 0 ) ) x = gen_rtx_PLUS ( Pmode , x , XEXP ( XEXP ( addr . disp , 0 ) , 1 ) ) ; if ( addr . index ) { rtx idx = addr . index ; if ( addr . scale != 1 ) idx = gen_rtx_MULT ( Pmode , idx , GEN_INT ( addr . scale ) ) ; x = gen_rtx_PLUS ( Pmode , idx , x ) ; } if ( addr . base ) x = gen_rtx_PLUS ( Pmode , addr . base , x ) ; if ( MEM_P ( orig_x ) ) x = replace_equiv_address_nv ( orig_x , x ) ; return x ; } </s>

Helper function for ix86_delegitimize_address . Attempt to delegitimize TLS local-exec accesses .


<s> static void ix86_dependencies_evaluation_hook ( rtx_insn * head , rtx_insn * tail ) { rtx_insn * insn ; rtx_insn * first_arg = NULL ; if ( reload_completed ) return ; while ( head != tail && DEBUG_INSN_P ( head ) ) head = NEXT_INSN ( head ) ; for ( insn = tail ; insn != head ; insn = PREV_INSN ( insn ) ) if ( INSN_P ( insn ) && CALL_P ( insn ) ) { first_arg = add_parameter_dependencies ( insn , head ) ; if ( first_arg ) { basic_block bb = BLOCK_FOR_INSN ( insn ) ; int rgn = CONTAINING_RGN ( bb -> index ) ; int nr_blks = RGN_NR_BLOCKS ( rgn ) ; if ( nr_blks > 1 && BLOCK_TO_BB ( bb -> index ) != 0 ) { edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , bb -> preds ) { if ( rgn == CONTAINING_RGN ( e -> src -> index ) && BLOCK_TO_BB ( bb -> index ) > BLOCK_TO_BB ( e -> src -> index ) ) add_dependee_for_func_arg ( first_arg , e -> src ) ; } } insn = first_arg ; if ( insn == head ) break ; } } else if ( first_arg ) avoid_func_arg_motion ( first_arg , insn ) ; } </s>

Hook for pre-reload schedule - avoid motion of function arguments passed in likely spilled HW registers .


<s> bool ix86_dep_by_shift_count ( const_rtx set_insn , const_rtx use_insn ) { return ix86_dep_by_shift_count_body ( PATTERN ( set_insn ) , PATTERN ( use_insn ) ) ; } </s>

Return true if destination reg of SET_INSN is shift count of USE_INSN .


<s> static bool ix86_dep_by_shift_count_body ( const_rtx set_body , const_rtx use_body ) { rtx set_dest ; rtx shift_rtx ; int i ; switch ( GET_CODE ( set_body ) ) { case SET : set_dest = SET_DEST ( set_body ) ; if ( ! set_dest || ! REG_P ( set_dest ) ) return false ; break ; case PARALLEL : for ( i = XVECLEN ( set_body , 0 ) - 1 ; i >= 0 ; i -- ) if ( ix86_dep_by_shift_count_body ( XVECEXP ( set_body , 0 , i ) , use_body ) ) return true ; default : return false ; } switch ( GET_CODE ( use_body ) ) { case SET : shift_rtx = XEXP ( use_body , 1 ) ; break ; case PARALLEL : for ( i = XVECLEN ( use_body , 0 ) - 1 ; i >= 0 ; i -- ) if ( ix86_dep_by_shift_count_body ( set_body , XVECEXP ( use_body , 0 , i ) ) ) return true ; default : return false ; } if ( shift_rtx && ( GET_CODE ( shift_rtx ) == ASHIFT || GET_CODE ( shift_rtx ) == LSHIFTRT || GET_CODE ( shift_rtx ) == ASHIFTRT || GET_CODE ( shift_rtx ) == ROTATE || GET_CODE ( shift_rtx ) == ROTATERT ) ) { rtx shift_count = XEXP ( shift_rtx , 1 ) ; if ( REG_P ( shift_count ) ) { if ( reload_completed && true_regnum ( set_dest ) == true_regnum ( shift_count ) ) return true ; else if ( REGNO ( set_dest ) == REGNO ( shift_count ) ) return true ; } } return false ; } </s>

Return true if destination reg of SET_BODY is shift count of USE_BODY .


<s> static void ix86_destroy_cost_data ( void * data ) { free ( data ) ; } </s>


<s> static int ix86_dirflag_mode_needed ( rtx_insn * insn ) { if ( CALL_P ( insn ) ) { if ( cfun -> machine -> func_type == TYPE_NORMAL ) return X86_DIRFLAG_ANY ; else return TARGET_CLD ? X86_DIRFLAG_ANY : X86_DIRFLAG_RESET ; } if ( recog_memoized ( insn ) < 0 ) return X86_DIRFLAG_ANY ; if ( get_attr_type ( insn ) == TYPE_STR ) { if ( cfun -> machine -> func_type == TYPE_NORMAL ) return TARGET_CLD ? X86_DIRFLAG_RESET : X86_DIRFLAG_ANY ; else return X86_DIRFLAG_RESET ; } return X86_DIRFLAG_ANY ; } </s>

Return needed mode for entity in optimize_mode_switching pass .


<s> static int ix86_division_cost ( const struct processor_costs * cost , enum machine_mode mode ) { machine_mode inner_mode = mode ; if ( VECTOR_MODE_P ( mode ) ) inner_mode = GET_MODE_INNER ( mode ) ; if ( SSE_FLOAT_MODE_SSEMATH_OR_HF_P ( mode ) ) return inner_mode == DFmode ? cost -> divsd : cost -> divss ; else if ( X87_FLOAT_MODE_P ( mode ) ) return cost -> fdiv ; else if ( FLOAT_MODE_P ( mode ) ) return ix86_vec_cost ( mode , inner_mode == DFmode ? cost -> divsd : cost -> divss ) ; else return cost -> divide [ MODE_INDEX ( mode ) ] ; } </s>


<s> static bool ix86_eax_live_at_start_p ( void ) { return REGNO_REG_SET_P ( df_get_live_out ( ENTRY_BLOCK_PTR_FOR_FN ( cfun ) ) , 0 ) ; } </s>

Return true if EAX is live at the start of the function . Used by ix86_expand_prologue to determine if we need special help before calling allocate_stack_worker .


<s> static void ix86_elim_entry_set_got ( rtx reg ) { basic_block bb = ENTRY_BLOCK_PTR_FOR_FN ( cfun ) -> next_bb ; rtx_insn * c_insn = BB_HEAD ( bb ) ; if ( ! NONDEBUG_INSN_P ( c_insn ) ) c_insn = next_nonnote_nondebug_insn ( c_insn ) ; if ( c_insn && NONJUMP_INSN_P ( c_insn ) ) { rtx pat = PATTERN ( c_insn ) ; if ( GET_CODE ( pat ) == PARALLEL ) { rtx vec = XVECEXP ( pat , 0 , 0 ) ; if ( GET_CODE ( vec ) == SET && XINT ( XEXP ( vec , 1 ) , 1 ) == UNSPEC_SET_GOT && REGNO ( XEXP ( vec , 0 ) ) == REGNO ( reg ) ) delete_insn ( c_insn ) ; } } } </s>

Delete SET_GOT right after entry block if it is allocated to reg .


<s> static void ix86_emit_leave ( rtx_insn * insn ) { struct machine_function * m = cfun -> machine ; if ( ! insn ) insn = emit_insn ( gen_leave ( word_mode ) ) ; ix86_add_queued_cfa_restore_notes ( insn ) ; gcc_assert ( m -> fs . fp_valid ) ; m -> fs . sp_valid = true ; m -> fs . sp_realigned = false ; m -> fs . sp_offset = m -> fs . fp_offset - UNITS_PER_WORD ; m -> fs . fp_valid = false ; if ( m -> fs . cfa_reg == hard_frame_pointer_rtx ) { m -> fs . cfa_reg = stack_pointer_rtx ; m -> fs . cfa_offset = m -> fs . sp_offset ; add_reg_note ( insn , REG_CFA_DEF_CFA , plus_constant ( Pmode , stack_pointer_rtx , m -> fs . sp_offset ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } ix86_add_cfa_restore_note ( insn , hard_frame_pointer_rtx , m -> fs . fp_offset ) ; } </s>

Emit code and notes for the LEAVE instruction .


<s> static void ix86_emit_mode_set ( int entity , int mode , int prev_mode ATTRIBUTE_UNUSED , HARD_REG_SET regs_live ATTRIBUTE_UNUSED ) { switch ( entity ) { case X86_DIRFLAG : if ( mode == X86_DIRFLAG_RESET ) emit_insn ( gen_cld ( ) ) ; break ; case AVX_U128 : if ( mode == AVX_U128_CLEAN ) ix86_expand_avx_vzeroupper ( ) ; break ; case I387_ROUNDEVEN : case I387_TRUNC : case I387_FLOOR : case I387_CEIL : if ( mode != I387_CW_ANY && mode != I387_CW_UNINITIALIZED ) emit_i387_cw_initialization ( mode ) ; break ; default : gcc_unreachable ( ) ; } } </s>

Generate one or more insns to set ENTITY to MODE . HARD_REG_LIVE is the set of hard registers live at the point where the insn ( s ) are to be inserted .


<s> static void ix86_emit_probe_stack_range ( HOST_WIDE_INT first , HOST_WIDE_INT size , const bool int_registers_saved ) { const HOST_WIDE_INT probe_interval = get_probe_interval ( ) ; if ( size <= 6 * probe_interval ) { HOST_WIDE_INT i ; for ( i = probe_interval ; i < size ; i += probe_interval ) emit_stack_probe ( plus_constant ( Pmode , stack_pointer_rtx , - ( first + i ) ) ) ; emit_stack_probe ( plus_constant ( Pmode , stack_pointer_rtx , - ( first + size ) ) ) ; } else { gcc_assert ( int_registers_saved ) ; HOST_WIDE_INT rounded_size , last ; struct scratch_reg sr ; get_scratch_register_on_entry ( & sr ) ; rounded_size = ROUND_DOWN ( size , probe_interval ) ; emit_move_insn ( sr . reg , GEN_INT ( - first ) ) ; last = first + rounded_size ; emit_insn ( gen_probe_stack_range ( Pmode , sr . reg , sr . reg , GEN_INT ( - last ) ) ) ; if ( size != rounded_size ) emit_stack_probe ( plus_constant ( Pmode , gen_rtx_PLUS ( Pmode , stack_pointer_rtx , sr . reg ) , rounded_size - size ) ) ; release_scratch_register_on_entry ( & sr , size , true ) ; } emit_insn ( gen_blockage ( ) ) ; } </s>

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


<s> static void ix86_emit_restore_regs_using_mov ( HOST_WIDE_INT cfa_offset , bool maybe_eh_return ) { struct machine_function * m = cfun -> machine ; unsigned int regno ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( GENERAL_REGNO_P ( regno ) && ix86_save_reg ( regno , maybe_eh_return , true ) ) { rtx reg = gen_rtx_REG ( word_mode , regno ) ; rtx mem ; rtx_insn * insn ; mem = choose_baseaddr ( cfa_offset , NULL ) ; mem = gen_frame_mem ( word_mode , mem ) ; insn = emit_move_insn ( reg , mem ) ; if ( m -> fs . cfa_reg == crtl -> drap_reg && regno == REGNO ( crtl -> drap_reg ) ) { add_reg_note ( insn , REG_CFA_DEF_CFA , reg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; m -> fs . drap_valid = true ; } else ix86_add_cfa_restore_note ( NULL , reg , cfa_offset ) ; cfa_offset -= UNITS_PER_WORD ; } } </s>

Emit code to restore saved registers using MOV insns . First register is restored from POINTER + OFFSET .


<s> static void ix86_emit_restore_regs_using_pop ( void ) { unsigned int regno ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( GENERAL_REGNO_P ( regno ) && ix86_save_reg ( regno , false , true ) ) ix86_emit_restore_reg_using_pop ( gen_rtx_REG ( word_mode , regno ) ) ; } </s>

Emit code to restore saved registers using POP insns .


<s> static void ix86_emit_restore_reg_using_pop ( rtx reg ) { struct machine_function * m = cfun -> machine ; rtx_insn * insn = emit_insn ( gen_pop ( reg ) ) ; ix86_add_cfa_restore_note ( insn , reg , m -> fs . sp_offset ) ; m -> fs . sp_offset -= UNITS_PER_WORD ; if ( m -> fs . cfa_reg == crtl -> drap_reg && REGNO ( reg ) == REGNO ( crtl -> drap_reg ) ) { add_reg_note ( insn , REG_CFA_DEF_CFA , reg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; m -> fs . drap_valid = true ; return ; } if ( m -> fs . cfa_reg == stack_pointer_rtx ) { rtx x = plus_constant ( Pmode , stack_pointer_rtx , UNITS_PER_WORD ) ; x = gen_rtx_SET ( stack_pointer_rtx , x ) ; add_reg_note ( insn , REG_CFA_ADJUST_CFA , x ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; m -> fs . cfa_offset -= UNITS_PER_WORD ; } if ( reg == hard_frame_pointer_rtx ) { m -> fs . fp_valid = false ; if ( m -> fs . cfa_reg == hard_frame_pointer_rtx ) { m -> fs . cfa_reg = stack_pointer_rtx ; m -> fs . cfa_offset -= UNITS_PER_WORD ; add_reg_note ( insn , REG_CFA_DEF_CFA , plus_constant ( Pmode , stack_pointer_rtx , m -> fs . cfa_offset ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } } } </s>

Emit code to restore REG using a POP insn .


<s> static void ix86_emit_restore_sse_regs_using_mov ( HOST_WIDE_INT cfa_offset , bool maybe_eh_return ) { unsigned int regno ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( SSE_REGNO_P ( regno ) && ix86_save_reg ( regno , maybe_eh_return , true ) ) { rtx reg = gen_rtx_REG ( V4SFmode , regno ) ; rtx mem ; unsigned int align = GET_MODE_ALIGNMENT ( V4SFmode ) ; mem = choose_baseaddr ( cfa_offset , & align ) ; mem = gen_rtx_MEM ( V4SFmode , mem ) ; align = MIN ( GET_MODE_ALIGNMENT ( V4SFmode ) , align ) ; gcc_assert ( ! ( cfa_offset & ( align / BITS_PER_UNIT - 1 ) ) ) ; set_mem_align ( mem , align ) ; emit_insn ( gen_rtx_SET ( reg , mem ) ) ; ix86_add_cfa_restore_note ( NULL , reg , cfa_offset ) ; cfa_offset -= GET_MODE_SIZE ( V4SFmode ) ; } } </s>

Emit code to restore saved registers using MOV insns . First register is restored from CFA - CFA_OFFSET .


<s> static void ix86_emit_save_regs ( void ) { unsigned int regno ; rtx_insn * insn ; for ( regno = FIRST_PSEUDO_REGISTER - 1 ; regno -- > 0 ; ) if ( GENERAL_REGNO_P ( regno ) && ix86_save_reg ( regno , true , true ) ) { insn = emit_insn ( gen_push ( gen_rtx_REG ( word_mode , regno ) ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } } </s>

Emit code to save registers in the prologue .


<s> static void ix86_emit_save_regs_using_mov ( HOST_WIDE_INT cfa_offset ) { unsigned int regno ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( GENERAL_REGNO_P ( regno ) && ix86_save_reg ( regno , true , true ) ) { ix86_emit_save_reg_using_mov ( word_mode , regno , cfa_offset ) ; cfa_offset -= UNITS_PER_WORD ; } } </s>

Emit code to save registers using MOV insns . First register is restored from POINTER + OFFSET .


<s> static void ix86_emit_save_reg_using_mov ( machine_mode mode , unsigned int regno , HOST_WIDE_INT cfa_offset ) { struct machine_function * m = cfun -> machine ; rtx reg = gen_rtx_REG ( mode , regno ) ; rtx mem , addr , base , insn ; unsigned int align = GET_MODE_ALIGNMENT ( mode ) ; addr = choose_baseaddr ( cfa_offset , & align ) ; mem = gen_frame_mem ( mode , addr ) ; align = MIN ( GET_MODE_ALIGNMENT ( mode ) , align ) ; gcc_assert ( ! ( cfa_offset & ( align / BITS_PER_UNIT - 1 ) ) ) ; set_mem_align ( mem , align ) ; insn = emit_insn ( gen_rtx_SET ( mem , reg ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; base = addr ; if ( GET_CODE ( base ) == PLUS ) base = XEXP ( base , 0 ) ; gcc_checking_assert ( REG_P ( base ) ) ; if ( m -> fs . realigned ) { gcc_checking_assert ( stack_realign_drap ) ; if ( regno == REGNO ( crtl -> drap_reg ) ) { gcc_checking_assert ( cfun -> machine -> fs . fp_valid ) ; addr = plus_constant ( Pmode , hard_frame_pointer_rtx , cfun -> machine -> fs . fp_offset - cfa_offset ) ; mem = gen_rtx_MEM ( mode , addr ) ; add_reg_note ( insn , REG_CFA_DEF_CFA , mem ) ; } else { gcc_checking_assert ( cfun -> machine -> fs . fp_valid ) ; addr = plus_constant ( Pmode , hard_frame_pointer_rtx , cfun -> machine -> fs . fp_offset - cfa_offset ) ; mem = gen_rtx_MEM ( mode , addr ) ; add_reg_note ( insn , REG_CFA_EXPRESSION , gen_rtx_SET ( mem , reg ) ) ; } } else if ( base == stack_pointer_rtx && m -> fs . sp_realigned && cfa_offset >= m -> fs . sp_realigned_offset ) { gcc_checking_assert ( stack_realign_fp ) ; add_reg_note ( insn , REG_CFA_EXPRESSION , gen_rtx_SET ( mem , reg ) ) ; } else if ( base != m -> fs . cfa_reg ) { addr = plus_constant ( Pmode , m -> fs . cfa_reg , m -> fs . cfa_offset - cfa_offset ) ; mem = gen_rtx_MEM ( mode , addr ) ; add_reg_note ( insn , REG_CFA_OFFSET , gen_rtx_SET ( mem , reg ) ) ; } } </s>

Emit a single register save at CFA - CFA_OFFSET .


<s> static void ix86_emit_save_sse_regs_using_mov ( HOST_WIDE_INT cfa_offset ) { unsigned int regno ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( SSE_REGNO_P ( regno ) && ix86_save_reg ( regno , true , true ) ) { ix86_emit_save_reg_using_mov ( V4SFmode , regno , cfa_offset ) ; cfa_offset -= GET_MODE_SIZE ( V4SFmode ) ; } } </s>

Emit code to save SSE registers using MOV insns . First register is stored at CFA - CFA_OFFSET .


<s> static void ATTRIBUTE_UNUSED ix86_encode_section_info ( tree decl , rtx rtl , int first ) { default_encode_section_info ( decl , rtl , first ) ; if ( ix86_in_large_data_p ( decl ) ) SYMBOL_REF_FLAGS ( XEXP ( rtl , 0 ) ) |= SYMBOL_FLAG_FAR_ADDR ; } </s>

Implements target vector targetm.asm.encode_section_info .


<s> static int ix86_enum_va_list ( int idx , const char * * pname , tree * ptree ) { if ( TARGET_64BIT ) { switch ( idx ) { default : break ; case 0 : * ptree = ms_va_list_type_node ; * pname = "__builtin_ms_va_list" ; return 1 ; case 1 : * ptree = sysv_va_list_type_node ; * pname = "__builtin_sysv_va_list" ; return 1 ; } } return 0 ; } </s>

Iterate through the target-specific builtin types for va_list . IDX denotes the iterator , * PTREE is set to the result type of the va_list builtin , and * PNAME to its internal type . Returns zero if there is no element for this index , otherwise IDX should be increased upon the next call . Note , do not iterate a base builtin 's name like __builtin_va_list . Used from c_common_nodes_and_builtins .


<s> bool ix86_epilogue_uses ( int regno ) { return ( epilogue_completed && cfun -> machine -> no_caller_saved_registers && ! fixed_regs [ regno ] && ! STACK_REGNO_P ( regno ) && ! MMX_REGNO_P ( regno ) ) ; } </s>

Return true if REGNO is used by the epilogue .


<s> static enum flt_eval_method ix86_excess_precision ( enum excess_precision_type type ) { switch ( type ) { case EXCESS_PRECISION_TYPE_FAST : return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT ; case EXCESS_PRECISION_TYPE_STANDARD : case EXCESS_PRECISION_TYPE_IMPLICIT : if ( ! TARGET_80387 ) return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT ; else if ( ! TARGET_MIX_SSE_I387 ) { if ( ! ( TARGET_SSE && TARGET_SSE_MATH ) ) return FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE ; else if ( TARGET_SSE2 ) return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT ; } return ( type == EXCESS_PRECISION_TYPE_STANDARD ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT : FLT_EVAL_METHOD_UNPREDICTABLE ) ; default : gcc_unreachable ( ) ; } return FLT_EVAL_METHOD_UNPREDICTABLE ; } </s>

Set the value of FLT_EVAL_METHOD in float.h . When using only the FPU , assume that the fpcw is set to extended precision ; when using only SSE , rounding is correct ; when using both SSE and the FPU , the rounding precision is indeterminate , since either may be chosen apparently at random .


<s> rtx ix86_find_base_term ( rtx x ) { rtx term ; if ( TARGET_64BIT ) { if ( GET_CODE ( x ) != CONST ) return x ; term = XEXP ( x , 0 ) ; if ( GET_CODE ( term ) == PLUS && CONST_INT_P ( XEXP ( term , 1 ) ) ) term = XEXP ( term , 0 ) ; if ( GET_CODE ( term ) != UNSPEC || ( XINT ( term , 1 ) != UNSPEC_GOTPCREL && XINT ( term , 1 ) != UNSPEC_PCREL ) ) return x ; return XVECEXP ( term , 0 , 0 ) ; } return ix86_delegitimize_address_1 ( x , true ) ; } </s>

If X is a machine specific address ( i.e . a symbol or label being referenced as a displacement from the GOT implemented using an UNSPEC ) , then return the base term . Otherwise return X .


<s> static void ix86_find_max_used_stack_alignment ( unsigned int & stack_alignment , bool check_stack_slot ) { HARD_REG_SET set_up_by_prologue , prologue_used ; basic_block bb ; CLEAR_HARD_REG_SET ( prologue_used ) ; CLEAR_HARD_REG_SET ( set_up_by_prologue ) ; add_to_hard_reg_set ( & set_up_by_prologue , Pmode , STACK_POINTER_REGNUM ) ; add_to_hard_reg_set ( & set_up_by_prologue , Pmode , ARG_POINTER_REGNUM ) ; add_to_hard_reg_set ( & set_up_by_prologue , Pmode , HARD_FRAME_POINTER_REGNUM ) ; if ( stack_alignment > crtl -> preferred_stack_boundary ) stack_alignment = crtl -> preferred_stack_boundary ; bool require_stack_frame = false ; FOR_EACH_BB_FN ( bb , cfun ) { rtx_insn * insn ; FOR_BB_INSNS ( bb , insn ) if ( NONDEBUG_INSN_P ( insn ) && requires_stack_frame_p ( insn , prologue_used , set_up_by_prologue ) ) { require_stack_frame = true ; if ( check_stack_slot ) { subrtx_iterator :: array_type array ; FOR_EACH_SUBRTX ( iter , array , PATTERN ( insn ) , ALL ) if ( MEM_P ( * iter ) && ( reg_mentioned_p ( stack_pointer_rtx , * iter ) || reg_mentioned_p ( frame_pointer_rtx , * iter ) ) ) { unsigned int alignment = MEM_ALIGN ( * iter ) ; if ( alignment > stack_alignment ) stack_alignment = alignment ; } } } } cfun -> machine -> stack_frame_required = require_stack_frame ; } </s>

Return true if stack frame is required . Update STACK_ALIGNMENT to the largest alignment , in bits , of stack slot used if stack frame is required and CHECK_STACK_SLOT is true .


<s> static void ix86_finish_cost ( void * data , unsigned * prologue_cost , unsigned * body_cost , unsigned * epilogue_cost ) { unsigned * cost = ( unsigned * ) data ; * prologue_cost = cost [ vect_prologue ] ; * body_cost = cost [ vect_body ] ; * epilogue_cost = cost [ vect_epilogue ] ; } </s>


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

Return the fixed registers used for condition codes .


<s> static tree ix86_fn_abi_va_list ( tree fndecl ) { if ( ! TARGET_64BIT ) return va_list_type_node ; gcc_assert ( fndecl != NULL_TREE ) ; if ( ix86_function_abi ( ( const_tree ) fndecl ) == MS_ABI ) return ms_va_list_type_node ; else return sysv_va_list_type_node ; } </s>

This function returns the calling abi specific va_list type node . It returns the FNDECL specific va_list type .


<s> bool ix86_force_load_from_GOT_p ( rtx x , bool call_p ) { return ( ( TARGET_64BIT || ( ! flag_pic && HAVE_AS_IX86_GOT32X ) ) && ! TARGET_PECOFF && ! TARGET_MACHO && ( ! flag_pic || this_is_asm_operands ) && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC && GET_CODE ( x ) == SYMBOL_REF && ( ( ! call_p && ( ! ix86_direct_extern_access || ( SYMBOL_REF_DECL ( x ) && lookup_attribute ( "nodirect_extern_access" , DECL_ATTRIBUTES ( SYMBOL_REF_DECL ( x ) ) ) ) ) ) || ( SYMBOL_REF_FUNCTION_P ( x ) && ( ! flag_plt || ( SYMBOL_REF_DECL ( x ) && lookup_attribute ( "noplt" , DECL_ATTRIBUTES ( SYMBOL_REF_DECL ( x ) ) ) ) ) ) ) && ! SYMBOL_REF_LOCAL_P ( x ) ) ; } </s>

True if the function symbol operand X should be loaded from GOT . NB : In 32-bit mode , only non-PIC is allowed in inline assembly statements , since a PIC register could not be available at the call site .


<s> enum rtx_code ix86_fp_compare_code_to_integer ( enum rtx_code code ) { switch ( code ) { case GT : return GTU ; case GE : return GEU ; case ORDERED : case UNORDERED : return code ; case UNEQ : return EQ ; case UNLT : return LTU ; case UNLE : return LEU ; case LTGT : return NE ; default : return UNKNOWN ; } } </s>

Convert comparison codes we use to represent FP comparison to integer code that will result in proper branch . Return UNKNOWN if no such code is available .


<s> enum ix86_fpcmp_strategy ix86_fp_comparison_strategy ( enum rtx_code ) { if ( TARGET_CMOVE ) return IX86_FPCMP_COMI ; if ( TARGET_SAHF && ( TARGET_USE_SAHF || optimize_insn_for_size_p ( ) ) ) return IX86_FPCMP_SAHF ; return IX86_FPCMP_ARITH ; } </s>

Return strategy to use for floating-point . We assume that fcomi is always preferrable where available , since that is also true when looking at size ( 2 bytes , vs. 3 for fnstsw+sahf and at least 5 for fnstsw+test ) .


Value should be nonzero if functions must have frame pointers . Zero means the frame pointer need not be set up ( and parms may be accessed via the stack pointer ) in functions that seem suitable .


<s> static rtx ix86_function_arg ( cumulative_args_t cum_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; machine_mode mode = arg . mode ; HOST_WIDE_INT bytes , words ; rtx reg ; if ( ! cum -> caller && cfun -> machine -> func_type != TYPE_NORMAL ) { gcc_assert ( arg . type != NULL_TREE ) ; if ( POINTER_TYPE_P ( arg . type ) ) { gcc_assert ( TYPE_MODE ( arg . type ) == Pmode ) ; reg = plus_constant ( Pmode , arg_pointer_rtx , - UNITS_PER_WORD ) ; } else { gcc_assert ( cfun -> machine -> func_type == TYPE_EXCEPTION && TREE_CODE ( arg . type ) == INTEGER_TYPE && TYPE_MODE ( arg . type ) == word_mode ) ; reg = gen_rtx_MEM ( word_mode , plus_constant ( Pmode , arg_pointer_rtx , - 2 * UNITS_PER_WORD ) ) ; } return reg ; } bytes = arg . promoted_size_in_bytes ( ) ; words = CEIL ( bytes , UNITS_PER_WORD ) ; if ( arg . type && TREE_CODE ( arg . type ) == VECTOR_TYPE ) mode = type_natural_mode ( arg . type , cum , false ) ; if ( TARGET_64BIT ) { enum calling_abi call_abi = cum ? cum -> call_abi : ix86_abi ; if ( call_abi == MS_ABI ) reg = function_arg_ms_64 ( cum , mode , arg . mode , arg . named , arg . type , bytes ) ; else reg = function_arg_64 ( cum , mode , arg . mode , arg . type , arg . named ) ; } else reg = function_arg_32 ( cum , mode , arg . mode , arg . type , bytes , words ) ; if ( reg == NULL_RTX && cum -> caller ) cfun -> machine -> outgoing_args_on_stack = true ; return reg ; } </s>

Return where to put the arguments to a function . Return zero to push the argument on the stack , or a hard register in which to store the argument . MODE is the argument 's machine mode . TYPE is the data type of the argument . It is null for libcalls where that information may not be available . CUM gives information about the preceding args and about the function being called . NAMED is nonzero if this argument is a named parameter ( otherwise it is an extra parameter matching an ellipsis ) .


<s> static void ix86_function_arg_advance ( cumulative_args_t cum_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; machine_mode mode = arg . mode ; HOST_WIDE_INT bytes , words ; int nregs ; if ( ! cum -> caller && cfun -> machine -> func_type != TYPE_NORMAL ) return ; bytes = arg . promoted_size_in_bytes ( ) ; words = CEIL ( bytes , UNITS_PER_WORD ) ; if ( arg . type ) mode = type_natural_mode ( arg . type , NULL , false ) ; if ( TARGET_64BIT ) { enum calling_abi call_abi = cum ? cum -> call_abi : ix86_abi ; if ( call_abi == MS_ABI ) nregs = function_arg_advance_ms_64 ( cum , bytes , words ) ; else nregs = function_arg_advance_64 ( cum , mode , arg . type , words , arg . named ) ; } else nregs = function_arg_advance_32 ( cum , mode , arg . type , bytes , words ) ; if ( ! nregs ) { if ( cum -> caller ) cfun -> machine -> outgoing_args_on_stack = true ; } } </s>

Update the data in CUM to advance over an argument of mode MODE and data type TYPE . ( TYPE is null for libcalls where that information may not be available . )


"the ABI for passing parameters with %d-byte"

Gives the alignment boundary , in bits , of an argument with the specified mode and type .


<s> bool ix86_function_arg_regno_p ( int regno ) { int i ; enum calling_abi call_abi ; const int * parm_regs ; if ( TARGET_SSE && SSE_REGNO_P ( regno ) && regno < FIRST_SSE_REG + SSE_REGPARM_MAX ) return true ; if ( ! TARGET_64BIT ) return ( regno < REGPARM_MAX || ( TARGET_MMX && MMX_REGNO_P ( regno ) && regno < FIRST_MMX_REG + MMX_REGPARM_MAX ) ) ; call_abi = ix86_cfun_abi ( ) ; if ( call_abi == SYSV_ABI && regno == AX_REG ) return true ; if ( call_abi == MS_ABI ) parm_regs = x86_64_ms_abi_int_parameter_registers ; else parm_regs = x86_64_int_parameter_registers ; for ( i = 0 ; i < ( call_abi == MS_ABI ? X86_64_MS_REGPARM_MAX : X86_64_REGPARM_MAX ) ; i ++ ) if ( regno == parm_regs [ i ] ) return true ; return false ; } </s>

Return true when register may be used to pass function parameters .


<s>
static
bool
ix86_function_ok_for_sibcall
(
tree
decl
,
tree
exp
)
{
tree
type
,
decl_or_type
;
rtx
a
,
b
;
bool
bind_global
=
decl
&&
!
targetm
.
binds_local_p
(
decl
)
;
if
(
ix86_function_naked
(
current_function_decl
)
)
return
false
;
if
(
cfun
->
machine
->
no_caller_saved_registers
)
return
false
;
if
(
!
TARGET_MACHO
&&
!
TARGET_64BIT
&&
flag_pic
&&
flag_plt
&&
bind_global
)
return
false
;
if
(
ix86_minimum_incoming_stack_boundary
(
true
)
<
PREFERRED_STACK_BOUNDARY
)
return
false
;
if
(
decl
)
{
decl_or_type
=
decl
;
type
=
TREE_TYPE
(
decl
)
;
}
else
{
type
=
CALL_EXPR_FN
(
exp
)
;
type
=
TREE_TYPE
(
type
)
;
type
=
TREE_TYPE
(
type
)
;
decl_or_type
=
type
;
}
if
(
(
OUTGOING_REG_PARM_STACK_SPACE
(
type
)
!=
OUTGOING_REG_PARM_STACK_SPACE
(
TREE_TYPE
(
current_function_decl
)
)
)
||
(
REG_PARM_STACK_SPACE
(
decl_or_type
)
!=
REG_PARM_STACK_SPACE
(
current_function_decl
)
)
)
{
maybe_complain_about_tail_call
(
exp
,
"inconsistent size of stack space"
" allocated for arguments which are"
" passed in registers"
)
;
return
false
;
}
a
=
ix86_function_value
(
TREE_TYPE
(
exp
)
,
decl_or_type
,
false
)
;
b
=
ix86_function_value
(
TREE_TYPE
(
DECL_RESULT
(
cfun
->
decl
)
)
,
cfun
->
decl
,
false
)
;
if
(
STACK_REG_P
(
a
)
||
STACK_REG_P
(
b
)
)
{
if
(
!
rtx_equal_p
(
a
,
b
)
)
return
false
;
}
else
if
(
VOID_TYPE_P
(
TREE_TYPE
(
DECL_RESULT
(
cfun
->
decl
)
)
)
)
;
else
if
(
!
rtx_equal_p
(
a
,
b
)
)
return
false
;
if
(
TARGET_64BIT
)
{
if
(
cfun
->
machine
->
call_abi
==
MS_ABI
&&
ix86_function_type_abi
(
type
)
==
SYSV_ABI
)
return
false
;
}
else
{
if
(
!
decl
||
(
bind_global
&&
flag_pic
&&
!
flag_plt
)
||
(
TARGET_DLLIMPORT_DECL_ATTRIBUTES
&&
DECL_DLLIMPORT_P
(
decl
)
)
||
flag_force_indirect_call
)
{
if
(
ix86_function_regparm
(
type
,
decl
)
>=
3
&&
!
cfun
->
machine
->
arg_reg_available
)
return
false
;
}
}
return
true
;
}
</s>

Decide whether we can make a sibling call to a function . DECL is the declaration of the function being targeted by the call and EXP is the CALL_EXPR representing the call .


<s> static int ix86_function_regparm ( const_tree type , const_tree decl ) { tree attr ; int regparm ; unsigned int ccvt ; if ( TARGET_64BIT ) return ( ix86_function_type_abi ( type ) == SYSV_ABI ? X86_64_REGPARM_MAX : X86_64_MS_REGPARM_MAX ) ; ccvt = ix86_get_callcvt ( type ) ; regparm = ix86_regparm ; if ( ( ccvt & IX86_CALLCVT_REGPARM ) != 0 ) { attr = lookup_attribute ( "regparm" , TYPE_ATTRIBUTES ( type ) ) ; if ( attr ) { regparm = TREE_INT_CST_LOW ( TREE_VALUE ( TREE_VALUE ( attr ) ) ) ; return regparm ; } } else if ( ( ccvt & IX86_CALLCVT_FASTCALL ) != 0 ) return 2 ; else if ( ( ccvt & IX86_CALLCVT_THISCALL ) != 0 ) return 1 ; if ( decl && TREE_CODE ( decl ) == FUNCTION_DECL ) { cgraph_node * target = cgraph_node :: get ( decl ) ; if ( target ) target = target -> function_symbol ( ) ; if ( target && opt_for_fn ( target -> decl , optimize ) && ! ( profile_flag && ! flag_fentry ) ) { if ( target -> local && target -> can_change_signature ) { int local_regparm , globals = 0 , regno ; for ( local_regparm = 0 ; local_regparm < REGPARM_MAX ; local_regparm ++ ) if ( fixed_regs [ local_regparm ] ) break ; if ( local_regparm == 3 && DECL_STATIC_CHAIN ( target -> decl ) ) local_regparm = 2 ; if ( flag_split_stack ) { if ( local_regparm == 3 ) local_regparm = 2 ; else if ( local_regparm == 2 && DECL_STATIC_CHAIN ( target -> decl ) ) local_regparm = 1 ; } for ( regno = AX_REG ; regno <= DI_REG ; regno ++ ) if ( fixed_regs [ regno ] ) globals ++ ; local_regparm = globals < local_regparm ? local_regparm - globals : 0 ; if ( local_regparm > regparm ) regparm = local_regparm ; } } } return regparm ; } </s>

Return the regparm value for a function with the indicated TYPE and DECL . DECL may be NULL when calling function indirectly or considering a libcall .


"calling %qD with attribute sseregparm without "

"calling %qT with attribute sseregparm without "

Return 1 or 2 , if we can pass up to SSE_REGPARM_MAX SFmode ( 1 ) and DFmode ( 2 ) arguments in SSE registers for a function with the indicated TYPE and DECL . DECL may be NULL when calling function indirectly or considering a libcall . Otherwise return 0 .


"X32 does not support %<ms_abi%> attribute"

Returns value SYSV_ABI , MS_ABI dependent on fntype , specifying the call abi used .


<s> static rtx ix86_function_value ( const_tree valtype , const_tree fntype_or_decl , bool ) { machine_mode mode , orig_mode ; orig_mode = TYPE_MODE ( valtype ) ; mode = type_natural_mode ( valtype , NULL , true ) ; return ix86_function_value_1 ( valtype , fntype_or_decl , orig_mode , mode ) ; } </s>

Define how to find the value returned by a function . VALTYPE is the data type of the value ( as a tree ) . If the precise function being called is known , FUNC is its FUNCTION_DECL ; otherwise , FUNC is 0 .


<s> static bool ix86_function_value_regno_p ( const unsigned int regno ) { switch ( regno ) { case AX_REG : return true ; case DX_REG : return ( ! TARGET_64BIT || ix86_cfun_abi ( ) != MS_ABI ) ; case DI_REG : case SI_REG : return TARGET_64BIT && ix86_cfun_abi ( ) != MS_ABI ; case ST0_REG : case ST1_REG : if ( TARGET_64BIT && ix86_cfun_abi ( ) == MS_ABI ) return false ; return TARGET_FLOAT_RETURNS_IN_80387 ; case XMM0_REG : case XMM1_REG : return TARGET_SSE ; case MM0_REG : if ( TARGET_MACHO || TARGET_64BIT ) return false ; return TARGET_MMX ; } return false ; } </s>

Return true if N is a possible register number of function value .


<s> rtx ix86_gen_scratch_sse_rtx ( machine_mode mode ) { return gen_reg_rtx ( mode ) ; } </s>

Implement the TARGET_GEN_MEMSET_SCRATCH_RTX hook . Return a scratch register in MODE for vector load and store .


<s> unsigned int ix86_get_callcvt ( const_tree type ) { unsigned int ret = 0 ; bool is_stdarg ; tree attrs ; if ( TARGET_64BIT ) return IX86_CALLCVT_CDECL ; attrs = TYPE_ATTRIBUTES ( type ) ; if ( attrs != NULL_TREE ) { if ( lookup_attribute ( "cdecl" , attrs ) ) ret |= IX86_CALLCVT_CDECL ; else if ( lookup_attribute ( "stdcall" , attrs ) ) ret |= IX86_CALLCVT_STDCALL ; else if ( lookup_attribute ( "fastcall" , attrs ) ) ret |= IX86_CALLCVT_FASTCALL ; else if ( lookup_attribute ( "thiscall" , attrs ) ) ret |= IX86_CALLCVT_THISCALL ; if ( ( ret & ( IX86_CALLCVT_THISCALL | IX86_CALLCVT_FASTCALL ) ) == 0 ) { if ( lookup_attribute ( "regparm" , attrs ) ) ret |= IX86_CALLCVT_REGPARM ; if ( lookup_attribute ( "sseregparm" , attrs ) ) ret |= IX86_CALLCVT_SSEREGPARM ; } if ( IX86_BASE_CALLCVT ( ret ) != 0 ) return ret ; } is_stdarg = stdarg_p ( type ) ; if ( TARGET_RTD && ! is_stdarg ) return IX86_CALLCVT_STDCALL | ret ; if ( ret != 0 || is_stdarg || TREE_CODE ( type ) != METHOD_TYPE || ix86_function_type_abi ( type ) != MS_ABI ) return IX86_CALLCVT_CDECL | ret ; return IX86_CALLCVT_THISCALL ; } </s>

This function determines from TYPE the calling-convention .


<s> static rtx ix86_get_drap_rtx ( void ) { if ( ix86_force_drap || ( ( cfun -> machine -> outgoing_args_on_stack || crtl -> sp_is_clobbered_by_asm ) && ! ACCUMULATE_OUTGOING_ARGS ) ) crtl -> need_drap = true ; if ( stack_realign_drap ) { unsigned int regno = find_drap_reg ( ) ; rtx drap_vreg ; rtx arg_ptr ; rtx_insn * seq , * insn ; arg_ptr = gen_rtx_REG ( Pmode , regno ) ; crtl -> drap_reg = arg_ptr ; start_sequence ( ) ; drap_vreg = copy_to_reg ( arg_ptr ) ; seq = get_insns ( ) ; end_sequence ( ) ; insn = emit_insn_before ( seq , NEXT_INSN ( entry_of_function ( ) ) ) ; if ( ! optimize ) { add_reg_note ( insn , REG_CFA_SET_VDRAP , drap_vreg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } return drap_vreg ; } else return NULL ; } </s>

Handle the TARGET_GET_DRAP_RTX hook . Return NULL if no DRAP is needed or an rtx for DRAP otherwise .


"%<-fexcess-precision=16%> is not compatible with %<-mfpmath=387%>"

Set the value of FLT_EVAL_METHOD in float.h . When using only the FPU , assume that the fpcw is set to extended precision ; when using only SSE , rounding is correct ; when using both SSE and the FPU , the rounding precision is indeterminate , since either may be chosen apparently at random .


<s> static HOST_WIDE_INT ix86_get_frame_size ( void ) { if ( cfun -> machine -> stack_frame_required ) return get_frame_size ( ) ; else return 0 ; } </s>

Return stack frame size . get_frame_size ( ) returns used stack slots during compilation , which may be optimized out later . If stack frame is needed , stack_frame_required should be true .


<s> static opt_machine_mode ix86_get_mask_mode ( machine_mode data_mode ) { unsigned vector_size = GET_MODE_SIZE ( data_mode ) ; unsigned nunits = GET_MODE_NUNITS ( data_mode ) ; unsigned elem_size = vector_size / nunits ; if ( ( TARGET_AVX512F && vector_size == 64 ) || ( TARGET_AVX512VL && ( vector_size == 32 || vector_size == 16 ) ) ) { if ( elem_size == 4 || elem_size == 8 || ( TARGET_AVX512BW && ( elem_size == 1 || elem_size == 2 ) ) ) return smallest_int_mode_for_size ( nunits ) ; } scalar_int_mode elem_mode = smallest_int_mode_for_size ( elem_size * BITS_PER_UNIT ) ; gcc_assert ( elem_size * nunits == vector_size ) ; return mode_for_vector ( elem_mode , nunits ) ; } </s>

Implemenation of targetm.vectorize.get_mask_mode .


<s> static const char * ix86_get_multilib_abi_name ( void ) { if ( ! ( TARGET_64BIT_P ( ix86_isa_flags ) ) ) return "i386" ; else if ( TARGET_X32_P ( ix86_isa_flags ) ) return "x32" ; else return "x86_64" ; } </s>

This hook returns name of multilib ABI .


<s> alias_set_type ix86_GOT_alias_set ( void ) { static alias_set_type set = - 1 ; if ( set == - 1 ) set = new_alias_set ( ) ; return set ; } </s>

Return an unique alias set for the GOT .


<s> bool ix86_gpr_tls_address_pattern_p ( rtx mem ) { gcc_assert ( MEM_P ( mem ) ) ; rtx addr = XEXP ( mem , 0 ) ; subrtx_var_iterator :: array_type array ; FOR_EACH_SUBRTX_VAR ( iter , array , addr , ALL ) { rtx op = * iter ; if ( GET_CODE ( op ) == UNSPEC ) switch ( XINT ( op , 1 ) ) { case UNSPEC_GOTNTPOFF : return true ; case UNSPEC_TPOFF : if ( ! TARGET_64BIT ) return true ; break ; default : break ; } } return false ; } </s>

Return true if the TLS address requires insn using integer registers . It 's used to prevent KMOV/VMOV in TLS code sequences which require integer MOV instructions , refer to PR103275 .


<s> bool ix86_hardreg_mov_ok ( rtx dst , rtx src ) { if ( REG_P ( dst ) && HARD_REGISTER_P ( dst ) && ! REG_P ( src ) && ! MEM_P ( src ) && ! ( VECTOR_MODE_P ( GET_MODE ( dst ) ) ? standard_sse_constant_p ( src , GET_MODE ( dst ) ) : x86_64_immediate_operand ( src , GET_MODE ( dst ) ) ) && ix86_class_likely_spilled_p ( REGNO_REG_CLASS ( REGNO ( dst ) ) ) && ! reload_completed ) return false ; return true ; } </s>

Return true if a set of DST by the expression SRC should be allowed . This prevents complex sets of likely_spilled hard regs before reload .


<s> static bool ix86_hard_regno_call_part_clobbered ( unsigned int abi_id , unsigned int regno , machine_mode mode ) { if ( abi_id == ABI_VZEROUPPER ) return ( GET_MODE_SIZE ( mode ) > 16 && ( ( TARGET_64BIT && REX_SSE_REGNO_P ( regno ) ) || LEGACY_SSE_REGNO_P ( regno ) ) ) ; return SSE_REGNO_P ( regno ) && GET_MODE_SIZE ( mode ) > 16 ; } </s>

Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED . The only ABI that saves SSE registers across calls is Win64 ( thus no need to check the current ABI here ) , and with AVX enabled Win64 only guarantees that the low 16 bytes are saved .


<s> static bool ix86_hard_regno_mode_ok ( unsigned int regno , machine_mode mode ) { if ( CC_REGNO_P ( regno ) ) return GET_MODE_CLASS ( mode ) == MODE_CC ; if ( GET_MODE_CLASS ( mode ) == MODE_CC || GET_MODE_CLASS ( mode ) == MODE_RANDOM ) return false ; if ( STACK_REGNO_P ( regno ) ) return VALID_FP_MODE_P ( mode ) ; if ( MASK_REGNO_P ( regno ) ) { if ( ( mode == P2QImode || mode == P2HImode ) ) return MASK_PAIR_REGNO_P ( regno ) ; return ( ( TARGET_AVX512F && VALID_MASK_REG_MODE ( mode ) ) || ( TARGET_AVX512BW && VALID_MASK_AVX512BW_MODE ( mode ) ) ) ; } if ( GET_MODE_CLASS ( mode ) == MODE_PARTIAL_INT ) return false ; if ( SSE_REGNO_P ( regno ) ) { if ( TARGET_AVX512F && ( VALID_AVX512F_REG_OR_XI_MODE ( mode ) || VALID_AVX512F_SCALAR_MODE ( mode ) ) ) return true ; if ( TARGET_AVX512FP16 && VALID_AVX512FP16_SCALAR_MODE ( mode ) ) return true ; if ( ( TARGET_AVX5124FMAPS || TARGET_AVX5124VNNIW ) && ( mode == V64SFmode || mode == V64SImode ) && MOD4_SSE_REGNO_P ( regno ) ) return true ; if ( TARGET_AVX512VL && ( VALID_AVX256_REG_OR_OI_MODE ( mode ) || VALID_AVX512VL_128_REG_MODE ( mode ) ) ) return true ; if ( EXT_REX_SSE_REGNO_P ( regno ) ) return false ; return ( ( TARGET_AVX && VALID_AVX256_REG_OR_OI_MODE ( mode ) ) || VALID_SSE_REG_MODE ( mode ) || VALID_SSE2_REG_MODE ( mode ) || VALID_MMX_REG_MODE ( mode ) || VALID_MMX_REG_MODE_3DNOW ( mode ) ) ; } if ( MMX_REGNO_P ( regno ) ) { return ( VALID_MMX_REG_MODE ( mode ) || VALID_MMX_REG_MODE_3DNOW ( mode ) ) ; } if ( mode == QImode ) { if ( ANY_QI_REGNO_P ( regno ) ) return true ; if ( ! TARGET_PARTIAL_REG_STALL ) return true ; if ( lra_in_progress ) return true ; return ! can_create_pseudo_p ( ) ; } else if ( VALID_INT_MODE_P ( mode ) || VALID_FP_MODE_P ( mode ) ) return true ; else if ( VALID_MMX_REG_MODE_3DNOW ( mode ) || VALID_MMX_REG_MODE ( mode ) ) return true ; return false ; } </s>

Return TRUE if hard register REGNO can hold a value of machine-mode MODE .


<s> static unsigned int ix86_hard_regno_nregs ( unsigned int regno , machine_mode mode ) { if ( GENERAL_REGNO_P ( regno ) ) { if ( mode == XFmode ) return TARGET_64BIT ? 2 : 3 ; if ( mode == XCmode ) return TARGET_64BIT ? 4 : 6 ; return CEIL ( GET_MODE_SIZE ( mode ) , UNITS_PER_WORD ) ; } if ( COMPLEX_MODE_P ( mode ) ) return 2 ; if ( mode == P2QImode || mode == P2HImode ) return 2 ; if ( mode == V64SFmode || mode == V64SImode ) return 4 ; return 1 ; } </s>

Implement TARGET_HARD_REGNO_NREGS . This is ordinarily the length in words of a value of mode MODE but can be less for certain modes in special long registers . Actually there are no two word move instructions for consecutive registers . And only registers 0-3 may have mov byte instructions applied to them .


<s> static bool ix86_hard_regno_scratch_ok ( unsigned int regno ) { return ( ! cfun -> machine -> no_caller_saved_registers || ( ! epilogue_completed && df_regs_ever_live_p ( regno ) ) ) ; } </s>

Return nonzero if register REGNO can be used as a scratch register in peephole2 .


<s> static int ix86_i387_mode_needed ( int entity , rtx_insn * insn ) { enum attr_i387_cw mode ; if ( CALL_P ( insn ) || ( NONJUMP_INSN_P ( insn ) && ( asm_noperands ( PATTERN ( insn ) ) >= 0 || GET_CODE ( PATTERN ( insn ) ) == ASM_INPUT ) ) ) return I387_CW_UNINITIALIZED ; if ( recog_memoized ( insn ) < 0 ) return I387_CW_ANY ; mode = get_attr_i387_cw ( insn ) ; switch ( entity ) { case I387_ROUNDEVEN : if ( mode == I387_CW_ROUNDEVEN ) return mode ; break ; case I387_TRUNC : if ( mode == I387_CW_TRUNC ) return mode ; break ; case I387_FLOOR : if ( mode == I387_CW_FLOOR ) return mode ; break ; case I387_CEIL : if ( mode == I387_CW_CEIL ) return mode ; break ; default : gcc_unreachable ( ) ; } return I387_CW_ANY ; } </s>

Return mode that i387 must be switched into prior to the execution of insn .


<s> void ix86_initialize_callee_abi ( unsigned int abi_id ) { gcc_assert ( abi_id == ABI_VZEROUPPER ) ; predefined_function_abi & vzeroupper_abi = function_abis [ abi_id ] ; if ( ! vzeroupper_abi . initialized_p ( ) ) { HARD_REG_SET full_reg_clobbers ; CLEAR_HARD_REG_SET ( full_reg_clobbers ) ; vzeroupper_abi . initialize ( ABI_VZEROUPPER , full_reg_clobbers ) ; } } </s>

Initialize function_abis with corresponding abi_id , currently only handle vzeroupper .


<s> HOST_WIDE_INT ix86_initial_elimination_offset ( int from , int to ) { struct ix86_frame & frame = cfun -> machine -> frame ; if ( from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM ) return frame . hard_frame_pointer_offset ; else if ( from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM ) return frame . hard_frame_pointer_offset - frame . frame_pointer_offset ; else { gcc_assert ( to == STACK_POINTER_REGNUM ) ; if ( from == ARG_POINTER_REGNUM ) return frame . stack_pointer_offset ; gcc_assert ( from == FRAME_POINTER_REGNUM ) ; return frame . stack_pointer_offset - frame . frame_pointer_offset ; } } </s>

Return the offset between two registers , one to be eliminated , and the other its replacement , at the start of a routine .


<s> static void * ix86_init_cost ( class loop * ) { unsigned * cost = XNEWVEC ( unsigned , 3 ) ; cost [ vect_prologue ] = cost [ vect_body ] = cost [ vect_epilogue ] = 0 ; return cost ; } </s>


<s> static void ix86_init_large_pic_reg ( unsigned int tmp_regno ) { rtx_code_label * label ; rtx tmp_reg ; gcc_assert ( Pmode == DImode ) ; label = gen_label_rtx ( ) ; emit_label ( label ) ; LABEL_PRESERVE_P ( label ) = 1 ; tmp_reg = gen_rtx_REG ( Pmode , tmp_regno ) ; gcc_assert ( REGNO ( pic_offset_table_rtx ) != tmp_regno ) ; emit_insn ( gen_set_rip_rex64 ( pic_offset_table_rtx , label ) ) ; emit_insn ( gen_set_got_offset_rex64 ( tmp_reg , label ) ) ; emit_insn ( gen_add2_insn ( pic_offset_table_rtx , tmp_reg ) ) ; const char * name = LABEL_NAME ( label ) ; PUT_CODE ( label , NOTE ) ; NOTE_KIND ( label ) = NOTE_INSN_DELETED_LABEL ; NOTE_DELETED_LABEL_NAME ( label ) = name ; } </s>


<s> static void ix86_init_pic_reg ( void ) { edge entry_edge ; rtx_insn * seq ; if ( ! ix86_use_pseudo_pic_reg ( ) ) return ; start_sequence ( ) ; if ( TARGET_64BIT ) { if ( ix86_cmodel == CM_LARGE_PIC ) ix86_init_large_pic_reg ( R11_REG ) ; else emit_insn ( gen_set_got_rex64 ( pic_offset_table_rtx ) ) ; } else { rtx reg = crtl -> profile ? gen_rtx_REG ( Pmode , REAL_PIC_OFFSET_TABLE_REGNUM ) : pic_offset_table_rtx ; rtx_insn * insn = emit_insn ( gen_set_got ( reg ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; if ( crtl -> profile ) emit_move_insn ( pic_offset_table_rtx , reg ) ; add_reg_note ( insn , REG_CFA_FLUSH_QUEUE , NULL_RTX ) ; } seq = get_insns ( ) ; end_sequence ( ) ; entry_edge = single_succ_edge ( ENTRY_BLOCK_PTR_FOR_FN ( cfun ) ) ; insert_insn_on_edge ( seq , entry_edge ) ; commit_one_edge_insertion ( entry_edge ) ; } </s>

Create and initialize PIC register if required .


<s> const predefined_function_abi & ix86_insn_callee_abi ( const rtx_insn * insn ) { unsigned int abi_id = 0 ; rtx pat = PATTERN ( insn ) ; if ( vzeroupper_pattern ( pat , VOIDmode ) ) abi_id = ABI_VZEROUPPER ; return function_abis [ abi_id ] ; } </s>


<s> static rtx ix86_internal_arg_pointer ( void ) { return virtual_incoming_args_rtx ; } </s>

Handle the TARGET_INTERNAL_ARG_POINTER hook .


<s> static bool ix86_in_large_data_p ( tree exp ) { if ( ix86_cmodel != CM_MEDIUM && ix86_cmodel != CM_MEDIUM_PIC ) return false ; if ( exp == NULL_TREE ) return false ; if ( TREE_CODE ( exp ) == FUNCTION_DECL ) return false ; if ( VAR_P ( exp ) && ! is_global_var ( exp ) ) return false ; if ( VAR_P ( exp ) && DECL_SECTION_NAME ( exp ) ) { const char * section = DECL_SECTION_NAME ( exp ) ; if ( strcmp ( section , ".ldata" ) == 0 || strcmp ( section , ".lbss" ) == 0 ) return true ; return false ; } else { HOST_WIDE_INT size = int_size_in_bytes ( TREE_TYPE ( exp ) ) ; if ( size <= 0 || size > ix86_section_threshold ) return true ; } return false ; } </s>

Return true if this goes in small data/bss .


<s> static bool ix86_is_empty_record ( const_tree type ) { if ( ! TARGET_64BIT ) return false ; return default_is_empty_record ( type ) ; } </s>


<s> bool ix86_lea_for_add_ok ( rtx_insn * insn , rtx operands [ ] ) { unsigned int regno0 = true_regnum ( operands [ 0 ] ) ; unsigned int regno1 = true_regnum ( operands [ 1 ] ) ; unsigned int regno2 = true_regnum ( operands [ 2 ] ) ; if ( regno0 != regno1 && regno0 != regno2 ) return true ; if ( ! TARGET_OPT_AGU || optimize_function_for_size_p ( cfun ) ) return false ; return ix86_lea_outperforms ( insn , regno0 , regno1 , regno2 , 0 , false ) ; } </s>

Return true if it is ok to optimize an ADD operation to LEA operation to avoid flag register consumation . For most processors , ADD is faster than LEA . For the processors like BONNELL , if the destination register of LEA holds an actual address which will be used soon , LEA is better and otherwise ADD is better .


<s> static bool ix86_lea_outperforms ( rtx_insn * insn , unsigned int regno0 , unsigned int regno1 , unsigned int regno2 , int split_cost , bool has_scale ) { int dist_define , dist_use ; if ( ! TARGET_CPU_P ( BONNELL ) ) { if ( has_scale ) return true ; if ( split_cost < 1 ) return false ; if ( regno0 == regno1 || regno0 == regno2 ) return false ; return true ; } struct recog_data_d recog_data_save = recog_data ; dist_define = distance_non_agu_define ( regno1 , regno2 , insn ) ; dist_use = distance_agu_use ( regno0 , insn ) ; recog_data = recog_data_save ; if ( dist_define < 0 || dist_define >= LEA_MAX_STALL ) { if ( dist_use < 0 && split_cost == 0 ) return TARGET_64BIT || IX86_LEA_PRIORITY ; else return true ; } dist_define += split_cost + IX86_LEA_PRIORITY ; if ( dist_use < 0 ) return dist_define > LEA_MAX_STALL ; return dist_define >= dist_use ; } </s>

Return true if usage of lea INSN has performance advantage over a sequence of instructions . Instructions sequence has SPLIT_COST cycles higher latency than lea latency .


<s> static bool ix86_legitimate_combined_insn ( rtx_insn * insn ) { int i ; gcc_assert ( INSN_CODE ( insn ) >= 0 ) ; extract_insn ( insn ) ; preprocess_constraints ( insn ) ; int n_operands = recog_data . n_operands ; int n_alternatives = recog_data . n_alternatives ; for ( i = 0 ; i < n_operands ; i ++ ) { rtx op = recog_data . operand [ i ] ; machine_mode mode = GET_MODE ( op ) ; const operand_alternative * op_alt ; int offset = 0 ; bool win ; int j ; if ( UNARY_P ( op ) ) op = XEXP ( op , 0 ) ; if ( SUBREG_P ( op ) ) { if ( REG_P ( SUBREG_REG ( op ) ) && REGNO ( SUBREG_REG ( op ) ) < FIRST_PSEUDO_REGISTER ) offset = subreg_regno_offset ( REGNO ( SUBREG_REG ( op ) ) , GET_MODE ( SUBREG_REG ( op ) ) , SUBREG_BYTE ( op ) , GET_MODE ( op ) ) ; op = SUBREG_REG ( op ) ; } if ( ! ( REG_P ( op ) && HARD_REGISTER_P ( op ) ) ) continue ; op_alt = recog_op_alt ; win = ! n_alternatives ; alternative_mask preferred = get_preferred_alternatives ( insn ) ; for ( j = 0 ; j < n_alternatives ; j ++ , op_alt += n_operands ) { if ( ! TEST_BIT ( preferred , j ) ) continue ; if ( op_alt [ i ] . anything_ok || ( op_alt [ i ] . matches != - 1 && operands_match_p ( recog_data . operand [ i ] , recog_data . operand [ op_alt [ i ] . matches ] ) ) || reg_fits_class_p ( op , op_alt [ i ] . cl , offset , mode ) ) { win = true ; break ; } } if ( ! win ) return false ; } return true ; } </s>

Implement the TARGET_LEGITIMATE_COMBINED_INSN hook .


<s> static bool ix86_legitimate_constant_p ( machine_mode mode , rtx x ) { switch ( GET_CODE ( x ) ) { case CONST : x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == PLUS ) { if ( ! CONST_INT_P ( XEXP ( x , 1 ) ) ) return false ; x = XEXP ( x , 0 ) ; } if ( TARGET_MACHO && darwin_local_data_pic ( x ) ) return true ; if ( GET_CODE ( x ) == UNSPEC ) switch ( XINT ( x , 1 ) ) { case UNSPEC_GOT : case UNSPEC_GOTOFF : case UNSPEC_PLTOFF : return TARGET_64BIT ; case UNSPEC_TPOFF : case UNSPEC_NTPOFF : x = XVECEXP ( x , 0 , 0 ) ; return ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL ( x ) == TLS_MODEL_LOCAL_EXEC ) ; case UNSPEC_DTPOFF : x = XVECEXP ( x , 0 , 0 ) ; return ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL ( x ) == TLS_MODEL_LOCAL_DYNAMIC ) ; default : return false ; } if ( GET_CODE ( x ) == LABEL_REF ) return true ; if ( GET_CODE ( x ) != SYMBOL_REF ) return false ; case SYMBOL_REF : if ( SYMBOL_REF_TLS_MODEL ( x ) ) return false ; if ( TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P ( x ) ) return false ; if ( MACHO_DYNAMIC_NO_PIC_P ) return machopic_symbol_defined_p ( x ) ; if ( ix86_force_load_from_GOT_p ( x ) ) return false ; break ; CASE_CONST_SCALAR_INT : if ( ix86_endbr_immediate_operand ( x , VOIDmode ) ) return false ; switch ( mode ) { case E_TImode : if ( TARGET_64BIT ) return true ; case E_OImode : case E_XImode : if ( ! standard_sse_constant_p ( x , mode ) && GET_MODE_SIZE ( TARGET_AVX512F ? XImode : ( TARGET_AVX ? OImode : ( TARGET_SSE2 ? TImode : DImode ) ) ) < GET_MODE_SIZE ( mode ) ) return false ; default : break ; } break ; case CONST_VECTOR : if ( ! standard_sse_constant_p ( x , mode ) ) return false ; default : break ; } return true ; } </s>

Determine if a given RTX is a valid constant . We already know this satisfies CONSTANT_P .


<s> rtx ix86_libcall_value ( machine_mode mode ) { return ix86_function_value_1 ( NULL , NULL , mode , mode ) ; } </s>

Define how to find the value returned by a library function assuming the value has mode MODE .


<s> bool ix86_libc_has_function ( enum function_class fn_class ) { return targetm . libc_has_function ( fn_class , NULL_TREE ) ; } </s>

We add this as a workaround in order to use libc_has_function hook in i386.md .


Implement target hook libgcc_floating_mode_supported_p .


<s> static void ix86_live_on_entry ( bitmap regs ) { if ( cfun -> machine -> split_stack_varargs_pointer != NULL_RTX ) { gcc_assert ( flag_split_stack ) ; bitmap_set_bit ( regs , split_stack_prologue_scratch_regno ( ) ) ; } } </s>

We may have to tell the dataflow pass that the split stack prologue is initializing a scratch register .


<s> unsigned int ix86_local_alignment ( tree exp , machine_mode mode , unsigned int align , bool may_lower ) { tree type , decl ; if ( exp && DECL_P ( exp ) ) { type = TREE_TYPE ( exp ) ; decl = exp ; } else { type = exp ; decl = NULL ; } if ( may_lower && ! TARGET_64BIT && align == 64 && ix86_preferred_stack_boundary < 64 && ( mode == DImode || ( type && TYPE_MODE ( type ) == DImode ) ) && ( ! type || ( ! TYPE_USER_ALIGN ( type ) && ! TYPE_ATOMIC ( strip_array_types ( type ) ) ) ) && ( ! decl || ! DECL_USER_ALIGN ( decl ) ) ) align = 32 ; if ( ! type ) { if ( mode == XFmode && align < GET_MODE_ALIGNMENT ( DFmode ) ) align = GET_MODE_ALIGNMENT ( DFmode ) ; return align ; } if ( TARGET_IAMCU ) return align ; if ( TARGET_64BIT && optimize_function_for_speed_p ( cfun ) && TARGET_SSE ) { if ( AGGREGATE_TYPE_P ( type ) && ( va_list_type_node == NULL_TREE || ( TYPE_MAIN_VARIANT ( type ) != TYPE_MAIN_VARIANT ( va_list_type_node ) ) ) && TYPE_SIZE ( type ) && TREE_CODE ( TYPE_SIZE ( type ) ) == INTEGER_CST && wi :: geu_p ( wi :: to_wide ( TYPE_SIZE ( type ) ) , 128 ) && align < 128 ) return 128 ; } if ( TREE_CODE ( type ) == ARRAY_TYPE ) { if ( TYPE_MODE ( TREE_TYPE ( type ) ) == DFmode && align < 64 ) return 64 ; if ( ALIGN_MODE_128 ( TYPE_MODE ( TREE_TYPE ( type ) ) ) && align < 128 ) return 128 ; } else if ( TREE_CODE ( type ) == COMPLEX_TYPE ) { if ( TYPE_MODE ( type ) == DCmode && align < 64 ) return 64 ; if ( ( TYPE_MODE ( type ) == XCmode || TYPE_MODE ( type ) == TCmode ) && align < 128 ) return 128 ; } else if ( ( TREE_CODE ( type ) == RECORD_TYPE || TREE_CODE ( type ) == UNION_TYPE || TREE_CODE ( type ) == QUAL_UNION_TYPE ) && TYPE_FIELDS ( type ) ) { if ( DECL_MODE ( TYPE_FIELDS ( type ) ) == DFmode && align < 64 ) return 64 ; if ( ALIGN_MODE_128 ( DECL_MODE ( TYPE_FIELDS ( type ) ) ) && align < 128 ) return 128 ; } else if ( TREE_CODE ( type ) == REAL_TYPE || TREE_CODE ( type ) == VECTOR_TYPE || TREE_CODE ( type ) == INTEGER_TYPE ) { if ( TYPE_MODE ( type ) == DFmode && align < 64 ) return 64 ; if ( ALIGN_MODE_128 ( TYPE_MODE ( type ) ) && align < 128 ) return 128 ; } return align ; } </s>

Compute the alignment for a local variable . TYPE is the data type , and ALIGN is the alignment that the object would ordinarily have . The value of this macro is used instead of that alignment to align the object .


<s> static unsigned ix86_loop_unroll_adjust ( unsigned nunroll , class loop * loop ) { basic_block * bbs ; rtx_insn * insn ; unsigned i ; unsigned mem_count = 0 ; if ( ! TARGET_ADJUST_UNROLL ) return nunroll ; subrtx_iterator :: array_type array ; bbs = get_loop_body ( loop ) ; for ( i = 0 ; i < loop -> num_nodes ; i ++ ) FOR_BB_INSNS ( bbs [ i ] , insn ) if ( NONDEBUG_INSN_P ( insn ) ) FOR_EACH_SUBRTX ( iter , array , PATTERN ( insn ) , NONCONST ) if ( const_rtx x = * iter ) if ( MEM_P ( x ) ) { machine_mode mode = GET_MODE ( x ) ; unsigned int n_words = GET_MODE_SIZE ( mode ) / UNITS_PER_WORD ; if ( n_words > 4 ) mem_count += 2 ; else mem_count += 1 ; } free ( bbs ) ; if ( mem_count && mem_count <= 32 ) return MIN ( nunroll , 32 / mem_count ) ; return nunroll ; } </s>

This function adjusts the unroll factor based on the hardware capabilities . For ex , bdver3 has a loop buffer which makes unrolling of smaller loops less important . This function decides the unroll factor using number of memory references ( value 32 is used ) as a heuristic .


<s> static void ix86_lower_local_decl_alignment ( tree decl ) { unsigned int new_align = ix86_local_alignment ( decl , VOIDmode , DECL_ALIGN ( decl ) , true ) ; if ( new_align < DECL_ALIGN ( decl ) ) SET_DECL_ALIGN ( decl , new_align ) ; } </s>


<s> static const char * ix86_mangle_type ( const_tree type ) { type = TYPE_MAIN_VARIANT ( type ) ; if ( TREE_CODE ( type ) != VOID_TYPE && TREE_CODE ( type ) != BOOLEAN_TYPE && TREE_CODE ( type ) != INTEGER_TYPE && TREE_CODE ( type ) != REAL_TYPE ) return NULL ; switch ( TYPE_MODE ( type ) ) { case E_HFmode : return "DF16_" ; case E_TFmode : return "g" ; case E_XFmode : return "e" ; default : return NULL ; } } </s>

Return the mangling of TYPE if it is an extended fundamental type .


<s> static bool ix86_masked_all_ones ( unsigned HOST_WIDE_INT elems , tree arg_mask ) { if ( TREE_CODE ( arg_mask ) != INTEGER_CST ) return false ; unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW ( arg_mask ) ; if ( ( mask | ( HOST_WIDE_INT_M1U << elems ) ) != HOST_WIDE_INT_M1U ) return false ; return true ; } </s>

Return true if arg_mask is all ones , ELEMS is elements number of corresponding vector .


<s> bool ix86_match_ccmode ( rtx insn , machine_mode req_mode ) { rtx set ; machine_mode set_mode ; set = PATTERN ( insn ) ; if ( GET_CODE ( set ) == PARALLEL ) set = XVECEXP ( set , 0 , 0 ) ; gcc_assert ( GET_CODE ( set ) == SET ) ; gcc_assert ( GET_CODE ( SET_SRC ( set ) ) == COMPARE ) ; set_mode = GET_MODE ( SET_DEST ( set ) ) ; switch ( set_mode ) { case E_CCNOmode : if ( req_mode != CCNOmode && ( req_mode != CCmode || XEXP ( SET_SRC ( set ) , 1 ) != const0_rtx ) ) return false ; break ; case E_CCmode : if ( req_mode == CCGCmode ) return false ; case E_CCGCmode : if ( req_mode == CCGOCmode || req_mode == CCNOmode ) return false ; case E_CCGOCmode : if ( req_mode == CCZmode ) return false ; case E_CCZmode : break ; case E_CCGZmode : case E_CCAmode : case E_CCCmode : case E_CCOmode : case E_CCPmode : case E_CCSmode : if ( set_mode != req_mode ) return false ; break ; default : gcc_unreachable ( ) ; } return GET_MODE ( SET_SRC ( set ) ) == set_mode ; } </s>

Return TRUE or FALSE depending on whether the first SET in INSN has source and destination with matching CC modes , and that the CC mode is at least as constrained as REQ_MODE .


Implement TARGET_MAX_NOCE_IFCVT_SEQ_COST . Like the default implementation , but returns a lower bound .


<s> static bool ix86_member_type_forces_blk ( const_tree field , machine_mode mode ) { return ( mode == XFmode && ( TREE_CODE ( DECL_FIELD_CONTEXT ( field ) ) == UNION_TYPE || TREE_CODE ( DECL_FIELD_CONTEXT ( field ) ) == QUAL_UNION_TYPE ) ) ; } </s>

Return true if a structure , union or array with MODE containing FIELD should be accessed using BLKmode .


"unknown architecture specific memory model"

"%<HLE_ACQUIRE%> not used with %<ACQUIRE%> or stronger "

"%<HLE_RELEASE%> not used with %<RELEASE%> or stronger "

Validate target specific memory model bits in VAL .


<s> static int ix86_memory_move_cost ( machine_mode mode , reg_class_t regclass , bool in ) { return inline_memory_move_cost ( mode , ( enum reg_class ) regclass , in ? 1 : 0 ) ; } </s>

Return the cost of moving data of mode M between a register and memory . A value of 2 is the default ; this cost is relative to those in ` REGISTER_MOVE_COST ' . If moving between registers and memory is more expensive than between two registers , you should define this macro to express the relative cost . Model also increased moving costs of QImode registers in non Q_REGS classes .


<s> unsigned int ix86_minimum_alignment ( tree exp , machine_mode mode , unsigned int align ) { tree type , decl ; if ( exp && DECL_P ( exp ) ) { type = TREE_TYPE ( exp ) ; decl = exp ; } else { type = exp ; decl = NULL ; } if ( TARGET_64BIT || align != 64 || ix86_preferred_stack_boundary >= 64 ) return align ; if ( ( mode == DImode || ( type && TYPE_MODE ( type ) == DImode ) ) && ( ! type || ( ! TYPE_USER_ALIGN ( type ) && ! TYPE_ATOMIC ( strip_array_types ( type ) ) ) ) && ( ! decl || ! DECL_USER_ALIGN ( decl ) ) ) { gcc_checking_assert ( ! TARGET_STV ) ; return 32 ; } return align ; } </s>

Compute the minimum required alignment for dynamic stack realignment purposes for a local variable , parameter or a stack slot . EXP is the data type or decl itself , MODE is its mode and ALIGN is the alignment that the object would ordinarily have .


<s> static unsigned int ix86_minimum_incoming_stack_boundary ( bool sibcall ) { unsigned int incoming_stack_boundary ; if ( cfun -> machine -> func_type != TYPE_NORMAL ) incoming_stack_boundary = TARGET_64BIT ? 128 : MIN_STACK_BOUNDARY ; else if ( ix86_user_incoming_stack_boundary ) incoming_stack_boundary = ix86_user_incoming_stack_boundary ; else if ( ! sibcall && ix86_force_align_arg_pointer && crtl -> stack_alignment_estimated == 128 ) incoming_stack_boundary = MIN_STACK_BOUNDARY ; else incoming_stack_boundary = ix86_default_incoming_stack_boundary ; if ( incoming_stack_boundary > MIN_STACK_BOUNDARY && lookup_attribute ( "force_align_arg_pointer" , TYPE_ATTRIBUTES ( TREE_TYPE ( current_function_decl ) ) ) ) incoming_stack_boundary = MIN_STACK_BOUNDARY ; if ( incoming_stack_boundary < crtl -> parm_stack_boundary ) incoming_stack_boundary = crtl -> parm_stack_boundary ; if ( incoming_stack_boundary > MAIN_STACK_BOUNDARY && DECL_NAME ( current_function_decl ) && MAIN_NAME_P ( DECL_NAME ( current_function_decl ) ) && DECL_FILE_SCOPE_P ( current_function_decl ) ) incoming_stack_boundary = MAIN_STACK_BOUNDARY ; return incoming_stack_boundary ; } </s>

Return minimum incoming stack alignment .


<s> int ix86_min_insn_size ( rtx_insn * insn ) { int l = 0 , len ; if ( ! INSN_P ( insn ) || ! active_insn_p ( insn ) ) return 0 ; if ( GET_CODE ( PATTERN ( insn ) ) == UNSPEC_VOLATILE && XINT ( PATTERN ( insn ) , 1 ) == UNSPECV_ALIGN ) return 0 ; if ( CALL_P ( insn ) && symbolic_reference_mentioned_p ( PATTERN ( insn ) ) && ! SIBLING_CALL_P ( insn ) ) return 5 ; len = get_attr_length ( insn ) ; if ( len <= 1 ) return 1 ; if ( ! JUMP_P ( insn ) ) { enum attr_type type = get_attr_type ( insn ) ; switch ( type ) { case TYPE_MULTI : if ( GET_CODE ( PATTERN ( insn ) ) == ASM_INPUT || asm_noperands ( PATTERN ( insn ) ) >= 0 ) return 0 ; break ; case TYPE_OTHER : case TYPE_FCMP : break ; default : return len ; } l = get_attr_length_address ( insn ) ; if ( l < 4 && symbolic_reference_mentioned_p ( PATTERN ( insn ) ) ) l = 4 ; } if ( l ) return 1 + l ; else return 2 ; } </s>

We do n't have exact information about the insn sizes , but we may assume quite safely that we are informed about all 1 byte insns and memory address sizes . This is enough to eliminate unnecessary padding in 99 % of cases .


<s> static bool ix86_modes_tieable_p ( machine_mode mode1 , machine_mode mode2 ) { if ( mode1 == mode2 ) return true ; if ( ix86_tieable_integer_mode_p ( mode1 ) && ix86_tieable_integer_mode_p ( mode2 ) ) return true ; if ( mode2 == XFmode ) return mode1 == SFmode || mode1 == DFmode ; if ( mode2 == DFmode ) return mode1 == SFmode ; if ( GET_MODE_SIZE ( mode2 ) == 64 && ix86_hard_regno_mode_ok ( FIRST_SSE_REG , mode2 ) ) return ( GET_MODE_SIZE ( mode1 ) == 64 && ix86_hard_regno_mode_ok ( FIRST_SSE_REG , mode1 ) ) ; if ( GET_MODE_SIZE ( mode2 ) == 32 && ix86_hard_regno_mode_ok ( FIRST_SSE_REG , mode2 ) ) return ( GET_MODE_SIZE ( mode1 ) == 32 && ix86_hard_regno_mode_ok ( FIRST_SSE_REG , mode1 ) ) ; if ( GET_MODE_SIZE ( mode2 ) == 16 && ix86_hard_regno_mode_ok ( FIRST_SSE_REG , mode2 ) ) return ( GET_MODE_SIZE ( mode1 ) == 16 && ix86_hard_regno_mode_ok ( FIRST_SSE_REG , mode1 ) ) ; if ( GET_MODE_SIZE ( mode2 ) == 8 && ix86_hard_regno_mode_ok ( FIRST_MMX_REG , mode2 ) ) return ( GET_MODE_SIZE ( mode1 ) == 8 && ix86_hard_regno_mode_ok ( FIRST_MMX_REG , mode1 ) ) ; return false ; } </s>

Return true if MODE1 is accessible in a register that can hold MODE2 without copying . That is , all register classes that can hold MODE2 can also hold MODE1 .


<s> static int ix86_mode_after ( int entity , int mode , rtx_insn * insn ) { switch ( entity ) { case X86_DIRFLAG : return mode ; case AVX_U128 : return ix86_avx_u128_mode_after ( mode , insn ) ; case I387_ROUNDEVEN : case I387_TRUNC : case I387_FLOOR : case I387_CEIL : return mode ; default : gcc_unreachable ( ) ; } } </s>

Return the mode that an insn results in .


<s> static int ix86_mode_entry ( int entity ) { switch ( entity ) { case X86_DIRFLAG : return ix86_dirflag_mode_entry ( ) ; case AVX_U128 : return ix86_avx_u128_mode_entry ( ) ; case I387_ROUNDEVEN : case I387_TRUNC : case I387_FLOOR : case I387_CEIL : return I387_CW_ANY ; default : gcc_unreachable ( ) ; } } </s>

Return a mode that ENTITY is assumed to be switched to at function entry .


<s> static int ix86_mode_exit ( int entity ) { switch ( entity ) { case X86_DIRFLAG : return X86_DIRFLAG_ANY ; case AVX_U128 : return ix86_avx_u128_mode_exit ( ) ; case I387_ROUNDEVEN : case I387_TRUNC : case I387_FLOOR : case I387_CEIL : return I387_CW_ANY ; default : gcc_unreachable ( ) ; } } </s>

Return a mode that ENTITY is assumed to be switched to at function exit .


<s> static int ix86_mode_needed ( int entity , rtx_insn * insn ) { switch ( entity ) { case X86_DIRFLAG : return ix86_dirflag_mode_needed ( insn ) ; case AVX_U128 : return ix86_avx_u128_mode_needed ( insn ) ; case I387_ROUNDEVEN : case I387_TRUNC : case I387_FLOOR : case I387_CEIL : return ix86_i387_mode_needed ( entity , insn ) ; default : gcc_unreachable ( ) ; } return 0 ; } </s>

Return needed mode for entity in optimize_mode_switching pass .


<s> static int ix86_multiplication_cost ( const struct processor_costs * cost , enum machine_mode mode ) { machine_mode inner_mode = mode ; if ( VECTOR_MODE_P ( mode ) ) inner_mode = GET_MODE_INNER ( mode ) ; if ( SSE_FLOAT_MODE_SSEMATH_OR_HF_P ( mode ) ) return inner_mode == DFmode ? cost -> mulsd : cost -> mulss ; else if ( X87_FLOAT_MODE_P ( mode ) ) return cost -> fmul ; else if ( FLOAT_MODE_P ( mode ) ) return ix86_vec_cost ( mode , inner_mode == DFmode ? cost -> mulsd : cost -> mulss ) ; else if ( GET_MODE_CLASS ( mode ) == MODE_VECTOR_INT ) { if ( TARGET_AVX512DQ ) return ix86_vec_cost ( mode , cost -> mulss ) ; if ( mode == V16QImode || mode == V32QImode ) { int extra = 11 ; if ( TARGET_XOP && mode == V16QImode ) extra = 5 ; else if ( TARGET_SSSE3 ) extra = 6 ; return ix86_vec_cost ( mode , cost -> mulss * 2 + cost -> sse_op * extra ) ; } else if ( mode == V2DImode || mode == V4DImode ) { if ( TARGET_XOP && mode == V2DImode ) return ix86_vec_cost ( mode , cost -> mulss * 2 + cost -> sse_op * 3 ) ; else return ix86_vec_cost ( mode , cost -> mulss * 3 + cost -> sse_op * 5 ) ; } else if ( mode == V4SImode && ! ( TARGET_SSE4_1 || TARGET_AVX ) ) return ix86_vec_cost ( mode , cost -> mulss * 2 + cost -> sse_op * 5 ) ; else return ix86_vec_cost ( mode , cost -> mulss ) ; } else return ( cost -> mult_init [ MODE_INDEX ( mode ) ] + cost -> mult_bit * 7 ) ; } </s>


<s> static bool ix86_must_pass_in_stack ( const function_arg_info & arg ) { if ( must_pass_in_stack_var_size_or_pad ( arg ) ) return true ; return ( ! TARGET_64BIT && arg . mode == TImode && arg . type && TREE_CODE ( arg . type ) != VECTOR_TYPE ) ; } </s>

Return if we do not know how to pass TYPE solely in registers .


<s> static bool ix86_noce_conversion_profitable_p ( rtx_insn * seq , struct noce_if_info * if_info ) { if ( TARGET_ONE_IF_CONV_INSN && if_info -> speed_p ) { int cmov_cnt = 0 ; for ( rtx_insn * insn = seq ; insn ; insn = NEXT_INSN ( insn ) ) { rtx set = single_set ( insn ) ; if ( ! set ) continue ; if ( GET_CODE ( SET_SRC ( set ) ) != IF_THEN_ELSE ) continue ; rtx src = SET_SRC ( set ) ; machine_mode mode = GET_MODE ( src ) ; if ( GET_MODE_CLASS ( mode ) != MODE_INT && GET_MODE_CLASS ( mode ) != MODE_FLOAT ) continue ; if ( ( ! REG_P ( XEXP ( src , 1 ) ) && ! MEM_P ( XEXP ( src , 1 ) ) ) || ( ! REG_P ( XEXP ( src , 2 ) ) && ! MEM_P ( XEXP ( src , 2 ) ) ) ) continue ; if ( ++ cmov_cnt > 1 ) return false ; } } return default_noce_conversion_profitable_p ( seq , if_info ) ; } </s>

Return true if SEQ is a good candidate as a replacement for the if-convertible sequence described in IF_INFO .


<s> static bool ix86_nopic_noplt_attribute_p ( rtx call_op ) { if ( flag_pic || ix86_cmodel == CM_LARGE || ! ( TARGET_64BIT || HAVE_AS_IX86_GOT32X ) || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF || SYMBOL_REF_LOCAL_P ( call_op ) ) return false ; tree symbol_decl = SYMBOL_REF_DECL ( call_op ) ; if ( ! flag_plt || ( symbol_decl != NULL_TREE && lookup_attribute ( "noplt" , DECL_ATTRIBUTES ( symbol_decl ) ) ) ) return true ; return false ; } </s>

Return true if the function being called was marked with attribute `` noplt '' or using -fno-plt and we are compiling for non-PIC and x86_64 . We need to handle the non-PIC case in the backend because there is no easy interface for the front-end to force non-PLT calls to use the GOT . This is currently used only with 64-bit ELF targets to call the function marked `` noplt '' indirectly .


<s> static int ix86_nsaved_regs ( void ) { int nregs = 0 ; int regno ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( GENERAL_REGNO_P ( regno ) && ix86_save_reg ( regno , true , true ) ) nregs ++ ; return nregs ; } </s>

Return number of registers to be saved on the stack .


<s> static int ix86_nsaved_sseregs ( void ) { int nregs = 0 ; int regno ; if ( ! TARGET_64BIT_MS_ABI ) return 0 ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( SSE_REGNO_P ( regno ) && ix86_save_reg ( regno , true , true ) ) nregs ++ ; return nregs ; } </s>


<s> static bool ix86_ok_to_clobber_flags ( rtx_insn * insn ) { basic_block bb = BLOCK_FOR_INSN ( insn ) ; df_ref use ; bitmap live ; while ( insn ) { if ( NONDEBUG_INSN_P ( insn ) ) { FOR_EACH_INSN_USE ( use , insn ) if ( DF_REF_REG_USE_P ( use ) && DF_REF_REGNO ( use ) == FLAGS_REG ) return false ; if ( insn_defines_reg ( FLAGS_REG , INVALID_REGNUM , insn ) ) return true ; } if ( insn == BB_END ( bb ) ) break ; insn = NEXT_INSN ( insn ) ; } live = df_get_live_out ( bb ) ; return ! REGNO_REG_SET_P ( live , FLAGS_REG ) ; } </s>

Return true if it is legal to clobber flags by INSN and false otherwise .


<s> bool ix86_operands_ok_for_move_multiple ( rtx * operands , bool load , machine_mode mode ) { HOST_WIDE_INT offval_1 , offval_2 , msize ; 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 ] ; } else { mem_1 = operands [ 0 ] ; mem_2 = operands [ 2 ] ; reg_1 = operands [ 1 ] ; reg_2 = operands [ 3 ] ; } gcc_assert ( REG_P ( reg_1 ) && REG_P ( reg_2 ) ) ; if ( REGNO ( reg_1 ) != REGNO ( reg_2 ) ) return false ; if ( ! extract_base_offset_in_addr ( mem_1 , & base_1 , & offset_1 ) ) return false ; if ( ! extract_base_offset_in_addr ( mem_2 , & base_2 , & offset_2 ) ) return false ; if ( ! rtx_equal_p ( base_1 , base_2 ) ) return false ; offval_1 = INTVAL ( offset_1 ) ; offval_2 = INTVAL ( offset_2 ) ; msize = GET_MODE_SIZE ( mode ) ; if ( offval_1 + msize != offval_2 ) return false ; return true ; } </s>

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


<s> static bool ix86_optab_supported_p ( int op , machine_mode mode1 , machine_mode , optimization_type opt_type ) { switch ( op ) { case asin_optab : case acos_optab : case log1p_optab : case exp_optab : case exp10_optab : case exp2_optab : case expm1_optab : case ldexp_optab : case scalb_optab : case round_optab : return opt_type == OPTIMIZE_FOR_SPEED ; case rint_optab : if ( SSE_FLOAT_MODE_P ( mode1 ) && TARGET_SSE_MATH && ! flag_trapping_math && ! TARGET_SSE4_1 && mode1 != HFmode ) return opt_type == OPTIMIZE_FOR_SPEED ; return true ; case floor_optab : case ceil_optab : case btrunc_optab : if ( ( ( SSE_FLOAT_MODE_P ( mode1 ) && TARGET_SSE_MATH && TARGET_SSE4_1 ) || mode1 == HFmode ) && ! flag_trapping_math ) return true ; return opt_type == OPTIMIZE_FOR_SPEED ; case rsqrt_optab : return opt_type == OPTIMIZE_FOR_SPEED && use_rsqrt_p ( mode1 ) ; default : return true ; } } </s>

Implement the TARGET_OPTAB_SUPPORTED_P hook .


Output the assembly for a call instruction .


<s>
const
char
*
ix86_output_function_return
(
bool
long_p
)
{
output_return_instrumentation
(
)
;
if
(
cfun
->
machine
->
function_return_type
!=
indirect_branch_keep
)
{
char
thunk_name
[
32
]
;
enum
indirect_thunk_prefix
need_prefix
=
indirect_thunk_need_prefix
(
current_output_insn
)
;
if
(
cfun
->
machine
->
function_return_type
!=
indirect_branch_thunk_inline
)
{
bool
need_thunk
=
(
cfun
->
machine
->
function_return_type
==
indirect_branch_thunk
)
;
indirect_thunk_name
(
thunk_name
,
INVALID_REGNUM
,
need_prefix
,
true
)
;
indirect_return_needed
|=
need_thunk
;
fprintf
(
asm_out_file
,
"\tjmp\t"
)
;
assemble_name
(
asm_out_file
,
thunk_name
)
;
putc
(
'\n'
,
asm_out_file
)
;
}
else
output_indirect_thunk
(
INVALID_REGNUM
)
;
return
""
;
}
output_asm_insn
(
long_p
"rep%; ret"
:
"ret"
,
nullptr
)
;
return
(
ix86_harden_sls
&
harden_sls_return
)
"int3"
:
""
;
}
</s>

Output function return . CALL_OP is the jump target . Add a REP prefix to RET if LONG_P is true and function return is kept .


<s> static void ix86_output_indirect_branch ( rtx call_op , const char * xasm , bool sibcall_p ) { if ( REG_P ( call_op ) ) ix86_output_indirect_branch_via_reg ( call_op , sibcall_p ) ; else ix86_output_indirect_branch_via_push ( call_op , xasm , sibcall_p ) ; } </s>

Output indirect branch via a call and return thunk . CALL_OP is the branch target . XASM is the assembly template for CALL_OP . Branch is a tail call if SIBCALL_P is true .


<s> static void ix86_output_indirect_branch_via_push ( rtx call_op , const char * xasm , bool sibcall_p ) { char thunk_name_buf [ 32 ] ; char * thunk_name ; char push_buf [ 64 ] ; enum indirect_thunk_prefix need_prefix = indirect_thunk_need_prefix ( current_output_insn ) ; int regno = - 1 ; if ( cfun -> machine -> indirect_branch_type != indirect_branch_thunk_inline ) { if ( cfun -> machine -> indirect_branch_type == indirect_branch_thunk ) indirect_thunk_needed = true ; indirect_thunk_name ( thunk_name_buf , regno , need_prefix , false ) ; thunk_name = thunk_name_buf ; } else thunk_name = NULL ; snprintf ( push_buf , sizeof ( push_buf ) , "push{%c}\t%s" , TARGET_64BIT ? 'q' : 'l' , xasm ) ; if ( sibcall_p ) { output_asm_insn ( push_buf , & call_op ) ; ix86_output_jmp_thunk_or_indirect ( thunk_name , regno ) ; } else { char indirectlabel1 [ 32 ] ; char indirectlabel2 [ 32 ] ; ASM_GENERATE_INTERNAL_LABEL ( indirectlabel1 , INDIRECT_LABEL , indirectlabelno ++ ) ; ASM_GENERATE_INTERNAL_LABEL ( indirectlabel2 , INDIRECT_LABEL , indirectlabelno ++ ) ; fputs ( "\tjmp\t" , asm_out_file ) ; assemble_name_raw ( asm_out_file , indirectlabel2 ) ; fputc ( '\n' , asm_out_file ) ; ASM_OUTPUT_INTERNAL_LABEL ( asm_out_file , indirectlabel1 ) ; if ( MEM_P ( call_op ) ) { struct ix86_address parts ; rtx addr = XEXP ( call_op , 0 ) ; if ( ix86_decompose_address ( addr , & parts ) && parts . base == stack_pointer_rtx ) { if ( parts . index ) { addr = gen_rtx_MULT ( Pmode , parts . index , GEN_INT ( parts . scale ) ) ; addr = gen_rtx_PLUS ( Pmode , stack_pointer_rtx , addr ) ; } else addr = stack_pointer_rtx ; rtx disp ; if ( parts . disp != NULL_RTX ) disp = plus_constant ( Pmode , parts . disp , UNITS_PER_WORD ) ; else disp = GEN_INT ( UNITS_PER_WORD ) ; addr = gen_rtx_PLUS ( Pmode , addr , disp ) ; call_op = gen_rtx_MEM ( GET_MODE ( call_op ) , addr ) ; } } output_asm_insn ( push_buf , & call_op ) ; ix86_output_jmp_thunk_or_indirect ( thunk_name , regno ) ; ASM_OUTPUT_INTERNAL_LABEL ( asm_out_file , indirectlabel2 ) ; fputs ( "\tcall\t" , asm_out_file ) ; assemble_name_raw ( asm_out_file , indirectlabel1 ) ; fputc ( '\n' , asm_out_file ) ; } } </s>

Output indirect branch via a call and return thunk . CALL_OP is the branch target . XASM is the assembly template for CALL_OP . Branch is a tail call if SIBCALL_P is true . A normal call is converted to : jmp L2 L1 : push CALL_OP jmp __x86_indirect_thunk L2 : call L1 and a tail call is converted to : push CALL_OP jmp __x86_indirect_thunk