<s> static rtx x86_this_parameter ( tree function ) { tree type = TREE_TYPE ( function ) ; if ( TARGET_64BIT ) { int n = aggregate_value_p ( TREE_TYPE ( type ) , type ) != 0 ; return gen_rtx_REG ( DImode , x86_64_int_parameter_registers [ n ] ) ; } if ( ix86_function_regparm ( type , function ) > 0 ) { tree parm ; parm = TYPE_ARG_TYPES ( type ) ; for ( ; parm ; parm = TREE_CHAIN ( parm ) ) if ( TREE_VALUE ( parm ) == void_type_node ) break ; if ( parm ) { int regno = 0 ; if ( lookup_attribute ( "fastcall" , TYPE_ATTRIBUTES ( type ) ) ) regno = 2 ; return gen_rtx_REG ( SImode , regno ) ; } } if ( aggregate_value_p ( TREE_TYPE ( type ) , type ) ) return gen_rtx_MEM ( SImode , plus_constant ( stack_pointer_rtx , 8 ) ) ; else return gen_rtx_MEM ( SImode , plus_constant ( stack_pointer_rtx , 4 ) ) ; } </s>

Returns an expression indicating where the this parameter is located on entry to the FUNCTION .


This adds a condition to the basic_block NEW_BB in function FUNCTION_DECL to return a pointer to VERSION_DECL if we are running on a machine that supports the index CLONE_ISA hardware architecture bits . This function will be called during version dispatch to decide which function version to execute . It returns the basic block at the end , to which more conditions can be added .


<s> static void add_insn_window ( rtx_insn * insn , dispatch_windows * window_list , int num_uops ) { int byte_len = min_insn_size ( insn ) ; int num_insn = window_list -> num_insn ; int imm_size ; sched_insn_info * window = window_list -> window ; enum dispatch_group group = get_insn_group ( insn ) ; enum insn_path path = get_insn_path ( insn ) ; int num_imm_operand ; int num_imm32_operand ; int num_imm64_operand ; if ( ! window_list -> violation && group != disp_cmp && ! fits_dispatch_window ( insn ) ) window_list -> violation = true ; imm_size = get_num_immediates ( insn , & num_imm_operand , & num_imm32_operand , & num_imm64_operand ) ; window [ num_insn ] . insn = insn ; window [ num_insn ] . byte_len = byte_len ; window [ num_insn ] . group = group ; window [ num_insn ] . path = path ; window [ num_insn ] . imm_bytes = imm_size ; window_list -> window_size += byte_len ; window_list -> num_insn = num_insn + 1 ; window_list -> num_uops = window_list -> num_uops + num_uops ; window_list -> imm_size += imm_size ; window_list -> num_imm += num_imm_operand ; window_list -> num_imm_32 += num_imm32_operand ; window_list -> num_imm_64 += num_imm64_operand ; if ( group == disp_store ) window_list -> num_stores += 1 ; else if ( group == disp_load || group == disp_prefetch ) window_list -> num_loads += 1 ; else if ( group == disp_load_store ) { window_list -> num_stores += 1 ; window_list -> num_loads += 1 ; } } </s>

Add an instruction INSN with NUM_UOPS micro-operations to the dispatch window WINDOW_LIST .


<s> static void add_to_dispatch_window ( rtx_insn * insn ) { int byte_len ; dispatch_windows * window_list ; dispatch_windows * next_list ; dispatch_windows * window0_list ; enum insn_path path ; enum dispatch_group insn_group ; bool insn_fits ; int num_insn ; int num_uops ; int window_num ; int insn_num_uops ; int sum ; if ( INSN_CODE ( insn ) < 0 ) return ; byte_len = min_insn_size ( insn ) ; window_list = dispatch_window_list ; next_list = window_list -> next ; path = get_insn_path ( insn ) ; insn_group = get_insn_group ( insn ) ; if ( next_list ) window_list = dispatch_window_list -> next ; if ( path == path_single ) insn_num_uops = 1 ; else if ( path == path_double ) insn_num_uops = 2 ; else insn_num_uops = ( int ) path ; num_insn = window_list -> num_insn ; num_uops = window_list -> num_uops ; window_num = window_list -> window_num ; insn_fits = fits_dispatch_window ( insn ) ; if ( num_insn >= MAX_INSN || num_uops + insn_num_uops > MAX_INSN || ! ( insn_fits ) ) { window_num = ~ window_num & 1 ; window_list = allocate_next_window ( window_num ) ; } if ( window_num == 0 ) { add_insn_window ( insn , window_list , insn_num_uops ) ; if ( window_list -> num_insn >= MAX_INSN && insn_group == disp_branch ) { process_end_window ( ) ; return ; } } else if ( window_num == 1 ) { window0_list = window_list -> prev ; sum = window0_list -> window_size + window_list -> window_size ; if ( sum == 32 || ( byte_len + sum ) >= 48 ) { process_end_window ( ) ; window_list = dispatch_window_list ; } add_insn_window ( insn , window_list , insn_num_uops ) ; } else gcc_unreachable ( ) ; if ( is_end_basic_block ( insn_group ) ) { process_end_window ( ) ; return ; } } </s>

Adds a scheduled instruction , INSN , to the current dispatch window . If the total bytes of instructions or the number of instructions in the window exceed allowable , it allocates a new window .


<s> static bool alg_usable_p ( enum stringop_alg alg , bool memset ) { if ( alg == no_stringop ) return false ; if ( alg == vector_loop ) return TARGET_SSE || TARGET_AVX ; if ( alg == rep_prefix_1_byte || alg == rep_prefix_4_byte || alg == rep_prefix_8_byte ) return ! ( fixed_regs [ CX_REG ] || fixed_regs [ DI_REG ] || ( memset ? fixed_regs [ AX_REG ] : fixed_regs [ SI_REG ] ) ) ; return true ; } </s>

Return true if ALG can be used in current context . Assume we expand memset if MEMSET is true .


<s> static dispatch_windows * allocate_next_window ( int window_num ) { if ( window_num == 0 ) { if ( dispatch_window_list -> next ) init_window ( 1 ) ; init_window ( 0 ) ; return dispatch_window_list ; } dispatch_window_list -> next = dispatch_window_list1 ; dispatch_window_list1 -> prev = dispatch_window_list ; return dispatch_window_list1 ; } </s>

Allocates a new dispatch window and adds it to WINDOW_LIST . WINDOW_NUM is either 0 or 1 . A maximum of two windows are generated for 48 bytes of instructions . Note that these windows are not dispatch windows that their sizes are DISPATCH_WINDOW_SIZE .


<s> static dispatch_windows * allocate_window ( void ) { dispatch_windows * new_list = XNEW ( struct dispatch_windows_s ) ; new_list -> window = XNEWVEC ( struct sched_insn_info_s , MAX_INSN + 1 ) ; return new_list ; } </s>

This function allocates and initializes a dispatch window and the list container holding a pointer to the window .


<s> static int attr_strcmp ( const void * v1 , const void * v2 ) { const char * c1 = * ( char * const * ) v1 ; const char * c2 = * ( char * const * ) v2 ; return strcmp ( c1 , c2 ) ; } </s>

Comparator function to be used in qsort routine to sort attribute specification strings to `` target '' .


<s> static void avoid_func_arg_motion ( rtx_insn * first_arg , rtx_insn * insn ) { rtx set ; rtx tmp ; if ( INSN_P ( insn ) && GET_CODE ( PATTERN ( insn ) ) == PARALLEL && GET_CODE ( XVECEXP ( PATTERN ( insn ) , 0 , 0 ) ) == UNSPEC && XINT ( XVECEXP ( PATTERN ( insn ) , 0 , 0 ) , 1 ) == UNSPEC_BNDSTX ) { add_dependence ( first_arg , insn , REG_DEP_ANTI ) ; return ; } set = single_set ( insn ) ; if ( ! set ) return ; tmp = SET_DEST ( set ) ; if ( REG_P ( tmp ) ) { add_dependence ( first_arg , insn , REG_DEP_OUTPUT ) ; return ; } add_dependence ( first_arg , insn , REG_DEP_ANTI ) ; } </s>

Add output or anti dependency from insn to first_arg to restrict its code motion .


<s> int avx_vpermilp_parallel ( rtx par , machine_mode mode ) { unsigned i , nelt = GET_MODE_NUNITS ( mode ) ; unsigned mask = 0 ; unsigned char ipar [ 16 ] = { } ; if ( XVECLEN ( par , 0 ) != ( int ) nelt ) return 0 ; for ( i = 0 ; i < nelt ; ++ i ) { rtx er = XVECEXP ( par , 0 , i ) ; unsigned HOST_WIDE_INT ei ; if ( ! CONST_INT_P ( er ) ) return 0 ; ei = INTVAL ( er ) ; if ( ei >= nelt ) return 0 ; ipar [ i ] = ei ; } switch ( mode ) { case V8DFmode : for ( i = 4 ; i < 6 ; ++ i ) { if ( ipar [ i ] < 4 || ipar [ i ] >= 6 ) return 0 ; mask |= ( ipar [ i ] - 4 ) << i ; } for ( i = 6 ; i < 8 ; ++ i ) { if ( ipar [ i ] < 6 ) return 0 ; mask |= ( ipar [ i ] - 6 ) << i ; } case V4DFmode : for ( i = 0 ; i < 2 ; ++ i ) { if ( ipar [ i ] >= 2 ) return 0 ; mask |= ipar [ i ] << i ; } for ( i = 2 ; i < 4 ; ++ i ) { if ( ipar [ i ] < 2 ) return 0 ; mask |= ( ipar [ i ] - 2 ) << i ; } break ; case V16SFmode : for ( i = 0 ; i < 8 ; ++ i ) if ( ipar [ i ] + 8 != ipar [ i + 8 ] ) return 0 ; case V8SFmode : for ( i = 0 ; i < 4 ; ++ i ) if ( ipar [ i ] + 4 != ipar [ i + 4 ] ) return 0 ; nelt = 4 ; case V2DFmode : case V4SFmode : for ( i = 0 ; i < nelt ; ++ i ) mask |= ipar [ i ] << ( i * ( nelt / 2 ) ) ; break ; default : gcc_unreachable ( ) ; } return mask + 1 ; } </s>

Helper for avx_vpermilps256_operand et al . This is also used by the expansion functions to turn the parallel back into a mask . The return value is 0 for no match and the imm8+1 for a match .


<s> static rtx choose_baseaddr ( HOST_WIDE_INT cfa_offset ) { const struct machine_function * m = cfun -> machine ; rtx base_reg = NULL ; HOST_WIDE_INT base_offset = 0 ; if ( m -> use_fast_prologue_epilogue ) { if ( m -> fs . fp_valid ) { base_reg = hard_frame_pointer_rtx ; base_offset = m -> fs . fp_offset - cfa_offset ; } else if ( m -> fs . drap_valid ) { base_reg = crtl -> drap_reg ; base_offset = 0 - cfa_offset ; } else if ( m -> fs . sp_valid ) { base_reg = stack_pointer_rtx ; base_offset = m -> fs . sp_offset - cfa_offset ; } } else { HOST_WIDE_INT toffset ; int len = 16 , tlen ; if ( m -> fs . sp_valid ) { base_reg = stack_pointer_rtx ; base_offset = m -> fs . sp_offset - cfa_offset ; len = choose_baseaddr_len ( STACK_POINTER_REGNUM , base_offset ) ; } if ( m -> fs . drap_valid ) { toffset = 0 - cfa_offset ; tlen = choose_baseaddr_len ( REGNO ( crtl -> drap_reg ) , toffset ) ; if ( tlen <= len ) { base_reg = crtl -> drap_reg ; base_offset = toffset ; len = tlen ; } } if ( m -> fs . fp_valid ) { toffset = m -> fs . fp_offset - cfa_offset ; tlen = choose_baseaddr_len ( HARD_FRAME_POINTER_REGNUM , toffset ) ; if ( tlen <= len ) { base_reg = hard_frame_pointer_rtx ; base_offset = toffset ; len = tlen ; } } } gcc_assert ( base_reg != NULL ) ; return plus_constant ( Pmode , base_reg , base_offset ) ; } </s>

Return an RTX that points to CFA_OFFSET within the stack frame . The valid base registers are taken from CFUN- > MACHINE- > FS .


<s> static rtx construct_plt_address ( rtx symbol ) { rtx tmp , unspec ; gcc_assert ( GET_CODE ( symbol ) == SYMBOL_REF ) ; gcc_assert ( ix86_cmodel == CM_LARGE_PIC && ! TARGET_PECOFF ) ; gcc_assert ( Pmode == DImode ) ; tmp = gen_reg_rtx ( Pmode ) ; unspec = gen_rtx_UNSPEC ( Pmode , gen_rtvec ( 1 , symbol ) , UNSPEC_PLTOFF ) ; emit_move_insn ( tmp , gen_rtx_CONST ( Pmode , unspec ) ) ; emit_insn ( ix86_gen_add3 ( tmp , tmp , pic_offset_table_rtx ) ) ; return tmp ; } </s>

For given symbol ( function ) construct code to compute address of it 's PLT entry in large x86-64 PIC model .


<s> static void core2i7_dfa_post_advance_cycle ( void ) { ix86_first_cycle_multipass_data_t data = ix86_first_cycle_multipass_data ; gcc_assert ( data -> ifetch_block_n_insns <= core2i7_ifetch_block_max_insns ) ; data -> ifetch_block_len = 0 ; data -> ifetch_block_n_insns = 0 ; } </s>

Advancing the cycle ; reset ifetch block counts .


<s> static void core2i7_first_cycle_multipass_backtrack ( const void * _data , signed char * ready_try , int n_ready ATTRIBUTE_UNUSED ) { const_ix86_first_cycle_multipass_data_t data = ( const_ix86_first_cycle_multipass_data_t ) _data ; unsigned int i = 0 ; sbitmap_iterator sbi ; gcc_assert ( bitmap_last_set_bit ( data -> ready_try_change ) < n_ready ) ; EXECUTE_IF_SET_IN_BITMAP ( data -> ready_try_change , 0 , i , sbi ) { ready_try [ i ] = 0 ; } } </s>


Prepare for a new round of multipass lookahead scheduling .


<s> static void core2i7_first_cycle_multipass_end ( const void * _data ) { const_ix86_first_cycle_multipass_data_t data = ( const_ix86_first_cycle_multipass_data_t ) _data ; ix86_first_cycle_multipass_data_t next_data = ix86_first_cycle_multipass_data ; if ( data != NULL ) { next_data -> ifetch_block_len = data -> ifetch_block_len ; next_data -> ifetch_block_n_insns = data -> ifetch_block_n_insns ; } } </s>

Save the result of multipass lookahead scheduling for the next round .


<s> static void core2i7_first_cycle_multipass_fini ( void * _data ) { ix86_first_cycle_multipass_data_t data = ( ix86_first_cycle_multipass_data_t ) _data ; if ( data -> ready_try_change ) { sbitmap_free ( data -> ready_try_change ) ; data -> ready_try_change = NULL ; data -> ready_try_change_size = 0 ; } } </s>


