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

Order the registers for register allocator .


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


<s>
void
scalar_chain
::
add_insn
(
bitmap
candidates
,
unsigned
int
insn_uid
)
{
if
(
bitmap_bit_p
(
insns
,
insn_uid
)
)
return
;
if
(
dump_file
)
fprintf
(
dump_file
,
"  Adding insn %d to chain #%d\n"
,
insn_uid
,
chain_id
)
;
bitmap_set_bit
(
insns
,
insn_uid
)
;
rtx_insn
*
insn
=
DF_INSN_UID_GET
(
insn_uid
)
->
insn
;
rtx
def_set
=
single_set
(
insn
)
;
if
(
def_set
&&
REG_P
(
SET_DEST
(
def_set
)
)
&&
!
HARD_REGISTER_P
(
SET_DEST
(
def_set
)
)
)
bitmap_set_bit
(
defs
,
REGNO
(
SET_DEST
(
def_set
)
)
)
;
df_ref
ref
;
df_ref
def
;
for
(
ref
=
DF_INSN_UID_DEFS
(
insn_uid
)
;
ref
;
ref
=
DF_REF_NEXT_LOC
(
ref
)
)
if
(
!
HARD_REGISTER_P
(
DF_REF_REG
(
ref
)
)
)
for
(
def
=
DF_REG_DEF_CHAIN
(
DF_REF_REGNO
(
ref
)
)
;
def
;
def
=
DF_REF_NEXT_REG
(
def
)
)
analyze_register_chain
(
candidates
,
def
)
;
for
(
ref
=
DF_INSN_UID_USES
(
insn_uid
)
;
ref
;
ref
=
DF_REF_NEXT_LOC
(
ref
)
)
if
(
!
DF_REF_REG_MEM_P
(
ref
)
)
analyze_register_chain
(
candidates
,
ref
)
;
}
</s>

Add instruction into a chain . Return true if OK , false if the search was aborted .


<s> static bool canonicalize_vector_int_perm ( const struct expand_vec_perm_d * d , struct expand_vec_perm_d * nd ) { int i ; enum machine_mode mode = VOIDmode ; switch ( d -> vmode ) { case V16QImode : mode = V8HImode ; break ; case V32QImode : mode = V16HImode ; break ; case V64QImode : mode = V32HImode ; break ; case V8HImode : mode = V4SImode ; break ; case V16HImode : mode = V8SImode ; break ; case V32HImode : mode = V16SImode ; break ; case V4SImode : mode = V2DImode ; break ; case V8SImode : mode = V4DImode ; break ; case V16SImode : mode = V8DImode ; break ; default : return false ; } for ( i = 0 ; i < d -> nelt ; i += 2 ) if ( ( d -> perm [ i ] & 1 ) || d -> perm [ i + 1 ] != d -> perm [ i ] + 1 ) return false ; nd -> vmode = mode ; nd -> nelt = d -> nelt / 2 ; for ( i = 0 ; i < nd -> nelt ; i ++ ) nd -> perm [ i ] = d -> perm [ 2 * i ] / 2 ; if ( GET_MODE_INNER ( mode ) != DImode ) canonicalize_vector_int_perm ( nd , nd ) ; if ( nd != d ) { nd -> one_operand_p = d -> one_operand_p ; nd -> testing_p = d -> testing_p ; if ( d -> op0 == d -> op1 ) nd -> op0 = nd -> op1 = gen_lowpart ( nd -> vmode , d -> op0 ) ; else { nd -> op0 = gen_lowpart ( nd -> vmode , d -> op0 ) ; nd -> op1 = gen_lowpart ( nd -> vmode , d -> op1 ) ; } if ( d -> testing_p ) nd -> target = gen_raw_REG ( nd -> vmode , LAST_VIRTUAL_REGISTER + 1 ) ; else nd -> target = gen_reg_rtx ( nd -> vmode ) ; } return true ; } </s>

For V * [ QHS ] Imode permutations , check if the same permutation ca n't be performed in a 2x , 4x or 8x wider inner mode .


<s>
int
scalar_chain
::
compute_convert_gain
(
)
{
bitmap_iterator
bi
;
unsigned
insn_uid
;
int
gain
=
0
;
int
cost
=
0
;
if
(
dump_file
)
fprintf
(
dump_file
,
"Computing gain for chain #%d...\n"
,
chain_id
)
;
EXECUTE_IF_SET_IN_BITMAP
(
insns
,
0
,
insn_uid
,
bi
)
{
rtx_insn
*
insn
=
DF_INSN_UID_GET
(
insn_uid
)
->
insn
;
rtx
def_set
=
single_set
(
insn
)
;
rtx
src
=
SET_SRC
(
def_set
)
;
rtx
dst
=
SET_DEST
(
def_set
)
;
if
(
REG_P
(
src
)
&&
REG_P
(
dst
)
)
gain
+=
COSTS_N_INSNS
(
2
)
ix86_cost
->
sse_move
;
else
if
(
REG_P
(
src
)
&&
MEM_P
(
dst
)
)
gain
+=
2
*
ix86_cost
->
int_store
[
2
]
ix86_cost
->
sse_store
[
1
]
;
else
if
(
MEM_P
(
src
)
&&
REG_P
(
dst
)
)
gain
+=
2
*
ix86_cost
->
int_load
[
2
]
ix86_cost
->
sse_load
[
1
]
;
else
if
(
GET_CODE
(
src
)
==
PLUS
||
GET_CODE
(
src
)
==
MINUS
||
GET_CODE
(
src
)
==
IOR
||
GET_CODE
(
src
)
==
XOR
||
GET_CODE
(
src
)
==
AND
)
gain
+=
ix86_cost
->
add
;
else
if
(
GET_CODE
(
src
)
==
COMPARE
)
{
}
else
gcc_unreachable
(
)
;
}
if
(
dump_file
)
fprintf
(
dump_file
,
"  Instruction conversion gain: %d\n"
,
gain
)
;
EXECUTE_IF_SET_IN_BITMAP
(
defs_conv
,
0
,
insn_uid
,
bi
)
cost
+=
DF_REG_DEF_COUNT
(
insn_uid
)
*
ix86_cost
->
mmxsse_to_integer
;
if
(
dump_file
)
fprintf
(
dump_file
,
"  Registers conversion cost: %d\n"
,
cost
)
;
gain
-=
cost
;
if
(
dump_file
)
fprintf
(
dump_file
,
"  Total gain: %d\n"
,
gain
)
;
return
gain
;
}
</s>


<s>
int
scalar_chain
::
convert
(
)
{
bitmap_iterator
bi
;
unsigned
id
;
int
converted_insns
=
0
;
if
(
!
dbg_cnt
(
stv_conversion
)
)
return
0
;
if
(
dump_file
)
fprintf
(
dump_file
,
"Converting chain #%d...\n"
,
chain_id
)
;
EXECUTE_IF_SET_IN_BITMAP
(
defs
,
0
,
id
,
bi
)
convert_reg
(
id
)
;
EXECUTE_IF_AND_COMPL_IN_BITMAP
(
defs_conv
,
defs
,
0
,
id
,
bi
)
make_vector_copies
(
id
)
;
EXECUTE_IF_SET_IN_BITMAP
(
insns
,
0
,
id
,
bi
)
{
convert_insn
(
DF_INSN_UID_GET
(
id
)
->
insn
)
;
converted_insns
++
;
}
return
converted_insns
;
}
</s>

Convert whole chain creating required register conversions and copies .


<s> static bool convertible_comparison_p ( rtx_insn * insn ) { if ( ! TARGET_SSE4_1 ) return false ; rtx def_set = single_set ( insn ) ; gcc_assert ( def_set ) ; rtx src = SET_SRC ( def_set ) ; rtx dst = SET_DEST ( def_set ) ; gcc_assert ( GET_CODE ( src ) == COMPARE ) ; if ( GET_CODE ( dst ) != REG || REGNO ( dst ) != FLAGS_REG || GET_MODE ( dst ) != CCZmode ) return false ; rtx op1 = XEXP ( src , 0 ) ; rtx op2 = XEXP ( src , 1 ) ; if ( op2 != CONST0_RTX ( GET_MODE ( op2 ) ) ) return false ; if ( GET_CODE ( op1 ) != IOR ) return false ; op2 = XEXP ( op1 , 1 ) ; op1 = XEXP ( op1 , 0 ) ; if ( ! SUBREG_P ( op1 ) || ! SUBREG_P ( op2 ) || GET_MODE ( op1 ) != SImode || GET_MODE ( op2 ) != SImode || ( ( SUBREG_BYTE ( op1 ) != 0 || SUBREG_BYTE ( op2 ) != GET_MODE_SIZE ( SImode ) ) && ( SUBREG_BYTE ( op2 ) != 0 || SUBREG_BYTE ( op1 ) != GET_MODE_SIZE ( SImode ) ) ) ) return false ; op1 = SUBREG_REG ( op1 ) ; op2 = SUBREG_REG ( op2 ) ; if ( op1 != op2 || ! REG_P ( op1 ) || GET_MODE ( op1 ) != DImode ) return false ; return true ; } </s>

Check if comparison INSN may be transformed into vector comparison . Currently we transform equality/inequality checks which look like : ( set ( reg : CCZ 17 flags ) ( compare : CCZ ( reg : TI x ) ( reg : TI y ) ) )


