<s> static unsigned int rest_of_insert_endbranch ( void ) { timevar_push ( TV_MACH_DEP ) ; rtx cet_eb ; rtx_insn * insn ; basic_block bb ; if ( ! lookup_attribute ( "nocf_check" , TYPE_ATTRIBUTES ( TREE_TYPE ( cfun -> decl ) ) ) && ! cgraph_node :: get ( cfun -> decl ) -> only_called_directly_p ( ) ) { cet_eb = gen_nop_endbr ( ) ; bb = ENTRY_BLOCK_PTR_FOR_FN ( cfun ) -> next_bb ; insn = BB_HEAD ( bb ) ; emit_insn_before ( cet_eb , insn ) ; } bb = 0 ; FOR_EACH_BB_FN ( bb , cfun ) { for ( insn = BB_HEAD ( bb ) ; insn != NEXT_INSN ( BB_END ( bb ) ) ; insn = NEXT_INSN ( insn ) ) { if ( CALL_P ( insn ) ) { if ( find_reg_note ( insn , REG_SETJMP , NULL ) == NULL ) continue ; cet_eb = gen_nop_endbr ( ) ; emit_insn_after_setloc ( cet_eb , insn , INSN_LOCATION ( insn ) ) ; continue ; } if ( JUMP_P ( insn ) && flag_cet_switch ) { rtx target = JUMP_LABEL ( insn ) ; if ( target == NULL_RTX || ANY_RETURN_P ( target ) ) continue ; rtx_insn * label = as_a < rtx_insn * > ( target ) ; rtx_insn * table = next_insn ( label ) ; if ( table == NULL_RTX || ! JUMP_TABLE_DATA_P ( table ) ) continue ; edge_iterator ei ; edge e ; basic_block dest_blk ; FOR_EACH_EDGE ( e , ei , bb -> succs ) { rtx_insn * insn ; dest_blk = e -> dest ; insn = BB_HEAD ( dest_blk ) ; gcc_assert ( LABEL_P ( insn ) ) ; cet_eb = gen_nop_endbr ( ) ; emit_insn_after ( cet_eb , insn ) ; } continue ; } if ( ( LABEL_P ( insn ) && LABEL_PRESERVE_P ( insn ) ) || ( NOTE_P ( insn ) && NOTE_KIND ( insn ) == NOTE_INSN_DELETED_LABEL ) ) { cet_eb = gen_nop_endbr ( ) ; emit_insn_after ( cet_eb , insn ) ; continue ; } } } timevar_pop ( TV_MACH_DEP ) ; return 0 ; } </s>


"List of x86 specific tuning parameter names:\n"

Helper function to set ix86_tune_features . IX86_TUNE is the processor type .


<s> void split_double_mode ( machine_mode mode , rtx operands [ ] , int num , rtx lo_half [ ] , rtx hi_half [ ] ) { machine_mode half_mode ; unsigned int byte ; switch ( mode ) { case E_TImode : half_mode = DImode ; break ; case E_DImode : half_mode = SImode ; break ; default : gcc_unreachable ( ) ; } byte = GET_MODE_SIZE ( half_mode ) ; while ( num -- ) { rtx op = operands [ num ] ; if ( MEM_P ( op ) ) { lo_half [ num ] = adjust_address ( op , half_mode , 0 ) ; hi_half [ num ] = adjust_address ( op , half_mode , byte ) ; } else { lo_half [ num ] = simplify_gen_subreg ( half_mode , op , GET_MODE ( op ) == VOIDmode ? mode : GET_MODE ( op ) , 0 ) ; hi_half [ num ] = simplify_gen_subreg ( half_mode , op , GET_MODE ( op ) == VOIDmode ? mode : GET_MODE ( op ) , byte ) ; } } } </s>

Split one or more double-mode RTL references into pairs of half-mode references . The RTL can be REG , offsettable MEM , integer constant , or CONST_DOUBLE . `` operands '' is a pointer to an array of double-mode RTLs to split and `` num '' is its length . lo_half and hi_half are output arrays that parallel `` operands '' .


"-mcall-ms2sysv-xlogues is not compatible with %s"

Emits a warning for unsupported msabi to sysv pro/epilogues .


<s>
static
void
x86_print_call_or_nop
(
FILE
*
file
,
const
char
*
target
)
{
if
(
flag_nop_mcount
)
fprintf
(
file
,
"1:"
ASM_BYTE
"0x0f, 0x1f, 0x44, 0x00, 0x00\n"
)
;
else
fprintf
(
file
,
"1:\tcall\t%s\n"
,
target
)
;
}
</s>


