<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 ) SET_HARD_REG_BIT ( indirect_thunks_used , regno ) ; indirect_thunk_name ( thunk_name_buf , regno , need_prefix , false ) ; thunk_name = thunk_name_buf ; } else thunk_name = NULL ; if ( sibcall_p ) ix86_output_jmp_thunk_or_indirect ( thunk_name , regno ) ; else { if ( thunk_name != NULL ) { if ( REX_INT_REGNO_P ( regno ) && ix86_indirect_branch_cs_prefix ) fprintf ( asm_out_file , "\tcs\n" ) ; fprintf ( asm_out_file , "\tcall\t" ) ; assemble_name ( asm_out_file , thunk_name ) ; putc ( '\n' , asm_out_file ) ; 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 ) ; ix86_output_jmp_thunk_or_indirect ( thunk_name , regno ) ; ASM_OUTPUT_INTERNAL_LABEL ( asm_out_file , indirectlabel2 ) ; fputs ( "\tcall\t" , asm_out_file ) ; assemble_name_raw ( asm_out_file , indirectlabel1 ) ; fputc ( '\n' , asm_out_file ) ; } } </s>

Output indirect branch via a call and return thunk . CALL_OP is 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 ; SET_HARD_REG_BIT ( indirect_thunks_used , CX_REG ) ; } fprintf ( asm_out_file , "\tjmp\t" ) ; assemble_name ( asm_out_file , thunk_name ) ; putc ( '\n' , asm_out_file ) ; } else output_indirect_thunk ( regno ) ; } else { output_asm_insn ( "%!jmp\t%A0" , & ret_op ) ; if ( ix86_harden_sls & harden_sls_indirect_jmp ) fputs ( "\tint3\n" , asm_out_file ) ; } return "" ; } </s>

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


<s> const char * ix86_output_indirect_jmp ( rtx call_op ) { if ( cfun -> machine -> indirect_branch_type != indirect_branch_keep ) { if ( ix86_red_zone_used ) gcc_unreachable ( ) ; ix86_output_indirect_branch ( call_op , "%0" , true ) ; } else output_asm_insn ( "%!jmp\t%A0" , & call_op ) ; return ( ix86_harden_sls & harden_sls_indirect_jmp ) ? "int3" : "" ; } </s>

Output indirect jump . CALL_OP is the jump target .


<s> static void ix86_output_jmp_thunk_or_indirect ( const char * thunk_name , const int regno ) { if ( thunk_name != NULL ) { if ( REX_INT_REGNO_P ( regno ) && ix86_indirect_branch_cs_prefix ) fprintf ( asm_out_file , "\tcs\n" ) ; fprintf ( asm_out_file , "\tjmp\t" ) ; assemble_name ( asm_out_file , thunk_name ) ; putc ( '\n' , asm_out_file ) ; if ( ( ix86_harden_sls & harden_sls_indirect_jmp ) ) fputs ( "\tint3\n" , asm_out_file ) ; } else output_indirect_thunk ( regno ) ; } </s>


<s> void ix86_output_patchable_area ( unsigned int patch_area_size , bool record_p ) { default_print_patchable_function_entry ( asm_out_file , patch_area_size , record_p ) ; } </s>

Output patchable area . NB : default_print_patchable_function_entry is n't available in i386.md .


<s>
const
char
*
ix86_output_ssemov
(
rtx_insn
*
insn
,
rtx
*
operands
)
{
machine_mode
mode
=
GET_MODE
(
operands
[
0
]
)
;
if
(
get_attr_type
(
insn
)
!=
TYPE_SSEMOV
||
mode
!=
GET_MODE
(
operands
[
1
]
)
)
gcc_unreachable
(
)
;
enum
attr_mode
insn_mode
=
get_attr_mode
(
insn
)
;
switch
(
insn_mode
)
{
case
MODE_XI
:
case
MODE_V8DF
:
case
MODE_V16SF
:
return
ix86_get_ssemov
(
operands
,
64
,
insn_mode
,
mode
)
;
case
MODE_OI
:
case
MODE_V4DF
:
case
MODE_V8SF
:
return
ix86_get_ssemov
(
operands
,
32
,
insn_mode
,
mode
)
;
case
MODE_TI
:
case
MODE_V2DF
:
case
MODE_V4SF
:
return
ix86_get_ssemov
(
operands
,
16
,
insn_mode
,
mode
)
;
case
MODE_DI
:
if
(
GENERAL_REG_P
(
operands
[
0
]
)
)
{
if
(
HAVE_AS_IX86_INTERUNIT_MOVQ
)
return
"%vmovq\t{%1, %q0|%q0, %1}"
;
else
return
"%vmovd\t{%1, %q0|%q0, %1}"
;
}
else
if
(
GENERAL_REG_P
(
operands
[
1
]
)
)
{
if
(
HAVE_AS_IX86_INTERUNIT_MOVQ
)
return
"%vmovq\t{%q1, %0|%0, %q1}"
;
else
return
"%vmovd\t{%q1, %0|%0, %q1}"
;
}
else
return
"%vmovq\t{%1, %0|%0, %1}"
;
case
MODE_SI
:
if
(
GENERAL_REG_P
(
operands
[
0
]
)
)
return
"%vmovd\t{%1, %k0|%k0, %1}"
;
else
if
(
GENERAL_REG_P
(
operands
[
1
]
)
)
return
"%vmovd\t{%k1, %0|%0, %k1}"
;
else
return
"%vmovd\t{%1, %0|%0, %1}"
;
case
MODE_HI
:
if
(
GENERAL_REG_P
(
operands
[
0
]
)
)
return
"vmovw\t{%1, %k0|%k0, %1}"
;
else
if
(
GENERAL_REG_P
(
operands
[
1
]
)
)
return
"vmovw\t{%k1, %0|%0, %k1}"
;
else
return
"vmovw\t{%1, %0|%0, %1}"
;
case
MODE_DF
:
if
(
TARGET_AVX
&&
REG_P
(
operands
[
0
]
)
&&
REG_P
(
operands
[
1
]
)
)
return
"vmovsd\t{%d1, %0|%0, %d1}"
;
else
return
"%vmovsd\t{%1, %0|%0, %1}"
;
case
MODE_SF
:
if
(
TARGET_AVX
&&
REG_P
(
operands
[
0
]
)
&&
REG_P
(
operands
[
1
]
)
)
return
"vmovss\t{%d1, %0|%0, %d1}"
;
else
return
"%vmovss\t{%1, %0|%0, %1}"
;
case
MODE_HF
:
if
(
REG_P
(
operands
[
0
]
)
&&
REG_P
(
operands
[
1
]
)
)
return
"vmovsh\t{%d1, %0|%0, %d1}"
;
else
return
"vmovsh\t{%1, %0|%0, %1}"
;
case
MODE_V1DF
:
gcc_assert
(
!
TARGET_AVX
)
;
return
"movlpd\t{%1, %0|%0, %1}"
;
case
MODE_V2SF
:
if
(
TARGET_AVX
&&
REG_P
(
operands
[
0
]
)
)
return
"vmovlps\t{%1, %d0|%d0, %1}"
;
else
return
"%vmovlps\t{%1, %0|%0, %1}"
;
default
:
gcc_unreachable
(
)
;
}
}
</s>

Return the template of the TYPE_SSEMOV instruction to move operands [ 1 ] into operands [ 0 ] .


<s> static void ix86_pad_returns ( void ) { edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , EXIT_BLOCK_PTR_FOR_FN ( cfun ) -> preds ) { basic_block bb = e -> src ; rtx_insn * ret = BB_END ( bb ) ; rtx_insn * prev ; bool replace = false ; if ( ! JUMP_P ( ret ) || ! ANY_RETURN_P ( PATTERN ( ret ) ) || optimize_bb_for_size_p ( bb ) ) continue ; for ( prev = PREV_INSN ( ret ) ; prev ; prev = PREV_INSN ( prev ) ) if ( active_insn_p ( prev ) || LABEL_P ( prev ) ) break ; if ( prev && LABEL_P ( prev ) ) { edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , bb -> preds ) if ( EDGE_FREQUENCY ( e ) && e -> src -> index >= 0 && ! ( e -> flags & EDGE_FALLTHRU ) ) { replace = true ; break ; } } if ( ! replace ) { prev = prev_active_insn ( ret ) ; if ( prev && ( ( JUMP_P ( prev ) && any_condjump_p ( prev ) ) || CALL_P ( prev ) ) ) replace = true ; if ( ! prev && ! optimize_function_for_size_p ( cfun ) ) replace = true ; } if ( replace ) { emit_jump_insn_before ( gen_simple_return_internal_long ( ) , ret ) ; delete_insn ( ret ) ; } } } </s>

AMD Athlon works faster when RET is not destination of conditional jump or directly preceded by other jump instruction . We avoid the penalty by inserting NOP just before the RET instructions in such cases .


<s> static void ix86_pad_short_function ( void ) { edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , EXIT_BLOCK_PTR_FOR_FN ( cfun ) -> preds ) { rtx_insn * ret = BB_END ( e -> src ) ; if ( JUMP_P ( ret ) && ANY_RETURN_P ( PATTERN ( ret ) ) ) { int insn_count = ix86_count_insn ( e -> src ) ; if ( insn_count < 4 ) { rtx_insn * insn = ret ; while ( insn && ( ! NOTE_P ( insn ) || NOTE_KIND ( insn ) != NOTE_INSN_EPILOGUE_BEG ) ) insn = PREV_INSN ( insn ) ; if ( ! insn ) insn = ret ; insn_count = 2 * ( 4 - insn_count ) ; emit_insn_before ( gen_nops ( GEN_INT ( insn_count ) ) , insn ) ; } } } } </s>