<s> void scalar_chain :: convert_insn ( rtx_insn * insn ) { rtx def_set = single_set ( insn ) ; rtx src = SET_SRC ( def_set ) ; rtx dst = SET_DEST ( def_set ) ; rtx subreg ; if ( MEM_P ( dst ) && ! REG_P ( src ) ) { rtx tmp = gen_reg_rtx ( DImode ) ; emit_conversion_insns ( gen_move_insn ( dst , tmp ) , insn ) ; dst = gen_rtx_SUBREG ( V2DImode , tmp , 0 ) ; } switch ( GET_CODE ( src ) ) { case PLUS : case MINUS : case IOR : case XOR : case AND : convert_op ( & XEXP ( src , 0 ) , insn ) ; convert_op ( & XEXP ( src , 1 ) , insn ) ; PUT_MODE ( src , V2DImode ) ; break ; case MEM : if ( ! REG_P ( dst ) ) convert_op ( & src , insn ) ; break ; case REG : if ( ! MEM_P ( dst ) ) convert_op ( & src , insn ) ; break ; case SUBREG : gcc_assert ( GET_MODE ( src ) == V2DImode ) ; break ; case COMPARE : src = SUBREG_REG ( XEXP ( XEXP ( src , 0 ) , 0 ) ) ; gcc_assert ( ( REG_P ( src ) && GET_MODE ( src ) == DImode ) || ( SUBREG_P ( src ) && GET_MODE ( src ) == V2DImode ) ) ; if ( REG_P ( src ) ) subreg = gen_rtx_SUBREG ( V2DImode , src , 0 ) ; else subreg = copy_rtx_if_shared ( src ) ; emit_insn_before ( gen_vec_interleave_lowv2di ( copy_rtx_if_shared ( subreg ) , copy_rtx_if_shared ( subreg ) , copy_rtx_if_shared ( subreg ) ) , insn ) ; dst = gen_rtx_REG ( CCmode , FLAGS_REG ) ; src = gen_rtx_UNSPEC ( CCmode , gen_rtvec ( 2 , copy_rtx_if_shared ( src ) , copy_rtx_if_shared ( src ) ) , UNSPEC_PTEST ) ; break ; default : gcc_unreachable ( ) ; } SET_SRC ( def_set ) = src ; SET_DEST ( def_set ) = dst ; PATTERN ( insn ) = def_set ; INSN_CODE ( insn ) = - 1 ; recog_memoized ( insn ) ; df_insn_rescan ( insn ) ; } </s>


"  Preloading operand for insn %d into r%d\n"

Convert operand OP in INSN . We should handle memory operands and uninitialized registers . All other register uses are converted during registers conversion .


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

Convert all definitions of register REGNO and fix its uses . Scalar copies may be created in case register is used in not convertible insn .


"Searching for mode conversion candidates...\n"

"There are no candidates for optimization.\n"

"Chain #%d conversion is not profitable\n"

Main STV pass function . Find and convert scalar instructions into vector mode when profitable .


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

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


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

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


<s> virtual unsigned int execute ( function * ) { return convert_scalars_to_vector ( ) ; } </s>


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

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


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

Compute number of immediate operands of an instruction .


"calling %qD with SSE calling convention without "

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

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


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


"calling %qD with SSE caling convention without "

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


<s> static rtx gen_pop ( rtx arg ) { if ( REG_P ( arg ) && GET_MODE ( arg ) != word_mode ) arg = gen_rtx_REG ( word_mode , REGNO ( arg ) ) ; return gen_rtx_SET ( arg , gen_rtx_MEM ( word_mode , gen_rtx_POST_INC ( Pmode , stack_pointer_rtx ) ) ) ; } </s>

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


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

Code to generate prologue and epilogue sequences


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

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


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

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


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

Return TRUE if Dispatch Scheduling is supported .


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

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


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

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


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

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


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

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


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

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


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

Return true if insn is a branch instruction .


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

Return true if insn is a prefetch instruction .


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

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


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

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


<s> static tree ix86_build_builtin_va_list ( void ) { if ( TARGET_64BIT ) { tree sysv_va_list , ms_va_list ; sysv_va_list = ix86_build_builtin_va_list_64 ( ) ; sysv_va_list_type_node = build_variant_type_copy ( sysv_va_list ) ; ms_va_list = build_pointer_type ( char_type_node ) ; ms_va_list_type_node = build_variant_type_copy ( ms_va_list ) ; return ( ix86_abi == MS_ABI ) ? ms_va_list : sysv_va_list ; } else { return build_pointer_type ( char_type_node ) ; } } </s>


<s> rtx ix86_build_signbit_mask ( machine_mode mode , bool vect , bool invert ) { machine_mode vec_mode , imode ; wide_int w ; rtx mask , v ; switch ( mode ) { case V16SImode : case V16SFmode : case V8SImode : case V4SImode : case V8SFmode : case V4SFmode : vec_mode = mode ; imode = SImode ; break ; case V8DImode : case V4DImode : case V2DImode : case V8DFmode : case V4DFmode : case V2DFmode : vec_mode = mode ; imode = DImode ; break ; case TImode : case TFmode : vec_mode = VOIDmode ; imode = TImode ; break ; default : gcc_unreachable ( ) ; } machine_mode inner_mode = GET_MODE_INNER ( mode ) ; w = wi :: set_bit_in_zero ( GET_MODE_BITSIZE ( inner_mode ) - 1 , GET_MODE_BITSIZE ( inner_mode ) ) ; if ( invert ) w = wi :: bit_not ( w ) ; mask = immed_wide_int_const ( w , imode ) ; mask = gen_lowpart ( inner_mode , mask ) ; if ( vec_mode == VOIDmode ) return force_reg ( inner_mode , mask ) ; v = ix86_build_const_vector ( vec_mode , vect , mask ) ; return force_reg ( vec_mode , v ) ; } </s>

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


<s> static tree ix86_builtin_reciprocal ( tree fndecl ) { switch ( DECL_FUNCTION_CODE ( fndecl ) ) { case IX86_BUILTIN_SQRTPS_NR : return ix86_get_builtin ( IX86_BUILTIN_RSQRTPS_NR ) ; case IX86_BUILTIN_SQRTPS_NR256 : return ix86_get_builtin ( IX86_BUILTIN_RSQRTPS_NR256 ) ; default : return NULL_TREE ; } } </s>

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


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


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

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


<s> static machine_mode ix86_cc_modes_compatible ( machine_mode m1 , machine_mode m2 ) { if ( m1 == m2 ) return m1 ; if ( GET_MODE_CLASS ( m1 ) != MODE_CC || GET_MODE_CLASS ( m2 ) != MODE_CC ) return VOIDmode ; if ( ( m1 == CCGCmode && m2 == CCGOCmode ) || ( m1 == CCGOCmode && m2 == CCGCmode ) ) return CCGCmode ; if ( m1 == CCZmode && ( m2 == CCGCmode || m2 == CCGOCmode ) ) return m2 ; else if ( m2 == CCZmode && ( m1 == CCGCmode || m1 == CCGOCmode ) ) return m1 ; switch ( m1 ) { default : gcc_unreachable ( ) ; case CCmode : case CCGCmode : case CCGOCmode : case CCNOmode : case CCAmode : case CCCmode : case CCOmode : case CCPmode : case CCSmode : case CCZmode : switch ( m2 ) { default : return VOIDmode ; case CCmode : case CCGCmode : case CCGOCmode : case CCNOmode : case CCAmode : case CCCmode : case CCOmode : case CCPmode : case CCSmode : case CCZmode : return CCmode ; } case CCFPmode : case CCFPUmode : return VOIDmode ; } } </s>

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


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

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


<s>
static
void
ix86_code_end
(
void
)
{
rtx
xops
[
2
]
;
int
regno
;
for
(
regno
=
AX_REG
;
regno
<=
SP_REG
;
regno
++
)
{
char
name
[
32
]
;
tree
decl
;
if
(
!
(
pic_labels_used
&
(
1
<<
regno
)
)
)
continue
;
get_pc_thunk_name
(
name
,
regno
)
;
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
[
text_coal_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
,
,
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
)
;
first_function_block_is_cold
=
false
;
final_start_function
(
emit_barrier
(
)
,
asm_out_file
,
1
)
;
if
(
TARGET_PAD_SHORT_FUNCTION
)
{
int
i
=
8
;
while
(
i
)
fputs
(
"\tnop\n"
,
asm_out_file
)
;
}
xops
[
0
]
=
gen_rtx_REG
(
Pmode
,
regno
)
;
xops
[
1
]
=
gen_rtx_MEM
(
Pmode
,
stack_pointer_rtx
)
;
output_asm_insn
(
"mov%z0\t{%1, %0|%0, %1}"
,
xops
)
;
output_asm_insn
(
"%!ret"
,
)
;
final_end_function
(
)
;
init_insn_lengths
(
)
;
free_after_compilation
(
cfun
)
;
set_cfun
(
)
;
current_function_decl
=
;
}
if
(
flag_split_stack
)
file_end_indicate_split_stack
(
)
;
}
</s>

This function generates code for -fpic that loads % ebx with the return address of the caller and then returns .


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

Update register usage after having seen the compiler flags .


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

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


