<s> static int get_template ( state_t state , int pos ) { switch ( pos ) { case 3 : if ( cpu_unit_reservation_p ( state , _0mmi_ ) ) return 1 ; else if ( cpu_unit_reservation_p ( state , _0mii_ ) ) return 0 ; else if ( cpu_unit_reservation_p ( state , _0mmb_ ) ) return 7 ; else if ( cpu_unit_reservation_p ( state , _0mib_ ) ) return 6 ; else if ( cpu_unit_reservation_p ( state , _0mbb_ ) ) return 5 ; else if ( cpu_unit_reservation_p ( state , _0bbb_ ) ) return 4 ; else if ( cpu_unit_reservation_p ( state , _0mmf_ ) ) return 3 ; else if ( cpu_unit_reservation_p ( state , _0mfi_ ) ) return 2 ; else if ( cpu_unit_reservation_p ( state , _0mfb_ ) ) return 8 ; else if ( cpu_unit_reservation_p ( state , _0mlx_ ) ) return 9 ; else gcc_unreachable ( ) ; case 6 : if ( cpu_unit_reservation_p ( state , _1mmi_ ) ) return 1 ; else if ( cpu_unit_reservation_p ( state , _1mii_ ) ) return 0 ; else if ( cpu_unit_reservation_p ( state , _1mmb_ ) ) return 7 ; else if ( cpu_unit_reservation_p ( state , _1mib_ ) ) return 6 ; else if ( cpu_unit_reservation_p ( state , _1mbb_ ) ) return 5 ; else if ( cpu_unit_reservation_p ( state , _1bbb_ ) ) return 4 ; else if ( _1mmf_ >= 0 && cpu_unit_reservation_p ( state , _1mmf_ ) ) return 3 ; else if ( cpu_unit_reservation_p ( state , _1mfi_ ) ) return 2 ; else if ( cpu_unit_reservation_p ( state , _1mfb_ ) ) return 8 ; else if ( cpu_unit_reservation_p ( state , _1mlx_ ) ) return 9 ; else gcc_unreachable ( ) ; default : gcc_unreachable ( ) ; } } </s>

The function returns code of a possible template for given position and state . The function should be called only with 2 values of position equal to 3 or 6 . We avoid generating F NOPs by putting templates containing F insns at the end of the template search because undocumented anomaly in McKinley derived cores which can cause stalls if an F-unit insn ( including a NOP ) is issued within a six-cycle window after reading certain application registers ( such as ar.bsp ) . Furthermore , power-considerations also argue against the use of F-unit instructions unless they 're really needed .


<s> static int group_barrier_needed ( rtx_insn * insn ) { rtx pat ; int need_barrier = 0 ; struct reg_flags flags ; memset ( & flags , 0 , sizeof ( flags ) ) ; switch ( GET_CODE ( insn ) ) { case NOTE : case DEBUG_INSN : break ; case BARRIER : break ; case CODE_LABEL : memset ( rws_insn , 0 , sizeof ( rws_insn ) ) ; return 1 ; case CALL_INSN : flags . is_branch = 1 ; flags . is_sibcall = SIBLING_CALL_P ( insn ) ; memset ( rws_insn , 0 , sizeof ( rws_insn ) ) ; if ( ( pat = prev_active_insn ( insn ) ) && CALL_P ( pat ) ) { need_barrier = 1 ; break ; } need_barrier = rtx_needs_barrier ( PATTERN ( insn ) , flags , 0 ) ; break ; case JUMP_INSN : if ( ! ia64_spec_check_p ( insn ) ) flags . is_branch = 1 ; if ( ( pat = prev_active_insn ( insn ) ) && CALL_P ( pat ) ) { need_barrier = 1 ; break ; } case INSN : if ( GET_CODE ( PATTERN ( insn ) ) == USE || GET_CODE ( PATTERN ( insn ) ) == CLOBBER ) break ; pat = PATTERN ( insn ) ; switch ( recog_memoized ( insn ) ) { case CODE_FOR_epilogue_deallocate_stack : case CODE_FOR_prologue_allocate_stack : pat = XVECEXP ( pat , 0 , 0 ) ; break ; case CODE_FOR_doloop_end_internal : pat = XVECEXP ( pat , 0 , 1 ) ; break ; case CODE_FOR_pred_rel_mutex : case CODE_FOR_prologue_use : return 0 ; default : break ; } memset ( rws_insn , 0 , sizeof ( rws_insn ) ) ; need_barrier = rtx_needs_barrier ( pat , flags , 0 ) ; if ( ! need_barrier ) need_barrier = rws_access_regno ( REG_VOLATILE , flags , 0 ) ; break ; default : gcc_unreachable ( ) ; } if ( first_instruction && important_for_bundling_p ( insn ) ) { need_barrier = 0 ; first_instruction = 0 ; } return need_barrier ; } </s>

Given the current state , determine whether a group barrier ( a stop bit ) is necessary before INSN . Return nonzero if so . This modifies the state to include the effects of INSN as a side-effect .


<s> inline hashval_t bundle_state_hasher :: hash ( const bundle_state * state ) { unsigned result , i ; for ( result = i = 0 ; i < dfa_state_size ; i ++ ) result += ( ( ( unsigned char * ) state -> dfa_state ) [ i ] << ( ( i % CHAR_BIT ) * 3 + CHAR_BIT ) ) ; return result + state -> insn_num ; } </s>

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


<s> static machine_mode hfa_element_mode ( const_tree type , bool nested ) { machine_mode element_mode = VOIDmode ; machine_mode mode ; enum tree_code code = TREE_CODE ( type ) ; int know_element_mode = 0 ; tree t ; if ( ! nested && ( ! TYPE_SIZE ( type ) || integer_zerop ( TYPE_SIZE ( type ) ) ) ) return VOIDmode ; switch ( code ) { case VOID_TYPE : case INTEGER_TYPE : case ENUMERAL_TYPE : case BOOLEAN_TYPE : case POINTER_TYPE : case OFFSET_TYPE : case REFERENCE_TYPE : case METHOD_TYPE : case LANG_TYPE : case FUNCTION_TYPE : return VOIDmode ; case COMPLEX_TYPE : if ( GET_MODE_CLASS ( TYPE_MODE ( type ) ) == MODE_COMPLEX_FLOAT && TYPE_MODE ( type ) != TCmode ) return GET_MODE_INNER ( TYPE_MODE ( type ) ) ; else return VOIDmode ; case REAL_TYPE : if ( nested && TYPE_MODE ( type ) != TFmode ) return TYPE_MODE ( type ) ; else return VOIDmode ; case ARRAY_TYPE : return hfa_element_mode ( TREE_TYPE ( type ) , 1 ) ; case RECORD_TYPE : case UNION_TYPE : case QUAL_UNION_TYPE : for ( t = TYPE_FIELDS ( type ) ; t ; t = DECL_CHAIN ( t ) ) { if ( TREE_CODE ( t ) != FIELD_DECL || DECL_FIELD_ABI_IGNORED ( t ) ) continue ; mode = hfa_element_mode ( TREE_TYPE ( t ) , 1 ) ; if ( know_element_mode ) { if ( mode != element_mode ) return VOIDmode ; } else if ( GET_MODE_CLASS ( mode ) != MODE_FLOAT ) return VOIDmode ; else { know_element_mode = 1 ; element_mode = mode ; } } return element_mode ; default : return VOIDmode ; } return VOIDmode ; } </s>

Check whether TYPE is a homogeneous floating point aggregate . If it is , return the mode of the floating point type that appears in all leafs . If it is not , return VOIDmode . An aggregate is a homogeneous floating point aggregate is if all fields/elements in it have the same floating point type ( e.g , SFmode ) . 128-bit quad-precision floats are excluded .


<s> static void ia64_add_bundle_selector_before ( int template0 , rtx_insn * insn ) { rtx b = gen_bundle_selector ( GEN_INT ( template0 ) ) ; ia64_emit_insn_before ( b , insn ) ; if ( ( template0 == 4 || template0 == 5 ) && ia64_except_unwind_info ( & global_options ) == UI_TARGET ) { int i ; rtx note = NULL_RTX ; insn = PREV_INSN ( insn ) ; for ( i = 0 ; i < 3 ; i ++ ) { do insn = next_active_insn ( insn ) ; while ( NONJUMP_INSN_P ( insn ) && get_attr_empty ( insn ) == EMPTY_YES ) ; if ( CALL_P ( insn ) ) note = find_reg_note ( insn , REG_EH_REGION , NULL_RTX ) ; else if ( note ) { int code ; gcc_assert ( ( code = recog_memoized ( insn ) ) == CODE_FOR_nop || code == CODE_FOR_nop_b ) ; if ( find_reg_note ( insn , REG_EH_REGION , NULL_RTX ) ) note = NULL_RTX ; else add_reg_note ( insn , REG_EH_REGION , XEXP ( note , 0 ) ) ; } } } } </s>

Add a bundle selector TEMPLATE0 before INSN .


<s> static int ia64_adjust_cost ( rtx_insn * insn , int dep_type1 , rtx_insn * dep_insn , int cost , dw_t dw ) { enum reg_note dep_type = ( enum reg_note ) dep_type1 ; enum attr_itanium_class dep_class ; enum attr_itanium_class insn_class ; insn_class = ia64_safe_itanium_class ( insn ) ; dep_class = ia64_safe_itanium_class ( dep_insn ) ; if ( dep_type == REG_DEP_TRUE && ( dep_class == ITANIUM_CLASS_ST || dep_class == ITANIUM_CLASS_STF ) && ( insn_class == ITANIUM_CLASS_BR || insn_class == ITANIUM_CLASS_SCALL ) ) return 0 ; if ( dw == MIN_DEP_WEAK ) return param_sched_mem_true_dep_cost ; else if ( dw > MIN_DEP_WEAK ) { if ( mflag_sched_fp_mem_deps_zero_cost && dep_class == ITANIUM_CLASS_STF ) return 0 ; else return cost ; } if ( dep_type != REG_DEP_OUTPUT ) return cost ; if ( dep_class == ITANIUM_CLASS_ST || dep_class == ITANIUM_CLASS_STF || insn_class == ITANIUM_CLASS_ST || insn_class == ITANIUM_CLASS_STF ) return 0 ; return cost ; } </s>

Adjust the cost of a scheduling dependency . Return the new cost of a dependency LINK or INSN on DEP_INSN . COST is the current cost .


<s> static void * ia64_alloc_sched_context ( void ) { return xmalloc ( sizeof ( struct _ia64_sched_context ) ) ; } </s>


<s> static int ia64_arg_partial_bytes ( cumulative_args_t cum_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; int words = ia64_function_arg_words ( arg . type , arg . mode ) ; int offset = ia64_function_arg_offset ( cum , arg . type , words ) ; if ( cum -> words + offset >= MAX_ARGUMENT_SLOTS ) return 0 ; if ( words + cum -> words + offset <= MAX_ARGUMENT_SLOTS ) return 0 ; return ( MAX_ARGUMENT_SLOTS - cum -> words - offset ) * UNITS_PER_WORD ; } </s>

Return number of bytes , at the beginning of the argument , that must be put in registers . 0 is the argument is entirely in registers or entirely in memory .


<s> static enum ivms_arg_type ia64_arg_type ( machine_mode mode ) { switch ( mode ) { case E_SFmode : return FS ; case E_DFmode : return FT ; default : return I64 ; } } </s>

Return ivms_arg_type based on machine_mode .


<s> static void ia64_asm_emit_except_personality ( rtx personality ) { fputs ( "\t.personality\t" , asm_out_file ) ; output_addr_const ( asm_out_file , personality ) ; fputc ( '\n' , asm_out_file ) ; } </s>


<s> static void ia64_asm_init_sections ( void ) { exception_section = get_unnamed_section ( 0 , output_section_asm_op , "\t.handlerdata" ) ; } </s>


<s> void ia64_asm_output_external ( FILE * file , tree decl , const char * name ) { if ( TREE_SYMBOL_REFERENCED ( DECL_ASSEMBLER_NAME ( decl ) ) ) { int need_visibility = ( ( * targetm . binds_local_p ) ( decl ) && maybe_assemble_visibility ( decl ) ) ; if ( ( TARGET_HPUX_LD || ! TARGET_GNU_AS ) && TREE_CODE ( decl ) == FUNCTION_DECL ) ( * targetm . asm_out . globalize_decl_name ) ( file , decl ) ; else if ( need_visibility && ! TARGET_GNU_AS ) ( * targetm . asm_out . globalize_label ) ( file , name ) ; } } </s>

Emit text to declare externally defined variables and functions , because the Intel assembler does not support undefined externals .


<s>
static
void
ia64_asm_unwind_emit
(
FILE
*
out_file
,
rtx_insn
*
insn
)
{
bool
unwind
=
ia64_except_unwind_info
(
&
global_options
)
==
UI_TARGET
;
bool
frame
=
dwarf2out_do_frame
(
)
;
rtx
note
,
pat
;
bool
handled_one
;
if
(
!
unwind
&&
!
frame
)
return
;
if
(
NOTE_INSN_BASIC_BLOCK_P
(
insn
)
)
{
last_block
=
NOTE_BASIC_BLOCK
(
insn
)
->
next_bb
==
EXIT_BLOCK_PTR_FOR_FN
(
cfun
)
;
if
(
need_copy_state
)
{
if
(
unwind
)
{
fprintf
(
out_file
,
"\t.body\n"
)
;
fprintf
(
out_file
,
"\t.copy_state %d\n"
,
cfun
->
machine
->
state_num
)
;
}
need_copy_state
=
false
;
}
}
if
(
NOTE_P
(
insn
)
||
!
RTX_FRAME_RELATED_P
(
insn
)
)
return
;
if
(
INSN_CODE
(
insn
)
==
CODE_FOR_alloc
)
{
rtx
dest
=
SET_DEST
(
XVECEXP
(
PATTERN
(
insn
)
,
0
,
0
)
)
;
int
dest_regno
=
REGNO
(
dest
)
;
if
(
dest_regno
==
current_frame_info
.
r
[
reg_save_ar_pfs
]
)
{
if
(
unwind
)
fprintf
(
out_file
,
"\t.save ar.pfs, r%d\n"
,
ia64_dbx_register_number
(
dest_regno
)
)
;
}
else
{
if
(
current_frame_info
.
total_size
==
0
&&
!
frame_pointer_needed
)
process_epilogue
(
out_file
,
insn
,
unwind
,
frame
)
;
if
(
unwind
)
fprintf
(
out_file
,
"\t.prologue\n"
)
;
}
return
;
}
handled_one
=
false
;
for
(
note
=
REG_NOTES
(
insn
)
;
note
;
note
=
XEXP
(
note
,
1
)
)
switch
(
REG_NOTE_KIND
(
note
)
)
{
case
REG_CFA_ADJUST_CFA
:
pat
=
XEXP
(
note
,
0
)
;
if
(
pat
==
)
pat
=
PATTERN
(
insn
)
;
process_cfa_adjust_cfa
(
out_file
,
pat
,
insn
,
unwind
,
frame
)
;
handled_one
=
true
;
break
;
case
REG_CFA_OFFSET
:
pat
=
XEXP
(
note
,
0
)
;
if
(
pat
==
)
pat
=
PATTERN
(
insn
)
;
process_cfa_offset
(
out_file
,
pat
,
unwind
)
;
handled_one
=
true
;
break
;
case
REG_CFA_REGISTER
:
pat
=
XEXP
(
note
,
0
)
;
if
(
pat
==
)
pat
=
PATTERN
(
insn
)
;
process_cfa_register
(
out_file
,
pat
,
unwind
)
;
handled_one
=
true
;
break
;
case
REG_FRAME_RELATED_EXPR
:
case
REG_CFA_DEF_CFA
:
case
REG_CFA_EXPRESSION
:
case
REG_CFA_RESTORE
:
case
REG_CFA_SET_VDRAP
:
gcc_unreachable
(
)
;
default
:
break
;
}
gcc_assert
(
handled_one
)
;
}
</s>

This function looks at a single insn and emits any directives required to unwind this insn .


