This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: MN10300: Add redundant comparison elimination pass


Hi Guys,

  As Richard pointed out my previous patch (for LIW/SETLB) included a
  separate feature which should have been submitted on its own.  So here
  it is - a machine reorg pass to eliminate redundant compares.

  The scan could be improved to look further back through the
  instruction stream for insns that set the EPSW register, but I am
  leaving that for a future patch.

  Tested without regressions on an mn10300-elf toolchain.

  OK to apply ?

Cheers
  Nick

gcc/ChangeLog
2010-11-10  Nick Clifton  <nickc@redhat.com>

	* config/mn10300/mn10300.c (scan_for_redundant_compares): New
	function.
	(mn10300_reorg): New function.
	(TARGET_MACHINE_DEPENDENT_REORG): Define.


Index: gcc/config/mn10300/mn10300.c
===================================================================
--- gcc/config/mn10300/mn10300.c	(revision 166474)
+++ gcc/config/mn10300/mn10300.c	(working copy)
@@ -2403,6 +2403,128 @@
   /* Extract the latency value from the timings attribute.  */
   return timings < 100 ? (timings % 10) : (timings % 100);
 }
+
+static void
+scan_for_redundant_compares (void)
+{
+  rtx cur_insn;
+
+  /* Look for this sequence:
+
+       (set (reg X)  (arith_op (...)))
+       (set (reg CC) (compare (reg X) (const_int 0)))
+       (set (pc)     (if_then_else (EQ|NE (...)) (...) (...)))
+
+     And remove the compare as the flags in the
+     EPSW register will already be correctly set.  */
+  for (cur_insn = get_insns (); cur_insn != NULL; cur_insn = NEXT_INSN (cur_insn))
+    {
+      rtx pattern;
+
+      if (! INSN_P (cur_insn))
+	continue;
+
+      pattern = PATTERN (cur_insn);
+
+      if (GET_CODE (pattern) == SET
+	  && GET_CODE (SET_SRC (pattern)) == COMPARE
+	  /* Paranoia checks:  */
+	  && REG_P (SET_DEST (pattern))
+	  && REGNO (SET_DEST (pattern)) == CC_REG
+	  && REG_P (XEXP (SET_SRC (pattern), 0))
+	  /* Normal checks:  */
+	  && CONST_INT_P (XEXP (SET_SRC (pattern), 1))
+	  && INTVAL (XEXP (SET_SRC (pattern), 1)) == 0)
+	{
+	  rtx prev_insn, branch, condition;
+	  unsigned int compare_reg;
+
+	  /* FIXME: We should scan backwards until the first ESPW
+	     setter or clobber insn is found (or the beginning of
+	     the block).  At the moment we just look back one insn.  */
+	  prev_insn = prev_nonnote_insn (cur_insn);
+
+	  if (prev_insn == NULL || ! INSN_P (prev_insn))
+	    continue;
+
+	  /* An UNSPEC might be an LIW insn which will not set the
+	     condition code flags in a way that we currently expect.  */
+	  if (GET_CODE (PATTERN (prev_insn)) == UNSPEC)
+	    continue;
+
+	  if (GET_CODE (PATTERN (prev_insn)) != PARALLEL
+	      || XVECLEN (PATTERN (prev_insn), 0) != 2
+	      || GET_CODE (XVECEXP (PATTERN (prev_insn), 0, 0)) != SET)
+	    continue;
+
+	  compare_reg = REGNO (XEXP (SET_SRC (pattern), 0));
+	  pattern = XVECEXP (PATTERN (prev_insn), 0, 0);
+
+	  if (! REG_P (SET_DEST (pattern))
+	      || REGNO (SET_DEST (pattern)) != compare_reg)
+	    continue;
+
+	  branch = next_nonnote_insn (cur_insn);
+	  if (branch == NULL || ! JUMP_P (branch)
+	      || GET_CODE (PATTERN (branch)) != SET
+	      || GET_CODE (SET_SRC (PATTERN (branch))) != IF_THEN_ELSE)
+	    continue;
+	  condition = XEXP (SET_SRC (PATTERN (branch)), 0);
+
+	  switch (GET_CODE (condition))
+	    {
+	    case EQ:
+	    case NE:
+	      break;
+	    default:
+	      continue;
+	    }
+
+	  /* Adding 1 or 4 to an address register results in an
+	     INC/INC4 instruction that doesn't set the flags.  */
+	  if (GET_CODE (SET_SRC (pattern)) == PLUS
+	      && REG_P (SET_DEST (pattern))
+	      && REGNO (SET_DEST (pattern)) >= FIRST_ADDRESS_REGNUM
+	      && REGNO (SET_DEST (pattern)) <= LAST_ADDRESS_REGNUM
+	      && REG_P (XEXP (SET_SRC (pattern), 0))
+	      && REGNO (XEXP (SET_SRC (pattern), 0)) == REGNO (SET_DEST (pattern))
+	      && CONST_INT_P (XEXP (SET_SRC (pattern), 1))
+	      && (INTVAL (XEXP (SET_SRC (pattern), 1)) == 1
+		  || INTVAL (XEXP (SET_SRC (pattern), 1)) == 4))
+	    continue;
+
+	  switch (GET_CODE (SET_SRC (pattern)))
+	    {
+	    case PLUS:
+	    case MINUS:
+	    case MULT:
+#if 0
+	      /* Some alternatives in the AND pattern use EXTBU which does
+		 not set the flags.  Hence a CMP following an AND might be
+		 needed.  */
+	    case AND:
+#endif
+	    case XOR:
+	    case NOT:
+	    case ASHIFT:
+	    case LSHIFTRT:
+	    case ASHIFTRT:
+	      delete_insn (cur_insn);
+	      break;
+	    default:
+	      break;
+	    }
+	}
+    }
+}
+
+/* Implements TARGET_MACHINE_DEPENDENT_REORG.  */
+
+static void
+mn10300_reorg (void)
+{
+  scan_for_redundant_compares ();
+}
 
 /* Initialize the GCC target structure.  */
 
@@ -2481,4 +2603,7 @@
 #undef  TARGET_SCHED_ADJUST_COST
 #define TARGET_SCHED_ADJUST_COST mn10300_adjust_sched_cost
 
+#undef  TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG mn10300_reorg
+
 struct gcc_target targetm = TARGET_INITIALIZER;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]