<s> static void ix86_default_align ( struct gcc_options * opts ) { if ( opts -> x_align_loops == 0 ) { opts -> x_align_loops = processor_target_table [ ix86_tune ] . align_loop ; align_loops_max_skip = processor_target_table [ ix86_tune ] . align_loop_max_skip ; } if ( opts -> x_align_jumps == 0 ) { opts -> x_align_jumps = processor_target_table [ ix86_tune ] . align_jump ; align_jumps_max_skip = processor_target_table [ ix86_tune ] . align_jump_max_skip ; } if ( opts -> x_align_functions == 0 ) { opts -> x_align_functions = processor_target_table [ ix86_tune ] . align_func ; } } </s>

Default align_ * from the processor table .


<s> static void ix86_emit_binop ( enum rtx_code code , machine_mode mode , rtx dst , rtx src ) { rtx op , clob ; op = gen_rtx_SET ( dst , gen_rtx_fmt_ee ( code , mode , dst , src ) ) ; clob = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , FLAGS_REG ) ) ; emit_insn ( gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , op , clob ) ) ) ; } </s>

Emit x86 binary operand CODE in mode MODE , where the first operand matches destination . RTX includes clobber of FLAGS_REG .


<s> static void ix86_emit_cmove ( rtx dst , rtx src , enum rtx_code code , rtx op1 , rtx op2 ) { rtx t ; if ( TARGET_CMOVE ) { t = ix86_expand_compare ( code , op1 , op2 ) ; emit_insn ( gen_rtx_SET ( dst , gen_rtx_IF_THEN_ELSE ( GET_MODE ( dst ) , t , src , dst ) ) ) ; } else { rtx_code_label * nomove = gen_label_rtx ( ) ; emit_cmp_and_jump_insns ( op1 , op2 , reverse_condition ( code ) , const0_rtx , GET_MODE ( op1 ) , 1 , nomove ) ; emit_move_insn ( dst , src ) ; emit_label ( nomove ) ; } } </s>

Emit conditional move of SRC to DST with condition OP1 CODE OP2 .


<s> void ix86_emit_fp_unordered_jump ( rtx label ) { rtx reg = gen_reg_rtx ( HImode ) ; rtx temp ; emit_insn ( gen_x86_fnstsw_1 ( reg ) ) ; if ( TARGET_SAHF && ( TARGET_USE_SAHF || optimize_insn_for_size_p ( ) ) ) { emit_insn ( gen_x86_sahf_1 ( reg ) ) ; temp = gen_rtx_REG ( CCmode , FLAGS_REG ) ; temp = gen_rtx_UNORDERED ( VOIDmode , temp , const0_rtx ) ; } else { emit_insn ( gen_testqi_ext_ccno_0 ( reg , GEN_INT ( 0x04 ) ) ) ; temp = gen_rtx_REG ( CCNOmode , FLAGS_REG ) ; temp = gen_rtx_NE ( VOIDmode , temp , const0_rtx ) ; } temp = gen_rtx_IF_THEN_ELSE ( VOIDmode , temp , gen_rtx_LABEL_REF ( VOIDmode , label ) , pc_rtx ) ; temp = gen_rtx_SET ( pc_rtx , temp ) ; emit_jump_insn ( temp ) ; predict_jump ( REG_BR_PROB_BASE * 10 / 100 ) ; } </s>

Output code to perform a conditional jump to LABEL , if C2 flag in FP status register is set .


<s> void ix86_emit_i387_log1p ( rtx op0 , rtx op1 ) { rtx_code_label * label1 = gen_label_rtx ( ) ; rtx_code_label * label2 = gen_label_rtx ( ) ; rtx tmp = gen_reg_rtx ( XFmode ) ; rtx tmp2 = gen_reg_rtx ( XFmode ) ; rtx test ; emit_insn ( gen_absxf2 ( tmp , op1 ) ) ; test = gen_rtx_GE ( VOIDmode , tmp , const_double_from_real_value ( REAL_VALUE_ATOF ( "0.29289321881345247561810596348408353" , XFmode ) , XFmode ) ) ; emit_jump_insn ( gen_cbranchxf4 ( test , XEXP ( test , 0 ) , XEXP ( test , 1 ) , label1 ) ) ; emit_move_insn ( tmp2 , standard_80387_constant_rtx ( 4 ) ) ; emit_insn ( gen_fyl2xp1xf3_i387 ( op0 , op1 , tmp2 ) ) ; emit_jump ( label2 ) ; emit_label ( label1 ) ; emit_move_insn ( tmp , CONST1_RTX ( XFmode ) ) ; emit_insn ( gen_addxf3 ( tmp , op1 , tmp ) ) ; emit_move_insn ( tmp2 , standard_80387_constant_rtx ( 4 ) ) ; emit_insn ( gen_fyl2xxf3_i387 ( op0 , tmp , tmp2 ) ) ; emit_label ( label2 ) ; } </s>

Output code to perform a log1p XFmode calculation .


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

Emit code and notes for the LEAVE instruction .


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

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


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

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


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

Emit code to restore saved registers using POP insns .


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

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


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

Emit code to save registers in the prologue .


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

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


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

Emit a single register save at CFA - CFA_OFFSET .


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

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


<s> void ix86_emit_swdivsf ( rtx res , rtx a , rtx b , machine_mode mode ) { rtx x0 , x1 , e0 , e1 ; x0 = gen_reg_rtx ( mode ) ; e0 = gen_reg_rtx ( mode ) ; e1 = gen_reg_rtx ( mode ) ; x1 = gen_reg_rtx ( mode ) ; b = force_reg ( mode , b ) ; if ( mode == V16SFmode || mode == V8DFmode ) emit_insn ( gen_rtx_SET ( x0 , gen_rtx_UNSPEC ( mode , gen_rtvec ( 1 , b ) , UNSPEC_RCP14 ) ) ) ; else emit_insn ( gen_rtx_SET ( x0 , gen_rtx_UNSPEC ( mode , gen_rtvec ( 1 , b ) , UNSPEC_RCP ) ) ) ; emit_insn ( gen_rtx_SET ( e0 , gen_rtx_MULT ( mode , x0 , b ) ) ) ; emit_insn ( gen_rtx_SET ( e0 , gen_rtx_MULT ( mode , x0 , e0 ) ) ) ; emit_insn ( gen_rtx_SET ( e1 , gen_rtx_PLUS ( mode , x0 , x0 ) ) ) ; emit_insn ( gen_rtx_SET ( x1 , gen_rtx_MINUS ( mode , e1 , e0 ) ) ) ; emit_insn ( gen_rtx_SET ( res , gen_rtx_MULT ( mode , a , x1 ) ) ) ; } </s>


<s> void ix86_emit_swsqrtsf ( rtx res , rtx a , machine_mode mode , bool recip ) { rtx x0 , e0 , e1 , e2 , e3 , mthree , mhalf ; REAL_VALUE_TYPE r ; int unspec ; x0 = gen_reg_rtx ( mode ) ; e0 = gen_reg_rtx ( mode ) ; e1 = gen_reg_rtx ( mode ) ; e2 = gen_reg_rtx ( mode ) ; e3 = gen_reg_rtx ( mode ) ; real_from_integer ( & r , VOIDmode , - 3 , SIGNED ) ; mthree = const_double_from_real_value ( r , SFmode ) ; real_arithmetic ( & r , NEGATE_EXPR , & dconsthalf , NULL ) ; mhalf = const_double_from_real_value ( r , SFmode ) ; unspec = UNSPEC_RSQRT ; if ( VECTOR_MODE_P ( mode ) ) { mthree = ix86_build_const_vector ( mode , true , mthree ) ; mhalf = ix86_build_const_vector ( mode , true , mhalf ) ; if ( GET_MODE_SIZE ( mode ) == 64 ) unspec = UNSPEC_RSQRT14 ; } a = force_reg ( mode , a ) ; emit_insn ( gen_rtx_SET ( x0 , gen_rtx_UNSPEC ( mode , gen_rtvec ( 1 , a ) , unspec ) ) ) ; if ( ! recip ) { rtx zero = force_reg ( mode , CONST0_RTX ( mode ) ) ; rtx mask ; if ( VECTOR_MODE_P ( mode ) && GET_MODE_SIZE ( mode ) == 64 ) { mask = gen_reg_rtx ( HImode ) ; emit_insn ( gen_avx512f_cmpv16sf3 ( mask , zero , a , GEN_INT ( 0x4 ) ) ) ; emit_insn ( gen_avx512f_blendmv16sf ( x0 , zero , x0 , mask ) ) ; } else { mask = gen_reg_rtx ( mode ) ; emit_insn ( gen_rtx_SET ( mask , gen_rtx_NE ( mode , zero , a ) ) ) ; emit_insn ( gen_rtx_SET ( x0 , gen_rtx_AND ( mode , x0 , mask ) ) ) ; } } emit_insn ( gen_rtx_SET ( e0 , gen_rtx_MULT ( mode , x0 , a ) ) ) ; emit_insn ( gen_rtx_SET ( e1 , gen_rtx_MULT ( mode , e0 , x0 ) ) ) ; mthree = force_reg ( mode , mthree ) ; emit_insn ( gen_rtx_SET ( e2 , gen_rtx_PLUS ( mode , e1 , mthree ) ) ) ; mhalf = force_reg ( mode , mhalf ) ; if ( recip ) emit_insn ( gen_rtx_SET ( e3 , gen_rtx_MULT ( mode , x0 , mhalf ) ) ) ; else emit_insn ( gen_rtx_SET ( e3 , gen_rtx_MULT ( mode , e0 , mhalf ) ) ) ; emit_insn ( gen_rtx_SET ( res , gen_rtx_MULT ( mode , e2 , e3 ) ) ) ; } </s>