<s> static void core2i7_first_cycle_multipass_init ( void * _data ) { ix86_first_cycle_multipass_data_t data = ( ix86_first_cycle_multipass_data_t ) _data ; data -> ifetch_block_len = 0 ; data -> ifetch_block_n_insns = 0 ; data -> ready_try_change = NULL ; data -> ready_try_change_size = 0 ; } </s>


INSN is being issued in current solution . Account for its impact on the decoder model .


Count number of GROUP restricted instructions in a dispatch window WINDOW_LIST .


<s> DEBUG_FUNCTION void debug_dispatch_window ( int window_num ) { debug_dispatch_window_file ( stdout , window_num ) ; } </s>


"  num_insn = %d, num_uops = %d, window_size = %d\n"

"  num_imm = %d, num_imm_32 = %d, num_imm_64 = %d, imm_size = %d\n"

"    group[%d] = %s, insn[%d] = %p, path[%d] = %d byte_len[%d] = %d, imm_bytes[%d] = %d\n"

Print the dispatch window , WINDOW_NUM , to FILE .


"  group = %s, path = %d, byte_len = %d\n"

Print INSN dispatch information to FILE .


<s>
DEBUG_FUNCTION
void
debug_ready_dispatch
(
void
)
{
int
i
;
int
no_ready
=
number_in_ready
(
)
;
fprintf
(
stdout
,
"Number of ready: %d\n"
,
no_ready
)
;
for
(
i
=
0
;
i
<
no_ready
;
i
++
)
debug_insn_dispatch_info_file
(
stdout
,
get_ready_element
(
i
)
)
;
}
</s>

Print to STDERR the status of the ready list with respect to dispatch windows .


<s> static inline tree def_builtin ( HOST_WIDE_INT mask , const char * name , enum ix86_builtin_func_type tcode , enum ix86_builtins code ) { tree decl = NULL_TREE ; if ( ! ( mask & OPTION_MASK_ISA_64BIT ) || TARGET_64BIT ) { ix86_builtins_isa [ ( int ) code ] . isa = mask ; mask &= ~ OPTION_MASK_ISA_64BIT ; if ( mask == 0 || ( mask & ix86_isa_flags ) != 0 || ( lang_hooks . builtin_function == lang_hooks . builtin_function_ext_scope ) ) { tree type = ix86_get_builtin_func_type ( tcode ) ; decl = add_builtin_function ( name , type , code , BUILT_IN_MD , NULL , NULL_TREE ) ; ix86_builtins [ ( int ) code ] = decl ; ix86_builtins_isa [ ( int ) code ] . set_and_not_built_p = false ; } else { deferred_isa_values |= mask ; ix86_builtins [ ( int ) code ] = NULL_TREE ; ix86_builtins_isa [ ( int ) code ] . tcode = tcode ; ix86_builtins_isa [ ( int ) code ] . name = name ; ix86_builtins_isa [ ( int ) code ] . leaf_p = false ; ix86_builtins_isa [ ( int ) code ] . nothrow_p = false ; ix86_builtins_isa [ ( int ) code ] . const_p = false ; ix86_builtins_isa [ ( int ) code ] . set_and_not_built_p = true ; } } return decl ; } </s>

Add a SPARC builtin function with NAME , ICODE , CODE and TYPE . Return the function decl or NULL_TREE if the builtin was not added .


<s> static inline tree def_builtin_const ( HOST_WIDE_INT mask , const char * name , enum ix86_builtin_func_type tcode , enum ix86_builtins code ) { tree decl = def_builtin ( mask , name , tcode , code ) ; if ( decl ) TREE_READONLY ( decl ) = 1 ; else ix86_builtins_isa [ ( int ) code ] . const_p = true ; return decl ; } </s>

Likewise , but also marks the function as `` const '' .


<s> static int dispatch_function_versions ( tree dispatch_decl , void * fndecls_p , basic_block * empty_bb ) { tree default_decl ; gimple ifunc_cpu_init_stmt ; gimple_seq gseq ; int ix ; tree ele ; vec < tree > * fndecls ; unsigned int num_versions = 0 ; unsigned int actual_versions = 0 ; unsigned int i ; struct _function_version_info { tree version_decl ; tree predicate_chain ; unsigned int dispatch_priority ; } * function_version_info ; gcc_assert ( dispatch_decl != NULL && fndecls_p != NULL && empty_bb != NULL ) ; fndecls = static_cast < vec < tree > * > ( fndecls_p ) ; num_versions = fndecls -> length ( ) ; gcc_assert ( num_versions >= 2 ) ; function_version_info = ( struct _function_version_info * ) XNEWVEC ( struct _function_version_info , ( num_versions - 1 ) ) ; default_decl = ( * fndecls ) [ 0 ] ; push_cfun ( DECL_STRUCT_FUNCTION ( dispatch_decl ) ) ; gseq = bb_seq ( * empty_bb ) ; ifunc_cpu_init_stmt = gimple_build_call_vec ( ix86_builtins [ ( int ) IX86_BUILTIN_CPU_INIT ] , vNULL ) ; gimple_seq_add_stmt ( & gseq , ifunc_cpu_init_stmt ) ; gimple_set_bb ( ifunc_cpu_init_stmt , * empty_bb ) ; set_bb_seq ( * empty_bb , gseq ) ; pop_cfun ( ) ; for ( ix = 1 ; fndecls -> iterate ( ix , & ele ) ; ++ ix ) { tree version_decl = ele ; tree predicate_chain = NULL_TREE ; unsigned int priority ; priority = get_builtin_code_for_version ( version_decl , & predicate_chain ) ; if ( predicate_chain == NULL_TREE ) continue ; function_version_info [ actual_versions ] . version_decl = version_decl ; function_version_info [ actual_versions ] . predicate_chain = predicate_chain ; function_version_info [ actual_versions ] . dispatch_priority = priority ; actual_versions ++ ; } qsort ( function_version_info , actual_versions , sizeof ( struct _function_version_info ) , feature_compare ) ; for ( i = 0 ; i < actual_versions ; ++ i ) * empty_bb = add_condition_to_bb ( dispatch_decl , function_version_info [ i ] . version_decl , function_version_info [ i ] . predicate_chain , * empty_bb ) ; * empty_bb = add_condition_to_bb ( dispatch_decl , default_decl , NULL , * empty_bb ) ; free ( function_version_info ) ; return 0 ; } </s>

This function generates the dispatch function for multi-versioned functions . DISPATCH_DECL is the function which will contain the dispatch logic . FNDECLS are the function choices for dispatch , and is a tree chain . EMPTY_BB is the basic block pointer in DISPATCH_DECL in which the dispatch code is generated .


<s> static bool dispatch_violation ( void ) { if ( dispatch_window_list -> next ) return dispatch_window_list -> next -> violation ; return dispatch_window_list -> violation ; } </s>

Return true if a dispatch violation encountered .


<s> static void do_dispatch ( rtx_insn * insn , int mode ) { if ( mode == DISPATCH_INIT ) init_dispatch_sched ( ) ; else if ( mode == ADD_TO_DISPATCH_WINDOW ) add_to_dispatch_window ( insn ) ; } </s>

This routine is the driver of the dispatch scheduler .


<s> static int do_reorder_for_imul ( rtx_insn * * ready , int n_ready ) { rtx_insn * insn ; rtx set , insn1 , insn2 ; sd_iterator_def sd_it ; dep_t dep ; int index = - 1 ; int i ; if ( ! TARGET_BONNELL ) return index ; insn = ready [ n_ready - 1 ] ; set = single_set ( insn ) ; if ( ! set ) return index ; if ( ! ( GET_CODE ( SET_SRC ( set ) ) == MULT && GET_MODE ( SET_SRC ( set ) ) == SImode ) ) return index ; for ( i = n_ready - 2 ; i >= 0 ; i -- ) { insn = ready [ i ] ; if ( ! NONDEBUG_INSN_P ( insn ) ) continue ; insn2 = PATTERN ( insn ) ; if ( GET_CODE ( insn2 ) == PARALLEL ) insn2 = XVECEXP ( insn2 , 0 , 0 ) ; if ( GET_CODE ( insn2 ) == SET && GET_CODE ( SET_SRC ( insn2 ) ) == MULT && GET_MODE ( SET_SRC ( insn2 ) ) == SImode ) continue ; FOR_EACH_DEP ( insn , SD_LIST_FORW , sd_it , dep ) { rtx con ; con = DEP_CON ( dep ) ; if ( ! NONDEBUG_INSN_P ( con ) ) continue ; insn1 = PATTERN ( con ) ; if ( GET_CODE ( insn1 ) == PARALLEL ) insn1 = XVECEXP ( insn1 , 0 , 0 ) ; if ( GET_CODE ( insn1 ) == SET && GET_CODE ( SET_SRC ( insn1 ) ) == MULT && GET_MODE ( SET_SRC ( insn1 ) ) == SImode ) { sd_iterator_def sd_it1 ; dep_t dep1 ; index = i ; FOR_EACH_DEP ( con , SD_LIST_BACK , sd_it1 , dep1 ) { rtx pro ; pro = DEP_PRO ( dep1 ) ; if ( ! NONDEBUG_INSN_P ( pro ) ) continue ; if ( pro != insn ) index = - 1 ; } if ( index >= 0 ) break ; } } if ( index >= 0 ) break ; } return index ; } </s>

Try to reorder ready list to take advantage of Atom pipelined IMUL execution . It is applied if ( 1 ) IMUL instruction is on the top of list ; ( 2 ) There exists the only producer of independent IMUL instruction in ready list . Return index of IMUL producer if it was found and -1 otherwise .


<s> static rtx emit_memmov ( rtx destmem , rtx * srcmem , rtx destptr , rtx srcptr , HOST_WIDE_INT size_to_move ) { rtx dst = destmem , src = * srcmem , adjust , tempreg ; enum insn_code code ; machine_mode move_mode ; int piece_size , i ; piece_size = 1 << floor_log2 ( size_to_move ) ; move_mode = mode_for_size ( piece_size * BITS_PER_UNIT , MODE_INT , 0 ) ; code = optab_handler ( mov_optab , move_mode ) ; while ( code == CODE_FOR_nothing && piece_size > 1 ) { piece_size >>= 1 ; move_mode = mode_for_size ( piece_size * BITS_PER_UNIT , MODE_INT , 0 ) ; code = optab_handler ( mov_optab , move_mode ) ; } if ( GET_MODE_SIZE ( move_mode ) > GET_MODE_SIZE ( word_mode ) ) { int nunits = GET_MODE_SIZE ( move_mode ) / GET_MODE_SIZE ( word_mode ) ; move_mode = mode_for_vector ( word_mode , nunits ) ; code = optab_handler ( mov_optab , move_mode ) ; if ( code == CODE_FOR_nothing ) { move_mode = word_mode ; piece_size = GET_MODE_SIZE ( move_mode ) ; code = optab_handler ( mov_optab , move_mode ) ; } } gcc_assert ( code != CODE_FOR_nothing ) ; dst = adjust_automodify_address_nv ( dst , move_mode , destptr , 0 ) ; src = adjust_automodify_address_nv ( src , move_mode , srcptr , 0 ) ; gcc_assert ( size_to_move % piece_size == 0 ) ; adjust = GEN_INT ( piece_size ) ; for ( i = 0 ; i < size_to_move ; i += piece_size ) { tempreg = gen_reg_rtx ( move_mode ) ; emit_insn ( GEN_FCN ( code ) ( tempreg , src ) ) ; emit_insn ( GEN_FCN ( code ) ( dst , tempreg ) ) ; emit_move_insn ( destptr , gen_rtx_PLUS ( Pmode , copy_rtx ( destptr ) , adjust ) ) ; emit_move_insn ( srcptr , gen_rtx_PLUS ( Pmode , copy_rtx ( srcptr ) , adjust ) ) ; dst = adjust_automodify_address_nv ( dst , move_mode , destptr , piece_size ) ; src = adjust_automodify_address_nv ( src , move_mode , srcptr , piece_size ) ; } * srcmem = src ; return dst ; } </s>

This function emits moves to copy SIZE_TO_MOVE bytes from SRCMEM to DESTMEM . SRC is passed by pointer to be updated on return . Return value is updated DST .


<s> static rtx emit_memset ( rtx destmem , rtx destptr , rtx promoted_val , HOST_WIDE_INT size_to_move ) { rtx dst = destmem , adjust ; enum insn_code code ; machine_mode move_mode ; int piece_size , i ; move_mode = GET_MODE ( promoted_val ) ; if ( move_mode == VOIDmode ) move_mode = QImode ; if ( size_to_move < GET_MODE_SIZE ( move_mode ) ) { move_mode = mode_for_size ( size_to_move * BITS_PER_UNIT , MODE_INT , 0 ) ; promoted_val = gen_lowpart ( move_mode , promoted_val ) ; } piece_size = GET_MODE_SIZE ( move_mode ) ; code = optab_handler ( mov_optab , move_mode ) ; gcc_assert ( code != CODE_FOR_nothing && promoted_val != NULL_RTX ) ; dst = adjust_automodify_address_nv ( dst , move_mode , destptr , 0 ) ; gcc_assert ( size_to_move % piece_size == 0 ) ; adjust = GEN_INT ( piece_size ) ; for ( i = 0 ; i < size_to_move ; i += piece_size ) { if ( piece_size <= GET_MODE_SIZE ( word_mode ) ) { emit_insn ( gen_strset ( destptr , dst , promoted_val ) ) ; dst = adjust_automodify_address_nv ( dst , move_mode , destptr , piece_size ) ; continue ; } emit_insn ( GEN_FCN ( code ) ( dst , promoted_val ) ) ; emit_move_insn ( destptr , gen_rtx_PLUS ( Pmode , copy_rtx ( destptr ) , adjust ) ) ; dst = adjust_automodify_address_nv ( dst , move_mode , destptr , piece_size ) ; } return dst ; } </s>

This function emits moves to fill SIZE_TO_MOVE bytes starting from DESTMEM with value PROMOTED_VAL . SRC is passed by pointer to be updated on return . Return value is updated DST .


<s> static bool exact_dependency_1 ( rtx addr , rtx insn ) { enum rtx_code code ; const char * format_ptr ; int i , j ; code = GET_CODE ( insn ) ; switch ( code ) { case MEM : if ( rtx_equal_p ( addr , insn ) ) return true ; break ; case REG : CASE_CONST_ANY : case SYMBOL_REF : case CODE_LABEL : case PC : case CC0 : case EXPR_LIST : return false ; default : break ; } format_ptr = GET_RTX_FORMAT ( code ) ; for ( i = 0 ; i < GET_RTX_LENGTH ( code ) ; i ++ ) { switch ( * format_ptr ++ ) { case 'e' : if ( exact_dependency_1 ( addr , XEXP ( insn , i ) ) ) return true ; break ; case 'E' : for ( j = 0 ; j < XVECLEN ( insn , i ) ; j ++ ) if ( exact_dependency_1 ( addr , XVECEXP ( insn , i , j ) ) ) return true ; break ; } } return false ; } </s>

Helper function for exact_store_load_dependency . Return true if addr is found in insn .


