predicates.md: New file.
* config/mmix/predicates.md: New file. * config/mmix/mmix.c (mmix_symbolic_or_address_operand) (mmix_reg_or_constant_operand, mmix_reg_cc_operand) (mmix_foldable_comparison_operator, mmix_comparison_operator) (mmix_reg_or_0_operand, mmix_reg_or_8bit_operand): Remove. * config/mmix/mmix.h (PREDICATE_CODES, SPECIAL_MODE_PREDICATES): Don't define. * config/mmix/mmix.md: Include predicates.md. ("call", "call_value"): Force address to register if it isn't a mmix_symbolic_or_address_operand. From-SVN: r99235
This commit is contained in:
parent
29572b4dae
commit
cc73528f07
5 changed files with 188 additions and 154 deletions
|
@ -1,3 +1,16 @@
|
|||
2005-05-05 Hans-Peter Nilsson <hp@bitrange.com>
|
||||
|
||||
* config/mmix/predicates.md: New file.
|
||||
* config/mmix/mmix.c (mmix_symbolic_or_address_operand)
|
||||
(mmix_reg_or_constant_operand, mmix_reg_cc_operand)
|
||||
(mmix_foldable_comparison_operator, mmix_comparison_operator)
|
||||
(mmix_reg_or_0_operand, mmix_reg_or_8bit_operand): Remove.
|
||||
* config/mmix/mmix.h (PREDICATE_CODES, SPECIAL_MODE_PREDICATES):
|
||||
Don't define.
|
||||
* config/mmix/mmix.md: Include predicates.md.
|
||||
("call", "call_value"): Force address to register if it isn't a
|
||||
mmix_symbolic_or_address_operand.
|
||||
|
||||
2005-05-04 Andrew MacLeod <amacleod@redhat.com>
|
||||
|
||||
* tree-flow-inline.h (op_iter_init_use, op_iter_init_def): Assert that
|
||||
|
|
|
@ -2343,139 +2343,6 @@ mmix_shiftable_wyde_value (unsigned HOST_WIDEST_INT value)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* True if this is an address_operand or a symbolic operand. */
|
||||
|
||||
int
|
||||
mmix_symbolic_or_address_operand (rtx op, enum machine_mode mode)
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
return 1;
|
||||
case CONST:
|
||||
op = XEXP (op, 0);
|
||||
if ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
|
||||
|| GET_CODE (XEXP (op, 0)) == LABEL_REF)
|
||||
&& (GET_CODE (XEXP (op, 1)) == CONST_INT
|
||||
|| (GET_CODE (XEXP (op, 1)) == CONST_DOUBLE
|
||||
&& GET_MODE (XEXP (op, 1)) == VOIDmode)))
|
||||
return 1;
|
||||
/* Fall through. */
|
||||
default:
|
||||
return address_operand (op, mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* True if this is a register or CONST_INT (or CONST_DOUBLE for DImode).
|
||||
We could narrow the value down with a couple of predicated, but that
|
||||
doesn't seem to be worth it at the moment. */
|
||||
|
||||
int
|
||||
mmix_reg_or_constant_operand (rtx op, enum machine_mode mode)
|
||||
{
|
||||
return register_operand (op, mode)
|
||||
|| (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
|
||||
|| GET_CODE (op) == CONST_INT;
|
||||
}
|
||||
|
||||
/* True if this is a register with a condition-code mode. */
|
||||
|
||||
int
|
||||
mmix_reg_cc_operand (rtx op, enum machine_mode mode)
|
||||
{
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (op);
|
||||
|
||||
return register_operand (op, mode)
|
||||
&& (mode == CCmode || mode == CC_UNSmode || mode == CC_FPmode
|
||||
|| mode == CC_FPEQmode || mode == CC_FUNmode);
|
||||
}
|
||||
|
||||
/* True if this is a foldable comparison operator
|
||||
- one where a the result of (compare:CC (reg) (const_int 0)) can be
|
||||
replaced by (reg). */
|
||||
|
||||
int
|
||||
mmix_foldable_comparison_operator (rtx op, enum machine_mode mode)
|
||||
{
|
||||
RTX_CODE code = GET_CODE (op);
|
||||
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (op);
|
||||
|
||||
if (mode == VOIDmode && COMPARISON_P (op))
|
||||
mode = GET_MODE (XEXP (op, 0));
|
||||
|
||||
return ((mode == CCmode || mode == DImode)
|
||||
&& (code == NE || code == EQ || code == GE || code == GT
|
||||
|| code == LE))
|
||||
/* FIXME: This may be a stupid trick. What happens when GCC wants to
|
||||
reverse the condition? Can it do that by itself? Maybe it can
|
||||
even reverse the condition to fit a foldable one in the first
|
||||
place? */
|
||||
|| (mode == CC_UNSmode && (code == GTU || code == LEU));
|
||||
}
|
||||
|
||||
/* Like comparison_operator, but only true if this comparison operator is
|
||||
applied to a valid mode. Needed to avoid jump.c generating invalid
|
||||
code with -ffast-math (gcc.dg/20001228-1.c). */
|
||||
|
||||
int
|
||||
mmix_comparison_operator (rtx op, enum machine_mode mode)
|
||||
{
|
||||
RTX_CODE code = GET_CODE (op);
|
||||
|
||||
/* Comparison operators usually don't have a mode, but let's try and get
|
||||
one anyway for the day that changes. */
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (op);
|
||||
|
||||
/* Get the mode from the first operand if we don't have one. */
|
||||
if (mode == VOIDmode && COMPARISON_P (op))
|
||||
mode = GET_MODE (XEXP (op, 0));
|
||||
|
||||
/* FIXME: This needs to be kept in sync with the tables in
|
||||
mmix_output_condition. */
|
||||
return
|
||||
(mode == VOIDmode && COMPARISON_P (op))
|
||||
|| (mode == CC_FUNmode
|
||||
&& (code == ORDERED || code == UNORDERED))
|
||||
|| (mode == CC_FPmode
|
||||
&& (code == GT || code == LT))
|
||||
|| (mode == CC_FPEQmode
|
||||
&& (code == NE || code == EQ))
|
||||
|| (mode == CC_UNSmode
|
||||
&& (code == GEU || code == GTU || code == LEU || code == LTU))
|
||||
|| (mode == CCmode
|
||||
&& (code == NE || code == EQ || code == GE || code == GT
|
||||
|| code == LE || code == LT))
|
||||
|| (mode == DImode
|
||||
&& (code == NE || code == EQ || code == GE || code == GT
|
||||
|| code == LE || code == LT || code == LEU || code == GTU));
|
||||
}
|
||||
|
||||
/* True if this is a register or 0 (int or float). */
|
||||
|
||||
int
|
||||
mmix_reg_or_0_operand (rtx op, enum machine_mode mode)
|
||||
{
|
||||
/* FIXME: Is mode calculation necessary and correct? */
|
||||
return
|
||||
op == CONST0_RTX (mode == VOIDmode ? GET_MODE (op) : mode)
|
||||
|| register_operand (op, mode);
|
||||
}
|
||||
|
||||
/* True if this is a register or an int 0..255. */
|
||||
|
||||
int
|
||||
mmix_reg_or_8bit_operand (rtx op, enum machine_mode mode)
|
||||
{
|
||||
return register_operand (op, mode)
|
||||
|| (GET_CODE (op) == CONST_INT
|
||||
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'));
|
||||
}
|
||||
|
||||
/* Returns zero if code and mode is not a valid condition from a
|
||||
compare-type insn. Nonzero if it is. The parameter op, if non-NULL,
|
||||
is the comparison of mode is CC-somethingmode. */
|
||||
|
|
|
@ -964,27 +964,6 @@ typedef struct { int regs; int lib; } CUMULATIVE_ARGS;
|
|||
|
||||
/* Node: Misc */
|
||||
|
||||
#define PREDICATE_CODES \
|
||||
{"mmix_reg_cc_operand", {SUBREG, REG}}, \
|
||||
{"mmix_foldable_comparison_operator", \
|
||||
{NE, EQ, GE, GT, LE, LT}}, \
|
||||
/* All '<', actually. */ \
|
||||
{"mmix_comparison_operator", \
|
||||
{NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, \
|
||||
LTU, UNORDERED, ORDERED, UNEQ, UNGE, UNLE, \
|
||||
UNLT, LTGT}}, \
|
||||
{"mmix_symbolic_or_address_operand", \
|
||||
{SYMBOL_REF, LABEL_REF, CONST, \
|
||||
SUBREG, REG, PLUS}}, \
|
||||
{"mmix_reg_or_constant_operand", \
|
||||
{CONST_INT, CONST_DOUBLE, SUBREG, REG}}, \
|
||||
{"mmix_reg_or_8bit_operand", \
|
||||
{CONST_INT, CONST_DOUBLE, SUBREG, REG}}, \
|
||||
{"mmix_reg_or_0_operand", \
|
||||
{CONST_INT, CONST_DOUBLE, SUBREG, REG}},
|
||||
|
||||
#define SPECIAL_MODE_PREDICATES "mmix_symbolic_or_address_operand",
|
||||
|
||||
/* There's no way to get a PC-relative offset into tables for SImode, so
|
||||
for the moment we have absolute entries in DImode.
|
||||
When we're going ELF, these should be SImode and 1. */
|
||||
|
|
|
@ -40,7 +40,11 @@
|
|||
(MMIX_rR_REGNUM 260)
|
||||
(MMIX_fp_rO_OFFSET -24)]
|
||||
)
|
||||
|
||||
;; Operand and operator predicates.
|
||||
|
||||
(include "predicates.md")
|
||||
|
||||
;; FIXME: Can we remove the reg-to-reg for smaller modes? Shouldn't they
|
||||
;; be synthesized ok?
|
||||
(define_insn "movqi"
|
||||
|
@ -1078,6 +1082,16 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
|
|||
""
|
||||
"
|
||||
{
|
||||
/* The caller checks that the operand is generally valid as an
|
||||
address, but at -O0 nothing makes sure that it's also a valid
|
||||
call address for a *call*; a mmix_symbolic_or_address_operand.
|
||||
Force into a register if it isn't. */
|
||||
if (!mmix_symbolic_or_address_operand (XEXP (operands[0], 0),
|
||||
GET_MODE (XEXP (operands[0], 0))))
|
||||
operands[0]
|
||||
= replace_equiv_address (operands[0],
|
||||
force_reg (Pmode, XEXP (operands[0], 0)));
|
||||
|
||||
/* Since the epilogue 'uses' the return address, and it is clobbered
|
||||
in the call, and we set it back after every call (all but one setting
|
||||
will be optimized away), integrity is maintained. */
|
||||
|
@ -1105,6 +1119,16 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
|
|||
""
|
||||
"
|
||||
{
|
||||
/* The caller checks that the operand is generally valid as an
|
||||
address, but at -O0 nothing makes sure that it's also a valid
|
||||
call address for a *call*; a mmix_symbolic_or_address_operand.
|
||||
Force into a register if it isn't. */
|
||||
if (!mmix_symbolic_or_address_operand (XEXP (operands[1], 0),
|
||||
GET_MODE (XEXP (operands[1], 0))))
|
||||
operands[1]
|
||||
= replace_equiv_address (operands[1],
|
||||
force_reg (Pmode, XEXP (operands[1], 0)));
|
||||
|
||||
/* Since the epilogue 'uses' the return address, and it is clobbered
|
||||
in the call, and we set it back after every call (all but one setting
|
||||
will be optimized away), integrity is maintained. */
|
||||
|
|
151
gcc/config/mmix/predicates.md
Normal file
151
gcc/config/mmix/predicates.md
Normal file
|
@ -0,0 +1,151 @@
|
|||
;; Operand and operator predicates for the GCC MMIX port.
|
||||
;; Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
;; This file is part of GCC.
|
||||
;;
|
||||
;; GCC is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
;;
|
||||
;; GCC is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GCC; see the file COPYING. If not, write to
|
||||
;; the Free Software Foundation, 51 Franklin Street - Fifth Floor,
|
||||
;; Boston, MA 02110-1301, USA.
|
||||
|
||||
;; True if this is a foldable comparison operator
|
||||
;; - one where a the result of (compare:CC (reg) (const_int 0)) can be
|
||||
;; replaced by (reg). */
|
||||
|
||||
(define_predicate "mmix_foldable_comparison_operator"
|
||||
(match_code "ne, eq, ge, gt, le, lt, gtu, leu")
|
||||
{
|
||||
RTX_CODE code = GET_CODE (op);
|
||||
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (op);
|
||||
|
||||
/* This little bit is why the body of this predicate is kept as C. */
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (XEXP (op, 0));
|
||||
|
||||
return ((mode == CCmode || mode == DImode)
|
||||
&& (code == NE || code == EQ || code == GE || code == GT
|
||||
|| code == LE || code == LT))
|
||||
/* FIXME: This may be a stupid trick. What happens when GCC wants to
|
||||
reverse the condition? Can it do that by itself? Maybe it can
|
||||
even reverse the condition to fit a foldable one in the first
|
||||
place? */
|
||||
|| (mode == CC_UNSmode && (code == GTU || code == LEU));
|
||||
})
|
||||
|
||||
;; Like comparison_operator, but only true if this comparison operator is
|
||||
;; applied to a valid mode. Needed to avoid jump.c generating invalid
|
||||
;; code with -ffast-math (gcc.dg/20001228-1.c).
|
||||
|
||||
(define_predicate "mmix_comparison_operator"
|
||||
(match_operand 0 "comparison_operator")
|
||||
{
|
||||
RTX_CODE code = GET_CODE (op);
|
||||
|
||||
/* Comparison operators usually don't have a mode, but let's try and get
|
||||
one anyway for the day that changes. */
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (op);
|
||||
|
||||
/* Get the mode from the first operand if we don't have one.
|
||||
Also the reason why we do this in C. */
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (XEXP (op, 0));
|
||||
|
||||
/* FIXME: This needs to be kept in sync with the tables in
|
||||
mmix_output_condition. */
|
||||
return
|
||||
mode == VOIDmode
|
||||
|| (mode == CC_FUNmode
|
||||
&& (code == ORDERED || code == UNORDERED))
|
||||
|| (mode == CC_FPmode
|
||||
&& (code == GT || code == LT))
|
||||
|| (mode == CC_FPEQmode
|
||||
&& (code == NE || code == EQ))
|
||||
|| (mode == CC_UNSmode
|
||||
&& (code == GEU || code == GTU || code == LEU || code == LTU))
|
||||
|| (mode == CCmode
|
||||
&& (code == NE || code == EQ || code == GE || code == GT
|
||||
|| code == LE || code == LT))
|
||||
|| (mode == DImode
|
||||
&& (code == NE || code == EQ || code == GE || code == GT
|
||||
|| code == LE || code == LT || code == LEU || code == GTU));
|
||||
})
|
||||
|
||||
;; True if this is a register with a condition-code mode.
|
||||
|
||||
(define_predicate "mmix_reg_cc_operand"
|
||||
(and (match_operand 0 "register_operand")
|
||||
(ior (match_test "GET_MODE (op) == CCmode")
|
||||
(ior (match_test "GET_MODE (op) == CC_UNSmode")
|
||||
(ior (match_test "GET_MODE (op) == CC_FPmode")
|
||||
(ior (match_test "GET_MODE (op) == CC_FPEQmode")
|
||||
(match_test "GET_MODE (op) == CC_FUNmode")))))))
|
||||
|
||||
;; True if this is an address_operand or a symbolic operand.
|
||||
|
||||
(define_predicate "mmix_symbolic_or_address_operand"
|
||||
(match_code "symbol_ref, label_ref, const, subreg, reg, plus")
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
return 1;
|
||||
case CONST:
|
||||
/* The reason why this body still is C. */
|
||||
op = XEXP (op, 0);
|
||||
if ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
|
||||
|| GET_CODE (XEXP (op, 0)) == LABEL_REF)
|
||||
&& (GET_CODE (XEXP (op, 1)) == CONST_INT
|
||||
|| (GET_CODE (XEXP (op, 1)) == CONST_DOUBLE
|
||||
&& GET_MODE (XEXP (op, 1)) == VOIDmode)))
|
||||
return 1;
|
||||
/* Fall through. */
|
||||
default:
|
||||
return address_operand (op, mode);
|
||||
}
|
||||
})
|
||||
|
||||
;; True if this is a register or CONST_INT (or CONST_DOUBLE for DImode).
|
||||
;; We could narrow the value down with a couple of predicates, but that
|
||||
;; doesn't seem to be worth it at the moment.
|
||||
|
||||
(define_predicate "mmix_reg_or_constant_operand"
|
||||
(ior (match_operand 0 "register_operand")
|
||||
(ior (match_code "const_int")
|
||||
(and (match_code "const_double")
|
||||
(match_test "GET_MODE (op) == VOIDmode")))))
|
||||
|
||||
;; True if this is a register or 0 (int or float).
|
||||
|
||||
(define_predicate "mmix_reg_or_0_operand"
|
||||
(ior
|
||||
(match_operand 0 "register_operand")
|
||||
(ior
|
||||
(and (match_code "const_int")
|
||||
(match_test "op == const0_rtx"))
|
||||
(and
|
||||
(match_code "const_double")
|
||||
;; FIXME: Is mode calculation necessary and correct?
|
||||
(match_test
|
||||
"op == CONST0_RTX (mode == VOIDmode ? GET_MODE (op) : mode)")))))
|
||||
|
||||
;; True if this is a register or an int 0..255.
|
||||
|
||||
(define_predicate "mmix_reg_or_8bit_operand"
|
||||
(ior
|
||||
(match_operand 0 "register_operand")
|
||||
(and (match_code "const_int")
|
||||
(match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')"))))
|
Loading…
Add table
Reference in a new issue