<s> static bool ia64_assemble_integer ( rtx x , unsigned int size , int aligned_p ) { if ( size == POINTER_SIZE / BITS_PER_UNIT && ! ( TARGET_NO_PIC || TARGET_AUTO_PIC ) && GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P ( x ) ) { static const char * const directive [ 2 ] [ 2 ] = { { "\tdata8.ua\t@fptr(" , "\tdata4.ua\t@fptr(" } , { "\tdata8\t@fptr(" , "\tdata4\t@fptr(" } } ; fputs ( directive [ ( aligned_p != 0 ) ] [ POINTER_SIZE == 32 ] , asm_out_file ) ; output_addr_const ( asm_out_file , x ) ; fputs ( ")\n" , asm_out_file ) ; return true ; } return default_assemble_integer ( x , size , aligned_p ) ; } </s>

Target hook for assembling integer objects . Handle word-sized aligned objects and detect the cases when @ fptr is needed .


<s> static bool ia64_attribute_takes_identifier_p ( const_tree attr_id ) { if ( is_attribute_p ( "model" , attr_id ) ) return true ; if ( is_attribute_p ( "common_object" , attr_id ) ) return true ; return false ; } </s>

Returns TRUE iff the target attribute indicated by ATTR_ID takes a plain identifier as an argument , so the front end should n't look it up .


<s> static tree ia64_builtin_decl ( unsigned code , bool initialize_p ATTRIBUTE_UNUSED ) { if ( code >= IA64_BUILTIN_max ) return error_mark_node ; return ia64_builtins [ code ] ; } </s>


<s> static bool ia64_cannot_force_const_mem ( machine_mode mode , rtx x ) { if ( mode == RFmode ) return true ; return tls_symbolic_operand_type ( x ) != 0 ; } </s>

Do n't allow TLS addresses to get spilled to memory .


<s> static bool ia64_can_change_mode_class ( machine_mode from , machine_mode to , reg_class_t rclass ) { if ( reg_classes_intersect_p ( rclass , BR_REGS ) ) return from == to ; if ( SCALAR_FLOAT_MODE_P ( from ) != SCALAR_FLOAT_MODE_P ( to ) ) return ! reg_classes_intersect_p ( rclass , FR_REGS ) ; return true ; } </s>

Implement TARGET_CAN_CHANGE_MODE_CLASS . In BR regs , we ca n't change the DImode at all . In FP regs , we ca n't change FP values to integer values and vice versa , but we can change e.g . DImode to SImode , and V2SFmode into DImode .


<s> bool ia64_can_eliminate ( const int from ATTRIBUTE_UNUSED , const int to ) { return ( to == BR_REG ( 0 ) ? crtl -> is_leaf : true ) ; } </s>

Worker function for TARGET_CAN_ELIMINATE .


<s> static void ia64_clear_sched_context ( void * _sc ) { ia64_sched_context_t sc = ( ia64_sched_context_t ) _sc ; free ( sc -> prev_cycle_state ) ; sc -> prev_cycle_state = NULL ; } </s>

Clears the data in the _SC scheduling context .


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


<s> static enum unwind_info_type ia64_debug_unwind_info ( void ) { return UI_TARGET ; } </s>


<s> static void ia64_dependencies_evaluation_hook ( rtx_insn * head , rtx_insn * tail ) { rtx_insn * insn , * next , * next_tail ; if ( ! reload_completed ) return ; next_tail = NEXT_INSN ( tail ) ; for ( insn = head ; insn != next_tail ; insn = NEXT_INSN ( insn ) ) if ( INSN_P ( insn ) ) insn -> call = 0 ; for ( insn = head ; insn != next_tail ; insn = NEXT_INSN ( insn ) ) if ( INSN_P ( insn ) && ia64_safe_itanium_class ( insn ) == ITANIUM_CLASS_IALU ) { sd_iterator_def sd_it ; dep_t dep ; bool has_mem_op_consumer_p = false ; FOR_EACH_DEP ( insn , SD_LIST_FORW , sd_it , dep ) { enum attr_itanium_class c ; if ( DEP_TYPE ( dep ) != REG_DEP_TRUE ) continue ; next = DEP_CON ( dep ) ; c = ia64_safe_itanium_class ( next ) ; if ( ( c == ITANIUM_CLASS_ST || c == ITANIUM_CLASS_STF ) && ia64_st_address_bypass_p ( insn , next ) ) { has_mem_op_consumer_p = true ; break ; } else if ( ( c == ITANIUM_CLASS_LD || c == ITANIUM_CLASS_FLD || c == ITANIUM_CLASS_FLDP ) && ia64_ld_address_bypass_p ( insn , next ) ) { has_mem_op_consumer_p = true ; break ; } } insn -> call = has_mem_op_consumer_p ; } } </s>