<s> static bool exact_store_load_dependency ( rtx_insn * store , rtx_insn * load ) { rtx set1 , set2 ; set1 = single_set ( store ) ; if ( ! set1 ) return false ; if ( ! MEM_P ( SET_DEST ( set1 ) ) ) return false ; set2 = single_set ( load ) ; if ( ! set2 ) return false ; if ( exact_dependency_1 ( SET_DEST ( set1 ) , SET_SRC ( set2 ) ) ) return true ; return false ; } </s>

Return true if there exists exact dependency for store & load , i.e . the same memory address is used in them .


<s> static void expand_setmem_epilogue_via_loop ( rtx destmem , rtx destptr , rtx value , rtx count , int max_size ) { count = expand_simple_binop ( counter_mode ( count ) , AND , count , GEN_INT ( max_size - 1 ) , count , 1 , OPTAB_DIRECT ) ; expand_set_or_movmem_via_loop ( destmem , NULL , destptr , NULL , gen_lowpart ( QImode , value ) , count , QImode , 1 , max_size / 2 , true ) ; } </s>

Output code to set at most count & ( max_size - 1 ) bytes starting by DEST .


<s> static rtx expand_set_or_movmem_constant_prologue ( rtx dst , rtx * srcp , rtx destreg , rtx srcreg , rtx value , rtx vec_value , int desired_align , int align_bytes , bool issetmem ) { rtx src = NULL ; rtx orig_dst = dst ; rtx orig_src = NULL ; int piece_size = 1 ; int copied_bytes = 0 ; if ( ! issetmem ) { gcc_assert ( srcp != NULL ) ; src = * srcp ; orig_src = src ; } for ( piece_size = 1 ; piece_size <= desired_align && copied_bytes < align_bytes ; piece_size <<= 1 ) { if ( align_bytes & piece_size ) { if ( issetmem ) { if ( vec_value && piece_size > GET_MODE_SIZE ( GET_MODE ( value ) ) ) dst = emit_memset ( dst , destreg , vec_value , piece_size ) ; else dst = emit_memset ( dst , destreg , value , piece_size ) ; } else dst = emit_memmov ( dst , & src , destreg , srcreg , piece_size ) ; copied_bytes += piece_size ; } } if ( MEM_ALIGN ( dst ) < ( unsigned int ) desired_align * BITS_PER_UNIT ) set_mem_align ( dst , desired_align * BITS_PER_UNIT ) ; if ( MEM_SIZE_KNOWN_P ( orig_dst ) ) set_mem_size ( dst , MEM_SIZE ( orig_dst ) - align_bytes ) ; if ( ! issetmem ) { int src_align_bytes = get_mem_align_offset ( src , desired_align * BITS_PER_UNIT ) ; if ( src_align_bytes >= 0 ) src_align_bytes = desired_align - src_align_bytes ; if ( src_align_bytes >= 0 ) { unsigned int src_align ; for ( src_align = desired_align ; src_align >= 2 ; src_align >>= 1 ) { if ( ( src_align_bytes & ( src_align - 1 ) ) == ( align_bytes & ( src_align - 1 ) ) ) break ; } if ( src_align > ( unsigned int ) desired_align ) src_align = desired_align ; if ( MEM_ALIGN ( src ) < src_align * BITS_PER_UNIT ) set_mem_align ( src , src_align * BITS_PER_UNIT ) ; } if ( MEM_SIZE_KNOWN_P ( orig_src ) ) set_mem_size ( src , MEM_SIZE ( orig_src ) - align_bytes ) ; * srcp = src ; } return dst ; } </s>

This function is like the previous one , except here we know how many bytes need to be copied . That allows us to update alignment not only of DST , which is returned , but also of SRC , which is passed as a pointer for that reason .


<s> static rtx expand_set_or_movmem_prologue ( rtx destmem , rtx srcmem , rtx destptr , rtx srcptr , rtx value , rtx vec_value , rtx count , int align , int desired_alignment , bool issetmem ) { int i ; for ( i = 1 ; i < desired_alignment ; i <<= 1 ) { if ( align <= i ) { rtx_code_label * label = ix86_expand_aligntest ( destptr , i , false ) ; if ( issetmem ) { if ( vec_value && i > GET_MODE_SIZE ( GET_MODE ( value ) ) ) destmem = emit_memset ( destmem , destptr , vec_value , i ) ; else destmem = emit_memset ( destmem , destptr , value , i ) ; } else destmem = emit_memmov ( destmem , & srcmem , destptr , srcptr , i ) ; ix86_adjust_counter ( count , i ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; set_mem_align ( destmem , i * 2 * BITS_PER_UNIT ) ; } } return destmem ; } </s>

Depending on ISSETMEM , copy enough from SRCMEM to DESTMEM or set enough to DESTMEM to align it to DESIRED_ALIGNMENT . Original alignment is ALIGN . Depending on ISSETMEM , either arguments SRCMEM/SRCPTR or VALUE/VEC_VALUE are ignored . Return value is updated DESTMEM .


<s> static void expand_set_or_movmem_via_rep ( rtx destmem , rtx srcmem , rtx destptr , rtx srcptr , rtx value , rtx orig_value , rtx count , machine_mode mode , bool issetmem ) { rtx destexp ; rtx srcexp ; rtx countreg ; HOST_WIDE_INT rounded_count ; if ( mode == QImode && CONST_INT_P ( count ) && ! ( INTVAL ( count ) & 3 ) && ( ! issetmem || orig_value == const0_rtx ) ) mode = SImode ; if ( destptr != XEXP ( destmem , 0 ) || GET_MODE ( destmem ) != BLKmode ) destmem = adjust_automodify_address_nv ( destmem , BLKmode , destptr , 0 ) ; countreg = ix86_zero_extend_to_Pmode ( scale_counter ( count , GET_MODE_SIZE ( mode ) ) ) ; if ( mode != QImode ) { destexp = gen_rtx_ASHIFT ( Pmode , countreg , GEN_INT ( exact_log2 ( GET_MODE_SIZE ( mode ) ) ) ) ; destexp = gen_rtx_PLUS ( Pmode , destexp , destptr ) ; } else destexp = gen_rtx_PLUS ( Pmode , destptr , countreg ) ; if ( ( ! issetmem || orig_value == const0_rtx ) && CONST_INT_P ( count ) ) { rounded_count = ( INTVAL ( count ) & ~ ( ( HOST_WIDE_INT ) GET_MODE_SIZE ( mode ) - 1 ) ) ; destmem = shallow_copy_rtx ( destmem ) ; set_mem_size ( destmem , rounded_count ) ; } else if ( MEM_SIZE_KNOWN_P ( destmem ) ) clear_mem_size ( destmem ) ; if ( issetmem ) { value = force_reg ( mode , gen_lowpart ( mode , value ) ) ; emit_insn ( gen_rep_stos ( destptr , countreg , destmem , value , destexp ) ) ; } else { if ( srcptr != XEXP ( srcmem , 0 ) || GET_MODE ( srcmem ) != BLKmode ) srcmem = adjust_automodify_address_nv ( srcmem , BLKmode , srcptr , 0 ) ; if ( mode != QImode ) { srcexp = gen_rtx_ASHIFT ( Pmode , countreg , GEN_INT ( exact_log2 ( GET_MODE_SIZE ( mode ) ) ) ) ; srcexp = gen_rtx_PLUS ( Pmode , srcexp , srcptr ) ; } else srcexp = gen_rtx_PLUS ( Pmode , srcptr , countreg ) ; if ( CONST_INT_P ( count ) ) { rounded_count = ( INTVAL ( count ) & ~ ( ( HOST_WIDE_INT ) GET_MODE_SIZE ( mode ) - 1 ) ) ; srcmem = shallow_copy_rtx ( srcmem ) ; set_mem_size ( srcmem , rounded_count ) ; } else { if ( MEM_SIZE_KNOWN_P ( srcmem ) ) clear_mem_size ( srcmem ) ; } emit_insn ( gen_rep_mov ( destptr , destmem , srcptr , srcmem , countreg , destexp , srcexp ) ) ; } } </s>

Output `` rep ; mov '' or `` rep ; stos '' instruction depending on ISSETMEM argument . When ISSETMEM is true , arguments SRCMEM and SRCPTR are ignored . When ISSETMEM is false , arguments VALUE and ORIG_VALUE are ignored . For setmem case , VALUE is a promoted to a wider size ORIG_VALUE . ORIG_VALUE is the original value passed to memset to fill the memory with . Other arguments have same meaning as for previous function .


<s> static void expand_small_movmem_or_setmem ( rtx destmem , rtx srcmem , rtx destptr , rtx srcptr , rtx value , rtx vec_value , rtx count , int size , rtx done_label , bool issetmem ) { rtx_code_label * label = ix86_expand_aligntest ( count , size , false ) ; machine_mode mode = mode_for_size ( size * BITS_PER_UNIT , MODE_INT , 1 ) ; rtx modesize ; int n ; if ( issetmem ) { if ( ! vec_value ) { if ( GET_MODE ( value ) == VOIDmode && size > 8 ) mode = Pmode ; else if ( GET_MODE_SIZE ( mode ) > GET_MODE_SIZE ( GET_MODE ( value ) ) ) mode = GET_MODE ( value ) ; } else mode = GET_MODE ( vec_value ) , value = vec_value ; } else { if ( size >= 32 ) mode = TARGET_AVX ? V32QImode : TARGET_SSE ? V16QImode : DImode ; else if ( size >= 16 ) mode = TARGET_SSE ? V16QImode : DImode ; srcmem = change_address ( srcmem , mode , srcptr ) ; } destmem = change_address ( destmem , mode , destptr ) ; modesize = GEN_INT ( GET_MODE_SIZE ( mode ) ) ; gcc_assert ( GET_MODE_SIZE ( mode ) <= size ) ; for ( n = 0 ; n * GET_MODE_SIZE ( mode ) < size ; n ++ ) { if ( issetmem ) emit_move_insn ( destmem , gen_lowpart ( mode , value ) ) ; else { emit_move_insn ( destmem , srcmem ) ; srcmem = offset_address ( srcmem , modesize , GET_MODE_SIZE ( mode ) ) ; } destmem = offset_address ( destmem , modesize , GET_MODE_SIZE ( mode ) ) ; } destmem = offset_address ( destmem , count , 1 ) ; destmem = offset_address ( destmem , GEN_INT ( - 2 * size ) , GET_MODE_SIZE ( mode ) ) ; if ( ! issetmem ) { srcmem = offset_address ( srcmem , count , 1 ) ; srcmem = offset_address ( srcmem , GEN_INT ( - 2 * size ) , GET_MODE_SIZE ( mode ) ) ; } for ( n = 0 ; n * GET_MODE_SIZE ( mode ) < size ; n ++ ) { if ( issetmem ) emit_move_insn ( destmem , gen_lowpart ( mode , value ) ) ; else { emit_move_insn ( destmem , srcmem ) ; srcmem = offset_address ( srcmem , modesize , GET_MODE_SIZE ( mode ) ) ; } destmem = offset_address ( destmem , modesize , GET_MODE_SIZE ( mode ) ) ; } emit_jump_insn ( gen_jump ( done_label ) ) ; emit_barrier ( ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; } </s>

Test if COUNT & SIZE is nonzero and if so , expand movme or setmem sequence that is valid for SIZE .. 2 * SIZE-1 bytes and jump to DONE_LABEL .


<s> static bool expand_vec_perm_broadcast_1 ( struct expand_vec_perm_d * d ) { unsigned elt = d -> perm [ 0 ] , nelt2 = d -> nelt / 2 ; machine_mode vmode = d -> vmode ; unsigned char perm2 [ 4 ] ; rtx op0 = d -> op0 , dest ; bool ok ; switch ( vmode ) { case V4DFmode : case V8SFmode : gcc_unreachable ( ) ; case V2DFmode : case V2DImode : case V4SFmode : case V4SImode : gcc_unreachable ( ) ; case V8HImode : case V16QImode : if ( d -> testing_p ) return true ; do { rtx dest ; rtx ( * gen ) ( rtx , rtx , rtx ) = vmode == V16QImode ? gen_vec_interleave_lowv16qi : gen_vec_interleave_lowv8hi ; if ( elt >= nelt2 ) { gen = vmode == V16QImode ? gen_vec_interleave_highv16qi : gen_vec_interleave_highv8hi ; elt -= nelt2 ; } nelt2 /= 2 ; dest = gen_reg_rtx ( vmode ) ; emit_insn ( gen ( dest , op0 , op0 ) ) ; vmode = get_mode_wider_vector ( vmode ) ; op0 = gen_lowpart ( vmode , dest ) ; } while ( vmode != V4SImode ) ; memset ( perm2 , elt , 4 ) ; dest = gen_reg_rtx ( V4SImode ) ; ok = expand_vselect ( dest , op0 , perm2 , 4 , d -> testing_p ) ; gcc_assert ( ok ) ; if ( ! d -> testing_p ) emit_move_insn ( d -> target , gen_lowpart ( d -> vmode , dest ) ) ; return true ; case V64QImode : case V32QImode : case V16HImode : case V8SImode : case V4DImode : gcc_assert ( ! TARGET_AVX2 || d -> perm [ 0 ] ) ; return false ; default : gcc_unreachable ( ) ; } } </s>

A subroutine of ix86_expand_vec_perm_builtin_1 . Implement broadcast permutations . We assume that expand_vec_perm_1 has already failed .


<s> static bool expand_vec_perm_interleave3 ( struct expand_vec_perm_d * d ) { unsigned i , nelt ; rtx ( * gen ) ( rtx , rtx , rtx ) ; if ( d -> one_operand_p ) return false ; if ( TARGET_AVX2 && GET_MODE_SIZE ( d -> vmode ) == 32 ) ; else if ( TARGET_AVX && ( d -> vmode == V8SFmode || d -> vmode == V4DFmode ) ) ; else return false ; nelt = d -> nelt ; if ( d -> perm [ 0 ] != 0 && d -> perm [ 0 ] != nelt / 2 ) return false ; for ( i = 0 ; i < nelt ; i += 2 ) if ( d -> perm [ i ] != d -> perm [ 0 ] + i / 2 || d -> perm [ i + 1 ] != d -> perm [ 0 ] + i / 2 + nelt ) return false ; if ( d -> testing_p ) return true ; switch ( d -> vmode ) { case V32QImode : if ( d -> perm [ 0 ] ) gen = gen_vec_interleave_highv32qi ; else gen = gen_vec_interleave_lowv32qi ; break ; case V16HImode : if ( d -> perm [ 0 ] ) gen = gen_vec_interleave_highv16hi ; else gen = gen_vec_interleave_lowv16hi ; break ; case V8SImode : if ( d -> perm [ 0 ] ) gen = gen_vec_interleave_highv8si ; else gen = gen_vec_interleave_lowv8si ; break ; case V4DImode : if ( d -> perm [ 0 ] ) gen = gen_vec_interleave_highv4di ; else gen = gen_vec_interleave_lowv4di ; break ; case V8SFmode : if ( d -> perm [ 0 ] ) gen = gen_vec_interleave_highv8sf ; else gen = gen_vec_interleave_lowv8sf ; break ; case V4DFmode : if ( d -> perm [ 0 ] ) gen = gen_vec_interleave_highv4df ; else gen = gen_vec_interleave_lowv4df ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen ( d -> target , d -> op0 , d -> op1 ) ) ; return true ; } </s>

A subroutine of ix86_expand_vec_perm_builtin_1 . Try to simplify a two vector permutation using 2 intra-lane interleave insns and cross-lane shuffle for 32-byte vectors .


<s> static bool expand_vec_perm_pshufb2 ( struct expand_vec_perm_d * d ) { rtx rperm [ 2 ] [ 16 ] , vperm , l , h , op , m128 ; unsigned int i , nelt , eltsz ; if ( ! TARGET_SSSE3 || GET_MODE_SIZE ( d -> vmode ) != 16 ) return false ; gcc_assert ( ! d -> one_operand_p ) ; if ( d -> testing_p ) return true ; nelt = d -> nelt ; eltsz = GET_MODE_SIZE ( GET_MODE_INNER ( d -> vmode ) ) ; m128 = GEN_INT ( - 128 ) ; for ( i = 0 ; i < nelt ; ++ i ) { unsigned j , e = d -> perm [ i ] ; unsigned which = ( e >= nelt ) ; if ( e >= nelt ) e -= nelt ; for ( j = 0 ; j < eltsz ; ++ j ) { rperm [ which ] [ i * eltsz + j ] = GEN_INT ( e * eltsz + j ) ; rperm [ 1 - which ] [ i * eltsz + j ] = m128 ; } } vperm = gen_rtx_CONST_VECTOR ( V16QImode , gen_rtvec_v ( 16 , rperm [ 0 ] ) ) ; vperm = force_reg ( V16QImode , vperm ) ; l = gen_reg_rtx ( V16QImode ) ; op = gen_lowpart ( V16QImode , d -> op0 ) ; emit_insn ( gen_ssse3_pshufbv16qi3 ( l , op , vperm ) ) ; vperm = gen_rtx_CONST_VECTOR ( V16QImode , gen_rtvec_v ( 16 , rperm [ 1 ] ) ) ; vperm = force_reg ( V16QImode , vperm ) ; h = gen_reg_rtx ( V16QImode ) ; op = gen_lowpart ( V16QImode , d -> op1 ) ; emit_insn ( gen_ssse3_pshufbv16qi3 ( h , op , vperm ) ) ; op = d -> target ; if ( d -> vmode != V16QImode ) op = gen_reg_rtx ( V16QImode ) ; emit_insn ( gen_iorv16qi3 ( op , l , h ) ) ; if ( op != d -> target ) emit_move_insn ( d -> target , gen_lowpart ( d -> vmode , op ) ) ; return true ; } </s>

A subroutine of expand_vec_perm_even_odd_1 . Implement the double-word permutation with two pshufb insns and an ior . We should have already failed all two instruction sequences .


<s> static bool expand_vec_perm_vpermi2_vpshub2 ( struct expand_vec_perm_d * d ) { if ( ! TARGET_AVX512BW || ! ( d -> vmode == V64QImode ) ) return false ; if ( d -> testing_p ) return true ; struct expand_vec_perm_d ds [ 2 ] ; rtx rperm [ 128 ] , vperm , target0 , target1 ; unsigned int i , nelt ; machine_mode vmode ; nelt = d -> nelt ; vmode = V64QImode ; for ( i = 0 ; i < 2 ; i ++ ) { ds [ i ] = * d ; ds [ i ] . vmode = V32HImode ; ds [ i ] . nelt = 32 ; ds [ i ] . target = gen_reg_rtx ( V32HImode ) ; ds [ i ] . op0 = gen_lowpart ( V32HImode , d -> op0 ) ; ds [ i ] . op1 = gen_lowpart ( V32HImode , d -> op1 ) ; } for ( i = 0 ; i < nelt ; i ++ ) { ds [ i & 1 ] . perm [ i / 2 ] = d -> perm [ i ] / 2 ; if ( i & 1 ) { rperm [ i ] = constm1_rtx ; rperm [ i + 64 ] = GEN_INT ( ( i & 14 ) + ( d -> perm [ i ] & 1 ) ) ; } else { rperm [ i ] = GEN_INT ( ( i & 14 ) + ( d -> perm [ i ] & 1 ) ) ; rperm [ i + 64 ] = constm1_rtx ; } } bool ok = expand_vec_perm_1 ( & ds [ 0 ] ) ; gcc_assert ( ok ) ; ds [ 0 ] . target = gen_lowpart ( V64QImode , ds [ 0 ] . target ) ; ok = expand_vec_perm_1 ( & ds [ 1 ] ) ; gcc_assert ( ok ) ; ds [ 1 ] . target = gen_lowpart ( V64QImode , ds [ 1 ] . target ) ; vperm = gen_rtx_CONST_VECTOR ( V64QImode , gen_rtvec_v ( 64 , rperm ) ) ; vperm = force_reg ( vmode , vperm ) ; target0 = gen_reg_rtx ( V64QImode ) ; emit_insn ( gen_avx512bw_pshufbv64qi3 ( target0 , ds [ 0 ] . target , vperm ) ) ; vperm = gen_rtx_CONST_VECTOR ( V64QImode , gen_rtvec_v ( 64 , rperm + 64 ) ) ; vperm = force_reg ( vmode , vperm ) ; target1 = gen_reg_rtx ( V64QImode ) ; emit_insn ( gen_avx512bw_pshufbv64qi3 ( target1 , ds [ 1 ] . target , vperm ) ) ; emit_insn ( gen_iorv64qi3 ( d -> target , target0 , target1 ) ) ; return true ; } </s>

Implement arbitrary permutations of two V64QImode operands will 2 vpermi2w , 2 vpshufb and one vpor instruction .


<s> static bool expand_vec_perm_vpshufb2_vpermq ( struct expand_vec_perm_d * d ) { rtx rperm [ 2 ] [ 32 ] , vperm , l , h , hp , op , m128 ; unsigned int i , nelt , eltsz ; if ( ! TARGET_AVX2 || ! d -> one_operand_p || ( d -> vmode != V32QImode && d -> vmode != V16HImode ) ) return false ; if ( d -> testing_p ) return true ; nelt = d -> nelt ; eltsz = GET_MODE_SIZE ( GET_MODE_INNER ( d -> vmode ) ) ; m128 = GEN_INT ( - 128 ) ; for ( i = 0 ; i < nelt ; ++ i ) { unsigned j , e = d -> perm [ i ] & ( nelt / 2 - 1 ) ; unsigned which = ( ( d -> perm [ i ] ^ i ) & ( nelt / 2 ) ) * eltsz ; for ( j = 0 ; j < eltsz ; ++ j ) { rperm [ ! ! which ] [ ( i * eltsz + j ) ^ which ] = GEN_INT ( e * eltsz + j ) ; rperm [ ! which ] [ ( i * eltsz + j ) ^ ( which ^ 16 ) ] = m128 ; } } vperm = gen_rtx_CONST_VECTOR ( V32QImode , gen_rtvec_v ( 32 , rperm [ 1 ] ) ) ; vperm = force_reg ( V32QImode , vperm ) ; h = gen_reg_rtx ( V32QImode ) ; op = gen_lowpart ( V32QImode , d -> op0 ) ; emit_insn ( gen_avx2_pshufbv32qi3 ( h , op , vperm ) ) ; hp = gen_reg_rtx ( V4DImode ) ; op = gen_lowpart ( V4DImode , h ) ; emit_insn ( gen_avx2_permv4di_1 ( hp , op , const2_rtx , GEN_INT ( 3 ) , const0_rtx , const1_rtx ) ) ; vperm = gen_rtx_CONST_VECTOR ( V32QImode , gen_rtvec_v ( 32 , rperm [ 0 ] ) ) ; vperm = force_reg ( V32QImode , vperm ) ; l = gen_reg_rtx ( V32QImode ) ; op = gen_lowpart ( V32QImode , d -> op0 ) ; emit_insn ( gen_avx2_pshufbv32qi3 ( l , op , vperm ) ) ; op = d -> target ; if ( d -> vmode != V32QImode ) op = gen_reg_rtx ( V32QImode ) ; emit_insn ( gen_iorv32qi3 ( op , l , gen_lowpart ( V32QImode , hp ) ) ) ; if ( op != d -> target ) emit_move_insn ( d -> target , gen_lowpart ( d -> vmode , op ) ) ; return true ; } </s>

Implement arbitrary permutation of one V32QImode and V16QImode operand with two vpshufb insns , vpermq and vpor . We should have already failed all two or three instruction sequences .


A subroutine of expand_vec_perm_even_odd_1 . Implement extract-even and extract-odd permutations of two V32QImode and V16QImode operand with two vpshufb insns , vpor and vpermq . We should have already failed all two or three instruction sequences .


<s> static bool expand_vselect_vconcat ( rtx target , rtx op0 , rtx op1 , const unsigned char * perm , unsigned nelt , bool testing_p ) { machine_mode v2mode ; rtx x ; bool ok ; if ( vselect_insn == NULL_RTX ) init_vselect_insn ( ) ; v2mode = GET_MODE_2XWIDER_MODE ( GET_MODE ( op0 ) ) ; x = XEXP ( SET_SRC ( PATTERN ( vselect_insn ) ) , 0 ) ; PUT_MODE ( x , v2mode ) ; XEXP ( x , 0 ) = op0 ; XEXP ( x , 1 ) = op1 ; ok = expand_vselect ( target , x , perm , nelt , testing_p ) ; XEXP ( x , 0 ) = const0_rtx ; XEXP ( x , 1 ) = const0_rtx ; return ok ; } </s>

Similar , but generate a vec_concat from op0 and op1 as well .


<s> static void find_constant ( rtx in_rtx , imm_info * imm_values ) { if ( INSN_P ( in_rtx ) ) in_rtx = PATTERN ( in_rtx ) ; subrtx_iterator :: array_type array ; FOR_EACH_SUBRTX ( iter , array , in_rtx , ALL ) if ( const_rtx x = * iter ) switch ( GET_CODE ( x ) ) { case CONST : case SYMBOL_REF : case CONST_INT : ( imm_values -> imm ) ++ ; if ( x86_64_immediate_operand ( CONST_CAST_RTX ( x ) , SImode ) ) ( imm_values -> imm32 ) ++ ; else ( imm_values -> imm64 ) ++ ; break ; case CONST_DOUBLE : ( imm_values -> imm ) ++ ; ( imm_values -> imm64 ) ++ ; break ; case CODE_LABEL : if ( LABEL_KIND ( x ) == LABEL_NORMAL ) { ( imm_values -> imm ) ++ ; ( imm_values -> imm32 ) ++ ; } break ; default : break ; } } </s>

Compute number of immediate operands of an instruction .


<s> static unsigned int find_drap_reg ( void ) { tree decl = cfun -> decl ; if ( TARGET_64BIT ) { if ( DECL_STATIC_CHAIN ( decl ) || crtl -> tail_call_emit ) return R13_REG ; return R10_REG ; } else { if ( DECL_STATIC_CHAIN ( decl ) || crtl -> tail_call_emit ) return DI_REG ; if ( ix86_function_regparm ( TREE_TYPE ( decl ) , decl ) <= 2 ) { unsigned int ccvt = ix86_get_callcvt ( TREE_TYPE ( decl ) ) ; if ( ( ccvt & ( IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL ) ) == 0 ) return CX_REG ; } return DI_REG ; } } </s>

Find an available register to be used as dynamic realign argument pointer regsiter . Such a register will be written in prologue and used in begin of body , so it must not be 1. parameter passing register . 2 . GOT pointer . We reuse static-chain register if it is available . Otherwise , we use DI for i386 and R13 for x86-64 . We chose R13 since it has shorter encoding . Return : the regno of chosen register .


<s> static bool fits_dispatch_window ( rtx_insn * insn ) { dispatch_windows * window_list = dispatch_window_list ; dispatch_windows * window_list_next = dispatch_window_list -> next ; unsigned int num_restrict ; enum dispatch_group group = get_insn_group ( insn ) ; enum insn_path path = get_insn_path ( insn ) ; int sum ; if ( group == disp_jcc || group == disp_cmp ) return false ; if ( group == disp_no_group || group == disp_branch ) return true ; if ( window_list_next ) window_list = window_list_next ; if ( window_list -> window_num == 1 ) { sum = window_list -> prev -> window_size + window_list -> window_size ; if ( sum == 32 || ( min_insn_size ( insn ) + sum ) >= 48 ) return true ; } num_restrict = count_num_restricted ( insn , window_list ) ; if ( num_restrict > num_allowable_groups [ group ] ) return false ; if ( window_list -> window_num == 0 ) { if ( path == path_double && ( window_list -> num_uops + 2 ) > MAX_INSN ) return false ; else if ( path != path_single ) return false ; } return true ; } </s>

This function returns true if insn satisfies dispatch rules on the last window scheduled .


<s> static rtx function_arg_32 ( const CUMULATIVE_ARGS * cum , machine_mode mode , machine_mode orig_mode , const_tree type , HOST_WIDE_INT bytes , HOST_WIDE_INT words ) { if ( mode == VOIDmode ) return constm1_rtx ; switch ( mode ) { default : break ; case BLKmode : if ( bytes < 0 ) break ; case DImode : case SImode : case HImode : case QImode : if ( words <= cum -> nregs ) { int regno = cum -> regno ; if ( cum -> fastcall ) { if ( mode == BLKmode || mode == DImode || ( type && AGGREGATE_TYPE_P ( type ) ) ) break ; if ( regno == AX_REG ) regno = CX_REG ; } return gen_rtx_REG ( mode , regno ) ; } break ; case DFmode : if ( cum -> float_in_sse < 2 ) break ; case SFmode : if ( cum -> float_in_sse < 1 ) break ; case TImode : case V16QImode : case V8HImode : case V4SImode : case V2DImode : case V4SFmode : case V2DFmode : if ( ! type || ! AGGREGATE_TYPE_P ( type ) ) { if ( cum -> sse_nregs ) return gen_reg_or_parallel ( mode , orig_mode , cum -> sse_regno + FIRST_SSE_REG ) ; } break ; case OImode : case XImode : gcc_unreachable ( ) ; case V64QImode : case V32HImode : case V16SImode : case V8DImode : case V16SFmode : case V8DFmode : case V8SFmode : case V8SImode : case V32QImode : case V16HImode : case V4DFmode : case V4DImode : if ( ! type || ! AGGREGATE_TYPE_P ( type ) ) { if ( cum -> sse_nregs ) return gen_reg_or_parallel ( mode , orig_mode , cum -> sse_regno + FIRST_SSE_REG ) ; } break ; case V8QImode : case V4HImode : case V2SImode : case V2SFmode : case V1TImode : case V1DImode : if ( ! type || ! AGGREGATE_TYPE_P ( type ) ) { if ( cum -> mmx_nregs ) return gen_reg_or_parallel ( mode , orig_mode , cum -> mmx_regno + FIRST_MMX_REG ) ; } break ; } return NULL_RTX ; } </s>

Define where to put the arguments to a function . Value is 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 ( as a tree ) . This is null for libcalls where that information may not be available . CUM is a variable of type CUMULATIVE_ARGS which gives info 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 int function_arg_advance_32 ( CUMULATIVE_ARGS * cum , machine_mode mode , const_tree type , HOST_WIDE_INT bytes , HOST_WIDE_INT words ) { int res = 0 ; switch ( mode ) { default : break ; case BLKmode : if ( bytes < 0 ) break ; case DImode : case SImode : case HImode : case QImode : cum -> words += words ; cum -> nregs -= words ; cum -> regno += words ; if ( cum -> nregs >= 0 ) res = words ; if ( cum -> nregs <= 0 ) { cum -> nregs = 0 ; cum -> regno = 0 ; } break ; case OImode : gcc_unreachable ( ) ; case DFmode : if ( cum -> float_in_sse < 2 ) break ; case SFmode : if ( cum -> float_in_sse < 1 ) break ; case V8SFmode : case V8SImode : case V64QImode : case V32HImode : case V16SImode : case V8DImode : case V16SFmode : case V8DFmode : case V32QImode : case V16HImode : case V4DFmode : case V4DImode : case TImode : case V16QImode : case V8HImode : case V4SImode : case V2DImode : case V4SFmode : case V2DFmode : if ( ! type || ! AGGREGATE_TYPE_P ( type ) ) { cum -> sse_words += words ; cum -> sse_nregs -= 1 ; cum -> sse_regno += 1 ; if ( cum -> sse_nregs <= 0 ) { cum -> sse_nregs = 0 ; cum -> sse_regno = 0 ; } } break ; case V8QImode : case V4HImode : case V2SImode : case V2SFmode : case V1TImode : case V1DImode : if ( ! type || ! AGGREGATE_TYPE_P ( type ) ) { cum -> mmx_words += words ; cum -> mmx_nregs -= 1 ; cum -> mmx_regno += 1 ; if ( cum -> mmx_nregs <= 0 ) { cum -> mmx_nregs = 0 ; cum -> mmx_regno = 0 ; } } break ; } return res ; } </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 . ) Return a number of integer regsiters advanced over .


<s> static rtx function_value_32 ( machine_mode orig_mode , machine_mode mode , const_tree fntype , const_tree fn ) { unsigned int regno ; if ( VECTOR_MODE_P ( mode ) && GET_MODE_SIZE ( mode ) == 8 ) regno = FIRST_MMX_REG ; else if ( mode == TImode || ( VECTOR_MODE_P ( mode ) && GET_MODE_SIZE ( mode ) == 16 ) ) regno = FIRST_SSE_REG ; else if ( VECTOR_MODE_P ( mode ) && GET_MODE_SIZE ( mode ) == 32 ) regno = FIRST_SSE_REG ; else if ( VECTOR_MODE_P ( mode ) && GET_MODE_SIZE ( mode ) == 64 ) regno = FIRST_SSE_REG ; else if ( X87_FLOAT_MODE_P ( mode ) && TARGET_FLOAT_RETURNS_IN_80387 ) regno = FIRST_FLOAT_REG ; else regno = AX_REG ; if ( ( fn || fntype ) && ( mode == SFmode || mode == DFmode ) ) { int sse_level = ix86_function_sseregparm ( fntype , fn , false ) ; if ( ( sse_level >= 1 && mode == SFmode ) || ( sse_level == 2 && mode == DFmode ) ) regno = FIRST_SSE_REG ; } gcc_assert ( mode != OImode ) ; return gen_rtx_REG ( orig_mode , regno ) ; } </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 rtx gen_pop ( rtx arg ) { if ( REG_P ( arg ) && GET_MODE ( arg ) != word_mode ) arg = gen_rtx_REG ( word_mode , REGNO ( arg ) ) ; return gen_rtx_SET ( VOIDmode , arg , gen_rtx_MEM ( word_mode , gen_rtx_POST_INC ( Pmode , stack_pointer_rtx ) ) ) ; } </s>

Generate an `` pop '' pattern for input ARG .


<s> static rtx gen_push ( rtx arg ) { struct machine_function * m = cfun -> machine ; if ( m -> fs . cfa_reg == stack_pointer_rtx ) m -> fs . cfa_offset += UNITS_PER_WORD ; m -> fs . sp_offset += UNITS_PER_WORD ; if ( REG_P ( arg ) && GET_MODE ( arg ) != word_mode ) arg = gen_rtx_REG ( word_mode , REGNO ( arg ) ) ; return gen_rtx_SET ( VOIDmode , gen_rtx_MEM ( word_mode , gen_rtx_PRE_DEC ( Pmode , stack_pointer_rtx ) ) , arg ) ; } </s>

Code to generate prologue and epilogue sequences


"selector must be an integer constant in the range 0..%wi"

Return the integer constant in ARG . Constrain it to be in the range of the subparts of VEC_TYPE ; issue an error if not .


<s> static enum dispatch_group get_insn_group ( rtx_insn * insn ) { enum dispatch_group group = get_mem_group ( insn ) ; if ( group ) return group ; if ( is_branch ( insn ) ) return disp_branch ; if ( is_cmp ( insn ) ) return disp_cmp ; if ( has_immediate ( insn ) ) return disp_imm ; if ( is_prefetch ( insn ) ) return disp_prefetch ; return disp_no_group ; } </s>


<s> static enum insn_path get_insn_path ( rtx_insn * insn ) { enum attr_amdfam10_decode path = get_attr_amdfam10_decode ( insn ) ; if ( ( int ) path == 0 ) return path_single ; if ( ( int ) path == 1 ) return path_double ; return path_multi ; } </s>

Return single or double path for instructions .


<s> static enum dispatch_group get_mem_group ( rtx_insn * insn ) { enum attr_memory memory ; if ( INSN_CODE ( insn ) < 0 ) return disp_no_group ; memory = get_attr_memory ( insn ) ; if ( memory == MEMORY_STORE ) return disp_store ; if ( memory == MEMORY_LOAD ) return disp_load ; if ( memory == MEMORY_BOTH ) return disp_load_store ; return disp_no_group ; } </s>


<s> static inline machine_mode get_mode_wider_vector ( machine_mode o ) { machine_mode n = GET_MODE_WIDER_MODE ( o ) ; gcc_assert ( GET_MODE_NUNITS ( o ) == GET_MODE_NUNITS ( n ) * 2 ) ; gcc_assert ( GET_MODE_SIZE ( o ) == GET_MODE_SIZE ( n ) ) ; return n ; } </s>

Get a vector mode of the same size as the original but with elements twice as wide . This is only guaranteed to apply to integral vectors .


<s> static int get_num_immediates ( rtx insn , int * imm , int * imm32 , int * imm64 ) { imm_info imm_values = { 0 , 0 , 0 } ; find_constant ( insn , & imm_values ) ; * imm = imm_values . imm ; * imm32 = imm_values . imm32 ; * imm64 = imm_values . imm64 ; return imm_values . imm32 * 4 + imm_values . imm64 * 8 ; } </s>

Return total size of immediate operands of an instruction along with number of corresponding immediate-operands . It initializes its parameters to zero befor calling FIND_CONSTANT . INSN is the input instruction . IMM is the total of immediates . IMM32 is the number of 32 bit immediates . IMM64 is the number of 64 bit immediates .


<s> static void get_scratch_register_on_entry ( struct scratch_reg * sr ) { int regno ; sr -> saved = false ; if ( TARGET_64BIT ) { regno = R11_REG ; } else { tree decl = current_function_decl , fntype = TREE_TYPE ( decl ) ; bool fastcall_p = lookup_attribute ( "fastcall" , TYPE_ATTRIBUTES ( fntype ) ) != NULL_TREE ; bool thiscall_p = lookup_attribute ( "thiscall" , TYPE_ATTRIBUTES ( fntype ) ) != NULL_TREE ; bool static_chain_p = DECL_STATIC_CHAIN ( decl ) ; int regparm = ix86_function_regparm ( fntype , decl ) ; int drap_regno = crtl -> drap_reg ? REGNO ( crtl -> drap_reg ) : INVALID_REGNUM ; if ( ( regparm < 1 || ( fastcall_p && ! static_chain_p ) ) && drap_regno != AX_REG ) regno = AX_REG ; else if ( thiscall_p && ! static_chain_p && drap_regno != AX_REG ) regno = AX_REG ; else if ( regparm < 2 && ! thiscall_p && drap_regno != DX_REG ) regno = DX_REG ; else if ( regparm < 3 && ! fastcall_p && ! thiscall_p && ! static_chain_p && drap_regno != CX_REG ) regno = CX_REG ; else if ( ix86_save_reg ( BX_REG , true ) ) regno = BX_REG ; else if ( ! ( regparm == 3 && static_chain_p ) && ix86_save_reg ( SI_REG , true ) ) regno = SI_REG ; else if ( ix86_save_reg ( DI_REG , true ) ) regno = DI_REG ; else { regno = ( drap_regno == AX_REG ? DX_REG : AX_REG ) ; sr -> saved = true ; } } sr -> reg = gen_rtx_REG ( Pmode , regno ) ; if ( sr -> saved ) { rtx insn = emit_insn ( gen_push ( sr -> reg ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } } </s>

Return a short-lived scratch register for use on function entry . In 32-bit mode , it is valid only after the registers are saved in the prologue . This register must be released by means of release_scratch_register_on_entry once it is dead .


<s> static bool has_dispatch ( rtx_insn * insn , int action ) { if ( ( TARGET_BDVER1 || TARGET_BDVER2 || TARGET_BDVER3 || TARGET_BDVER4 ) && flag_dispatch_scheduler ) switch ( action ) { default : return false ; case IS_DISPATCH_ON : return true ; break ; case IS_CMP : return is_cmp ( insn ) ; case DISPATCH_VIOLATION : return dispatch_violation ( ) ; case FITS_DISPATCH_WINDOW : return fits_dispatch_window ( insn ) ; } return false ; } </s>

Return TRUE if Dispatch Scheduling is supported .


<s> static bool has_immediate ( rtx insn ) { int num_imm_operand ; int num_imm32_operand ; int num_imm64_operand ; if ( insn ) return get_num_immediates ( insn , & num_imm_operand , & num_imm32_operand , & num_imm64_operand ) ; return false ; } </s>

This function indicates if an operand of an instruction is an immediate .


<s> static bool i386_asm_output_addr_const_extra ( FILE * file , rtx x ) { rtx op ; if ( GET_CODE ( x ) != UNSPEC ) return false ; op = XVECEXP ( x , 0 , 0 ) ; switch ( XINT ( x , 1 ) ) { case UNSPEC_GOTTPOFF : output_addr_const ( file , op ) ; fputs ( "@gottpoff" , file ) ; break ; case UNSPEC_TPOFF : output_addr_const ( file , op ) ; fputs ( "@tpoff" , file ) ; break ; case UNSPEC_NTPOFF : output_addr_const ( file , op ) ; if ( TARGET_64BIT ) fputs ( "@tpoff" , file ) ; else fputs ( "@ntpoff" , file ) ; break ; case UNSPEC_DTPOFF : output_addr_const ( file , op ) ; fputs ( "@dtpoff" , file ) ; break ; case UNSPEC_GOTNTPOFF : output_addr_const ( file , op ) ; if ( TARGET_64BIT ) fputs ( ASSEMBLER_DIALECT == ASM_ATT ? "@gottpoff(%rip)" : "@gottpoff[rip]" , file ) ; else fputs ( "@gotntpoff" , file ) ; break ; case UNSPEC_INDNTPOFF : output_addr_const ( file , op ) ; fputs ( "@indntpoff" , file ) ; break ; case UNSPEC_MACHOPIC_OFFSET : output_addr_const ( file , op ) ; putc ( '-' , file ) ; machopic_output_function_base_name ( file ) ; break ; case UNSPEC_STACK_CHECK : { int offset ; gcc_assert ( flag_split_stack ) ; offset = TARGET_THREAD_SPLIT_STACK_OFFSET ; gcc_unreachable ( ) ; fprintf ( file , "%s:%d" , TARGET_64BIT ? "%fs" : "%gs" , offset ) ; } break ; default : return false ; } return true ; } </s>

Implementation of TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA .


<s> static void i386_solaris_elf_named_section ( const char * name , unsigned int flags , tree decl ) { if ( TARGET_64BIT && strcmp ( name , ".eh_frame" ) == 0 ) { fprintf ( asm_out_file , "\t.section\t%s,\"%s\",@unwind\n" , name , flags & SECTION_WRITE ? "aw" : "a" ) ; return ; } if ( HAVE_COMDAT_GROUP && flags & SECTION_LINKONCE ) { solaris_elf_asm_comdat_section ( name , flags , decl ) ; return ; } default_elf_asm_named_section ( name , flags , decl ) ; } </s>

Solaris named-section hook . Parameters are as for named_section_real .


<s> static int ia32_multipass_dfa_lookahead ( void ) { switch ( ix86_tune ) { case PROCESSOR_PENTIUM : return 2 ; case PROCESSOR_PENTIUMPRO : case PROCESSOR_K6 : return 1 ; case PROCESSOR_BDVER1 : case PROCESSOR_BDVER2 : case PROCESSOR_BDVER3 : case PROCESSOR_BDVER4 : return 4 ; case PROCESSOR_CORE2 : case PROCESSOR_NEHALEM : case PROCESSOR_SANDYBRIDGE : case PROCESSOR_HASWELL : case PROCESSOR_BONNELL : case PROCESSOR_SILVERMONT : case PROCESSOR_KNL : case PROCESSOR_INTEL : if ( reload_completed ) return ix86_issue_rate ( ) ; return 0 ; default : return 0 ; } } </s>

How many alternative schedules to try . This should be as wide as the scheduling freedom in the DFA , but no wider . Making this value too large results extra work for the scheduler .


<s> void init_cumulative_args ( CUMULATIVE_ARGS * cum , tree fntype , rtx libname , tree fndecl , int caller ) { struct cgraph_local_info * i = NULL ; struct cgraph_node * target = NULL ; memset ( cum , 0 , sizeof ( * cum ) ) ; if ( fndecl ) { target = cgraph_node :: get ( fndecl ) ; if ( target ) { target = target -> function_symbol ( ) ; i = cgraph_node :: local_info ( target -> decl ) ; cum -> call_abi = ix86_function_abi ( target -> decl ) ; } else cum -> call_abi = ix86_function_abi ( fndecl ) ; } else cum -> call_abi = ix86_function_type_abi ( fntype ) ; cum -> caller = caller ; cum -> nregs = ix86_regparm ; if ( TARGET_64BIT ) { cum -> nregs = ( cum -> call_abi == SYSV_ABI ? X86_64_REGPARM_MAX : X86_64_MS_REGPARM_MAX ) ; } if ( TARGET_SSE ) { cum -> sse_nregs = SSE_REGPARM_MAX ; if ( TARGET_64BIT ) { cum -> sse_nregs = ( cum -> call_abi == SYSV_ABI ? X86_64_SSE_REGPARM_MAX : X86_64_MS_SSE_REGPARM_MAX ) ; } } if ( TARGET_MMX ) cum -> mmx_nregs = MMX_REGPARM_MAX ; cum -> warn_avx512f = true ; cum -> warn_avx = true ; cum -> warn_sse = true ; cum -> warn_mmx = true ; if ( i && i -> local && i -> can_change_signature ) fntype = TREE_TYPE ( target -> decl ) ; cum -> stdarg = stdarg_p ( fntype ) ; cum -> maybe_vaarg = ( fntype ? ( ! prototype_p ( fntype ) || stdarg_p ( fntype ) ) : ! libname ) ; cum -> bnd_regno = FIRST_BND_REG ; cum -> bnds_in_bt = 0 ; cum -> force_bnd_pass = 0 ; if ( ! TARGET_64BIT ) { if ( stdarg_p ( fntype ) ) { cum -> nregs = 0 ; cum -> sse_nregs = 0 ; cum -> mmx_nregs = 0 ; cum -> warn_avx512f = false ; cum -> warn_avx = false ; cum -> warn_sse = false ; cum -> warn_mmx = false ; return ; } if ( fntype ) { unsigned int ccvt = ix86_get_callcvt ( fntype ) ; if ( ( ccvt & IX86_CALLCVT_THISCALL ) != 0 ) { cum -> nregs = 1 ; cum -> fastcall = 1 ; } else if ( ( ccvt & IX86_CALLCVT_FASTCALL ) != 0 ) { cum -> nregs = 2 ; cum -> fastcall = 1 ; } else cum -> nregs = ix86_function_regparm ( fntype , fndecl ) ; } cum -> float_in_sse = ix86_function_sseregparm ( fntype , fndecl , true ) ; } } </s>

Handle the INIT_CUMULATIVE_ARGS macro . Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE . For a library call , FNTYPE is 0 .


<s> static void init_dispatch_sched ( void ) { dispatch_window_list = allocate_window ( ) ; dispatch_window_list1 = allocate_window ( ) ; init_window ( 0 ) ; init_window ( 1 ) ; } </s>

This routine initializes the dispatch scheduling information . It initiates building dispatch scheduler tables and constructs the first dispatch window .


<s> static void init_vselect_insn ( void ) { unsigned i ; rtx x ; x = gen_rtx_PARALLEL ( VOIDmode , rtvec_alloc ( MAX_VECT_LEN ) ) ; for ( i = 0 ; i < MAX_VECT_LEN ; ++ i ) XVECEXP ( x , 0 , i ) = const0_rtx ; x = gen_rtx_VEC_SELECT ( V2DFmode , gen_rtx_VEC_CONCAT ( V4DFmode , const0_rtx , const0_rtx ) , x ) ; x = gen_rtx_SET ( VOIDmode , const0_rtx , x ) ; start_sequence ( ) ; vselect_insn = emit_insn ( x ) ; end_sequence ( ) ; } </s>


<s> static void init_window ( int window_num ) { int i ; dispatch_windows * new_list ; if ( window_num == 0 ) new_list = dispatch_window_list ; else new_list = dispatch_window_list1 ; new_list -> num_insn = 0 ; new_list -> num_uops = 0 ; new_list -> window_size = 0 ; new_list -> next = NULL ; new_list -> prev = NULL ; new_list -> window_num = window_num ; new_list -> num_imm = 0 ; new_list -> num_imm_32 = 0 ; new_list -> num_imm_64 = 0 ; new_list -> imm_size = 0 ; new_list -> num_loads = 0 ; new_list -> num_stores = 0 ; new_list -> violation = false ; for ( i = 0 ; i < MAX_INSN ; i ++ ) { new_list -> window [ i ] . insn = NULL ; new_list -> window [ i ] . group = disp_no_group ; new_list -> window [ i ] . path = no_path ; new_list -> window [ i ] . byte_len = 0 ; new_list -> window [ i ] . imm_bytes = 0 ; } return ; } </s>

This function initializes a dispatch window and the list container holding a pointer to the window .


<s> static inline bool inline_secondary_memory_needed ( enum reg_class class1 , enum reg_class class2 , machine_mode mode , int strict ) { if ( lra_in_progress && ( class1 == NO_REGS || class2 == NO_REGS ) ) return false ; if ( MAYBE_FLOAT_CLASS_P ( class1 ) != FLOAT_CLASS_P ( class1 ) || MAYBE_FLOAT_CLASS_P ( class2 ) != FLOAT_CLASS_P ( class2 ) || MAYBE_SSE_CLASS_P ( class1 ) != SSE_CLASS_P ( class1 ) || MAYBE_SSE_CLASS_P ( class2 ) != SSE_CLASS_P ( class2 ) || MAYBE_MMX_CLASS_P ( class1 ) != MMX_CLASS_P ( class1 ) || MAYBE_MMX_CLASS_P ( class2 ) != MMX_CLASS_P ( class2 ) ) { gcc_assert ( ! strict || lra_in_progress ) ; return true ; } if ( FLOAT_CLASS_P ( class1 ) != FLOAT_CLASS_P ( class2 ) ) return true ; if ( ( MAYBE_MASK_CLASS_P ( class1 ) != MAYBE_MASK_CLASS_P ( class2 ) ) && ( GET_MODE_SIZE ( mode ) > UNITS_PER_WORD ) ) return true ; if ( MMX_CLASS_P ( class1 ) != MMX_CLASS_P ( class2 ) ) return true ; if ( SSE_CLASS_P ( class1 ) != SSE_CLASS_P ( class2 ) ) { if ( ! TARGET_SSE2 ) return true ; if ( ( SSE_CLASS_P ( class1 ) && ! TARGET_INTER_UNIT_MOVES_FROM_VEC ) || ( SSE_CLASS_P ( class2 ) && ! TARGET_INTER_UNIT_MOVES_TO_VEC ) ) return true ; if ( GET_MODE_SIZE ( mode ) > UNITS_PER_WORD ) return true ; } return false ; } </s>

If we are copying between general and FP registers , we need a memory location . The same is true for SSE and MMX registers . To optimize register_move_cost performance , allow inline variant . The macro ca n't work reliably when one of the CLASSES is class containing registers from multiple units ( SSE , MMX , integer ) . We avoid this by never combining those units in single alternative in the machine description . Ensure that this constraint holds to avoid unexpected surprises . When STRICT is false , we are being called from REGISTER_MOVE_COST , so do not enforce these sanity checks .


<s> static bool insn_defines_reg ( unsigned int regno1 , unsigned int regno2 , rtx insn ) { df_ref def ; FOR_EACH_INSN_DEF ( def , insn ) if ( DF_REF_REG_DEF_P ( def ) && ! DF_REF_IS_ARTIFICIAL ( def ) && ( regno1 == DF_REF_REGNO ( def ) || regno2 == DF_REF_REGNO ( def ) ) ) return true ; return false ; } </s>

Function checks if instruction INSN defines register number REGNO1 or REGNO2 .


<s> static bool is_branch ( rtx insn ) { return ( CALL_P ( insn ) || JUMP_P ( insn ) ) ; } </s>

Return true if insn is a branch instruction .


<s> static bool is_cmp ( rtx_insn * insn ) { enum attr_type type ; type = get_attr_type ( insn ) ; return ( type == TYPE_TEST || type == TYPE_ICMP || type == TYPE_FCMP || GET_CODE ( PATTERN ( insn ) ) == COMPARE ) ; } </s>

Return true if insn is a compare instruction .


<s> static bool is_end_basic_block ( enum dispatch_group group ) { return group == disp_branch ; } </s>

This function returns true if a branch is detected . End of a basic block does not have to be a branch , but here we assume only branches end a window .


<s> static bool is_function_default_version ( const tree decl ) { if ( TREE_CODE ( decl ) != FUNCTION_DECL || ! DECL_FUNCTION_VERSIONED ( decl ) ) return false ; tree attr = lookup_attribute ( "target" , DECL_ATTRIBUTES ( decl ) ) ; gcc_assert ( attr ) ; attr = TREE_VALUE ( TREE_VALUE ( attr ) ) ; return ( TREE_CODE ( attr ) == STRING_CST && strcmp ( TREE_STRING_POINTER ( attr ) , "default" ) == 0 ) ; } </s>

Returns true if decl is multi-versioned and DECL is the default function , that is it is not tagged with target specific optimization .


<s> static bool is_prefetch ( rtx insn ) { return NONJUMP_INSN_P ( insn ) && GET_CODE ( PATTERN ( insn ) ) == PREFETCH ; } </s>

Return true if insn is a prefetch instruction .


<s> static int ix86_address_cost ( rtx x , machine_mode , addr_space_t , bool ) { struct ix86_address parts ; int cost = 1 ; int ok = ix86_decompose_address ( x , & parts ) ; gcc_assert ( ok ) ; if ( parts . base && GET_CODE ( parts . base ) == SUBREG ) parts . base = SUBREG_REG ( parts . base ) ; if ( parts . index && GET_CODE ( parts . index ) == SUBREG ) parts . index = SUBREG_REG ( parts . index ) ; if ( parts . base && ( ! REG_P ( parts . base ) || REGNO ( parts . base ) >= FIRST_PSEUDO_REGISTER ) && ( current_pass -> type == GIMPLE_PASS || ! pic_offset_table_rtx || ! REG_P ( parts . base ) || REGNO ( pic_offset_table_rtx ) != REGNO ( parts . base ) ) ) cost ++ ; if ( parts . index && ( ! REG_P ( parts . index ) || REGNO ( parts . index ) >= FIRST_PSEUDO_REGISTER ) && ( current_pass -> type == GIMPLE_PASS || ! pic_offset_table_rtx || ! REG_P ( parts . index ) || REGNO ( pic_offset_table_rtx ) != REGNO ( parts . index ) ) ) cost ++ ; if ( TARGET_K6 && ( ( ! parts . disp && parts . base && parts . index && parts . scale != 1 ) || ( parts . disp && ! parts . base && parts . index && parts . scale != 1 ) || ( ! parts . disp && parts . base && parts . index && parts . scale == 1 ) ) ) cost += 10 ; return cost ; } </s>

Return cost of the memory address x . For i386 , it is better to use a complex address than let gcc copy the address into a reg and make a new pseudo . But not if the address requires to two regs - that would mean more pseudos with longer lifetimes .


<s> static void ix86_add_cfa_restore_note ( rtx insn , rtx reg , HOST_WIDE_INT cfa_offset ) { if ( ! crtl -> shrink_wrapped && cfa_offset <= cfun -> machine -> fs . red_zone_offset ) return ; if ( insn ) { add_reg_note ( insn , REG_CFA_RESTORE , reg ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } else queued_cfa_restores = alloc_reg_note ( REG_CFA_RESTORE , reg , queued_cfa_restores ) ; } </s>

Add a REG_CFA_RESTORE REG note to INSN or queue them until next stack manipulation insn . The value is on the stack at CFA - CFA_OFFSET . Do n't add the note if the previously saved value will be left untouched within stack red-zone till return , as unwinders can find the same value in the register and on the stack .


<s> static void ix86_add_new_builtins ( HOST_WIDE_INT isa ) { if ( ( isa & deferred_isa_values ) == 0 ) return ; deferred_isa_values &= ~ isa ; int i ; tree saved_current_target_pragma = current_target_pragma ; current_target_pragma = NULL_TREE ; for ( i = 0 ; i < ( int ) IX86_BUILTIN_MAX ; i ++ ) { if ( ( ix86_builtins_isa [ i ] . isa & isa ) != 0 && ix86_builtins_isa [ i ] . set_and_not_built_p ) { tree decl , type ; ix86_builtins_isa [ i ] . set_and_not_built_p = false ; type = ix86_get_builtin_func_type ( ix86_builtins_isa [ i ] . tcode ) ; decl = add_builtin_function_ext_scope ( ix86_builtins_isa [ i ] . name , type , i , BUILT_IN_MD , NULL , NULL_TREE ) ; ix86_builtins [ i ] = decl ; if ( ix86_builtins_isa [ i ] . const_p ) TREE_READONLY ( decl ) = 1 ; if ( ix86_builtins_isa [ i ] . leaf_p ) DECL_ATTRIBUTES ( decl ) = build_tree_list ( get_identifier ( "leaf" ) , NULL_TREE ) ; if ( ix86_builtins_isa [ i ] . nothrow_p ) TREE_NOTHROW ( decl ) = 1 ; } } current_target_pragma = saved_current_target_pragma ; } </s>

Add any new builtin functions for a given ISA that may not have been declared . This saves a bit of space compared to adding all of the declarations to the tree , even if we did n't use them .


<s> static unsigned ix86_add_stmt_cost ( void * data , int count , enum vect_cost_for_stmt kind , struct _stmt_vec_info * stmt_info , int misalign , enum vect_cost_model_location where ) { unsigned * cost = ( unsigned * ) data ; unsigned retval = 0 ; tree vectype = stmt_info ? stmt_vectype ( stmt_info ) : NULL_TREE ; int stmt_cost = ix86_builtin_vectorization_cost ( kind , vectype , misalign ) ; if ( where == vect_body && stmt_info && stmt_in_inner_loop_p ( stmt_info ) ) count *= 50 ; retval = ( unsigned ) ( count * stmt_cost ) ; if ( TARGET_SILVERMONT || TARGET_INTEL ) if ( stmt_info && stmt_info -> stmt ) { tree lhs_op = gimple_get_lhs ( stmt_info -> stmt ) ; if ( lhs_op && TREE_CODE ( TREE_TYPE ( lhs_op ) ) == INTEGER_TYPE ) retval = ( retval * 17 ) / 10 ; } cost [ where ] += retval ; return retval ; } </s>


<s> static void ix86_adjust_counter ( rtx countreg , HOST_WIDE_INT value ) { rtx ( * gen_add ) ( rtx , rtx , rtx ) = GET_MODE ( countreg ) == DImode ? gen_adddi3 : gen_addsi3 ; emit_insn ( gen_add ( countreg , countreg , GEN_INT ( - value ) ) ) ; } </s>


<s> static void ix86_adjust_stack_and_probe ( const HOST_WIDE_INT size ) { const int dope = 4 * UNITS_PER_WORD ; rtx size_rtx = GEN_INT ( size ) , last ; if ( size <= 5 * PROBE_INTERVAL ) { HOST_WIDE_INT i , adjust ; bool first_probe = true ; for ( i = PROBE_INTERVAL ; i < size ; i += PROBE_INTERVAL ) { if ( first_probe ) { adjust = 2 * PROBE_INTERVAL + dope ; first_probe = false ; } else adjust = PROBE_INTERVAL ; emit_insn ( gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , - adjust ) ) ) ; emit_stack_probe ( stack_pointer_rtx ) ; } if ( first_probe ) adjust = size + PROBE_INTERVAL + dope ; else adjust = size + PROBE_INTERVAL - i ; emit_insn ( gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , - adjust ) ) ) ; emit_stack_probe ( stack_pointer_rtx ) ; last = emit_insn ( gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , PROBE_INTERVAL + dope ) ) ) ; } else { HOST_WIDE_INT rounded_size ; struct scratch_reg sr ; get_scratch_register_on_entry ( & sr ) ; rounded_size = size & - PROBE_INTERVAL ; emit_insn ( gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , - ( PROBE_INTERVAL + dope ) ) ) ) ; emit_move_insn ( sr . reg , GEN_INT ( - rounded_size ) ) ; emit_insn ( gen_rtx_SET ( VOIDmode , sr . reg , gen_rtx_PLUS ( Pmode , sr . reg , stack_pointer_rtx ) ) ) ; emit_insn ( ix86_gen_adjust_stack_and_probe ( sr . reg , sr . reg , size_rtx ) ) ; if ( size != rounded_size ) { emit_insn ( gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , rounded_size - size ) ) ) ; emit_stack_probe ( stack_pointer_rtx ) ; } last = emit_insn ( gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , PROBE_INTERVAL + dope ) ) ) ; release_scratch_register_on_entry ( & sr ) ; } gcc_assert ( cfun -> machine -> fs . cfa_reg != stack_pointer_rtx ) ; if ( size > 0 ) { rtx expr = gen_rtx_SEQUENCE ( VOIDmode , rtvec_alloc ( 2 ) ) ; XVECEXP ( expr , 0 , 0 ) = gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , - size ) ) ; XVECEXP ( expr , 0 , 1 ) = gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , PROBE_INTERVAL + dope + size ) ) ; add_reg_note ( last , REG_FRAME_RELATED_EXPR , expr ) ; RTX_FRAME_RELATED_P ( last ) = 1 ; cfun -> machine -> fs . sp_offset += size ; } emit_insn ( gen_blockage ( ) ) ; } </s>