<s> static inline tree def_builtin ( HOST_WIDE_INT mask , HOST_WIDE_INT mask2 , 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 ; ix86_builtins_isa [ ( int ) code ] . isa2 = mask2 ; mask &= ~ OPTION_MASK_ISA_64BIT ; if ( ( mask & ix86_isa_flags & OPTION_MASK_ISA_AVX512VL ) && mask != OPTION_MASK_ISA_AVX512VL ) mask &= ~ OPTION_MASK_ISA_AVX512VL ; if ( ( mask & ix86_isa_flags & OPTION_MASK_ISA_AVX512BW ) && mask != OPTION_MASK_ISA_AVX512BW ) mask &= ~ OPTION_MASK_ISA_AVX512BW ; if ( ( ( mask2 == 0 || ( mask2 & ix86_isa_flags2 ) != 0 ) && ( 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 ; deferred_isa_values2 |= mask2 ; 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 ] . const_p = false ; ix86_builtins_isa [ ( int ) code ] . pure_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 bool dimode_scalar_to_vector_candidate_p ( rtx_insn * insn ) { rtx def_set = single_set ( insn ) ; if ( ! def_set ) return false ; if ( has_non_address_hard_reg ( insn ) ) return false ; rtx src = SET_SRC ( def_set ) ; rtx dst = SET_DEST ( def_set ) ; if ( GET_CODE ( src ) == COMPARE ) return convertible_comparison_p ( insn ) ; if ( ( GET_MODE ( src ) != DImode && ! CONST_INT_P ( src ) ) || GET_MODE ( dst ) != DImode ) return false ; if ( ! REG_P ( dst ) && ! MEM_P ( dst ) ) return false ; switch ( GET_CODE ( src ) ) { case ASHIFTRT : if ( ! TARGET_AVX512VL ) return false ; case ASHIFT : case LSHIFTRT : if ( ! CONST_INT_P ( XEXP ( src , 1 ) ) || ! IN_RANGE ( INTVAL ( XEXP ( src , 1 ) ) , 0 , 63 ) ) return false ; break ; case PLUS : case MINUS : case IOR : case XOR : case AND : if ( ! REG_P ( XEXP ( src , 1 ) ) && ! MEM_P ( XEXP ( src , 1 ) ) && ! CONST_INT_P ( XEXP ( src , 1 ) ) ) return false ; if ( GET_MODE ( XEXP ( src , 1 ) ) != DImode && ! CONST_INT_P ( XEXP ( src , 1 ) ) ) return false ; break ; case NEG : case NOT : break ; case REG : return true ; case MEM : case CONST_INT : return REG_P ( dst ) ; default : return false ; } if ( ! REG_P ( XEXP ( src , 0 ) ) && ! MEM_P ( XEXP ( src , 0 ) ) && ! CONST_INT_P ( XEXP ( src , 0 ) ) && ( GET_CODE ( src ) != AND || GET_CODE ( XEXP ( src , 0 ) ) != NOT || ! REG_P ( XEXP ( XEXP ( src , 0 ) , 0 ) ) ) ) return false ; if ( GET_MODE ( XEXP ( src , 0 ) ) != DImode && ! CONST_INT_P ( XEXP ( src , 0 ) ) ) return false ; return true ; } </s>

The DImode version of scalar_to_vector_candidate_p .


<s> static inline int inline_memory_move_cost ( machine_mode mode , enum reg_class regclass , int in ) { int cost ; if ( FLOAT_CLASS_P ( regclass ) ) { int index ; switch ( mode ) { case E_SFmode : index = 0 ; break ; case E_DFmode : index = 1 ; break ; case E_XFmode : index = 2 ; break ; default : return 100 ; } if ( in == 2 ) return MAX ( ix86_cost -> fp_load [ index ] , ix86_cost -> fp_store [ index ] ) ; return in ? ix86_cost -> fp_load [ index ] : ix86_cost -> fp_store [ index ] ; } if ( SSE_CLASS_P ( regclass ) ) { int index = sse_store_index ( mode ) ; if ( index == - 1 ) return 100 ; if ( in == 2 ) return MAX ( ix86_cost -> sse_load [ index ] , ix86_cost -> sse_store [ index ] ) ; return in ? ix86_cost -> sse_load [ index ] : ix86_cost -> sse_store [ index ] ; } if ( MMX_CLASS_P ( regclass ) ) { int index ; switch ( GET_MODE_SIZE ( mode ) ) { case 4 : index = 0 ; break ; case 8 : index = 1 ; break ; default : return 100 ; } if ( in == 2 ) return MAX ( ix86_cost -> mmx_load [ index ] , ix86_cost -> mmx_store [ index ] ) ; return in ? ix86_cost -> mmx_load [ index ] : ix86_cost -> mmx_store [ index ] ; } switch ( GET_MODE_SIZE ( mode ) ) { case 1 : if ( Q_CLASS_P ( regclass ) || TARGET_64BIT ) { if ( ! in ) return ix86_cost -> int_store [ 0 ] ; if ( TARGET_PARTIAL_REG_DEPENDENCY && optimize_function_for_speed_p ( cfun ) ) cost = ix86_cost -> movzbl_load ; else cost = ix86_cost -> int_load [ 0 ] ; if ( in == 2 ) return MAX ( cost , ix86_cost -> int_store [ 0 ] ) ; return cost ; } else { if ( in == 2 ) return MAX ( ix86_cost -> movzbl_load , ix86_cost -> int_store [ 0 ] + 4 ) ; if ( in ) return ix86_cost -> movzbl_load ; else return ix86_cost -> int_store [ 0 ] + 4 ; } break ; case 2 : if ( in == 2 ) return MAX ( ix86_cost -> int_load [ 1 ] , ix86_cost -> int_store [ 1 ] ) ; return in ? ix86_cost -> int_load [ 1 ] : ix86_cost -> int_store [ 1 ] ; default : if ( in == 2 ) cost = MAX ( ix86_cost -> int_load [ 2 ] , ix86_cost -> int_store [ 2 ] ) ; else if ( in ) cost = ix86_cost -> int_load [ 2 ] ; else cost = ix86_cost -> int_store [ 2 ] ; return cost * CEIL ( ( int ) GET_MODE_SIZE ( mode ) , UNITS_PER_WORD ) ; } } </s>

Return the cost of moving data of mode M between a register and memory . A value of 2 is the default ; this cost is relative to those in ` REGISTER_MOVE_COST ' . This function is used extensively by register_move_cost that is used to build tables at startup . Make it inline in this case . When IN is 2 , return maximum of in and out move cost . If moving between registers and memory is more expensive than between two registers , you should define this macro to express the relative cost . Model also increased moving costs of QImode registers in non Q_REGS classes .


<s> static void ix86_add_new_builtins ( HOST_WIDE_INT isa , HOST_WIDE_INT isa2 ) { isa &= ~ OPTION_MASK_ISA_64BIT ; if ( ( isa & deferred_isa_values ) == 0 && ( isa2 & deferred_isa_values2 ) == 0 ) return ; deferred_isa_values &= ~ isa ; deferred_isa_values2 &= ~ isa2 ; 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 ] . isa2 & isa2 ) != 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 ; } } 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 int ix86_avx_u128_mode_after ( int mode , rtx_insn * insn ) { rtx pat = PATTERN ( insn ) ; if ( vzeroupper_pattern ( pat , VOIDmode ) || vzeroall_pattern ( pat , VOIDmode ) ) return AVX_U128_CLEAN ; if ( CALL_P ( insn ) ) { bool avx_upper_reg_found = false ; note_stores ( pat , ix86_check_avx_upper_stores , & avx_upper_reg_found ) ; return avx_upper_reg_found ? AVX_U128_DIRTY : AVX_U128_CLEAN ; } return mode ; } </s>

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


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

Update register usage after having seen the compiler flags .


<s>
void
ATTRIBUTE_UNUSED
ix86_debug_options
(
void
)
{
char
*
opts
=
ix86_target_string
(
ix86_isa_flags
,
ix86_isa_flags2
,
target_flags
,
ix86_target_flags
,
ix86_arch_string
,
ix86_tune_string
,
ix86_fpmath
,
true
,
true
)
;
if
(
opts
)
{
fprintf
(
stderr
,
"%s\n\n"
,
opts
)
;
free
(
opts
)
;
}
else
fputs
(
"<no options>\n\n"
,
stderr
)
;
return
;
}
</s>

Function that is callable from the debugger to print the current options .


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

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


<s> static void ix86_expand_divmod_libfunc ( rtx libfunc , machine_mode mode , rtx op0 , rtx op1 , rtx * quot_p , rtx * rem_p ) { rtx rem = assign_386_stack_local ( mode , SLOT_TEMP ) ; rtx quot = emit_library_call_value ( libfunc , NULL_RTX , LCT_NORMAL , mode , op0 , mode , op1 , mode , XEXP ( rem , 0 ) , Pmode ) ; * quot_p = quot ; * rem_p = rem ; } </s>


<s> static rtx ix86_expand_sse_cmp ( rtx dest , enum rtx_code code , rtx cmp_op0 , rtx cmp_op1 , rtx op_true , rtx op_false ) { machine_mode mode = GET_MODE ( dest ) ; machine_mode cmp_ops_mode = GET_MODE ( cmp_op0 ) ; machine_mode cmp_mode ; bool maskcmp = false ; rtx x ; if ( GET_MODE_SIZE ( cmp_ops_mode ) == 64 ) { unsigned int nbits = GET_MODE_NUNITS ( cmp_ops_mode ) ; cmp_mode = int_mode_for_size ( nbits , 0 ) . require ( ) ; maskcmp = true ; } else cmp_mode = cmp_ops_mode ; cmp_op0 = force_reg ( cmp_ops_mode , cmp_op0 ) ; int ( * op1_predicate ) ( rtx , machine_mode ) = VECTOR_MODE_P ( cmp_ops_mode ) ? vector_operand : nonimmediate_operand ; if ( ! op1_predicate ( cmp_op1 , cmp_ops_mode ) ) cmp_op1 = force_reg ( cmp_ops_mode , cmp_op1 ) ; if ( optimize || ( maskcmp && cmp_mode != mode ) || ( op_true && reg_overlap_mentioned_p ( dest , op_true ) ) || ( op_false && reg_overlap_mentioned_p ( dest , op_false ) ) ) dest = gen_reg_rtx ( maskcmp ? cmp_mode : mode ) ; if ( maskcmp && ( code == GT || code == EQ ) ) { rtx ( * gen ) ( rtx , rtx , rtx ) ; switch ( cmp_ops_mode ) { case E_V64QImode : gcc_assert ( TARGET_AVX512BW ) ; gen = code == GT ? gen_avx512bw_gtv64qi3 : gen_avx512bw_eqv64qi3_1 ; break ; case E_V32HImode : gcc_assert ( TARGET_AVX512BW ) ; gen = code == GT ? gen_avx512bw_gtv32hi3 : gen_avx512bw_eqv32hi3_1 ; break ; case E_V16SImode : gen = code == GT ? gen_avx512f_gtv16si3 : gen_avx512f_eqv16si3_1 ; break ; case E_V8DImode : gen = code == GT ? gen_avx512f_gtv8di3 : gen_avx512f_eqv8di3_1 ; break ; default : gen = NULL ; } if ( gen ) { emit_insn ( gen ( dest , cmp_op0 , cmp_op1 ) ) ; return dest ; } } x = gen_rtx_fmt_ee ( code , cmp_mode , cmp_op0 , cmp_op1 ) ; if ( cmp_mode != mode && ! maskcmp ) { x = force_reg ( cmp_ops_mode , x ) ; convert_move ( dest , x , false ) ; } else emit_insn ( gen_rtx_SET ( dest , x ) ) ; return dest ; } </s>

Expand an sse vector comparison . Return the register with the result .


<s> void ix86_expand_xorsign ( rtx operands [ ] ) { rtx ( * xorsign_insn ) ( rtx , rtx , rtx , rtx ) ; machine_mode mode , vmode ; rtx dest , op0 , op1 , mask ; dest = operands [ 0 ] ; op0 = operands [ 1 ] ; op1 = operands [ 2 ] ; mode = GET_MODE ( dest ) ; if ( mode == SFmode ) { xorsign_insn = gen_xorsignsf3_1 ; vmode = V4SFmode ; } else if ( mode == DFmode ) { xorsign_insn = gen_xorsigndf3_1 ; vmode = V2DFmode ; } else gcc_unreachable ( ) ; mask = ix86_build_signbit_mask ( vmode , 0 , 0 ) ; emit_insn ( xorsign_insn ( dest , op0 , op1 , mask ) ) ; } </s>


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

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


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

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


<s>
static
void
ix86_function_specific_print
(
FILE
*
file
,
int
indent
,
struct
cl_target_option
*
ptr
)
{
char
*
target_string
=
ix86_target_string
(
ptr
->
x_ix86_isa_flags
,
ptr
->
x_ix86_isa_flags2
,
ptr
->
x_target_flags
,
ptr
->
x_ix86_target_flags
,
,
,
ptr
->
x_ix86_fpmath
,
false
,
true
)
;
gcc_assert
(
ptr
->
arch
<
PROCESSOR_max
)
;
fprintf
(
file
,
"%*sarch = %d (%s)\n"
,
indent
,
""
,
ptr
->
arch
,
processor_names
[
ptr
->
arch
]
)
;
gcc_assert
(
ptr
->
tune
<
PROCESSOR_max
)
;
fprintf
(
file
,
"%*stune = %d (%s)\n"
,
indent
,
""
,
ptr
->
tune
,
processor_names
[
ptr
->
tune
]
)
;
fprintf
(
file
,
"%*sbranch_cost = %d\n"
,
indent
,
""
,
ptr
->
branch_cost
)
;
if
(
target_string
)
{
fprintf
(
file
,
"%*s%s\n"
,
indent
,
""
,
target_string
)
;
free
(
target_string
)
;
}
}
</s>


<s> static void ix86_function_specific_restore ( struct gcc_options * opts , struct cl_target_option * ptr ) { enum processor_type old_tune = ix86_tune ; enum processor_type old_arch = ix86_arch ; unsigned HOST_WIDE_INT ix86_arch_mask ; int i ; opts -> x_flag_pic = flag_pic ; ix86_arch = ( enum processor_type ) ptr -> arch ; ix86_schedule = ( enum attr_cpu ) ptr -> schedule ; ix86_tune = ( enum processor_type ) ptr -> tune ; x86_prefetch_sse = ptr -> prefetch_sse ; opts -> x_ix86_branch_cost = ptr -> branch_cost ; ix86_tune_defaulted = ptr -> tune_defaulted ; ix86_arch_specified = ptr -> arch_specified ; opts -> x_ix86_isa_flags_explicit = ptr -> x_ix86_isa_flags_explicit ; opts -> x_ix86_isa_flags2_explicit = ptr -> x_ix86_isa_flags2_explicit ; opts -> x_recip_mask_explicit = ptr -> x_recip_mask_explicit ; opts -> x_ix86_arch_string = ptr -> x_ix86_arch_string ; opts -> x_ix86_tune_string = ptr -> x_ix86_tune_string ; opts -> x_ix86_cmodel = ptr -> x_ix86_cmodel ; opts -> x_ix86_abi = ptr -> x_ix86_abi ; opts -> x_ix86_asm_dialect = ptr -> x_ix86_asm_dialect ; opts -> x_ix86_branch_cost = ptr -> x_ix86_branch_cost ; opts -> x_ix86_dump_tunes = ptr -> x_ix86_dump_tunes ; opts -> x_ix86_force_align_arg_pointer = ptr -> x_ix86_force_align_arg_pointer ; opts -> x_ix86_force_drap = ptr -> x_ix86_force_drap ; opts -> x_ix86_incoming_stack_boundary_arg = ptr -> x_ix86_incoming_stack_boundary_arg ; opts -> x_ix86_pmode = ptr -> x_ix86_pmode ; opts -> x_ix86_preferred_stack_boundary_arg = ptr -> x_ix86_preferred_stack_boundary_arg ; opts -> x_ix86_recip_name = ptr -> x_ix86_recip_name ; opts -> x_ix86_regparm = ptr -> x_ix86_regparm ; opts -> x_ix86_section_threshold = ptr -> x_ix86_section_threshold ; opts -> x_ix86_sse2avx = ptr -> x_ix86_sse2avx ; opts -> x_ix86_stack_protector_guard = ptr -> x_ix86_stack_protector_guard ; opts -> x_ix86_stringop_alg = ptr -> x_ix86_stringop_alg ; opts -> x_ix86_tls_dialect = ptr -> x_ix86_tls_dialect ; opts -> x_ix86_tune_ctrl_string = ptr -> x_ix86_tune_ctrl_string ; opts -> x_ix86_tune_memcpy_strategy = ptr -> x_ix86_tune_memcpy_strategy ; opts -> x_ix86_tune_memset_strategy = ptr -> x_ix86_tune_memset_strategy ; opts -> x_ix86_tune_no_default = ptr -> x_ix86_tune_no_default ; opts -> x_ix86_veclibabi_type = ptr -> x_ix86_veclibabi_type ; ix86_tune_cost = processor_cost_table [ ix86_tune ] ; if ( opts -> x_optimize_size ) ix86_cost = & ix86_size_cost ; else ix86_cost = ix86_tune_cost ; if ( old_arch != ix86_arch ) { ix86_arch_mask = HOST_WIDE_INT_1U << ix86_arch ; for ( i = 0 ; i < X86_ARCH_LAST ; ++ i ) ix86_arch_features [ i ] = ! ! ( initial_ix86_arch_features [ i ] & ix86_arch_mask ) ; } if ( old_tune != ix86_tune ) set_ix86_tune_features ( ix86_tune , false ) ; } </s>


"virtual function multiversioning not supported"

Generate the dispatching code body to dispatch multi-versioned function DECL . The target hook is called to process the `` target '' attributes and provide the code to dispatch the right function at run-time . NODE points to the dispatcher decl whose body will be created .


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

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


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

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


<s> static bool ix86_lea_outperforms ( rtx_insn * insn , unsigned int regno0 , unsigned int regno1 , unsigned int regno2 , int split_cost , bool has_scale ) { int dist_define , dist_use ; if ( TARGET_SILVERMONT || TARGET_GOLDMONT || TARGET_GOLDMONT_PLUS || TARGET_TREMONT || TARGET_INTEL ) { if ( has_scale ) return true ; if ( split_cost < 1 ) return false ; if ( regno0 == regno1 || regno0 == regno2 ) return false ; return true ; } dist_define = distance_non_agu_define ( regno1 , regno2 , insn ) ; dist_use = distance_agu_use ( regno0 , insn ) ; if ( dist_define < 0 || dist_define >= LEA_MAX_STALL ) { if ( dist_use < 0 && split_cost == 0 ) return TARGET_64BIT || IX86_LEA_PRIORITY ; else return true ; } dist_define += split_cost + IX86_LEA_PRIORITY ; if ( dist_use < 0 ) return dist_define > LEA_MAX_STALL ; return dist_define >= dist_use ; } </s>

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


"function versions cannot be marked as gnu_inline,"

This function changes the assembler name for functions that are versions . If DECL is a function version and has a `` target '' attribute , it appends the attribute string to its assembler name .


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

Return the mode that an insn results in .


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

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


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

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


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

Return needed mode for entity in optimize_mode_switching pass .


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

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


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

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


<s> static void ix86_output_indirect_branch_via_reg ( rtx call_op , bool sibcall_p ) { char thunk_name_buf [ 32 ] ; char * thunk_name ; enum indirect_thunk_prefix need_prefix = indirect_thunk_need_prefix ( current_output_insn ) ; int regno = REGNO ( call_op ) ; if ( cfun -> machine -> indirect_branch_type != indirect_branch_thunk_inline ) { if ( cfun -> machine -> indirect_branch_type == indirect_branch_thunk ) { int i = regno ; if ( i >= FIRST_REX_INT_REG ) i -= ( FIRST_REX_INT_REG - LAST_INT_REG - 1 ) ; indirect_thunks_used |= 1 << i ; } indirect_thunk_name ( thunk_name_buf , regno , need_prefix , false ) ; thunk_name = thunk_name_buf ; } else thunk_name = NULL ; if ( sibcall_p ) { if ( thunk_name != NULL ) fprintf ( asm_out_file , "\tjmp\t%s\n" , thunk_name ) ; else output_indirect_thunk ( regno ) ; } else { if ( thunk_name != NULL ) { fprintf ( asm_out_file , "\tcall\t%s\n" , thunk_name ) ; return ; } char indirectlabel1 [ 32 ] ; char indirectlabel2 [ 32 ] ; ASM_GENERATE_INTERNAL_LABEL ( indirectlabel1 , INDIRECT_LABEL , indirectlabelno ++ ) ; ASM_GENERATE_INTERNAL_LABEL ( indirectlabel2 , INDIRECT_LABEL , indirectlabelno ++ ) ; fputs ( "\tjmp\t" , asm_out_file ) ; assemble_name_raw ( asm_out_file , indirectlabel2 ) ; fputc ( '\n' , asm_out_file ) ; ASM_OUTPUT_INTERNAL_LABEL ( asm_out_file , indirectlabel1 ) ; if ( thunk_name != NULL ) fprintf ( asm_out_file , "\tjmp\t%s\n" , thunk_name ) ; else output_indirect_thunk ( regno ) ; ASM_OUTPUT_INTERNAL_LABEL ( asm_out_file , indirectlabel2 ) ; fputs ( "\tcall\t" , asm_out_file ) ; assemble_name_raw ( asm_out_file , indirectlabel1 ) ; fputc ( '\n' , asm_out_file ) ; } } </s>

Output indirect branch via a call and return thunk . CALL_OP is a register which contains the branch target . XASM is the assembly template for CALL_OP . Branch is a tail call if SIBCALL_P is true . A normal call is converted to : call __x86_indirect_thunk_reg and a tail call is converted to : jmp __x86_indirect_thunk_reg


<s> const char * ix86_output_indirect_function_return ( rtx ret_op ) { if ( cfun -> machine -> function_return_type != indirect_branch_keep ) { char thunk_name [ 32 ] ; enum indirect_thunk_prefix need_prefix = indirect_thunk_need_prefix ( current_output_insn ) ; unsigned int regno = REGNO ( ret_op ) ; gcc_assert ( regno == CX_REG ) ; if ( cfun -> machine -> function_return_type != indirect_branch_thunk_inline ) { bool need_thunk = ( cfun -> machine -> function_return_type == indirect_branch_thunk ) ; indirect_thunk_name ( thunk_name , regno , need_prefix , true ) ; if ( need_thunk ) { indirect_return_via_cx = true ; indirect_thunks_used |= 1 << CX_REG ; } fprintf ( asm_out_file , "\tjmp\t%s\n" , thunk_name ) ; } else output_indirect_thunk ( regno ) ; return "" ; } else return "%!jmp\t%A0" ; } </s>

Output indirect function return . RET_OP is the function return target .


<s> static bool ix86_pass_by_reference ( cumulative_args_t cum_v , machine_mode mode , const_tree type , bool ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; if ( TARGET_64BIT ) { enum calling_abi call_abi = cum ? cum -> call_abi : ix86_abi ; if ( call_abi == MS_ABI ) { HOST_WIDE_INT msize = GET_MODE_SIZE ( mode ) ; if ( type ) { if ( TREE_CODE ( type ) == ARRAY_TYPE ) return true ; if ( RECORD_OR_UNION_TYPE_P ( type ) ) { msize = int_size_in_bytes ( type ) ; } } return msize != 1 && msize != 2 && msize != 4 && msize != 8 ; } else if ( type && int_size_in_bytes ( type ) == - 1 ) return true ; } return false ; } </s>

A C expression that indicates when an argument must be passed by reference . If nonzero for an argument , a copy of that argument is made in memory and a pointer to the argument is passed instead of the argument itself . The pointer is passed in whatever way is appropriate for passing a pointer to that type .


<s> static reg_class_t ix86_preferred_output_reload_class ( rtx x , reg_class_t regclass ) { machine_mode mode = GET_MODE ( x ) ; mode = GET_MODE ( x ) ; if ( SSE_FLOAT_MODE_P ( mode ) && TARGET_SSE_MATH ) return MAYBE_SSE_CLASS_P ( regclass ) ? ALL_SSE_REGS : NO_REGS ; if ( IS_STACK_MODE ( mode ) ) return FLOAT_CLASS_P ( regclass ) ? regclass : NO_REGS ; return regclass ; } </s>

Discourage putting floating-point values in SSE registers unless SSE math is being used , and likewise for the 387 registers .


<s> ix86_dependencies_evaluation_hook static int ix86_reassociation_width ( unsigned int op , machine_mode mode ) { int width = 1 ; if ( VECTOR_MODE_P ( mode ) ) { int div = 1 ; if ( INTEGRAL_MODE_P ( mode ) ) width = ix86_cost -> reassoc_vec_int ; else if ( FLOAT_MODE_P ( mode ) ) width = ix86_cost -> reassoc_vec_fp ; if ( width == 1 ) return 1 ; if ( ( ix86_tune == PROCESSOR_ZNVER1 || ix86_tune == PROCESSOR_ZNVER2 ) && INTEGRAL_MODE_P ( mode ) && op != PLUS && op != MINUS ) return 1 ; if ( TARGET_AVX128_OPTIMAL && GET_MODE_BITSIZE ( mode ) > 128 ) div = GET_MODE_BITSIZE ( mode ) / 128 ; else if ( TARGET_SSE_SPLIT_REGS && GET_MODE_BITSIZE ( mode ) > 64 ) div = GET_MODE_BITSIZE ( mode ) / 64 ; width = ( width + div - 1 ) / div ; } else if ( INTEGRAL_MODE_P ( mode ) ) width = ix86_cost -> reassoc_int ; else if ( FLOAT_MODE_P ( mode ) ) width = ix86_cost -> reassoc_fp ; if ( ! TARGET_64BIT && width > 2 ) width = 2 ; return width ; } </s>

Implementation of reassociation_width target hook used by reassoc phase to identify parallelism level in reassociated tree . Statements tree_code is passed in OPC . Arguments type is passed in MODE . Currently parallel reassociation is enabled for Atom processors only and we set reassociation width to be 2 because Atom may issue up to 2 instructions per cycle . Return value should be fixed if parallel reassociation is enabled for other processors .


<s> static bool ix86_save_reg ( unsigned int regno , bool maybe_eh_return , bool ignore_outlined ) { if ( cfun -> machine -> no_caller_saved_registers ) { rtx reg = crtl -> return_rtx ; if ( reg ) { unsigned int i = REGNO ( reg ) ; unsigned int nregs = REG_NREGS ( reg ) ; while ( nregs -- > 0 ) if ( ( i + nregs ) == regno ) return false ; } return ( df_regs_ever_live_p ( regno ) && ! fixed_regs [ regno ] && ! STACK_REGNO_P ( regno ) && ! MMX_REGNO_P ( regno ) && ( regno != HARD_FRAME_POINTER_REGNUM || ! frame_pointer_needed ) ) ; } if ( regno == REAL_PIC_OFFSET_TABLE_REGNUM && pic_offset_table_rtx ) { if ( ix86_use_pseudo_pic_reg ( ) ) { if ( ! TARGET_64BIT && flag_pic && crtl -> profile ) return true ; } else if ( df_regs_ever_live_p ( REAL_PIC_OFFSET_TABLE_REGNUM ) || crtl -> profile || crtl -> calls_eh_return || crtl -> uses_const_pool || cfun -> has_nonlocal_label ) return ix86_select_alt_pic_regnum ( ) == INVALID_REGNUM ; } if ( crtl -> calls_eh_return && maybe_eh_return ) { unsigned i ; for ( i = 0 ; ; i ++ ) { unsigned test = EH_RETURN_DATA_REGNO ( i ) ; if ( test == INVALID_REGNUM ) break ; if ( test == regno ) return true ; } } if ( ignore_outlined && cfun -> machine -> call_ms2sysv ) { unsigned count = cfun -> machine -> call_ms2sysv_extra_regs + xlogue_layout :: MIN_REGS ; if ( xlogue_layout :: is_stub_managed_reg ( regno , count ) ) return false ; } if ( crtl -> drap_reg && regno == REGNO ( crtl -> drap_reg ) && ! cfun -> machine -> no_drap_save_restore ) return true ; return ( df_regs_ever_live_p ( regno ) && ! call_used_regs [ regno ] && ! fixed_regs [ regno ] && ( regno != HARD_FRAME_POINTER_REGNUM || ! frame_pointer_needed ) ) ; } </s>


"%s instructions aren%'t allowed in a function with "

Establish appropriate back-end context for processing the function FNDECL . The argument might be NULL to indicate processing at top level , outside of any function scope .


"%<-mindirect-branch=%s%> and %<-mcmodel=large%> are not "

"%<-mindirect-branch%> and %<-fcf-protection%> are not "

"%<-mfunction-return=%s%> and %<-mcmodel=large%> are not "

"%<-mfunction-return%> and %<-fcf-protection%> are not "

Set the indirect_branch_type field from the function FNDECL .


<s> static void ix86_simd_clone_adjust ( struct cgraph_node * node ) { const char * str = NULL ; if ( ! node -> definition ) return ; gcc_assert ( node -> decl == cfun -> decl ) ; switch ( node -> simdclone -> vecsize_mangle ) { case 'b' : if ( ! TARGET_SSE2 ) str = "sse2" ; break ; case 'c' : if ( ! TARGET_AVX ) str = "avx" ; break ; case 'd' : if ( ! TARGET_AVX2 ) str = "avx2" ; break ; case 'e' : if ( ! TARGET_AVX512F ) str = "avx512f" ; break ; default : gcc_unreachable ( ) ; } if ( str == NULL ) return ; push_cfun ( NULL ) ; tree args = build_tree_list ( NULL_TREE , build_string ( strlen ( str ) , str ) ) ; bool ok = ix86_valid_target_attribute_p ( node -> decl , NULL , args , 0 ) ; gcc_assert ( ok ) ; pop_cfun ( ) ; ix86_reset_previous_fndecl ( ) ; ix86_set_current_function ( node -> decl ) ; } </s>

Add target attribute to SIMD clone NODE if needed .


<s> static tree ix86_vectorize_builtin_scatter ( const_tree vectype , const_tree index_type , int scale ) { bool si ; enum ix86_builtins code ; if ( ! TARGET_AVX512F ) return NULL_TREE ; if ( ( TREE_CODE ( index_type ) != INTEGER_TYPE && ! POINTER_TYPE_P ( index_type ) ) || ( TYPE_MODE ( index_type ) != SImode && TYPE_MODE ( index_type ) != DImode ) ) return NULL_TREE ; if ( TYPE_PRECISION ( index_type ) > POINTER_SIZE ) return NULL_TREE ; if ( TYPE_PRECISION ( index_type ) < POINTER_SIZE && TYPE_UNSIGNED ( index_type ) ) return NULL_TREE ; if ( scale <= 0 || scale > 8 || ( scale & ( scale - 1 ) ) != 0 ) return NULL_TREE ; si = TYPE_MODE ( index_type ) == SImode ; switch ( TYPE_MODE ( vectype ) ) { case E_V8DFmode : code = si ? IX86_BUILTIN_SCATTERALTSIV8DF : IX86_BUILTIN_SCATTERDIV8DF ; break ; case E_V8DImode : code = si ? IX86_BUILTIN_SCATTERALTSIV8DI : IX86_BUILTIN_SCATTERDIV8DI ; break ; case E_V16SFmode : code = si ? IX86_BUILTIN_SCATTERSIV16SF : IX86_BUILTIN_SCATTERALTDIV16SF ; break ; case E_V16SImode : code = si ? IX86_BUILTIN_SCATTERSIV16SI : IX86_BUILTIN_SCATTERALTDIV16SI ; break ; case E_V4DFmode : if ( TARGET_AVX512VL ) code = si ? IX86_BUILTIN_SCATTERALTSIV4DF : IX86_BUILTIN_SCATTERDIV4DF ; else return NULL_TREE ; break ; case E_V4DImode : if ( TARGET_AVX512VL ) code = si ? IX86_BUILTIN_SCATTERALTSIV4DI : IX86_BUILTIN_SCATTERDIV4DI ; else return NULL_TREE ; break ; case E_V8SFmode : if ( TARGET_AVX512VL ) code = si ? IX86_BUILTIN_SCATTERSIV8SF : IX86_BUILTIN_SCATTERALTDIV8SF ; else return NULL_TREE ; break ; case E_V8SImode : if ( TARGET_AVX512VL ) code = si ? IX86_BUILTIN_SCATTERSIV8SI : IX86_BUILTIN_SCATTERALTDIV8SI ; else return NULL_TREE ; break ; case E_V2DFmode : if ( TARGET_AVX512VL ) code = si ? IX86_BUILTIN_SCATTERALTSIV2DF : IX86_BUILTIN_SCATTERDIV2DF ; else return NULL_TREE ; break ; case E_V2DImode : if ( TARGET_AVX512VL ) code = si ? IX86_BUILTIN_SCATTERALTSIV2DI : IX86_BUILTIN_SCATTERDIV2DI ; else return NULL_TREE ; break ; case E_V4SFmode : if ( TARGET_AVX512VL ) code = si ? IX86_BUILTIN_SCATTERSIV4SF : IX86_BUILTIN_SCATTERALTDIV4SF ; else return NULL_TREE ; break ; case E_V4SImode : if ( TARGET_AVX512VL ) code = si ? IX86_BUILTIN_SCATTERSIV4SI : IX86_BUILTIN_SCATTERALTDIV4SI ; else return NULL_TREE ; break ; default : return NULL_TREE ; } return ix86_builtins [ code ] ; } </s>

Returns a decl of a function that implements scatter store with register type VECTYPE and index type INDEX_TYPE and SCALE . Return NULL_TREE if it is not available .


<s> static int ix86_vec_cost ( machine_mode mode , int cost ) { if ( ! VECTOR_MODE_P ( mode ) ) return cost ; if ( GET_MODE_BITSIZE ( mode ) == 128 && TARGET_SSE_SPLIT_REGS ) return cost * 2 ; if ( GET_MODE_BITSIZE ( mode ) > 128 && TARGET_AVX128_OPTIMAL ) return cost * GET_MODE_BITSIZE ( mode ) / 128 ; return cost ; } </s>

Return cost of vector operation in MODE given that scalar version has COST . If PARALLEL is true assume that CPU has more than one unit performing the operation .


<s> static tree make_resolver_func ( const tree default_decl , const tree ifunc_alias_decl , basic_block * empty_bb ) { char * resolver_name ; tree decl , type , decl_name , t ; if ( TREE_PUBLIC ( default_decl ) == 0 ) { char * ifunc_name = make_unique_name ( default_decl , "ifunc" , true ) ; symtab -> change_decl_assembler_name ( ifunc_alias_decl , get_identifier ( ifunc_name ) ) ; XDELETEVEC ( ifunc_name ) ; } resolver_name = make_unique_name ( default_decl , "resolver" , false ) ; type = build_function_type_list ( ptr_type_node , NULL_TREE ) ; decl = build_fn_decl ( resolver_name , type ) ; decl_name = get_identifier ( resolver_name ) ; SET_DECL_ASSEMBLER_NAME ( decl , decl_name ) ; DECL_NAME ( decl ) = decl_name ; TREE_USED ( decl ) = 1 ; DECL_ARTIFICIAL ( decl ) = 1 ; DECL_IGNORED_P ( decl ) = 1 ; TREE_PUBLIC ( decl ) = 0 ; DECL_UNINLINABLE ( decl ) = 1 ; DECL_EXTERNAL ( decl ) = 0 ; DECL_EXTERNAL ( ifunc_alias_decl ) = 0 ; DECL_CONTEXT ( decl ) = NULL_TREE ; DECL_INITIAL ( decl ) = make_node ( BLOCK ) ; DECL_STATIC_CONSTRUCTOR ( decl ) = 0 ; if ( DECL_COMDAT_GROUP ( default_decl ) || TREE_PUBLIC ( default_decl ) ) { DECL_COMDAT ( decl ) = 1 ; make_decl_one_only ( decl , DECL_ASSEMBLER_NAME ( decl ) ) ; } t = build_decl ( UNKNOWN_LOCATION , RESULT_DECL , NULL_TREE , ptr_type_node ) ; DECL_CONTEXT ( t ) = decl ; DECL_ARTIFICIAL ( t ) = 1 ; DECL_IGNORED_P ( t ) = 1 ; DECL_RESULT ( decl ) = t ; gimplify_function_tree ( decl ) ; push_cfun ( DECL_STRUCT_FUNCTION ( decl ) ) ; * empty_bb = init_lowered_empty_function ( decl , false , profile_count :: uninitialized ( ) ) ; cgraph_node :: add_new_function ( decl , true ) ; symtab -> call_cgraph_insertion_hooks ( cgraph_node :: get_create ( decl ) ) ; pop_cfun ( ) ; gcc_assert ( ifunc_alias_decl != NULL ) ; DECL_ATTRIBUTES ( ifunc_alias_decl ) = make_attribute ( "ifunc" , resolver_name , DECL_ATTRIBUTES ( ifunc_alias_decl ) ) ; cgraph_node :: create_same_body_alias ( ifunc_alias_decl , decl ) ; XDELETEVEC ( resolver_name ) ; return decl ; } </s>

Make the resolver function decl to dispatch the versions of a multi- versioned function , DEFAULT_DECL . Create an empty basic block in the resolver and store the pointer in EMPTY_BB . Return the decl of the resolver function .


"  Copied r%d to a vector register r%d for insn %d\n"

Make vector copies for all register REGNO definitions and replace its uses in a chain .


"unknown parameter to option %<-mtune-ctrl%>: %s"

parse -mtune-ctrl= option . When DUMP is true , print the features that are explicitly set .


"%<-mcall-ms2sysv-xlogues%> is not compatible with %s"

Emits a warning for unsupported msabi to sysv pro/epilogues .


<s> void x86_order_regs_for_local_alloc ( void ) { int pos = 0 ; int i ; for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) if ( GENERAL_REGNO_P ( i ) && call_used_regs [ i ] ) reg_alloc_order [ pos ++ ] = i ; for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) if ( GENERAL_REGNO_P ( i ) && ! call_used_regs [ i ] ) reg_alloc_order [ pos ++ ] = i ; if ( ! TARGET_SSE_MATH ) for ( i = FIRST_STACK_REG ; i <= LAST_STACK_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; for ( i = FIRST_SSE_REG ; i <= LAST_SSE_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; for ( i = FIRST_REX_SSE_REG ; i <= LAST_REX_SSE_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; for ( i = FIRST_EXT_REX_SSE_REG ; i <= LAST_EXT_REX_SSE_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; for ( i = FIRST_MASK_REG ; i <= LAST_MASK_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; if ( TARGET_SSE_MATH ) for ( i = FIRST_STACK_REG ; i <= LAST_STACK_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; for ( i = FIRST_MMX_REG ; i <= LAST_MMX_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; while ( pos < FIRST_PSEUDO_REGISTER ) reg_alloc_order [ pos ++ ] = 0 ; } </s>

Order the registers for register allocator .


<s> static void add_dependee_for_func_arg ( rtx_insn * arg , basic_block bb ) { rtx_insn * insn = BB_END ( bb ) ; while ( insn ) { if ( NONDEBUG_INSN_P ( insn ) && NONJUMP_INSN_P ( insn ) ) { rtx set = single_set ( insn ) ; if ( set ) { avoid_func_arg_motion ( arg , insn ) ; return ; } } if ( insn == BB_HEAD ( bb ) ) return ; insn = PREV_INSN ( insn ) ; } } </s>

Avoid cross block motion of function argument through adding dependency from the first non-jump instruction in bb .


<s> static rtx_insn * add_parameter_dependencies ( rtx_insn * call , rtx_insn * head ) { rtx_insn * insn ; rtx_insn * last = call ; rtx_insn * first_arg = NULL ; bool is_spilled = false ; head = PREV_INSN ( head ) ; while ( true ) { last = PREV_INSN ( last ) ; if ( last == head ) return NULL ; if ( ! NONDEBUG_INSN_P ( last ) ) continue ; if ( insn_is_function_arg ( last , & is_spilled ) ) break ; return NULL ; } first_arg = last ; while ( true ) { insn = PREV_INSN ( last ) ; if ( ! INSN_P ( insn ) ) break ; if ( insn == head ) break ; if ( ! NONDEBUG_INSN_P ( insn ) ) { last = insn ; continue ; } if ( insn_is_function_arg ( insn , & is_spilled ) ) { if ( is_spilled ) add_dependence ( first_arg , insn , REG_DEP_OUTPUT ) ; first_arg = last = insn ; } else break ; } if ( ! is_spilled ) return NULL ; return first_arg ; } </s>

Add output dependencies for chain of function adjacent arguments if only there is a move to likely spilled HW register . Return first argument if at least one dependence was added or NULL otherwise .


<s> rtx assign_386_stack_local ( machine_mode mode , enum ix86_stack_slot n ) { struct stack_local_entry * s ; gcc_assert ( n < MAX_386_STACK_LOCALS ) ; for ( s = ix86_stack_locals ; s ; s = s -> next ) if ( s -> mode == mode && s -> n == n ) return validize_mem ( copy_rtx ( s -> rtl ) ) ; s = ggc_alloc < stack_local_entry > ( ) ; s -> n = n ; s -> mode = mode ; s -> rtl = assign_stack_local ( mode , GET_MODE_SIZE ( mode ) , 0 ) ; s -> next = ix86_stack_locals ; ix86_stack_locals = s ; return validize_mem ( copy_rtx ( s -> rtl ) ) ; } </s>

Return a MEM corresponding to a stack slot with mode MODE . Allocate a new slot if necessary . The RTL for a function can have several slots available : N is which slot to use .


<s> static void avoid_func_arg_motion ( rtx_insn * first_arg , rtx_insn * insn ) { rtx set ; rtx tmp ; 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_vperm2f128_parallel ( rtx par , machine_mode mode ) { unsigned i , nelt = GET_MODE_NUNITS ( mode ) , nelt2 = nelt / 2 ; unsigned mask = 0 ; unsigned char ipar [ 8 ] = { } ; 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 >= 2 * nelt ) return 0 ; ipar [ i ] = ei ; } for ( i = 0 ; i < nelt2 - 1 ; ++ i ) if ( ipar [ i ] + 1 != ipar [ i + 1 ] ) return 0 ; for ( i = nelt2 ; i < nelt - 1 ; ++ i ) if ( ipar [ i ] + 1 != ipar [ i + 1 ] ) return 0 ; for ( i = 0 ; i < 2 ; ++ i ) { unsigned e = ipar [ i * nelt2 ] ; if ( e % nelt2 ) return 0 ; e /= nelt2 ; mask |= e << ( i * 4 ) ; } return mask + 1 ; } </s>

Helper for avx_vperm2f128_v4df_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> 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 E_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 E_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 E_V16SFmode : for ( i = 0 ; i < 8 ; ++ i ) if ( ipar [ i ] + 8 != ipar [ i + 8 ] ) return 0 ; case E_V8SFmode : for ( i = 0 ; i < 4 ; ++ i ) if ( ipar [ i ] + 4 != ipar [ i + 4 ] ) return 0 ; nelt = 4 ; case E_V2DFmode : case E_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 , unsigned int * align , unsigned int scratch_regno = INVALID_REGNUM ) { rtx base_reg = NULL ; HOST_WIDE_INT base_offset = 0 ; if ( align && * align ) choose_basereg ( cfa_offset , base_reg , base_offset , * align , align ) ; if ( ! base_reg ) choose_basereg ( cfa_offset , base_reg , base_offset , 0 , align ) ; gcc_assert ( base_reg != NULL ) ; rtx base_offset_rtx = GEN_INT ( base_offset ) ; if ( ! x86_64_immediate_operand ( base_offset_rtx , Pmode ) ) { gcc_assert ( scratch_regno != INVALID_REGNUM ) ; rtx scratch_reg = gen_rtx_REG ( Pmode , scratch_regno ) ; emit_move_insn ( scratch_reg , base_offset_rtx ) ; return gen_rtx_PLUS ( Pmode , base_reg , scratch_reg ) ; } 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 inline int choose_baseaddr_len ( unsigned int regno , HOST_WIDE_INT offset ) { int len = 4 ; if ( offset == 0 ) { len = ( regno == BP_REG || regno == R13_REG ) ; } else if ( IN_RANGE ( offset , - 128 , 127 ) ) len = 1 ; if ( regno == SP_REG || regno == R12_REG ) len ++ ; return len ; } </s>

This is semi-inlined memory_address_length , but simplified since we know that we 're always dealing with reg+offset , and to avoid having to create and discard all that rtl .


<s> static void choose_basereg ( HOST_WIDE_INT cfa_offset , rtx & base_reg , HOST_WIDE_INT & base_offset , unsigned int align_reqested , unsigned int * align ) { const struct machine_function * m = cfun -> machine ; unsigned int hfp_align ; unsigned int drap_align ; unsigned int sp_align ; bool hfp_ok = fp_valid_at ( cfa_offset ) ; bool drap_ok = m -> fs . drap_valid ; bool sp_ok = sp_valid_at ( cfa_offset ) ; hfp_align = drap_align = sp_align = INCOMING_STACK_BOUNDARY ; if ( align_reqested ) { if ( m -> fs . realigned ) hfp_align = drap_align = sp_align = crtl -> stack_alignment_needed ; else if ( m -> fs . sp_realigned ) sp_align = crtl -> stack_alignment_needed ; hfp_ok = hfp_ok && hfp_align >= align_reqested ; drap_ok = drap_ok && drap_align >= align_reqested ; sp_ok = sp_ok && sp_align >= align_reqested ; } if ( m -> use_fast_prologue_epilogue ) { if ( hfp_ok ) { base_reg = hard_frame_pointer_rtx ; base_offset = m -> fs . fp_offset - cfa_offset ; } else if ( drap_ok ) { base_reg = crtl -> drap_reg ; base_offset = 0 - cfa_offset ; } else if ( sp_ok ) { base_reg = stack_pointer_rtx ; base_offset = m -> fs . sp_offset - cfa_offset ; } } else { HOST_WIDE_INT toffset ; int len = 16 , tlen ; if ( sp_ok ) { base_reg = stack_pointer_rtx ; base_offset = m -> fs . sp_offset - cfa_offset ; len = choose_baseaddr_len ( STACK_POINTER_REGNUM , base_offset ) ; } if ( drap_ok ) { 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 ( hfp_ok ) { 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 ; } } } if ( align ) { if ( base_reg == stack_pointer_rtx ) * align = sp_align ; else if ( base_reg == crtl -> drap_reg ) * align = drap_align ; else if ( base_reg == hard_frame_pointer_rtx ) * align = hfp_align ; } } </s>

Choose a base register based upon alignment requested , speed and/or size .


"the ABI of passing C structures with zero-width bit-fields"

Classify the argument of type TYPE and mode MODE . CLASSES will be filled by the register class used to pass each word of the operand . The number of words is returned . In case the parameter should be passed in memory , 0 is returned . As a special case for zero sized containers , classes [ 0 ] will be NO_CLASS and 1 is returned . BIT_OFFSET is used internally for handling records and specifies offset of the offset in bits modulo 256 to avoid overflow cases . See the x86-64 PS ABI for details .


<s> bool constant_address_p ( rtx x ) { return CONSTANT_P ( x ) && ix86_legitimate_address_p ( Pmode , x , 1 ) ; } </s>

Determine if a given RTX is a valid constant address .


<s> static bool darwin_local_data_pic ( rtx disp ) { return ( GET_CODE ( disp ) == UNSPEC && XINT ( disp , 1 ) == UNSPEC_MACHOPIC_OFFSET ) ; } </s>

Allow { LABEL | SYMBOL } _REF - SYMBOL_REF-FOR-PICBASE for Mach-O as this is used for to form addresses to local data when -fPIC is in use .


<s> static int distance_agu_use ( unsigned int regno0 , rtx_insn * insn ) { basic_block bb = BLOCK_FOR_INSN ( insn ) ; int distance = 0 ; bool found = false ; bool redefined = false ; if ( insn != BB_END ( bb ) ) distance = distance_agu_use_in_bb ( regno0 , insn , distance , NEXT_INSN ( insn ) , & found , & redefined ) ; if ( ! found && ! redefined && distance < LEA_SEARCH_THRESHOLD ) { edge e ; edge_iterator ei ; bool simple_loop = false ; FOR_EACH_EDGE ( e , ei , bb -> succs ) if ( e -> dest == bb ) { simple_loop = true ; break ; } if ( simple_loop ) distance = distance_agu_use_in_bb ( regno0 , insn , distance , BB_HEAD ( bb ) , & found , & redefined ) ; else { int shortest_dist = - 1 ; bool found_in_bb = false ; bool redefined_in_bb = false ; FOR_EACH_EDGE ( e , ei , bb -> succs ) { int bb_dist = distance_agu_use_in_bb ( regno0 , insn , distance , BB_HEAD ( e -> dest ) , & found_in_bb , & redefined_in_bb ) ; if ( found_in_bb ) { if ( shortest_dist < 0 ) shortest_dist = bb_dist ; else if ( bb_dist > 0 ) shortest_dist = MIN ( bb_dist , shortest_dist ) ; found = true ; } } distance = shortest_dist ; } } if ( ! found || redefined ) return - 1 ; return distance >> 1 ; } </s>

Return the distance between INSN and the next insn that uses register number REGNO0 in memory address . Return -1 if no such a use is found within LEA_SEARCH_THRESHOLD or REGNO0 is set .


<s> static int distance_agu_use_in_bb ( unsigned int regno , rtx_insn * insn , int distance , rtx_insn * start , bool * found , bool * redefined ) { basic_block bb = NULL ; rtx_insn * next = start ; rtx_insn * prev = NULL ; * found = false ; * redefined = false ; if ( start != NULL_RTX ) { bb = BLOCK_FOR_INSN ( start ) ; if ( start != BB_HEAD ( bb ) ) prev = insn ; } while ( next && next != insn && distance < LEA_SEARCH_THRESHOLD ) { if ( NONDEBUG_INSN_P ( next ) && NONJUMP_INSN_P ( next ) ) { distance = increase_distance ( prev , next , distance ) ; if ( insn_uses_reg_mem ( regno , next ) ) { * found = true ; return distance ; } if ( insn_defines_reg ( regno , INVALID_REGNUM , next ) ) { * redefined = true ; return - 1 ; } prev = next ; } if ( next == BB_END ( bb ) ) break ; next = NEXT_INSN ( next ) ; } return distance ; } </s>

Return the distance in half-cycles between INSN and the next insn that uses register number REGNO in memory address added to DISTANCE . Return -1 if REGNO0 is set . Put true value into * FOUND if register usage was found and false otherwise . Put true value into * REDEFINED if register redefinition was found and false otherwise .


<s> static int distance_non_agu_define ( unsigned int regno1 , unsigned int regno2 , rtx_insn * insn ) { basic_block bb = BLOCK_FOR_INSN ( insn ) ; int distance = 0 ; bool found = false ; if ( insn != BB_HEAD ( bb ) ) distance = distance_non_agu_define_in_bb ( regno1 , regno2 , insn , distance , PREV_INSN ( insn ) , & found ) ; if ( ! found && distance < LEA_SEARCH_THRESHOLD ) { edge e ; edge_iterator ei ; bool simple_loop = false ; FOR_EACH_EDGE ( e , ei , bb -> preds ) if ( e -> src == bb ) { simple_loop = true ; break ; } if ( simple_loop ) distance = distance_non_agu_define_in_bb ( regno1 , regno2 , insn , distance , BB_END ( bb ) , & found ) ; else { int shortest_dist = - 1 ; bool found_in_bb = false ; FOR_EACH_EDGE ( e , ei , bb -> preds ) { int bb_dist = distance_non_agu_define_in_bb ( regno1 , regno2 , insn , distance , BB_END ( e -> src ) , & found_in_bb ) ; if ( found_in_bb ) { if ( shortest_dist < 0 ) shortest_dist = bb_dist ; else if ( bb_dist > 0 ) shortest_dist = MIN ( bb_dist , shortest_dist ) ; found = true ; } } distance = shortest_dist ; } } if ( ! found ) return - 1 ; return distance >> 1 ; } </s>

Search backward for non-agu definition of register number REGNO1 or register number REGNO2 in INSN 's basic block until 1 . Pass LEA_SEARCH_THRESHOLD instructions , or 2 . Reach neighbour BBs boundary , or 3 . Reach agu definition . Returns the distance between the non-agu definition point and INSN . If no definition point , returns -1 .


<s> static int distance_non_agu_define_in_bb ( unsigned int regno1 , unsigned int regno2 , rtx_insn * insn , int distance , rtx_insn * start , bool * found ) { basic_block bb = start ? BLOCK_FOR_INSN ( start ) : NULL ; rtx_insn * prev = start ; rtx_insn * next = NULL ; * found = false ; while ( prev && prev != insn && distance < LEA_SEARCH_THRESHOLD ) { if ( NONDEBUG_INSN_P ( prev ) && NONJUMP_INSN_P ( prev ) ) { distance = increase_distance ( prev , next , distance ) ; if ( insn_defines_reg ( regno1 , regno2 , prev ) ) { if ( recog_memoized ( prev ) < 0 || get_attr_type ( prev ) != TYPE_LEA ) { * found = true ; return distance ; } } next = prev ; } if ( prev == BB_HEAD ( bb ) ) break ; prev = PREV_INSN ( prev ) ; } return distance ; } </s>

Search backward for non-agu definition of register number REGNO1 or register number REGNO2 in basic block starting from instruction START up to head of basic block or instruction INSN . Function puts true value into * FOUND var if definition was found and false otherwise . Distance in half-cycles between START and found instruction or head of BB is added to DISTANCE and returned .


<s> static inline bool equal ( tree_map * a , tree_map * b ) { return a -> base . from == b -> base . from ; } </s>


<s> static bool examine_argument ( machine_mode mode , const_tree type , int in_return , int * int_nregs , int * sse_nregs ) { enum x86_64_reg_class regclass [ MAX_CLASSES ] ; int n = classify_argument ( mode , type , regclass , 0 ) ; * int_nregs = 0 ; * sse_nregs = 0 ; if ( ! n ) return true ; for ( n -- ; n >= 0 ; n -- ) switch ( regclass [ n ] ) { case X86_64_INTEGER_CLASS : case X86_64_INTEGERSI_CLASS : ( * int_nregs ) ++ ; break ; case X86_64_SSE_CLASS : case X86_64_SSEHF_CLASS : case X86_64_SSESF_CLASS : case X86_64_SSEDF_CLASS : ( * sse_nregs ) ++ ; break ; case X86_64_NO_CLASS : case X86_64_SSEUP_CLASS : break ; case X86_64_X87_CLASS : case X86_64_X87UP_CLASS : case X86_64_COMPLEX_X87_CLASS : if ( ! in_return ) return true ; break ; case X86_64_MEMORY_CLASS : gcc_unreachable ( ) ; } return false ; } </s>

Examine the argument and return set number of register required in each class . Return 0 iff parameter should be passed in memory .


<s> static bool extract_base_offset_in_addr ( rtx mem , rtx * base , rtx * offset ) { rtx addr ; gcc_assert ( MEM_P ( mem ) ) ; addr = XEXP ( mem , 0 ) ; if ( GET_CODE ( addr ) == CONST ) addr = XEXP ( addr , 0 ) ; if ( REG_P ( addr ) || GET_CODE ( addr ) == SYMBOL_REF ) { * base = addr ; * offset = const0_rtx ; return true ; } if ( GET_CODE ( addr ) == PLUS && ( REG_P ( XEXP ( addr , 0 ) ) || GET_CODE ( XEXP ( addr , 0 ) ) == SYMBOL_REF ) && CONST_INT_P ( XEXP ( addr , 1 ) ) ) { * base = XEXP ( addr , 0 ) ; * offset = XEXP ( addr , 1 ) ; return true ; } return false ; } </s>

If MEM is in the form of `` base+offset '' , extract the two parts of address and set to BASE and OFFSET , otherwise return false after clearing BASE and OFFSET .


<s> static unsigned int find_drap_reg ( void ) { tree decl = cfun -> decl ; if ( TARGET_64BIT ) { if ( DECL_STATIC_CHAIN ( decl ) || cfun -> machine -> no_caller_saved_registers || crtl -> tail_call_emit ) return R13_REG ; return R10_REG ; } else { if ( DECL_STATIC_CHAIN ( decl ) || cfun -> machine -> no_caller_saved_registers || crtl -> tail_call_emit || crtl -> calls_eh_return ) 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 inline bool fp_valid_at ( HOST_WIDE_INT cfa_offset ) { const struct machine_frame_state & fs = cfun -> machine -> fs ; if ( fs . sp_realigned && cfa_offset > fs . sp_realigned_fp_last ) { gcc_assert ( cfa_offset >= fs . sp_realigned_offset ) ; return false ; } return fs . fp_valid ; } </s>

Determine if the frame pointer is valid for accessing the CFA_OFFSET in the frame save area . The register is saved at CFA - CFA_OFFSET .


"calling %qD with SSE calling convention without "

"this is a GCC bug that can be worked around by adding "

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 ) .


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 .


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_insn * gen_and2_insn ( rtx x , rtx y ) { enum insn_code icode = optab_handler ( and_optab , GET_MODE ( x ) ) ; gcc_assert ( insn_operand_matches ( icode , 0 , x ) ) ; gcc_assert ( insn_operand_matches ( icode , 1 , x ) ) ; gcc_assert ( insn_operand_matches ( icode , 2 , y ) ) ; return GEN_FCN ( icode ) ( x , x , y ) ; } </s>

Generate and return an insn body to AND X with Y .


<s> 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 ( arg , gen_rtx_MEM ( word_mode , gen_rtx_POST_INC ( Pmode , stack_pointer_rtx ) ) ) ; } </s>

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


<s> 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 ( gen_rtx_MEM ( word_mode , gen_rtx_PRE_DEC ( Pmode , stack_pointer_rtx ) ) , arg ) ; } </s>

Code to generate prologue and epilogue sequences


<s> static rtx gen_reg_or_parallel ( machine_mode mode , machine_mode orig_mode , unsigned int regno ) { rtx tmp ; if ( orig_mode != BLKmode ) tmp = gen_rtx_REG ( orig_mode , regno ) ; else { tmp = gen_rtx_REG ( mode , regno ) ; tmp = gen_rtx_EXPR_LIST ( VOIDmode , tmp , const0_rtx ) ; tmp = gen_rtx_PARALLEL ( orig_mode , gen_rtvec ( 1 , tmp ) ) ; } return tmp ; } </s>

We want to pass a value in REGNO whose `` natural '' mode is MODE . However , this may not agree with the mode that the type system has chosen for the register , which is ORIG_MODE . If ORIG_MODE is not BLKmode , then we can go ahead and use it . Otherwise we have to build a PARALLEL instead .


<s> static void get_pc_thunk_name ( char name [ 32 ] , unsigned int regno ) { gcc_assert ( ! TARGET_64BIT ) ; if ( USE_HIDDEN_LINKONCE ) sprintf ( name , "__x86.get_pc_thunk.%s" , reg_names [ regno ] ) ; else ASM_GENERATE_INTERNAL_LABEL ( name , "LPR" , regno ) ; } </s>

Fills in the label name that should be used for a pc thunk for the given register .


Return the probing interval for -fstack-clash-protection .


<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 , false ) ) regno = BX_REG ; else if ( ! ( regparm == 3 && static_chain_p ) && ix86_save_reg ( SI_REG , true , false ) ) regno = SI_REG ; else if ( ix86_save_reg ( DI_REG , true , false ) ) 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 * 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 rtx get_thread_pointer ( machine_mode tp_mode , bool to_reg ) { rtx tp = gen_rtx_UNSPEC ( ptr_mode , gen_rtvec ( 1 , const0_rtx ) , UNSPEC_TP ) ; if ( GET_MODE ( tp ) != tp_mode ) { gcc_assert ( GET_MODE ( tp ) == SImode ) ; gcc_assert ( tp_mode == DImode ) ; tp = gen_rtx_ZERO_EXTEND ( tp_mode , tp ) ; } if ( to_reg ) tp = copy_to_mode_reg ( tp_mode , tp ) ; return tp ; } </s>

Load the thread pointer . If TO_REG is true , force it into a register .


<s> static inline hashval_t hash ( tree_map * m ) { return m -> hash ; } </s>

Hash function for builtin functions with up to 3 arguments and a return type .


<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_GOTOFF : output_addr_const ( file , op ) ; fputs ( "@gotoff" , file ) ; break ; 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 ; default : return false ; } return true ; } </s>

Implementation of TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA .


<s>
static
void
ATTRIBUTE_UNUSED
i386_output_dwarf_dtprel
(
FILE
*
file
,
int
size
,
rtx
x
)
{
fputs
(
ASM_LONG
,
file
)
;
output_addr_const
(
file
,
x
)
;
fputs
(
"@dtpoff"
,
file
)
;
switch
(
size
)
{
case
4
:
break
;
case
8
:
fputs
(
", 0"
,
file
)
;
break
;
default
:
gcc_unreachable
(
)
;
}
}
</s>

This is called from dwarf2out.cc via TARGET_ASM_OUTPUT_DWARF_DTPREL . We need to emit DTP-relative relocations .


<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 ; } if ( flags & SECTION_EXCLUDE ) { fprintf ( asm_out_file , "\t.section\t%s,#exclude\n" , name ) ; return ; } default_elf_asm_named_section ( name , flags , decl ) ; } </s>

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


<s> static int iamcu_alignment ( tree type , int align ) { machine_mode mode ; if ( align < 32 || TYPE_USER_ALIGN ( type ) ) return align ; type = strip_array_types ( type ) ; if ( TYPE_ATOMIC ( type ) ) return align ; mode = TYPE_MODE ( type ) ; switch ( GET_MODE_CLASS ( mode ) ) { case MODE_INT : case MODE_COMPLEX_INT : case MODE_COMPLEX_FLOAT : case MODE_FLOAT : case MODE_DECIMAL_FLOAT : return 32 ; default : return align ; } } </s>

Compute the alignment for a variable for Intel MCU psABI . TYPE is the data type , and ALIGN is the alignment that the object would ordinarily have .


<s> static unsigned int increase_distance ( rtx_insn * prev , rtx_insn * next , unsigned int distance ) { df_ref def , use ; if ( ! prev || ! next ) return distance + ( distance & 1 ) + 2 ; if ( ! DF_INSN_USES ( next ) || ! DF_INSN_DEFS ( prev ) ) return distance + 1 ; FOR_EACH_INSN_USE ( use , next ) FOR_EACH_INSN_DEF ( def , prev ) if ( ! DF_REF_IS_ARTIFICIAL ( def ) && DF_REF_REGNO ( use ) == DF_REF_REGNO ( def ) ) return distance + ( distance & 1 ) + 2 ; return distance + 1 ; } </s>

Increase given DISTANCE in half-cycles according to dependencies between PREV and NEXT instructions . Add 1 half-cycle if there is no dependency and go to next cycle if there is some dependecy .


<s> static void indirect_thunk_name ( char name [ 32 ] , unsigned int regno , enum indirect_thunk_prefix need_prefix , bool ret_p ) { if ( regno != INVALID_REGNUM && regno != CX_REG && ret_p ) gcc_unreachable ( ) ; if ( USE_HIDDEN_LINKONCE ) { const char * prefix ; if ( need_prefix == indirect_thunk_prefix_nt && regno != INVALID_REGNUM ) { prefix = "_nt" ; } else prefix = "" ; const char * ret = ret_p ? "return" : "indirect" ; if ( regno != INVALID_REGNUM ) { const char * reg_prefix ; if ( LEGACY_INT_REGNO_P ( regno ) ) reg_prefix = TARGET_64BIT ? "r" : "e" ; else reg_prefix = "" ; sprintf ( name , "__x86_%s_thunk%s_%s%s" , ret , prefix , reg_prefix , reg_names [ regno ] ) ; } else sprintf ( name , "__x86_%s_thunk%s" , ret , prefix ) ; } else { if ( regno != INVALID_REGNUM ) ASM_GENERATE_INTERNAL_LABEL ( name , "LITR" , regno ) ; else { if ( ret_p ) ASM_GENERATE_INTERNAL_LABEL ( name , "LRT" , 0 ) ; else ASM_GENERATE_INTERNAL_LABEL ( name , "LIT" , 0 ) ; } } } </s>

Fills in the label name that should be used for the indirect thunk .


<s> enum indirect_thunk_prefix indirect_thunk_need_prefix ( rtx_insn * insn ) { enum indirect_thunk_prefix need_prefix ; if ( ( cfun -> machine -> indirect_branch_type == indirect_branch_thunk_extern ) && ix86_notrack_prefixed_insn_p ( insn ) ) { need_prefix = indirect_thunk_prefix_nt ; } else need_prefix = indirect_thunk_prefix_none ; return need_prefix ; } </s>

Return the prefix needed for an indirect branch INSN .


Initialize the table of extra 80387 mathematical constants .


<s> static inline bool inline_secondary_memory_needed ( machine_mode mode , reg_class_t class1 , reg_class_t class2 , 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 ) || MAYBE_MASK_CLASS_P ( class1 ) != MASK_CLASS_P ( class1 ) || MAYBE_MASK_CLASS_P ( class2 ) != MASK_CLASS_P ( class2 ) ) { gcc_assert ( ! strict || lra_in_progress ) ; return true ; } if ( FLOAT_CLASS_P ( class1 ) != FLOAT_CLASS_P ( class2 ) ) return true ; if ( MMX_CLASS_P ( class1 ) != MMX_CLASS_P ( class2 ) ) return true ; if ( MASK_CLASS_P ( class1 ) != MASK_CLASS_P ( class2 ) ) { if ( ! ( INTEGER_CLASS_P ( class1 ) || INTEGER_CLASS_P ( class2 ) ) || GET_MODE_SIZE ( mode ) > UNITS_PER_WORD ) return true ; } if ( SSE_CLASS_P ( class1 ) != SSE_CLASS_P ( class2 ) ) { if ( ! TARGET_SSE2 ) return true ; if ( ! ( INTEGER_CLASS_P ( class1 ) || INTEGER_CLASS_P ( class2 ) ) ) return true ; int msize = GET_MODE_SIZE ( mode ) ; if ( msize > UNITS_PER_WORD ) return true ; int minsize = GET_MODE_SIZE ( TARGET_SSE2 ? HImode : SImode ) ; if ( msize < minsize ) 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 ; } 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> bool insn_defines_reg ( unsigned int regno1 , unsigned int regno2 , rtx_insn * 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 insn_is_function_arg ( rtx insn , bool * is_spilled ) { rtx dst ; if ( ! NONDEBUG_INSN_P ( insn ) ) return false ; if ( CALL_P ( insn ) ) return false ; insn = PATTERN ( insn ) ; if ( GET_CODE ( insn ) == PARALLEL ) insn = XVECEXP ( insn , 0 , 0 ) ; if ( GET_CODE ( insn ) != SET ) return false ; dst = SET_DEST ( insn ) ; if ( REG_P ( dst ) && HARD_REGISTER_P ( dst ) && ix86_function_arg_regno_p ( REGNO ( dst ) ) ) { if ( ! TEST_HARD_REG_BIT ( fixed_reg_set , REGNO ( dst ) ) && ix86_class_likely_spilled_p ( REGNO_REG_CLASS ( REGNO ( dst ) ) ) ) * is_spilled = true ; return true ; } return false ; } </s>

Returns true if lhs of insn is HW function argument register and set up is_spilled to true if it is likely spilled HW register .


<s> static bool insn_uses_reg_mem ( unsigned int regno , rtx insn ) { df_ref use ; FOR_EACH_INSN_USE ( use , insn ) if ( DF_REF_REG_MEM_P ( use ) && regno == DF_REF_REGNO ( use ) ) return true ; return false ; } </s>

Function checks if instruction INSN uses register number REGNO as a part of address expression .


<s> static bool is_imported_p ( rtx x ) { if ( ! TARGET_DLLIMPORT_DECL_ATTRIBUTES || GET_CODE ( x ) != SYMBOL_REF ) return false ; return SYMBOL_REF_DLLIMPORT_P ( x ) || SYMBOL_REF_STUBVAR_P ( x ) ; } </s>

Nonzero if the symbol is marked as dllimport , or as stub-variable , otherwise zero .


<s> static bool is_va_list_char_pointer ( tree type ) { tree canonic ; if ( ! TARGET_64BIT ) return true ; canonic = ix86_canonical_va_list_type ( type ) ; return ( canonic == ms_va_list_type_node || ( ix86_abi == MS_ABI && canonic == va_list_type_node ) ) ; } </s>

Checks if TYPE is of kind va_list char * .


<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 && SUBREG_P ( parts . base ) ) parts . base = SUBREG_REG ( parts . base ) ; if ( parts . index && SUBREG_P ( parts . index ) ) 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_CPU_P ( 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 bool ix86_addr_space_zero_address_valid ( addr_space_t as ) { return as != ADDR_SPACE_GENERIC ; } </s>

All use of segmentation is assumed to make address 0 valid .


<s> static void ix86_add_cfa_restore_note ( rtx_insn * 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_queued_cfa_restore_notes ( rtx insn ) { rtx last ; if ( ! queued_cfa_restores ) return ; for ( last = queued_cfa_restores ; XEXP ( last , 1 ) ; last = XEXP ( last , 1 ) ) ; XEXP ( last , 1 ) = REG_NOTES ( insn ) ; REG_NOTES ( insn ) = queued_cfa_restores ; queued_cfa_restores = NULL_RTX ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } </s>

Add queued REG_CFA_RESTORE notes if any to INSN .


<s> static int ix86_adjust_priority ( rtx_insn * insn , int priority ) { rtx set ; if ( reload_completed ) return priority ; if ( ! NONDEBUG_INSN_P ( insn ) ) return priority ; set = single_set ( insn ) ; if ( set ) { rtx tmp = SET_SRC ( set ) ; if ( REG_P ( tmp ) && HARD_REGISTER_P ( tmp ) && ! TEST_HARD_REG_BIT ( fixed_reg_set , REGNO ( tmp ) ) && ix86_class_likely_spilled_p ( REGNO_REG_CLASS ( REGNO ( tmp ) ) ) ) return current_sched_info -> sched_max_insns_priority ; } return priority ; } </s>

Hook for pre-reload schedule - set priority of moves from likely spilled HW registers to maximum , to schedule them at soon as possible . These are moves from function argument registers at the top of the function entry and moves from function return value registers after call .


<s> static unsigned HOST_WIDE_INT ix86_asan_shadow_offset ( void ) { return SUBTARGET_SHADOW_OFFSET ; } </s>

Implement the TARGET_ASAN_SHADOW_OFFSET hook .


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 ) { rtx op = recog_data . operand [ i ] ; if ( MEM_P ( op ) ) { 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 ; } int len = memory_address_length ( XEXP ( op , 0 ) , false ) ; if ( ! ADDR_SPACE_GENERIC_P ( MEM_ADDR_SPACE ( op ) ) ) len ++ ; return len ; } } return 0 ; } </s>

Compute default value for `` length_address '' attribute .


<s>
int
ix86_attr_length_immediate_default
(
rtx_insn
*
insn
,
bool
shortform
)
{
int
len
=
0
;
int
i
;
extract_insn_cached
(
insn
)
;
for
(
i
=
recog_data
.
n_operands
1
;
i
>=
0
;
i
)
if
(
CONSTANT_P
(
recog_data
.
operand
[
i
]
)
)
{
enum
attr_mode
mode
=
get_attr_mode
(
insn
)
;
gcc_assert
(
!
len
)
;
if
(
shortform
&&
CONST_INT_P
(
recog_data
.
operand
[
i
]
)
)
{
HOST_WIDE_INT
ival
=
INTVAL
(
recog_data
.
operand
[
i
]
)
;
switch
(
mode
)
{
case
MODE_QI
:
len
=
1
;
continue
;
case
MODE_HI
:
ival
=
trunc_int_for_mode
(
ival
,
HImode
)
;
break
;
case
MODE_SI
:
ival
=
trunc_int_for_mode
(
ival
,
SImode
)
;
break
;
default
:
break
;
}
if
(
IN_RANGE
(
ival
,
128
,
127
)
)
{
len
=
1
;
continue
;
}
}
switch
(
mode
)
{
case
MODE_QI
:
len
=
1
;
break
;
case
MODE_HI
:
len
=
2
;
break
;
case
MODE_SI
:
len
=
4
;
break
;
case
MODE_DI
:
len
=
4
;
break
;
default
:
fatal_insn
(
"unknown insn mode"
,
insn
)
;
}
}
return
len
;
}
</s>

Compute default value for `` length_immediate '' attribute . When SHORTFORM is set expect that insn have 8bit immediate alternative .


<s> int ix86_attr_length_vex_default ( rtx_insn * insn , bool has_0f_opcode , bool has_vex_w ) { int i ; if ( ! has_0f_opcode || has_vex_w ) return 3 + 1 ; if ( ! TARGET_64BIT ) return 2 + 1 ; extract_insn_cached ( insn ) ; for ( i = recog_data . n_operands - 1 ; i >= 0 ; -- i ) if ( REG_P ( recog_data . operand [ i ] ) ) { if ( GET_MODE ( recog_data . operand [ i ] ) == DImode && GENERAL_REG_P ( recog_data . operand [ i ] ) ) return 3 + 1 ; } else { if ( MEM_P ( recog_data . operand [ i ] ) && x86_extended_reg_mentioned_p ( recog_data . operand [ i ] ) ) return 3 + 1 ; } return 2 + 1 ; } </s>

Compute default value for `` length_vex '' attribute . It includes 2 or 3 byte VEX prefix and 1 opcode byte .


<s> static unsigned int ix86_autovectorize_vector_modes ( vector_modes * modes , bool all ) { if ( TARGET_AVX512F && ! TARGET_PREFER_AVX256 ) { modes -> safe_push ( V64QImode ) ; modes -> safe_push ( V32QImode ) ; modes -> safe_push ( V16QImode ) ; } else if ( TARGET_AVX512F && all ) { modes -> safe_push ( V32QImode ) ; modes -> safe_push ( V16QImode ) ; modes -> safe_push ( V64QImode ) ; } else if ( TARGET_AVX && ! TARGET_PREFER_AVX128 ) { modes -> safe_push ( V32QImode ) ; modes -> safe_push ( V16QImode ) ; } else if ( TARGET_AVX && all ) { modes -> safe_push ( V16QImode ) ; modes -> safe_push ( V32QImode ) ; } else if ( TARGET_SSE2 ) modes -> safe_push ( V16QImode ) ; if ( TARGET_MMX_WITH_SSE ) modes -> safe_push ( V8QImode ) ; if ( TARGET_SSE2 ) modes -> safe_push ( V4QImode ) ; return 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
)
)
{
align_flags
alignment
=
label_to_alignment
(
insn
)
;
int
align
=
alignment
.
levels
[
0
]
.
log
;
int
max_skip
=
alignment
.
levels
[
0
]
.
maxskip
;
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
-=
ix86_min_insn_size
(
start
)
;
}
}
continue
;
}
min_size
=
ix86_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
-=
ix86_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
+
ix86_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_add ( rtx_insn * insn , rtx operands [ ] ) { unsigned int regno0 , regno1 , regno2 ; if ( ! TARGET_OPT_AGU || optimize_function_for_size_p ( cfun ) ) return false ; regno0 = true_regnum ( operands [ 0 ] ) ; regno1 = true_regnum ( operands [ 1 ] ) ; regno2 = true_regnum ( operands [ 2 ] ) ; if ( regno0 == regno1 || regno0 == regno2 ) return false ; else return ! ix86_lea_outperforms ( insn , regno0 , regno1 , regno2 , 1 , false ) ; } </s>

Return true if we need to split op0 = op1 + op2 into a sequence of move and add to avoid AGU stalls .


<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 ( REG_P ( operands [ 1 ] ) || ( SImode_address_operand ( operands [ 1 ] , VOIDmode ) && REG_P ( XEXP ( operands [ 1 ] , 0 ) ) ) ) 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 ) ; if ( ! TARGET_CPU_P ( BONNELL ) && parts . scale == 1 && ( ! parts . disp || parts . disp == const0_rtx ) && ( regno0 == regno1 || regno0 == regno2 ) ) return true ; if ( ! TARGET_AVOID_LEA_FOR_ADDR || optimize_function_for_size_p ( cfun ) ) return false ; 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 int ix86_avx_u128_mode_after ( int mode , rtx_insn * insn ) { rtx pat = PATTERN ( insn ) ; if ( vzeroupper_pattern ( pat , VOIDmode ) || vzeroall_pattern ( pat , VOIDmode ) ) return AVX_U128_CLEAN ; if ( CALL_P ( insn ) ) { bool avx_upper_reg_found = false ; note_stores ( insn , ix86_check_avx_upper_stores , & avx_upper_reg_found ) ; return avx_upper_reg_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 ( DEBUG_INSN_P ( insn ) ) return AVX_U128_ANY ; 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_avx_upper_register ( arg ) ) return AVX_U128_DIRTY ; } } bool avx_upper_reg_found = false ; note_stores ( insn , ix86_check_avx_upper_stores , & avx_upper_reg_found ) ; if ( avx_upper_reg_found ) return AVX_U128_DIRTY ; const function_abi & abi = insn_callee_abi ( insn ) ; if ( ! hard_reg_set_subset_p ( reg_class_contents [ SSE_REGS ] , abi . mode_clobbers ( V4DImode ) ) ) return AVX_U128_ANY ; return AVX_U128_CLEAN ; } subrtx_iterator :: array_type array ; rtx set = single_set ( insn ) ; if ( set ) { rtx dest = SET_DEST ( set ) ; rtx src = SET_SRC ( set ) ; if ( ix86_check_avx_upper_register ( dest ) ) { if ( standard_sse_constant_p ( src , GET_MODE ( dest ) ) != 1 ) return AVX_U128_DIRTY ; else return AVX_U128_ANY ; } else { FOR_EACH_SUBRTX ( iter , array , src , NONCONST ) if ( ix86_check_avx_upper_register ( * iter ) ) return AVX_U128_DIRTY ; } return AVX_U128_ANY ; } FOR_EACH_SUBRTX ( iter , array , PATTERN ( insn ) , NONCONST ) if ( ix86_check_avx_upper_register ( * iter ) ) return AVX_U128_DIRTY ; return AVX_U128_ANY ; } </s>

Return needed mode for entity in optimize_mode_switching pass .


<s> static bool ix86_binds_local_p ( const_tree exp ) { bool direct_extern_access = ( ix86_direct_extern_access && ! ( VAR_OR_FUNCTION_DECL_P ( exp ) && lookup_attribute ( "nodirect_extern_access" , DECL_ATTRIBUTES ( exp ) ) ) ) ; if ( ! direct_extern_access ) ix86_has_no_direct_extern_access = true ; return default_binds_local_p_3 ( exp , flag_shlib != 0 , true , direct_extern_access , ( direct_extern_access && ( ! flag_pic || ( TARGET_64BIT && HAVE_LD_PIE_COPYRELOC != 0 ) ) ) ) ; } </s>

For i386 , common symbol is local only for non-PIE binaries . For x86-64 , common symbol is local only for non-PIE binaries or linker supports copy reloc in PIE binaries .


<s>
static
tree
ix86_build_builtin_va_list
(
void
)
{
if
(
TARGET_64BIT
)
{
sysv_va_list_type_node
=
ix86_build_builtin_va_list_64
(
)
;
tree
char_ptr_type
=
build_pointer_type
(
char_type_node
)
;
tree
attr
=
tree_cons
(
get_identifier
(
"ms_abi va_list"
)
,
NULL_TREE
,
TYPE_ATTRIBUTES
(
char_ptr_type
)
)
;
ms_va_list_type_node
=
build_type_attribute_variant
(
char_ptr_type
,
attr
)
;
return
(
(
ix86_abi
==
MS_ABI
)
ms_va_list_type_node
:
sysv_va_list_type_node
)
;
}
else
{
return
build_pointer_type
(
char_type_node
)
;
}
}
</s>


<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 E_V64QImode : case E_V32QImode : case E_V16QImode : case E_V32HImode : case E_V16HImode : case E_V8HImode : case E_V16SImode : case E_V8SImode : case E_V4SImode : case E_V2SImode : case E_V8DImode : case E_V4DImode : case E_V2DImode : gcc_assert ( vect ) ; case E_V8HFmode : case E_V16HFmode : case E_V32HFmode : case E_V16SFmode : case E_V8SFmode : case E_V4SFmode : case E_V2SFmode : case E_V8DFmode : case E_V4DFmode : case E_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 ; wide_int w ; rtx mask , v ; switch ( mode ) { case E_V8HFmode : case E_V16HFmode : case E_V32HFmode : vec_mode = mode ; imode = HImode ; break ; case E_V16SImode : case E_V16SFmode : case E_V8SImode : case E_V4SImode : case E_V8SFmode : case E_V4SFmode : case E_V2SFmode : case E_V2SImode : vec_mode = mode ; imode = SImode ; break ; case E_V8DImode : case E_V4DImode : case E_V2DImode : case E_V8DFmode : case E_V4DFmode : case E_V2DFmode : vec_mode = mode ; imode = DImode ; break ; case E_TImode : case E_TFmode : vec_mode = VOIDmode ; imode = TImode ; break ; default : gcc_unreachable ( ) ; } machine_mode inner_mode = GET_MODE_INNER ( mode ) ; w = wi :: set_bit_in_zero ( GET_MODE_BITSIZE ( inner_mode ) - 1 , GET_MODE_BITSIZE ( inner_mode ) ) ; if ( invert ) w = wi :: bit_not ( w ) ; mask = immed_wide_int_const ( w , imode ) ; mask = gen_lowpart ( inner_mode , mask ) ; if ( vec_mode == VOIDmode ) return force_reg ( inner_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 .