Output code to perform a Newton-Rhapson approximation of a single precision floating point [ reciprocal ] square root .


<s> rtx ix86_expand_adjust_ufix_to_sfix_si ( rtx val , rtx * xorp ) { REAL_VALUE_TYPE TWO31r ; rtx two31r , tmp [ 4 ] ; machine_mode mode = GET_MODE ( val ) ; machine_mode scalarmode = GET_MODE_INNER ( mode ) ; machine_mode intmode = GET_MODE_SIZE ( mode ) == 32 ? V8SImode : V4SImode ; rtx ( * cmp ) ( rtx , rtx , rtx , rtx ) ; int i ; for ( i = 0 ; i < 3 ; i ++ ) tmp [ i ] = gen_reg_rtx ( mode ) ; real_ldexp ( & TWO31r , & dconst1 , 31 ) ; two31r = const_double_from_real_value ( TWO31r , scalarmode ) ; two31r = ix86_build_const_vector ( mode , 1 , two31r ) ; two31r = force_reg ( mode , two31r ) ; switch ( mode ) { case V8SFmode : cmp = gen_avx_maskcmpv8sf3 ; break ; case V4SFmode : cmp = gen_sse_maskcmpv4sf3 ; break ; case V4DFmode : cmp = gen_avx_maskcmpv4df3 ; break ; case V2DFmode : cmp = gen_sse2_maskcmpv2df3 ; break ; default : gcc_unreachable ( ) ; } tmp [ 3 ] = gen_rtx_LE ( mode , two31r , val ) ; emit_insn ( cmp ( tmp [ 0 ] , two31r , val , tmp [ 3 ] ) ) ; tmp [ 1 ] = expand_simple_binop ( mode , AND , tmp [ 0 ] , two31r , tmp [ 1 ] , 0 , OPTAB_DIRECT ) ; if ( intmode == V4SImode || TARGET_AVX2 ) * xorp = expand_simple_binop ( intmode , ASHIFT , gen_lowpart ( intmode , tmp [ 0 ] ) , GEN_INT ( 31 ) , NULL_RTX , 0 , OPTAB_DIRECT ) ; else { rtx two31 = GEN_INT ( HOST_WIDE_INT_1U << 31 ) ; two31 = ix86_build_const_vector ( intmode , 1 , two31 ) ; * xorp = expand_simple_binop ( intmode , AND , gen_lowpart ( intmode , tmp [ 0 ] ) , two31 , NULL_RTX , 0 , OPTAB_DIRECT ) ; } return expand_simple_binop ( mode , MINUS , val , tmp [ 1 ] , tmp [ 2 ] , 0 , OPTAB_DIRECT ) ; } </s>

Adjust a V * SFmode/V * DFmode value VAL so that * sfix_trunc * resp . fix_trunc * pattern can be used on it instead of fixuns_trunc * . This is done by doing just signed conversion if < 0x1p31 , and otherwise by subtracting 0x1p31 first and xoring in 0x80000000 from * XORP afterwards .


<s> void ix86_expand_copysign ( rtx operands [ ] ) { machine_mode mode , vmode ; rtx dest , op0 , op1 , mask , nmask ; dest = operands [ 0 ] ; op0 = operands [ 1 ] ; op1 = operands [ 2 ] ; mode = GET_MODE ( dest ) ; if ( mode == SFmode ) vmode = V4SFmode ; else if ( mode == DFmode ) vmode = V2DFmode ; else vmode = mode ; if ( CONST_DOUBLE_P ( op0 ) ) { rtx ( * copysign_insn ) ( rtx , rtx , rtx , rtx ) ; if ( real_isneg ( CONST_DOUBLE_REAL_VALUE ( op0 ) ) ) op0 = simplify_unary_operation ( ABS , mode , op0 , mode ) ; if ( mode == SFmode || mode == DFmode ) { if ( op0 == CONST0_RTX ( mode ) ) op0 = CONST0_RTX ( vmode ) ; else { rtx v = ix86_build_const_vector ( vmode , false , op0 ) ; op0 = force_reg ( vmode , v ) ; } } else if ( op0 != CONST0_RTX ( mode ) ) op0 = force_reg ( mode , op0 ) ; mask = ix86_build_signbit_mask ( vmode , 0 , 0 ) ; if ( mode == SFmode ) copysign_insn = gen_copysignsf3_const ; else if ( mode == DFmode ) copysign_insn = gen_copysigndf3_const ; else copysign_insn = gen_copysigntf3_const ; emit_insn ( copysign_insn ( dest , op0 , op1 , mask ) ) ; } else { rtx ( * copysign_insn ) ( rtx , rtx , rtx , rtx , rtx , rtx ) ; nmask = ix86_build_signbit_mask ( vmode , 0 , 1 ) ; mask = ix86_build_signbit_mask ( vmode , 0 , 0 ) ; if ( mode == SFmode ) copysign_insn = gen_copysignsf3_var ; else if ( mode == DFmode ) copysign_insn = gen_copysigndf3_var ; else copysign_insn = gen_copysigntf3_var ; emit_insn ( copysign_insn ( dest , NULL_RTX , op0 , op1 , nmask , mask ) ) ; } } </s>

Expand a copysign operation . Special case operand 0 being a constant .


<s> void ix86_expand_floorceildf_32 ( rtx operand0 , rtx operand1 , bool do_floor ) { machine_mode mode = GET_MODE ( operand0 ) ; rtx xa , TWO52 , tmp , one , res , mask ; rtx_code_label * label ; TWO52 = ix86_gen_TWO52 ( mode ) ; res = gen_reg_rtx ( mode ) ; emit_move_insn ( res , operand1 ) ; xa = ix86_expand_sse_fabs ( res , & mask ) ; label = ix86_expand_sse_compare_and_jump ( UNLE , TWO52 , xa , false ) ; xa = expand_simple_binop ( mode , PLUS , xa , TWO52 , NULL_RTX , 0 , OPTAB_DIRECT ) ; xa = expand_simple_binop ( mode , MINUS , xa , TWO52 , xa , 0 , OPTAB_DIRECT ) ; ix86_sse_copysign_to_positive ( xa , xa , res , mask ) ; one = force_reg ( mode , const_double_from_real_value ( do_floor ? dconst1 : dconstm1 , mode ) ) ; tmp = ix86_expand_sse_compare_mask ( UNGT , xa , res , ! do_floor ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_AND ( mode , one , tmp ) ) ) ; tmp = expand_simple_binop ( mode , MINUS , xa , tmp , NULL_RTX , 0 , OPTAB_DIRECT ) ; emit_move_insn ( res , tmp ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; emit_move_insn ( operand0 , res ) ; } </s>

Expand SSE2 sequence for computing floor or ceil from OPERAND1 storing into OPERAND0 .


<s> void ix86_expand_fp_absneg_operator ( enum rtx_code code , machine_mode mode , rtx operands [ ] ) { rtx mask , set , dst , src ; bool use_sse = false ; bool vector_mode = VECTOR_MODE_P ( mode ) ; machine_mode vmode = mode ; if ( vector_mode ) use_sse = true ; else if ( mode == TFmode ) use_sse = true ; else if ( TARGET_SSE_MATH ) { use_sse = SSE_FLOAT_MODE_P ( mode ) ; if ( mode == SFmode ) vmode = V4SFmode ; else if ( mode == DFmode ) vmode = V2DFmode ; } if ( use_sse ) mask = ix86_build_signbit_mask ( vmode , vector_mode , code == ABS ) ; else mask = NULL_RTX ; dst = operands [ 0 ] ; src = operands [ 1 ] ; set = gen_rtx_fmt_e ( code , mode , src ) ; set = gen_rtx_SET ( dst , set ) ; if ( mask ) { rtx use , clob ; rtvec par ; use = gen_rtx_USE ( VOIDmode , mask ) ; if ( vector_mode ) par = gen_rtvec ( 2 , set , use ) ; else { clob = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , FLAGS_REG ) ) ; par = gen_rtvec ( 3 , set , use , clob ) ; } emit_insn ( gen_rtx_PARALLEL ( VOIDmode , par ) ) ; } else emit_insn ( set ) ; } </s>

Generate code for floating point ABS or NEG .