Emit code to adjust the stack pointer by SIZE bytes while probing it .


<s> bool ix86_agi_dependent ( rtx_insn * set_insn , rtx_insn * use_insn ) { int i ; extract_insn_cached ( use_insn ) ; for ( i = recog_data . n_operands - 1 ; i >= 0 ; -- i ) if ( MEM_P ( recog_data . operand [ i ] ) ) { rtx addr = XEXP ( recog_data . operand [ i ] , 0 ) ; return modified_in_p ( addr , set_insn ) != 0 ; } return false ; } </s>

Return true iff USE_INSN has a memory address with operands set by SET_INSN .


Write the extra assembler code needed to declare a function properly .


<s> int ix86_attr_length_address_default ( rtx_insn * insn ) { int i ; if ( get_attr_type ( insn ) == TYPE_LEA ) { rtx set = PATTERN ( insn ) , addr ; if ( GET_CODE ( set ) == PARALLEL ) set = XVECEXP ( set , 0 , 0 ) ; gcc_assert ( GET_CODE ( set ) == SET ) ; addr = SET_SRC ( set ) ; return memory_address_length ( addr , true ) ; } extract_insn_cached ( insn ) ; for ( i = recog_data . n_operands - 1 ; i >= 0 ; -- i ) if ( MEM_P ( recog_data . operand [ i ] ) ) { constrain_operands_cached ( insn , reload_completed ) ; if ( which_alternative != - 1 ) { const char * constraints = recog_data . constraints [ i ] ; int alt = which_alternative ; while ( * constraints == '=' || * constraints == '+' ) constraints ++ ; while ( alt -- > 0 ) while ( * constraints ++ != ',' ) ; if ( * constraints == 'X' ) continue ; } return memory_address_length ( XEXP ( recog_data . operand [ i ] , 0 ) , false ) ; } return 0 ; } </s>

