Committed, MMIX: predicates.md

Hans-Peter Nilsson hp@bitrange.com
Wed May 4 22:40:00 GMT 2005


I did this manually without Kazu-sans machine-generated (IIRC) patches
(sorry), to avoid overlooking simplifications and more easily spot other
issues.  For example, I see I must have missed LT in the original
mmix_foldable_comparison_operator.  Fixing that made a great deal in
removing redundant compares by 0, by inspection of libgcc.a.

The mmix_symbolic_or_address_operand problem Kazu found in his compile.exp
test, turned out to be a missing adjustment in the call define_expands.
That predicate also now lost its special_predicate status, as it doesn't
accept the only VOIDmode RTX it once did: CONST_INT (I missed fixing that
when I introduce the "base-address" addressing).  I think CONST also could
be VOIDmode previously, but obviously that has changed, at least in the
mind of lead maintainers, but I still somewhat doubt all ports comply.
The address operand of call insns insn is PC-relative, so allowing a naked
constant there would likely cause it to be expanded into more than just
one instruction by the assembler (and linker).

Three of the predicates kept most of their C body, as that seemed the most
compact expression.

	* 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.

Index: predicates.md
===================================================================
RCS file: predicates.md
diff -N predicates.md
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ predicates.md	4 May 2005 22:29:33 -0000
@@ -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')"))))
Index: mmix.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mmix/mmix.c,v
retrieving revision 1.78
diff -p -c -r1.78 mmix.c
*** mmix.c	2 May 2005 21:17:36 -0000	1.78
--- mmix.c	4 May 2005 13:27:50 -0000
*************** mmix_shiftable_wyde_value (unsigned HOST
*** 2343,2481 ****
    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.  */
--- 2343,2348 ----
Index: mmix.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mmix/mmix.h,v
retrieving revision 1.72
diff -p -c -r1.72 mmix.h
*** mmix.h	2 May 2005 21:17:37 -0000	1.72
--- mmix.h	4 May 2005 13:27:50 -0000
*************** typedef struct { int regs; int lib; } CU
*** 964,990 ****

  /* 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.  */
--- 964,969 ----
Index: mmix.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mmix/mmix.md,v
retrieving revision 1.27
diff -p -c -r1.27 mmix.md
*** mmix.md	28 Apr 2005 05:38:42 -0000	1.27
--- mmix.md	4 May 2005 13:27:51 -0000
***************
*** 40,46 ****
--- 40,50 ----
     (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"
*************** DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\
*** 1078,1083 ****
--- 1082,1097 ----
    ""
    "
  {
+   /* 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.  */
*************** DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\
*** 1105,1110 ****
--- 1119,1134 ----
    ""
    "
  {
+   /* 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.  */

brgds, H-P



More information about the Gcc-patches mailing list