<s> bool ix86_expand_pextr ( rtx * operands ) { rtx dst = operands [ 0 ] ; rtx src = operands [ 1 ] ; unsigned int size = INTVAL ( operands [ 2 ] ) ; unsigned int pos = INTVAL ( operands [ 3 ] ) ; if ( SUBREG_P ( dst ) ) { if ( SUBREG_BYTE ( dst ) > 0 ) return false ; dst = SUBREG_REG ( dst ) ; } if ( SUBREG_P ( src ) ) { pos += SUBREG_BYTE ( src ) * BITS_PER_UNIT ; src = SUBREG_REG ( src ) ; } switch ( GET_MODE ( src ) ) { case V16QImode : case V8HImode : case V4SImode : case V2DImode : case V1TImode : case TImode : { machine_mode srcmode , dstmode ; rtx d , pat ; dstmode = mode_for_size ( size , MODE_INT , 0 ) ; switch ( dstmode ) { case QImode : if ( ! TARGET_SSE4_1 ) return false ; srcmode = V16QImode ; break ; case HImode : if ( ! TARGET_SSE2 ) return false ; srcmode = V8HImode ; break ; case SImode : if ( ! TARGET_SSE4_1 ) return false ; srcmode = V4SImode ; break ; case DImode : gcc_assert ( TARGET_64BIT ) ; if ( ! TARGET_SSE4_1 ) return false ; srcmode = V2DImode ; break ; default : return false ; } if ( pos & ( size - 1 ) ) return false ; if ( GET_MODE ( dst ) == dstmode ) d = dst ; else d = gen_reg_rtx ( dstmode ) ; pat = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 1 , GEN_INT ( pos / size ) ) ) ; pat = gen_rtx_VEC_SELECT ( dstmode , gen_lowpart ( srcmode , src ) , pat ) ; if ( dstmode == QImode || dstmode == HImode ) { pat = gen_rtx_ZERO_EXTEND ( SImode , pat ) ; d = gen_lowpart ( SImode , d ) ; } emit_insn ( gen_rtx_SET ( d , pat ) ) ; if ( d != dst ) emit_move_insn ( dst , gen_lowpart ( GET_MODE ( dst ) , d ) ) ; return true ; } default : return false ; } } </s>

Expand an extract from a vector register through pextr insn . Return true if successful .


<s> bool ix86_expand_pinsr ( rtx * operands ) { rtx dst = operands [ 0 ] ; rtx src = operands [ 3 ] ; unsigned int size = INTVAL ( operands [ 1 ] ) ; unsigned int pos = INTVAL ( operands [ 2 ] ) ; if ( SUBREG_P ( dst ) ) { pos += SUBREG_BYTE ( dst ) * BITS_PER_UNIT ; dst = SUBREG_REG ( dst ) ; } switch ( GET_MODE ( dst ) ) { case V16QImode : case V8HImode : case V4SImode : case V2DImode : case V1TImode : case TImode : { machine_mode srcmode , dstmode ; rtx ( * pinsr ) ( rtx , rtx , rtx , rtx ) ; rtx d ; srcmode = mode_for_size ( size , MODE_INT , 0 ) ; switch ( srcmode ) { case QImode : if ( ! TARGET_SSE4_1 ) return false ; dstmode = V16QImode ; pinsr = gen_sse4_1_pinsrb ; break ; case HImode : if ( ! TARGET_SSE2 ) return false ; dstmode = V8HImode ; pinsr = gen_sse2_pinsrw ; break ; case SImode : if ( ! TARGET_SSE4_1 ) return false ; dstmode = V4SImode ; pinsr = gen_sse4_1_pinsrd ; break ; case DImode : gcc_assert ( TARGET_64BIT ) ; if ( ! TARGET_SSE4_1 ) return false ; dstmode = V2DImode ; pinsr = gen_sse4_1_pinsrq ; break ; default : return false ; } if ( pos & ( size - 1 ) ) return false ; if ( SUBREG_P ( src ) ) { unsigned int srcpos = SUBREG_BYTE ( src ) ; if ( srcpos > 0 ) { rtx extr_ops [ 4 ] ; extr_ops [ 0 ] = gen_reg_rtx ( srcmode ) ; extr_ops [ 1 ] = gen_lowpart ( srcmode , SUBREG_REG ( src ) ) ; extr_ops [ 2 ] = GEN_INT ( size ) ; extr_ops [ 3 ] = GEN_INT ( srcpos * BITS_PER_UNIT ) ; if ( ! ix86_expand_pextr ( extr_ops ) ) return false ; src = extr_ops [ 0 ] ; } else src = gen_lowpart ( srcmode , SUBREG_REG ( src ) ) ; } if ( GET_MODE ( dst ) == dstmode ) d = dst ; else d = gen_reg_rtx ( dstmode ) ; emit_insn ( pinsr ( d , gen_lowpart ( dstmode , dst ) , gen_lowpart ( srcmode , src ) , GEN_INT ( 1 << ( pos / size ) ) ) ) ; if ( d != dst ) emit_move_insn ( dst , gen_lowpart ( GET_MODE ( dst ) , d ) ) ; return true ; } default : return false ; } } </s>

Expand an insert into a vector register through pinsr insn . Return true if successful .


<s> void ix86_expand_rounddf_32 ( rtx operand0 , rtx operand1 ) { machine_mode mode = GET_MODE ( operand0 ) ; rtx xa , xa2 , dxa , TWO52 , tmp , half , mhalf , one , res , mask ; rtx_code_label * label ; TWO52 = ix86_gen_TWO52 ( mode ) ; res = gen_reg_rtx ( mode ) ; emit_move_insn ( res , operand1 ) ; xa = ix86_expand_sse_fabs ( res , & mask ) ; label = ix86_expand_sse_compare_and_jump ( UNLE , TWO52 , xa , false ) ; xa2 = expand_simple_binop ( mode , PLUS , xa , TWO52 , NULL_RTX , 0 , OPTAB_DIRECT ) ; xa2 = expand_simple_binop ( mode , MINUS , xa2 , TWO52 , xa2 , 0 , OPTAB_DIRECT ) ; dxa = expand_simple_binop ( mode , MINUS , xa2 , xa , NULL_RTX , 0 , OPTAB_DIRECT ) ; half = force_reg ( mode , const_double_from_real_value ( dconsthalf , mode ) ) ; one = expand_simple_binop ( mode , PLUS , half , half , NULL_RTX , 0 , OPTAB_DIRECT ) ; mhalf = expand_simple_binop ( mode , MINUS , half , one , NULL_RTX , 0 , OPTAB_DIRECT ) ; tmp = gen_reg_rtx ( mode ) ; tmp = ix86_expand_sse_compare_mask ( UNGT , dxa , half , false ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_AND ( mode , one , tmp ) ) ) ; xa2 = expand_simple_binop ( mode , MINUS , xa2 , tmp , NULL_RTX , 0 , OPTAB_DIRECT ) ; tmp = ix86_expand_sse_compare_mask ( UNGE , mhalf , dxa , false ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_AND ( mode , one , tmp ) ) ) ; xa2 = expand_simple_binop ( mode , PLUS , xa2 , tmp , NULL_RTX , 0 , OPTAB_DIRECT ) ; ix86_sse_copysign_to_positive ( res , xa2 , force_reg ( mode , operand1 ) , mask ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; emit_move_insn ( operand0 , res ) ; } </s>

Expand SSE sequence for computing round from OPERAND1 storing into OPERAND0 . Sequence that works without relying on DImode truncation via cvttsd2siq that is only available on 64bit targets .


<s> void ix86_expand_round_sse4 ( rtx op0 , rtx op1 ) { machine_mode mode = GET_MODE ( op0 ) ; rtx e1 , e2 , res , half ; const struct real_format * fmt ; REAL_VALUE_TYPE pred_half , half_minus_pred_half ; rtx ( * gen_copysign ) ( rtx , rtx , rtx ) ; rtx ( * gen_round ) ( rtx , rtx , rtx ) ; switch ( mode ) { case SFmode : gen_copysign = gen_copysignsf3 ; gen_round = gen_sse4_1_roundsf2 ; break ; case DFmode : gen_copysign = gen_copysigndf3 ; gen_round = gen_sse4_1_rounddf2 ; break ; default : gcc_unreachable ( ) ; } fmt = REAL_MODE_FORMAT ( mode ) ; real_2expN ( & half_minus_pred_half , - ( fmt -> p ) - 1 , mode ) ; real_arithmetic ( & pred_half , MINUS_EXPR , & dconsthalf , & half_minus_pred_half ) ; half = const_double_from_real_value ( pred_half , mode ) ; e1 = gen_reg_rtx ( mode ) ; emit_insn ( gen_copysign ( e1 , half , op1 ) ) ; e2 = expand_simple_binop ( mode , PLUS , op1 , e1 , NULL_RTX , 0 , OPTAB_DIRECT ) ; res = gen_reg_rtx ( mode ) ; emit_insn ( gen_round ( res , e2 , GEN_INT ( ROUND_TRUNC ) ) ) ; emit_move_insn ( op0 , res ) ; } </s>

Expand SSE sequence for computing round from OP1 storing into OP0 using sse4 round insn .


<s> void ix86_expand_sse2_abs ( rtx target , rtx input ) { machine_mode mode = GET_MODE ( target ) ; rtx tmp0 , tmp1 , x ; switch ( mode ) { case V4SImode : tmp0 = expand_simple_binop ( mode , ASHIFTRT , input , GEN_INT ( GET_MODE_UNIT_BITSIZE ( mode ) - 1 ) , NULL , 0 , OPTAB_DIRECT ) ; tmp1 = expand_simple_binop ( mode , XOR , tmp0 , input , NULL , 0 , OPTAB_DIRECT ) ; x = expand_simple_binop ( mode , MINUS , tmp1 , tmp0 , target , 0 , OPTAB_DIRECT ) ; break ; case V8HImode : tmp0 = expand_unop ( mode , neg_optab , input , NULL_RTX , 0 ) ; x = expand_simple_binop ( mode , SMAX , tmp0 , input , target , 0 , OPTAB_DIRECT ) ; break ; case V16QImode : tmp0 = expand_unop ( mode , neg_optab , input , NULL_RTX , 0 ) ; x = expand_simple_binop ( V16QImode , UMIN , tmp0 , input , target , 0 , OPTAB_DIRECT ) ; break ; default : gcc_unreachable ( ) ; } if ( x != target ) emit_move_insn ( target , x ) ; } </s>