<s> static bool ix86_pass_by_reference ( cumulative_args_t cum_v , const function_arg_info & arg ) { 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 ( arg . mode ) ; if ( tree type = arg . 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 ( arg . type && int_size_in_bytes ( arg . 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 bool ix86_pic_register_p ( rtx x ) { if ( GET_CODE ( x ) == VALUE && CSELIB_VAL_PTR ( x ) ) return ( pic_offset_table_rtx && rtx_equal_for_cselib_p ( x , pic_offset_table_rtx ) ) ; else if ( GET_CODE ( x ) == UNSPEC && XINT ( x , 1 ) == UNSPEC_SET_GOT ) return true ; else if ( ! REG_P ( x ) ) return false ; else if ( pic_offset_table_rtx ) { if ( REGNO ( x ) == REGNO ( pic_offset_table_rtx ) ) return true ; if ( HARD_REGISTER_P ( x ) && ! HARD_REGISTER_P ( pic_offset_table_rtx ) && ORIGINAL_REGNO ( x ) == REGNO ( pic_offset_table_rtx ) ) return true ; return false ; } else return REGNO ( x ) == PIC_OFFSET_TABLE_REGNUM ; } </s>

Return true if X is a representation of the PIC register . This copes with calls from ix86_find_base_term , where the register might have been replaced by a cselib value .


<s> static reg_class_t ix86_preferred_output_reload_class ( rtx x , reg_class_t regclass ) { machine_mode 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> static reg_class_t ix86_preferred_reload_class ( rtx x , reg_class_t regclass ) { machine_mode mode = GET_MODE ( x ) ; if ( regclass == NO_REGS ) return NO_REGS ; if ( x == CONST0_RTX ( mode ) ) return regclass ; if ( CONSTANT_P ( x ) && ( MAYBE_MMX_CLASS_P ( regclass ) || MAYBE_SSE_CLASS_P ( regclass ) || MAYBE_MASK_CLASS_P ( regclass ) ) ) return NO_REGS ; if ( CONST_DOUBLE_P ( x ) ) { if ( INTEGER_CLASS_P ( regclass ) ) return regclass ; if ( IS_STACK_MODE ( mode ) && standard_80387_constant_p ( x ) > 0 ) { if ( FLOAT_CLASS_P ( regclass ) ) return FLOAT_REGS ; } return NO_REGS ; } if ( SSE_FLOAT_MODE_P ( mode ) && TARGET_SSE_MATH ) { if ( TARGET_INTER_UNIT_MOVES_FROM_VEC && TARGET_INTER_UNIT_MOVES_TO_VEC && GET_MODE_SIZE ( mode ) <= GET_MODE_SIZE ( word_mode ) ) return INT_SSE_CLASS_P ( regclass ) ? regclass : NO_REGS ; else return SSE_CLASS_P ( regclass ) ? regclass : NO_REGS ; } if ( GET_CODE ( x ) == PLUS ) return INTEGER_CLASS_P ( regclass ) ? regclass : NO_REGS ; if ( GET_MODE ( x ) == QImode && ! CONSTANT_P ( x ) ) { if ( Q_CLASS_P ( regclass ) ) return regclass ; else if ( reg_class_subset_p ( Q_REGS , regclass ) ) return Q_REGS ; else if ( MASK_CLASS_P ( regclass ) ) return regclass ; else return NO_REGS ; } return regclass ; } </s>

Put float CONST_DOUBLE in the constant pool instead of fp regs . QImode must go into class Q_REGS . Narrow ALL_REGS to GENERAL_REGS . This supports allowing movsf and movdf to do mem-to-mem moves through integer regs .


<s> bool ix86_pre_reload_split ( void ) { return ( can_create_pseudo_p ( ) && ! ( cfun -> curr_properties & PROP_rtl_split_insns ) ) ; } </s>

Predicate for pre-reload splitters with associated instructions , which can match any time before the split1 pass ( usually combine ) , then are unconditionally split in that pass and should not be matched again afterwards .


<s>
static
void
ix86_print_operand_address
(
FILE
*
file
,
machine_mode
,
rtx
addr
)
{
if
(
this_is_asm_operands
&&
!
address_operand
(
addr
,
VOIDmode
)
)
output_operand_lossage
(
"invalid constraints for operand"
)
;
else
ix86_print_operand_address_as
(
file
,
addr
,
ADDR_SPACE_GENERIC
,
false
)
;
}
</s>

Print a memory operand whose address is ADDR .


<s> void ix86_print_patchable_function_entry ( FILE * file , unsigned HOST_WIDE_INT patch_area_size , bool record_p ) { if ( cfun -> machine -> function_label_emitted ) { return ; } default_print_patchable_function_entry ( file , patch_area_size , record_p ) ; } </s>


<s> static bool ix86_profile_before_prologue ( void ) { return flag_fentry != 0 ; } </s>

Return true , if profiling code should be emitted before prologue . Otherwise it returns false . Note : For x86 with `` hotfix '' it is sorried .


<s> static machine_mode ix86_promote_function_mode ( const_tree type , machine_mode mode , int * punsignedp , const_tree fntype , int for_return ) { if ( cfun -> machine -> func_type == TYPE_NORMAL && type != NULL_TREE && POINTER_TYPE_P ( type ) ) { * punsignedp = POINTERS_EXTEND_UNSIGNED ; return word_mode ; } return default_promote_function_mode ( type , mode , punsignedp , fntype , for_return ) ; } </s>

Pointer function arguments and return values are promoted to word_mode .


<s> static bool ix86_push_argument ( unsigned int npush ) { return ( ( ! TARGET_SSE2 || npush < ( TARGET_64BIT ? 16 : 8 ) ) && TARGET_PUSH_ARGS && ! ACCUMULATE_OUTGOING_ARGS ) ; } </s>


<s> poly_int64 ix86_push_rounding ( poly_int64 bytes ) { return ROUND_UP ( bytes , UNITS_PER_WORD ) ; } </s>

Implement PUSH_ROUNDING . On 386 , we have pushw instruction that decrements by exactly 2 no matter what the position was , there is no pushb . But as CIE data alignment factor on this arch is -4 for 32bit targets and -8 for 64bit targets , we need to make sure all stack pointer adjustments are in multiple of 4 for 32bit targets and 8 for 64bit targets .


<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 || ix86_tune == PROCESSOR_ZNVER3 ) && INTEGRAL_MODE_P ( mode ) && op != PLUS && op != MINUS ) return 1 ; if ( TARGET_AVX256_SPLIT_REGS && 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 int ix86_register_move_cost ( machine_mode mode , reg_class_t class1_i , reg_class_t class2_i ) { enum reg_class class1 = ( enum reg_class ) class1_i ; enum reg_class class2 = ( enum reg_class ) class2_i ; if ( inline_secondary_memory_needed ( mode , class1 , class2 , false ) ) { int cost = 1 ; cost += inline_memory_move_cost ( mode , class1 , 2 ) ; cost += inline_memory_move_cost ( mode , class2 , 2 ) ; if ( GET_MODE_BITSIZE ( mode ) > BITS_PER_WORD && TARGET_MEMORY_MISMATCH_STALL && targetm . class_max_nregs ( class1 , mode ) > targetm . class_max_nregs ( class2 , mode ) ) cost += 20 ; if ( ( MMX_CLASS_P ( class1 ) && MAYBE_FLOAT_CLASS_P ( class2 ) ) || ( MMX_CLASS_P ( class2 ) && MAYBE_FLOAT_CLASS_P ( class1 ) ) ) cost += 20 ; return cost ; } if ( MMX_CLASS_P ( class1 ) != MMX_CLASS_P ( class2 ) ) gcc_unreachable ( ) ; if ( SSE_CLASS_P ( class1 ) != SSE_CLASS_P ( class2 ) ) return ( SSE_CLASS_P ( class1 ) ? ix86_cost -> hard_register . sse_to_integer : ix86_cost -> hard_register . integer_to_sse ) ; if ( MASK_CLASS_P ( class1 ) != MASK_CLASS_P ( class2 ) ) { return ( MASK_CLASS_P ( class1 ) ? ix86_cost -> hard_register . mask_to_integer : ix86_cost -> hard_register . integer_to_mask ) ; } if ( MASK_CLASS_P ( class1 ) && MASK_CLASS_P ( class2 ) ) return ix86_cost -> hard_register . mask_move ; if ( MAYBE_FLOAT_CLASS_P ( class1 ) ) return ix86_cost -> hard_register . fp_move ; if ( MAYBE_SSE_CLASS_P ( class1 ) ) { if ( GET_MODE_BITSIZE ( mode ) <= 128 ) return ix86_cost -> hard_register . xmm_move ; if ( GET_MODE_BITSIZE ( mode ) <= 256 ) return ix86_cost -> hard_register . ymm_move ; return ix86_cost -> hard_register . zmm_move ; } if ( MAYBE_MMX_CLASS_P ( class1 ) ) return ix86_cost -> hard_register . mmx_move ; return 2 ; } </s>

Return the cost of moving data from a register in class CLASS1 to one in class CLASS2 . It is not required that the cost always equal 2 when FROM is the same as TO ; on some machines it is expensive to move between registers if they are not general registers .


<s> static int ix86_register_priority ( int hard_regno ) { if ( hard_regno == R12_REG || hard_regno == R13_REG ) return 0 ; if ( hard_regno == BP_REG ) return 1 ; if ( REX_INT_REGNO_P ( hard_regno ) ) return 2 ; if ( REX_SSE_REGNO_P ( hard_regno ) ) return 2 ; if ( EXT_REX_SSE_REGNO_P ( hard_regno ) ) return 1 ; if ( hard_regno == AX_REG ) return 4 ; return 3 ; } </s>

Return a register priority for hard reg REGNO .


<s> unsigned int ix86_regmode_natural_size ( machine_mode mode ) { if ( mode == P2HImode || mode == P2QImode ) return GET_MODE_SIZE ( mode ) / 2 ; return UNITS_PER_WORD ; } </s>

Implement REGMODE_NATURAL_SIZE ( MODE ) .


<s> int ix86_reg_parm_stack_space ( const_tree fndecl ) { enum calling_abi call_abi = SYSV_ABI ; if ( fndecl != NULL_TREE && TREE_CODE ( fndecl ) == FUNCTION_DECL ) call_abi = ix86_function_abi ( fndecl ) ; else call_abi = ix86_function_type_abi ( fndecl ) ; if ( TARGET_64BIT && call_abi == MS_ABI ) return 32 ; return 0 ; } </s>

It returns the size , in bytes , of the area reserved for arguments passed in registers for the function represented by fndecl dependent to the used abi format .


<s> static int ix86_reloc_rw_mask ( void ) { return ( flag_pic || ! ix86_direct_extern_access ) ? 3 : 0 ; } </s>

If flag_pic or ix86_direct_extern_access is false , then neither local nor global relocs should be placed in readonly memory .


<s> static void ix86_reorg ( void ) { compute_bb_for_insn ( ) ; if ( TARGET_SEH && current_function_has_exception_handlers ( ) ) ix86_seh_fixup_eh_fallthru ( ) ; if ( optimize && optimize_function_for_speed_p ( cfun ) ) { if ( TARGET_SSE2 ) ix86_split_stlf_stall_load ( ) ; if ( TARGET_PAD_SHORT_FUNCTION ) ix86_pad_short_function ( ) ; else if ( TARGET_PAD_RETURNS ) ix86_pad_returns ( ) ; if ( TARGET_FOUR_JUMP_LIMIT ) ix86_avoid_jump_mispredicts ( ) ; } } </s>

Implement machine specific optimizations . We implement padding of returns for K8 CPUs and pass to avoid 4 jumps in the single 16 byte window .


<s> static bool ix86_return_in_memory ( const_tree type , const_tree fntype ATTRIBUTE_UNUSED ) { const machine_mode mode = type_natural_mode ( type , NULL , true ) ; HOST_WIDE_INT size ; if ( TARGET_64BIT ) { if ( ix86_function_type_abi ( fntype ) == MS_ABI ) { size = int_size_in_bytes ( type ) ; if ( ( ! type || VECTOR_INTEGER_TYPE_P ( type ) || INTEGRAL_TYPE_P ( type ) || VECTOR_FLOAT_TYPE_P ( type ) ) && ( SCALAR_INT_MODE_P ( mode ) || VECTOR_MODE_P ( mode ) ) && ! COMPLEX_MODE_P ( mode ) && ( GET_MODE_SIZE ( mode ) == 16 || size == 16 ) ) return false ; return size != 1 && size != 2 && size != 4 && size != 8 ; } else { int needed_intregs , needed_sseregs ; return examine_argument ( mode , type , 1 , & needed_intregs , & needed_sseregs ) ; } } else { size = int_size_in_bytes ( type ) ; if ( TARGET_IAMCU ) return VECTOR_MODE_P ( mode ) || size < 0 || size > 8 ; if ( mode == BLKmode ) return true ; if ( MS_AGGREGATE_RETURN && AGGREGATE_TYPE_P ( type ) && size <= 8 ) return false ; if ( VECTOR_MODE_P ( mode ) || mode == TImode ) { if ( size < 8 ) return false ; if ( size == 8 ) return TARGET_VECT8_RETURNS || ! TARGET_MMX ; if ( size == 16 ) return ! TARGET_SSE ; if ( size == 32 ) return ! TARGET_AVX ; if ( size == 64 ) return ! TARGET_AVX512F ; } if ( mode == XFmode ) return false ; if ( size > 12 ) return true ; gcc_assert ( mode != OImode ) ; return false ; } } </s>

Return false iff type is returned in memory .


<s> static poly_int64 ix86_return_pops_args ( tree fundecl , tree funtype , poly_int64 size ) { unsigned int ccvt ; if ( TARGET_64BIT ) return 0 ; ccvt = ix86_get_callcvt ( funtype ) ; if ( ( ccvt & ( IX86_CALLCVT_STDCALL | IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL ) ) != 0 && ! stdarg_p ( funtype ) ) return size ; if ( aggregate_value_p ( TREE_TYPE ( funtype ) , fundecl ) && ! ix86_keep_aggregate_return_pointer ( funtype ) ) { int nregs = ix86_function_regparm ( funtype , fundecl ) ; if ( nregs == 0 ) return GET_MODE_SIZE ( Pmode ) ; } return 0 ; } </s>

Value is the number of bytes of arguments automatically popped when returning from a subroutine call . FUNDECL is the declaration node of the function ( as a tree ) , FUNTYPE is the data type of the function ( as a tree ) , or for a library call it is an identifier node for the subroutine name . SIZE is the number of bytes of arguments passed on the stack . On the 80386 , the RTD insn may be used to pop them if the number of args is fixed , but if the number is variable then the caller must pop them all . RTD ca n't be used for library calls now because the library is compiled with the Unix compiler . Use of RTD is a selectable option , since it is incompatible with standard Unix calling sequences . If the option is not selected , the caller must always pop the args . The attribute stdcall is equivalent to RTD on a per module basis .


<s> enum rtx_code ix86_reverse_condition ( enum rtx_code code , machine_mode mode ) { return ( mode == CCFPmode ? reverse_condition_maybe_unordered ( code ) : reverse_condition ( code ) ) ; } </s>


<s> rtx ix86_rewrite_tls_address ( rtx pattern ) { pattern = copy_insn ( pattern ) ; ix86_rewrite_tls_address_1 ( & pattern ) ; return pattern ; } </s>

Rewrite instruction pattern involvning TLS address so that it refers to a default TLS address space .


<s> void ix86_rewrite_tls_address_1 ( rtx * loc ) { subrtx_ptr_iterator :: array_type array ; FOR_EACH_SUBRTX_PTR ( iter , array , loc , ALL ) { rtx * loc = * iter ; if ( MEM_P ( * loc ) ) { rtx addr = XEXP ( * loc , 0 ) ; rtx * x = & addr ; while ( GET_CODE ( * x ) == PLUS ) { int i ; for ( i = 0 ; i < 2 ; i ++ ) { rtx u = XEXP ( * x , i ) ; if ( GET_CODE ( u ) == ZERO_EXTEND ) u = XEXP ( u , 0 ) ; if ( GET_CODE ( u ) == UNSPEC && XINT ( u , 1 ) == UNSPEC_TP ) { addr_space_t as = DEFAULT_TLS_SEG_REG ; * x = XEXP ( * x , 1 - i ) ; * loc = replace_equiv_address_nv ( * loc , addr , true ) ; set_mem_addr_space ( * loc , as ) ; return ; } } x = & XEXP ( * x , 0 ) ; } iter . skip_subrtxes ( ) ; } } } </s>

Rewrite * LOC so that it refers to a default TLS address space .


<s> bool ix86_rip_relative_addr_p ( struct ix86_address * parts ) { rtx base , index , disp ; base = parts -> base ; index = parts -> index ; disp = parts -> disp ; if ( disp && ! base && ! index ) { if ( TARGET_64BIT ) { rtx symbol = disp ; if ( GET_CODE ( disp ) == CONST ) symbol = XEXP ( disp , 0 ) ; if ( GET_CODE ( symbol ) == PLUS && CONST_INT_P ( XEXP ( symbol , 1 ) ) ) symbol = XEXP ( symbol , 0 ) ; if ( GET_CODE ( symbol ) == LABEL_REF || ( GET_CODE ( symbol ) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL ( symbol ) == 0 ) || ( GET_CODE ( symbol ) == UNSPEC && ( XINT ( symbol , 1 ) == UNSPEC_GOTPCREL || XINT ( symbol , 1 ) == UNSPEC_PCREL || XINT ( symbol , 1 ) == UNSPEC_GOTNTPOFF ) ) ) return true ; } } return false ; } </s>

Check whether x86 address PARTS is a pc-relative address .


<s> static void ix86_run_selftests ( void ) { ix86_test_dumping_hard_regs ( ) ; ix86_test_dumping_memory_blockage ( ) ; ix86_test_loading_dump_fragment_1 ( ) ; ix86_test_loading_call_insn ( ) ; ix86_test_loading_full_dump ( ) ; ix86_test_loading_unspec ( ) ; } </s>


<s> 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_or_fixed_reg_p ( regno ) && ( regno != HARD_FRAME_POINTER_REGNUM || ! frame_pointer_needed ) ) ; } </s>


<s> static bool ix86_scalar_mode_supported_p ( scalar_mode mode ) { if ( DECIMAL_FLOAT_MODE_P ( mode ) ) return default_decimal_float_supported_p ( ) ; else if ( mode == TFmode ) return true ; else if ( mode == HFmode && TARGET_SSE2 ) return true ; else return default_scalar_mode_supported_p ( mode ) ; } </s>

Target hook for scalar_mode_supported_p .


<s> static void ix86_sched_init_global ( FILE * , int , int ) { switch ( ix86_tune ) { case PROCESSOR_CORE2 : case PROCESSOR_NEHALEM : case PROCESSOR_SANDYBRIDGE : case PROCESSOR_HASWELL : case PROCESSOR_TREMONT : case PROCESSOR_ALDERLAKE : case PROCESSOR_GENERIC : if ( reload_completed ) { ix86_core2i7_init_hooks ( ) ; break ; } default : targetm . sched . dfa_post_advance_cycle = NULL ; targetm . sched . first_cycle_multipass_init = NULL ; targetm . sched . first_cycle_multipass_begin = NULL ; targetm . sched . first_cycle_multipass_issue = NULL ; targetm . sched . first_cycle_multipass_backtrack = NULL ; targetm . sched . first_cycle_multipass_end = NULL ; targetm . sched . first_cycle_multipass_fini = NULL ; break ; } } </s>


<s> static bool ix86_secondary_memory_needed ( machine_mode mode , reg_class_t class1 , reg_class_t class2 ) { return inline_secondary_memory_needed ( mode , class1 , class2 , true ) ; } </s>

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


<s> static machine_mode ix86_secondary_memory_needed_mode ( machine_mode mode ) { if ( GET_MODE_BITSIZE ( mode ) < 32 && INTEGRAL_MODE_P ( mode ) ) return mode_for_size ( 32 , GET_MODE_CLASS ( mode ) , 0 ) . require ( ) ; return mode ; } </s>

Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE . get_secondary_mem widens integral modes to BITS_PER_WORD . There is no need to emit full 64 bit move on 64 bit targets for integral modes that can be moved using 32 bit move .


<s> static void ix86_seh_fixup_eh_fallthru ( void ) { edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , EXIT_BLOCK_PTR_FOR_FN ( cfun ) -> preds ) { rtx_insn * insn , * next ; for ( insn = BB_END ( e -> src ) ; insn != NULL ; insn = PREV_INSN ( insn ) ) if ( NOTE_P ( insn ) && NOTE_KIND ( insn ) == NOTE_INSN_EPILOGUE_BEG ) break ; if ( insn == NULL ) continue ; insn = prev_active_insn ( insn ) ; if ( insn == NULL || ! can_throw_internal ( insn ) ) continue ; for ( next = NEXT_INSN ( insn ) ; next != NULL ; next = NEXT_INSN ( next ) ) if ( NOTE_P ( next ) && NOTE_KIND ( next ) == NOTE_INSN_VAR_LOCATION ) insn = next ; else break ; emit_insn_after ( gen_nops ( const1_rtx ) , insn ) ; } } </s>

Fix up a Windows system unwinder issue . If an EH region falls through into the epilogue , the Windows system unwinder will apply epilogue logic and produce incorrect offsets . This can be avoided by adding a nop between the last insn that can throw and the first insn of the epilogue .


Return > = 0 if there is an unused call-clobbered register available for the entire function .


<s> void ix86_setup_frame_addresses ( void ) { cfun -> machine -> accesses_prev_frame = 1 ; } </s>

Record that the current function accesses previous call frames .


<s> static void ix86_setup_incoming_varargs ( cumulative_args_t cum_v , const function_arg_info & arg , int * , int no_rtl ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; CUMULATIVE_ARGS next_cum ; tree fntype ; gcc_assert ( ! no_rtl ) ; if ( ! TARGET_64BIT ) return ; fntype = TREE_TYPE ( current_function_decl ) ; next_cum = * cum ; if ( stdarg_p ( fntype ) ) ix86_function_arg_advance ( pack_cumulative_args ( & next_cum ) , arg ) ; if ( cum -> call_abi == MS_ABI ) setup_incoming_varargs_ms_64 ( & next_cum ) ; else setup_incoming_varargs_64 ( & next_cum ) ; } </s>

Worker function for TARGET_SETUP_INCOMING_VARARGS .


<s> static int ix86_set_reg_reg_cost ( machine_mode mode ) { unsigned int units = UNITS_PER_WORD ; switch ( GET_MODE_CLASS ( mode ) ) { default : break ; case MODE_CC : units = GET_MODE_SIZE ( CCmode ) ; break ; case MODE_FLOAT : if ( ( TARGET_SSE && mode == TFmode ) || ( TARGET_80387 && mode == XFmode ) || ( ( TARGET_80387 || TARGET_SSE2 ) && mode == DFmode ) || ( ( TARGET_80387 || TARGET_SSE ) && mode == SFmode ) ) units = GET_MODE_SIZE ( mode ) ; break ; case MODE_COMPLEX_FLOAT : if ( ( TARGET_SSE && mode == TCmode ) || ( TARGET_80387 && mode == XCmode ) || ( ( TARGET_80387 || TARGET_SSE2 ) && mode == DCmode ) || ( ( TARGET_80387 || TARGET_SSE ) && mode == SCmode ) ) units = GET_MODE_SIZE ( mode ) ; break ; case MODE_VECTOR_INT : case MODE_VECTOR_FLOAT : if ( ( TARGET_AVX512F && VALID_AVX512F_REG_MODE ( mode ) ) || ( TARGET_AVX && VALID_AVX256_REG_MODE ( mode ) ) || ( TARGET_SSE2 && VALID_SSE2_REG_MODE ( mode ) ) || ( TARGET_SSE && VALID_SSE_REG_MODE ( mode ) ) || ( ( TARGET_MMX || TARGET_MMX_WITH_SSE ) && VALID_MMX_REG_MODE ( mode ) ) ) units = GET_MODE_SIZE ( mode ) ; } return COSTS_N_INSNS ( CEIL ( GET_MODE_SIZE ( mode ) , units ) ) ; } </s>

Return the cost of moving between two registers of mode MODE .


<s> static int ix86_shift_rotate_cost ( const struct processor_costs * cost , enum rtx_code code , enum machine_mode mode , bool constant_op1 , HOST_WIDE_INT op1_val , bool speed , bool and_in_op1 , bool shift_and_truncate , bool * skip_op0 , bool * skip_op1 ) { if ( skip_op0 ) * skip_op0 = * skip_op1 = false ; if ( GET_MODE_CLASS ( mode ) == MODE_VECTOR_INT ) { if ( mode == V16QImode || mode == V32QImode ) { int count = 11 ; if ( TARGET_XOP && mode == V16QImode ) { if ( constant_op1 ) { if ( skip_op1 ) * skip_op1 = true ; return ix86_vec_cost ( mode , cost -> sse_op + ( speed ? 2 : COSTS_N_BYTES ( GET_MODE_UNIT_SIZE ( mode ) ) ) ) ; } count = 3 ; } else if ( TARGET_SSSE3 ) count = 7 ; return ix86_vec_cost ( mode , cost -> sse_op * count ) ; } else if ( code == ASHIFTRT && ( mode == V2DImode || mode == V4DImode ) && ! TARGET_XOP && ! TARGET_AVX512VL ) { int count = 4 ; if ( constant_op1 && op1_val == 63 && TARGET_SSE4_2 ) count = 2 ; else if ( constant_op1 ) count = 3 ; return ix86_vec_cost ( mode , cost -> sse_op * count ) ; } else return ix86_vec_cost ( mode , cost -> sse_op ) ; } if ( GET_MODE_SIZE ( mode ) > UNITS_PER_WORD ) { if ( constant_op1 ) { if ( op1_val > 32 ) return cost -> shift_const + COSTS_N_INSNS ( 2 ) ; else return cost -> shift_const * 2 ; } else { if ( and_in_op1 ) return cost -> shift_var * 2 ; else return cost -> shift_var * 6 + COSTS_N_INSNS ( 2 ) ; } } else { if ( constant_op1 ) return cost -> shift_const ; else if ( shift_and_truncate ) { if ( skip_op0 ) * skip_op0 = * skip_op1 = true ; return cost -> shift_var ; } else return cost -> shift_var ; } } </s>

Return cost of shift in MODE . If CONSTANT_OP1 is true , the op1 value is known and set in OP1_VAL . AND_IN_OP1 specify in op1 is result of AND and SHIFT_AND_TRUNCATE if op1 is a result of subreg . SKIP_OP0/1 is set to true if cost of OP0/1 should be ignored .


<s> static int ix86_simd_clone_usable ( struct cgraph_node * node ) { switch ( node -> simdclone -> vecsize_mangle ) { case 'b' : if ( ! TARGET_SSE2 ) return - 1 ; if ( ! TARGET_AVX ) return 0 ; return TARGET_AVX512F ? 3 : TARGET_AVX2 ? 2 : 1 ; case 'c' : if ( ! TARGET_AVX ) return - 1 ; return TARGET_AVX512F ? 2 : TARGET_AVX2 ? 1 : 0 ; case 'd' : if ( ! TARGET_AVX2 ) return - 1 ; return TARGET_AVX512F ? 1 : 0 ; case 'e' : if ( ! TARGET_AVX512F ) return - 1 ; return 0 ; default : gcc_unreachable ( ) ; } } </s>

If SIMD clone NODE ca n't be used in a vectorized loop in current function , return -1 , otherwise return a badness of using it ( 0 if it is most desirable from vecsize_mangle point of view , 1 slightly less desirable , etc . ) .


<s> static reg_class_t ix86_spill_class ( reg_class_t rclass , machine_mode mode ) { if ( 0 && TARGET_GENERAL_REGS_SSE_SPILL && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES_TO_VEC && TARGET_INTER_UNIT_MOVES_FROM_VEC && ( mode == SImode || ( TARGET_64BIT && mode == DImode ) ) && INTEGER_CLASS_P ( rclass ) ) return ALL_SSE_REGS ; return NO_REGS ; } </s>

Return class of registers which could be used for pseudo of MODE and of class RCLASS for spilling instead of memory . Return NO_REGS if it is not possible or non-profitable .


<s> rtx ix86_split_stack_guard ( void ) { int offset ; addr_space_t as = DEFAULT_TLS_SEG_REG ; rtx r ; gcc_assert ( flag_split_stack ) ; offset = TARGET_THREAD_SPLIT_STACK_OFFSET ; gcc_unreachable ( ) ; r = GEN_INT ( offset ) ; r = gen_const_mem ( Pmode , r ) ; set_mem_addr_space ( r , as ) ; return r ; } </s>

Return location of the stack guard value in the TLS block .


"Due to potential STLF stall, split instruction:\n"

Split vector load from parm_decl to elemental loads to avoid STLF stalls .


<s> static tree ATTRIBUTE_UNUSED ix86_stack_protect_fail ( void ) { return TARGET_64BIT ? default_external_stack_protect_fail ( ) : default_hidden_stack_protect_fail ( ) ; } </s>

For 32-bit code we can save PIC register setup by using __stack_chk_fail_local hidden function instead of calling __stack_chk_fail directly . 64-bit code does n't need to setup any PIC register , so it is better to call __stack_chk_fail directly .


<s> static tree ix86_stack_protect_guard ( void ) { if ( TARGET_SSP_TLS_GUARD ) { tree type_node = lang_hooks . types . type_for_mode ( ptr_mode , 1 ) ; int qual = ENCODE_QUAL_ADDR_SPACE ( ix86_stack_protector_guard_reg ) ; tree type = build_qualified_type ( type_node , qual ) ; tree t ; if ( OPTION_SET_P ( ix86_stack_protector_guard_symbol_str ) ) { t = ix86_tls_stack_chk_guard_decl ; if ( t == NULL ) { rtx x ; t = build_decl ( UNKNOWN_LOCATION , VAR_DECL , get_identifier ( ix86_stack_protector_guard_symbol_str ) , type ) ; TREE_STATIC ( t ) = 1 ; TREE_PUBLIC ( t ) = 1 ; DECL_EXTERNAL ( t ) = 1 ; TREE_USED ( t ) = 1 ; TREE_THIS_VOLATILE ( t ) = 1 ; DECL_ARTIFICIAL ( t ) = 1 ; DECL_IGNORED_P ( t ) = 1 ; x = DECL_RTL ( t ) ; RTX_FLAG ( x , used ) = 1 ; ix86_tls_stack_chk_guard_decl = t ; } } else { tree asptrtype = build_pointer_type ( type ) ; t = build_int_cst ( asptrtype , ix86_stack_protector_guard_offset ) ; t = build2 ( MEM_REF , asptrtype , t , build_int_cst ( asptrtype , 0 ) ) ; TREE_THIS_VOLATILE ( t ) = 1 ; } return t ; } return default_stack_protect_guard ( ) ; } </s>

If using TLS guards , do n't waste time creating and expanding __stack_chk_guard decl and MEM as we are going to ignore it .


<s> bool ix86_standard_x87sse_constant_load_p ( const rtx_insn * insn , rtx dst ) { rtx src = find_constant_src ( insn ) ; gcc_assert ( REG_P ( dst ) ) ; if ( src == NULL || ( SSE_REGNO_P ( REGNO ( dst ) ) && standard_sse_constant_p ( src , GET_MODE ( dst ) ) != 1 ) || ( STACK_REGNO_P ( REGNO ( dst ) ) && standard_80387_constant_p ( src ) < 1 ) ) return false ; return true ; } </s>

Returns true if INSN can be transformed from a memory load to a supported FP constant load .


<s> static rtx ix86_static_chain ( const_tree fndecl_or_type , bool incoming_p ) { unsigned regno ; if ( TARGET_64BIT ) { regno = R10_REG ; } else { const_tree fntype , fndecl ; unsigned int ccvt ; regno = CX_REG ; if ( TREE_CODE ( fndecl_or_type ) == FUNCTION_DECL ) { fntype = TREE_TYPE ( fndecl_or_type ) ; fndecl = fndecl_or_type ; } else { fntype = fndecl_or_type ; fndecl = NULL ; } ccvt = ix86_get_callcvt ( fntype ) ; if ( ( ccvt & IX86_CALLCVT_FASTCALL ) != 0 ) { regno = AX_REG ; } else if ( ( ccvt & IX86_CALLCVT_THISCALL ) != 0 ) { regno = AX_REG ; } else if ( ix86_function_regparm ( fntype , fndecl ) == 3 ) { if ( incoming_p ) { if ( fndecl == current_function_decl && ! ix86_static_chain_on_stack ) { gcc_assert ( ! reload_completed ) ; ix86_static_chain_on_stack = true ; } return gen_frame_mem ( SImode , plus_constant ( Pmode , arg_pointer_rtx , - 8 ) ) ; } regno = SI_REG ; } } return gen_rtx_REG ( Pmode , regno ) ; } </s>

Find a location for the static chain incoming to a nested function . This is a register , unless all free registers are used by arguments .


<s> static HOST_WIDE_INT ix86_static_rtx_alignment ( machine_mode mode ) { if ( mode == DFmode ) return 64 ; if ( ALIGN_MODE_128 ( mode ) ) return MAX ( 128 , GET_MODE_ALIGNMENT ( mode ) ) ; return GET_MODE_ALIGNMENT ( mode ) ; } </s>


<s> bool ix86_target_stack_probe ( void ) { if ( flag_stack_check == STATIC_BUILTIN_STACK_CHECK ) return false ; return TARGET_STACK_PROBE ; } </s>

Decide whether we must probe the stack before any space allocation on this target . It 's essentially TARGET_STACK_PROBE except when -fstack-check causes the stack to be already probed differently .


<s>
static
void
ix86_test_dumping_hard_regs
(
)
{
ASSERT_RTL_DUMP_EQ
(
"(reg:SI ax)"
,
gen_raw_REG
(
SImode
,
0
)
)
;
ASSERT_RTL_DUMP_EQ
(
"(reg:SI dx)"
,
gen_raw_REG
(
SImode
,
1
)
)
;
}
</s>

Verify that hard regs are dumped as expected ( in compact mode ) .


"(cinsn 1 (set (mem/v:BLK (0|scratch:DI) [0  A8])\n"

"                (mem/v:BLK (reuse_rtx 0) [0  A8])\n"

"            ] UNSPEC_MEMORY_BLOCKAGE)))\n"

Test dumping an insn with repeated references to the same SCRATCH , to verify the rtx_reuse code .

"                (mem/v:BLK (reuse_rtx 0) [0  A8])\n"

"            ] UNSPEC_MEMORY_BLOCKAGE)))\n"


<s> static void ix86_test_loading_call_insn ( ) { if ( ! TARGET_SSE ) return ; rtl_dump_test t ( SELFTEST_LOCATION , locate_file ( "x86_64/call-insn.rtl" ) ) ; rtx_insn * insn = get_insns ( ) ; ASSERT_EQ ( CALL_INSN , GET_CODE ( insn ) ) ; ASSERT_TRUE ( RTX_FLAG ( insn , jump ) ) ; rtx pat = PATTERN ( insn ) ; ASSERT_EQ ( CALL , GET_CODE ( SET_SRC ( pat ) ) ) ; { ASSERT_EQ ( EXPR_LIST , GET_CODE ( REG_NOTES ( insn ) ) ) ; rtx_expr_list * note0 = as_a < rtx_expr_list * > ( REG_NOTES ( insn ) ) ; ASSERT_EQ ( REG_CALL_DECL , REG_NOTE_KIND ( note0 ) ) ; rtx_expr_list * note1 = note0 -> next ( ) ; ASSERT_EQ ( REG_EH_REGION , REG_NOTE_KIND ( note1 ) ) ; ASSERT_EQ ( NULL , note1 -> next ( ) ) ; } { rtx_expr_list * usage = as_a < rtx_expr_list * > ( CALL_INSN_FUNCTION_USAGE ( insn ) ) ; ASSERT_EQ ( EXPR_LIST , GET_CODE ( usage ) ) ; ASSERT_EQ ( DFmode , GET_MODE ( usage ) ) ; ASSERT_EQ ( USE , GET_CODE ( usage -> element ( ) ) ) ; ASSERT_EQ ( NULL , usage -> next ( ) ) ; } } </s>

Verify that the RTL loader copes with a call_insn dump . This test is target-specific since the dump contains a target-specific hard reg name .


<s> static void ix86_test_loading_dump_fragment_1 ( ) { rtl_dump_test t ( SELFTEST_LOCATION , locate_file ( "x86_64/copy-hard-reg-into-frame.rtl" ) ) ; rtx_insn * insn = get_insn_by_uid ( 1 ) ; tree mem_expr ; { rtx pat = PATTERN ( insn ) ; ASSERT_EQ ( SET , GET_CODE ( pat ) ) ; { rtx dest = SET_DEST ( pat ) ; ASSERT_EQ ( MEM , GET_CODE ( dest ) ) ; ASSERT_TRUE ( RTX_FLAG ( dest , call ) ) ; ASSERT_EQ ( SImode , GET_MODE ( dest ) ) ; { rtx addr = XEXP ( dest , 0 ) ; ASSERT_EQ ( PLUS , GET_CODE ( addr ) ) ; ASSERT_EQ ( DImode , GET_MODE ( addr ) ) ; { rtx lhs = XEXP ( addr , 0 ) ; ASSERT_RTX_PTR_EQ ( frame_pointer_rtx , lhs ) ; } { rtx rhs = XEXP ( addr , 1 ) ; ASSERT_EQ ( CONST_INT , GET_CODE ( rhs ) ) ; ASSERT_EQ ( - 4 , INTVAL ( rhs ) ) ; } } ASSERT_EQ ( 1 , MEM_ALIAS_SET ( dest ) ) ; mem_expr = MEM_EXPR ( dest ) ; ASSERT_NE ( mem_expr , NULL ) ; ASSERT_EQ ( VAR_DECL , TREE_CODE ( mem_expr ) ) ; ASSERT_EQ ( integer_type_node , TREE_TYPE ( mem_expr ) ) ; ASSERT_EQ ( IDENTIFIER_NODE , TREE_CODE ( DECL_NAME ( mem_expr ) ) ) ; ASSERT_STREQ ( "i" , IDENTIFIER_POINTER ( DECL_NAME ( mem_expr ) ) ) ; ASSERT_TRUE ( MEM_OFFSET_KNOWN_P ( dest ) ) ; ASSERT_EQ ( 0 , MEM_OFFSET ( dest ) ) ; ASSERT_EQ ( 4 , MEM_SIZE ( dest ) ) ; ASSERT_EQ ( 32 , MEM_ALIGN ( dest ) ) ; } { rtx src = SET_SRC ( pat ) ; ASSERT_EQ ( REG , GET_CODE ( src ) ) ; ASSERT_EQ ( SImode , GET_MODE ( src ) ) ; ASSERT_EQ ( 5 , REGNO ( src ) ) ; tree reg_expr = REG_EXPR ( src ) ; ASSERT_EQ ( reg_expr , mem_expr ) ; } } } </s>

Verify loading an RTL dump ; specifically a dump of copying a param on x86_64 from a hard reg into the frame . This test is target-specific since the dump contains target-specific hard reg names .


<s> static void ix86_test_loading_full_dump ( ) { rtl_dump_test t ( SELFTEST_LOCATION , locate_file ( "x86_64/times-two.rtl" ) ) ; ASSERT_STREQ ( "times_two" , IDENTIFIER_POINTER ( DECL_NAME ( cfun -> decl ) ) ) ; rtx_insn * insn_1 = get_insn_by_uid ( 1 ) ; ASSERT_EQ ( NOTE , GET_CODE ( insn_1 ) ) ; rtx_insn * insn_7 = get_insn_by_uid ( 7 ) ; ASSERT_EQ ( INSN , GET_CODE ( insn_7 ) ) ; ASSERT_EQ ( PARALLEL , GET_CODE ( PATTERN ( insn_7 ) ) ) ; rtx_insn * insn_15 = get_insn_by_uid ( 15 ) ; ASSERT_EQ ( INSN , GET_CODE ( insn_15 ) ) ; ASSERT_EQ ( USE , GET_CODE ( PATTERN ( insn_15 ) ) ) ; ASSERT_EQ ( REG , GET_CODE ( crtl -> return_rtx ) ) ; ASSERT_EQ ( 0 , REGNO ( crtl -> return_rtx ) ) ; ASSERT_EQ ( SImode , GET_MODE ( crtl -> return_rtx ) ) ; } </s>

Verify that the RTL loader copes a dump from print_rtx_function . This test is target-specific since the dump contains target-specific hard reg names .


<s> static void ix86_test_loading_unspec ( ) { rtl_dump_test t ( SELFTEST_LOCATION , locate_file ( "x86_64/unspec.rtl" ) ) ; ASSERT_STREQ ( "test_unspec" , IDENTIFIER_POINTER ( DECL_NAME ( cfun -> decl ) ) ) ; ASSERT_TRUE ( cfun ) ; rtx_insn * insn = get_insns ( ) ; ASSERT_EQ ( INSN , GET_CODE ( insn ) ) ; rtx set = single_set ( insn ) ; ASSERT_NE ( NULL , set ) ; rtx dst = SET_DEST ( set ) ; ASSERT_EQ ( MEM , GET_CODE ( dst ) ) ; rtx src = SET_SRC ( set ) ; ASSERT_EQ ( UNSPEC , GET_CODE ( src ) ) ; ASSERT_EQ ( BLKmode , GET_MODE ( src ) ) ; ASSERT_EQ ( UNSPEC_MEMORY_BLOCKAGE , XINT ( src , 1 ) ) ; rtx v0 = XVECEXP ( src , 0 , 0 ) ; rtx scratch_a = XEXP ( dst , 0 ) ; ASSERT_EQ ( SCRATCH , GET_CODE ( scratch_a ) ) ; rtx scratch_b = XEXP ( v0 , 0 ) ; ASSERT_EQ ( SCRATCH , GET_CODE ( scratch_b ) ) ; ASSERT_EQ ( scratch_a , scratch_b ) ; ASSERT_TRUE ( rtx_equal_p ( dst , v0 ) ) ; ASSERT_NE ( - 1 , recog_memoized ( insn ) ) ; insn = NEXT_INSN ( insn ) ; ASSERT_EQ ( INSN , GET_CODE ( insn ) ) ; set = single_set ( insn ) ; ASSERT_NE ( NULL , set ) ; src = SET_SRC ( set ) ; ASSERT_EQ ( UNSPEC_VOLATILE , GET_CODE ( src ) ) ; ASSERT_EQ ( UNSPECV_RDTSCP , XINT ( src , 1 ) ) ; } </s>

Verify that the RTL loader copes with UNSPEC and UNSPEC_VOLATILE insns . In particular , verify that it correctly loads the 2nd operand . This test is target-specific since these are machine-specific operands ( and enums ) .


<s> static bool ix86_tieable_integer_mode_p ( machine_mode mode ) { switch ( mode ) { case E_HImode : case E_SImode : return true ; case E_QImode : return TARGET_64BIT || ! TARGET_PARTIAL_REG_STALL ; case E_DImode : return TARGET_64BIT ; default : return false ; } } </s>

A subroutine of ix86_modes_tieable_p . Return true if MODE is a tieable integer mode .


<s> bool ix86_tls_address_pattern_p ( rtx op ) { subrtx_var_iterator :: array_type array ; FOR_EACH_SUBRTX_VAR ( iter , array , op , ALL ) { rtx op = * iter ; if ( MEM_P ( op ) ) { rtx * x = & XEXP ( op , 0 ) ; while ( GET_CODE ( * x ) == PLUS ) { int i ; for ( i = 0 ; i < 2 ; i ++ ) { rtx u = XEXP ( * x , i ) ; if ( GET_CODE ( u ) == ZERO_EXTEND ) u = XEXP ( u , 0 ) ; if ( GET_CODE ( u ) == UNSPEC && XINT ( u , 1 ) == UNSPEC_TP ) return true ; } x = & XEXP ( * x , 0 ) ; } iter . skip_subrtxes ( ) ; } } return false ; } </s>

Return true if OP refers to a TLS address .


<s> bool ix86_unary_operator_ok ( enum rtx_code , machine_mode , rtx operands [ 2 ] ) { if ( ( MEM_P ( operands [ 0 ] ) || MEM_P ( operands [ 1 ] ) ) && ! rtx_equal_p ( operands [ 0 ] , operands [ 1 ] ) ) return false ; return true ; } </s>

Return TRUE or FALSE depending on whether the unary operator meets the appropriate constraints .


Update incoming stack boundary and estimated stack alignment .


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

Return true if we should emit lea instruction instead of mov instruction .


<s> bool ix86_use_pseudo_pic_reg ( void ) { if ( ( TARGET_64BIT && ( ix86_cmodel == CM_SMALL_PIC || TARGET_PECOFF ) ) || ! flag_pic ) return false ; return true ; } </s>

Return 1 if pseudo register should be created and used to hold GOT address for PIC code .


<s> bool ix86_using_red_zone ( void ) { return ( TARGET_RED_ZONE && ! TARGET_64BIT_MS_ABI && ( ! cfun -> machine -> has_local_indirect_jump || cfun -> machine -> indirect_branch_type == indirect_branch_keep ) ) ; } </s>


<s> static rtx ix86_validate_address_register ( rtx op ) { machine_mode mode = GET_MODE ( op ) ; if ( mode != SImode && mode != DImode ) return NULL_RTX ; if ( REG_P ( op ) ) return op ; else if ( SUBREG_P ( op ) ) { rtx reg = SUBREG_REG ( op ) ; if ( ! REG_P ( reg ) ) return NULL_RTX ; mode = GET_MODE ( reg ) ; if ( GET_MODE_SIZE ( mode ) > UNITS_PER_WORD ) return NULL_RTX ; if ( register_no_elim_operand ( reg , mode ) ) return reg ; } return NULL_RTX ; } </s>

Determine if op is suitable RTX for an address register . Return naked register if a register or a register subreg is found , otherwise return NULL_RTX .


<s> tree ix86_veclibabi_acml ( combined_fn fn , tree type_out , tree type_in ) { char name [ 20 ] = "__vr.._" ; tree fntype , new_fndecl , args ; unsigned arity ; const char * bname ; machine_mode el_mode , in_mode ; int n , in_n ; if ( ! TARGET_64BIT || ! flag_unsafe_math_optimizations ) return NULL_TREE ; el_mode = TYPE_MODE ( TREE_TYPE ( type_out ) ) ; n = TYPE_VECTOR_SUBPARTS ( type_out ) ; in_mode = TYPE_MODE ( TREE_TYPE ( type_in ) ) ; in_n = TYPE_VECTOR_SUBPARTS ( type_in ) ; if ( el_mode != in_mode || n != in_n ) return NULL_TREE ; switch ( fn ) { CASE_CFN_SIN : CASE_CFN_COS : CASE_CFN_EXP : CASE_CFN_LOG : CASE_CFN_LOG2 : CASE_CFN_LOG10 : if ( el_mode == DFmode && n == 2 ) { name [ 4 ] = 'd' ; name [ 5 ] = '2' ; } else if ( el_mode == SFmode && n == 4 ) { name [ 4 ] = 's' ; name [ 5 ] = '4' ; } else return NULL_TREE ; break ; default : return NULL_TREE ; } tree fndecl = mathfn_built_in ( el_mode == DFmode ? double_type_node : float_type_node , fn ) ; bname = IDENTIFIER_POINTER ( DECL_NAME ( fndecl ) ) ; sprintf ( name + 7 , "%s" , bname + 10 ) ; arity = 0 ; for ( args = DECL_ARGUMENTS ( fndecl ) ; args ; args = TREE_CHAIN ( args ) ) arity ++ ; if ( arity == 1 ) fntype = build_function_type_list ( type_out , type_in , NULL ) ; else fntype = build_function_type_list ( type_out , type_in , type_in , NULL ) ; new_fndecl = build_decl ( BUILTINS_LOCATION , FUNCTION_DECL , get_identifier ( name ) , fntype ) ; TREE_PUBLIC ( new_fndecl ) = 1 ; DECL_EXTERNAL ( new_fndecl ) = 1 ; DECL_IS_NOVOPS ( new_fndecl ) = 1 ; TREE_READONLY ( new_fndecl ) = 1 ; return new_fndecl ; } </s>

Handler for an ACML-style interface to a library with vectorized intrinsics .


<s> tree ix86_veclibabi_svml ( combined_fn fn , tree type_out , tree type_in ) { char name [ 20 ] ; tree fntype , new_fndecl , args ; unsigned arity ; const char * bname ; machine_mode el_mode , in_mode ; int n , in_n ; if ( ! flag_unsafe_math_optimizations ) return NULL_TREE ; el_mode = TYPE_MODE ( TREE_TYPE ( type_out ) ) ; n = TYPE_VECTOR_SUBPARTS ( type_out ) ; in_mode = TYPE_MODE ( TREE_TYPE ( type_in ) ) ; in_n = TYPE_VECTOR_SUBPARTS ( type_in ) ; if ( el_mode != in_mode || n != in_n ) return NULL_TREE ; switch ( fn ) { CASE_CFN_EXP : CASE_CFN_LOG : CASE_CFN_LOG10 : CASE_CFN_POW : CASE_CFN_TANH : CASE_CFN_TAN : CASE_CFN_ATAN : CASE_CFN_ATAN2 : CASE_CFN_ATANH : CASE_CFN_CBRT : CASE_CFN_SINH : CASE_CFN_SIN : CASE_CFN_ASINH : CASE_CFN_ASIN : CASE_CFN_COSH : CASE_CFN_COS : CASE_CFN_ACOSH : CASE_CFN_ACOS : if ( ( el_mode != DFmode || n != 2 ) && ( el_mode != SFmode || n != 4 ) ) return NULL_TREE ; break ; default : return NULL_TREE ; } tree fndecl = mathfn_built_in ( el_mode == DFmode ? double_type_node : float_type_node , fn ) ; bname = IDENTIFIER_POINTER ( DECL_NAME ( fndecl ) ) ; if ( DECL_FUNCTION_CODE ( fndecl ) == BUILT_IN_LOGF ) strcpy ( name , "vmlsLn4" ) ; else if ( DECL_FUNCTION_CODE ( fndecl ) == BUILT_IN_LOG ) strcpy ( name , "vmldLn2" ) ; else if ( n == 4 ) { sprintf ( name , "vmls%s" , bname + 10 ) ; name [ strlen ( name ) - 1 ] = '4' ; } else sprintf ( name , "vmld%s2" , bname + 10 ) ; name [ 4 ] &= ~ 0x20 ; arity = 0 ; for ( args = DECL_ARGUMENTS ( fndecl ) ; args ; args = TREE_CHAIN ( args ) ) arity ++ ; if ( arity == 1 ) fntype = build_function_type_list ( type_out , type_in , NULL ) ; else fntype = build_function_type_list ( type_out , type_in , type_in , NULL ) ; new_fndecl = build_decl ( BUILTINS_LOCATION , FUNCTION_DECL , get_identifier ( name ) , fntype ) ; TREE_PUBLIC ( new_fndecl ) = 1 ; DECL_EXTERNAL ( new_fndecl ) = 1 ; DECL_IS_NOVOPS ( new_fndecl ) = 1 ; TREE_READONLY ( new_fndecl ) = 1 ; return new_fndecl ; } </s>

Handler for an SVML-style interface to a library with vectorized intrinsics .


<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 get_ix86_builtin ( 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 vector_costs * ix86_vectorize_create_costs ( vec_info * vinfo , bool costing_for_scalar ) { return new ix86_vector_costs ( vinfo , costing_for_scalar ) ; } </s>


<s> static bool ix86_vector_mode_supported_p ( machine_mode mode ) { if ( ! TARGET_64BIT && GET_MODE_INNER ( mode ) == TImode ) return false ; if ( TARGET_SSE && VALID_SSE_REG_MODE ( mode ) ) return true ; if ( TARGET_SSE2 && VALID_SSE2_REG_MODE ( mode ) ) return true ; if ( TARGET_AVX && VALID_AVX256_REG_MODE ( mode ) ) return true ; if ( TARGET_AVX512F && VALID_AVX512F_REG_MODE ( mode ) ) return true ; if ( ( TARGET_MMX || TARGET_MMX_WITH_SSE ) && VALID_MMX_REG_MODE ( mode ) ) return true ; if ( ( TARGET_3DNOW || TARGET_MMX_WITH_SSE ) && VALID_MMX_REG_MODE_3DNOW ( mode ) ) return true ; if ( mode == V2QImode ) return true ; return false ; } </s>

Implements target hook vector_mode_supported_p .


<s> static tree ix86_vector_shift_count ( tree arg1 ) { if ( tree_fits_uhwi_p ( arg1 ) ) return arg1 ; else if ( TREE_CODE ( arg1 ) == VECTOR_CST && CHAR_BIT == 8 ) { unsigned char buf [ 16 ] ; int len = native_encode_expr ( arg1 , buf , 16 ) ; if ( len == 0 ) return NULL_TREE ; tree t = native_interpret_expr ( uint64_type_node , buf , len ) ; if ( t && tree_fits_uhwi_p ( t ) ) return t ; } return NULL_TREE ; } </s>

Return the shift count of a vector by scalar shift builtin second argument ARG1 .


<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_AVX256_SPLIT_REGS ) 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> bool ix86_vec_interleave_v2df_operator_ok ( rtx operands [ 3 ] , bool high ) { if ( MEM_P ( operands [ 0 ] ) ) return rtx_equal_p ( operands [ 0 ] , operands [ 1 + high ] ) ; if ( MEM_P ( operands [ 1 ] ) && MEM_P ( operands [ 2 ] ) ) return TARGET_SSE3 && rtx_equal_p ( operands [ 1 ] , operands [ 2 ] ) ; return true ; } </s>

Return TRUE if the operands to a vec_interleave_ { high , low } v2df are ok , keeping in mind the possible movddup alternative .


"empty class %qT parameter passing ABI "

"changes in %<-fabi-version=12%> (GCC 8)"


<s> static int ix86_widen_mult_cost ( const struct processor_costs * cost , enum machine_mode mode , bool uns_p ) { gcc_assert ( GET_MODE_CLASS ( mode ) == MODE_VECTOR_INT ) ; int extra_cost = 0 ; int basic_cost = 0 ; switch ( mode ) { case V8HImode : case V16HImode : if ( ! uns_p || mode == V16HImode ) extra_cost = cost -> sse_op * 2 ; basic_cost = cost -> mulss * 2 + cost -> sse_op * 4 ; break ; case V4SImode : case V8SImode : basic_cost = cost -> mulss * 2 + cost -> sse_op * 2 ; break ; case V2DImode : if ( ! TARGET_SSE4_1 && ! uns_p ) extra_cost = ( cost -> mulss + cost -> addss + cost -> sse_op ) * 4 + cost -> sse_op * 2 ; case V4DImode : basic_cost = cost -> mulss * 2 + cost -> sse_op * 4 ; break ; default : gcc_unreachable ( ) ; } return ix86_vec_cost ( mode , basic_cost + extra_cost ) ; } </s>

Return cost of vec_widen_ < s > mult_hi/lo_ < mode > , vec_widen_ < s > mul_hi/lo_ < mode > is only available for VI124_AVX2 .


<s> rtx ix86_zero_extend_to_Pmode ( rtx exp ) { return force_reg ( Pmode , convert_to_mode ( Pmode , exp , 1 ) ) ; } </s>

Zero extend possibly SImode EXP to Pmode register .


<s> bool legitimate_pic_operand_p ( rtx x ) { rtx inner ; switch ( GET_CODE ( x ) ) { case CONST : inner = XEXP ( x , 0 ) ; if ( GET_CODE ( inner ) == PLUS && CONST_INT_P ( XEXP ( inner , 1 ) ) ) inner = XEXP ( inner , 0 ) ; if ( GET_CODE ( inner ) == UNSPEC ) switch ( XINT ( inner , 1 ) ) { case UNSPEC_GOT : case UNSPEC_GOTOFF : case UNSPEC_PLTOFF : return TARGET_64BIT ; case UNSPEC_TPOFF : x = XVECEXP ( inner , 0 , 0 ) ; return ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL ( x ) == TLS_MODEL_LOCAL_EXEC ) ; case UNSPEC_MACHOPIC_OFFSET : return legitimate_pic_address_disp_p ( x ) ; default : return false ; } case SYMBOL_REF : case LABEL_REF : return legitimate_pic_address_disp_p ( x ) ; default : return true ; } } </s>

