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]

[committed] canonicalize LE comparisons


The mips port only has LT comparisons for integer compares, and the
range of integer compare is limited in the immediate range. This tries
to canonicalize and force into registers LE and LEU compares if we can
do so safely.

It allows us to generate much smaller code for this:

int foo (unsigned int a) { return a < 0xfff0; }

and similar testcases:

li reg, constant
jr $31
sltu reg, reg, constant

isntead of inverting the result. Saves an instruction :)

Tested on mips-elf, mipsisa64-elf. No regressions. Committed to
mainline.

2005-07-13  Eric Christopher  <echristo@redhat.com>

        * config/mips/mips.c (mips_canonicalize_comparison): New.
        (mips_emit_int_relational): Use.


-eric


Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.514
diff -u -p -w -r1.514 mips.c
--- config/mips/mips.c	12 Jul 2005 03:48:16 -0000	1.514
+++ config/mips/mips.c	13 Jul 2005 05:27:19 -0000
@@ -2881,6 +2881,50 @@ mips_relational_operand_ok_p (enum rtx_c
     }
 }
 
+/* Canonicalize LE or LEU comparisons into LT comparisons when
+   possible to avoid extra instructions or inverting the
+   comparison.  */
+
+static bool
+mips_canonicalize_comparison (enum rtx_code *code, rtx *cmp1, 
+			      enum machine_mode mode)
+{
+  HOST_WIDE_INT original, plus_one;
+
+  if (GET_CODE (*cmp1) != CONST_INT)
+    return false;
+  
+  original = INTVAL (*cmp1);
+  plus_one = trunc_int_for_mode (original + 1, mode);
+  
+  switch (*code)
+    {
+    case LE:
+      if (original < plus_one)
+	{
+	  *code = LT;
+	  *cmp1 = GEN_INT (plus_one);
+	  return true;
+	}
+      break;
+      
+    case LEU:
+      if (plus_one != 0)
+	{
+	  *code = LTU;
+	  *cmp1 = GEN_INT (plus_one);
+	  return true;
+	}
+      break;
+      
+    default:
+      return false;
+   }
+  
+  return false;
+
+}
+
 /* Compare CMP0 and CMP1 using relational operator CODE and store the
    result in TARGET.  CMP0 and TARGET are register_operands that have
    the same integer mode.  If INVERT_PTR is nonnull, it's OK to set
@@ -2891,11 +2935,15 @@ mips_emit_int_relational (enum rtx_code 
 			  rtx target, rtx cmp0, rtx cmp1)
 {
   /* First see if there is a MIPS instruction that can do this operation
-     with CMP1 in its current form.  If not, try doing the same for the
+     with CMP1 in its current form. If not, try to canonicalize the
+     comparison to LT. If that fails, try doing the same for the
      inverse operation.  If that also fails, force CMP1 into a register
      and try again.  */
   if (mips_relational_operand_ok_p (code, cmp1))
     mips_emit_binary (code, target, cmp0, cmp1);
+  else if (mips_canonicalize_comparison (&code, &cmp1, GET_MODE (target))
+	   && mips_relational_operand_ok_p (code, cmp1))
+    mips_emit_binary (code, target, cmp0, cmp1);
   else
     {
       enum rtx_code inv_code = reverse_condition (code);

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