Calculate integer abs ( ) using only SSE2 instructions .


<s> static rtx ix86_expand_sse_cmp ( rtx dest , enum rtx_code code , rtx cmp_op0 , rtx cmp_op1 , rtx op_true , rtx op_false ) { machine_mode mode = GET_MODE ( dest ) ; machine_mode cmp_ops_mode = GET_MODE ( cmp_op0 ) ; machine_mode cmp_mode ; bool maskcmp = false ; rtx x ; if ( GET_MODE_SIZE ( cmp_ops_mode ) == 64 ) { cmp_mode = mode_for_size ( GET_MODE_NUNITS ( cmp_ops_mode ) , MODE_INT , 0 ) ; gcc_assert ( cmp_mode != BLKmode ) ; maskcmp = true ; } else cmp_mode = cmp_ops_mode ; cmp_op0 = force_reg ( cmp_ops_mode , cmp_op0 ) ; if ( ! nonimmediate_operand ( cmp_op1 , cmp_ops_mode ) ) cmp_op1 = force_reg ( cmp_ops_mode , cmp_op1 ) ; if ( optimize || ( op_true && reg_overlap_mentioned_p ( dest , op_true ) ) || ( op_false && reg_overlap_mentioned_p ( dest , op_false ) ) ) dest = gen_reg_rtx ( maskcmp ? cmp_mode : mode ) ; if ( maskcmp && ( code == GT || code == EQ ) ) { rtx ( * gen ) ( rtx , rtx , rtx ) ; switch ( cmp_ops_mode ) { case V64QImode : gcc_assert ( TARGET_AVX512BW ) ; gen = code == GT ? gen_avx512bw_gtv64qi3 : gen_avx512bw_eqv64qi3_1 ; break ; case V32HImode : gcc_assert ( TARGET_AVX512BW ) ; gen = code == GT ? gen_avx512bw_gtv32hi3 : gen_avx512bw_eqv32hi3_1 ; break ; case V16SImode : gen = code == GT ? gen_avx512f_gtv16si3 : gen_avx512f_eqv16si3_1 ; break ; case V8DImode : gen = code == GT ? gen_avx512f_gtv8di3 : gen_avx512f_eqv8di3_1 ; break ; default : gen = NULL ; } if ( gen ) { emit_insn ( gen ( dest , cmp_op0 , cmp_op1 ) ) ; return dest ; } } x = gen_rtx_fmt_ee ( code , cmp_mode , cmp_op0 , cmp_op1 ) ; if ( cmp_mode != mode && ! maskcmp ) { x = force_reg ( cmp_ops_mode , x ) ; convert_move ( dest , x , false ) ; } else emit_insn ( gen_rtx_SET ( dest , x ) ) ; return dest ; } </s>

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


<s> static rtx_code_label * ix86_expand_sse_compare_and_jump ( enum rtx_code code , rtx op0 , rtx op1 , bool swap_operands ) { machine_mode fpcmp_mode = ix86_fp_compare_mode ( code ) ; rtx_code_label * label ; rtx tmp ; if ( swap_operands ) std :: swap ( op0 , op1 ) ; label = gen_label_rtx ( ) ; tmp = gen_rtx_REG ( fpcmp_mode , FLAGS_REG ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_COMPARE ( fpcmp_mode , op0 , op1 ) ) ) ; tmp = gen_rtx_fmt_ee ( code , VOIDmode , tmp , const0_rtx ) ; tmp = gen_rtx_IF_THEN_ELSE ( VOIDmode , tmp , gen_rtx_LABEL_REF ( VOIDmode , label ) , pc_rtx ) ; tmp = emit_jump_insn ( gen_rtx_SET ( pc_rtx , tmp ) ) ; JUMP_LABEL ( tmp ) = label ; return label ; } </s>

Expands a comparison of OP0 with OP1 using comparison code CODE , swapping the operands if SWAP_OPERANDS is true . The expanded code is a forward jump to a newly created label in case the comparison is true . The generated label rtx is returned .


<s> static bool ix86_expand_sse_fp_minmax ( rtx dest , enum rtx_code code , rtx cmp_op0 , rtx cmp_op1 , rtx if_true , rtx if_false ) { machine_mode mode ; bool is_min ; rtx tmp ; if ( code == LT ) ; else if ( code == UNGE ) std :: swap ( if_true , if_false ) ; else return false ; if ( rtx_equal_p ( cmp_op0 , if_true ) && rtx_equal_p ( cmp_op1 , if_false ) ) is_min = true ; else if ( rtx_equal_p ( cmp_op1 , if_true ) && rtx_equal_p ( cmp_op0 , if_false ) ) is_min = false ; else return false ; mode = GET_MODE ( dest ) ; if ( ! flag_finite_math_only || ! flag_unsafe_math_optimizations ) { int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX ; rtvec v ; if_true = force_reg ( mode , if_true ) ; v = gen_rtvec ( 2 , if_true , if_false ) ; tmp = gen_rtx_UNSPEC ( mode , v , u ) ; } else { code = is_min ? SMIN : SMAX ; tmp = gen_rtx_fmt_ee ( code , mode , if_true , if_false ) ; } emit_insn ( gen_rtx_SET ( dest , tmp ) ) ; return true ; } </s>

Detect conditional moves that exactly match min/max operational semantics . Note that this is IEEE safe , as long as we do n't interchange the operands . Returns FALSE if this conditional move does n't match a MIN/MAX , and TRUE if the operation is successful and instructions are emitted .


<s> bool ix86_expand_strlen ( rtx out , rtx src , rtx eoschar , rtx align ) { rtx addr , scratch1 , scratch2 , scratch3 , scratch4 ; if ( TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1 && ! TARGET_INLINE_ALL_STRINGOPS && ! optimize_insn_for_size_p ( ) && ( ! CONST_INT_P ( align ) || INTVAL ( align ) < 4 ) ) return false ; addr = force_reg ( Pmode , XEXP ( src , 0 ) ) ; scratch1 = gen_reg_rtx ( Pmode ) ; if ( TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1 && ! optimize_insn_for_size_p ( ) ) { emit_move_insn ( out , addr ) ; ix86_expand_strlensi_unroll_1 ( out , src , align ) ; emit_insn ( ix86_gen_sub3 ( out , out , addr ) ) ; } else { rtx unspec ; if ( fixed_regs [ AX_REG ] || fixed_regs [ CX_REG ] || fixed_regs [ DI_REG ] ) return false ; if ( ! ADDR_SPACE_GENERIC_P ( MEM_ADDR_SPACE ( src ) ) ) return false ; scratch2 = gen_reg_rtx ( Pmode ) ; scratch3 = gen_reg_rtx ( Pmode ) ; scratch4 = force_reg ( Pmode , constm1_rtx ) ; emit_move_insn ( scratch3 , addr ) ; eoschar = force_reg ( QImode , eoschar ) ; src = replace_equiv_address_nv ( src , scratch3 ) ; unspec = gen_rtx_UNSPEC ( Pmode , gen_rtvec ( 4 , src , eoschar , align , scratch4 ) , UNSPEC_SCAS ) ; emit_insn ( gen_strlenqi_1 ( scratch1 , scratch3 , unspec ) ) ; emit_insn ( ix86_gen_one_cmpl2 ( scratch2 , scratch1 ) ) ; emit_insn ( ix86_gen_add3 ( out , scratch2 , constm1_rtx ) ) ; } return true ; } </s>


<s> void ix86_expand_vector_init ( bool mmx_ok , rtx target , rtx vals ) { machine_mode mode = GET_MODE ( target ) ; machine_mode inner_mode = GET_MODE_INNER ( mode ) ; int n_elts = GET_MODE_NUNITS ( mode ) ; int n_var = 0 , one_var = - 1 ; bool all_same = true , all_const_zero = true ; int i ; rtx x ; for ( i = 0 ; i < n_elts ; ++ i ) { x = XVECEXP ( vals , 0 , i ) ; if ( ! ( CONST_SCALAR_INT_P ( x ) || CONST_DOUBLE_P ( x ) || CONST_FIXED_P ( x ) ) ) n_var ++ , one_var = i ; else if ( x != CONST0_RTX ( inner_mode ) ) all_const_zero = false ; if ( i > 0 && ! rtx_equal_p ( x , XVECEXP ( vals , 0 , 0 ) ) ) all_same = false ; } if ( n_var == 0 ) { emit_move_insn ( target , gen_rtx_CONST_VECTOR ( mode , XVEC ( vals , 0 ) ) ) ; return ; } if ( all_same && ix86_expand_vector_init_duplicate ( mmx_ok , mode , target , XVECEXP ( vals , 0 , 0 ) ) ) return ; if ( n_var == 1 ) { if ( all_const_zero && ix86_expand_vector_init_one_nonzero ( mmx_ok , mode , target , XVECEXP ( vals , 0 , one_var ) , one_var ) ) return ; if ( ix86_expand_vector_init_one_var ( mmx_ok , mode , target , vals , one_var ) ) return ; } ix86_expand_vector_init_general ( mmx_ok , mode , target , vals ) ; } </s>

