Commit dcfe3c8f by Simon Dardis Committed by Simon Dardis

Undo delay slot filling and use compact branches in selected cases.

gcc/
	* config/mips/mips.c (mips_breakable_sequence_p): New function.
	(mips_break_sequence): New function. 
	(mips_reorg_process_insns) Use them. Use compact branches in selected
          situations.
    
gcc/testsuite/
        * gcc.target/mips/split-ds-sequence.c: New test.

From-SVN: r230160
parent c08de514
2015-11-11 Simon Dardis <simon.dardis@imgtec.com>
* config/mips/mips.c (mips_breakable_sequence_p): New function.
(mips_break_sequence): New function.
(mips_reorg_process_insns): Use them. Use compact branches in selected
situations.
2015-11-11 Alan Lawrence <alan.lawrence@arm.com>
* fold-const.c (get_array_ctor_element_at_index): Fix whitespace, typo.
......@@ -16824,6 +16824,34 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay,
}
}
/* A SEQUENCE is breakable iff the branch inside it has a compact form
and the target has compact branches. */
static bool
mips_breakable_sequence_p (rtx_insn *insn)
{
return (insn && GET_CODE (PATTERN (insn)) == SEQUENCE
&& TARGET_CB_MAYBE
&& get_attr_compact_form (SEQ_BEGIN (insn)) != COMPACT_FORM_NEVER);
}
/* Remove a SEQUENCE and replace it with the delay slot instruction
followed by the branch and return the instruction in the delay slot.
Return the first of the two new instructions.
Subroutine of mips_reorg_process_insns. */
static rtx_insn *
mips_break_sequence (rtx_insn *insn)
{
rtx_insn *before = PREV_INSN (insn);
rtx_insn *branch = SEQ_BEGIN (insn);
rtx_insn *ds = SEQ_END (insn);
remove_insn (insn);
add_insn_after (ds, before, NULL);
add_insn_after (branch, ds, NULL);
return ds;
}
/* Go through the instruction stream and insert nops where necessary.
Also delete any high-part relocations whose partnering low parts
are now all dead. See if the whole function can then be put into
......@@ -16916,6 +16944,68 @@ mips_reorg_process_insns (void)
{
if (GET_CODE (PATTERN (insn)) == SEQUENCE)
{
rtx_insn *next_active = next_active_insn (insn);
/* Undo delay slots to avoid bubbles if the next instruction can
be placed in a forbidden slot or the cost of adding an
explicit NOP in a forbidden slot is OK and if the SEQUENCE is
safely breakable. */
if (TARGET_CB_MAYBE
&& mips_breakable_sequence_p (insn)
&& INSN_P (SEQ_BEGIN (insn))
&& INSN_P (SEQ_END (insn))
&& ((next_active
&& INSN_P (next_active)
&& GET_CODE (PATTERN (next_active)) != SEQUENCE
&& get_attr_can_delay (next_active) == CAN_DELAY_YES)
|| !optimize_size))
{
/* To hide a potential pipeline bubble, if we scan backwards
from the current SEQUENCE and find that there is a load
of a value that is used in the CTI and there are no
dependencies between the CTI and instruction in the delay
slot, break the sequence so the load delay is hidden. */
HARD_REG_SET uses;
CLEAR_HARD_REG_SET (uses);
note_uses (&PATTERN (SEQ_BEGIN (insn)), record_hard_reg_uses,
&uses);
HARD_REG_SET delay_sets;
CLEAR_HARD_REG_SET (delay_sets);
note_stores (PATTERN (SEQ_END (insn)), record_hard_reg_sets,
&delay_sets);
rtx_insn *prev = prev_active_insn (insn);
if (prev
&& GET_CODE (PATTERN (prev)) == SET
&& MEM_P (SET_SRC (PATTERN (prev))))
{
HARD_REG_SET sets;
CLEAR_HARD_REG_SET (sets);
note_stores (PATTERN (prev), record_hard_reg_sets,
&sets);
/* Re-order if safe. */
if (!hard_reg_set_intersect_p (delay_sets, uses)
&& hard_reg_set_intersect_p (uses, sets))
{
next_insn = mips_break_sequence (insn);
/* Need to process the hazards of the newly
introduced instructions. */
continue;
}
}
/* If we find an orphaned high-part relocation in a delay
slot then we can convert to a compact branch and get
the orphaned high part deleted. */
if (mips_orphaned_high_part_p (&htab, SEQ_END (insn)))
{
next_insn = mips_break_sequence (insn);
/* Need to process the hazards of the newly
introduced instructions. */
continue;
}
}
/* If we find an orphaned high-part relocation in a delay
slot, it's easier to turn that instruction into a NOP than
to delete it. The delay slot will be a NOP either way. */
......@@ -16950,6 +17040,33 @@ mips_reorg_process_insns (void)
{
mips_avoid_hazard (last_insn, insn, &hilo_delay,
&delayed_reg, lo_reg, &fs_delay);
/* When a compact branch introduces a forbidden slot hazard
and the next useful instruction is a SEQUENCE of a jump
and a non-nop instruction in the delay slot, remove the
sequence and replace it with the delay slot instruction
then the jump to clear the forbidden slot hazard. */
if (fs_delay)
{
/* Search onwards from the current position looking for
a SEQUENCE. We are looking for pipeline hazards here
and do not need to worry about labels or barriers as
the optimization only undoes delay slot filling which
only affects the order of the branch and its delay
slot. */
rtx_insn *next = next_active_insn (insn);
if (next
&& USEFUL_INSN_P (next)
&& GET_CODE (PATTERN (next)) == SEQUENCE
&& mips_breakable_sequence_p (next))
{
last_insn = insn;
next_insn = mips_break_sequence (next);
/* Need to process the hazards of the newly
introduced instructions. */
continue;
}
}
last_insn = insn;
}
}
......
2015-11-11 Simon Dardis <simon.dardis@imgtec.com>
* gcc.target/mips/split-ds-sequence.c: New test.
2015-11-11 Julia Koval <julia.koval@intel.com>
* g++.dg/ext/mv16.C: New functions.
......
/* { dg-options "isa_rev>=6" } */
/* { dg-skip-if "code quality test" { *-*-* } { "-mcompact-branches=never" } { "" } } */
/* { dg-final { scan-assembler-not "nop" } } */
int
testg2 (int a, int c)
{
int j = 0;
do
{
j += a;
}
while (j < 56);
j += c;
return j;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment