<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_debugger_regno
(
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 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 ( type == float128_type_node || type == float64x_type_node ) 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
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_debugger_regno
(
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_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 ) ; if ( ! TYPE_NO_NAMED_ARGS_STDARG_P ( TREE_TYPE ( current_function_decl ) ) ) 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
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_debugger_regno
(
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_debugger_regno
(
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_debugger_regno
(
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_debugger_regno
(
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_debugger_regno
(
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 emit_predicate_relation_info ( ) { int i ; for ( i = n_basic_blocks - 1 ; i >= 0 ; -- i ) { basic_block bb = BASIC_BLOCK ( i ) ; int r ; rtx head = bb -> head ; if ( GET_CODE ( head ) != CODE_LABEL ) continue ; if ( GET_CODE ( NEXT_INSN ( head ) ) == NOTE && NOTE_LINE_NUMBER ( NEXT_INSN ( head ) ) == NOTE_INSN_BASIC_BLOCK ) head = NEXT_INSN ( head ) ; for ( r = PR_REG ( 0 ) ; r < PR_REG ( 64 ) ; r += 2 ) if ( REGNO_REG_SET_P ( bb -> global_live_at_start , r ) ) { rtx p = gen_rtx_REG ( BImode , r ) ; rtx n = emit_insn_after ( gen_pred_rel_mutex ( p ) , head ) ; if ( head == bb -> end ) bb -> end = n ; head = n ; } } for ( i = n_basic_blocks - 1 ; i >= 0 ; -- i ) { basic_block bb = BASIC_BLOCK ( i ) ; rtx insn = bb -> head ; while ( 1 ) { if ( GET_CODE ( insn ) == CALL_INSN && GET_CODE ( PATTERN ( insn ) ) == COND_EXEC && find_reg_note ( insn , REG_NORETURN , NULL_RTX ) ) { rtx b = emit_insn_before ( gen_safe_across_calls_all ( ) , insn ) ; rtx a = emit_insn_after ( gen_safe_across_calls_normal ( ) , insn ) ; if ( bb -> head == insn ) bb -> head = b ; if ( bb -> end == insn ) bb -> end = a ; } if ( insn == bb -> end ) break ; insn = NEXT_INSN ( insn ) ; } } } </s>

Emit pseudo-ops for the assembler to describe predicate relations . At present this assumes that we only consider predicate pairs to be mutex , and that the assembler can deduce proper values from straight-line code .


<s> static void fixup_errata ( ) { rtx insn ; if ( ! TARGET_B_STEP ) return ; group_idx = 0 ; memset ( last_group , 0 , sizeof last_group ) ; for ( insn = get_insns ( ) ; insn ; insn = NEXT_INSN ( insn ) ) { if ( ! INSN_P ( insn ) ) continue ; if ( ia64_safe_type ( insn ) == TYPE_S ) { group_idx ^= 1 ; memset ( last_group + group_idx , 0 , sizeof last_group [ group_idx ] ) ; } else errata_emit_nops ( insn ) ; } } </s>

Emit extra nops if they are required to work around hardware errata .


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


<s> static void ia64_emit_nops ( ) { rtx insn ; const struct bundle * b = 0 ; int bundle_pos = 0 ; for ( insn = get_insns ( ) ; insn ; insn = NEXT_INSN ( insn ) ) { rtx pat ; enum attr_type t ; pat = INSN_P ( insn ) ? PATTERN ( insn ) : const0_rtx ; if ( GET_CODE ( pat ) == USE || GET_CODE ( pat ) == CLOBBER ) continue ; if ( ( GET_CODE ( pat ) == UNSPEC && XINT ( pat , 1 ) == 22 ) || GET_CODE ( insn ) == CODE_LABEL ) { if ( b ) while ( bundle_pos < 3 ) { emit_insn_before ( gen_nop_type ( b -> t [ bundle_pos ] ) , insn ) ; bundle_pos ++ ; } if ( GET_CODE ( insn ) != CODE_LABEL ) b = bundle + INTVAL ( XVECEXP ( pat , 0 , 0 ) ) ; else b = 0 ; bundle_pos = 0 ; continue ; } else if ( GET_CODE ( pat ) == UNSPEC_VOLATILE && XINT ( pat , 1 ) == 2 ) { int t = INTVAL ( XVECEXP ( pat , 0 , 0 ) ) ; if ( b ) while ( bundle_pos < t ) { emit_insn_before ( gen_nop_type ( b -> t [ bundle_pos ] ) , insn ) ; bundle_pos ++ ; } continue ; } if ( bundle_pos == 3 ) b = 0 ; if ( b && INSN_P ( insn ) ) { t = ia64_safe_type ( insn ) ; if ( asm_noperands ( PATTERN ( insn ) ) >= 0 || GET_CODE ( PATTERN ( insn ) ) == ASM_INPUT ) { while ( bundle_pos < 3 ) { emit_insn_before ( gen_nop_type ( b -> t [ bundle_pos ] ) , insn ) ; bundle_pos ++ ; } continue ; } if ( t == TYPE_UNKNOWN ) continue ; while ( bundle_pos < 3 ) { if ( t == b -> t [ bundle_pos ] || ( t == TYPE_A && ( b -> t [ bundle_pos ] == TYPE_M || b -> t [ bundle_pos ] == TYPE_I ) ) ) break ; emit_insn_before ( gen_nop_type ( b -> t [ bundle_pos ] ) , insn ) ; bundle_pos ++ ; } if ( bundle_pos < 3 ) bundle_pos ++ ; } } } </s>

After the last scheduling pass , fill in NOPs . It 's easier to do this here than while scheduling .


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

Return the maximum number of instructions a cpu can issue .


"cannot optimize division for both latency and throughput"


<s> static void init_insn_group_barriers ( ) { 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
void
process_epilogue
(
)
{
if
(
block_num
!=
n_basic_blocks
1
)
{
fprintf
(
asm_out_file
,
"\t.label_state 1\n"
)
;
need_copy_state
=
1
;
}
fprintf
(
asm_out_file
,
"\t.restore sp\n"
)
;
}
</s>

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


<s>
void
emit_safe_across_calls
(
void
)
{
unsigned
int
rs
,
re
;
int
out_state
;
rs
=
1
;
out_state
=
0
;
while
(
1
)
{
while
(
rs
<
64
&&
call_used_regs
[
PR_REG
(
rs
)
]
)
rs
++
;
if
(
rs
>=
64
)
break
;
for
(
re
=
rs
+
1
;
re
<
64
&&
!
call_used_regs
[
PR_REG
(
re
)
]
;
re
++
)
continue
;
if
(
out_state
==
0
)
{
fputs
(
"\t.pred.safe_across_calls "
,
asm_out_file
)
;
out_state
=
1
;
}
else
fputc
(
','
,
asm_out_file
)
;
if
(
re
==
rs
+
1
)
fprintf
(
asm_out_file
,
"p%u"
,
rs
)
;
else
fprintf
(
asm_out_file
,
"p%u-p%u"
,
rs
,
re
1
)
;
rs
=
re
+
1
;
}
if
(
out_state
)
fputc
(
'\n'
,
asm_out_file
)
;
}
</s>


<s> static int find_gr_spill ( int try_locals ) { int regno ; if ( current_function_is_leaf ) { for ( regno = GR_REG ( 1 ) ; regno <= GR_REG ( 31 ) ; regno ++ ) if ( ! regs_ever_live [ regno ] && call_used_regs [ regno ] && ! fixed_regs [ regno ] && ! global_regs [ regno ] && ( ( current_frame_info . gr_used_mask >> regno ) & 1 ) == 0 ) { current_frame_info . gr_used_mask |= 1 << regno ; return regno ; } } if ( try_locals ) { regno = current_frame_info . n_local_regs ; if ( regno < ( 80 - frame_pointer_needed ) ) { current_frame_info . n_local_regs = regno + 1 ; return LOC_REG ( 0 ) + regno ; } } return 0 ; } </s>

Helper function for ia64_compute_frame_size : find an appropriate general register to spill some special register to . SPECIAL_SPILL_MASK contains bits in GR0 to GR31 that have already been allocated by this routine . TRY_LOCALS is true if we should attempt to locate a local regnum .


<s> static enum machine_mode hfa_element_mode ( tree type , bool nested ) { enum machine_mode element_mode = VOIDmode ; enum 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 CHAR_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 = TREE_CHAIN ( t ) ) { if ( TREE_CODE ( t ) != FIELD_DECL ) 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 int ia64_arg_partial_bytes ( CUMULATIVE_ARGS * cum , enum machine_mode mode , tree type , bool named ATTRIBUTE_UNUSED ) { int words = ia64_function_arg_words ( type , mode ) ; int offset = ia64_function_arg_offset ( cum , 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 bool ia64_cannot_force_const_mem ( rtx x ) { return tls_symbolic_operand_type ( x ) != 0 ; } </s>

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


<s> bool ia64_const_double_ok_for_letter_p ( rtx value , char c ) { switch ( c ) { case 'G' : return CONST_DOUBLE_OK_FOR_G ( value ) ; default : return false ; } } </s>


<s> bool ia64_const_ok_for_letter_p ( HOST_WIDE_INT value , char c ) { switch ( c ) { case 'I' : return CONST_OK_FOR_I ( value ) ; case 'J' : return CONST_OK_FOR_J ( value ) ; case 'K' : return CONST_OK_FOR_K ( value ) ; case 'L' : return CONST_OK_FOR_L ( value ) ; case 'M' : return CONST_OK_FOR_M ( value ) ; case 'N' : return CONST_OK_FOR_N ( value ) ; case 'O' : return CONST_OK_FOR_O ( value ) ; case 'P' : return CONST_OK_FOR_P ( value ) ; default : return false ; } } </s>


<s> void ia64_emit_cond_move ( rtx op0 , rtx op1 , rtx cond ) { rtx 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> void ia64_expand_atomic_op ( enum rtx_code code , rtx mem , rtx val , rtx old_dst , rtx new_dst ) { enum machine_mode mode = GET_MODE ( mem ) ; rtx old_reg , new_reg , cmp_reg , ar_ccv , label ; enum insn_code icode ; if ( ( mode == SImode || mode == DImode ) && ( code == PLUS || code == MINUS ) && fetchadd_operand ( val , mode ) ) { if ( code == MINUS ) val = GEN_INT ( - INTVAL ( val ) ) ; if ( ! old_dst ) old_dst = gen_reg_rtx ( mode ) ; emit_insn ( gen_memory_barrier ( ) ) ; if ( mode == SImode ) icode = CODE_FOR_fetchadd_acq_si ; else icode = CODE_FOR_fetchadd_acq_di ; emit_insn ( GEN_FCN ( icode ) ( old_dst , mem , val ) ) ; if ( new_dst ) { new_reg = expand_simple_binop ( mode , PLUS , old_dst , val , new_dst , true , OPTAB_WIDEN ) ; if ( new_reg != new_dst ) emit_move_insn ( new_dst , new_reg ) ; } return ; } gcc_assert ( MEM_VOLATILE_P ( mem ) ) ; old_reg = gen_reg_rtx ( DImode ) ; cmp_reg = gen_reg_rtx ( DImode ) ; label = gen_label_rtx ( ) ; if ( mode != DImode ) { val = simplify_gen_subreg ( DImode , val , mode , 0 ) ; emit_insn ( gen_extend_insn ( cmp_reg , mem , DImode , mode , 1 ) ) ; } else emit_move_insn ( cmp_reg , mem ) ; emit_label ( label ) ; ar_ccv = gen_rtx_REG ( DImode , AR_CCV_REGNUM ) ; emit_move_insn ( old_reg , cmp_reg ) ; emit_move_insn ( ar_ccv , cmp_reg ) ; if ( old_dst ) emit_move_insn ( old_dst , gen_lowpart ( mode , cmp_reg ) ) ; new_reg = cmp_reg ; if ( code == NOT ) { new_reg = expand_simple_unop ( DImode , NOT , new_reg , NULL_RTX , true ) ; code = AND ; } new_reg = expand_simple_binop ( DImode , code , new_reg , val , NULL_RTX , true , OPTAB_DIRECT ) ; if ( mode != DImode ) new_reg = gen_lowpart ( mode , new_reg ) ; if ( new_dst ) emit_move_insn ( new_dst , new_reg ) ; switch ( mode ) { case QImode : icode = CODE_FOR_cmpxchg_rel_qi ; break ; case HImode : icode = CODE_FOR_cmpxchg_rel_hi ; break ; case SImode : icode = CODE_FOR_cmpxchg_rel_si ; break ; case DImode : icode = CODE_FOR_cmpxchg_rel_di ; break ; default : gcc_unreachable ( ) ; } emit_insn ( GEN_FCN ( icode ) ( cmp_reg , mem , ar_ccv , new_reg ) ) ; emit_cmp_and_jump_insns ( cmp_reg , old_reg , NE , NULL , DImode , true , label ) ; } </s>

Expand an atomic operation . We want to perform MEM < CODE > = VAL atomically . This differs from the generic code in that we know about the zero-extending properties of cmpxchg , and the zero-extending requirements of ar.ccv . We also know that ld.acq+cmpxchg.rel equals a full barrier . The loop we want to generate looks like cmp_reg = mem ; label : old_reg = cmp_reg ; new_reg = cmp_reg op val ; cmp_reg = compare-and-swap ( mem , old_reg , new_reg ) if ( cmp_reg ! = old_reg ) goto label ; Note that we only do the plain load from memory once . Subsequent iterations use the value loaded by the compare-and-swap pattern .


<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 ) ; } </s>

Emit the appropriate sequence for a call .


<s> rtx ia64_expand_compare ( enum rtx_code code , enum machine_mode mode ) { rtx op0 = ia64_compare_op0 , op1 = ia64_compare_op1 ; rtx cmp ; if ( GET_MODE ( op0 ) == BImode ) { gcc_assert ( ( code == NE || code == EQ ) && op1 == const0_rtx ) ; cmp = op0 ; } else if ( GET_MODE ( op0 ) == TFmode ) { enum qfcmp_magic { QCMP_INV = 1 , QCMP_UNORD = 2 , QCMP_EQ = 4 , QCMP_LT = 8 , QCMP_GT = 16 } magic ; enum rtx_code ncode ; rtx ret , insns ; 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 ; default : gcc_unreachable ( ) ; } start_sequence ( ) ; ret = emit_library_call_value ( cmptf_libfunc , 0 , LCT_CONST , DImode , 3 , op0 , TFmode , op1 , TFmode , GEN_INT ( magic ) , DImode ) ; cmp = gen_reg_rtx ( BImode ) ; emit_insn ( gen_rtx_SET ( VOIDmode , cmp , gen_rtx_fmt_ee ( ncode , BImode , ret , const0_rtx ) ) ) ; 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 ( VOIDmode , cmp , gen_rtx_fmt_ee ( code , BImode , op0 , op1 ) ) ) ; code = NE ; } return gen_rtx_fmt_ee ( code , mode , cmp , const0_rtx ) ; } </s>

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


Emit a signed or unsigned V8QI dot product operation .


<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 ) , 0 ) ; 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 { 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 ( 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 ( VOIDmode , dest , tmp ) ) ; tmp = gen_rtx_LO_SUM ( Pmode , dest , src ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , tmp ) ) ; if ( addend ) { tmp = gen_rtx_PLUS ( Pmode , dest , GEN_INT ( addend ) ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , tmp ) ) ; } } return true ; } </s>


<s> void ia64_expand_vecint_cmov ( rtx operands [ ] ) { enum 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 ( VOIDmode , operands [ 0 ] , x ) ) ; } else if ( of == CONST0_RTX ( mode ) ) { x = gen_rtx_AND ( mode , cmp , ot ) ; emit_insn ( gen_rtx_SET ( VOIDmode , 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 ( VOIDmode , 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 ( VOIDmode , f , x ) ) ; x = gen_rtx_IOR ( mode , t , f ) ; emit_insn ( gen_rtx_SET ( VOIDmode , operands [ 0 ] , x ) ) ; } } </s>

Emit an integral vector conditional move .


<s> static bool ia64_expand_vecint_compare ( enum rtx_code code , enum 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 V2SImode : { rtx t1 , t2 , mask ; t1 = gen_reg_rtx ( V2SImode ) ; emit_insn ( gen_subv2si3 ( t1 , op0 , op1 ) ) ; mask = GEN_INT ( - 0x80000000 ) ; mask = gen_rtx_CONST_VECTOR ( V2SImode , gen_rtvec ( 2 , mask , mask ) ) ; mask = force_reg ( V2SImode , mask ) ; t2 = gen_reg_rtx ( V2SImode ) ; emit_insn ( gen_andv2si3 ( t2 , op0 , mask ) ) ; x = gen_reg_rtx ( V2SImode ) ; emit_insn ( gen_xorv2si3 ( x , t1 , t2 ) ) ; code = GT ; op0 = x ; op1 = CONST0_RTX ( mode ) ; } break ; case V8QImode : case V4HImode : x = gen_reg_rtx ( mode ) ; emit_insn ( gen_rtx_SET ( VOIDmode , 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 ( VOIDmode , 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 , enum 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 ( VOIDmode , 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> void ia64_expand_widen_sum ( rtx operands [ 3 ] , bool unsignedp ) { rtx l , h , x , s ; enum machine_mode wmode , mode ; rtx ( * unpack_l ) ( rtx , rtx , rtx ) ; rtx ( * unpack_h ) ( rtx , rtx , rtx ) ; rtx ( * plus ) ( rtx , rtx , rtx ) ; wmode = GET_MODE ( operands [ 0 ] ) ; mode = GET_MODE ( operands [ 1 ] ) ; switch ( mode ) { case V8QImode : unpack_l = gen_unpack1_l ; unpack_h = gen_unpack1_h ; plus = gen_addv4hi3 ; break ; case V4HImode : unpack_l = gen_unpack2_l ; unpack_h = gen_unpack2_h ; plus = gen_addv2si3 ; break ; default : gcc_unreachable ( ) ; } if ( unsignedp ) x = CONST0_RTX ( mode ) ; else { bool neg ; x = gen_reg_rtx ( mode ) ; neg = ia64_expand_vecint_compare ( LT , mode , x , operands [ 1 ] , CONST0_RTX ( mode ) ) ; gcc_assert ( ! neg ) ; } l = gen_reg_rtx ( wmode ) ; h = gen_reg_rtx ( wmode ) ; s = gen_reg_rtx ( wmode ) ; emit_insn ( unpack_l ( gen_lowpart ( mode , l ) , operands [ 1 ] , x ) ) ; emit_insn ( unpack_h ( gen_lowpart ( mode , h ) , operands [ 1 ] , x ) ) ; emit_insn ( plus ( s , l , operands [ 2 ] ) ) ; emit_insn ( plus ( operands [ 0 ] , h , s ) ) ; } </s>

Emit an integral vector widening sum operations .


<s> bool ia64_extra_constraint ( rtx value , char c ) { switch ( c ) { case 'Q' : return memory_operand ( value , VOIDmode ) && ! MEM_VOLATILE_P ( value ) ; case 'R' : return ( GET_CODE ( value ) == CONST_INT && INTVAL ( value ) >= 1 && INTVAL ( value ) <= 4 ) ; case 'S' : return ( GET_CODE ( value ) == MEM && GET_RTX_CLASS ( GET_CODE ( XEXP ( value , 0 ) ) ) != RTX_AUTOINC && ( reload_in_progress || memory_operand ( value , VOIDmode ) ) ) ; case 'T' : return small_addr_symbolic_operand ( value , VOIDmode ) ; case 'U' : return value == CONST0_RTX ( GET_MODE ( value ) ) ; case 'W' : if ( GET_CODE ( value ) == CONST_VECTOR && GET_MODE_CLASS ( GET_MODE ( value ) ) == MODE_VECTOR_INT ) { value = simplify_subreg ( DImode , value , GET_MODE ( value ) , 0 ) ; return ia64_const_ok_for_letter_p ( INTVAL ( value ) , 'J' ) ; } return false ; case 'Y' : return ( GET_CODE ( value ) == CONST_VECTOR && GET_MODE ( value ) == V2SFmode && ia64_const_double_ok_for_letter_p ( XVECEXP ( value , 0 , 0 ) , 'G' ) && ia64_const_double_ok_for_letter_p ( XVECEXP ( value , 0 , 1 ) , 'G' ) ) ; default : return false ; } } </s>


<s> static void ia64_file_start ( void ) { ia64_flag_var_tracking = flag_var_tracking ; flag_var_tracking = 0 ; default_file_start ( ) ; emit_safe_across_calls ( ) ; } </s>


<s> void ia64_function_arg_advance ( CUMULATIVE_ARGS * cum , enum machine_mode mode , tree type , int named ) { int words = ia64_function_arg_words ( type , mode ) ; int offset = ia64_function_arg_offset ( cum , type , words ) ; enum machine_mode hfa_mode = VOIDmode ; if ( cum -> words >= MAX_ARGUMENT_SLOTS ) return ; cum -> words += words + offset ; if ( type ) hfa_mode = hfa_element_mode ( type , 0 ) ; if ( hfa_mode != VOIDmode && ( ! cum -> prototype || 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 = ( ( mode == BLKmode ) ? int_size_in_bytes ( type ) : GET_MODE_SIZE ( mode ) ) ; 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 ( mode == TFmode || mode == TCmode || ( ! FLOAT_MODE_P ( mode ) || cum -> fp_regs == MAX_ARGUMENT_SLOTS ) ) cum -> int_regs = cum -> words ; else if ( cum -> prototype ) { if ( ! named ) cum -> int_regs = cum -> words ; else cum -> fp_regs += ( GET_MODE_CLASS ( mode ) == MODE_COMPLEX_FLOAT ? 2 : 1 ) ; } else { cum -> fp_regs += ( GET_MODE_CLASS ( 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> int ia64_function_arg_boundary ( enum machine_mode mode , 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 int ia64_function_arg_words ( tree type , enum 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 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 ) ; } </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> rtx ia64_function_value ( tree valtype , tree func ATTRIBUTE_UNUSED ) { enum machine_mode mode ; enum machine_mode hfa_mode ; 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 ) ) ; } return gen_rtx_REG ( mode , GR_RET_FIRST ) ; } } </s>

Return rtx for register that holds the function return value .


<s> static tree ia64_gimplify_va_arg ( tree valist , tree type , tree * pre_p , tree * post_p ) { if ( pass_by_reference ( NULL , TYPE_MODE ( type ) , type , false ) ) { 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 = build ( PLUS_EXPR , TREE_TYPE ( valist ) , valist , build_int_cst ( NULL_TREE , 2 * UNITS_PER_WORD - 1 ) ) ; t = build ( BIT_AND_EXPR , TREE_TYPE ( t ) , t , build_int_cst ( NULL_TREE , - 2 * UNITS_PER_WORD ) ) ; t = build ( MODIFY_EXPR , TREE_TYPE ( valist ) , valist , t ) ; gimplify_and_add ( t , pre_p ) ; } return std_gimplify_va_arg_expr ( valist , type , pre_p , post_p ) ; } </s>


<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 : if ( current_function_is_leaf ) offset = - current_frame_info . total_size ; else offset = - ( current_frame_info . total_size - current_function_outgoing_args_size - 16 ) ; break ; case STACK_POINTER_REGNUM : if ( current_function_is_leaf ) offset = 0 ; else offset = 16 + current_function_outgoing_args_size ; break ; default : gcc_unreachable ( ) ; } break ; case ARG_POINTER_REGNUM : switch ( to ) { case HARD_FRAME_POINTER_REGNUM : offset = 16 - current_function_pretend_args_size ; break ; case STACK_POINTER_REGNUM : offset = ( current_frame_info . total_size + 16 - current_function_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> bool ia64_legitimate_constant_p ( rtx x ) { switch ( GET_CODE ( x ) ) { case CONST_INT : case LABEL_REF : return true ; case CONST_DOUBLE : if ( GET_MODE ( x ) == VOIDmode ) return true ; return CONST_DOUBLE_OK_FOR_G ( x ) ; case CONST : case SYMBOL_REF : return tls_symbolic_operand_type ( x ) == 0 ; case CONST_VECTOR : { enum machine_mode mode = GET_MODE ( x ) ; if ( mode == V2SFmode ) return ia64_extra_constraint ( x , 'Y' ) ; 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> int ia64_load_pair_ok ( rtx dst , rtx src ) { if ( GET_CODE ( dst ) != REG || ! FP_REGNO_P ( REGNO ( dst ) ) ) 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> 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 GET_CODE ( src ) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G ( src ) ; } </s>

Return 1 if the operands of a move are ok .


<s> static void ia64_output_function_end_prologue ( FILE * file ) { if ( ! flag_unwind_tables && ( ! flag_exceptions || USING_SJLJ_EXCEPTIONS ) ) return ; fputs ( "\t.body\n" , file ) ; } </s>

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


<s>
static
void
ia64_output_function_prologue
(
FILE
*
file
,
HOST_WIDE_INT
size
ATTRIBUTE_UNUSED
)
{
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
(
!
flag_unwind_tables
&&
(
!
flag_exceptions
||
USING_SJLJ_EXCEPTIONS
)
)
return
;
mask
=
0
;
grsave
=
grsave_prev
=
0
;
if
(
current_frame_info
.
reg_save_b0
!=
0
)
{
mask
|=
8
;
grsave
=
grsave_prev
=
current_frame_info
.
reg_save_b0
;
}
if
(
current_frame_info
.
reg_save_ar_pfs
!=
0
&&
(
grsave_prev
==
0
||
current_frame_info
.
reg_save_ar_pfs
==
grsave_prev
+
1
)
)
{
mask
|=
4
;
if
(
grsave_prev
==
0
)
grsave
=
current_frame_info
.
reg_save_ar_pfs
;
grsave_prev
=
current_frame_info
.
reg_save_ar_pfs
;
}
if
(
current_frame_info
.
reg_fp
!=
0
&&
(
grsave_prev
==
0
||
current_frame_info
.
reg_fp
==
grsave_prev
+
1
)
)
{
mask
|=
2
;
if
(
grsave_prev
==
0
)
grsave
=
HARD_FRAME_POINTER_REGNUM
;
grsave_prev
=
current_frame_info
.
reg_fp
;
}
if
(
current_frame_info
.
reg_save_pr
!=
0
&&
(
grsave_prev
==
0
||
current_frame_info
.
reg_save_pr
==
grsave_prev
+
1
)
)
{
mask
|=
1
;
if
(
grsave_prev
==
0
)
grsave
=
current_frame_info
.
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> int ia64_register_move_cost ( enum machine_mode mode , enum reg_class from , enum reg_class to ) { if ( to == ADDL_REGS ) to = GR_REGS ; if ( from == ADDL_REGS ) from = GR_REGS ; if ( from < to ) { enum reg_class tmp = to ; to = from , from = tmp ; } if ( mode == XFmode || mode == RFmode ) { if ( to != GR_REGS || from != GR_REGS ) return MEMORY_MOVE_COST ( mode , to , 0 ) ; else return 3 ; } switch ( to ) { case PR_REGS : if ( from == PR_REGS ) return 3 ; if ( from != GR_REGS ) return MEMORY_MOVE_COST ( mode , to , 0 ) ; break ; case BR_REGS : if ( from != GR_REGS && from != GR_AND_BR_REGS ) return MEMORY_MOVE_COST ( mode , to , 0 ) ; break ; case AR_I_REGS : case AR_M_REGS : if ( from != GR_REGS ) return MEMORY_MOVE_COST ( mode , to , 0 ) ; 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 bool ia64_return_in_memory ( tree valtype , tree fntype ATTRIBUTE_UNUSED ) { enum machine_mode mode ; enum 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_setup_incoming_varargs ( CUMULATIVE_ARGS * cum , enum machine_mode mode , tree type , int * pretend_size , int second_time ATTRIBUTE_UNUSED ) { CUMULATIVE_ARGS next_cum = * cum ; ia64_function_arg_advance ( & next_cum , mode , type , 1 ) ; 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> 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 . reg_save_b0 != 0 ) src = gen_rtx_REG ( DImode , current_frame_info . reg_save_b0 ) ; else { HOST_WIDE_INT off ; unsigned int regno ; 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 ; } if ( CONST_OK_FOR_I ( off ) ) emit_insn ( gen_adddi3 ( dest , src , GEN_INT ( off ) ) ) ; else { emit_move_insn ( dest , GEN_INT ( off ) ) ; 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 ; 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 ) ) \ REG_NOTES ( INSN ) = gen_rtx_EXPR_LIST ( REG_INC , \ XEXP ( XEXP ( EXP , 0 ) , 0 ) , \ REG_NOTES ( INSN ) ) insn = emit_insn ( gen_rtx_SET ( VOIDmode , 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 ( VOIDmode , 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> 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 = hard_regno_nregs [ regno ] [ GET_MODE ( 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> static enum tls_model tls_symbolic_operand_type ( rtx addr ) { enum tls_model tls_kind = 0 ; 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> inline bool bundle_state_hasher :: equal ( const value_type * state1 , const compare_type * state2 ) { return ( state1 -> insn_num == state2 -> insn_num && memcmp ( state1 -> dfa_state , state2 -> dfa_state , dfa_state_size ) == 0 ) ; } </s>


<s> static bool expand_vec_perm_broadcast ( struct expand_vec_perm_d * d ) { unsigned i , elt , nelt = d -> nelt ; unsigned char perm2 [ 2 ] ; rtx temp ; bool ok ; if ( ! d -> one_operand_p ) return false ; elt = d -> perm [ 0 ] ; for ( i = 1 ; i < nelt ; ++ i ) if ( d -> perm [ i ] != elt ) return false ; switch ( d -> vmode ) { case V2SImode : case V2SFmode : perm2 [ 0 ] = elt ; perm2 [ 1 ] = elt + 2 ; ok = expand_vselect_vconcat ( d -> target , d -> op0 , d -> op0 , perm2 , 2 ) ; gcc_assert ( ok ) ; break ; case V8QImode : if ( BYTES_BIG_ENDIAN ) elt = 7 - elt ; elt *= BITS_PER_UNIT ; temp = gen_reg_rtx ( DImode ) ; emit_insn ( gen_extzv ( temp , gen_lowpart ( DImode , d -> op0 ) , GEN_INT ( 8 ) , GEN_INT ( elt ) ) ) ; emit_insn ( gen_mux1_brcst_qi ( d -> target , gen_lowpart ( QImode , temp ) ) ) ; break ; case V4HImode : default : gcc_unreachable ( ) ; } return true ; } </s>


<s> static bool expand_vec_perm_v4hi_5 ( struct expand_vec_perm_d * d ) { unsigned char perm2 [ 4 ] ; rtx rmask [ 4 ] ; unsigned i ; rtx t0 , t1 , mask , x ; bool ok ; if ( d -> vmode != V4HImode || d -> one_operand_p ) return false ; if ( d -> testing_p ) return true ; for ( i = 0 ; i < 4 ; ++ i ) { perm2 [ i ] = d -> perm [ i ] & 3 ; rmask [ i ] = ( d -> perm [ i ] & 4 ? const0_rtx : constm1_rtx ) ; } mask = gen_rtx_CONST_VECTOR ( V4HImode , gen_rtvec_v ( 4 , rmask ) ) ; mask = force_reg ( V4HImode , mask ) ; t0 = gen_reg_rtx ( V4HImode ) ; t1 = gen_reg_rtx ( V4HImode ) ; ok = expand_vselect ( t0 , d -> op0 , perm2 , 4 ) ; gcc_assert ( ok ) ; ok = expand_vselect ( t1 , d -> op1 , perm2 , 4 ) ; gcc_assert ( ok ) ; x = gen_rtx_AND ( V4HImode , mask , t0 ) ; emit_insn ( gen_rtx_SET ( VOIDmode , t0 , x ) ) ; x = gen_rtx_NOT ( V4HImode , mask ) ; x = gen_rtx_AND ( V4HImode , x , t1 ) ; emit_insn ( gen_rtx_SET ( VOIDmode , t1 , x ) ) ; x = gen_rtx_IOR ( V4HImode , t0 , t1 ) ; emit_insn ( gen_rtx_SET ( VOIDmode , d -> target , x ) ) ; return true ; } </s>

A subroutine of ia64_expand_vec_perm_const_1 . Emit a full V4HImode constant permutation via two mux2 and a merge .


<s> static bool expand_vselect ( rtx target , rtx op0 , const unsigned char * perm , unsigned nelt ) { rtx rperm [ MAX_VECT_LEN ] , x ; unsigned i ; for ( i = 0 ; i < nelt ; ++ i ) rperm [ i ] = GEN_INT ( perm [ i ] ) ; x = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec_v ( nelt , rperm ) ) ; x = gen_rtx_VEC_SELECT ( GET_MODE ( target ) , op0 , x ) ; x = gen_rtx_SET ( VOIDmode , target , x ) ; rtx_insn * insn = emit_insn ( x ) ; if ( recog_memoized ( insn ) < 0 ) { remove_insn ( insn ) ; return false ; } return true ; } </s>

Construct ( set target ( vec_select op0 ( parallel perm ) ) ) and return true if that 's a valid instruction in the active ISA .


<s> static bool expand_vselect_vconcat ( rtx target , rtx op0 , rtx op1 , const unsigned char * perm , unsigned nelt ) { machine_mode v2mode ; rtx x ; v2mode = GET_MODE_2XWIDER_MODE ( GET_MODE ( op0 ) ) ; x = gen_rtx_VEC_CONCAT ( v2mode , op0 , op1 ) ; return expand_vselect ( target , x , perm , nelt ) ; } </s>

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


<s> static int find_gr_spill ( enum ia64_frame_regs r , int try_locals ) { int regno ; if ( emitted_frame_related_regs [ r ] != 0 ) { regno = emitted_frame_related_regs [ r ] ; if ( regno >= LOC_REG ( 0 ) && regno < LOC_REG ( 80 - frame_pointer_needed ) && current_frame_info . n_local_regs < regno - LOC_REG ( 0 ) + 1 ) current_frame_info . n_local_regs = regno - LOC_REG ( 0 ) + 1 ; else if ( crtl -> is_leaf && regno >= GR_REG ( 1 ) && regno <= GR_REG ( 31 ) ) current_frame_info . gr_used_mask |= 1 << regno ; return regno ; } if ( crtl -> is_leaf ) { for ( regno = GR_REG ( 1 ) ; regno <= GR_REG ( 31 ) ; regno ++ ) if ( ! df_regs_ever_live_p ( regno ) && call_used_regs [ regno ] && ! fixed_regs [ regno ] && ! global_regs [ regno ] && ( ( current_frame_info . gr_used_mask >> regno ) & 1 ) == 0 && ! is_emitted ( regno ) ) { current_frame_info . gr_used_mask |= 1 << regno ; return regno ; } } if ( try_locals ) { regno = current_frame_info . n_local_regs ; while ( regno < ( 80 - frame_pointer_needed ) ) if ( ! is_emitted ( LOC_REG ( regno ++ ) ) ) { current_frame_info . n_local_regs = regno ; return LOC_REG ( regno - 1 ) ; } } return 0 ; } </s>

Helper function for ia64_compute_frame_size : find an appropriate general register to spill some special register to . SPECIAL_SPILL_MASK contains bits in GR0 to GR31 that have already been allocated by this routine . TRY_LOCALS is true if we should attempt to locate a local regnum .


"value of -mfixed-range must have form REG1-REG2"

Parse the -mfixed-range= option string .


<s> inline hashval_t bundle_state_hasher :: hash ( const value_type * 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 ) 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 int ia64_adjust_cost_2 ( 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_VALUE ( 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 of type DEP_TYPE or INSN on DEP_INSN . COST is the current cost , DW is dependency weakness .


<s> static int ia64_arg_partial_bytes ( cumulative_args_t cum_v , machine_mode mode , tree type , bool named ATTRIBUTE_UNUSED ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; int words = ia64_function_arg_words ( type , mode ) ; int offset = ia64_function_arg_offset ( cum , 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 SFmode : return FS ; case DFmode : return FT ; default : return I64 ; } } </s>

Return ivms_arg_type based on machine_mode .


<s> static void ia64_emit_insn_before ( rtx insn , rtx 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> 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 , insns ; 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 , 3 , * op0 , TFmode , * op1 , TFmode , GEN_INT ( magic ) , DImode ) ; cmp = gen_reg_rtx ( BImode ) ; emit_insn ( gen_rtx_SET ( VOIDmode , cmp , gen_rtx_fmt_ee ( ncode , BImode , ret , const0_rtx ) ) ) ; 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 ( VOIDmode , 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 { 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 ( VOIDmode , dest , tmp ) ) ; tmp = gen_rtx_LO_SUM ( Pmode , gen_const_mem ( Pmode , dest ) , src ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , tmp ) ) ; if ( addend ) { tmp = gen_rtx_PLUS ( Pmode , dest , GEN_INT ( addend ) ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , tmp ) ) ; } } return true ; } </s>


<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 ( VOIDmode , operands [ 0 ] , x ) ) ; } else if ( of == CONST0_RTX ( mode ) ) { x = gen_rtx_AND ( mode , cmp , ot ) ; emit_insn ( gen_rtx_SET ( VOIDmode , 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 ( VOIDmode , 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 ( VOIDmode , f , x ) ) ; x = gen_rtx_IOR ( mode , t , f ) ; emit_insn ( gen_rtx_SET ( VOIDmode , 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 V2SImode : { rtx t1 , t2 , mask ; mask = GEN_INT ( 0x80000000 ) ; mask = gen_rtx_CONST_VECTOR ( V2SImode , gen_rtvec ( 2 , mask , 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 V8QImode : case V4HImode : x = gen_reg_rtx ( mode ) ; emit_insn ( gen_rtx_SET ( VOIDmode , 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 ( VOIDmode , 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 ( VOIDmode , 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 rtx ia64_function_arg ( cumulative_args_t cum , machine_mode mode , const_tree type , bool named ) { return ia64_function_arg_1 ( cum , mode , type , named , false ) ; } </s>

Implement TARGET_FUNCION_ARG target hook .


<s> static void ia64_function_arg_advance ( cumulative_args_t cum_v , machine_mode mode , const_tree type , bool named ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; int words = ia64_function_arg_words ( type , mode ) ; int offset = ia64_function_arg_offset ( cum , 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 ( mode ) ; cum -> words += words + offset ; if ( TARGET_ABI_OPEN_VMS ) { cum -> int_regs = cum -> words ; cum -> fp_regs = cum -> words ; return ; } if ( type ) hfa_mode = hfa_element_mode ( type , 0 ) ; if ( hfa_mode != VOIDmode && ( ! cum -> prototype || 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 = ( ( mode == BLKmode ) ? int_size_in_bytes ( type ) : GET_MODE_SIZE ( mode ) ) ; 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 ( mode == TFmode || mode == TCmode || ( ! FLOAT_MODE_P ( mode ) || cum -> fp_regs == MAX_ARGUMENT_SLOTS ) ) cum -> int_regs = cum -> words ; else if ( cum -> prototype ) { if ( ! named ) cum -> int_regs = cum -> words ; else cum -> fp_regs += ( GET_MODE_CLASS ( mode ) == MODE_COMPLEX_FLOAT ? 2 : 1 ) ; } else { cum -> fp_regs += ( GET_MODE_CLASS ( 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 rtx ia64_function_incoming_arg ( cumulative_args_t cum , machine_mode mode , const_tree type , bool named ) { return ia64_function_arg_1 ( cum , mode , type , named , true ) ; } </s>

Implement TARGET_FUNCION_INCOMING_ARG target hook .


<s> static tree ia64_gimplify_va_arg ( tree valist , tree type , gimple_seq * pre_p , gimple_seq * post_p ) { if ( pass_by_reference ( NULL , TYPE_MODE ( type ) , type , false ) ) { 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> enum direction ia64_hpux_function_arg_padding ( machine_mode mode , const_tree type ) { if ( type && AGGREGATE_TYPE_P ( type ) && int_size_in_bytes ( type ) < UNITS_PER_WORD ) return upward ; return DEFAULT_FUNCTION_ARG_PADDING ( mode , type ) ; } </s>

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


<s> static bool ia64_libgcc_floating_mode_supported_p ( machine_mode mode ) { switch ( mode ) { case SFmode : case DFmode : return true ; case XFmode : return false ; return true ; case TFmode : return false ; return true ; default : return false ; } } </s>


<s> static int ia64_mode_to_int ( machine_mode mode ) { switch ( mode ) { case BImode : return 0 ; case QImode : return 1 ; case HImode : return 2 ; case SImode : return 3 ; case DImode : return 4 ; case SFmode : return 5 ; case DFmode : return 6 ; case XFmode : return 7 ; case TImode : return SPEC_MODE_INVALID ; default : return SPEC_MODE_INVALID ; } } </s>


<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 = ( global_options_set . x_g_switch_value ? g_switch_value : IA64_DEFAULT_GVALUE ) ; init_machine_status = ia64_init_machine_status ; if ( align_functions <= 0 ) align_functions = 64 ; if ( align_loops <= 0 ) align_loops = 32 ; if ( TARGET_ABI_OPEN_VMS ) flag_no_common = 1 ; ia64_override_options_after_change ( ) ; } </s>


<s>
static
void
ia64_output_function_prologue
(
FILE
*
file
,
HOST_WIDE_INT
size
ATTRIBUTE_UNUSED
)
{
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_setup_incoming_varargs ( cumulative_args_t cum , machine_mode mode , tree type , 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 ) , mode , type , 1 ) ; 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> 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 ( VOIDmode , 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 ( VOIDmode , 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> static bool ia64_vectorize_vec_perm_const_ok ( machine_mode vmode , const unsigned char * sel ) { struct expand_vec_perm_d d ; unsigned int i , nelt , which ; bool ret ; d . vmode = vmode ; d . nelt = nelt = GET_MODE_NUNITS ( d . vmode ) ; d . testing_p = true ; memcpy ( d . perm , sel , nelt ) ; for ( i = which = 0 ; i < nelt ; ++ i ) { unsigned char e = d . perm [ i ] ; gcc_assert ( e < 2 * nelt ) ; which |= ( e < nelt ? 1 : 2 ) ; } if ( which == 2 ) for ( i = 0 ; i < nelt ; ++ i ) d . perm [ i ] -= nelt ; d . one_operand_p = ( which != 3 ) ; 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 ( ) ; ret = ia64_expand_vec_perm_const_1 ( & d ) ; end_sequence ( ) ; return ret ; } </s>


<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" ) ; abort_libfunc = init_one_libfunc ( "decc$abort" ) ; memcmp_libfunc = init_one_libfunc ( "decc$memcmp" ) ; 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>
const
char
*
output_probe_stack_range
(
rtx
reg1
,
rtx
reg2
)
{
static
int
labelno
=
0
;
char
loop_lab
[
32
]
,
end_lab
[
32
]
;
rtx
xops
[
3
]
;
ASM_GENERATE_INTERNAL_LABEL
(
loop_lab
,
"LPSRL"
,
labelno
)
;
ASM_GENERATE_INTERNAL_LABEL
(
end_lab
,
"LPSRE"
,
labelno
++
)
;
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
loop_lab
)
;
xops
[
0
]
=
reg1
;
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
[
REGNO
(
xops
[
2
]
)
]
)
;
assemble_name_raw
(
asm_out_file
,
end_lab
)
;
fputc
(
'\n'
,
asm_out_file
)
;
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
)
;
fprintf
(
asm_out_file
,
"\tbr "
)
;
assemble_name_raw
(
asm_out_file
,
loop_lab
)
;
fputc
(
'\n'
,
asm_out_file
)
;
ASM_OUTPUT_INTERNAL_LABEL
(
asm_out_file
,
end_lab
)
;
return
""
;
}
</s>

Wrapper around the output_probe_stack_range routines .


<s>
static
void
process_cfa_adjust_cfa
(
FILE
*
asm_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
(
asm_out_file
,
"\t.fframe "
HOST_WIDE_INT_PRINT_DEC
"\n"
,
INTVAL
(
op1
)
)
;
}
else
process_epilogue
(
asm_out_file
,
insn
,
unwind
,
frame
)
;
}
else
{
gcc_assert
(
src
==
hard_frame_pointer_rtx
)
;
process_epilogue
(
asm_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
(
asm_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> 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 , insns ; 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 , 3 , * 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 ) ) ) ; 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>


<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 V2SImode : { rtx t1 , t2 , mask ; mask = gen_int_mode ( 0x80000000 , SImode ) ; mask = gen_rtx_CONST_VECTOR ( V2SImode , gen_rtvec ( 2 , mask , 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 V8QImode : case 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>


<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_VALUE ( 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> 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 , 3 , * 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>


"value of %<-mfixed-range%> must have form REG1-REG2"

Parse the -mfixed-range= option string .


<s>
static
void
emit_insn_group_barriers
(
FILE
*
dump
)
{
rtx_insn
*
insn
;
rtx_insn
*
last_label
=
0
;
int
insns_since_last_label
=
0
;
init_insn_group_barriers
(
)
;
for
(
insn
=
get_insns
(
)
;
insn
;
insn
=
NEXT_INSN
(
insn
)
)
{
if
(
LABEL_P
(
insn
)
)
{
if
(
insns_since_last_label
)
last_label
=
insn
;
insns_since_last_label
=
0
;
}
else
if
(
NOTE_P
(
insn
)
&&
NOTE_KIND
(
insn
)
==
NOTE_INSN_BASIC_BLOCK
)
{
if
(
insns_since_last_label
)
last_label
=
insn
;
insns_since_last_label
=
0
;
}
else
if
(
NONJUMP_INSN_P
(
insn
)
&&
GET_CODE
(
PATTERN
(
insn
)
)
==
UNSPEC_VOLATILE
&&
XINT
(
PATTERN
(
insn
)
,
1
)
==
UNSPECV_INSN_GROUP_BARRIER
)
{
init_insn_group_barriers
(
)
;
last_label
=
0
;
}
else
if
(
NONDEBUG_INSN_P
(
insn
)
)
{
insns_since_last_label
=
1
;
if
(
group_barrier_needed
(
insn
)
)
{
if
(
last_label
)
{
if
(
dump
)
fprintf
(
dump
,
"Emitting stop before label %d\n"
,
INSN_UID
(
last_label
)
)
;
emit_insn_before
(
gen_insn_group_barrier
(
GEN_INT
(
3
)
)
,
last_label
)
;
insn
=
last_label
;
init_insn_group_barriers
(
)
;
last_label
=
0
;
}
}
}
}
}
</s>

INSNS is an chain of instructions . Scan the chain , and insert stop bits as necessary to eliminate dependendencies . This function assumes that a final instruction scheduling pass has been run which has already inserted most of the necessary stop bits . This function only inserts new ones at basic block boundaries , since these are invisible to the scheduler .


<s> static void emit_predicate_relation_info ( void ) { basic_block bb ; FOR_EACH_BB_REVERSE_FN ( bb , cfun ) { int r ; rtx_insn * head = BB_HEAD ( bb ) ; if ( ! LABEL_P ( head ) ) continue ; if ( NOTE_INSN_BASIC_BLOCK_P ( NEXT_INSN ( head ) ) ) head = NEXT_INSN ( head ) ; for ( r = PR_REG ( 2 ) ; r < PR_REG ( 64 ) ; r += 2 ) if ( REGNO_REG_SET_P ( df_get_live_in ( bb ) , r ) ) { rtx p = gen_rtx_REG ( BImode , r ) ; rtx_insn * n = emit_insn_after ( gen_pred_rel_mutex ( p ) , head ) ; if ( head == BB_END ( bb ) ) BB_END ( bb ) = n ; head = n ; } } FOR_EACH_BB_REVERSE_FN ( bb , cfun ) { rtx_insn * insn = BB_HEAD ( bb ) ; while ( 1 ) { if ( CALL_P ( insn ) && GET_CODE ( PATTERN ( insn ) ) == COND_EXEC && find_reg_note ( insn , REG_NORETURN , NULL_RTX ) ) { rtx_insn * b = emit_insn_before ( gen_safe_across_calls_all ( ) , insn ) ; rtx_insn * a = emit_insn_after ( gen_safe_across_calls_normal ( ) , insn ) ; if ( BB_HEAD ( bb ) == insn ) BB_HEAD ( bb ) = b ; if ( BB_END ( bb ) == insn ) BB_END ( bb ) = a ; } if ( insn == BB_END ( bb ) ) break ; insn = NEXT_INSN ( insn ) ; } } } </s>

Emit pseudo-ops for the assembler to describe predicate relations . At present this assumes that we only consider predicate pairs to be mutex , and that the assembler can deduce proper values from straight-line code .


<s>
void
emit_safe_across_calls
(
void
)
{
unsigned
int
rs
,
re
;
int
out_state
;
rs
=
1
;
out_state
=
0
;
while
(
1
)
{
while
(
rs
<
64
&&
call_used_or_fixed_reg_p
(
PR_REG
(
rs
)
)
)
rs
++
;
if
(
rs
>=
64
)
break
;
for
(
re
=
rs
+
1
;
re
<
64
&&
!
call_used_or_fixed_reg_p
(
PR_REG
(
re
)
)
;
re
++
)
continue
;
if
(
out_state
==
0
)
{
fputs
(
"\t.pred.safe_across_calls "
,
asm_out_file
)
;
out_state
=
1
;
}
else
fputc
(
','
,
asm_out_file
)
;
if
(
re
==
rs
+
1
)
fprintf
(
asm_out_file
,
"p%u"
,
rs
)
;
else
fprintf
(
asm_out_file
,
"p%u-p%u"
,
rs
,
re
1
)
;
rs
=
re
+
1
;
}
if
(
out_state
)
fputc
(
'\n'
,
asm_out_file
)
;
}
</s>


<s> inline bool bundle_state_hasher :: equal ( const bundle_state * state1 , const bundle_state * state2 ) { return ( state1 -> insn_num == state2 -> insn_num && memcmp ( state1 -> dfa_state , state2 -> dfa_state , dfa_state_size ) == 0 ) ; } </s>


<s> static bool expand_vec_perm_1 ( struct expand_vec_perm_d * d ) { unsigned i , nelt = d -> nelt ; unsigned char perm2 [ MAX_VECT_LEN ] ; if ( d -> one_operand_p ) { if ( expand_vec_perm_identity ( d ) ) return true ; if ( expand_vselect ( d -> target , d -> op0 , d -> perm , nelt ) ) return true ; } if ( expand_vselect_vconcat ( d -> target , d -> op0 , d -> op1 , d -> perm , nelt ) ) return true ; if ( ! d -> one_operand_p ) { for ( i = 0 ; i < nelt ; ++ i ) { unsigned e = d -> perm [ i ] ; if ( e >= nelt ) e -= nelt ; else e += nelt ; perm2 [ i ] = e ; } if ( expand_vselect_vconcat ( d -> target , d -> op1 , d -> op0 , perm2 , nelt ) ) return true ; } if ( expand_vec_perm_shrp ( d ) ) return true ; return false ; } </s>

Try to instantiate D in a single instruction .


<s> static bool expand_vec_perm_broadcast ( struct expand_vec_perm_d * d ) { unsigned i , elt , nelt = d -> nelt ; unsigned char perm2 [ 2 ] ; rtx temp ; bool ok ; if ( ! d -> one_operand_p ) return false ; elt = d -> perm [ 0 ] ; for ( i = 1 ; i < nelt ; ++ i ) if ( d -> perm [ i ] != elt ) return false ; switch ( d -> vmode ) { case E_V2SImode : case E_V2SFmode : perm2 [ 0 ] = elt ; perm2 [ 1 ] = elt + 2 ; ok = expand_vselect_vconcat ( d -> target , d -> op0 , d -> op0 , perm2 , 2 ) ; gcc_assert ( ok ) ; break ; case E_V8QImode : if ( BYTES_BIG_ENDIAN ) elt = 7 - elt ; elt *= BITS_PER_UNIT ; temp = gen_reg_rtx ( DImode ) ; emit_insn ( gen_extzv ( temp , gen_lowpart ( DImode , d -> op0 ) , GEN_INT ( 8 ) , GEN_INT ( elt ) ) ) ; emit_insn ( gen_mux1_brcst_qi ( d -> target , gen_lowpart ( QImode , temp ) ) ) ; break ; case E_V4HImode : default : gcc_unreachable ( ) ; } return true ; } </s>


<s> static bool expand_vec_perm_identity ( struct expand_vec_perm_d * d ) { unsigned i , nelt = d -> nelt ; for ( i = 0 ; i < nelt ; ++ i ) if ( d -> perm [ i ] != i ) return false ; if ( ! d -> testing_p ) emit_move_insn ( d -> target , d -> op0 ) ; return true ; } </s>


<s> static bool expand_vec_perm_shrp ( struct expand_vec_perm_d * d ) { unsigned i , nelt = d -> nelt , shift , mask ; rtx tmp , hi , lo ; if ( d -> vmode == V2SFmode ) return false ; mask = ( d -> one_operand_p ? nelt - 1 : 2 * nelt - 1 ) ; shift = d -> perm [ 0 ] ; if ( BYTES_BIG_ENDIAN && shift > nelt ) return false ; for ( i = 1 ; i < nelt ; ++ i ) if ( d -> perm [ i ] != ( ( shift + i ) & mask ) ) return false ; if ( d -> testing_p ) return true ; hi = shift < nelt ? d -> op1 : d -> op0 ; lo = shift < nelt ? d -> op0 : d -> op1 ; shift %= nelt ; shift *= GET_MODE_UNIT_SIZE ( d -> vmode ) * BITS_PER_UNIT ; gcc_assert ( IN_RANGE ( shift , 1 , 63 ) ) ; if ( BYTES_BIG_ENDIAN ) shift = 64 - shift ; tmp = gen_reg_rtx ( DImode ) ; hi = gen_lowpart ( DImode , hi ) ; lo = gen_lowpart ( DImode , lo ) ; emit_insn ( gen_shrp ( tmp , hi , lo , GEN_INT ( shift ) ) ) ; emit_move_insn ( d -> target , gen_lowpart ( d -> vmode , tmp ) ) ; return true ; } </s>

Try to expand D via a shrp instruction .


<s> static bool expand_vec_perm_v4hi_5 ( struct expand_vec_perm_d * d ) { unsigned char perm2 [ 4 ] ; rtx rmask [ 4 ] ; unsigned i ; rtx t0 , t1 , mask , x ; bool ok ; if ( d -> vmode != V4HImode || d -> one_operand_p ) return false ; if ( d -> testing_p ) return true ; for ( i = 0 ; i < 4 ; ++ i ) { perm2 [ i ] = d -> perm [ i ] & 3 ; rmask [ i ] = ( d -> perm [ i ] & 4 ? const0_rtx : constm1_rtx ) ; } mask = gen_rtx_CONST_VECTOR ( V4HImode , gen_rtvec_v ( 4 , rmask ) ) ; mask = force_reg ( V4HImode , mask ) ; t0 = gen_reg_rtx ( V4HImode ) ; t1 = gen_reg_rtx ( V4HImode ) ; ok = expand_vselect ( t0 , d -> op0 , perm2 , 4 ) ; gcc_assert ( ok ) ; ok = expand_vselect ( t1 , d -> op1 , perm2 , 4 ) ; gcc_assert ( ok ) ; x = gen_rtx_AND ( V4HImode , mask , t0 ) ; emit_insn ( gen_rtx_SET ( t0 , x ) ) ; x = gen_rtx_NOT ( V4HImode , mask ) ; x = gen_rtx_AND ( V4HImode , x , t1 ) ; emit_insn ( gen_rtx_SET ( t1 , x ) ) ; x = gen_rtx_IOR ( V4HImode , t0 , t1 ) ; emit_insn ( gen_rtx_SET ( d -> target , x ) ) ; return true ; } </s>

A subroutine of ia64_expand_vec_perm_const_1 . Emit a full V4HImode constant permutation via two mux2 and a merge .


<s> static bool expand_vselect ( rtx target , rtx op0 , const unsigned char * perm , unsigned nelt ) { rtx rperm [ MAX_VECT_LEN ] , x ; unsigned i ; for ( i = 0 ; i < nelt ; ++ i ) rperm [ i ] = GEN_INT ( perm [ i ] ) ; x = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec_v ( nelt , rperm ) ) ; x = gen_rtx_VEC_SELECT ( GET_MODE ( target ) , op0 , x ) ; x = gen_rtx_SET ( target , x ) ; rtx_insn * insn = emit_insn ( x ) ; if ( recog_memoized ( insn ) < 0 ) { remove_insn ( insn ) ; return false ; } return true ; } </s>

Construct ( set target ( vec_select op0 ( parallel perm ) ) ) and return true if that 's a valid instruction in the active ISA .


<s> static bool expand_vselect_vconcat ( rtx target , rtx op0 , rtx op1 , const unsigned char * perm , unsigned nelt ) { machine_mode v2mode ; rtx x ; if ( ! GET_MODE_2XWIDER_MODE ( GET_MODE ( op0 ) ) . exists ( & v2mode ) ) return false ; x = gen_rtx_VEC_CONCAT ( v2mode , op0 , op1 ) ; return expand_vselect ( target , x , perm , nelt ) ; } </s>

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


<s> static int find_gr_spill ( enum ia64_frame_regs r , int try_locals ) { int regno ; if ( emitted_frame_related_regs [ r ] != 0 ) { regno = emitted_frame_related_regs [ r ] ; if ( regno >= LOC_REG ( 0 ) && regno < LOC_REG ( 80 - frame_pointer_needed ) && current_frame_info . n_local_regs < regno - LOC_REG ( 0 ) + 1 ) current_frame_info . n_local_regs = regno - LOC_REG ( 0 ) + 1 ; else if ( crtl -> is_leaf && regno >= GR_REG ( 1 ) && regno <= GR_REG ( 31 ) ) current_frame_info . gr_used_mask |= 1 << regno ; return regno ; } if ( crtl -> is_leaf ) { for ( regno = GR_REG ( 1 ) ; regno <= GR_REG ( 31 ) ; regno ++ ) if ( ! df_regs_ever_live_p ( regno ) && call_used_or_fixed_reg_p ( regno ) && ! fixed_regs [ regno ] && ! global_regs [ regno ] && ( ( current_frame_info . gr_used_mask >> regno ) & 1 ) == 0 && ! is_emitted ( regno ) ) { current_frame_info . gr_used_mask |= 1 << regno ; return regno ; } } if ( try_locals ) { regno = current_frame_info . n_local_regs ; while ( regno < ( 80 - frame_pointer_needed ) ) if ( ! is_emitted ( LOC_REG ( regno ++ ) ) ) { current_frame_info . n_local_regs = regno ; return LOC_REG ( regno - 1 ) ; } } return 0 ; } </s>

Helper function for ia64_compute_frame_size : find an appropriate general register to spill some special register to . SPECIAL_SPILL_MASK contains bits in GR0 to GR31 that have already been allocated by this routine . TRY_LOCALS is true if we should attempt to locate a local regnum .


<s> static void finish_bundle_states ( void ) { struct bundle_state * curr_state , * next_state ; for ( curr_state = allocated_bundle_states_chain ; curr_state != NULL ; curr_state = next_state ) { next_state = curr_state -> allocated_states_chain ; free ( curr_state -> dfa_state ) ; free ( curr_state ) ; } } </s>

Finish work with abstract data ` bundle states ' .


<s> static void finish_bundle_state_table ( void ) { delete bundle_state_table ; bundle_state_table = NULL ; } </s>


<s> static void free_bundle_state ( struct bundle_state * state ) { state -> next = free_bundle_state_chain ; free_bundle_state_chain = state ; } </s>

The following function frees given bundle state .


<s> static rtx gen_movdi_x ( rtx dest , rtx src , rtx offset ATTRIBUTE_UNUSED ) { return gen_movdi ( dest , src ) ; } </s>

Wrapper functions that discards the CONST_INT spill offset . These exist so that we can give gr_spill/gr_fill the offset they need and use a consistant function interface .


<s> const char * get_bundle_name ( int b ) { return bundle_name [ b ] ; } </s>


<s> static struct bundle_state * get_free_bundle_state ( void ) { struct bundle_state * result ; if ( free_bundle_state_chain != NULL ) { result = free_bundle_state_chain ; free_bundle_state_chain = result -> next ; } else { result = XNEW ( struct bundle_state ) ; result -> dfa_state = xmalloc ( dfa_state_size ) ; result -> allocated_states_chain = allocated_bundle_states_chain ; allocated_bundle_states_chain = result ; } result -> unique_num = bundle_states_num ++ ; return result ; } </s>

The following function returns a free bundle state .


<s> static int get_insn_spec_code ( const_rtx insn ) { rtx pat , reg , mem ; pat = PATTERN ( insn ) ; if ( GET_CODE ( pat ) == COND_EXEC ) pat = COND_EXEC_CODE ( pat ) ; if ( GET_CODE ( pat ) != SET ) return - 1 ; reg = SET_DEST ( pat ) ; if ( ! REG_P ( reg ) ) return - 1 ; mem = SET_SRC ( pat ) ; if ( GET_CODE ( mem ) == ZERO_EXTEND ) mem = XEXP ( mem , 0 ) ; return get_spec_unspec_code ( mem ) ; } </s>

If INSN is a speculative load , return its UNSPEC code . Return -1 otherwise .


<s> static int get_max_pos ( state_t state ) { if ( cpu_unit_reservation_p ( state , pos_6 ) ) return 6 ; else if ( cpu_unit_reservation_p ( state , pos_5 ) ) return 5 ; else if ( cpu_unit_reservation_p ( state , pos_4 ) ) return 4 ; else if ( cpu_unit_reservation_p ( state , pos_3 ) ) return 3 ; else if ( cpu_unit_reservation_p ( state , pos_2 ) ) return 2 ; else if ( cpu_unit_reservation_p ( state , pos_1 ) ) return 1 ; else return 0 ; } </s>

The following function returns position in the two window bundle for given STATE .


<s> static int get_mode_no_for_insn ( rtx_insn * insn ) { rtx reg , mem , mode_rtx ; int mode_no ; bool extend_p ; extract_insn_cached ( insn ) ; if ( recog_data . n_operands != 2 ) return - 1 ; reg = recog_data . operand [ 0 ] ; mem = recog_data . operand [ 1 ] ; if ( get_attr_speculable1 ( insn ) == SPECULABLE1_YES ) { if ( ! reload_completed ) { if ( ! REG_P ( reg ) || AR_REGNO_P ( REGNO ( reg ) ) ) return - 1 ; if ( ! MEM_P ( mem ) ) return - 1 ; { rtx mem_reg = XEXP ( mem , 0 ) ; if ( ! REG_P ( mem_reg ) ) return - 1 ; } mode_rtx = mem ; } else if ( get_attr_speculable2 ( insn ) == SPECULABLE2_YES ) { gcc_assert ( REG_P ( reg ) && MEM_P ( mem ) ) ; mode_rtx = mem ; } else return - 1 ; } else if ( get_attr_data_speculative ( insn ) == DATA_SPECULATIVE_YES || get_attr_control_speculative ( insn ) == CONTROL_SPECULATIVE_YES || get_attr_check_load ( insn ) == CHECK_LOAD_YES ) { gcc_assert ( REG_P ( reg ) && MEM_P ( mem ) ) ; mode_rtx = mem ; } else { enum attr_itanium_class attr_class = get_attr_itanium_class ( insn ) ; if ( attr_class == ITANIUM_CLASS_CHK_A || attr_class == ITANIUM_CLASS_CHK_S_I || attr_class == ITANIUM_CLASS_CHK_S_F ) mode_rtx = reg ; else return - 1 ; } mode_no = ia64_mode_to_int ( GET_MODE ( mode_rtx ) ) ; if ( mode_no == SPEC_MODE_INVALID ) return - 1 ; extend_p = ( GET_MODE ( reg ) != GET_MODE ( mode_rtx ) ) ; if ( extend_p ) { if ( ! ( SPEC_MODE_FOR_EXTEND_FIRST <= mode_no && mode_no <= SPEC_MODE_FOR_EXTEND_LAST ) ) return - 1 ; mode_no += SPEC_GEN_EXTEND_OFFSET ; } return mode_no ; } </s>

If INSN is an appropriate load return its mode . Return -1 otherwise .


<s> static rtx_insn * get_next_important_insn ( rtx_insn * insn , rtx_insn * tail ) { for ( ; insn && insn != tail ; insn = NEXT_INSN ( insn ) ) if ( important_for_bundling_p ( insn ) ) return insn ; return NULL ; } </s>

The following function returns an insn important for insn bundling followed by INSN and before TAIL .


Return a function that will generate a check for speculation TS with mode MODE_NO . If simple check is needed , pass true for SIMPLE_CHECK_P . If clearing check is needed , pass true for CLEARING_CHECK_P .


Return a function that will generate a load of mode MODE_NO with speculation types TS .


<s> static int get_spec_unspec_code ( const_rtx x ) { if ( GET_CODE ( x ) != UNSPEC ) return - 1 ; { int code ; code = XINT ( x , 1 ) ; switch ( code ) { case UNSPEC_LDA : case UNSPEC_LDS : case UNSPEC_LDS_A : case UNSPEC_LDSA : return code ; default : return - 1 ; } } } </s>

If X is an unspec part of a speculative load , return its code . Return -1 otherwise .