Initialize vector TARGET via VALS . Suppress the use of MMX instructions unless MMX_OK is true .


<s> void ix86_expand_vector_logical_operator ( enum rtx_code code , machine_mode mode , rtx operands [ ] ) { rtx op1 = NULL_RTX , op2 = NULL_RTX ; if ( SUBREG_P ( operands [ 1 ] ) ) { op1 = operands [ 1 ] ; op2 = operands [ 2 ] ; } else if ( SUBREG_P ( operands [ 2 ] ) ) { op1 = operands [ 2 ] ; op2 = operands [ 1 ] ; } if ( op1 && ! TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL && ( SUBREG_P ( op2 ) || GET_CODE ( op2 ) == CONST_VECTOR ) && GET_MODE_CLASS ( GET_MODE ( SUBREG_REG ( op1 ) ) ) == MODE_VECTOR_FLOAT && GET_MODE_SIZE ( GET_MODE ( SUBREG_REG ( op1 ) ) ) == GET_MODE_SIZE ( mode ) && SUBREG_BYTE ( op1 ) == 0 && ( GET_CODE ( op2 ) == CONST_VECTOR || ( GET_MODE ( SUBREG_REG ( op1 ) ) == GET_MODE ( SUBREG_REG ( op2 ) ) && SUBREG_BYTE ( op2 ) == 0 ) ) && can_create_pseudo_p ( ) ) { rtx dst ; switch ( GET_MODE ( SUBREG_REG ( op1 ) ) ) { case V4SFmode : case V8SFmode : case V16SFmode : case V2DFmode : case V4DFmode : case V8DFmode : dst = gen_reg_rtx ( GET_MODE ( SUBREG_REG ( op1 ) ) ) ; if ( GET_CODE ( op2 ) == CONST_VECTOR ) { op2 = gen_lowpart ( GET_MODE ( dst ) , op2 ) ; op2 = force_reg ( GET_MODE ( dst ) , op2 ) ; } else { op1 = operands [ 1 ] ; op2 = SUBREG_REG ( operands [ 2 ] ) ; if ( ! vector_operand ( op2 , GET_MODE ( dst ) ) ) op2 = force_reg ( GET_MODE ( dst ) , op2 ) ; } op1 = SUBREG_REG ( op1 ) ; if ( ! vector_operand ( op1 , GET_MODE ( dst ) ) ) op1 = force_reg ( GET_MODE ( dst ) , op1 ) ; emit_insn ( gen_rtx_SET ( dst , gen_rtx_fmt_ee ( code , GET_MODE ( dst ) , op1 , op2 ) ) ) ; emit_move_insn ( operands [ 0 ] , gen_lowpart ( mode , dst ) ) ; return ; default : break ; } } if ( ! vector_operand ( operands [ 1 ] , mode ) ) operands [ 1 ] = force_reg ( mode , operands [ 1 ] ) ; if ( ! vector_operand ( operands [ 2 ] , mode ) ) operands [ 2 ] = force_reg ( mode , operands [ 2 ] ) ; ix86_fixup_binary_operands_no_copy ( code , mode , operands ) ; emit_insn ( gen_rtx_SET ( operands [ 0 ] , gen_rtx_fmt_ee ( code , mode , operands [ 1 ] , operands [ 2 ] ) ) ) ; } </s>

Expand vector logical operation CODE ( AND , IOR , XOR ) in MODE with the given OPERANDS .


The guts of ix86_expand_vec_perm_const , also used by the ok hook . With all of the interface bits taken care of , perform the expansion in D and return true on success .


Finalize stack_realign_needed flag , which will guide prologue/epilogue to be generated in correct form .


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

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


<s> static int ix86_fp_cmp_code_to_pcmp_immediate ( enum rtx_code code ) { switch ( code ) { case EQ : return 0x08 ; case NE : return 0x04 ; case GT : return 0x16 ; case LE : return 0x1a ; case GE : return 0x15 ; case LT : return 0x19 ; default : gcc_unreachable ( ) ; } } </s>

Helper for ix86_cmp_code_to_pcmp_immediate for fp modes .


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


<s> static rtx ix86_function_arg ( cumulative_args_t cum_v , machine_mode omode , const_tree type , bool named ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; machine_mode mode = omode ; HOST_WIDE_INT bytes , words ; rtx arg ; if ( ( type && POINTER_BOUNDS_TYPE_P ( type ) ) || POINTER_BOUNDS_MODE_P ( mode ) ) { if ( cum -> bnds_in_bt ) arg = NULL ; else if ( cum -> bnd_regno <= LAST_BND_REG ) arg = gen_rtx_REG ( BNDmode , cum -> bnd_regno ) ; else arg = GEN_INT ( cum -> bnd_regno - LAST_BND_REG - 1 ) ; return arg ; } if ( mode == BLKmode ) bytes = int_size_in_bytes ( type ) ; else bytes = GET_MODE_SIZE ( mode ) ; words = CEIL ( bytes , UNITS_PER_WORD ) ; if ( type && TREE_CODE ( type ) == VECTOR_TYPE ) mode = type_natural_mode ( type , cum , false ) ; if ( TARGET_64BIT ) { enum calling_abi call_abi = cum ? cum -> call_abi : ix86_abi ; if ( call_abi == MS_ABI ) arg = function_arg_ms_64 ( cum , mode , omode , named , bytes ) ; else arg = function_arg_64 ( cum , mode , omode , type , named ) ; } else arg = function_arg_32 ( cum , mode , omode , type , bytes , words ) ; return arg ; } </s>

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


<s> static void ix86_function_arg_advance ( cumulative_args_t cum_v , machine_mode mode , const_tree type , bool named ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; HOST_WIDE_INT bytes , words ; int nregs ; if ( mode == BLKmode ) bytes = int_size_in_bytes ( type ) ; else bytes = GET_MODE_SIZE ( mode ) ; words = CEIL ( bytes , UNITS_PER_WORD ) ; if ( type ) mode = type_natural_mode ( type , NULL , false ) ; if ( ( type && POINTER_BOUNDS_TYPE_P ( type ) ) || POINTER_BOUNDS_MODE_P ( mode ) ) { if ( cum -> bnds_in_bt ) { cum -> bnds_in_bt -- ; return ; } if ( cum -> force_bnd_pass ) cum -> force_bnd_pass -- ; cum -> bnd_regno ++ ; return ; } cum -> bnds_in_bt = 0 ; if ( cum -> force_bnd_pass ) { cum -> bnd_regno += cum -> force_bnd_pass ; cum -> force_bnd_pass = 0 ; } if ( TARGET_64BIT ) { enum calling_abi call_abi = cum ? cum -> call_abi : ix86_abi ; if ( call_abi == MS_ABI ) nregs = function_arg_advance_ms_64 ( cum , bytes , words ) ; else nregs = function_arg_advance_64 ( cum , mode , type , words , named ) ; } else nregs = function_arg_advance_32 ( cum , mode , type , bytes , words ) ; if ( cum -> stdarg ) cum -> force_bnd_pass = nregs ; if ( ! nregs ) cum -> bnds_in_bt = chkp_type_bounds_count ( type ) ; } </s>

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


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

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


<s> static bool ix86_function_ok_for_sibcall ( tree decl , tree exp ) { tree type , decl_or_type ; rtx a , b ; bool bind_global = decl && ! targetm . binds_local_p ( decl ) ; if ( ! TARGET_MACHO && ! TARGET_64BIT && flag_pic && flag_plt && bind_global ) return false ; if ( ix86_minimum_incoming_stack_boundary ( true ) < PREFERRED_STACK_BOUNDARY ) return false ; if ( decl ) { decl_or_type = decl ; type = TREE_TYPE ( decl ) ; } else { type = CALL_EXPR_FN ( exp ) ; type = TREE_TYPE ( type ) ; type = TREE_TYPE ( type ) ; decl_or_type = type ; } a = ix86_function_value ( TREE_TYPE ( exp ) , decl_or_type , false ) ; b = ix86_function_value ( TREE_TYPE ( DECL_RESULT ( cfun -> decl ) ) , cfun -> decl , false ) ; if ( STACK_REG_P ( a ) || STACK_REG_P ( b ) ) { if ( ! rtx_equal_p ( a , b ) ) return false ; } else if ( VOID_TYPE_P ( TREE_TYPE ( DECL_RESULT ( cfun -> decl ) ) ) ) ; else if ( ! rtx_equal_p ( a , b ) ) return false ; if ( TARGET_64BIT ) { if ( cfun -> machine -> call_abi == MS_ABI && ix86_function_type_abi ( type ) == SYSV_ABI ) return false ; } else { if ( ! decl || ( bind_global && flag_pic && ! flag_plt ) || ( TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P ( decl ) ) ) { if ( ix86_function_regparm ( type , NULL ) >= 3 && ! cfun -> machine -> arg_reg_available ) return false ; } } return true ; } </s>

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


"calling %qD with attribute sseregparm without "

