This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[committed] canonicalize LE comparisons
- From: Eric Christopher <echristo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Richard Sandiford <richard at codesourcery dot com>
- Date: Wed, 13 Jul 2005 11:32:59 -0700
- Subject: [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);