Compute default value for `` length_address '' attribute .


<s> static unsigned int ix86_autovectorize_vector_sizes ( void ) { return TARGET_AVX512F ? 64 | 32 | 16 : ( TARGET_AVX && ! TARGET_PREFER_AVX128 ) ? 32 | 16 : 0 ; } </s>

If AVX is enabled then try vectorizing with both 256bit and 128bit vectors . If AVX512F is enabled then try vectorizing with 512bit , 256bit and 128bit vectors .


<s>
static
void
ix86_avoid_jump_mispredicts
(
void
)
{
rtx_insn
*
insn
,
*
start
=
get_insns
(
)
;
int
nbytes
=
0
,
njumps
=
0
;
bool
isjump
=
false
;
for
(
insn
=
start
;
insn
;
insn
=
NEXT_INSN
(
insn
)
)
{
int
min_size
;
if
(
LABEL_P
(
insn
)
)
{
int
align
=
label_to_alignment
(
insn
)
;
int
max_skip
=
label_to_max_skip
(
insn
)
;
if
(
max_skip
>
15
)
max_skip
=
15
;
if
(
align
<=
0
||
(
align
<=
3
&&
max_skip
!=
(
1
<<
align
)
1
)
)
max_skip
=
0
;
if
(
dump_file
)
fprintf
(
dump_file
,
"Label %i with max_skip %i\n"
,
INSN_UID
(
insn
)
,
max_skip
)
;
if
(
max_skip
)
{
while
(
nbytes
+
max_skip
>=
16
)
{
start
=
NEXT_INSN
(
start
)
;
if
(
(
JUMP_P
(
start
)
&&
asm_noperands
(
PATTERN
(
start
)
)
<
0
)
||
CALL_P
(
start
)
)
njumps
,
isjump
=
true
;
else
isjump
=
false
;
nbytes
-=
min_insn_size
(
start
)
;
}
}
continue
;
}
min_size
=
min_insn_size
(
insn
)
;
nbytes
+=
min_size
;
if
(
dump_file
)
fprintf
(
dump_file
,
"Insn %i estimated to %i bytes\n"
,
INSN_UID
(
insn
)
,
min_size
)
;
if
(
(
JUMP_P
(
insn
)
&&
asm_noperands
(
PATTERN
(
insn
)
)
<
0
)
||
CALL_P
(
insn
)
)
njumps
++
;
else
continue
;
while
(
njumps
>
3
)
{
start
=
NEXT_INSN
(
start
)
;
if
(
(
JUMP_P
(
start
)
&&
asm_noperands
(
PATTERN
(
start
)
)
<
0
)
||
CALL_P
(
start
)
)
njumps
,
isjump
=
true
;
else
isjump
=
false
;
nbytes
-=
min_insn_size
(
start
)
;
}
gcc_assert
(
njumps
>=
0
)
;
if
(
dump_file
)
fprintf
(
dump_file
,
"Interval %i to %i has %i bytes\n"
,
INSN_UID
(
start
)
,
INSN_UID
(
insn
)
,
nbytes
)
;
if
(
njumps
==
3
&&
isjump
&&
nbytes
<
16
)
{
int
padsize
=
15
nbytes
+
min_insn_size
(
insn
)
;
if
(
dump_file
)
fprintf
(
dump_file
,
"Padding insn %i by %i bytes!\n"
,
INSN_UID
(
insn
)
,
padsize
)
;
emit_insn_before
(
gen_pad
(
GEN_INT
(
padsize
)
)
,
insn
)
;
}
}
}
</s>