Return true if OP is a legitimate general operand when generating PIC code . It is given that flag_pic is on and that OP satisfies CONSTANT_P or is a CONST_DOUBLE .


<s> static rtx legitimize_dllimport_symbol ( rtx symbol , bool want_reg ) { tree imp_decl ; rtx x ; gcc_assert ( SYMBOL_REF_DECL ( symbol ) ) ; imp_decl = get_dllimport_decl ( SYMBOL_REF_DECL ( symbol ) , true ) ; x = DECL_RTL ( imp_decl ) ; if ( want_reg ) x = force_reg ( Pmode , x ) ; return x ; } </s>

Expand SYMBOL into its corresponding dllimport symbol . WANT_REG is true if we require the result be a register .


<s> static rtx legitimize_pe_coff_extern_decl ( rtx symbol , bool want_reg ) { tree imp_decl ; rtx x ; gcc_assert ( SYMBOL_REF_DECL ( symbol ) ) ; imp_decl = get_dllimport_decl ( SYMBOL_REF_DECL ( symbol ) , false ) ; x = DECL_RTL ( imp_decl ) ; if ( want_reg ) x = force_reg ( Pmode , x ) ; return x ; } </s>

Expand SYMBOL into its corresponding far-addresse symbol . WANT_REG is true if we require the result be a register .


