RFA: Try to attach REG_EQUAL notes to split insns

Richard Sandiford rdsandiford@googlemail.com
Fri Aug 29 22:05:00 GMT 2008


In MIPS n64 code, it takes 5 instructions to load (high (symbol_ref FOO)).
We therefore split SETs of such constants after reload.  Unfortunately,
the split sequence makes no mention of the original unsplit constant,
and it's quite hard to piece it back together.

I'd therefore like to make split_insn attach a REG_EQUAL note to the
last instruction in a split sequence if:

  - the original insn was known to be a SET of a constant,
    or equivalent to such a SET.

  - the last instruction in the split sequence sets the same
    thing as the original insn did.

Current code doesn't take much advantage of this.  The idea is usually
to keep things whole while the combined effect is useful, then split
it once the combined effect matters less.  FWIW, I compared -O2 and -Os
testsuite output for:

    arm-eabi
    cris-elf
    mipsisa64-elfoabi
    mipsisa64-elf
    powerpc-linux-gnu
    s390-linux-gnu
    sh-elf
    sparc-sun-solaris2.8
    x86_64-linux-gnu

and saw no code differences.

However, I have an md_reorg patch that works around R10K hardware errata.
It's the kind of workaround that only makes sense in md_reorg, at the
very end of compilation.  The workarounds benefit greatly from such
a REG_EQUAL note (and the patch in question comes with tests that fail
without the note).

Tested on mips64-linux-gnu and x86_64-linux-gnu.  OK to install?

Richard


	* recog.c (split_insn): Consider attaching a REG_EQUAL note to the
	final insn of a split.

Index: gcc/recog.c
===================================================================
--- gcc/recog.c	2008-08-09 10:14:53.000000000 +0100
+++ gcc/recog.c	2008-08-27 19:38:31.000000000 +0100
@@ -2630,10 +2630,29 @@ split_insn (rtx insn)
   /* Split insns here to get max fine-grain parallelism.  */
   rtx first = PREV_INSN (insn);
   rtx last = try_split (PATTERN (insn), insn, 1);
+  rtx insn_set, last_set, note;
 
   if (last == insn)
     return NULL_RTX;
 
+  /* If the original instruction was a single set that was known to be
+     equivalent to a constant, see if we can say the same about the last
+     instruction in the split sequence.  The two instructions must set
+     the same destination.  */
+  insn_set = single_set (insn);
+  if (insn_set)
+    {
+      last_set = single_set (last);
+      if (last_set && rtx_equal_p (SET_DEST (last_set), SET_DEST (insn_set)))
+	{
+	  note = find_reg_equal_equiv_note (insn);
+	  if (note && CONSTANT_P (XEXP (note, 0)))
+	    set_unique_reg_note (last, REG_EQUAL, XEXP (note, 0));
+	  else if (CONSTANT_P (SET_SRC (insn_set)))
+	    set_unique_reg_note (last, REG_EQUAL, SET_SRC (insn_set));
+	}
+    }
+
   /* try_split returns the NOTE that INSN became.  */
   SET_INSN_DELETED (insn);
 
@@ -2651,6 +2670,7 @@ split_insn (rtx insn)
 	  first = NEXT_INSN (first);
 	}
     }
+
   return last;
 }
 



More information about the Gcc-patches mailing list