diff mbox

RFA: Fix PR rtl-optimization/60651

Message ID CAMqJFCqLHS3Mmm7bCsToJHemS6ikKqyC_crxQcV7PJK+ytotSQ@mail.gmail.com
State New
Headers show

Commit Message

Joern Rennecke April 2, 2014, 3:57 p.m. UTC
On 28 March 2014 10:20, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> However, the first call is for blocks with incoming abnormal edges.
>> If these are empty, the change as I wrote it yesterday is fine, but not
>> when they are non-empty; in that case, we should indeed insert before the
>> first instruction in that block.
>
> OK, so the issue is specific to empty basic blocks and boils down to inserting
> instructions in a FIFO manner into them.

Actually, the issue also applies to abnormal edges where lcm did leave a set -
but these are rare, and my last patch should handle these properly in any event,
by no longer using the NOTE_INSN_BASIC_BLOCK itself unless the block is
empty.

>> This can be archived by finding an insert-before position using NEXT_INSN
>> on the basic block head; this amounts to the very same insertion place
>> as inserting after the basic block head.  Also, we will continue to set no
>> location, and use the same bb, because both add_insn_before and
>> add_insn_after (in contradiction to its block comment) will infer the basic
>> block from the insn given (in the case for add_insn_before, I assume
>> that the basic block doesn't start with a BARRIER - that would be invalid -
>> and that the insn it starts with has a valid BLOCK_FOR_INSN setting the
>> same way the basic block head has.
>
> This looks reasonable, but I think that we need more commentary because it's
> not straightforward to understand, so I would:
>
>   1. explicitly state that we enforce an order on the entities in addition to
> the order on priority, both in the code (for example create a 4th paragraph in
> the comment at the top of the file, before "More details ...") and in the doc
> as you already did, but "ordering" the two orders for the sake of clarity:
> first the order on priority then, for the same priority, the order to the
> entities.

Actually, all the patch provides is a partial order, just as I stated.
Providing the strict order you describe would require adding another
loop nesting to the entity/basic block/seginfo loop, and it wouldn't
really be useful for targets.
To order by entity first, then by priority, could be useful for some targets,
so that they can express a dependency chain of mode switching events
to be computed in a single lcm pass without inflating the mode count
(which determines how often we have to invoke the lcm machinery).
However, that would require having separate buckets for each entity for
each  insert_insn_on_edge point.

For epiphany,  EPIPHANY_MSW_ENTITY_FPU_OMNIBUS (for -O0) and
EPIPHANY_MSW_ENTITY_ROUND_KNOWN (used when optimizing)
depend on EPIPHANY_MSW_ENTITY_AND,  EPIPHANY_MSW_ENTITY_OR and
EPIPHANY_MSW_ENTITY_CONFIG.
The latter three only have two modes, an the former two use the
enum attr_fp_mode values, the first of which is FP_MODE_ROUND_UNKNOWN.
That value does not actually appear as a needed mode for these entities, hence
the partial order is sufficient.

EPIPHANY_MSW_ENTITY_FPU_OMNIBUS also depends on EPIPHANY_MSW_ENTITY_OR.

>   2. add a line in the head comment of new_seginfo saying that INSN may not be
> a NOTE_BASIC_BLOCK, unless BB is empty.
>
>   3. add a comment above the trick in optimize_mode_switching saying that it
> is both required to implement the FIFO insertion and valid because we know
> that the basic block was initially empty.

Done.

> It's not clear to me whether this is a regression or not, so you'll also need
> to run it by the RMs.

I don't think it's a regression.
2014-04-02  Joern Rennecke  <joern.rennecke@embecosm.com>

gcc:
	PR rtl-optimization/60651
	* mode-switching.c (optimize_mode_switching): Make sure to emit
	sets of a lower numbered entity before sets of a higher numbered
	entity to a mode of the same or lower priority.
	(new_seginfo): Document and enforce requirement that
	NOTE_INSN_BASIC_BLOCK only appears for empty blocks.
	* doc/tm.texi.in: Document ordering constraint for emitted mode sets.
	* doc/tm.texi: Regenerate.
gcc/testsuite:
	PR rtl-optimization/60651
	* gcc.target/epiphany/mode-switch.c: New test.

Comments

Joern Rennecke April 2, 2014, 4:34 p.m. UTC | #1
Hmm, the sanity check in new_seginfo caused a boostrap failure
building libjava on x86.
There was a block with CODE_LABEL as basic block head, otherwise empty.
diff mbox

Patch

diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index f7024a7..b8ca17e 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -9778,6 +9778,8 @@  for @var{entity}.  For any fixed @var{entity}, @code{mode_priority_to_mode}
 Generate one or more insns to set @var{entity} to @var{mode}.
 @var{hard_reg_live} is the set of hard registers live at the point where
 the insn(s) are to be inserted.
+Sets of a lower numbered entity will be emitted before sets of a higher
+numbered entity to a mode of the same or lower priority.
 @end defmac
 
 @node Target Attributes
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 6dcbde4..d793d26 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7447,6 +7447,8 @@  for @var{entity}.  For any fixed @var{entity}, @code{mode_priority_to_mode}
 Generate one or more insns to set @var{entity} to @var{mode}.
 @var{hard_reg_live} is the set of hard registers live at the point where
 the insn(s) are to be inserted.
+Sets of a lower numbered entity will be emitted before sets of a higher
+numbered entity to a mode of the same or lower priority.
 @end defmac
 
 @node Target Attributes
diff --git a/gcc/mode-switching.c b/gcc/mode-switching.c
index 88543b2..bafe934 100644
--- a/gcc/mode-switching.c
+++ b/gcc/mode-switching.c
@@ -96,12 +96,18 @@  static void make_preds_opaque (basic_block, int);
 
 
 /* This function will allocate a new BBINFO structure, initialized
-   with the MODE, INSN, and basic block BB parameters.  */
+   with the MODE, INSN, and basic block BB parameters.
+   INSN may not be a NOTE_INSN_BASIC_BLOCK, unless it is en empty
+   basic block; that allows us later to insert instructions in a FIFO-like
+   manner.  */
 
 static struct seginfo *
 new_seginfo (int mode, rtx insn, int bb, HARD_REG_SET regs_live)
 {
   struct seginfo *ptr;
+
+  gcc_assert (!NOTE_INSN_BASIC_BLOCK_P (insn)
+	      || insn == BB_END (NOTE_BASIC_BLOCK (insn)));
   ptr = XNEW (struct seginfo);
   ptr->mode = mode;
   ptr->insn_ptr = insn;
@@ -534,7 +540,10 @@  optimize_mode_switching (void)
 		break;
 	    if (e)
 	      {
-		ptr = new_seginfo (no_mode, BB_HEAD (bb), bb->index, live_now);
+		ptr = new_seginfo (no_mode,
+				   (BB_HEAD (bb) == BB_END (bb)
+				    ? BB_HEAD (bb) : NEXT_INSN (BB_HEAD (bb))),
+				   bb->index, live_now);
 		add_seginfo (info + bb->index, ptr);
 		bitmap_clear_bit (transp[bb->index], j);
 	      }
@@ -733,7 +742,15 @@  optimize_mode_switching (void)
 		    {
 		      emitted = true;
 		      if (NOTE_INSN_BASIC_BLOCK_P (ptr->insn_ptr))
-			emit_insn_after (mode_set, ptr->insn_ptr);
+			/* We need to emit the insns in a FIFO-like manner,
+			   i.e. the first to be emitted at our insertion
+			   point ends up first in the instruction steam.
+			   Because we made sure that NOTE_INSN_BASIC_BLOCK is
+			   only used for initially empty basic blocks, we
+			   can archive this by appending at the end of
+			   the block.  */
+			emit_insn_after
+			  (mode_set, BB_END (NOTE_BASIC_BLOCK (ptr->insn_ptr)));
 		      else
 			emit_insn_before (mode_set, ptr->insn_ptr);
 		    }
--- /dev/null	2014-03-19 18:18:19.244212660 +0000
+++ b/gcc/testsuite/gcc.target/epiphany/mode-switch.c	2014-03-25 13:31:41.186140611 +0000
@@ -0,0 +1,12 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "#-917506" } } */
+/* PR 60651 */
+
+int a;
+int c;
+
+void __attribute__((interrupt))
+misc_handler (void) {
+   a*= c;
+}