This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[MIPS 20/30] Improve handling of GT and GTU
- From: Richard Sandiford <rsandifo at nildram dot co dot uk>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 19 Oct 2007 10:17:48 +0100
- Subject: [MIPS 20/30] Improve handling of GT and GTU
- References: <87przc9wms.fsf@firetop.home>
[Last of these patches for today]
We can implement LE and LEU of most 16-bit CONST_INTs by adding
one to the constant and using LT and LTU. We were missing the
same transformation when inverting a GT or GTU.
Richard
gcc/
* config/mips/mips.c (mips_canonicalize_comparison): Check
mips_relational_operand_ok_p before trying to rewrite the test.
Only calculate PLUS_ONE if needed.
(mips_emit_int_relational): Don't call mips_relational_operand_ok_p
here.
Index: gcc/config/mips/mips.c
===================================================================
*** gcc/config/mips/mips.c 2007-10-18 11:07:13.000000000 +0100
--- gcc/config/mips/mips.c 2007-10-18 11:07:13.000000000 +0100
*************** mips_relational_operand_ok_p (enum rtx_c
*** 3742,3781 ****
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 ((unsigned HOST_WIDE_INT) original + 1, mode);
!
! switch (*code)
! {
! case LE:
! if (original < plus_one)
! {
! *code = LT;
! *cmp1 = force_reg (mode, GEN_INT (plus_one));
! return true;
! }
! break;
! case LEU:
! if (plus_one != 0)
! {
! *code = LTU;
! *cmp1 = force_reg (mode, GEN_INT (plus_one));
! return true;
! }
! break;
! default:
! return false;
! }
return false;
-
}
/* Compare CMP0 and CMP1 using relational operator CODE and store the
--- 3742,3779 ----
mips_canonicalize_comparison (enum rtx_code *code, rtx *cmp1,
enum machine_mode mode)
{
! HOST_WIDE_INT plus_one;
! if (mips_relational_operand_ok_p (*code, *cmp1))
! return true;
! if (GET_CODE (*cmp1) == CONST_INT)
! switch (*code)
! {
! case LE:
! plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
! if (INTVAL (*cmp1) < plus_one)
! {
! *code = LT;
! *cmp1 = force_reg (mode, GEN_INT (plus_one));
! return true;
! }
! break;
! case LEU:
! plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
! if (plus_one != 0)
! {
! *code = LTU;
! *cmp1 = force_reg (mode, GEN_INT (plus_one));
! return true;
! }
! break;
+ default:
+ break;
+ }
return false;
}
/* Compare CMP0 and CMP1 using relational operator CODE and store the
*************** mips_canonicalize_comparison (enum rtx_c
*** 3787,3805 ****
mips_emit_int_relational (enum rtx_code code, bool *invert_ptr,
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 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_emit_binary (code, target, cmp0, cmp1);
else
{
enum rtx_code inv_code = reverse_condition (code);
! if (!mips_relational_operand_ok_p (inv_code, cmp1))
{
cmp1 = force_reg (GET_MODE (cmp0), cmp1);
mips_emit_int_relational (code, invert_ptr, target, cmp0, cmp1);
--- 3785,3799 ----
mips_emit_int_relational (enum rtx_code code, bool *invert_ptr,
rtx target, rtx cmp0, rtx cmp1)
{
! /* First see if there is a MIPS instruction that can do this operation.
! If not, try doing the same for the inverse operation. If that also
! fails, force CMP1 into a register and try again. */
! if (mips_canonicalize_comparison (&code, &cmp1, GET_MODE (target)))
mips_emit_binary (code, target, cmp0, cmp1);
else
{
enum rtx_code inv_code = reverse_condition (code);
! if (!mips_canonicalize_comparison (&inv_code, &cmp1, GET_MODE (target)))
{
cmp1 = force_reg (GET_MODE (cmp0), cmp1);
mips_emit_int_relational (code, invert_ptr, target, cmp0, cmp1);