<s> rtx legitimize_pe_coff_symbol ( rtx addr , bool inreg ) { if ( ! TARGET_PECOFF ) return NULL_RTX ; if ( TARGET_DLLIMPORT_DECL_ATTRIBUTES ) { if ( GET_CODE ( addr ) == SYMBOL_REF && SYMBOL_REF_DLLIMPORT_P ( addr ) ) return legitimize_dllimport_symbol ( addr , inreg ) ; if ( GET_CODE ( addr ) == CONST && GET_CODE ( XEXP ( addr , 0 ) ) == PLUS && GET_CODE ( XEXP ( XEXP ( addr , 0 ) , 0 ) ) == SYMBOL_REF && SYMBOL_REF_DLLIMPORT_P ( XEXP ( XEXP ( addr , 0 ) , 0 ) ) ) { rtx t = legitimize_dllimport_symbol ( XEXP ( XEXP ( addr , 0 ) , 0 ) , inreg ) ; return gen_rtx_PLUS ( Pmode , t , XEXP ( XEXP ( addr , 0 ) , 1 ) ) ; } } if ( ix86_cmodel != CM_LARGE_PIC && ix86_cmodel != CM_MEDIUM_PIC ) return NULL_RTX ; if ( GET_CODE ( addr ) == SYMBOL_REF && ! is_imported_p ( addr ) && SYMBOL_REF_EXTERNAL_P ( addr ) && SYMBOL_REF_DECL ( addr ) ) return legitimize_pe_coff_extern_decl ( addr , inreg ) ; if ( GET_CODE ( addr ) == CONST && GET_CODE ( XEXP ( addr , 0 ) ) == PLUS && GET_CODE ( XEXP ( XEXP ( addr , 0 ) , 0 ) ) == SYMBOL_REF && ! is_imported_p ( XEXP ( XEXP ( addr , 0 ) , 0 ) ) && SYMBOL_REF_EXTERNAL_P ( XEXP ( XEXP ( addr , 0 ) , 0 ) ) && SYMBOL_REF_DECL ( XEXP ( XEXP ( addr , 0 ) , 0 ) ) ) { rtx t = legitimize_pe_coff_extern_decl ( XEXP ( XEXP ( addr , 0 ) , 0 ) , inreg ) ; return gen_rtx_PLUS ( Pmode , t , XEXP ( XEXP ( addr , 0 ) , 1 ) ) ; } return NULL_RTX ; } </s>

