rtlanal.c (note_uses): Deal with SEQUENCEs.
* rtlanal.c (note_uses): Deal with SEQUENCEs. * config/bfin/bfin.c: Include "timevar.h". (bfin_flag_schedule_insns2, splitting_for_sched, bfin_flag_var_tracking): New variables. (print_operand): Handle '%!'. (override_options): Disable normal sched2 pass, instead set bfin_flag_schedule_insns2 for reorg to handle it. (output_file_start): Likewise for var-tracking. (bfin_optimize_loop): Take some care not to stumble over SEQUENCEs. (gen_one_bundle, bfin_gen_bundles, type_for_anomaly, trapping_loads_p): New functions. (bfin_reorg): Do second scheduling pass here, and call bfin_gen_bundles. Use type_for_anomaly and trapping_loads_p instead of examining insns directly. If bfin_flag_var_tracking, call var-tracking pass when done with everything else. * config/bfin/bfin.h (PRINT_OPERAND_PUNCT_VALID_P): '!' is valid. * config/bfin/bfin.md (UNSPEC_32BIT): New constant. (movsi_insn32): New pattern, with two new splits to create it before the final scheduling pass. (neghi2): Not a dsp32 insn, rather alu0. (movbi, pushsi_insn, popsi_insn, movsi_insn, movv2hi_insn, movhi_insn, movqi_insn, movsf_insn, movsi_insv, extendhisi2, zero_extendhisi2, extendqihi2, extendqisi2, zero_extendqihi2, zero_extendqisi2, mulhisi3, umulhisi3, ssadsi3, sssubsi3, smaxsi3, sminsi3, abssi2, ssnegsi2, signbitssi2, smaxhi3, sminhi3, abshi2, ssneghi2, signbitshi2, movhi_low2high, movhi_high2high, movhi_low2low, movhi_high2low, movhiv2hi_low, movhiv2hi_high, composev2hi, packv2hi, movv2hi_hi, ssaddhi3, sssubhi3, addv2hi3, ssaddv2hi3, subv2hi3, sssubv2hi3, addsubv2hi3, subaddv2hi3, ssaddsubv2hi3, sssubaddv2hi3, sublohiv2hi3, subhilov2hi3, sssublohiv2hi3, sssubhilov2hi3, addlohiv2hi3, addhilov2hi3, ssaddlohiv2hi3, ssaddhilov2hi3, sminv2hi3, smaxv2hi3, flag_mulhi, flag_mulhisi, flag_mulhisi_parts, flag_machi, flag_machi_acconly, flag_macinithi, flag_macinit1hi, mulv2hi3, flag_mulv2hi, flag_mulv2hi_parts, flag_macv2hi_parts, flag_macv2hi_parts_acconly, flag_macinitv2hi_parts, flag_macinit1v2hi_parts, mulhisi_ll, mulhisi_lh, mulhisi_hl, mulhisi_hh, ssnegv2hi2, absv2hi2, ssashiftv2hi3, ssashifthi3, lshiftv2hi3, lshifthi3): Use '%!' to terminate all dsp32/load/store variants instead of ';'. (ror_one, rol_one): Likewise. Make them dsp32 insns. (ashlsi3_insn, ashrsi3, lshrsi3): Add dsp32 variants. (align8, align16, align24): Now named patterns; also using '%!'. (mnop): New insn. From-SVN: r119534
This commit is contained in:
parent
9fc4da9d86
commit
bbbc206e9f
@ -1,3 +1,49 @@
|
||||
2006-12-04 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||
|
||||
* rtlanal.c (note_uses): Deal with SEQUENCEs.
|
||||
* config/bfin/bfin.c: Include "timevar.h".
|
||||
(bfin_flag_schedule_insns2, splitting_for_sched,
|
||||
bfin_flag_var_tracking): New variables.
|
||||
(print_operand): Handle '%!'.
|
||||
(override_options): Disable normal sched2 pass, instead set
|
||||
bfin_flag_schedule_insns2 for reorg to handle it.
|
||||
(output_file_start): Likewise for var-tracking.
|
||||
(bfin_optimize_loop): Take some care not to stumble over SEQUENCEs.
|
||||
(gen_one_bundle, bfin_gen_bundles, type_for_anomaly, trapping_loads_p):
|
||||
New functions.
|
||||
(bfin_reorg): Do second scheduling pass here, and call
|
||||
bfin_gen_bundles. Use type_for_anomaly and trapping_loads_p instead
|
||||
of examining insns directly. If bfin_flag_var_tracking, call
|
||||
var-tracking pass when done with everything else.
|
||||
* config/bfin/bfin.h (PRINT_OPERAND_PUNCT_VALID_P): '!' is valid.
|
||||
* config/bfin/bfin.md (UNSPEC_32BIT): New constant.
|
||||
(movsi_insn32): New pattern, with two new splits to create it
|
||||
before the final scheduling pass.
|
||||
(neghi2): Not a dsp32 insn, rather alu0.
|
||||
(movbi, pushsi_insn, popsi_insn, movsi_insn, movv2hi_insn, movhi_insn,
|
||||
movqi_insn, movsf_insn, movsi_insv, extendhisi2, zero_extendhisi2,
|
||||
extendqihi2, extendqisi2, zero_extendqihi2, zero_extendqisi2,
|
||||
mulhisi3, umulhisi3, ssadsi3, sssubsi3, smaxsi3, sminsi3, abssi2,
|
||||
ssnegsi2, signbitssi2, smaxhi3, sminhi3, abshi2, ssneghi2, signbitshi2,
|
||||
movhi_low2high, movhi_high2high, movhi_low2low, movhi_high2low,
|
||||
movhiv2hi_low, movhiv2hi_high, composev2hi, packv2hi, movv2hi_hi,
|
||||
ssaddhi3, sssubhi3, addv2hi3, ssaddv2hi3, subv2hi3, sssubv2hi3,
|
||||
addsubv2hi3, subaddv2hi3, ssaddsubv2hi3, sssubaddv2hi3, sublohiv2hi3,
|
||||
subhilov2hi3, sssublohiv2hi3, sssubhilov2hi3, addlohiv2hi3,
|
||||
addhilov2hi3, ssaddlohiv2hi3, ssaddhilov2hi3, sminv2hi3, smaxv2hi3,
|
||||
flag_mulhi, flag_mulhisi, flag_mulhisi_parts, flag_machi,
|
||||
flag_machi_acconly, flag_macinithi, flag_macinit1hi, mulv2hi3,
|
||||
flag_mulv2hi, flag_mulv2hi_parts, flag_macv2hi_parts,
|
||||
flag_macv2hi_parts_acconly, flag_macinitv2hi_parts,
|
||||
flag_macinit1v2hi_parts, mulhisi_ll, mulhisi_lh, mulhisi_hl,
|
||||
mulhisi_hh, ssnegv2hi2, absv2hi2, ssashiftv2hi3, ssashifthi3,
|
||||
lshiftv2hi3, lshifthi3): Use '%!' to terminate all dsp32/load/store
|
||||
variants instead of ';'.
|
||||
(ror_one, rol_one): Likewise. Make them dsp32 insns.
|
||||
(ashlsi3_insn, ashrsi3, lshrsi3): Add dsp32 variants.
|
||||
(align8, align16, align24): Now named patterns; also using '%!'.
|
||||
(mnop): New insn.
|
||||
|
||||
2006-12-05 Kazu Hirata <kazu@codesourcery.com>
|
||||
|
||||
* config/i386/darwin.h, config/spu/spu.c, tree-ssa-live.c,
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "tm-preds.h"
|
||||
#include "gt-bfin.h"
|
||||
#include "basic-block.h"
|
||||
#include "timevar.h"
|
||||
|
||||
/* A C structure for machine-specific, per-function data.
|
||||
This is added to the cfun structure. */
|
||||
@ -82,6 +83,16 @@ static int arg_regs[] = FUNCTION_ARG_REGISTERS;
|
||||
/* Nonzero if -mshared-library-id was given. */
|
||||
static int bfin_lib_id_given;
|
||||
|
||||
/* Nonzero if -fschedule-insns2 was given. We override it and
|
||||
call the scheduler ourselves during reorg. */
|
||||
static int bfin_flag_schedule_insns2;
|
||||
|
||||
/* Determines whether we run variable tracking in machine dependent
|
||||
reorganization. */
|
||||
static int bfin_flag_var_tracking;
|
||||
|
||||
int splitting_for_sched;
|
||||
|
||||
static void
|
||||
bfin_globalize_label (FILE *stream, const char *name)
|
||||
{
|
||||
@ -97,6 +108,13 @@ output_file_start (void)
|
||||
FILE *file = asm_out_file;
|
||||
int i;
|
||||
|
||||
/* Variable tracking should be run after all optimizations which change order
|
||||
of insns. It also needs a valid CFG. This can't be done in
|
||||
ia64_override_options, because flag_var_tracking is finalized after
|
||||
that. */
|
||||
bfin_flag_var_tracking = flag_var_tracking;
|
||||
flag_var_tracking = 0;
|
||||
|
||||
fprintf (file, ".file \"%s\";\n", input_filename);
|
||||
|
||||
for (i = 0; arg_regs[i] >= 0; i++)
|
||||
@ -1161,7 +1179,18 @@ print_address_operand (FILE *file, rtx x)
|
||||
void
|
||||
print_operand (FILE *file, rtx x, char code)
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (x);
|
||||
enum machine_mode mode;
|
||||
|
||||
if (code == '!')
|
||||
{
|
||||
if (GET_MODE (current_output_insn) == SImode)
|
||||
fprintf (file, " ||");
|
||||
else
|
||||
fprintf (file, ";");
|
||||
return;
|
||||
}
|
||||
|
||||
mode = GET_MODE (x);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
@ -2079,6 +2108,11 @@ override_options (void)
|
||||
|
||||
flag_schedule_insns = 0;
|
||||
|
||||
/* Passes after sched2 can break the helpful TImode annotations that
|
||||
haifa-sched puts on every insn. Just do scheduling in reorg. */
|
||||
bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
|
||||
flag_schedule_insns_after_reload = 0;
|
||||
|
||||
init_machine_status = bfin_init_machine_status;
|
||||
}
|
||||
|
||||
@ -3243,7 +3277,8 @@ bfin_optimize_loop (loop_info loop)
|
||||
}
|
||||
}
|
||||
else if (CALL_P (last_insn)
|
||||
|| get_attr_type (last_insn) == TYPE_SYNC
|
||||
|| (GET_CODE (PATTERN (last_insn)) != SEQUENCE
|
||||
&& get_attr_type (last_insn) == TYPE_SYNC)
|
||||
|| recog_memoized (last_insn) == CODE_FOR_return_internal)
|
||||
{
|
||||
if (dump_file)
|
||||
@ -3254,7 +3289,8 @@ bfin_optimize_loop (loop_info loop)
|
||||
|
||||
if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
|
||||
|| asm_noperands (PATTERN (last_insn)) >= 0
|
||||
|| get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI)
|
||||
|| (GET_CODE (PATTERN (last_insn)) != SEQUENCE
|
||||
&& get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI))
|
||||
{
|
||||
nop_insn = emit_insn_after (gen_nop (), last_insn);
|
||||
last_insn = nop_insn;
|
||||
@ -3602,9 +3638,184 @@ bfin_reorg_loops (FILE *dump_file)
|
||||
|
||||
if (dump_file)
|
||||
print_rtl (dump_file, get_insns ());
|
||||
|
||||
FOR_EACH_BB (bb)
|
||||
bb->aux = NULL;
|
||||
}
|
||||
|
||||
/* Possibly generate a SEQUENCE out of three insns found in SLOT.
|
||||
Returns true if we modified the insn chain, false otherwise. */
|
||||
static bool
|
||||
gen_one_bundle (rtx slot[3])
|
||||
{
|
||||
rtx bundle;
|
||||
|
||||
gcc_assert (slot[1] != NULL_RTX);
|
||||
|
||||
/* Verify that we really can do the multi-issue. */
|
||||
if (slot[0])
|
||||
{
|
||||
rtx t = NEXT_INSN (slot[0]);
|
||||
while (t != slot[1])
|
||||
{
|
||||
if (GET_CODE (t) != NOTE
|
||||
|| NOTE_LINE_NUMBER (t) != NOTE_INSN_DELETED)
|
||||
return false;
|
||||
t = NEXT_INSN (t);
|
||||
}
|
||||
}
|
||||
if (slot[2])
|
||||
{
|
||||
rtx t = NEXT_INSN (slot[1]);
|
||||
while (t != slot[2])
|
||||
{
|
||||
if (GET_CODE (t) != NOTE
|
||||
|| NOTE_LINE_NUMBER (t) != NOTE_INSN_DELETED)
|
||||
return false;
|
||||
t = NEXT_INSN (t);
|
||||
}
|
||||
}
|
||||
|
||||
if (slot[0] == NULL_RTX)
|
||||
slot[0] = emit_insn_before (gen_mnop (), slot[1]);
|
||||
if (slot[2] == NULL_RTX)
|
||||
slot[2] = emit_insn_after (gen_nop (), slot[1]);
|
||||
|
||||
/* Avoid line number information being printed inside one bundle. */
|
||||
if (INSN_LOCATOR (slot[1])
|
||||
&& INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
|
||||
INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
|
||||
if (INSN_LOCATOR (slot[2])
|
||||
&& INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
|
||||
INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
|
||||
|
||||
/* Terminate them with "|| " instead of ";" in the output. */
|
||||
PUT_MODE (slot[0], SImode);
|
||||
PUT_MODE (slot[1], SImode);
|
||||
|
||||
/* This is a cheat to avoid emit_insn's special handling of SEQUENCEs.
|
||||
Generating a PARALLEL first and changing its code later is the
|
||||
easiest way to emit a SEQUENCE insn. */
|
||||
bundle = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (3, slot[0], slot[1], slot[2]));
|
||||
emit_insn_before (bundle, slot[0]);
|
||||
remove_insn (slot[0]);
|
||||
remove_insn (slot[1]);
|
||||
remove_insn (slot[2]);
|
||||
PUT_CODE (bundle, SEQUENCE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Go through all insns, and use the information generated during scheduling
|
||||
to generate SEQUENCEs to represent bundles of instructions issued
|
||||
simultaneously. */
|
||||
|
||||
static void
|
||||
bfin_gen_bundles (void)
|
||||
{
|
||||
basic_block bb;
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
rtx insn, next;
|
||||
rtx slot[3];
|
||||
int n_filled = 0;
|
||||
|
||||
slot[0] = slot[1] = slot[2] = NULL_RTX;
|
||||
for (insn = BB_HEAD (bb);; insn = next)
|
||||
{
|
||||
int at_end;
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
if (get_attr_type (insn) == TYPE_DSP32)
|
||||
slot[0] = insn;
|
||||
else if (slot[1] == NULL_RTX)
|
||||
slot[1] = insn;
|
||||
else
|
||||
slot[2] = insn;
|
||||
n_filled++;
|
||||
}
|
||||
|
||||
next = NEXT_INSN (insn);
|
||||
while (next && insn != BB_END (bb)
|
||||
&& !(INSN_P (next)
|
||||
&& GET_CODE (PATTERN (next)) != USE
|
||||
&& GET_CODE (PATTERN (next)) != CLOBBER))
|
||||
{
|
||||
insn = next;
|
||||
next = NEXT_INSN (insn);
|
||||
}
|
||||
|
||||
/* BB_END can change due to emitting extra NOPs, so check here. */
|
||||
at_end = insn == BB_END (bb);
|
||||
if (at_end || GET_MODE (next) == TImode)
|
||||
{
|
||||
if ((n_filled < 2
|
||||
|| !gen_one_bundle (slot))
|
||||
&& slot[0] != NULL_RTX)
|
||||
{
|
||||
rtx pat = PATTERN (slot[0]);
|
||||
if (GET_CODE (pat) == SET
|
||||
&& GET_CODE (SET_SRC (pat)) == UNSPEC
|
||||
&& XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
|
||||
{
|
||||
SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
|
||||
INSN_CODE (slot[0]) = -1;
|
||||
}
|
||||
}
|
||||
n_filled = 0;
|
||||
slot[0] = slot[1] = slot[2] = NULL_RTX;
|
||||
}
|
||||
if (at_end)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return an insn type for INSN that can be used by the caller for anomaly
|
||||
workarounds. This differs from plain get_attr_type in that it handles
|
||||
SEQUENCEs. */
|
||||
|
||||
static enum attr_type
|
||||
type_for_anomaly (rtx insn)
|
||||
{
|
||||
rtx pat = PATTERN (insn);
|
||||
if (GET_CODE (pat) == SEQUENCE)
|
||||
{
|
||||
enum attr_type t;
|
||||
t = get_attr_type (XVECEXP (pat, 0, 1));
|
||||
if (t == TYPE_MCLD)
|
||||
return t;
|
||||
t = get_attr_type (XVECEXP (pat, 0, 2));
|
||||
if (t == TYPE_MCLD)
|
||||
return t;
|
||||
return TYPE_MCST;
|
||||
}
|
||||
else
|
||||
return get_attr_type (insn);
|
||||
}
|
||||
|
||||
/* Return nonzero if INSN contains any loads that may trap. It handles
|
||||
SEQUENCEs correctly. */
|
||||
|
||||
static bool
|
||||
trapping_loads_p (rtx insn)
|
||||
{
|
||||
rtx pat = PATTERN (insn);
|
||||
if (GET_CODE (pat) == SEQUENCE)
|
||||
{
|
||||
enum attr_type t;
|
||||
t = get_attr_type (XVECEXP (pat, 0, 1));
|
||||
if (t == TYPE_MCLD && may_trap_p (SET_SRC (XVECEXP (pat, 0, 1))))
|
||||
return true;
|
||||
t = get_attr_type (XVECEXP (pat, 0, 2));
|
||||
if (t == TYPE_MCLD && may_trap_p (SET_SRC (XVECEXP (pat, 0, 2))))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return may_trap_p (SET_SRC (single_set (insn)));
|
||||
}
|
||||
|
||||
/* We use the machine specific reorg pass for emitting CSYNC instructions
|
||||
after conditional branches as needed.
|
||||
|
||||
@ -3631,6 +3842,27 @@ bfin_reorg (void)
|
||||
rtx insn, last_condjump = NULL_RTX;
|
||||
int cycles_since_jump = INT_MAX;
|
||||
|
||||
/* We are freeing block_for_insn in the toplev to keep compatibility
|
||||
with old MDEP_REORGS that are not CFG based. Recompute it now. */
|
||||
compute_bb_for_insn ();
|
||||
|
||||
if (bfin_flag_schedule_insns2)
|
||||
{
|
||||
splitting_for_sched = 1;
|
||||
split_all_insns (0);
|
||||
splitting_for_sched = 0;
|
||||
|
||||
update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
|
||||
|
||||
timevar_push (TV_SCHED2);
|
||||
schedule_insns ();
|
||||
timevar_pop (TV_SCHED2);
|
||||
|
||||
/* Examine the schedule and insert nops as necessary for 64 bit parallel
|
||||
instructions. */
|
||||
bfin_gen_bundles ();
|
||||
}
|
||||
|
||||
/* Doloop optimization */
|
||||
if (cfun->machine->has_hardware_loops)
|
||||
bfin_reorg_loops (dump_file);
|
||||
@ -3666,15 +3898,14 @@ bfin_reorg (void)
|
||||
}
|
||||
else if (INSN_P (insn))
|
||||
{
|
||||
enum attr_type type = get_attr_type (insn);
|
||||
enum attr_type type = type_for_anomaly (insn);
|
||||
int delay_needed = 0;
|
||||
if (cycles_since_jump < INT_MAX)
|
||||
cycles_since_jump++;
|
||||
|
||||
if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
|
||||
{
|
||||
rtx pat = single_set (insn);
|
||||
if (may_trap_p (SET_SRC (pat)))
|
||||
if (trapping_loads_p (insn))
|
||||
delay_needed = 3;
|
||||
}
|
||||
else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
|
||||
@ -3736,7 +3967,7 @@ bfin_reorg (void)
|
||||
|
||||
if (INSN_P (target))
|
||||
{
|
||||
enum attr_type type = get_attr_type (target);
|
||||
enum attr_type type = type_for_anomaly (target);
|
||||
int delay_needed = 0;
|
||||
if (cycles_since_jump < INT_MAX)
|
||||
cycles_since_jump++;
|
||||
@ -3774,6 +4005,13 @@ bfin_reorg (void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bfin_flag_var_tracking)
|
||||
{
|
||||
timevar_push (TV_VAR_TRACKING);
|
||||
variable_tracking_main ();
|
||||
timevar_pop (TV_VAR_TRACKING);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle interrupt_handler, exception_handler and nmi_handler function
|
||||
|
@ -1233,4 +1233,8 @@ extern struct rtx_def *bfin_cc_rtx, *bfin_rets_rtx;
|
||||
|
||||
#define SIZE_ASM_OP "\t.size\t"
|
||||
|
||||
extern int splitting_for_sched;
|
||||
|
||||
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) ((CHAR) == '!')
|
||||
|
||||
#endif /* _BFIN_CONFIG */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1390,6 +1390,11 @@ note_uses (rtx *pbody, void (*fun) (rtx *, void *), void *data)
|
||||
note_uses (&XVECEXP (body, 0, i), fun, data);
|
||||
return;
|
||||
|
||||
case SEQUENCE:
|
||||
for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
|
||||
note_uses (&PATTERN (XVECEXP (body, 0, i)), fun, data);
|
||||
return;
|
||||
|
||||
case USE:
|
||||
(*fun) (&XEXP (body, 0), data);
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user