The following function marks insns who produce addresses for load and store insns . Such insns will be placed into M slots because it decrease latency time for Itanium1 ( see function ` ia64_produce_address_p ' and the DFA descriptions ) .


<s> int ia64_depz_field_mask ( rtx rop , rtx rshift ) { unsigned HOST_WIDE_INT op = INTVAL ( rop ) ; unsigned HOST_WIDE_INT shift = INTVAL ( rshift ) ; op >>= shift ; return exact_log2 ( op + 1 ) ; } </s>

Check if OP is a mask suitible for use with SHIFT in a dep.z instruction . Return the length of the field , or < = 0 on failure .


<s>
static
int
ia64_dfa_new_cycle
(
FILE
*
dump
,
int
verbose
,
rtx_insn
*
insn
,
int
last_clock
,
int
clock
,
int
*
sort_p
)
{
gcc_assert
(
insn
&&
INSN_P
(
insn
)
)
;
if
(
DEBUG_INSN_P
(
insn
)
)
return
0
;
gcc_assert
(
!
(
reload_completed
&&
safe_group_barrier_needed
(
insn
)
)
||
last_scheduled_insn
)
;
if
(
(
reload_completed
&&
(
safe_group_barrier_needed
(
insn
)
||
(
mflag_sched_stop_bits_after_every_cycle
&&
last_clock
!=
clock
&&
last_scheduled_insn
&&
scheduled_good_insn
(
last_scheduled_insn
)
)
)
)
||
(
last_scheduled_insn
&&
(
CALL_P
(
last_scheduled_insn
)
||
unknown_for_bundling_p
(
last_scheduled_insn
)
)
)
)
{
init_insn_group_barriers
(
)
;
if
(
verbose
&&
dump
)
fprintf
(
dump
,
"//    Stop should be before %d%s\n"
,
INSN_UID
(
insn
)
,
last_clock
==
clock
" + cycle advance"
:
""
)
;
stop_before_p
=
1
;
current_cycle
=
clock
;
mem_ops_in_group
[
current_cycle
%
4
]
=
0
;
if
(
last_clock
==
clock
)
{
state_transition
(
curr_state
,
dfa_stop_insn
)
;
if
(
TARGET_EARLY_STOP_BITS
)
*
sort_p
=
(
last_scheduled_insn
==
NULL_RTX
||
!
CALL_P
(
last_scheduled_insn
)
)
;
else
*
sort_p
=
0
;
return
1
;
}
if
(
last_scheduled_insn
)
{
if
(
unknown_for_bundling_p
(
last_scheduled_insn
)
)
state_reset
(
curr_state
)
;
else
{
memcpy
(
curr_state
,
prev_cycle_state
,
dfa_state_size
)
;
state_transition
(
curr_state
,
dfa_stop_insn
)
;
state_transition
(
curr_state
,
dfa_pre_cycle_insn
)
;
state_transition
(
curr_state
,
)
;
}
}
}
return
0
;
}
</s>

We are about to being issuing INSN . Return nonzero if we can not issue it on given cycle CLOCK and return zero if we should not sort the ready queue on the next clock start .


<s> static rtx ia64_dfa_pre_cycle_insn ( void ) { return dfa_pre_cycle_insn ; } </s>

The following function returns the pseudo insn DFA_PRE_CYCLE_INSN used by the DFA insn scheduler .


"// ia64_dfa_sched_reorder (type %d):\n"

We are about to being issuing insns for this clock cycle . Override the default sort algorithm to better slot instructions .


<s> int ia64_direct_return ( void ) { if ( reload_completed && ! frame_pointer_needed ) { ia64_compute_frame_size ( get_frame_size ( ) ) ; return ( current_frame_info . total_size == 0 && current_frame_info . n_spilled == 0 && current_frame_info . r [ reg_save_b0 ] == 0 && current_frame_info . r [ reg_save_pr ] == 0 && current_frame_info . r [ reg_save_ar_pfs ] == 0 && current_frame_info . r [ reg_save_ar_unat ] == 0 && current_frame_info . r [ reg_save_ar_lc ] == 0 ) ; } return 0 ; } </s>

Return 1 if br.ret can do all the work required to return from a function .


<s> int ia64_eh_uses ( int regno ) { unsigned int r ; if ( ! reload_completed ) return 0 ; if ( regno == 0 ) return 0 ; for ( r = reg_save_b0 ; r <= reg_save_ar_lc ; r ++ ) if ( regno == current_frame_info . r [ r ] || regno == emitted_frame_related_regs [ r ] ) return 1 ; return 0 ; } </s>

Return true if REGNO is used by the frame unwinder .


<s> void ia64_emit_cond_move ( rtx op0 , rtx op1 , rtx cond ) { rtx_insn * insn , * first = get_last_insn ( ) ; emit_move_insn ( op0 , op1 ) ; for ( insn = get_last_insn ( ) ; insn != first ; insn = PREV_INSN ( insn ) ) if ( INSN_P ( insn ) ) PATTERN ( insn ) = gen_rtx_COND_EXEC ( VOIDmode , copy_rtx ( cond ) , PATTERN ( insn ) ) ; } </s>

Split a move from OP1 to OP0 conditional on COND .


<s> static void ia64_emit_insn_before ( rtx insn , rtx_insn * before ) { emit_insn_before ( insn , before ) ; } </s>

Like emit_insn_before , but skip cycle_display insns . This makes the assembly output a bit prettier .


<s> int ia64_epilogue_uses ( int regno ) { switch ( regno ) { case R_GR ( 1 ) : return ! ( TARGET_AUTO_PIC || TARGET_NO_PIC ) ; case IN_REG ( 0 ) : case IN_REG ( 1 ) : case IN_REG ( 2 ) : case IN_REG ( 3 ) : case IN_REG ( 4 ) : case IN_REG ( 5 ) : case IN_REG ( 6 ) : case IN_REG ( 7 ) : return lookup_attribute ( "syscall_linkage" , TYPE_ATTRIBUTES ( TREE_TYPE ( current_function_decl ) ) ) != NULL ; case R_BR ( 0 ) : return 1 ; case AR_PFS_REGNUM : return 1 ; default : return 0 ; } } </s>

Return true if REGNO is used by the epilogue .


<s> void ia64_expand_call ( rtx retval , rtx addr , rtx nextarg ATTRIBUTE_UNUSED , int sibcall_p ) { rtx insn , b0 ; addr = XEXP ( addr , 0 ) ; addr = convert_memory_address ( DImode , addr ) ; b0 = gen_rtx_REG ( DImode , R_BR ( 0 ) ) ; if ( TARGET_NO_PIC || TARGET_AUTO_PIC ) { if ( sibcall_p ) insn = gen_sibcall_nogp ( addr ) ; else if ( ! retval ) insn = gen_call_nogp ( addr , b0 ) ; else insn = gen_call_value_nogp ( retval , addr , b0 ) ; insn = emit_call_insn ( insn ) ; } else { if ( sibcall_p ) insn = gen_sibcall_gp ( addr ) ; else if ( ! retval ) insn = gen_call_gp ( addr , b0 ) ; else insn = gen_call_value_gp ( retval , addr , b0 ) ; insn = emit_call_insn ( insn ) ; use_reg ( & CALL_INSN_FUNCTION_USAGE ( insn ) , pic_offset_table_rtx ) ; } if ( sibcall_p ) use_reg ( & CALL_INSN_FUNCTION_USAGE ( insn ) , b0 ) ; if ( TARGET_ABI_OPEN_VMS ) use_reg ( & CALL_INSN_FUNCTION_USAGE ( insn ) , gen_rtx_REG ( DImode , GR_REG ( 25 ) ) ) ; } </s>

Emit the appropriate sequence for a call .


<s> void ia64_expand_compare ( rtx * expr , rtx * op0 , rtx * op1 ) { enum rtx_code code = GET_CODE ( * expr ) ; rtx cmp ; if ( GET_MODE ( * op0 ) == BImode ) { gcc_assert ( ( code == NE || code == EQ ) && * op1 == const0_rtx ) ; cmp = * op0 ; } else if ( TARGET_HPUX && GET_MODE ( * op0 ) == TFmode ) { enum qfcmp_magic { QCMP_INV = 1 , QCMP_UNORD = 2 , QCMP_EQ = 4 , QCMP_LT = 8 , QCMP_GT = 16 } ; int magic ; enum rtx_code ncode ; rtx ret ; gcc_assert ( cmptf_libfunc && GET_MODE ( * op1 ) == TFmode ) ; switch ( code ) { case EQ : magic = QCMP_EQ ; ncode = NE ; break ; case NE : magic = QCMP_EQ ; ncode = EQ ; break ; case UNORDERED : magic = QCMP_UNORD ; ncode = NE ; break ; case ORDERED : magic = QCMP_UNORD ; ncode = EQ ; break ; case LT : magic = QCMP_LT | QCMP_INV ; ncode = NE ; break ; case LE : magic = QCMP_LT | QCMP_EQ | QCMP_INV ; ncode = NE ; break ; case GT : magic = QCMP_GT | QCMP_INV ; ncode = NE ; break ; case GE : magic = QCMP_GT | QCMP_EQ | QCMP_INV ; ncode = NE ; break ; case UNLT : magic = QCMP_LT | QCMP_UNORD ; ncode = NE ; break ; case UNLE : magic = QCMP_LT | QCMP_EQ | QCMP_UNORD ; ncode = NE ; break ; case UNGT : magic = QCMP_GT | QCMP_UNORD ; ncode = NE ; break ; case UNGE : magic = QCMP_GT | QCMP_EQ | QCMP_UNORD ; ncode = NE ; break ; case UNEQ : case LTGT : default : gcc_unreachable ( ) ; } start_sequence ( ) ; ret = emit_library_call_value ( cmptf_libfunc , 0 , LCT_CONST , DImode , * op0 , TFmode , * op1 , TFmode , GEN_INT ( magic ) , DImode ) ; cmp = gen_reg_rtx ( BImode ) ; emit_insn ( gen_rtx_SET ( cmp , gen_rtx_fmt_ee ( ncode , BImode , ret , const0_rtx ) ) ) ; rtx_insn * insns = get_insns ( ) ; end_sequence ( ) ; emit_libcall_block ( insns , cmp , cmp , gen_rtx_fmt_ee ( code , BImode , * op0 , * op1 ) ) ; code = NE ; } else { cmp = gen_reg_rtx ( BImode ) ; emit_insn ( gen_rtx_SET ( cmp , gen_rtx_fmt_ee ( code , BImode , * op0 , * op1 ) ) ) ; code = NE ; } * expr = gen_rtx_fmt_ee ( code , VOIDmode , cmp , const0_rtx ) ; * op0 = cmp ; * op1 = const0_rtx ; } </s>

Emit comparison instruction if necessary , returning the expression that holds the compare result in the proper mode .


<s> bool ia64_expand_load_address ( rtx dest , rtx src ) { gcc_assert ( GET_CODE ( dest ) == REG ) ; if ( GET_MODE ( dest ) != Pmode ) dest = gen_rtx_REG_offset ( dest , Pmode , REGNO ( dest ) , byte_lowpart_offset ( Pmode , GET_MODE ( dest ) ) ) ; if ( TARGET_NO_PIC ) return false ; if ( small_addr_symbolic_operand ( src , VOIDmode ) ) return false ; if ( TARGET_AUTO_PIC ) emit_insn ( gen_load_gprel64 ( dest , src ) ) ; else if ( GET_CODE ( src ) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P ( src ) ) emit_insn ( gen_load_fptr ( dest , src ) ) ; else if ( sdata_symbolic_operand ( src , VOIDmode ) ) emit_insn ( gen_load_gprel ( dest , src ) ) ; else if ( local_symbolic_operand64 ( src , VOIDmode ) ) { emit_insn ( gen_load_gprel64 ( dest , src ) ) ; } else { HOST_WIDE_INT addend = 0 ; rtx tmp ; if ( GET_CODE ( src ) == CONST ) { HOST_WIDE_INT hi , lo ; hi = INTVAL ( XEXP ( XEXP ( src , 0 ) , 1 ) ) ; lo = ( ( hi & 0x3fff ) ^ 0x2000 ) - 0x2000 ; hi = hi - lo ; if ( lo != 0 ) { addend = lo ; src = plus_constant ( Pmode , XEXP ( XEXP ( src , 0 ) , 0 ) , hi ) ; } } tmp = gen_rtx_HIGH ( Pmode , src ) ; tmp = gen_rtx_PLUS ( Pmode , tmp , pic_offset_table_rtx ) ; emit_insn ( gen_rtx_SET ( dest , tmp ) ) ; tmp = gen_rtx_LO_SUM ( Pmode , gen_const_mem ( Pmode , dest ) , src ) ; emit_insn ( gen_rtx_SET ( dest , tmp ) ) ; if ( addend ) { tmp = gen_rtx_PLUS ( Pmode , dest , GEN_INT ( addend ) ) ; emit_insn ( gen_rtx_SET ( dest , tmp ) ) ; } } return true ; } </s>


<s> void ia64_expand_unpack ( rtx operands [ 3 ] , bool unsignedp , bool highp ) { rtx sign = ia64_unpack_sign ( operands [ 1 ] , unsignedp ) ; ia64_unpack_assemble ( operands [ 0 ] , operands [ 1 ] , sign , highp ) ; } </s>

Emit an integral vector unpack operation .


<s> void ia64_expand_vecint_cmov ( rtx operands [ ] ) { machine_mode mode = GET_MODE ( operands [ 0 ] ) ; enum rtx_code code = GET_CODE ( operands [ 3 ] ) ; bool negate ; rtx cmp , x , ot , of ; cmp = gen_reg_rtx ( mode ) ; negate = ia64_expand_vecint_compare ( code , mode , cmp , operands [ 4 ] , operands [ 5 ] ) ; ot = operands [ 1 + negate ] ; of = operands [ 2 - negate ] ; if ( ot == CONST0_RTX ( mode ) ) { if ( of == CONST0_RTX ( mode ) ) { emit_move_insn ( operands [ 0 ] , ot ) ; return ; } x = gen_rtx_NOT ( mode , cmp ) ; x = gen_rtx_AND ( mode , x , of ) ; emit_insn ( gen_rtx_SET ( operands [ 0 ] , x ) ) ; } else if ( of == CONST0_RTX ( mode ) ) { x = gen_rtx_AND ( mode , cmp , ot ) ; emit_insn ( gen_rtx_SET ( operands [ 0 ] , x ) ) ; } else { rtx t , f ; t = gen_reg_rtx ( mode ) ; x = gen_rtx_AND ( mode , cmp , operands [ 1 + negate ] ) ; emit_insn ( gen_rtx_SET ( t , x ) ) ; f = gen_reg_rtx ( mode ) ; x = gen_rtx_NOT ( mode , cmp ) ; x = gen_rtx_AND ( mode , x , operands [ 2 - negate ] ) ; emit_insn ( gen_rtx_SET ( f , x ) ) ; x = gen_rtx_IOR ( mode , t , f ) ; emit_insn ( gen_rtx_SET ( operands [ 0 ] , x ) ) ; } } </s>

Emit an integral vector conditional move .


<s> static bool ia64_expand_vecint_compare ( enum rtx_code code , machine_mode mode , rtx dest , rtx op0 , rtx op1 ) { bool negate = false ; rtx x ; switch ( code ) { case EQ : case GT : case GTU : break ; case NE : case LE : case LEU : code = reverse_condition ( code ) ; negate = true ; break ; case GE : case GEU : code = reverse_condition ( code ) ; negate = true ; case LT : case LTU : code = swap_condition ( code ) ; x = op0 , op0 = op1 , op1 = x ; break ; default : gcc_unreachable ( ) ; } if ( code == GTU ) { switch ( mode ) { case E_V2SImode : { rtx t1 , t2 , mask ; mask = gen_int_mode ( 0x80000000 , SImode ) ; mask = gen_const_vec_duplicate ( V2SImode , mask ) ; mask = force_reg ( mode , mask ) ; t1 = gen_reg_rtx ( mode ) ; emit_insn ( gen_subv2si3 ( t1 , op0 , mask ) ) ; t2 = gen_reg_rtx ( mode ) ; emit_insn ( gen_subv2si3 ( t2 , op1 , mask ) ) ; op0 = t1 ; op1 = t2 ; code = GT ; } break ; case E_V8QImode : case E_V4HImode : x = gen_reg_rtx ( mode ) ; emit_insn ( gen_rtx_SET ( x , gen_rtx_US_MINUS ( mode , op0 , op1 ) ) ) ; code = EQ ; op0 = x ; op1 = CONST0_RTX ( mode ) ; negate = ! negate ; break ; default : gcc_unreachable ( ) ; } } x = gen_rtx_fmt_ee ( code , mode , op0 , op1 ) ; emit_insn ( gen_rtx_SET ( dest , x ) ) ; return negate ; } </s>

Generate an integral vector comparison . Return true if the condition has been reversed , and so the sense of the comparison should be inverted .


<s> bool ia64_expand_vecint_minmax ( enum rtx_code code , machine_mode mode , rtx operands [ ] ) { rtx xops [ 6 ] ; if ( mode == V8QImode && ( code == UMIN || code == UMAX ) ) return false ; if ( mode == V4HImode && ( code == SMIN || code == SMAX ) ) return false ; if ( mode == V4HImode && code == UMAX ) { rtx x , tmp = gen_reg_rtx ( mode ) ; x = gen_rtx_US_MINUS ( mode , operands [ 1 ] , operands [ 2 ] ) ; emit_insn ( gen_rtx_SET ( tmp , x ) ) ; emit_insn ( gen_addv4hi3 ( operands [ 0 ] , tmp , operands [ 2 ] ) ) ; return true ; } xops [ 0 ] = operands [ 0 ] ; xops [ 4 ] = xops [ 1 ] = operands [ 1 ] ; xops [ 5 ] = xops [ 2 ] = operands [ 2 ] ; switch ( code ) { case UMIN : code = LTU ; break ; case UMAX : code = GTU ; break ; case SMIN : code = LT ; break ; case SMAX : code = GT ; break ; default : gcc_unreachable ( ) ; } xops [ 3 ] = gen_rtx_fmt_ee ( code , VOIDmode , operands [ 1 ] , operands [ 2 ] ) ; ia64_expand_vecint_cmov ( xops ) ; return true ; } </s>

Emit an integral vector min or max operation . Return true if all done .


<s> static bool ia64_expand_vec_perm_const_1 ( struct expand_vec_perm_d * d ) { if ( expand_vec_perm_1 ( d ) ) return true ; if ( expand_vec_perm_broadcast ( d ) ) return true ; if ( expand_vec_perm_interleave_2 ( d ) ) return true ; if ( expand_vec_perm_v4hi_5 ( d ) ) return true ; return false ; } </s>

The guts of ia64_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 .


<s> void ia64_expand_widen_sum ( rtx operands [ 3 ] , bool unsignedp ) { machine_mode wmode ; rtx l , h , t , sign ; sign = ia64_unpack_sign ( operands [ 1 ] , unsignedp ) ; wmode = GET_MODE ( operands [ 0 ] ) ; l = gen_reg_rtx ( wmode ) ; h = gen_reg_rtx ( wmode ) ; ia64_unpack_assemble ( l , operands [ 1 ] , sign , false ) ; ia64_unpack_assemble ( h , operands [ 1 ] , sign , true ) ; t = expand_binop ( wmode , add_optab , l , operands [ 2 ] , NULL , 0 , OPTAB_DIRECT ) ; t = expand_binop ( wmode , add_optab , h , t , operands [ 0 ] , 0 , OPTAB_DIRECT ) ; if ( t != operands [ 0 ] ) emit_move_insn ( operands [ 0 ] , t ) ; } </s>

Emit an integral vector widening sum operations .


<s> static void ia64_file_start ( void ) { default_file_start ( ) ; emit_safe_across_calls ( ) ; } </s>


If the following function returns TRUE , we will use the DFA insn scheduler .


We are choosing insn from the ready queue . Return nonzero if INSN can be chosen .


<s> static void ia64_free_sched_context ( void * _sc ) { gcc_assert ( _sc != NULL ) ; free ( _sc ) ; } </s>


<s> static rtx ia64_function_arg ( cumulative_args_t cum , const function_arg_info & arg ) { return ia64_function_arg_1 ( cum , arg , false ) ; } </s>

Implement TARGET_FUNCION_ARG target hook .


<s> static void ia64_function_arg_advance ( cumulative_args_t cum_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; int words = ia64_function_arg_words ( arg . type , arg . mode ) ; int offset = ia64_function_arg_offset ( cum , arg . type , words ) ; machine_mode hfa_mode = VOIDmode ; if ( cum -> words >= MAX_ARGUMENT_SLOTS ) { cum -> words += words + offset ; return ; } cum -> atypes [ cum -> words ] = ia64_arg_type ( arg . mode ) ; cum -> words += words + offset ; if ( TARGET_ABI_OPEN_VMS ) { cum -> int_regs = cum -> words ; cum -> fp_regs = cum -> words ; return ; } if ( arg . type ) hfa_mode = hfa_element_mode ( arg . type , 0 ) ; if ( hfa_mode != VOIDmode && ( ! cum -> prototype || arg . named ) ) { int fp_regs = cum -> fp_regs ; int int_regs = cum -> words - words ; int hfa_size = GET_MODE_SIZE ( hfa_mode ) ; int byte_size ; int args_byte_size ; byte_size = arg . promoted_size_in_bytes ( ) ; args_byte_size = int_regs * UNITS_PER_WORD ; offset = 0 ; for ( ; ( offset < byte_size && fp_regs < MAX_ARGUMENT_SLOTS && args_byte_size < ( MAX_ARGUMENT_SLOTS * UNITS_PER_WORD ) ) ; ) { offset += hfa_size ; args_byte_size += hfa_size ; fp_regs ++ ; } cum -> fp_regs = fp_regs ; } else if ( arg . mode == TFmode || arg . mode == TCmode || ! FLOAT_MODE_P ( arg . mode ) || cum -> fp_regs == MAX_ARGUMENT_SLOTS ) cum -> int_regs = cum -> words ; else if ( cum -> prototype ) { if ( ! arg . named ) cum -> int_regs = cum -> words ; else cum -> fp_regs += ( GET_MODE_CLASS ( arg . mode ) == MODE_COMPLEX_FLOAT ? 2 : 1 ) ; } else { cum -> fp_regs += ( GET_MODE_CLASS ( arg . mode ) == MODE_COMPLEX_FLOAT ? 2 : 1 ) ; cum -> int_regs = cum -> words ; } } </s>

Update CUM to point after this argument . This is patterned after ia64_function_arg .


<s> static unsigned int ia64_function_arg_boundary ( machine_mode mode , const_tree type ) { if ( mode == TFmode && TARGET_HPUX && TARGET_ILP32 ) return PARM_BOUNDARY * 2 ; if ( type ) { if ( TYPE_ALIGN ( type ) > PARM_BOUNDARY ) return PARM_BOUNDARY * 2 ; else return PARM_BOUNDARY ; } if ( GET_MODE_BITSIZE ( mode ) > PARM_BOUNDARY ) return PARM_BOUNDARY * 2 ; else return PARM_BOUNDARY ; } </s>

Arguments with alignment larger than 8 bytes start at the next even boundary . On ILP32 HPUX , TFmode arguments start on next even boundary even though their normal alignment is 8 bytes . See ia64_function_arg .


<s> static pad_direction ia64_function_arg_padding ( machine_mode mode , const_tree type ) { if ( TARGET_HPUX && type && AGGREGATE_TYPE_P ( type ) && int_size_in_bytes ( type ) < UNITS_PER_WORD ) return PAD_UPWARD ; return default_function_arg_padding ( mode , type ) ; } </s>

Implement TARGET_FUNCTION_ARG_PADDING . For the HP-UX IA64 aggregate parameters are passed stored in the most significant bits of the stack slot .


<s> static int ia64_function_arg_words ( const_tree type , machine_mode mode ) { int words ; if ( mode == BLKmode ) words = int_size_in_bytes ( type ) ; else words = GET_MODE_SIZE ( mode ) ; return ( words + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ; } </s>

Return the number of words required to hold a quantity of TYPE and MODE when passed as an argument .


<s> static rtx ia64_function_incoming_arg ( cumulative_args_t cum , const function_arg_info & arg ) { return ia64_function_arg_1 ( cum , arg , true ) ; } </s>

Implement TARGET_FUNCION_INCOMING_ARG target hook .


<s> static bool ia64_function_ok_for_sibcall ( tree decl , tree exp ATTRIBUTE_UNUSED ) { if ( lookup_attribute ( "syscall_linkage" , TYPE_ATTRIBUTES ( TREE_TYPE ( current_function_decl ) ) ) ) return false ; return ( decl && ( * targetm . binds_local_p ) ( decl ) ) || TARGET_CONST_GP ; } </s>

True if it is OK to do sibling call optimization for the specified call expression EXP . DECL will be the called function , or NULL if this is an indirect call .


<s> static rtx ia64_function_value ( const_tree valtype , const_tree fn_decl_or_type , bool outgoing ATTRIBUTE_UNUSED ) { machine_mode mode ; machine_mode hfa_mode ; int unsignedp ; const_tree func = fn_decl_or_type ; if ( fn_decl_or_type && ! DECL_P ( fn_decl_or_type ) ) func = NULL ; mode = TYPE_MODE ( valtype ) ; hfa_mode = hfa_element_mode ( valtype , 0 ) ; if ( hfa_mode != VOIDmode ) { rtx loc [ 8 ] ; int i ; int hfa_size ; int byte_size ; int offset ; hfa_size = GET_MODE_SIZE ( hfa_mode ) ; byte_size = ( ( mode == BLKmode ) ? int_size_in_bytes ( valtype ) : GET_MODE_SIZE ( mode ) ) ; offset = 0 ; for ( i = 0 ; offset < byte_size ; i ++ ) { loc [ i ] = gen_rtx_EXPR_LIST ( VOIDmode , gen_rtx_REG ( hfa_mode , FR_ARG_FIRST + i ) , GEN_INT ( offset ) ) ; offset += hfa_size ; } return gen_rtx_PARALLEL ( mode , gen_rtvec_v ( i , loc ) ) ; } else if ( FLOAT_TYPE_P ( valtype ) && mode != TFmode && mode != TCmode ) return gen_rtx_REG ( mode , FR_ARG_FIRST ) ; else { bool need_parallel = false ; if ( BYTES_BIG_ENDIAN && ( mode == BLKmode || ( valtype && AGGREGATE_TYPE_P ( valtype ) ) ) ) need_parallel = true ; else if ( mode == XFmode || mode == XCmode || mode == RFmode ) need_parallel = true ; if ( need_parallel ) { rtx loc [ 8 ] ; int offset ; int bytesize ; int i ; offset = 0 ; bytesize = int_size_in_bytes ( valtype ) ; if ( bytesize == 0 ) return gen_rtx_REG ( mode , GR_RET_FIRST ) ; for ( i = 0 ; offset < bytesize ; i ++ ) { loc [ i ] = gen_rtx_EXPR_LIST ( VOIDmode , gen_rtx_REG ( DImode , GR_RET_FIRST + i ) , GEN_INT ( offset ) ) ; offset += UNITS_PER_WORD ; } return gen_rtx_PARALLEL ( mode , gen_rtvec_v ( i , loc ) ) ; } mode = promote_function_mode ( valtype , mode , & unsignedp , func ? TREE_TYPE ( func ) : NULL_TREE , true ) ; return gen_rtx_REG ( mode , GR_RET_FIRST ) ; } } </s>

Return rtx for register that holds the function return value .


<s> static bool ia64_function_value_regno_p ( const unsigned int regno ) { return ( ( regno >= GR_RET_FIRST && regno <= GR_RET_LAST ) || ( regno >= FR_RET_FIRST && regno <= FR_RET_LAST ) ) ; } </s>

Worker function for FUNCTION_VALUE_REGNO_P .


<s> static rtx ia64_gen_spec_check ( rtx_insn * insn , rtx_insn * label , ds_t ds ) { rtx op1 , pat , check_pat ; gen_func_t gen_check ; int mode_no ; mode_no = get_mode_no_for_insn ( insn ) ; gcc_assert ( mode_no >= 0 ) ; if ( label ) op1 = label ; else { gcc_assert ( ! ia64_needs_block_p ( ds ) ) ; op1 = copy_rtx ( recog_data . operand [ 1 ] ) ; } gen_check = get_spec_check_gen_function ( ds , mode_no , label == NULL_RTX , true ) ; check_pat = gen_check ( copy_rtx ( recog_data . operand [ 0 ] ) , op1 ) ; pat = PATTERN ( insn ) ; if ( GET_CODE ( pat ) == COND_EXEC ) check_pat = gen_rtx_COND_EXEC ( VOIDmode , copy_rtx ( COND_EXEC_TEST ( pat ) ) , check_pat ) ; return check_pat ; } </s>

Generate ( or regenerate ) a recovery check for INSN .


<s> static rtx ia64_gen_spec_load ( rtx insn , ds_t ts , int mode_no ) { rtx pat , new_pat ; gen_func_t gen_load ; gen_load = get_spec_load_gen_function ( ts , mode_no ) ; new_pat = gen_load ( copy_rtx ( recog_data . operand [ 0 ] ) , copy_rtx ( recog_data . operand [ 1 ] ) ) ; pat = PATTERN ( insn ) ; if ( GET_CODE ( pat ) == COND_EXEC ) new_pat = gen_rtx_COND_EXEC ( VOIDmode , copy_rtx ( COND_EXEC_TEST ( pat ) ) , new_pat ) ; return new_pat ; } </s>

If GEN_P is true , calculate the index of needed speculation check and return speculative pattern for INSN with speculative mode TS , machine mode MODE_NO and with ZERO_EXTEND ( if EXTEND_P is true ) . If GEN_P is false , just calculate the index of needed speculation check .


<s> static ia64_addr_area ia64_get_addr_area ( tree decl ) { tree model_attr ; model_attr = lookup_attribute ( "model" , DECL_ATTRIBUTES ( decl ) ) ; if ( model_attr ) { tree id ; init_idents ( ) ; id = TREE_VALUE ( TREE_VALUE ( model_attr ) ) ; if ( id == small_ident1 || id == small_ident2 ) return ADDR_AREA_SMALL ; } return ADDR_AREA_NORMAL ; } </s>

Retrieve the address area that has been chosen for the given decl .


<s> static ds_t ia64_get_insn_checked_ds ( rtx_insn * insn ) { int code = get_insn_spec_code ( insn ) ; switch ( code ) { case UNSPEC_LDA : return BEGIN_DATA | BEGIN_CONTROL ; case UNSPEC_LDS : return BEGIN_CONTROL ; case UNSPEC_LDS_A : case UNSPEC_LDSA : return BEGIN_DATA | BEGIN_CONTROL ; default : return 0 ; } } </s>

If INSN is a speculative load return a ds with the speculation types that will be checked . Otherwise [ if INSN is a normal instruction ] return 0 .


<s> static ds_t ia64_get_insn_spec_ds ( rtx_insn * insn ) { int code = get_insn_spec_code ( insn ) ; switch ( code ) { case UNSPEC_LDA : return BEGIN_DATA ; case UNSPEC_LDS : case UNSPEC_LDS_A : return BEGIN_CONTROL ; case UNSPEC_LDSA : return BEGIN_DATA | BEGIN_CONTROL ; default : return 0 ; } } </s>

If INSN is a speculative load , return a ds with the speculation types . Otherwise [ if INSN is a normal instruction ] return 0 .


<s> static tree ia64_gimplify_va_arg ( tree valist , tree type , gimple_seq * pre_p , gimple_seq * post_p ) { if ( pass_va_arg_by_reference ( type ) ) { tree ptrtype = build_pointer_type ( type ) ; tree addr = std_gimplify_va_arg_expr ( valist , ptrtype , pre_p , post_p ) ; return build_va_arg_indirect_ref ( addr ) ; } if ( ( TREE_CODE ( type ) == REAL_TYPE || TREE_CODE ( type ) == INTEGER_TYPE ) ? int_size_in_bytes ( type ) > 8 : TYPE_ALIGN ( type ) > 8 * BITS_PER_UNIT ) { tree t = fold_build_pointer_plus_hwi ( valist , 2 * UNITS_PER_WORD - 1 ) ; t = build2 ( BIT_AND_EXPR , TREE_TYPE ( t ) , t , build_int_cst ( TREE_TYPE ( t ) , - 2 * UNITS_PER_WORD ) ) ; gimplify_assign ( unshare_expr ( valist ) , t , pre_p ) ; } return std_gimplify_va_arg_expr ( valist , type , pre_p , post_p ) ; } </s>


<s>
static
void
ia64_globalize_decl_name
(
FILE
*
stream
,
tree
decl
)
{
const
char
*
name
=
XSTR
(
XEXP
(
DECL_RTL
(
decl
)
,
0
)
,
0
)
;
tree
version_attr
=
lookup_attribute
(
"version_id"
,
DECL_ATTRIBUTES
(
decl
)
)
;
if
(
version_attr
)
{
tree
v
=
TREE_VALUE
(
TREE_VALUE
(
version_attr
)
)
;
const
char
*
p
=
TREE_STRING_POINTER
(
v
)
;
fprintf
(
stream
,
"\t.alias %s#, \"%s{%s}\"\n"
,
name
,
name
,
p
)
;
}
targetm
.
asm_out
.
globalize_label
(
stream
,
name
)
;
if
(
TREE_CODE
(
decl
)
==
FUNCTION_DECL
)
ASM_OUTPUT_TYPE_DIRECTIVE
(
stream
,
name
,
"function"
)
;
}
</s>


<s> static bool ia64_hard_regno_mode_ok ( unsigned int regno , machine_mode mode ) { if ( FR_REGNO_P ( regno ) ) return ( GET_MODE_CLASS ( mode ) != MODE_CC && mode != BImode && mode != TFmode ) ; if ( PR_REGNO_P ( regno ) ) return mode == BImode || GET_MODE_CLASS ( mode ) == MODE_CC ; if ( GR_REGNO_P ( regno ) ) return mode != XFmode && mode != XCmode && mode != RFmode ; if ( AR_REGNO_P ( regno ) ) return mode == DImode ; if ( BR_REGNO_P ( regno ) ) return mode == DImode ; return false ; } </s>


<s> ATTRIBUTE_UNUSED static section * ia64_hpux_function_section ( tree decl ATTRIBUTE_UNUSED , enum node_frequency freq ATTRIBUTE_UNUSED , bool startup ATTRIBUTE_UNUSED , bool exit ATTRIBUTE_UNUSED ) { return NULL ; } </s>

Always default to .text section until HP-UX linker is fixed .


<s> static void ia64_hpux_init_libfuncs ( void ) { ia64_init_libfuncs ( ) ; set_optab_libfunc ( sdiv_optab , SImode , 0 ) ; set_optab_libfunc ( udiv_optab , SImode , 0 ) ; set_optab_libfunc ( smod_optab , SImode , 0 ) ; set_optab_libfunc ( umod_optab , SImode , 0 ) ; set_optab_libfunc ( sdiv_optab , DImode , "__milli_divI" ) ; set_optab_libfunc ( udiv_optab , DImode , "__milli_divU" ) ; set_optab_libfunc ( smod_optab , DImode , "__milli_remI" ) ; set_optab_libfunc ( umod_optab , DImode , "__milli_remU" ) ; set_optab_libfunc ( smin_optab , TFmode , "_U_Qfmin" ) ; set_optab_libfunc ( smax_optab , TFmode , "_U_Qfmax" ) ; set_optab_libfunc ( abs_optab , TFmode , "_U_Qfabs" ) ; cmptf_libfunc = init_one_libfunc ( "_U_Qfcmp" ) ; set_optab_libfunc ( eq_optab , TFmode , 0 ) ; set_optab_libfunc ( ne_optab , TFmode , 0 ) ; set_optab_libfunc ( gt_optab , TFmode , 0 ) ; set_optab_libfunc ( ge_optab , TFmode , 0 ) ; set_optab_libfunc ( lt_optab , TFmode , 0 ) ; set_optab_libfunc ( le_optab , TFmode , 0 ) ; } </s>

Rename all the TFmode libfuncs using the HPUX conventions .


<s> static int ia64_hpux_reloc_rw_mask ( void ) { return 3 ; } </s>

For HPUX , it is illegal to have relocations in shared segments .


<s> static void ia64_h_i_d_extended ( void ) { if ( stops_p != NULL ) { int new_clocks_length = get_max_uid ( ) * 3 / 2 ; stops_p = ( char * ) xrecalloc ( stops_p , new_clocks_length , clocks_length , 1 ) ; clocks_length = new_clocks_length ; } } </s>

Implement targetm.sched.h_i_d_extended hook . Extend internal data structures .


<s> HOST_WIDE_INT ia64_initial_elimination_offset ( int from , int to ) { HOST_WIDE_INT offset ; ia64_compute_frame_size ( get_frame_size ( ) ) ; switch ( from ) { case FRAME_POINTER_REGNUM : switch ( to ) { case HARD_FRAME_POINTER_REGNUM : offset = - current_frame_info . total_size ; if ( ! crtl -> is_leaf || cfun -> calls_alloca ) offset += 16 + crtl -> outgoing_args_size ; break ; case STACK_POINTER_REGNUM : offset = 0 ; if ( ! crtl -> is_leaf || cfun -> calls_alloca ) offset += 16 + crtl -> outgoing_args_size ; break ; default : gcc_unreachable ( ) ; } break ; case ARG_POINTER_REGNUM : switch ( to ) { case HARD_FRAME_POINTER_REGNUM : offset = 16 - crtl -> args . pretend_args_size ; break ; case STACK_POINTER_REGNUM : offset = ( current_frame_info . total_size + 16 - crtl -> args . pretend_args_size ) ; break ; default : gcc_unreachable ( ) ; } break ; default : gcc_unreachable ( ) ; } return offset ; } </s>

Compute the initial difference between the specified pair of registers .


<s> static void ia64_init_dfa_pre_cycle_insn ( void ) { if ( temp_dfa_state == NULL ) { dfa_state_size = state_size ( ) ; temp_dfa_state = xmalloc ( dfa_state_size ) ; prev_cycle_state = xmalloc ( dfa_state_size ) ; } dfa_pre_cycle_insn = make_insn_raw ( gen_pre_cycle ( ) ) ; SET_PREV_INSN ( dfa_pre_cycle_insn ) = SET_NEXT_INSN ( dfa_pre_cycle_insn ) = NULL_RTX ; recog_memoized ( dfa_pre_cycle_insn ) ; dfa_stop_insn = make_insn_raw ( gen_insn_group_barrier ( GEN_INT ( 3 ) ) ) ; SET_PREV_INSN ( dfa_stop_insn ) = SET_NEXT_INSN ( dfa_stop_insn ) = NULL_RTX ; recog_memoized ( dfa_stop_insn ) ; } </s>

The following function initiates variable ` dfa_pre_cycle_insn ' .


<s> static void ia64_init_libfuncs ( void ) { set_optab_libfunc ( sdiv_optab , SImode , "__divsi3" ) ; set_optab_libfunc ( udiv_optab , SImode , "__udivsi3" ) ; set_optab_libfunc ( smod_optab , SImode , "__modsi3" ) ; set_optab_libfunc ( umod_optab , SImode , "__umodsi3" ) ; set_optab_libfunc ( add_optab , TFmode , "_U_Qfadd" ) ; set_optab_libfunc ( sub_optab , TFmode , "_U_Qfsub" ) ; set_optab_libfunc ( smul_optab , TFmode , "_U_Qfmpy" ) ; set_optab_libfunc ( sdiv_optab , TFmode , "_U_Qfdiv" ) ; set_optab_libfunc ( neg_optab , TFmode , "_U_Qfneg" ) ; set_conv_libfunc ( sext_optab , TFmode , SFmode , "_U_Qfcnvff_sgl_to_quad" ) ; set_conv_libfunc ( sext_optab , TFmode , DFmode , "_U_Qfcnvff_dbl_to_quad" ) ; set_conv_libfunc ( sext_optab , TFmode , XFmode , "_U_Qfcnvff_f80_to_quad" ) ; set_conv_libfunc ( trunc_optab , SFmode , TFmode , "_U_Qfcnvff_quad_to_sgl" ) ; set_conv_libfunc ( trunc_optab , DFmode , TFmode , "_U_Qfcnvff_quad_to_dbl" ) ; set_conv_libfunc ( trunc_optab , XFmode , TFmode , "_U_Qfcnvff_quad_to_f80" ) ; set_conv_libfunc ( sfix_optab , SImode , TFmode , "_U_Qfcnvfxt_quad_to_sgl" ) ; set_conv_libfunc ( sfix_optab , DImode , TFmode , "_U_Qfcnvfxt_quad_to_dbl" ) ; set_conv_libfunc ( sfix_optab , TImode , TFmode , "_U_Qfcnvfxt_quad_to_quad" ) ; set_conv_libfunc ( ufix_optab , SImode , TFmode , "_U_Qfcnvfxut_quad_to_sgl" ) ; set_conv_libfunc ( ufix_optab , DImode , TFmode , "_U_Qfcnvfxut_quad_to_dbl" ) ; set_conv_libfunc ( sfloat_optab , TFmode , SImode , "_U_Qfcnvxf_sgl_to_quad" ) ; set_conv_libfunc ( sfloat_optab , TFmode , DImode , "_U_Qfcnvxf_dbl_to_quad" ) ; set_conv_libfunc ( sfloat_optab , TFmode , TImode , "_U_Qfcnvxf_quad_to_quad" ) ; set_conv_libfunc ( ufloat_optab , TFmode , DImode , "_U_Qfcnvxuf_dbl_to_quad" ) ; } </s>

Set SImode div/mod functions , init_integral_libfuncs only initializes modes of word_mode and larger . Rename the TFmode libfuncs using the HPUX conventions . __divtf3 is used for XFmode . We need to keep it for backward compatibility .


<s> static void ia64_init_sched_context ( void * _sc , bool clean_p ) { ia64_sched_context_t sc = ( ia64_sched_context_t ) _sc ; sc -> prev_cycle_state = xmalloc ( dfa_state_size ) ; if ( clean_p ) { state_reset ( sc -> prev_cycle_state ) ; sc -> last_scheduled_insn = NULL ; memset ( sc -> rws_sum , 0 , sizeof ( rws_sum ) ) ; memset ( sc -> rws_insn , 0 , sizeof ( rws_insn ) ) ; sc -> first_instruction = 1 ; sc -> pending_data_specs = 0 ; sc -> current_cycle = 0 ; memset ( sc -> mem_ops_in_group , 0 , sizeof ( mem_ops_in_group ) ) ; } else { memcpy ( sc -> prev_cycle_state , prev_cycle_state , dfa_state_size ) ; sc -> last_scheduled_insn = last_scheduled_insn ; memcpy ( sc -> rws_sum , rws_sum , sizeof ( rws_sum ) ) ; memcpy ( sc -> rws_insn , rws_insn , sizeof ( rws_insn ) ) ; sc -> first_instruction = first_instruction ; sc -> pending_data_specs = pending_data_specs ; sc -> current_cycle = current_cycle ; memcpy ( sc -> mem_ops_in_group , mem_ops_in_group , sizeof ( mem_ops_in_group ) ) ; } } </s>

Initializes the _SC context with clean data , if CLEAN_P , and from the global context otherwise .


<s>
static
const
char
*
ia64_invalid_binary_op
(
int
op
ATTRIBUTE_UNUSED
,
const_tree
type1
,
const_tree
type2
)
{
if
(
TYPE_MODE
(
type1
)
==
RFmode
||
TYPE_MODE
(
type2
)
==
RFmode
)
return
N_
(
"invalid operation on %<__fpreg%>"
)
;
return
;
}
</s>

Return the diagnostic message string if the binary operation OP is not permitted on TYPE1 and TYPE2 , NULL otherwise .


<s>
static
const
char
*
ia64_invalid_conversion
(
const_tree
fromtype
,
const_tree
totype
)
{
if
(
TYPE_MODE
(
fromtype
)
==
RFmode
&&
TYPE_MODE
(
totype
)
!=
RFmode
&&
TYPE_MODE
(
totype
)
!=
VOIDmode
)
return
N_
(
"invalid conversion from %<__fpreg%>"
)
;
if
(
TYPE_MODE
(
totype
)
==
RFmode
&&
TYPE_MODE
(
fromtype
)
!=
RFmode
)
return
N_
(
"invalid conversion to %<__fpreg%>"
)
;
return
;
}
</s>

Return the diagnostic message string if conversion from FROMTYPE to TOTYPE is not allowed , NULL otherwise .

ia64
"invalid conversion from %<__fpreg%>"
"invalid conversion to %<__fpreg%>"


<s>
static
const
char
*
ia64_invalid_unary_op
(
int
op
,
const_tree
type
)
{
if
(
TYPE_MODE
(
type
)
==
RFmode
&&
op
!=
CONVERT_EXPR
&&
op
!=
ADDR_EXPR
)
return
N_
(
"invalid operation on %<__fpreg%>"
)
;
return
;
}
</s>

Return the diagnostic message string if the unary operation OP is not permitted on TYPE , NULL otherwise .


<s> static int ia64_issue_rate ( void ) { return 6 ; } </s>

Return the maximum number of instructions a cpu can issue .


<s> int ia64_ld_address_bypass_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx dest , src , reg , mem ; gcc_assert ( producer && consumer ) ; dest = ia64_single_set ( producer ) ; gcc_assert ( dest ) ; reg = SET_DEST ( dest ) ; gcc_assert ( reg ) ; if ( GET_CODE ( reg ) == SUBREG ) reg = SUBREG_REG ( reg ) ; gcc_assert ( GET_CODE ( reg ) == REG ) ; src = ia64_single_set ( consumer ) ; gcc_assert ( src ) ; mem = SET_SRC ( src ) ; gcc_assert ( mem ) ; if ( GET_CODE ( mem ) == UNSPEC && XVECLEN ( mem , 0 ) > 0 ) mem = XVECEXP ( mem , 0 , 0 ) ; else if ( GET_CODE ( mem ) == IF_THEN_ELSE ) { gcc_assert ( XINT ( XEXP ( XEXP ( mem , 0 ) , 0 ) , 1 ) == UNSPEC_LDCCLR ) ; mem = XEXP ( mem , 1 ) ; } while ( GET_CODE ( mem ) == SUBREG || GET_CODE ( mem ) == ZERO_EXTEND ) mem = XEXP ( mem , 0 ) ; if ( GET_CODE ( mem ) == UNSPEC ) { int c = XINT ( mem , 1 ) ; gcc_assert ( c == UNSPEC_LDA || c == UNSPEC_LDS || c == UNSPEC_LDS_A || c == UNSPEC_LDSA ) ; mem = XVECEXP ( mem , 0 , 0 ) ; } gcc_assert ( GET_CODE ( mem ) == LO_SUM || GET_CODE ( mem ) == MEM ) ; return reg_mentioned_p ( reg , mem ) ; } </s>