Expand SYMBOL into its corresponding dllimport or refptr symbol . WANT_REG is true if we require the result be a register .


Generate external symbol indirection stubs ( PIC and non-PIC ) .


<s> int memory_address_length ( rtx addr , bool lea ) { struct ix86_address parts ; rtx base , index , disp ; int len ; int ok ; if ( GET_CODE ( addr ) == PRE_DEC || GET_CODE ( addr ) == POST_INC || GET_CODE ( addr ) == PRE_MODIFY || GET_CODE ( addr ) == POST_MODIFY ) return 0 ; ok = ix86_decompose_address ( addr , & parts ) ; gcc_assert ( ok ) ; len = ( parts . seg == ADDR_SPACE_GENERIC ) ? 0 : 1 ; if ( TARGET_64BIT && ! lea && ( SImode_address_operand ( addr , VOIDmode ) || ( parts . base && GET_MODE ( parts . base ) == SImode ) || ( parts . index && GET_MODE ( parts . index ) == SImode ) ) ) len ++ ; base = parts . base ; index = parts . index ; disp = parts . disp ; if ( base && SUBREG_P ( base ) ) base = SUBREG_REG ( base ) ; if ( index && SUBREG_P ( index ) ) index = SUBREG_REG ( index ) ; gcc_assert ( base == NULL_RTX || REG_P ( base ) ) ; gcc_assert ( index == NULL_RTX || REG_P ( index ) ) ; if ( base && ! index && ! disp ) { if ( base == arg_pointer_rtx || base == frame_pointer_rtx || REGNO ( base ) == SP_REG || REGNO ( base ) == BP_REG || REGNO ( base ) == R12_REG || REGNO ( base ) == R13_REG ) len ++ ; } else if ( disp && ! base && ! index ) { len += 4 ; if ( ! ix86_rip_relative_addr_p ( & parts ) ) len ++ ; } else { if ( disp ) { if ( base && satisfies_constraint_K ( disp ) ) len += 1 ; else len += 4 ; } else if ( base && ( REGNO ( base ) == BP_REG || REGNO ( base ) == R13_REG ) ) len ++ ; if ( index || base == arg_pointer_rtx || base == frame_pointer_rtx || ( base && ( REGNO ( base ) == SP_REG || REGNO ( base ) == R12_REG ) ) ) len ++ ; } return len ; } </s>

Calculate the length of the memory address in the instruction encoding . Does not include the one-byte modrm , opcode , or prefix .


Return the union class of CLASS1 and CLASS2 . See the x86-64 PS ABI for details .


<s> static const char * output_387_ffreep ( rtx * operands ATTRIBUTE_UNUSED , int opno ) { if ( TARGET_USE_FFREEP ) return opno ? "ffreep\t%y1" : "ffreep\t%y0" ; { static char retval [ 32 ] ; int regno = REGNO ( operands [ opno ] ) ; gcc_assert ( STACK_REGNO_P ( regno ) ) ; regno -= FIRST_STACK_REG ; snprintf ( retval , sizeof ( retval ) , ASM_SHORT "0xc%ddf" , regno ) ; return retval ; } return opno ? "fstp\t%y1" : "fstp\t%y0" ; } </s>

Output code for x87 ffreep insn . The OPNO argument , which may only have the values zero or one , indicates the ffreep insn 's operand from the OPERANDS array .