AMD K8 core mispredicts jumps when there are more than 3 jumps in 16 byte window .


<s> bool ix86_avoid_lea_for_addr ( rtx_insn * insn , rtx operands [ ] ) { unsigned int regno0 , regno1 , regno2 ; int split_cost ; struct ix86_address parts ; int ok ; if ( ! TARGET_AVOID_LEA_FOR_ADDR || optimize_function_for_size_p ( cfun ) ) return false ; if ( REG_P ( operands [ 1 ] ) || ( SImode_address_operand ( operands [ 1 ] , VOIDmode ) && REG_P ( XEXP ( operands [ 1 ] , 0 ) ) ) ) return false ; if ( ! ix86_ok_to_clobber_flags ( insn ) ) return false ; ok = ix86_decompose_address ( operands [ 1 ] , & parts ) ; gcc_assert ( ok ) ; if ( ( parts . base != NULL_RTX ) + ( parts . index != NULL_RTX ) + ( parts . disp != NULL_RTX ) + ( parts . scale > 1 ) < 2 ) return false ; if ( parts . disp && flag_pic && ! LEGITIMATE_PIC_OPERAND_P ( parts . disp ) ) return false ; regno0 = true_regnum ( operands [ 0 ] ) ; regno1 = INVALID_REGNUM ; regno2 = INVALID_REGNUM ; if ( parts . base ) regno1 = true_regnum ( parts . base ) ; if ( parts . index ) regno2 = true_regnum ( parts . index ) ; split_cost = 0 ; if ( parts . base || parts . index ) { if ( regno1 != regno0 && regno2 != regno0 ) split_cost += 1 ; if ( parts . base && parts . index ) split_cost += 1 ; if ( parts . scale > 1 ) { if ( regno0 != regno1 ) split_cost += 1 ; else if ( regno2 == regno0 ) split_cost += 4 ; else split_cost += parts . scale ; } if ( parts . disp && parts . disp != const0_rtx ) split_cost += 1 ; split_cost -= 1 ; } return ! ix86_lea_outperforms ( insn , regno0 , regno1 , regno2 , split_cost , parts . scale > 1 ) ; } </s>

Return true if we need to split lea into a sequence of instructions to avoid AGU stalls during peephole2 .


<s> static void ix86_avx256_split_vector_move_misalign ( rtx op0 , rtx op1 ) { rtx m ; rtx ( * extract ) ( rtx , rtx , rtx ) ; rtx ( * load_unaligned ) ( rtx , rtx ) ; rtx ( * store_unaligned ) ( rtx , rtx ) ; machine_mode mode ; switch ( GET_MODE ( op0 ) ) { default : gcc_unreachable ( ) ; case V32QImode : extract = gen_avx_vextractf128v32qi ; load_unaligned = gen_avx_loaddquv32qi ; store_unaligned = gen_avx_storedquv32qi ; mode = V16QImode ; break ; case V8SFmode : extract = gen_avx_vextractf128v8sf ; load_unaligned = gen_avx_loadups256 ; store_unaligned = gen_avx_storeups256 ; mode = V4SFmode ; break ; case V4DFmode : extract = gen_avx_vextractf128v4df ; load_unaligned = gen_avx_loadupd256 ; store_unaligned = gen_avx_storeupd256 ; mode = V2DFmode ; break ; } if ( MEM_P ( op1 ) ) { if ( TARGET_AVX256_SPLIT_UNALIGNED_LOAD && optimize_insn_for_speed_p ( ) ) { rtx r = gen_reg_rtx ( mode ) ; m = adjust_address ( op1 , mode , 0 ) ; emit_move_insn ( r , m ) ; m = adjust_address ( op1 , mode , 16 ) ; r = gen_rtx_VEC_CONCAT ( GET_MODE ( op0 ) , r , m ) ; emit_move_insn ( op0 , r ) ; } else if ( misaligned_operand ( op1 , GET_MODE ( op1 ) ) ) emit_insn ( gen_rtx_SET ( VOIDmode , op0 , op1 ) ) ; else emit_insn ( load_unaligned ( op0 , op1 ) ) ; } else if ( MEM_P ( op0 ) ) { if ( TARGET_AVX256_SPLIT_UNALIGNED_STORE && optimize_insn_for_speed_p ( ) ) { m = adjust_address ( op0 , mode , 0 ) ; emit_insn ( extract ( m , op1 , const0_rtx ) ) ; m = adjust_address ( op0 , mode , 16 ) ; emit_insn ( extract ( m , op1 , const1_rtx ) ) ; } else emit_insn ( store_unaligned ( op0 , op1 ) ) ; } else gcc_unreachable ( ) ; } </s>

Split 32-byte AVX unaligned load and store if needed .


<s> void ix86_avx_emit_vzeroupper ( HARD_REG_SET regs_live ) { int i ; for ( i = FIRST_SSE_REG ; i <= LAST_SSE_REG ; i ++ ) if ( TEST_HARD_REG_BIT ( regs_live , i ) && ! call_used_regs [ i ] ) return ; if ( TARGET_64BIT ) for ( i = FIRST_REX_SSE_REG ; i <= LAST_REX_SSE_REG ; i ++ ) if ( TEST_HARD_REG_BIT ( regs_live , i ) && ! call_used_regs [ i ] ) return ; emit_insn ( gen_avx_vzeroupper ( ) ) ; } </s>


<s> static int ix86_avx_u128_mode_after ( int mode , rtx_insn * insn ) { rtx pat = PATTERN ( insn ) ; if ( vzeroupper_operation ( pat , VOIDmode ) || vzeroall_operation ( pat , VOIDmode ) ) return AVX_U128_CLEAN ; if ( CALL_P ( insn ) ) { bool avx_reg256_found = false ; note_stores ( pat , ix86_check_avx256_stores , & avx_reg256_found ) ; return avx_reg256_found ? AVX_U128_DIRTY : AVX_U128_CLEAN ; } return mode ; } </s>

Calculate mode of upper 128bit AVX registers after the insn .


<s> static int ix86_avx_u128_mode_needed ( rtx_insn * insn ) { if ( CALL_P ( insn ) ) { rtx link ; for ( link = CALL_INSN_FUNCTION_USAGE ( insn ) ; link ; link = XEXP ( link , 1 ) ) { if ( GET_CODE ( XEXP ( link , 0 ) ) == USE ) { rtx arg = XEXP ( XEXP ( link , 0 ) , 0 ) ; if ( ix86_check_avx256_register ( arg ) ) return AVX_U128_DIRTY ; } } return AVX_U128_CLEAN ; } subrtx_iterator :: array_type array ; FOR_EACH_SUBRTX ( iter , array , PATTERN ( insn ) , NONCONST ) if ( ix86_check_avx256_register ( * iter ) ) return AVX_U128_DIRTY ; return AVX_U128_ANY ; } </s>

Return needed mode for entity in optimize_mode_switching pass .


<s> bool ix86_bnd_prefixed_insn_p ( rtx insn ) { if ( insn && CALL_P ( insn ) ) { rtx call = get_call_rtx_from ( insn ) ; if ( call ) return CALL_EXPR_WITH_BOUNDS_P ( call ) ; } return chkp_function_instrumented_p ( current_function_decl ) ; } </s>

Return 1 if control tansfer instruction INSN should be encoded with bnd prefix . If insn is NULL then return 1 when control transfer instructions should be prefixed with bnd by default for current function .


<s> static tree ix86_build_builtin_va_list ( void ) { tree ret = ix86_build_builtin_va_list_abi ( ix86_abi ) ; if ( TARGET_64BIT ) { tree t ; if ( ix86_abi == MS_ABI ) { t = ix86_build_builtin_va_list_abi ( SYSV_ABI ) ; if ( TREE_CODE ( t ) != RECORD_TYPE ) t = build_variant_type_copy ( t ) ; sysv_va_list_type_node = t ; } else { t = ret ; if ( TREE_CODE ( t ) != RECORD_TYPE ) t = build_variant_type_copy ( t ) ; sysv_va_list_type_node = t ; } if ( ix86_abi != MS_ABI ) { t = ix86_build_builtin_va_list_abi ( MS_ABI ) ; if ( TREE_CODE ( t ) != RECORD_TYPE ) t = build_variant_type_copy ( t ) ; ms_va_list_type_node = t ; } else { t = ret ; if ( TREE_CODE ( t ) != RECORD_TYPE ) t = build_variant_type_copy ( t ) ; ms_va_list_type_node = t ; } } return ret ; } </s>