The following function returns TRUE if PRODUCER ( of type ilog or ld ) produces address for CONSUMER ( of type ld or fld ) .


<s> static bool ia64_legitimate_address_p ( machine_mode mode ATTRIBUTE_UNUSED , rtx x , bool strict ) { if ( ia64_legitimate_address_reg ( x , strict ) ) return true ; else if ( ( GET_CODE ( x ) == POST_INC || GET_CODE ( x ) == POST_DEC ) && ia64_legitimate_address_reg ( XEXP ( x , 0 ) , strict ) && XEXP ( x , 0 ) != arg_pointer_rtx ) return true ; else if ( GET_CODE ( x ) == POST_MODIFY && ia64_legitimate_address_reg ( XEXP ( x , 0 ) , strict ) && XEXP ( x , 0 ) != arg_pointer_rtx && ia64_legitimate_address_disp ( XEXP ( x , 0 ) , XEXP ( x , 1 ) , strict ) ) return true ; else return false ; } </s>


<s> static bool ia64_legitimate_constant_p ( machine_mode mode , rtx x ) { switch ( GET_CODE ( x ) ) { case CONST_INT : case LABEL_REF : return true ; case CONST_DOUBLE : if ( GET_MODE ( x ) == VOIDmode || mode == SFmode || mode == DFmode ) return true ; return satisfies_constraint_G ( x ) ; case CONST : case SYMBOL_REF : if ( tls_symbolic_operand_type ( x ) == 0 ) { HOST_WIDE_INT addend = 0 ; rtx op = x ; if ( GET_CODE ( op ) == CONST && GET_CODE ( XEXP ( op , 0 ) ) == PLUS && GET_CODE ( XEXP ( XEXP ( op , 0 ) , 1 ) ) == CONST_INT ) { addend = INTVAL ( XEXP ( XEXP ( op , 0 ) , 1 ) ) ; op = XEXP ( XEXP ( op , 0 ) , 0 ) ; } if ( any_offset_symbol_operand ( op , mode ) || function_operand ( op , mode ) ) return true ; if ( aligned_offset_symbol_operand ( op , mode ) ) return ( addend & 0x3fff ) == 0 ; return false ; } return false ; case CONST_VECTOR : if ( mode == V2SFmode ) return satisfies_constraint_Y ( x ) ; return ( GET_MODE_CLASS ( mode ) == MODE_VECTOR_INT && GET_MODE_SIZE ( mode ) <= 8 ) ; default : return false ; } } </s>