<s> const char * output_387_reg_move ( rtx_insn * insn , rtx * operands ) { if ( REG_P ( operands [ 0 ] ) ) { if ( REG_P ( operands [ 1 ] ) && find_regno_note ( insn , REG_DEAD , REGNO ( operands [ 1 ] ) ) ) { if ( REGNO ( operands [ 0 ] ) == FIRST_STACK_REG ) return output_387_ffreep ( operands , 0 ) ; return "fstp\t%y0" ; } if ( STACK_TOP_P ( operands [ 0 ] ) ) return "fld%Z1\t%y1" ; return "fst\t%y0" ; } else if ( MEM_P ( operands [ 0 ] ) ) { gcc_assert ( REG_P ( operands [ 1 ] ) ) ; if ( find_regno_note ( insn , REG_DEAD , REGNO ( operands [ 1 ] ) ) ) return "fstp%Z0\t%y0" ; else { if ( GET_MODE ( operands [ 0 ] ) == XFmode ) return "fstp%Z0\t%y0\n\tfld%Z0\t%y0" ; else return "fst%Z0\t%y0" ; } } else gcc_unreachable ( ) ; } </s>

Output code to perform an x87 FP register move , from OPERANDS [ 1 ] to OPERANDS [ 0 ] .


<s>
const
char
*
output_adjust_stack_and_probe
(
rtx
reg
)
{
static
int
labelno
=
0
;
char
loop_lab
[
32
]
;
rtx
xops
[
2
]
;
ASM_GENERATE_INTERNAL_LABEL
(
loop_lab
,
"LPSRL"
,
labelno
++
)
;
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
loop_lab
)
;
xops
[
0
]
=
stack_pointer_rtx
;
xops
[
1
]
=
GEN_INT
(
get_probe_interval
(
)
)
;
output_asm_insn
(
"sub%z0\t{%1, %0|%0, %1}"
,
xops
)
;
xops
[
1
]
=
const0_rtx
;
output_asm_insn
(
"or%z0\t{%1, (%0)|DWORD PTR [%0], %1}"
,
xops
)
;
xops
[
0
]
=
stack_pointer_rtx
;
xops
[
1
]
=
reg
;
output_asm_insn
(
"cmp%z0\t{%1, %0|%0, %1}"
,
xops
)
;
fputs
(
"\tjne\t"
,
asm_out_file
)
;
assemble_name_raw
(
asm_out_file
,
loop_lab
)
;
fputc
(
'\n'
,
asm_out_file
)
;
return
""
;
}
</s>

Adjust the stack pointer up to REG while probing it .


<s> const char * output_fix_trunc ( rtx_insn * insn , rtx * operands , bool fisttp ) { bool stack_top_dies = find_regno_note ( insn , REG_DEAD , FIRST_STACK_REG ) ; bool dimode_p = GET_MODE ( operands [ 0 ] ) == DImode ; int round_mode = get_attr_i387_cw ( insn ) ; static char buf [ 40 ] ; const char * p ; if ( ( dimode_p || fisttp ) && ! stack_top_dies ) output_asm_insn ( "fld\t%y1" , operands ) ; gcc_assert ( STACK_TOP_P ( operands [ 1 ] ) ) ; gcc_assert ( MEM_P ( operands [ 0 ] ) ) ; gcc_assert ( GET_MODE ( operands [ 1 ] ) != TFmode ) ; if ( fisttp ) return "fisttp%Z0\t%0" ; strcpy ( buf , "fist" ) ; if ( round_mode != I387_CW_ANY ) output_asm_insn ( "fldcw\t%3" , operands ) ; p = "p%Z0\t%0" ; strcat ( buf , p + ! ( stack_top_dies || dimode_p ) ) ; output_asm_insn ( buf , operands ) ; if ( round_mode != I387_CW_ANY ) output_asm_insn ( "fldcw\t%2" , operands ) ; return "" ; } </s>

Output code for INSN to convert a float to a signed int . OPERANDS are the insn operands . The output may be [ HSD ] Imode and the input operand may be [ SDX ] Fmode .


<s>
const
char
*
output_fp_compare
(
rtx_insn
*
insn
,
rtx
*
operands
,
bool
eflags_p
,
bool
unordered_p
)
{
rtx
*
xops
=
eflags_p
&
operands
[
0
]
:
&
operands
[
1
]
;
bool
stack_top_dies
;
static
char
buf
[
40
]
;
const
char
*
p
;
gcc_assert
(
STACK_TOP_P
(
xops
[
0
]
)
)
;
stack_top_dies
=
find_regno_note
(
insn
,
REG_DEAD
,
FIRST_STACK_REG
)
;
if
(
eflags_p
)
{
p
=
unordered_p
"fucomi"
:
"fcomi"
;
strcpy
(
buf
,
p
)
;
p
=
"p\t{%y1, %0|%0, %y1}"
;
strcat
(
buf
,
p
+
!
stack_top_dies
)
;
return
buf
;
}
if
(
STACK_REG_P
(
xops
[
1
]
)
&&
stack_top_dies
&&
find_regno_note
(
insn
,
REG_DEAD
,
FIRST_STACK_REG
+
1
)
)
{
gcc_assert
(
REGNO
(
xops
[
1
]
)
==
FIRST_STACK_REG
+
1
)
;
p
=
unordered_p
"fucompp"
:
"fcompp"
;
strcpy
(
buf
,
p
)
;
}
else
if
(
const0_operand
(
xops
[
1
]
,
VOIDmode
)
)
{
gcc_assert
(
!
unordered_p
)
;
strcpy
(
buf
,
"ftst"
)
;
}
else
{
if
(
GET_MODE_CLASS
(
GET_MODE
(
xops
[
1
]
)
)
==
MODE_INT
)
{
gcc_assert
(
!
unordered_p
)
;
p
=
"ficom"
;
}
else
p
=
unordered_p
"fucom"
:
"fcom"
;
strcpy
(
buf
,
p
)
;
p
=
"p%Z2\t%y2"
;
strcat
(
buf
,
p
+
!
stack_top_dies
)
;
}
output_asm_insn
(
buf
,
operands
)
;
return
"fnstsw\t%0"
;
}
</s>

Output code for INSN to compare OPERANDS . EFLAGS_P is 1 when fcomi should be used and 2 when fnstsw should be used . UNORDERED_P is true when fucom should be used .


<s>
static
void
output_indirect_thunk
(
unsigned
int
regno
)
{
char
indirectlabel1
[
32
]
;
char
indirectlabel2
[
32
]
;
ASM_GENERATE_INTERNAL_LABEL
(
indirectlabel1
,
INDIRECT_LABEL
,
indirectlabelno
++
)
;
ASM_GENERATE_INTERNAL_LABEL
(
indirectlabel2
,
INDIRECT_LABEL
,
indirectlabelno
++
)
;
fputs
(
"\tcall\t"
,
asm_out_file
)
;
assemble_name_raw
(
asm_out_file
,
indirectlabel2
)
;
fputc
(
'\n'
,
asm_out_file
)
;
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
indirectlabel1
)
;
fprintf
(
asm_out_file
,
"\tpause\n\tlfence\n"
)
;
fputs
(
"\tjmp\t"
,
asm_out_file
)
;
assemble_name_raw
(
asm_out_file
,
indirectlabel1
)
;
fputc
(
'\n'
,
asm_out_file
)
;
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
indirectlabel2
)
;
if
(
flag_asynchronous_unwind_tables
&&
dwarf2out_do_frame
(
)
)
{
if
(
!
dwarf2out_do_cfi_asm
(
)
)
{
dw_cfi_ref
xcfi
=
ggc_cleared_alloc
<
dw_cfi_node
>
(
)
;
xcfi
->
dw_cfi_opc
=
DW_CFA_advance_loc4
;
xcfi
->
dw_cfi_oprnd1
.
dw_cfi_addr
=
ggc_strdup
(
indirectlabel2
)
;
vec_safe_push
(
cfun
->
fde
->
dw_fde_cfi
,
xcfi
)
;
}
dw_cfi_ref
xcfi
=
ggc_cleared_alloc
<
dw_cfi_node
>
(
)
;
xcfi
->
dw_cfi_opc
=
DW_CFA_def_cfa_offset
;
xcfi
->
dw_cfi_oprnd1
.
dw_cfi_offset
=
2
*
UNITS_PER_WORD
;
vec_safe_push
(
cfun
->
fde
->
dw_fde_cfi
,
xcfi
)
;
dwarf2out_emit_cfi
(
xcfi
)
;
}
if
(
regno
!=
INVALID_REGNUM
)
{
rtx
xops
[
2
]
;
xops
[
0
]
=
gen_rtx_MEM
(
word_mode
,
stack_pointer_rtx
)
;
xops
[
1
]
=
gen_rtx_REG
(
word_mode
,
regno
)
;
output_asm_insn
(
"mov\t{%1, %0|%0, %1}"
,
xops
)
;
}
else
{
rtx
xops
[
2
]
;
xops
[
0
]
=
stack_pointer_rtx
;
xops
[
1
]
=
plus_constant
(
Pmode
,
stack_pointer_rtx
,
UNITS_PER_WORD
)
;
output_asm_insn
(
"lea\t{%E1, %0|%0, %E1}"
,
xops
)
;
}
fputs
(
"\tret\n"
,
asm_out_file
)
;
if
(
(
ix86_harden_sls
&
harden_sls_return
)
)
fputs
(
"\tint3\n"
,
asm_out_file
)
;
}
</s>

Output a call and return thunk for indirect branch . If BND_P is true , the BND prefix is needed . If REGNO ! = -1 , the function address is in REGNO and the call and return thunk looks like : call L2 L1 : pause lfence jmp L1 L2 : mov % REG , ( % sp ) ret Otherwise , the function address is on the top of stack and the call and return thunk looks like : call L2 L1 : pause lfence jmp L1 L2 : lea WORD_SIZE ( % sp ) , % sp ret


<s> static void output_indirect_thunk_function ( enum indirect_thunk_prefix need_prefix , unsigned int regno , bool ret_p ) { char name [ 32 ] ; tree decl ; indirect_thunk_name ( name , regno , need_prefix , ret_p ) ; decl = build_decl ( BUILTINS_LOCATION , FUNCTION_DECL , get_identifier ( name ) , build_function_type_list ( void_type_node , NULL_TREE ) ) ; DECL_RESULT ( decl ) = build_decl ( BUILTINS_LOCATION , RESULT_DECL , NULL_TREE , void_type_node ) ; TREE_PUBLIC ( decl ) = 1 ; TREE_STATIC ( decl ) = 1 ; DECL_IGNORED_P ( decl ) = 1 ; if ( TARGET_MACHO ) { switch_to_section ( darwin_sections [ picbase_thunk_section ] ) ; fputs ( "\t.weak_definition\t" , asm_out_file ) ; assemble_name ( asm_out_file , name ) ; fputs ( "\n\t.private_extern\t" , asm_out_file ) ; assemble_name ( asm_out_file , name ) ; putc ( '\n' , asm_out_file ) ; ASM_OUTPUT_LABEL ( asm_out_file , name ) ; DECL_WEAK ( decl ) = 1 ; } else if ( USE_HIDDEN_LINKONCE ) { cgraph_node :: create ( decl ) -> set_comdat_group ( DECL_ASSEMBLER_NAME ( decl ) ) ; targetm . asm_out . unique_section ( decl , 0 ) ; switch_to_section ( get_named_section ( decl , NULL , 0 ) ) ; targetm . asm_out . globalize_label ( asm_out_file , name ) ; fputs ( "\t.hidden\t" , asm_out_file ) ; assemble_name ( asm_out_file , name ) ; putc ( '\n' , asm_out_file ) ; ASM_DECLARE_FUNCTION_NAME ( asm_out_file , name , decl ) ; } else { switch_to_section ( text_section ) ; ASM_OUTPUT_LABEL ( asm_out_file , name ) ; } DECL_INITIAL ( decl ) = make_node ( BLOCK ) ; current_function_decl = decl ; allocate_struct_function ( decl , false ) ; init_function_start ( decl ) ; cfun -> is_thunk = true ; first_function_block_is_cold = false ; final_start_function ( emit_barrier ( ) , asm_out_file , 1 ) ; output_indirect_thunk ( regno ) ; final_end_function ( ) ; init_insn_lengths ( ) ; free_after_compilation ( cfun ) ; set_cfun ( NULL ) ; current_function_decl = NULL ; } </s>

Output a funtion with a call and return thunk for indirect branch . If BND_P is true , the BND prefix is needed . If REGNO ! = UNVALID_REGNUM , the function address is in REGNO . Otherwise , the function address is on the top of stack . Thunk is used for function return if RET_P is true .


Wrapper around the output_probe_stack_range routines .


Output return instrumentation for current function if needed .