Returns the calling convention specific va_list date type . The argument ABI can be DEFAULT_ABI , MS_ABI , or SYSV_ABI .


<s> rtx ix86_build_const_vector ( machine_mode mode , bool vect , rtx value ) { int i , n_elt ; rtvec v ; machine_mode scalar_mode ; switch ( mode ) { case V64QImode : case V32QImode : case V16QImode : case V32HImode : case V16HImode : case V8HImode : case V16SImode : case V8SImode : case V4SImode : case V8DImode : case V4DImode : case V2DImode : gcc_assert ( vect ) ; case V16SFmode : case V8SFmode : case V4SFmode : case V8DFmode : case V4DFmode : case V2DFmode : n_elt = GET_MODE_NUNITS ( mode ) ; v = rtvec_alloc ( n_elt ) ; scalar_mode = GET_MODE_INNER ( mode ) ; RTVEC_ELT ( v , 0 ) = value ; for ( i = 1 ; i < n_elt ; ++ i ) RTVEC_ELT ( v , i ) = vect ? value : CONST0_RTX ( scalar_mode ) ; return gen_rtx_CONST_VECTOR ( mode , v ) ; default : gcc_unreachable ( ) ; } } </s>

A subroutine of ix86_build_signbit_mask . If VECT is true , then replicate the value for all elements of the vector register .


<s> rtx ix86_build_signbit_mask ( machine_mode mode , bool vect , bool invert ) { machine_mode vec_mode , imode ; HOST_WIDE_INT hi , lo ; int shift = 63 ; rtx v ; rtx mask ; switch ( mode ) { case V16SImode : case V16SFmode : case V8SImode : case V4SImode : case V8SFmode : case V4SFmode : vec_mode = mode ; mode = GET_MODE_INNER ( mode ) ; imode = SImode ; lo = 0x80000000 , hi = lo < 0 ; break ; case V8DImode : case V4DImode : case V2DImode : case V8DFmode : case V4DFmode : case V2DFmode : vec_mode = mode ; mode = GET_MODE_INNER ( mode ) ; imode = DImode ; if ( HOST_BITS_PER_WIDE_INT >= 64 ) lo = ( HOST_WIDE_INT ) 1 << shift , hi = - 1 ; else lo = 0 , hi = ( HOST_WIDE_INT ) 1 << ( shift - HOST_BITS_PER_WIDE_INT ) ; break ; case TImode : case TFmode : vec_mode = VOIDmode ; if ( HOST_BITS_PER_WIDE_INT >= 64 ) { imode = TImode ; lo = 0 , hi = ( HOST_WIDE_INT ) 1 << shift ; } else { rtvec vec ; imode = DImode ; lo = 0 , hi = ( HOST_WIDE_INT ) 1 << ( shift - HOST_BITS_PER_WIDE_INT ) ; if ( invert ) { lo = ~ lo , hi = ~ hi ; v = constm1_rtx ; } else v = const0_rtx ; mask = immed_double_const ( lo , hi , imode ) ; vec = gen_rtvec ( 2 , v , mask ) ; v = gen_rtx_CONST_VECTOR ( V2DImode , vec ) ; v = copy_to_mode_reg ( mode , gen_lowpart ( mode , v ) ) ; return v ; } break ; default : gcc_unreachable ( ) ; } if ( invert ) lo = ~ lo , hi = ~ hi ; mask = immed_double_const ( lo , hi , imode ) ; mask = gen_lowpart ( mode , mask ) ; if ( vec_mode == VOIDmode ) return force_reg ( mode , mask ) ; v = ix86_build_const_vector ( vec_mode , vect , mask ) ; return force_reg ( vec_mode , v ) ; } </s>

A subroutine of ix86_expand_fp_absneg_operator and copysign expanders . Create a mask for the sign bit in MODE for an SSE register . If VECT is true , then replicate the mask for all elements of the vector register . If INVERT is true , then create a mask excluding the sign bit .


<s> static tree ix86_builtin_decl ( unsigned code , bool ) { if ( code >= IX86_BUILTIN_MAX ) return error_mark_node ; return ix86_builtins [ code ] ; } </s>


<s> static tree ix86_builtin_mpx_function ( unsigned fcode ) { switch ( fcode ) { case BUILT_IN_CHKP_BNDMK : return ix86_builtins [ IX86_BUILTIN_BNDMK ] ; case BUILT_IN_CHKP_BNDSTX : return ix86_builtins [ IX86_BUILTIN_BNDSTX ] ; case BUILT_IN_CHKP_BNDLDX : return ix86_builtins [ IX86_BUILTIN_BNDLDX ] ; case BUILT_IN_CHKP_BNDCL : return ix86_builtins [ IX86_BUILTIN_BNDCL ] ; case BUILT_IN_CHKP_BNDCU : return ix86_builtins [ IX86_BUILTIN_BNDCU ] ; case BUILT_IN_CHKP_BNDRET : return ix86_builtins [ IX86_BUILTIN_BNDRET ] ; case BUILT_IN_CHKP_INTERSECT : return ix86_builtins [ IX86_BUILTIN_BNDINT ] ; case BUILT_IN_CHKP_NARROW : return ix86_builtins [ IX86_BUILTIN_BNDNARROW ] ; case BUILT_IN_CHKP_SIZEOF : return ix86_builtins [ IX86_BUILTIN_SIZEOF ] ; case BUILT_IN_CHKP_EXTRACT_LOWER : return ix86_builtins [ IX86_BUILTIN_BNDLOWER ] ; case BUILT_IN_CHKP_EXTRACT_UPPER : return ix86_builtins [ IX86_BUILTIN_BNDUPPER ] ; default : return NULL_TREE ; } gcc_unreachable ( ) ; } </s>

Return function decl for target specific builtin for given MPX builtin passed i FCODE .


<s> static tree ix86_builtin_reciprocal ( unsigned int fn , bool md_fn , bool ) { if ( ! ( TARGET_SSE_MATH && ! optimize_insn_for_size_p ( ) && flag_finite_math_only && ! flag_trapping_math && flag_unsafe_math_optimizations ) ) return NULL_TREE ; if ( md_fn ) switch ( fn ) { case IX86_BUILTIN_SQRTPS_NR : return ix86_get_builtin ( IX86_BUILTIN_RSQRTPS_NR ) ; case IX86_BUILTIN_SQRTPS_NR256 : return ix86_get_builtin ( IX86_BUILTIN_RSQRTPS_NR256 ) ; default : return NULL_TREE ; } else switch ( fn ) { case BUILT_IN_SQRTF : return ix86_get_builtin ( IX86_BUILTIN_RSQRTF ) ; default : return NULL_TREE ; } } </s>

Returns a code for a target-specific builtin that implements reciprocal of the function , or NULL_TREE if not available .


<s> static rtx ix86_builtin_setjmp_frame_value ( void ) { return stack_realign_fp ? hard_frame_pointer_rtx : virtual_stack_vars_rtx ; } </s>

In a dynamically-aligned function , we ca n't know the offset from stack pointer to frame pointer , so we must ensure that setjmp eliminates fp against the hard fp ( % ebp ) rather than trying to index from % esp up to the top of the frame across a gap that is of unknown ( at compile-time ) size .


<s> static tree ix86_builtin_tm_load ( tree type ) { if ( TREE_CODE ( type ) == VECTOR_TYPE ) { switch ( tree_to_uhwi ( TYPE_SIZE ( type ) ) ) { case 64 : return builtin_decl_explicit ( BUILT_IN_TM_LOAD_M64 ) ; case 128 : return builtin_decl_explicit ( BUILT_IN_TM_LOAD_M128 ) ; case 256 : return builtin_decl_explicit ( BUILT_IN_TM_LOAD_M256 ) ; } } return NULL_TREE ; } </s>

Return the builtin decl needed to load a vector of TYPE .


<s> static tree ix86_builtin_tm_store ( tree type ) { if ( TREE_CODE ( type ) == VECTOR_TYPE ) { switch ( tree_to_uhwi ( TYPE_SIZE ( type ) ) ) { case 64 : return builtin_decl_explicit ( BUILT_IN_TM_STORE_M64 ) ; case 128 : return builtin_decl_explicit ( BUILT_IN_TM_STORE_M128 ) ; case 256 : return builtin_decl_explicit ( BUILT_IN_TM_STORE_M256 ) ; } } return NULL_TREE ; } </s>

Return the builtin decl needed to store a vector of TYPE .


<s> static int ix86_builtin_vectorization_cost ( enum vect_cost_for_stmt type_of_cost , tree vectype , int ) { unsigned elements ; switch ( type_of_cost ) { case scalar_stmt : return ix86_cost -> scalar_stmt_cost ; case scalar_load : return ix86_cost -> scalar_load_cost ; case scalar_store : return ix86_cost -> scalar_store_cost ; case vector_stmt : return ix86_cost -> vec_stmt_cost ; case vector_load : return ix86_cost -> vec_align_load_cost ; case vector_store : return ix86_cost -> vec_store_cost ; case vec_to_scalar : return ix86_cost -> vec_to_scalar_cost ; case scalar_to_vec : return ix86_cost -> scalar_to_vec_cost ; case unaligned_load : case unaligned_store : return ix86_cost -> vec_unalign_load_cost ; 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_cost -> vec_stmt_cost ; case vec_construct : elements = TYPE_VECTOR_SUBPARTS ( vectype ) ; return elements / 2 + 1 ; default : gcc_unreachable ( ) ; } } </s>


<s> void ix86_call_abi_override ( const_tree fndecl ) { if ( fndecl == NULL_TREE ) cfun -> machine -> call_abi = ix86_abi ; else cfun -> machine -> call_abi = ix86_function_type_abi ( TREE_TYPE ( 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_cannot_change_mode_class ( machine_mode from , machine_mode to , enum reg_class regclass ) { if ( from == to ) return false ; if ( MAYBE_FLOAT_CLASS_P ( regclass ) ) return true ; if ( MAYBE_SSE_CLASS_P ( regclass ) || MAYBE_MMX_CLASS_P ( regclass ) ) { if ( GET_MODE_SIZE ( from ) < 4 ) return true ; } return false ; } </s>

Return true if the registers in CLASS can not represent the change from modes FROM to TO .


<s> static bool ix86_cannot_force_const_mem ( machine_mode mode , rtx x ) { switch ( GET_CODE ( x ) ) { case CONST_INT : case CONST_DOUBLE : case CONST_VECTOR : 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 tree ix86_canonical_va_list_type ( tree type ) { tree wtype , htype ; if ( TREE_CODE ( type ) == MEM_REF ) type = TREE_TYPE ( type ) ; else if ( POINTER_TYPE_P ( type ) && POINTER_TYPE_P ( TREE_TYPE ( type ) ) ) type = TREE_TYPE ( type ) ; else if ( POINTER_TYPE_P ( type ) && TREE_CODE ( TREE_TYPE ( type ) ) == ARRAY_TYPE ) type = TREE_TYPE ( type ) ; if ( TARGET_64BIT && va_list_type_node != NULL_TREE ) { wtype = va_list_type_node ; gcc_assert ( wtype != NULL_TREE ) ; htype = type ; if ( TREE_CODE ( wtype ) == ARRAY_TYPE ) { if ( TREE_CODE ( htype ) == ARRAY_TYPE || POINTER_TYPE_P ( htype ) ) { wtype = TREE_TYPE ( wtype ) ; htype = TREE_TYPE ( htype ) ; } } if ( TYPE_MAIN_VARIANT ( wtype ) == TYPE_MAIN_VARIANT ( htype ) ) return va_list_type_node ; wtype = sysv_va_list_type_node ; gcc_assert ( wtype != NULL_TREE ) ; htype = type ; if ( TREE_CODE ( wtype ) == ARRAY_TYPE ) { if ( TREE_CODE ( htype ) == ARRAY_TYPE || POINTER_TYPE_P ( htype ) ) { wtype = TREE_TYPE ( wtype ) ; htype = TREE_TYPE ( htype ) ; } } if ( TYPE_MAIN_VARIANT ( wtype ) == TYPE_MAIN_VARIANT ( htype ) ) return sysv_va_list_type_node ; wtype = ms_va_list_type_node ; gcc_assert ( wtype != NULL_TREE ) ; htype = type ; if ( TREE_CODE ( wtype ) == ARRAY_TYPE ) { if ( TREE_CODE ( htype ) == ARRAY_TYPE || POINTER_TYPE_P ( htype ) ) { wtype = TREE_TYPE ( wtype ) ; htype = TREE_TYPE ( htype ) ; } } if ( TYPE_MAIN_VARIANT ( wtype ) == TYPE_MAIN_VARIANT ( htype ) ) return ms_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 .


<s> static bool ix86_can_inline_p ( tree caller , tree callee ) { bool ret = false ; tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET ( caller ) ; tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET ( callee ) ; if ( ! callee_tree ) ret = true ; else if ( ! caller_tree ) ret = false ; else { struct cl_target_option * caller_opts = TREE_TARGET_OPTION ( caller_tree ) ; struct cl_target_option * callee_opts = TREE_TARGET_OPTION ( callee_tree ) ; if ( ( caller_opts -> x_ix86_isa_flags & callee_opts -> x_ix86_isa_flags ) != callee_opts -> x_ix86_isa_flags ) ret = false ; else if ( caller_opts -> x_target_flags != callee_opts -> x_target_flags ) ret = false ; else if ( caller_opts -> arch != callee_opts -> arch ) ret = false ; else if ( caller_opts -> tune != callee_opts -> tune ) ret = false ; else if ( caller_opts -> x_ix86_fpmath != callee_opts -> x_ix86_fpmath ) ret = false ; else if ( 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 ) { struct ix86_frame frame ; if ( ! reload_completed || frame_pointer_needed ) return 0 ; if ( crtl -> args . pops_args && crtl -> args . size >= 32768 ) return 0 ; ix86_compute_frame_layout ( & 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 == CCZmode && ( m2 == CCGCmode || m2 == CCGOCmode ) ) return m2 ; else if ( m2 == CCZmode && ( m1 == CCGCmode || m1 == CCGOCmode ) ) return m1 ; switch ( m1 ) { default : gcc_unreachable ( ) ; case CCmode : case CCGCmode : case CCGOCmode : case CCNOmode : case CCAmode : case CCCmode : case CCOmode : case CCSmode : case CCZmode : switch ( m2 ) { default : return VOIDmode ; case CCmode : case CCGCmode : case CCGOCmode : case CCNOmode : case CCAmode : case CCCmode : case CCOmode : case CCSmode : case CCZmode : return CCmode ; } case CCFPmode : case CCFPUmode : 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 ) { if ( ! cfun ) return ix86_abi ; return cfun -> machine -> call_abi ; } </s>

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


<s> static bool ix86_check_avx256_register ( const_rtx exp ) { if ( GET_CODE ( exp ) == SUBREG ) exp = SUBREG_REG ( exp ) ; return ( REG_P ( exp ) && VALID_AVX256_REG_OR_OI_MODE ( GET_MODE ( exp ) ) ) ; } </s>

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


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

Check if a 256bit 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 ( GET_CODE ( mem ) == SUBREG ) 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> 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 : case BND_REGS : 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 ( ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / 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 .