Return true if X is a constant that is valid for some immediate field in an instruction .


<s> static rtx ia64_libcall_value ( machine_mode mode , const_rtx fun ATTRIBUTE_UNUSED ) { return gen_rtx_REG ( mode , ( ( ( GET_MODE_CLASS ( mode ) == MODE_FLOAT || GET_MODE_CLASS ( mode ) == MODE_COMPLEX_FLOAT ) && ( mode ) != TFmode ) ? FR_RET_FIRST : GR_RET_FIRST ) ) ; } </s>

Worker function for TARGET_LIBCALL_VALUE .


<s> int ia64_load_pair_ok ( rtx dst , rtx src ) { if ( GET_CODE ( dst ) != REG || ! ( FP_REGNO_P ( REGNO ( dst ) ) && FP_REGNO_P ( REGNO ( dst ) + 1 ) ) ) return 0 ; if ( GET_CODE ( src ) != MEM || MEM_VOLATILE_P ( src ) ) return 0 ; switch ( GET_CODE ( XEXP ( src , 0 ) ) ) { case REG : case POST_INC : break ; case POST_DEC : return 0 ; case POST_MODIFY : { rtx adjust = XEXP ( XEXP ( XEXP ( src , 0 ) , 1 ) , 1 ) ; if ( GET_CODE ( adjust ) != CONST_INT || INTVAL ( adjust ) != GET_MODE_SIZE ( GET_MODE ( src ) ) ) return 0 ; } break ; default : abort ( ) ; } return 1 ; } </s>

Return 1 if the operands are ok for a floating point load pair .


<s> static const char * ia64_mangle_type ( const_tree type ) { type = TYPE_MAIN_VARIANT ( type ) ; if ( TREE_CODE ( type ) != VOID_TYPE && TREE_CODE ( type ) != BOOLEAN_TYPE && TREE_CODE ( type ) != INTEGER_TYPE && TREE_CODE ( type ) != REAL_TYPE ) return NULL ; if ( ! TARGET_HPUX && TYPE_MODE ( type ) == TFmode ) return "g" ; if ( TYPE_MODE ( type ) == XFmode ) return TARGET_HPUX ? "u9__float80" : "e" ; if ( TYPE_MODE ( type ) == RFmode ) return "u7__fpreg" ; return NULL ; } </s>

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


<s> static int ia64_memory_move_cost ( machine_mode mode ATTRIBUTE_UNUSED , reg_class_t rclass , bool in ATTRIBUTE_UNUSED ) { if ( rclass == GENERAL_REGS || rclass == FR_REGS || rclass == FP_REGS || rclass == GR_AND_FR_REGS ) return 4 ; else return 10 ; } </s>

Calculate the cost of moving data of MODE from a register to or from memory .


<s> static bool ia64_modes_tieable_p ( machine_mode mode1 , machine_mode mode2 ) { return ( GET_MODE_CLASS ( mode1 ) == GET_MODE_CLASS ( mode2 ) && ( ( mode1 == XFmode || mode1 == XCmode || mode1 == RFmode ) == ( mode2 == XFmode || mode2 == XCmode || mode2 == RFmode ) ) && ( mode1 == BImode ) == ( mode2 == BImode ) ) ; } </s>

Implement TARGET_MODES_TIEABLE_P . Do n't tie integer and FP modes , as that causes us to get integer registers allocated for FP instructions . XFmode only supported in FP registers so we ca n't tie it with any other modes .


<s> static int ia64_mode_to_int ( machine_mode mode ) { switch ( mode ) { case E_BImode : return 0 ; case E_QImode : return 1 ; case E_HImode : return 2 ; case E_SImode : return 3 ; case E_DImode : return 4 ; case E_SFmode : return 5 ; case E_DFmode : return 6 ; case E_XFmode : return 7 ; case E_TImode : return SPEC_MODE_INVALID ; default : return SPEC_MODE_INVALID ; } } </s>


<s> int ia64_move_ok ( rtx dst , rtx src ) { if ( GET_CODE ( dst ) != MEM ) return 1 ; if ( GET_CODE ( src ) == MEM ) return 0 ; if ( register_operand ( src , VOIDmode ) ) return 1 ; if ( INTEGRAL_MODE_P ( GET_MODE ( dst ) ) ) return src == const0_rtx ; else return satisfies_constraint_G ( src ) ; } </s>

Return 1 if the operands of a move are ok .


<s> static bool ia64_needs_block_p ( ds_t ts ) { if ( ts & BEGIN_DATA ) return ! mflag_sched_spec_ldc ; gcc_assert ( ( ts & BEGIN_CONTROL ) != 0 ) ; return ! ( mflag_sched_spec_control_ldc && mflag_sched_spec_ldc ) ; } </s>

Return nonzero , if INSN needs branchy recovery check .


<s> static void ia64_option_override ( void ) { unsigned int i ; cl_deferred_option * opt ; vec < cl_deferred_option > * v = ( vec < cl_deferred_option > * ) ia64_deferred_options ; if ( v ) FOR_EACH_VEC_ELT ( * v , i , opt ) { switch ( opt -> opt_index ) { case OPT_mfixed_range_ : fix_range ( opt -> arg ) ; break ; default : gcc_unreachable ( ) ; } } if ( TARGET_AUTO_PIC ) target_flags |= MASK_CONST_GP ; if ( optimize >= 3 ) flag_ira_loop_pressure = 1 ; ia64_section_threshold = ( OPTION_SET_P ( g_switch_value ) ? g_switch_value : IA64_DEFAULT_GVALUE ) ; init_machine_status = ia64_init_machine_status ; if ( flag_align_functions && ! str_align_functions ) str_align_functions = "64" ; if ( flag_align_loops && ! str_align_loops ) str_align_loops = "32" ; if ( TARGET_ABI_OPEN_VMS ) flag_no_common = 1 ; ia64_override_options_after_change ( ) ; } </s>


<s> static void ia64_output_dwarf_dtprel ( FILE * file , int size , rtx x ) { gcc_assert ( size == 4 || size == 8 ) ; if ( size == 4 ) fputs ( "\tdata4.ua\t@dtprel(" , file ) ; else fputs ( "\tdata8.ua\t@dtprel(" , file ) ; output_addr_const ( file , x ) ; fputs ( ")" , file ) ; } </s>

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


<s> static void ia64_output_function_end_prologue ( FILE * file ) { if ( ia64_except_unwind_info ( & global_options ) != UI_TARGET ) return ; fputs ( "\t.body\n" , file ) ; } </s>

Emit the .body directive at the scheduled end of the prologue .


<s> static void ia64_output_function_epilogue ( FILE * ) { int i ; if ( current_frame_info . r [ reg_fp ] ) { const char * tmp = reg_names [ HARD_FRAME_POINTER_REGNUM ] ; reg_names [ HARD_FRAME_POINTER_REGNUM ] = reg_names [ current_frame_info . r [ reg_fp ] ] ; reg_names [ current_frame_info . r [ reg_fp ] ] = tmp ; reg_emitted ( reg_fp ) ; } if ( ! TARGET_REG_NAMES ) { for ( i = 0 ; i < current_frame_info . n_input_regs ; i ++ ) reg_names [ IN_REG ( i ) ] = ia64_input_reg_names [ i ] ; for ( i = 0 ; i < current_frame_info . n_local_regs ; i ++ ) reg_names [ LOC_REG ( i ) ] = ia64_local_reg_names [ i ] ; for ( i = 0 ; i < current_frame_info . n_output_regs ; i ++ ) reg_names [ OUT_REG ( i ) ] = ia64_output_reg_names [ i ] ; } current_frame_info . initialized = 0 ; } </s>


"\taddl r14 = @ltoff(@fptr(_mcount)), r1\n"

"\tbr.call.sptk.many b0 = _mcount\n\t;;\n"


<s>
static
void
ia64_output_function_prologue
(
FILE
*
file
)
{
int
mask
,
grsave
,
grsave_prev
;
if
(
current_frame_info
.
need_regstk
)
fprintf
(
file
,
"\t.regstk %d, %d, %d, %d\n"
,
current_frame_info
.
n_input_regs
,
current_frame_info
.
n_local_regs
,
current_frame_info
.
n_output_regs
,
current_frame_info
.
n_rotate_regs
)
;
if
(
ia64_except_unwind_info
(
&
global_options
)
!=
UI_TARGET
)
return
;
mask
=
0
;
grsave
=
grsave_prev
=
0
;
if
(
current_frame_info
.
r
[
reg_save_b0
]
!=
0
)
{
mask
|=
8
;
grsave
=
grsave_prev
=
current_frame_info
.
r
[
reg_save_b0
]
;
}
if
(
current_frame_info
.
r
[
reg_save_ar_pfs
]
!=
0
&&
(
grsave_prev
==
0
||
current_frame_info
.
r
[
reg_save_ar_pfs
]
==
grsave_prev
+
1
)
)
{
mask
|=
4
;
if
(
grsave_prev
==
0
)
grsave
=
current_frame_info
.
r
[
reg_save_ar_pfs
]
;
grsave_prev
=
current_frame_info
.
r
[
reg_save_ar_pfs
]
;
}
if
(
current_frame_info
.
r
[
reg_fp
]
!=
0
&&
(
grsave_prev
==
0
||
current_frame_info
.
r
[
reg_fp
]
==
grsave_prev
+
1
)
)
{
mask
|=
2
;
if
(
grsave_prev
==
0
)
grsave
=
HARD_FRAME_POINTER_REGNUM
;
grsave_prev
=
current_frame_info
.
r
[
reg_fp
]
;
}
if
(
current_frame_info
.
r
[
reg_save_pr
]
!=
0
&&
(
grsave_prev
==
0
||
current_frame_info
.
r
[
reg_save_pr
]
==
grsave_prev
+
1
)
)
{
mask
|=
1
;
if
(
grsave_prev
==
0
)
grsave
=
current_frame_info
.
r
[
reg_save_pr
]
;
}
if
(
mask
&&
TARGET_GNU_AS
)
fprintf
(
file
,
"\t.prologue %d, %d\n"
,
mask
,
ia64_dbx_register_number
(
grsave
)
)
;
else
fputs
(
"\t.prologue\n"
,
file
)
;
if
(
current_frame_info
.
spill_cfa_off
!=
16
)
fprintf
(
file
,
"\t.spill %ld\n"
,
(
long
)
(
current_frame_info
.
spill_cfa_off
+
current_frame_info
.
spill_size
)
)
;
}
</s>


<s> static void ia64_override_options_after_change ( void ) { if ( optimize >= 3 && ! OPTION_SET_P ( flag_selective_scheduling ) && ! OPTION_SET_P ( flag_selective_scheduling2 ) ) { flag_selective_scheduling2 = 1 ; flag_sel_sched_pipelining = 1 ; } if ( mflag_sched_control_spec == 2 ) { mflag_sched_control_spec = flag_selective_scheduling2 ? 1 : 0 ; } if ( flag_sel_sched_pipelining && flag_auto_inc_dec ) { flag_auto_inc_dec = 0 ; } } </s>