<s> static rtx pro_epilogue_adjust_stack ( rtx dest , rtx src , rtx offset , int style , bool set_cfa ) { struct machine_function * m = cfun -> machine ; rtx addend = offset ; rtx insn ; bool add_frame_related_expr = false ; if ( ! x86_64_immediate_operand ( offset , Pmode ) ) { if ( style ) addend = gen_rtx_REG ( Pmode , R11_REG ) ; else { gcc_assert ( src != hard_frame_pointer_rtx && dest != hard_frame_pointer_rtx ) ; addend = hard_frame_pointer_rtx ; } emit_insn ( gen_rtx_SET ( addend , offset ) ) ; if ( style < 0 ) add_frame_related_expr = true ; } insn = emit_insn ( gen_pro_epilogue_adjust_stack_add ( Pmode , dest , src , addend ) ) ; if ( style >= 0 ) ix86_add_queued_cfa_restore_notes ( insn ) ; if ( set_cfa ) { rtx r ; gcc_assert ( m -> fs . cfa_reg == src ) ; m -> fs . cfa_offset += INTVAL ( offset ) ; m -> fs . cfa_reg = dest ; r = gen_rtx_PLUS ( Pmode , src , offset ) ; r = gen_rtx_SET ( dest , r ) ; add_reg_note ( insn , REG_CFA_ADJUST_CFA , r ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } else if ( style < 0 ) { RTX_FRAME_RELATED_P ( insn ) = 1 ; if ( add_frame_related_expr ) { rtx r = gen_rtx_PLUS ( Pmode , src , offset ) ; r = gen_rtx_SET ( dest , r ) ; add_reg_note ( insn , REG_FRAME_RELATED_EXPR , r ) ; } } if ( dest == stack_pointer_rtx ) { HOST_WIDE_INT ooffset = m -> fs . sp_offset ; bool valid = m -> fs . sp_valid ; bool realigned = m -> fs . sp_realigned ; if ( src == hard_frame_pointer_rtx ) { valid = m -> fs . fp_valid ; realigned = false ; ooffset = m -> fs . fp_offset ; } else if ( src == crtl -> drap_reg ) { valid = m -> fs . drap_valid ; realigned = false ; ooffset = 0 ; } else { gcc_checking_assert ( src == stack_pointer_rtx || offset == const0_rtx ) ; } m -> fs . sp_offset = ooffset - INTVAL ( offset ) ; m -> fs . sp_valid = valid ; m -> fs . sp_realigned = realigned ; } return insn ; } </s>

Expand prologue or epilogue stack adjustment . The pattern exist to put a dependency on all ebp-based memory accesses . STYLE should be negative if instructions should be marked as frame related , zero if % r11 register is live and can not be freely used and positive otherwise .


<s> static void release_scratch_register_on_entry ( struct scratch_reg * sr , HOST_WIDE_INT offset , bool release_via_pop ) { if ( sr -> saved ) { if ( release_via_pop ) { struct machine_function * m = cfun -> machine ; rtx x , insn = emit_insn ( gen_pop ( sr -> reg ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; x = plus_constant ( Pmode , stack_pointer_rtx , UNITS_PER_WORD ) ; x = gen_rtx_SET ( stack_pointer_rtx , x ) ; add_reg_note ( insn , REG_FRAME_RELATED_EXPR , x ) ; m -> fs . sp_offset -= UNITS_PER_WORD ; } else { rtx x = plus_constant ( Pmode , stack_pointer_rtx , offset ) ; x = gen_rtx_SET ( sr -> reg , gen_rtx_MEM ( word_mode , x ) ) ; emit_insn ( x ) ; } } } </s>

Release a scratch register obtained from the preceding function . If RELEASE_VIA_POP is true , we just pop the register off the stack to release it . This is what non-Linux systems use with -fstack-check . Otherwise we use OFFSET to locate the saved register and the allocated stack space becomes part of the local frame and is deallocated by the epilogue .


<s> static void setup_incoming_varargs_64 ( CUMULATIVE_ARGS * cum ) { rtx save_area , mem ; alias_set_type set ; int i , max ; if ( cfun -> va_list_gpr_size ) ix86_varargs_gpr_size = X86_64_REGPARM_MAX * UNITS_PER_WORD ; else ix86_varargs_gpr_size = 0 ; if ( TARGET_SSE && cfun -> va_list_fpr_size ) ix86_varargs_fpr_size = X86_64_SSE_REGPARM_MAX * 16 ; else ix86_varargs_fpr_size = 0 ; if ( ! ix86_varargs_gpr_size && ! ix86_varargs_fpr_size ) return ; save_area = frame_pointer_rtx ; set = get_varargs_alias_set ( ) ; max = cum -> regno + cfun -> va_list_gpr_size / UNITS_PER_WORD ; if ( max > X86_64_REGPARM_MAX ) max = X86_64_REGPARM_MAX ; for ( i = cum -> regno ; i < max ; i ++ ) { mem = gen_rtx_MEM ( word_mode , plus_constant ( Pmode , save_area , i * UNITS_PER_WORD ) ) ; MEM_NOTRAP_P ( mem ) = 1 ; set_mem_alias_set ( mem , set ) ; emit_move_insn ( mem , gen_rtx_REG ( word_mode , x86_64_int_parameter_registers [ i ] ) ) ; } if ( ix86_varargs_fpr_size ) { machine_mode smode ; rtx_code_label * label ; rtx test ; label = gen_label_rtx ( ) ; test = gen_rtx_EQ ( VOIDmode , gen_rtx_REG ( QImode , AX_REG ) , const0_rtx ) ; emit_jump_insn ( gen_cbranchqi4 ( test , XEXP ( test , 0 ) , XEXP ( test , 1 ) , label ) ) ; smode = V4SFmode ; if ( crtl -> stack_alignment_needed < GET_MODE_ALIGNMENT ( smode ) ) crtl -> stack_alignment_needed = GET_MODE_ALIGNMENT ( smode ) ; max = cum -> sse_regno + cfun -> va_list_fpr_size / 16 ; if ( max > X86_64_SSE_REGPARM_MAX ) max = X86_64_SSE_REGPARM_MAX ; for ( i = cum -> sse_regno ; i < max ; ++ i ) { mem = plus_constant ( Pmode , save_area , i * 16 + ix86_varargs_gpr_size ) ; mem = gen_rtx_MEM ( smode , mem ) ; MEM_NOTRAP_P ( mem ) = 1 ; set_mem_alias_set ( mem , set ) ; set_mem_align ( mem , GET_MODE_ALIGNMENT ( smode ) ) ; emit_move_insn ( mem , gen_rtx_REG ( smode , GET_SSE_REGNO ( i ) ) ) ; } emit_label ( label ) ; } } </s>

Worker function for TARGET_SETUP_INCOMING_VARARGS .


"%<-fsplit-stack%> does not support fastcall with "

"%<-fsplit-stack%> does not support 2 register "

"%<-fsplit-stack%> does not support 3 register parameters"

Return a scratch register to use in the split stack prologue . The split stack prologue is used for -fsplit-stack . It is the first instructions in the function , even before the regular prologue . The scratch register can be any caller-saved register which is not used for parameters or for the static chain .


<s> static bool sp_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_offset ) { gcc_assert ( cfa_offset <= fs . sp_realigned_fp_last ) ; return false ; } return fs . sp_valid ; } </s>

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


<s> static inline int sse_store_index ( machine_mode mode ) { if ( mode == E_HFmode ) mode = E_SFmode ; switch ( GET_MODE_SIZE ( mode ) ) { case 4 : return 0 ; case 8 : return 1 ; case 16 : return 2 ; case 32 : return 3 ; case 64 : return 4 ; default : return - 1 ; } } </s>

Return index of MODE in the sse load/store tables .


<s> const char * standard_80387_constant_opcode ( rtx x ) { switch ( standard_80387_constant_p ( x ) ) { case 1 : return "fldz" ; case 2 : return "fld1" ; case 3 : return "fldlg2" ; case 4 : return "fldln2" ; case 5 : return "fldl2e" ; case 6 : return "fldl2t" ; case 7 : return "fldpi" ; case 8 : case 9 : return "#" ; default : gcc_unreachable ( ) ; } } </s>

Return the opcode of the special instruction to be used to load the constant X .


<s> int standard_80387_constant_p ( rtx x ) { machine_mode mode = GET_MODE ( x ) ; const REAL_VALUE_TYPE * r ; if ( ! ( CONST_DOUBLE_P ( x ) && X87_FLOAT_MODE_P ( mode ) ) ) return - 1 ; if ( x == CONST0_RTX ( mode ) ) return 1 ; if ( x == CONST1_RTX ( mode ) ) return 2 ; r = CONST_DOUBLE_REAL_VALUE ( x ) ; if ( mode == XFmode && ( optimize_function_for_size_p ( cfun ) || TARGET_EXT_80387_CONSTANTS ) && ! flag_rounding_math ) { int i ; if ( ! ext_80387_constants_init ) init_ext_80387_constants ( ) ; for ( i = 0 ; i < 5 ; i ++ ) if ( real_identical ( r , & ext_80387_constants_table [ i ] ) ) return i + 3 ; } if ( real_isnegzero ( r ) ) return 8 ; if ( real_identical ( r , & dconstm1 ) ) return 9 ; return 0 ; } </s>

Return true if the constant is something that can be loaded with a special instruction .


<s> rtx standard_80387_constant_rtx ( int idx ) { int i ; if ( ! ext_80387_constants_init ) init_ext_80387_constants ( ) ; switch ( idx ) { case 3 : case 4 : case 5 : case 6 : case 7 : i = idx - 3 ; break ; default : gcc_unreachable ( ) ; } return const_double_from_real_value ( ext_80387_constants_table [ i ] , XFmode ) ; } </s>

Return the CONST_DOUBLE representing the 80387 constant that is loaded by the specified special instruction . The argument IDX matches the return value from standard_80387_constant_p .


<s> int standard_sse_constant_p ( rtx x , machine_mode pred_mode ) { machine_mode mode ; if ( ! TARGET_SSE ) return 0 ; mode = GET_MODE ( x ) ; if ( x == const0_rtx || const0_operand ( x , mode ) ) return 1 ; if ( x == constm1_rtx || vector_all_ones_operand ( x , mode ) || ( ( GET_MODE_CLASS ( mode ) == MODE_VECTOR_FLOAT || GET_MODE_CLASS ( pred_mode ) == MODE_VECTOR_FLOAT ) && float_vector_all_ones_operand ( x , mode ) ) ) { if ( mode == VOIDmode ) mode = pred_mode ; switch ( GET_MODE_SIZE ( mode ) ) { case 64 : if ( TARGET_AVX512F ) return 2 ; break ; case 32 : if ( TARGET_AVX2 ) return 2 ; break ; case 16 : if ( TARGET_SSE2 ) return 2 ; break ; case 0 : gcc_unreachable ( ) ; default : break ; } } return 0 ; } </s>

Return 1 if X is all 0s and 2 if x is all 1s in supported SSE/AVX vector mode .


<s> bool symbolic_reference_mentioned_p ( rtx op ) { const char * fmt ; int i ; if ( GET_CODE ( op ) == SYMBOL_REF || GET_CODE ( op ) == LABEL_REF ) return true ; fmt = GET_RTX_FORMAT ( GET_CODE ( op ) ) ; for ( i = GET_RTX_LENGTH ( GET_CODE ( op ) ) - 1 ; i >= 0 ; i -- ) { if ( fmt [ i ] == 'E' ) { int j ; for ( j = XVECLEN ( op , i ) - 1 ; j >= 0 ; j -- ) if ( symbolic_reference_mentioned_p ( XVECEXP ( op , i , j ) ) ) return true ; } else if ( fmt [ i ] == 'e' && symbolic_reference_mentioned_p ( XEXP ( op , i ) ) ) return true ; } return false ; } </s>

Return true if OP contains a symbol reference


"without AVX512F enabled changes the ABI"

Return the `` natural '' mode for TYPE . In most cases , this is just TYPE_MODE . But in the case of vector types , it is some vector mode . When we have only some of our vector isa extensions enabled , then there are some modes for which vector_mode_supported_p is false . For these modes , the generic vector support in gcc will choose some non-vector mode in order to implement the type . By computing the natural mode , we 'll select the proper ABI location for the operand and not depend on whatever the middle-end decides to do with these vector types .


<s> static bool use_rsqrt_p ( machine_mode mode ) { return ( ( mode == HFmode || ( TARGET_SSE && TARGET_SSE_MATH ) ) && flag_finite_math_only && ! flag_trapping_math && flag_unsafe_math_optimizations ) ; } </s>

Return true if it is safe to use the rsqrt optabs to optimize 1.0/sqrt .


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

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


<s> static unsigned int ATTRIBUTE_UNUSED x86_64_elf_section_type_flags ( tree decl , const char * name , int reloc ) { unsigned int flags = default_section_type_flags ( decl , name , reloc ) ; if ( ix86_in_large_data_p ( decl ) ) flags |= SECTION_LARGE ; if ( decl == NULL_TREE && ( strcmp ( name , ".ldata.rel.ro" ) == 0 || strcmp ( name , ".ldata.rel.ro.local" ) == 0 ) ) flags |= SECTION_RELRO ; if ( strcmp ( name , ".lbss" ) == 0 || startswith ( name , ".lbss." ) || startswith ( name , ".gnu.linkonce.lb." ) ) flags |= SECTION_BSS ; return flags ; } </s>

Select a set of attributes for section NAME based on the properties of DECL and whether or not RELOC indicates that DECL 's initializer might contain runtime relocations .


<s> ATTRIBUTE_UNUSED static section * x86_64_elf_select_section ( tree decl , int reloc , unsigned HOST_WIDE_INT align ) { if ( ix86_in_large_data_p ( decl ) ) { const char * sname = NULL ; unsigned int flags = SECTION_WRITE | SECTION_LARGE ; switch ( categorize_decl_for_section ( decl , reloc ) ) { case SECCAT_DATA : sname = ".ldata" ; break ; case SECCAT_DATA_REL : sname = ".ldata.rel" ; break ; case SECCAT_DATA_REL_LOCAL : sname = ".ldata.rel.local" ; break ; case SECCAT_DATA_REL_RO : sname = ".ldata.rel.ro" ; break ; case SECCAT_DATA_REL_RO_LOCAL : sname = ".ldata.rel.ro.local" ; break ; case SECCAT_BSS : sname = ".lbss" ; flags |= SECTION_BSS ; break ; case SECCAT_RODATA : case SECCAT_RODATA_MERGE_STR : case SECCAT_RODATA_MERGE_STR_INIT : case SECCAT_RODATA_MERGE_CONST : sname = ".lrodata" ; flags &= ~ SECTION_WRITE ; break ; case SECCAT_SRODATA : case SECCAT_SDATA : case SECCAT_SBSS : gcc_unreachable ( ) ; case SECCAT_TEXT : case SECCAT_TDATA : case SECCAT_TBSS : break ; } if ( sname ) { if ( ! DECL_P ( decl ) ) return get_section ( sname , flags , NULL ) ; return get_named_section ( decl , sname , reloc ) ; } } return default_elf_select_section ( decl , reloc , align ) ; } </s>

switch to the appropriate section for output of DECL . DECL is either a ` VAR_DECL ' node or a constant of some sort . RELOC indicates whether forming the initial value of DECL requires link-time relocations .


<s> static void ATTRIBUTE_UNUSED x86_64_elf_unique_section ( tree decl , int reloc ) { if ( ix86_in_large_data_p ( decl ) ) { const char * prefix = NULL ; bool one_only = DECL_COMDAT_GROUP ( decl ) && ! HAVE_COMDAT_GROUP ; switch ( categorize_decl_for_section ( decl , reloc ) ) { case SECCAT_DATA : case SECCAT_DATA_REL : case SECCAT_DATA_REL_LOCAL : case SECCAT_DATA_REL_RO : case SECCAT_DATA_REL_RO_LOCAL : prefix = one_only ? ".ld" : ".ldata" ; break ; case SECCAT_BSS : prefix = one_only ? ".lb" : ".lbss" ; break ; case SECCAT_RODATA : case SECCAT_RODATA_MERGE_STR : case SECCAT_RODATA_MERGE_STR_INIT : case SECCAT_RODATA_MERGE_CONST : prefix = one_only ? ".lr" : ".lrodata" ; break ; case SECCAT_SRODATA : case SECCAT_SDATA : case SECCAT_SBSS : gcc_unreachable ( ) ; case SECCAT_TEXT : case SECCAT_TDATA : case SECCAT_TBSS : break ; } if ( prefix ) { const char * name , * linkonce ; char * string ; name = IDENTIFIER_POINTER ( DECL_ASSEMBLER_NAME ( decl ) ) ; name = targetm . strip_name_encoding ( name ) ; linkonce = one_only ? ".gnu.linkonce" : "" ; string = ACONCAT ( ( linkonce , prefix , "." , name , NULL ) ) ; set_decl_section_name ( decl , string ) ; return ; } } default_unique_section ( decl , reloc ) ; } </s>

Build up a unique section name , expressed as a STRING_CST node , and assign it to DECL_SECTION_NAME ( decl ) . RELOC indicates whether the initial value of EXP requires link-time relocations .


<s> static bool x86_can_output_mi_thunk ( const_tree , HOST_WIDE_INT , HOST_WIDE_INT vcall_offset , const_tree function ) { if ( TARGET_64BIT ) return true ; if ( ix86_function_regparm ( TREE_TYPE ( function ) , function ) < 3 ) return true ; if ( vcall_offset ) return false ; if ( flag_pic && ! targetm . binds_local_p ( function ) ) return false ; return true ; } </s>

Determine whether x86_output_mi_thunk can succeed .


<s> void x86_elf_aligned_decl_common ( FILE * file , tree decl , const char * name , unsigned HOST_WIDE_INT size , unsigned align ) { if ( ( ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC ) && size > ( unsigned int ) ix86_section_threshold ) { switch_to_section ( get_named_section ( decl , ".lbss" , 0 ) ) ; fputs ( LARGECOMM_SECTION_ASM_OP , file ) ; } else fputs ( COMMON_ASM_OP , file ) ; assemble_name ( file , name ) ; fprintf ( file , "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n" , size , align / BITS_PER_UNIT ) ; } </s>

This says how to output assembler code to declare an uninitialized external linkage data object . For medium model x86-64 we need to use LARGECOMM_SECTION_ASM_OP opcode for large objects .


<s> void x86_emit_floatuns ( rtx operands [ 2 ] ) { rtx_code_label * neglab , * donelab ; rtx i0 , i1 , f0 , in , out ; machine_mode mode , inmode ; inmode = GET_MODE ( operands [ 1 ] ) ; gcc_assert ( inmode == SImode || inmode == DImode ) ; out = operands [ 0 ] ; in = force_reg ( inmode , operands [ 1 ] ) ; mode = GET_MODE ( out ) ; neglab = gen_label_rtx ( ) ; donelab = gen_label_rtx ( ) ; f0 = gen_reg_rtx ( mode ) ; emit_cmp_and_jump_insns ( in , const0_rtx , LT , const0_rtx , inmode , 0 , neglab ) ; expand_float ( out , in , 0 ) ; emit_jump_insn ( gen_jump ( donelab ) ) ; emit_barrier ( ) ; emit_label ( neglab ) ; i0 = expand_simple_binop ( inmode , LSHIFTRT , in , const1_rtx , NULL , 1 , OPTAB_DIRECT ) ; i1 = expand_simple_binop ( inmode , AND , in , const1_rtx , NULL , 1 , OPTAB_DIRECT ) ; i0 = expand_simple_binop ( inmode , IOR , i0 , i1 , i0 , 1 , OPTAB_DIRECT ) ; expand_float ( f0 , i0 , 0 ) ; emit_insn ( gen_rtx_SET ( out , gen_rtx_PLUS ( mode , f0 , f0 ) ) ) ; emit_label ( donelab ) ; } </s>

Generate an unsigned DImode/SImode to FP conversion . This is the same code optabs would emit if we did n't have TFmode patterns .


<s> bool x86_extended_QIreg_mentioned_p ( rtx_insn * insn ) { int i ; extract_insn_cached ( insn ) ; for ( i = 0 ; i < recog_data . n_operands ; i ++ ) if ( GENERAL_REG_P ( recog_data . operand [ i ] ) && ! QI_REGNO_P ( REGNO ( recog_data . operand [ i ] ) ) ) return true ; return false ; } </s>

Return nonzero when QImode register that must be represented via REX prefix is used .


<s> bool x86_extended_reg_mentioned_p ( rtx insn ) { subrtx_iterator :: array_type array ; FOR_EACH_SUBRTX ( iter , array , INSN_P ( insn ) ? PATTERN ( insn ) : insn , NONCONST ) { const_rtx x = * iter ; if ( REG_P ( x ) && ( REX_INT_REGNO_P ( REGNO ( x ) ) || REX_SSE_REGNO_P ( REGNO ( x ) ) ) ) return true ; } return false ; } </s>

Return true when INSN mentions register that must be encoded using REX prefix .


"profiling %<-mcmodel=large%> with PIC is not supported"

Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry .


<s> bool x86_maybe_negate_const_int ( rtx * loc , machine_mode mode ) { HOST_WIDE_INT val ; if ( ! CONST_INT_P ( * loc ) ) return false ; switch ( mode ) { case E_DImode : gcc_assert ( x86_64_immediate_operand ( * loc , mode ) ) ; mode = SImode ; break ; case E_SImode : case E_HImode : case E_QImode : break ; default : gcc_unreachable ( ) ; } if ( mode_signbit_p ( mode , * loc ) ) return false ; val = INTVAL ( * loc ) ; if ( ( val < 0 && val != - 128 ) || val == 128 ) { * loc = GEN_INT ( - val ) ; return true ; } return false ; } </s>

If profitable , negate ( without causing overflow ) integer constant of mode MODE at location LOC . Return true in this case .


<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_or_fixed_reg_p ( i ) ) reg_alloc_order [ pos ++ ] = i ; for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) if ( GENERAL_REGNO_P ( i ) && ! call_used_or_fixed_reg_p ( 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> void x86_output_aligned_bss ( FILE * file , tree decl , const char * name , unsigned HOST_WIDE_INT size , unsigned align ) { if ( ( ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC ) && size > ( unsigned int ) ix86_section_threshold ) switch_to_section ( get_named_section ( decl , ".lbss" , 0 ) ) ; else switch_to_section ( bss_section ) ; ASM_OUTPUT_ALIGN ( file , floor_log2 ( align / BITS_PER_UNIT ) ) ; last_assemble_variable_decl = decl ; ASM_DECLARE_OBJECT_NAME ( file , name , decl ) ; ASM_OUTPUT_LABEL ( file , name ) ; ASM_OUTPUT_SKIP ( file , size ? size : 1 ) ; } </s>

Utility function for targets to use in implementing ASM_OUTPUT_ALIGNED_BSS .


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


<s> static rtx x86_this_parameter ( tree function ) { tree type = TREE_TYPE ( function ) ; bool aggr = aggregate_value_p ( TREE_TYPE ( type ) , type ) != 0 ; int nregs ; if ( TARGET_64BIT ) { const int * parm_regs ; if ( ix86_function_type_abi ( type ) == MS_ABI ) parm_regs = x86_64_ms_abi_int_parameter_registers ; else parm_regs = x86_64_int_parameter_registers ; return gen_rtx_REG ( Pmode , parm_regs [ aggr ] ) ; } nregs = ix86_function_regparm ( type , function ) ; if ( nregs > 0 && ! stdarg_p ( type ) ) { int regno ; unsigned int ccvt = ix86_get_callcvt ( type ) ; if ( ( ccvt & IX86_CALLCVT_FASTCALL ) != 0 ) regno = aggr ? DX_REG : CX_REG ; else if ( ( ccvt & IX86_CALLCVT_THISCALL ) != 0 ) { regno = CX_REG ; if ( aggr ) return gen_rtx_MEM ( SImode , plus_constant ( Pmode , stack_pointer_rtx , 4 ) ) ; } else { regno = AX_REG ; if ( aggr ) { regno = DX_REG ; if ( nregs == 1 ) return gen_rtx_MEM ( SImode , plus_constant ( Pmode , stack_pointer_rtx , 4 ) ) ; } } return gen_rtx_REG ( SImode , regno ) ; } return gen_rtx_MEM ( SImode , plus_constant ( Pmode , stack_pointer_rtx , aggr ? 8 : 4 ) ) ; } </s>

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


<s> static bool zero_all_mm_registers ( HARD_REG_SET need_zeroed_hardregs , unsigned int ret_mmx_regno ) { bool need_zero_all_mm = false ; for ( unsigned int regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( STACK_REGNO_P ( regno ) && TEST_HARD_REG_BIT ( need_zeroed_hardregs , regno ) ) { need_zero_all_mm = true ; break ; } if ( ! need_zero_all_mm ) return false ; rtx zero_mmx = NULL_RTX ; machine_mode mode = V4HImode ; for ( unsigned int regno = FIRST_MMX_REG ; regno <= LAST_MMX_REG ; regno ++ ) if ( regno != ret_mmx_regno ) { rtx reg = gen_rtx_REG ( mode , regno ) ; if ( zero_mmx == NULL_RTX ) { zero_mmx = reg ; emit_insn ( gen_rtx_SET ( reg , CONST0_RTX ( mode ) ) ) ; } else emit_move_insn ( reg , zero_mmx ) ; } return true ; } </s>

When the routine exit in MMX mode , if any ST register needs to be zeroed , we should clear all MMX registers except the RET_MMX_REGNO that holds the return value .


<s> static int zero_all_st_registers ( HARD_REG_SET need_zeroed_hardregs ) { if ( ! ( TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 ) ) return 0 ; unsigned int num_of_st = 0 ; for ( unsigned int regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( ( STACK_REGNO_P ( regno ) || MMX_REGNO_P ( regno ) ) && TEST_HARD_REG_BIT ( need_zeroed_hardregs , regno ) ) { num_of_st ++ ; break ; } if ( num_of_st == 0 ) return 0 ; bool return_with_x87 = false ; return_with_x87 = ( crtl -> return_rtx && ( STACK_REG_P ( crtl -> return_rtx ) ) ) ; bool complex_return = false ; complex_return = ( crtl -> return_rtx && COMPLEX_MODE_P ( GET_MODE ( crtl -> return_rtx ) ) ) ; if ( return_with_x87 ) if ( complex_return ) num_of_st = 6 ; else num_of_st = 7 ; else num_of_st = 8 ; rtx st_reg = gen_rtx_REG ( XFmode , FIRST_STACK_REG ) ; for ( unsigned int i = 0 ; i < num_of_st ; i ++ ) emit_insn ( gen_rtx_SET ( st_reg , CONST0_RTX ( XFmode ) ) ) ; for ( unsigned int i = 0 ; i < num_of_st ; i ++ ) { rtx insn ; insn = emit_insn ( gen_rtx_SET ( st_reg , st_reg ) ) ; add_reg_note ( insn , REG_DEAD , st_reg ) ; } return num_of_st ; } </s>

Generate insns to zero all st registers together . Return true when zeroing instructions are generated . Assume the number of st registers that are zeroed is num_of_st , we will emit the following sequence to zero them together : fldz ; \ fldz ; \ ... fldz ; \ fstp % % st ( 0 ) ; \ fstp % % st ( 0 ) ; \ ... fstp % % st ( 0 ) ; i.e. , num_of_st fldz followed by num_of_st fstp to clear the stack mark stack slots empty . How to compute the num_of_st : There is no direct mapping from stack registers to hard register numbers . If one stack register needs to be cleared , we do n't know where in the stack the value remains . So , if any stack register needs to be cleared , the whole stack should be cleared . However , x87 stack registers that hold the return value should be excluded . x87 returns in the top ( two for complex values ) register , so num_of_st should be 7/6 when x87 returns , otherwise it will be 8 .


<s> static rtx zero_all_vector_registers ( HARD_REG_SET need_zeroed_hardregs ) { if ( ! TARGET_AVX ) return NULL ; for ( unsigned int regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( ( LEGACY_SSE_REGNO_P ( regno ) || ( TARGET_64BIT && ( REX_SSE_REGNO_P ( regno ) || ( TARGET_AVX512F && EXT_REX_SSE_REGNO_P ( regno ) ) ) ) ) && ! TEST_HARD_REG_BIT ( need_zeroed_hardregs , regno ) ) return NULL ; return gen_avx_vzeroall ( ) ; } </s>

Generate a rtx to zero all vector registers together if possible , otherwise , return NULL .


<s> static machine_mode zero_call_used_regno_mode ( const unsigned int regno ) { if ( GENERAL_REGNO_P ( regno ) ) return SImode ; else if ( SSE_REGNO_P ( regno ) ) return V4SFmode ; else if ( MASK_REGNO_P ( regno ) ) return HImode ; else if ( MMX_REGNO_P ( regno ) ) return V4HImode ; else gcc_unreachable ( ) ; } </s>

Return the machine_mode that is used to zero register REGNO .


<s> static bool zero_call_used_regno_p ( const unsigned int regno , bool all_sse_zeroed , bool need_zero_mmx ) { return GENERAL_REGNO_P ( regno ) || ( ! all_sse_zeroed && SSE_REGNO_P ( regno ) ) || MASK_REGNO_P ( regno ) || ( need_zero_mmx && MMX_REGNO_P ( regno ) ) ; } </s>

Check whether the register REGNO should be zeroed on X86 . When ALL_SSE_ZEROED is true , all SSE registers have been zeroed together , no need to zero it again . When NEED_ZERO_MMX is true , MMX registers should be cleared .


"static const void *__offload_target_data[] = {\n"

"  &__offload_image_intelmic_start, &__offload_image_intelmic_end\n"

"void GOMP_offload_register (void *, int, void *);\n"

"void GOMP_offload_unregister (void *, int, void *);\n\n"

"  GOMP_offload_register (&__OFFLOAD_TABLE__, %d, __offload_target_data);\n"

"  GOMP_offload_unregister (&__OFFLOAD_TABLE__, %d, __offload_target_data);\n"

Generates object file with the host side descriptor .


"__attribute__ ((__used__, visibility (\"hidden\"),\n"

"section (\".gnu.offload_funcs\"))) = { };\n\n"

"section (\".gnu.offload_vars\"))) = { };\n\n"

"__attribute__ ((__used__, visibility (\"hidden\"))) = {\n"

"  &__offload_func_table, &__offload_funcs_end,\n"

"  &__offload_var_table, &__offload_vars_end\n"

"void target_register_lib (const void *);\n\n"

"  target_register_lib (__OFFLOAD_TARGET_TABLE__);\n"

Generates object file with the descriptor for the target library .


"section (\".gnu.offload_vars\"))) = { };\n"

Generates object file with __offload_ * _end symbols for the target library .


"unrecognizable argument of option -foffload-abi"

Main program to convert flat files into built-in initialization code .


<s>
void
maybe_unlink
(
const
char
*
file
)
{
if
(
debug
)
notice
(
"[Leaving %s]\n"
,
file
)
;
else
unlink_if_ordinary
(
file
)
;
}
</s>

Unlink a temporary file unless requested otherwise .