"calling %qT with attribute sseregparm without "

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


<s>
enum
calling_abi
ix86_function_type_abi
(
const_tree
fntype
)
{
enum
calling_abi
abi
=
ix86_abi
;
if
(
fntype
==
NULL_TREE
||
TYPE_ATTRIBUTES
(
fntype
)
==
NULL_TREE
)
return
abi
;
if
(
abi
==
SYSV_ABI
&&
lookup_attribute
(
"ms_abi"
,
TYPE_ATTRIBUTES
(
fntype
)
)
)
{
if
(
TARGET_X32
)
error
(
"X32 does not support ms_abi attribute"
)
;
abi
=
MS_ABI
;
}
else
if
(
abi
==
MS_ABI
&&
lookup_attribute
(
"sysv_abi"
,
TYPE_ATTRIBUTES
(
fntype
)
)
)
abi
=
SYSV_ABI
;
return
abi
;
}
</s>

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


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

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


"missing %<target%> attribute for multi-versioned %D"

This function returns true if FN1 and FN2 are versions of the same function , that is , the target strings of the function decls are different . This assumes that FN1 and FN2 have the same signature .


<s> static machine_mode ix86_get_mask_mode ( unsigned nunits , unsigned vector_size ) { unsigned elem_size = vector_size / nunits ; if ( ( TARGET_AVX512F && vector_size == 64 ) || ( TARGET_AVX512VL && ( vector_size == 32 || vector_size == 16 ) ) ) { if ( elem_size == 4 || elem_size == 8 || TARGET_AVX512BW ) return smallest_mode_for_size ( nunits , MODE_INT ) ; } machine_mode elem_mode = smallest_mode_for_size ( elem_size * BITS_PER_UNIT , MODE_INT ) ; gcc_assert ( elem_size * nunits == vector_size ) ; return mode_for_vector ( elem_mode , nunits ) ; } </s>

Implemenation of targetm.vectorize.get_mask_mode .


<s> static int ix86_get_modrm_for_rop ( rtx_insn * insn , rtx * operands , int noperands , int * popno0 = 0 , int * popno1 = 0 ) { if ( asm_noperands ( PATTERN ( insn ) ) >= 0 ) return - 1 ; int has_modrm = get_attr_modrm ( insn ) ; if ( ! has_modrm ) return - 1 ; enum attr_modrm_class cls = get_attr_modrm_class ( insn ) ; rtx op0 , op1 ; switch ( cls ) { case MODRM_CLASS_OP02 : gcc_assert ( noperands >= 3 ) ; if ( popno0 ) { * popno0 = 0 ; * popno1 = 2 ; } op0 = operands [ 0 ] ; op1 = operands [ 2 ] ; break ; case MODRM_CLASS_OP01 : gcc_assert ( noperands >= 2 ) ; if ( popno0 ) { * popno0 = 0 ; * popno1 = 1 ; } op0 = operands [ 0 ] ; op1 = operands [ 1 ] ; break ; default : return - 1 ; } if ( REG_P ( op0 ) && REG_P ( op1 ) ) { int enc0 = reg_encoded_number ( op0 ) ; int enc1 = reg_encoded_number ( op1 ) ; return 0xc0 + ( enc1 << 3 ) + enc0 ; } return - 1 ; } </s>

Given an insn INSN with NOPERANDS OPERANDS , return the modr/m byte used in its encoding if it could be relevant for ROP mitigation , otherwise return -1 . If POPNO0 and POPNO1 are nonnull , store the operand numbers used for calculating it into them .


<s> static int ix86_issue_rate ( void ) { switch ( ix86_tune ) { case PROCESSOR_PENTIUM : case PROCESSOR_LAKEMONT : case PROCESSOR_BONNELL : case PROCESSOR_SILVERMONT : case PROCESSOR_KNL : case PROCESSOR_INTEL : case PROCESSOR_K6 : case PROCESSOR_BTVER2 : case PROCESSOR_PENTIUM4 : case PROCESSOR_NOCONA : return 2 ; case PROCESSOR_PENTIUMPRO : case PROCESSOR_ATHLON : case PROCESSOR_K8 : case PROCESSOR_AMDFAM10 : case PROCESSOR_GENERIC : case PROCESSOR_BTVER1 : return 3 ; case PROCESSOR_BDVER1 : case PROCESSOR_BDVER2 : case PROCESSOR_BDVER3 : case PROCESSOR_BDVER4 : case PROCESSOR_ZNVER1 : case PROCESSOR_CORE2 : case PROCESSOR_NEHALEM : case PROCESSOR_SANDYBRIDGE : case PROCESSOR_HASWELL : return 4 ; default : return 1 ; } } </s>

Return the maximum number of instructions a cpu can issue .


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

Implement the TARGET_LEGITIMATE_COMBINED_INSN hook .


<s> static bool ix86_legitimate_constant_p ( machine_mode , rtx x ) { if ( POINTER_BOUNDS_MODE_P ( GET_MODE ( x ) ) ) return false ; switch ( GET_CODE ( x ) ) { case CONST : x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == PLUS ) { if ( ! CONST_INT_P ( XEXP ( x , 1 ) ) ) return false ; x = XEXP ( x , 0 ) ; } if ( TARGET_MACHO && darwin_local_data_pic ( x ) ) return true ; if ( GET_CODE ( x ) == UNSPEC ) switch ( XINT ( x , 1 ) ) { case UNSPEC_GOT : case UNSPEC_GOTOFF : case UNSPEC_PLTOFF : return TARGET_64BIT ; case UNSPEC_TPOFF : case UNSPEC_NTPOFF : x = XVECEXP ( x , 0 , 0 ) ; return ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL ( x ) == TLS_MODEL_LOCAL_EXEC ) ; case UNSPEC_DTPOFF : x = XVECEXP ( x , 0 , 0 ) ; return ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL ( x ) == TLS_MODEL_LOCAL_DYNAMIC ) ; default : return false ; } if ( GET_CODE ( x ) == LABEL_REF ) return true ; if ( GET_CODE ( x ) != SYMBOL_REF ) return false ; case SYMBOL_REF : if ( SYMBOL_REF_TLS_MODEL ( x ) ) return false ; if ( TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P ( x ) ) return false ; if ( MACHO_DYNAMIC_NO_PIC_P ) return machopic_symbol_defined_p ( x ) ; break ; case CONST_WIDE_INT : if ( ! TARGET_64BIT && ! standard_sse_constant_p ( x ) ) return false ; break ; case CONST_VECTOR : if ( ! standard_sse_constant_p ( x ) ) return false ; default : break ; } return true ; } </s>

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


<s> static rtx ix86_load_bounds ( rtx slot , rtx ptr , rtx slot_no ) { rtx reg = gen_reg_rtx ( BNDmode ) ; rtx addr ; addr = ix86_get_arg_address_for_bt ( slot , slot_no , arg_pointer_rtx ) ; if ( ! ptr ) { gcc_assert ( MEM_P ( slot ) ) ; ptr = copy_addr_to_reg ( slot ) ; } if ( ! register_operand ( ptr , Pmode ) ) ptr = ix86_zero_extend_to_Pmode ( ptr ) ; emit_insn ( BNDmode == BND64mode ? gen_bnd64_ldx ( reg , addr , ptr ) : gen_bnd32_ldx ( reg , addr , ptr ) ) ; return reg ; } </s>

Expand pass uses this hook to load bounds for function parameter PTR passed in SLOT in case its bounds are not passed in a register . If SLOT is a memory , then bounds are loaded as for regular pointer loaded from memory . PTR may be NULL in case SLOT is a memory . In such case value of PTR ( if required ) may be loaded from SLOT . If SLOT is NULL or a register then SLOT_NO is an integer constant holding number of the target dependent special slot which should be used to obtain bounds . Return loaded bounds .


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

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


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

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


<s> bool ix86_match_ccmode ( rtx insn , machine_mode req_mode ) { rtx set ; machine_mode set_mode ; set = PATTERN ( insn ) ; if ( GET_CODE ( set ) == PARALLEL ) set = XVECEXP ( set , 0 , 0 ) ; gcc_assert ( GET_CODE ( set ) == SET ) ; gcc_assert ( GET_CODE ( SET_SRC ( set ) ) == COMPARE ) ; set_mode = GET_MODE ( SET_DEST ( set ) ) ; switch ( set_mode ) { case CCNOmode : if ( req_mode != CCNOmode && ( req_mode != CCmode || XEXP ( SET_SRC ( set ) , 1 ) != const0_rtx ) ) return false ; break ; case CCmode : if ( req_mode == CCGCmode ) return false ; case CCGCmode : if ( req_mode == CCGOCmode || req_mode == CCNOmode ) return false ; case CCGOCmode : if ( req_mode == CCZmode ) return false ; case CCZmode : break ; case CCAmode : case CCCmode : case CCOmode : case CCPmode : case CCSmode : if ( set_mode != req_mode ) return false ; break ; default : gcc_unreachable ( ) ; } return GET_MODE ( SET_SRC ( set ) ) == set_mode ; } </s>

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


"Unknown architecture specific memory model"

"HLE_ACQUIRE not used with ACQUIRE or stronger memory model"

"HLE_RELEASE not used with RELEASE or stronger memory model"

Validate target specific memory model bits in VAL .


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

Return minimum incoming stack alignment .