<s> static reg_class_t ia64_preferred_reload_class ( rtx x , reg_class_t rclass ) { switch ( rclass ) { case FR_REGS : case FP_REGS : if ( MEM_P ( x ) && MEM_VOLATILE_P ( x ) ) return NO_REGS ; if ( CONSTANT_P ( x ) ) return NO_REGS ; break ; case AR_M_REGS : case AR_I_REGS : if ( ! OBJECT_P ( x ) ) return NO_REGS ; break ; default : break ; } return rclass ; } </s>

Implement PREFERRED_RELOAD_CLASS . Place additional restrictions on CLASS to use when copying X into that class .


<s> static bool ia64_print_operand_punct_valid_p ( unsigned char code ) { return ( code == '+' || code == ',' ) ; } </s>

Worker function for TARGET_PRINT_OPERAND_PUNCT_VALID_P .


<s> int ia64_produce_address_p ( rtx insn ) { return insn -> call ; } </s>

The following function returns TRUE if INSN produces address for a load/store insn . We will place such insns into M slot because it decreases its latency time .


<s> static int ia64_register_move_cost ( machine_mode mode , reg_class_t from , reg_class_t to ) { if ( to == ADDL_REGS ) to = GR_REGS ; if ( from == ADDL_REGS ) from = GR_REGS ; if ( from < to ) { reg_class_t tmp = to ; to = from , from = tmp ; } if ( mode == XFmode || mode == RFmode ) { if ( to != GR_REGS || from != GR_REGS ) return memory_move_cost ( mode , to , false ) ; else return 3 ; } switch ( to ) { case PR_REGS : if ( from == PR_REGS ) return 3 ; if ( from != GR_REGS ) return memory_move_cost ( mode , to , false ) ; break ; case BR_REGS : if ( from != GR_REGS && from != GR_AND_BR_REGS ) return memory_move_cost ( mode , to , false ) ; break ; case AR_I_REGS : case AR_M_REGS : if ( from != GR_REGS ) return memory_move_cost ( mode , to , false ) ; break ; case GR_REGS : case FR_REGS : case FP_REGS : case GR_AND_FR_REGS : case GR_AND_BR_REGS : case ALL_REGS : break ; default : gcc_unreachable ( ) ; } return 2 ; } </s>

Calulate the cost of moving data from a register in class FROM to one in class TO , using MODE .


<s> static inline bool ia64_reg_ok_for_base_p ( const_rtx reg , bool strict ) { if ( strict && REGNO_OK_FOR_BASE_P ( REGNO ( reg ) ) ) return true ; else if ( ! strict && ( GENERAL_REGNO_P ( REGNO ( reg ) ) || ! HARD_REGISTER_P ( reg ) ) ) return true ; else return false ; } </s>

Returns true if REG ( assumed to be a ` reg ' RTX ) is valid for use as a base register .


<s> static int ia64_reloc_rw_mask ( void ) { return flag_pic ? 3 : 2 ; } </s>

For others , relax this so that relocations to local data goes in read-only segments , but we still can not allow global relocations in read-only segments .


<s> rtx ia64_return_addr_rtx ( HOST_WIDE_INT count , rtx frame ATTRIBUTE_UNUSED ) { if ( count != 0 ) return NULL ; return gen_rtx_UNSPEC ( Pmode , gen_rtvec ( 1 , const0_rtx ) , UNSPEC_RET_ADDR ) ; } </s>

Return the magic cookie that we use to hold the return address during early compilation .


<s> static bool ia64_return_in_memory ( const_tree valtype , const_tree fntype ATTRIBUTE_UNUSED ) { machine_mode mode ; machine_mode hfa_mode ; HOST_WIDE_INT byte_size ; mode = TYPE_MODE ( valtype ) ; byte_size = GET_MODE_SIZE ( mode ) ; if ( mode == BLKmode ) { byte_size = int_size_in_bytes ( valtype ) ; if ( byte_size < 0 ) return true ; } hfa_mode = hfa_element_mode ( valtype , 0 ) ; if ( hfa_mode != VOIDmode ) { int hfa_size = GET_MODE_SIZE ( hfa_mode ) ; if ( byte_size / hfa_size > MAX_ARGUMENT_SLOTS ) return true ; else return false ; } else if ( byte_size > UNITS_PER_WORD * MAX_INT_RETURN_SLOTS ) return true ; else return false ; } </s>

Return 1 if function return value returned in memory . Return 0 if it is in a register .


<s>
static
void
ia64_sched_finish
(
FILE
*
dump
,
int
sched_verbose
)
{
if
(
sched_verbose
)
fprintf
(
dump
,
"// Finishing schedule.\n"
)
;
if
(
!
reload_completed
)
return
;
if
(
reload_completed
)
{
final_emit_insn_group_barriers
(
dump
)
;
bundling
(
dump
,
sched_verbose
,
current_sched_info
->
prev_head
,
current_sched_info
->
next_tail
)
;
if
(
sched_verbose
&&
dump
)
fprintf
(
dump
,
"//    finishing %d-%d\n"
,
INSN_UID
(
NEXT_INSN
(
current_sched_info
->
prev_head
)
)
,
INSN_UID
(
PREV_INSN
(
current_sched_info
->
next_tail
)
)
)
;
return
;
}
}
</s>

Free data allocated by ia64_sched_init .

ia64
"// Finishing schedule.\n"
"//    finishing %d-%d\n"


<s> static int ia64_sched_reorder ( FILE * dump , int sched_verbose , rtx_insn * * ready , int * pn_ready , int clock_var ) { return ia64_dfa_sched_reorder ( dump , sched_verbose , ready , pn_ready , clock_var , 0 ) ; } </s>

We are about to being issuing insns for this clock cycle . Override the default sort algorithm to better slot instructions .


<s> enum reg_class ia64_secondary_reload_class ( enum reg_class rclass , machine_mode mode ATTRIBUTE_UNUSED , rtx x ) { int regno = - 1 ; if ( GET_CODE ( x ) == REG || GET_CODE ( x ) == SUBREG ) regno = true_regnum ( x ) ; switch ( rclass ) { case BR_REGS : case AR_M_REGS : case AR_I_REGS : if ( regno >= 0 && ! GENERAL_REGNO_P ( regno ) ) return GR_REGS ; if ( GET_CODE ( x ) == MEM ) return GR_REGS ; break ; case FR_REGS : case FP_REGS : if ( regno >= 0 && ! ( FR_REGNO_P ( regno ) || GENERAL_REGNO_P ( regno ) ) ) return GR_REGS ; if ( GET_CODE ( x ) == MEM && ( GET_MODE ( x ) == SImode || GET_MODE ( x ) == HImode || GET_MODE ( x ) == QImode ) ) return GR_REGS ; if ( GET_CODE ( x ) == CONST_INT ) return GR_REGS ; if ( GET_CODE ( x ) == PLUS ) return GR_REGS ; break ; case PR_REGS : if ( GET_CODE ( x ) == MEM ) return GR_REGS ; if ( regno >= 0 && ! GENERAL_REGNO_P ( regno ) && ! PR_REGNO_P ( regno ) ) return GR_REGS ; break ; default : break ; } return NO_REGS ; } </s>

This function returns the register class required for a secondary register when copying between one of the registers in CLASS , and X , using MODE . A return value of NO_REGS means that no secondary register is required .


<s> static section * ia64_select_rtx_section ( machine_mode mode , rtx x , unsigned HOST_WIDE_INT align ) { if ( GET_MODE_SIZE ( mode ) > 0 && GET_MODE_SIZE ( mode ) <= ia64_section_threshold && ! TARGET_NO_SDATA ) return sdata_section ; else return default_elf_select_rtx_section ( mode , x , align ) ; } </s>

Switch to the section to which we should output X . The only thing special we do here is to honor small data .


<s> static void ia64_setup_incoming_varargs ( cumulative_args_t cum , const function_arg_info & arg , int * pretend_size , int second_time ATTRIBUTE_UNUSED ) { CUMULATIVE_ARGS next_cum = * get_cumulative_args ( cum ) ; ia64_function_arg_advance ( pack_cumulative_args ( & next_cum ) , arg ) ; if ( next_cum . words < MAX_ARGUMENT_SLOTS ) { int n = MAX_ARGUMENT_SLOTS - next_cum . words ; * pretend_size = n * UNITS_PER_WORD ; cfun -> machine -> n_varargs = n ; } } </s>

Do any needed setup for a variadic function . CUM has not been updated for the last named argument which has type TYPE and mode MODE . We generate the actual spill instructions during prologue generation .


<s> static void ia64_set_sched_context ( void * _sc ) { ia64_sched_context_t sc = ( ia64_sched_context_t ) _sc ; gcc_assert ( sc != NULL ) ; memcpy ( prev_cycle_state , sc -> prev_cycle_state , dfa_state_size ) ; last_scheduled_insn = sc -> last_scheduled_insn ; memcpy ( rws_sum , sc -> rws_sum , sizeof ( rws_sum ) ) ; memcpy ( rws_insn , sc -> rws_insn , sizeof ( rws_insn ) ) ; first_instruction = sc -> first_instruction ; pending_data_specs = sc -> pending_data_specs ; current_cycle = sc -> current_cycle ; memcpy ( mem_ops_in_group , sc -> mem_ops_in_group , sizeof ( mem_ops_in_group ) ) ; } </s>

Sets the global scheduling context to the one pointed to by _SC .


<s> static void ia64_set_sched_flags ( spec_info_t spec_info ) { unsigned int * flags = & ( current_sched_info -> flags ) ; if ( * flags & SCHED_RGN || * flags & SCHED_EBB || * flags & SEL_SCHED ) { int mask = 0 ; if ( ( mflag_sched_br_data_spec && ! reload_completed && optimize > 0 ) || ( mflag_sched_ar_data_spec && reload_completed ) ) { mask |= BEGIN_DATA ; if ( ! sel_sched_p ( ) && ( ( mflag_sched_br_in_data_spec && ! reload_completed ) || ( mflag_sched_ar_in_data_spec && reload_completed ) ) ) mask |= BE_IN_DATA ; } if ( mflag_sched_control_spec && ( ! sel_sched_p ( ) || reload_completed ) ) { mask |= BEGIN_CONTROL ; if ( ! sel_sched_p ( ) && mflag_sched_in_control_spec ) mask |= BE_IN_CONTROL ; } spec_info -> mask = mask ; if ( mask ) { * flags |= USE_DEPS_LIST | DO_SPECULATION ; if ( mask & BE_IN_SPEC ) * flags |= NEW_BBS ; spec_info -> flags = 0 ; if ( ( mask & CONTROL_SPEC ) && sel_sched_p ( ) && mflag_sel_sched_dont_check_control_spec ) spec_info -> flags |= SEL_SCHED_SPEC_DONT_CHECK_CONTROL ; if ( sched_verbose >= 1 ) spec_info -> dump = sched_dump ; else spec_info -> dump = 0 ; if ( mflag_sched_count_spec_in_critical_path ) spec_info -> flags |= COUNT_SPEC_IN_CRITICAL_PATH ; } } else spec_info -> mask = 0 ; } </s>

Provide information about speculation capabilities .


<s> static rtx ia64_single_set ( rtx_insn * insn ) { rtx x = PATTERN ( insn ) , ret ; if ( GET_CODE ( x ) == COND_EXEC ) x = COND_EXEC_CODE ( x ) ; if ( GET_CODE ( x ) == SET ) return x ; switch ( recog_memoized ( insn ) ) { case CODE_FOR_prologue_allocate_stack : case CODE_FOR_prologue_allocate_stack_pr : case CODE_FOR_epilogue_deallocate_stack : case CODE_FOR_epilogue_deallocate_stack_pr : ret = XVECEXP ( x , 0 , 0 ) ; break ; default : ret = single_set_2 ( insn , x ) ; break ; } return ret ; } </s>

Helper function - like single_set , but look inside COND_EXEC .


<s> static bool ia64_skip_rtx_p ( const_rtx x ) { return get_spec_unspec_code ( x ) != - 1 ; } </s>


<s> static void ia64_soft_fp_init_libfuncs ( void ) { } </s>


<s> static int ia64_speculate_insn ( rtx_insn * insn , ds_t ts , rtx * new_pat ) { int mode_no ; int res ; gcc_assert ( ! ( ts & ~ SPECULATIVE ) ) ; if ( ia64_spec_check_p ( insn ) ) return - 1 ; if ( ( ts & BE_IN_SPEC ) && ! insn_can_be_in_speculative_p ( insn , ts ) ) return - 1 ; mode_no = get_mode_no_for_insn ( insn ) ; if ( mode_no != SPEC_MODE_INVALID ) { if ( ia64_get_insn_spec_ds ( insn ) == ds_get_speculation_types ( ts ) ) res = 0 ; else { res = 1 ; * new_pat = ia64_gen_spec_load ( insn , ts , mode_no ) ; } } else res = - 1 ; return res ; } </s>

Implement targetm.sched.speculate_insn hook . Check if the INSN can be TS speculative . If 'no ' - return -1 . If 'yes ' - generate speculative pattern in the NEW_PAT and return 1 . If current pattern of the INSN already provides TS speculation , return 0 .


<s> static int ia64_spec_check_p ( rtx x ) { x = PATTERN ( x ) ; if ( GET_CODE ( x ) == COND_EXEC ) x = COND_EXEC_CODE ( x ) ; if ( GET_CODE ( x ) == SET ) return ia64_spec_check_src_p ( SET_SRC ( x ) ) ; return 0 ; } </s>

Return nonzero , if X is branchy recovery check .


<s> static int ia64_spec_check_src_p ( rtx src ) { if ( GET_CODE ( src ) == IF_THEN_ELSE ) { rtx t ; t = XEXP ( src , 0 ) ; if ( GET_CODE ( t ) == NE ) { t = XEXP ( t , 0 ) ; if ( GET_CODE ( t ) == UNSPEC ) { int code ; code = XINT ( t , 1 ) ; if ( code == UNSPEC_LDCCLR || code == UNSPEC_LDCNC || code == UNSPEC_CHKACLR || code == UNSPEC_CHKANC || code == UNSPEC_CHKS ) { gcc_assert ( code != 0 ) ; return code ; } } } } return 0 ; } </s>

Return nonzero , if SRC belongs to recovery check .


<s> void ia64_split_return_addr_rtx ( rtx dest ) { rtx src ; if ( TEST_HARD_REG_BIT ( current_frame_info . mask , BR_REG ( 0 ) ) ) { if ( current_frame_info . r [ reg_save_b0 ] != 0 ) { src = gen_rtx_REG ( DImode , current_frame_info . r [ reg_save_b0 ] ) ; reg_emitted ( reg_save_b0 ) ; } else { HOST_WIDE_INT off ; unsigned int regno ; rtx off_r ; off = ( current_frame_info . spill_cfa_off + current_frame_info . spill_size ) ; for ( regno = GR_REG ( 1 ) ; regno <= GR_REG ( 31 ) ; ++ regno ) if ( TEST_HARD_REG_BIT ( current_frame_info . mask , regno ) ) off -= 8 ; if ( frame_pointer_needed ) src = hard_frame_pointer_rtx ; else { src = stack_pointer_rtx ; off += current_frame_info . total_size ; } off_r = GEN_INT ( off ) ; if ( satisfies_constraint_I ( off_r ) ) emit_insn ( gen_adddi3 ( dest , src , off_r ) ) ; else { emit_move_insn ( dest , off_r ) ; emit_insn ( gen_adddi3 ( dest , src , dest ) ) ; } src = gen_rtx_MEM ( Pmode , dest ) ; } } else src = gen_rtx_REG ( DImode , BR_REG ( 0 ) ) ; emit_move_insn ( dest , src ) ; } </s>

Split this value after reload , now that we know where the return address is saved .


<s> void ia64_split_tmode_move ( rtx operands [ ] ) { rtx in [ 2 ] , out [ 2 ] , insn ; rtx fixup [ 2 ] ; bool dead = false ; bool reversed = false ; if ( GET_CODE ( operands [ 1 ] ) == MEM && reg_overlap_mentioned_p ( operands [ 0 ] , operands [ 1 ] ) ) { rtx base = XEXP ( operands [ 1 ] , 0 ) ; while ( GET_CODE ( base ) != REG ) base = XEXP ( base , 0 ) ; if ( REGNO ( base ) == REGNO ( operands [ 0 ] ) ) reversed = true ; if ( refers_to_regno_p ( REGNO ( operands [ 0 ] ) , REGNO ( operands [ 0 ] ) + 2 , base , 0 ) ) dead = true ; } if ( GET_CODE ( operands [ 0 ] ) == REG && GET_CODE ( operands [ 1 ] ) == REG && REGNO ( operands [ 0 ] ) == REGNO ( operands [ 1 ] ) + 1 ) reversed = true ; fixup [ 0 ] = ia64_split_tmode ( in , operands [ 1 ] , reversed , dead ) ; fixup [ 1 ] = ia64_split_tmode ( out , operands [ 0 ] , reversed , dead ) ; if ( GET_CODE ( EXP ) == MEM \ && ( GET_CODE ( XEXP ( EXP , 0 ) ) == POST_MODIFY \ || GET_CODE ( XEXP ( EXP , 0 ) ) == POST_INC \ || GET_CODE ( XEXP ( EXP , 0 ) ) == POST_DEC ) ) \ add_reg_note ( insn , REG_INC , XEXP ( XEXP ( EXP , 0 ) , 0 ) ) insn = emit_insn ( gen_rtx_SET ( out [ 0 ] , in [ 0 ] ) ) ; MAYBE_ADD_REG_INC_NOTE ( insn , in [ 0 ] ) ; MAYBE_ADD_REG_INC_NOTE ( insn , out [ 0 ] ) ; insn = emit_insn ( gen_rtx_SET ( out [ 1 ] , in [ 1 ] ) ) ; MAYBE_ADD_REG_INC_NOTE ( insn , in [ 1 ] ) ; MAYBE_ADD_REG_INC_NOTE ( insn , out [ 1 ] ) ; if ( fixup [ 0 ] ) emit_insn ( fixup [ 0 ] ) ; if ( fixup [ 1 ] ) emit_insn ( fixup [ 1 ] ) ; } </s>

Split a TImode or TFmode move instruction after reload . This is used by * movtf_internal and * movti_internal .


<s>
void
ia64_start_function
(
FILE
*
file
,
const
char
*
fnname
,
tree
decl
ATTRIBUTE_UNUSED
)
{
vms_start_function
(
fnname
)
;
fputs
(
"\t.proc "
,
file
)
;
assemble_name
(
file
,
fnname
)
;
fputc
(
'\n'
,
file
)
;
ASM_OUTPUT_LABEL
(
file
,
fnname
)
;
}
</s>

Output the textual info surrounding the prologue .


<s> static bool ia64_struct_retval_addr_is_first_parm_p ( tree fntype ) { tree ret_type = TREE_TYPE ( fntype ) ; return ( abi_version_at_least ( 2 ) && ret_type && TYPE_MODE ( ret_type ) == BLKmode && TREE_ADDRESSABLE ( ret_type ) && lang_GNU_CXX ( ) ) ; } </s>

Returns true if FNTYPE ( a FUNCTION_TYPE or a METHOD_TYPE ) returns a structure type and that the address of that type should be passed in out0 , rather than in r8 .


<s> static rtx ia64_struct_value_rtx ( tree fntype , int incoming ATTRIBUTE_UNUSED ) { if ( TARGET_ABI_OPEN_VMS || ( fntype && ia64_struct_retval_addr_is_first_parm_p ( fntype ) ) ) return NULL_RTX ; return gen_rtx_REG ( Pmode , GR_REG ( 8 ) ) ; } </s>

Worker function for TARGET_STRUCT_VALUE_RTX .


<s> int ia64_st_address_bypass_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx dest , reg , mem ; gcc_assert ( producer && consumer ) ; dest = ia64_single_set ( producer ) ; gcc_assert ( dest ) ; reg = SET_DEST ( dest ) ; gcc_assert ( reg ) ; if ( GET_CODE ( reg ) == SUBREG ) reg = SUBREG_REG ( reg ) ; gcc_assert ( GET_CODE ( reg ) == REG ) ; dest = ia64_single_set ( consumer ) ; gcc_assert ( dest ) ; mem = SET_DEST ( dest ) ; gcc_assert ( mem && GET_CODE ( mem ) == MEM ) ; return reg_mentioned_p ( reg , mem ) ; } </s>

The following function returns TRUE if PRODUCER ( of type ilog or ld ) produces address for CONSUMER ( of type st or stf ) .


<s> static void ia64_sysv4_init_libfuncs ( void ) { ia64_init_libfuncs ( ) ; set_optab_libfunc ( eq_optab , TFmode , "_U_Qfeq" ) ; set_optab_libfunc ( ne_optab , TFmode , "_U_Qfne" ) ; set_optab_libfunc ( gt_optab , TFmode , "_U_Qfgt" ) ; set_optab_libfunc ( ge_optab , TFmode , "_U_Qfge" ) ; set_optab_libfunc ( lt_optab , TFmode , "_U_Qflt" ) ; set_optab_libfunc ( le_optab , TFmode , "_U_Qfle" ) ; } </s>

Rename the TFmode libfuncs available from soft-fp in glibc using the HPUX conventions .


<s> static void ia64_trampoline_init ( rtx m_tramp , tree fndecl , rtx static_chain ) { rtx fnaddr = XEXP ( DECL_RTL ( fndecl ) , 0 ) ; rtx addr , addr_reg , tramp , eight = GEN_INT ( 8 ) ; if ( ! TARGET_GNU_AS ) { static bool declared_ia64_trampoline = false ; if ( ! declared_ia64_trampoline ) { declared_ia64_trampoline = true ; ( * targetm . asm_out . globalize_label ) ( asm_out_file , "__ia64_trampoline" ) ; } } addr = convert_memory_address ( Pmode , XEXP ( m_tramp , 0 ) ) ; fnaddr = convert_memory_address ( Pmode , fnaddr ) ; static_chain = convert_memory_address ( Pmode , static_chain ) ; addr_reg = copy_to_reg ( addr ) ; m_tramp = adjust_automodify_address ( m_tramp , Pmode , addr_reg , 0 ) ; tramp = gen_rtx_SYMBOL_REF ( Pmode , "__ia64_trampoline" ) ; if ( TARGET_ABI_OPEN_VMS ) { rtx reg = gen_reg_rtx ( Pmode ) ; SYMBOL_REF_FLAGS ( tramp ) |= SYMBOL_FLAG_FUNCTION ; emit_move_insn ( reg , tramp ) ; emit_move_insn ( reg , gen_rtx_MEM ( Pmode , reg ) ) ; tramp = reg ; } emit_move_insn ( m_tramp , tramp ) ; emit_insn ( gen_adddi3 ( addr_reg , addr_reg , eight ) ) ; m_tramp = adjust_automodify_address ( m_tramp , VOIDmode , NULL , 8 ) ; emit_move_insn ( m_tramp , force_reg ( Pmode , plus_constant ( Pmode , addr , 16 ) ) ) ; emit_insn ( gen_adddi3 ( addr_reg , addr_reg , eight ) ) ; m_tramp = adjust_automodify_address ( m_tramp , VOIDmode , NULL , 8 ) ; emit_move_insn ( m_tramp , force_reg ( Pmode , fnaddr ) ) ; emit_insn ( gen_adddi3 ( addr_reg , addr_reg , eight ) ) ; m_tramp = adjust_automodify_address ( m_tramp , VOIDmode , NULL , 8 ) ; emit_move_insn ( m_tramp , static_chain ) ; } </s>

Implement TARGET_TRAMPOLINE_INIT . The trampoline should set the static chain pointer to value placed into the trampoline and should branch to the specified routine . To make the normal indirect-subroutine calling convention work , the trampoline must look like a function descriptor ; the first word being the target address and the second being the target 's global pointer . We abuse the concept of a global pointer by arranging for it to point to the data we need to load . The complete trampoline has the following form : + -- -- -- -- -- -- -- -- -- -+ \ TRAMP : | __ia64_trampoline | | + -- -- -- -- -- -- -- -- -- -+ > fake function descriptor | TRAMP+16 | | + -- -- -- -- -- -- -- -- -- -+ / | target descriptor | + -- -- -- -- -- -- -- -- -- -+ | static link | + -- -- -- -- -- -- -- -- -- -+


<s> void ia64_unpack_assemble ( rtx out , rtx lo , rtx hi , bool highp ) { machine_mode vmode = GET_MODE ( lo ) ; unsigned int i , high , nelt = GET_MODE_NUNITS ( vmode ) ; struct expand_vec_perm_d d ; bool ok ; d . target = gen_lowpart ( vmode , out ) ; d . op0 = ( TARGET_BIG_ENDIAN ? hi : lo ) ; d . op1 = ( TARGET_BIG_ENDIAN ? lo : hi ) ; d . vmode = vmode ; d . nelt = nelt ; d . one_operand_p = false ; d . testing_p = false ; high = ( highp ? nelt / 2 : 0 ) ; for ( i = 0 ; i < nelt / 2 ; ++ i ) { d . perm [ i * 2 ] = i + high ; d . perm [ i * 2 + 1 ] = i + high + nelt ; } ok = ia64_expand_vec_perm_const_1 ( & d ) ; gcc_assert ( ok ) ; } </s>

The vectors LO and HI each contain N halves of a double-wide vector . Reassemble either the first N/2 or the second N/2 elements .


<s> static rtx ia64_unpack_sign ( rtx vec , bool unsignedp ) { machine_mode mode = GET_MODE ( vec ) ; rtx zero = CONST0_RTX ( mode ) ; if ( unsignedp ) return zero ; else { rtx sign = gen_reg_rtx ( mode ) ; bool neg ; neg = ia64_expand_vecint_compare ( LT , mode , sign , vec , zero ) ; gcc_assert ( ! neg ) ; return sign ; } } </s>

Return a vector of the sign-extension of VEC .


<s> static int ia64_unspec_may_trap_p ( const_rtx x , unsigned flags ) { switch ( XINT ( x , 1 ) ) { case UNSPEC_LDA : case UNSPEC_LDS : case UNSPEC_LDSA : case UNSPEC_LDCCLR : case UNSPEC_CHKACLR : case UNSPEC_CHKS : return may_trap_p_1 ( XVECEXP ( x , 0 , 0 ) , flags ) ; } return default_unspec_may_trap_p ( x , flags ) ; } </s>

Implement targetm.unspec_may_trap_p hook .


<s> static bool ia64_vectorize_vec_perm_const ( machine_mode vmode , rtx target , rtx op0 , rtx op1 , const vec_perm_indices & sel ) { struct expand_vec_perm_d d ; unsigned char perm [ MAX_VECT_LEN ] ; unsigned int i , nelt , which ; d . target = target ; if ( op0 ) { rtx nop0 = force_reg ( vmode , op0 ) ; if ( op0 == op1 ) op1 = nop0 ; op0 = nop0 ; } if ( op1 ) op1 = force_reg ( vmode , op1 ) ; d . op0 = op0 ; d . op1 = op1 ; d . vmode = vmode ; gcc_assert ( VECTOR_MODE_P ( d . vmode ) ) ; d . nelt = nelt = GET_MODE_NUNITS ( d . vmode ) ; d . testing_p = ! target ; gcc_assert ( sel . length ( ) == nelt ) ; gcc_checking_assert ( sizeof ( d . perm ) == sizeof ( perm ) ) ; for ( i = which = 0 ; i < nelt ; ++ i ) { unsigned int ei = sel [ i ] & ( 2 * nelt - 1 ) ; which |= ( ei < nelt ? 1 : 2 ) ; d . perm [ i ] = ei ; perm [ i ] = ei ; } switch ( which ) { default : gcc_unreachable ( ) ; case 3 : if ( d . testing_p || ! rtx_equal_p ( d . op0 , d . op1 ) ) { d . one_operand_p = false ; break ; } for ( i = 0 ; i < nelt ; ++ i ) if ( d . perm [ i ] >= nelt ) d . perm [ i ] -= nelt ; case 1 : d . op1 = d . op0 ; d . one_operand_p = true ; break ; case 2 : for ( i = 0 ; i < nelt ; ++ i ) d . perm [ i ] -= nelt ; d . op0 = d . op1 ; d . one_operand_p = true ; break ; } if ( d . testing_p ) { d . target = gen_raw_REG ( d . vmode , LAST_VIRTUAL_REGISTER + 1 ) ; d . op1 = d . op0 = gen_raw_REG ( d . vmode , LAST_VIRTUAL_REGISTER + 2 ) ; if ( ! d . one_operand_p ) d . op1 = gen_raw_REG ( d . vmode , LAST_VIRTUAL_REGISTER + 3 ) ; start_sequence ( ) ; bool ret = ia64_expand_vec_perm_const_1 ( & d ) ; end_sequence ( ) ; return ret ; } if ( ia64_expand_vec_perm_const_1 ( & d ) ) return true ; if ( which == 3 && d . one_operand_p ) { memcpy ( d . perm , perm , sizeof ( perm ) ) ; d . one_operand_p = false ; return ia64_expand_vec_perm_const_1 ( & d ) ; } return false ; } </s>


"%qE attribute requires a string constant argument"

Part of the low level implementation of DEC Ada pragma Common_Object which enables the shared use of variables stored in overlaid linker areas corresponding to the use of Fortran COMMON .


<s> static void ia64_vms_init_libfuncs ( void ) { set_optab_libfunc ( sdiv_optab , SImode , "OTS$DIV_I" ) ; set_optab_libfunc ( sdiv_optab , DImode , "OTS$DIV_L" ) ; set_optab_libfunc ( udiv_optab , SImode , "OTS$DIV_UI" ) ; set_optab_libfunc ( udiv_optab , DImode , "OTS$DIV_UL" ) ; set_optab_libfunc ( smod_optab , SImode , "OTS$REM_I" ) ; set_optab_libfunc ( smod_optab , DImode , "OTS$REM_L" ) ; set_optab_libfunc ( umod_optab , SImode , "OTS$REM_UI" ) ; set_optab_libfunc ( umod_optab , DImode , "OTS$REM_UL" ) ; MEM_LIBFUNCS_INIT ; } </s>

Rename the division and modulus functions in VMS .


<s> void ia64_vms_output_aligned_decl_common ( FILE * file , tree decl , const char * name , unsigned HOST_WIDE_INT size , unsigned int align ) { tree attr = DECL_ATTRIBUTES ( decl ) ; if ( attr ) attr = lookup_attribute ( "common_object" , attr ) ; if ( attr ) { tree id = TREE_VALUE ( TREE_VALUE ( attr ) ) ; const char * name ; if ( TREE_CODE ( id ) == IDENTIFIER_NODE ) name = IDENTIFIER_POINTER ( id ) ; else if ( TREE_CODE ( id ) == STRING_CST ) name = TREE_STRING_POINTER ( id ) ; else abort ( ) ; fprintf ( file , "\t.vms_common\t\"%s\"," , name ) ; } else fprintf ( file , "%s" , COMMON_ASM_OP ) ; assemble_name ( file , name ) ; fprintf ( file , "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u" , size , align / BITS_PER_UNIT ) ; fputc ( '\n' , file ) ; } </s>

Part of the low level implementation of DEC Ada pragma Common_Object .


<s> static bool important_for_bundling_p ( rtx_insn * insn ) { return ( INSN_P ( insn ) && ia64_safe_itanium_class ( insn ) != ITANIUM_CLASS_IGNORE && GET_CODE ( PATTERN ( insn ) ) != USE && GET_CODE ( PATTERN ( insn ) ) != CLOBBER ) ; } </s>

True when INSN is important for bundling .


<s> static void initiate_bundle_states ( void ) { bundle_states_num = 0 ; free_bundle_state_chain = NULL ; allocated_bundle_states_chain = NULL ; } </s>

Start work with abstract data ` bundle states ' .


<s> static void initiate_bundle_state_table ( void ) { bundle_state_table = new hash_table < bundle_state_hasher > ( 50 ) ; } </s>


<s> static void init_insn_group_barriers ( void ) { memset ( rws_sum , 0 , sizeof ( rws_sum ) ) ; first_instruction = 1 ; } </s>

Clear out the state for group_barrier_needed_p at the start of a sequence of insns .


<s> static int insert_bundle_state ( struct bundle_state * bundle_state ) { struct bundle_state * * entry_ptr ; entry_ptr = bundle_state_table -> find_slot ( bundle_state , INSERT ) ; if ( * entry_ptr == NULL ) { bundle_state -> next = index_to_bundle_states [ bundle_state -> insn_num ] ; index_to_bundle_states [ bundle_state -> insn_num ] = bundle_state ; * entry_ptr = bundle_state ; return TRUE ; } else if ( bundle_state -> cost < ( * entry_ptr ) -> cost || ( bundle_state -> cost == ( * entry_ptr ) -> cost && ( ( * entry_ptr ) -> accumulated_insns_num > bundle_state -> accumulated_insns_num || ( ( * entry_ptr ) -> accumulated_insns_num == bundle_state -> accumulated_insns_num && ( ( * entry_ptr ) -> branch_deviation > bundle_state -> branch_deviation || ( ( * entry_ptr ) -> branch_deviation == bundle_state -> branch_deviation && ( * entry_ptr ) -> middle_bundle_stops > bundle_state -> middle_bundle_stops ) ) ) ) ) ) { struct bundle_state temp ; temp = * * entry_ptr ; * * entry_ptr = * bundle_state ; ( * entry_ptr ) -> next = temp . next ; * bundle_state = temp ; } return FALSE ; } </s>

The function inserts the BUNDLE_STATE into the hash table . The function returns nonzero if the bundle has been inserted into the table . The table contains the best bundle state with given key .


<s> static bool is_load_p ( rtx_insn * insn ) { enum attr_itanium_class insn_class = ia64_safe_itanium_class ( insn ) ; return ( ( insn_class == ITANIUM_CLASS_LD || insn_class == ITANIUM_CLASS_FLD ) && get_attr_check_load ( insn ) == CHECK_LOAD_NO ) ; } </s>

Return TRUE if INSN is a load ( either normal or speculative , but not a speculation check ) , FALSE otherwise .


<s> static void mark_reg_gr_used_mask ( rtx reg , void * data ATTRIBUTE_UNUSED ) { unsigned int regno = REGNO ( reg ) ; if ( regno < 32 ) { unsigned int i , n = REG_NREGS ( reg ) ; for ( i = 0 ; i < n ; ++ i ) current_frame_info . gr_used_mask |= 1 << ( regno + i ) ; } } </s>

Helper function for ia64_compute_frame_size , called through diddle_return_value . Mark REG in current_frame_info.gr_used_mask .


<s>
const
char
*
output_probe_stack_range
(
rtx
reg1
,
rtx
reg2
)
{
static
int
labelno
=
0
;
char
loop_lab
[
32
]
;
rtx
xops
[
3
]
;
ASM_GENERATE_INTERNAL_LABEL
(
loop_lab
,
"LPSRL"
,
labelno
++
)
;
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
loop_lab
)
;
xops
[
0
]
=
reg1
;
xops
[
1
]
=
GEN_INT
(
PROBE_INTERVAL
)
;
output_asm_insn
(
"addl %0 = %1, %0"
,
xops
)
;
fputs
(
"\t;;\n"
,
asm_out_file
)
;
output_asm_insn
(
"probe.w.fault %0, 0"
,
xops
)
;
xops
[
1
]
=
reg2
;
xops
[
2
]
=
gen_rtx_REG
(
BImode
,
PR_REG
(
6
)
)
;
output_asm_insn
(
"cmp.eq %2, %I2 = %0, %1"
,
xops
)
;
fprintf
(
asm_out_file
,
"\t(%s) br.cond.dpnt "
,
reg_names
[
PR_REG
(
7
)
]
)
;
assemble_name_raw
(
asm_out_file
,
loop_lab
)
;
fputc
(
'\n'
,
asm_out_file
)
;
return
""
;
}
</s>

Wrapper around the output_probe_stack_range routines .


<s>
static
void
process_cfa_adjust_cfa
(
FILE
*
out_file
,
rtx
pat
,
rtx
insn
,
bool
unwind
,
bool
frame
)
{
rtx
dest
=
SET_DEST
(
pat
)
;
rtx
src
=
SET_SRC
(
pat
)
;
if
(
dest
==
stack_pointer_rtx
)
{
if
(
GET_CODE
(
src
)
==
PLUS
)
{
rtx
op0
=
XEXP
(
src
,
0
)
;
rtx
op1
=
XEXP
(
src
,
1
)
;
gcc_assert
(
op0
==
dest
&&
GET_CODE
(
op1
)
==
CONST_INT
)
;
if
(
INTVAL
(
op1
)
<
0
)
{
gcc_assert
(
!
frame_pointer_needed
)
;
if
(
unwind
)
fprintf
(
out_file
,
"\t.fframe "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
INTVAL
(
op1
)
)
;
}
else
process_epilogue
(
out_file
,
insn
,
unwind
,
frame
)
;
}
else
{
gcc_assert
(
src
==
hard_frame_pointer_rtx
)
;
process_epilogue
(
out_file
,
insn
,
unwind
,
frame
)
;
}
}
else
if
(
dest
==
hard_frame_pointer_rtx
)
{
gcc_assert
(
src
==
stack_pointer_rtx
)
;
gcc_assert
(
frame_pointer_needed
)
;
if
(
unwind
)
fprintf
(
out_file
,
"\t.vframe r%d\n"
,
ia64_dbx_register_number
(
REGNO
(
dest
)
)
)
;
}
else
gcc_unreachable
(
)
;
}
</s>

This function processes a SET pattern for REG_CFA_ADJUST_CFA .


<s>
static
void
process_cfa_register
(
FILE
*
out_file
,
rtx
pat
,
bool
unwind
)
{
rtx
dest
=
SET_DEST
(
pat
)
;
rtx
src
=
SET_SRC
(
pat
)
;
int
dest_regno
=
REGNO
(
dest
)
;
int
src_regno
;
if
(
src
==
pc_rtx
)
{
if
(
unwind
)
fprintf
(
out_file
,
"\t.save rp, r%d\n"
,
ia64_dbx_register_number
(
dest_regno
)
)
;
return
;
}
src_regno
=
REGNO
(
src
)
;
switch
(
src_regno
)
{
case
PR_REG
(
0
)
:
gcc_assert
(
dest_regno
==
current_frame_info
.
r
[
reg_save_pr
]
)
;
if
(
unwind
)
fprintf
(
out_file
,
"\t.save pr, r%d\n"
,
ia64_dbx_register_number
(
dest_regno
)
)
;
break
;
case
AR_UNAT_REGNUM
:
gcc_assert
(
dest_regno
==
current_frame_info
.
r
[
reg_save_ar_unat
]
)
;
if
(
unwind
)
fprintf
(
out_file
,
"\t.save ar.unat, r%d\n"
,
ia64_dbx_register_number
(
dest_regno
)
)
;
break
;
case
AR_LC_REGNUM
:
gcc_assert
(
dest_regno
==
current_frame_info
.
r
[
reg_save_ar_lc
]
)
;
if
(
unwind
)
fprintf
(
out_file
,
"\t.save ar.lc, r%d\n"
,
ia64_dbx_register_number
(
dest_regno
)
)
;
break
;
default
:
gcc_unreachable
(
)
;
}
}
</s>

This function processes a SET pattern for REG_CFA_REGISTER .

ia64
"\t.save rp, r%d\n"
0
"\t.save pr, r%d\n"
"\t.save ar.unat, r%d\n"
"\t.save ar.lc, r%d\n"


<s>
static
void
process_epilogue
(
FILE
*
out_file
,
rtx
insn
ATTRIBUTE_UNUSED
,
bool
unwind
,
bool
frame
ATTRIBUTE_UNUSED
)
{
if
(
!
last_block
)
{
if
(
unwind
)
fprintf
(
out_file
,
"\t.label_state %d\n"
,
++
cfun
->
machine
->
state_num
)
;
need_copy_state
=
true
;
}
if
(
unwind
)
fprintf
(
out_file
,
"\t.restore sp\n"
)
;
}
</s>

The function emits unwind directives for the start of an epilogue .

ia64
"\t.label_state %d\n"
"\t.restore sp\n"


<s> static void record_memory_reference ( rtx_insn * insn ) { enum attr_itanium_class insn_class = ia64_safe_itanium_class ( insn ) ; switch ( insn_class ) { case ITANIUM_CLASS_FLD : case ITANIUM_CLASS_LD : mem_ops_in_group [ current_cycle % 4 ] ++ ; break ; case ITANIUM_CLASS_STF : case ITANIUM_CLASS_ST : mem_ops_in_group [ ( current_cycle + 3 ) % 4 ] ++ ; break ; default : ; } } </s>

If INSN is a memory reference , memoize it in MEM_OPS_IN_GROUP global array ( taking account for 3-cycle cache reference postponing for stores : Intel Itanium 2 Reference Manual for Software Development and Optimization , 6.7.3.1 ) .


<s> static int rws_access_regno ( int regno , struct reg_flags flags , int pred ) { int need_barrier = 0 ; gcc_assert ( regno < NUM_REGS ) ; if ( ! PR_REGNO_P ( regno ) ) flags . is_and = flags . is_or = 0 ; if ( flags . is_write ) { int write_count ; rws_insn_set ( regno ) ; write_count = rws_sum [ regno ] . write_count ; switch ( write_count ) { case 0 : if ( ! in_safe_group_barrier ) rws_update ( regno , flags , pred ) ; break ; case 1 : if ( flags . is_and && rws_sum [ regno ] . written_by_and ) ; else if ( flags . is_or && rws_sum [ regno ] . written_by_or ) ; else need_barrier = 1 ; if ( ! in_safe_group_barrier ) rws_update ( regno , flags , pred ) ; break ; case 2 : if ( flags . is_and && rws_sum [ regno ] . written_by_and ) ; else if ( flags . is_or && rws_sum [ regno ] . written_by_or ) ; else need_barrier = 1 ; if ( ! in_safe_group_barrier ) { rws_sum [ regno ] . written_by_and = flags . is_and ; rws_sum [ regno ] . written_by_or = flags . is_or ; } break ; default : gcc_unreachable ( ) ; } } else { if ( flags . is_branch ) { if ( REGNO_REG_CLASS ( regno ) == BR_REGS || regno == AR_PFS_REGNUM ) return 0 ; if ( REGNO_REG_CLASS ( regno ) == PR_REGS && ! rws_sum [ regno ] . written_by_fp ) return 0 ; } if ( flags . is_and && rws_sum [ regno ] . written_by_and ) return 0 ; if ( flags . is_or && rws_sum [ regno ] . written_by_or ) return 0 ; switch ( rws_sum [ regno ] . write_count ) { case 0 : break ; case 1 : need_barrier = 1 ; break ; case 2 : need_barrier = 1 ; break ; default : gcc_unreachable ( ) ; } } return need_barrier ; } </s>

Handle an access to register REGNO of type FLAGS using predicate register PRED . Update rws_insn and rws_sum arrays . Return 1 if this access creates a dependency with an earlier instruction in the same group .


<s> static void rws_update ( int regno , struct reg_flags flags , int pred ) { if ( pred ) rws_sum [ regno ] . write_count ++ ; else rws_sum [ regno ] . write_count = 2 ; rws_sum [ regno ] . written_by_fp |= flags . is_fp ; rws_sum [ regno ] . written_by_and = flags . is_and ; rws_sum [ regno ] . written_by_or = flags . is_or ; rws_sum [ regno ] . first_pred = pred ; } </s>

Update * RWS for REGNO , which is being written by the current instruction , with predicate PRED , and associated register flags in FLAGS .


<s> static int safe_group_barrier_needed ( rtx_insn * insn ) { int saved_first_instruction ; int t ; saved_first_instruction = first_instruction ; in_safe_group_barrier = 1 ; t = group_barrier_needed ( insn ) ; first_instruction = saved_first_instruction ; in_safe_group_barrier = 0 ; return t ; } </s>

Like group_barrier_needed , but do not clobber the current state .


<s> static int scheduled_good_insn ( rtx_insn * last ) { if ( last && recog_memoized ( last ) >= 0 ) return 1 ; for ( ; last != NULL && ! NOTE_INSN_BASIC_BLOCK_P ( last ) && ! stops_p [ INSN_UID ( last ) ] ; last = PREV_INSN ( last ) ) if ( INSN_P ( last ) && recog_memoized ( last ) >= 0 ) return 1 ; return 0 ; } </s>

Returns 1 when a meaningful insn was scheduled between the last group barrier and LAST .


<s> static int set_src_needs_barrier ( rtx x , struct reg_flags flags , int pred ) { int need_barrier = 0 ; rtx dst ; rtx src = SET_SRC ( x ) ; if ( GET_CODE ( src ) == CALL ) return rtx_needs_barrier ( src , flags , pred ) ; else if ( SET_DEST ( x ) == pc_rtx ) { if ( ! ia64_spec_check_src_p ( src ) ) flags . is_branch = 1 ; return rtx_needs_barrier ( src , flags , pred ) ; } if ( ia64_spec_check_src_p ( src ) ) { gcc_assert ( REG_P ( XEXP ( src , 2 ) ) ) ; need_barrier = rtx_needs_barrier ( XEXP ( src , 2 ) , flags , pred ) ; src = XEXP ( src , 1 ) ; } need_barrier |= rtx_needs_barrier ( src , flags , pred ) ; dst = SET_DEST ( x ) ; if ( GET_CODE ( dst ) == ZERO_EXTRACT ) { need_barrier |= rtx_needs_barrier ( XEXP ( dst , 1 ) , flags , pred ) ; need_barrier |= rtx_needs_barrier ( XEXP ( dst , 2 ) , flags , pred ) ; } return need_barrier ; } </s>

Subroutine of rtx_needs_barrier ; this function determines whether the source of a given SET rtx found in X needs a barrier . FLAGS and PRED are as in rtx_needs_barrier . COND is an rtx that holds the condition for this insn .


<s> static enum tls_model tls_symbolic_operand_type ( rtx addr ) { enum tls_model tls_kind = TLS_MODEL_NONE ; if ( GET_CODE ( addr ) == CONST ) { if ( GET_CODE ( XEXP ( addr , 0 ) ) == PLUS && GET_CODE ( XEXP ( XEXP ( addr , 0 ) , 0 ) ) == SYMBOL_REF ) tls_kind = SYMBOL_REF_TLS_MODEL ( XEXP ( XEXP ( addr , 0 ) , 0 ) ) ; } else if ( GET_CODE ( addr ) == SYMBOL_REF ) tls_kind = SYMBOL_REF_TLS_MODEL ( addr ) ; return tls_kind ; } </s>

Return the TLS model to use for SYMBOL .


<s> static int try_issue_insn ( struct bundle_state * curr_state , rtx insn ) { if ( insn && state_transition ( curr_state -> dfa_state , insn ) >= 0 ) { free_bundle_state ( curr_state ) ; return FALSE ; } return TRUE ; } </s>

The following function tries to issue INSN for the current state without advancing processor cycle . If it failed , the function returns FALSE and frees the current state .


<s> static int try_issue_nops ( struct bundle_state * curr_state , int nops_num ) { int i ; for ( i = 0 ; i < nops_num ; i ++ ) if ( state_transition ( curr_state -> dfa_state , ia64_nop ) >= 0 ) { free_bundle_state ( curr_state ) ; return FALSE ; } return TRUE ; } </s>

The following function tries to issue NOPS_NUM nops for the current state without advancing processor cycle . If it failed , the function returns FALSE and frees the current state .


<s> static bool unknown_for_bundling_p ( rtx_insn * insn ) { return ( INSN_P ( insn ) && ia64_safe_itanium_class ( insn ) == ITANIUM_CLASS_UNKNOWN && GET_CODE ( PATTERN ( insn ) ) != USE && GET_CODE ( PATTERN ( insn ) ) != CLOBBER ) ; } </s>

True when INSN is unknown , but important , for bundling .


<s> static void update_set_flags ( rtx x , struct reg_flags * pflags ) { rtx src = SET_SRC ( x ) ; switch ( GET_CODE ( src ) ) { case CALL : return ; case IF_THEN_ELSE : return ; default : if ( COMPARISON_P ( src ) && SCALAR_FLOAT_MODE_P ( GET_MODE ( XEXP ( src , 0 ) ) ) ) pflags -> is_fp = 1 ; else if ( GET_CODE ( src ) == AND ) pflags -> is_and = 1 ; else if ( GET_CODE ( src ) == IOR ) pflags -> is_or = 1 ; break ; } } </s>

Examine X , which is a SET rtx , and update the flags , the predicate , and the condition , stored in * PFLAGS , * PPRED and * PCOND .


<s> static inline void desc_abi ( unsigned char abi , unsigned char context , struct unw_state_record * sr ) { sr -> unwabi = ( abi << 8 ) | context ; } </s>