This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
define_constraints conversion for h8300
- From: Zack Weinberg <zackw at panix dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 27 Feb 2006 22:41:47 -0500
- Subject: define_constraints conversion for h8300
As previously discussed, here is the define_constraints conversion
for the h8300 which Bernd declined to approve. I can't in conscience
recommend it for inclusion myself, as there *are* a handful of
C testsuite regressions that look real. However, neither do I have any
more time to look at it myself. Perhaps someone else will find this a
useful baseline.
[ The failures are of the form
gcc.c-torture/execute/20040709-2.c:109:
error: insn does not satisfy its constraints:
(insn 44 610 611 4 (set (mem/c:QI (plus:HI (reg/f:HI 6 r6)
(const_int -45 [0xffffffd3])) [218 S1 A8])
(and:QI (mem/c:QI (plus:HI (reg/f:HI 6 r6)
(const_int -45 [0xffffffd3])) [218 S1 A8])
(const_int -4 [0xfffffffc]))) 158 {andqi3_1} (insn_list:REG_DEP_TRUE 43 (nil))
(nil))
and are probably down to an obvious typo somewhere in this patch, but,
like I said, I'm out of time for this - nor are a severely buggy simulator
and assembler exactly a good baseline to be working with. ]
There's a weird bit in here: I had to move reload.c's #include "tm_p.h"
to the bottom of the list, because one of these predicates has a
definition that depends on REG_OK_STRICT(!) and the strict version
needs reg_renumber[]. This wasn't a problem before because it was a
macro. Now it's an inline function. (No, it is not feasible to
make them macros, they have local variables.)
zw
:ADDPATCH h8300:
* reload.c: Move inclusion of tm_p.h below all others.
* config/h8300/predicates.md (a, c, D, f, d, I, J, L, M, N, O)
(P1>X, P3>X, P4>X, P5>X, P8>X, P3<X, G, R, S, T, Q, U, WU, Z):
New constraint definitions.
(bit_operand, bit_memory_operand, incdec_operand):
Use constraint_satisfied_p.
* config/h8300/h8300.h (CONST_OK_FOR_I, CONST_OK_FOR_J, CONST_OK_FOR_L)
(CONST_OK_FOR_M, CONST_OK_FOR_N, CONST_OK_FOR_O, CONST_OK_FOR_P)
(CONST_OK_FOR_Pnegative, CONST_OK_FOR_Ppositive, CONSTRAINT_LEN_FOR_P)
(CONST_OK_FOR_CONSTRAINT_P, CONST_OK_FOR_LETTER_P)
(CONST_DOUBLE_OK_FOR_LETTER_P, OK_FOR_Q, OK_FOR_R, OK_FOR_S, OK_FOR_T)
(OK_FOR_U, OK_FOR_WU, OK_FOR_W, CONSTRAINT_LEN_FOR_W, OK_FOR_Y)
(CONSTRAINT_LEN_FOR_Y, OK_FOR_Z, EXTRA_CONSTRAINT_STR, CONSTRAINT_LEN)
(EXTRA_MEMORY_CONSTRAINT, REG_CLASS_FROM_LETTER): Delete.
Merge adjacent #ifndef REG_OK_STRICT blocks.
* config/h8300/h8300.md (*tst_extzv_1_n, *tstsi_variable_bit_qi)
(peepholes): Use constraint_satisfied_p.
* config/h8300/h8300.c (h8300_reg_class_from_letter): Delete.
(compute_mov_length, fix_bit_operand): Use constraint_satisfied_p.
=== config/h8300/h8300.c
==================================================================
--- config/h8300/h8300.c (revision 111546)
+++ config/h8300/h8300.c (local)
@@ -404,71 +404,6 @@
}
}
-/* Implement REG_CLASS_FROM_LETTER.
-
- Some patterns need to use er6 as a scratch register. This is
- difficult to arrange since er6 is the frame pointer and usually
- can't be spilled.
-
- Such patterns should define two alternatives, one which allows only
- er6 and one which allows any general register. The former alternative
- should have a 'd' constraint while the latter should be disparaged and
- use 'D'.
-
- Normally, 'd' maps to DESTINATION_REGS and 'D' maps to GENERAL_REGS.
- However, there are cases where they should be NO_REGS:
-
- - 'd' should be NO_REGS when reloading a function that uses the
- frame pointer. In this case, DESTINATION_REGS won't contain any
- spillable registers, so the first alternative can't be used.
-
- - -fno-omit-frame-pointer means that the frame pointer will
- always be in use. It's therefore better to map 'd' to NO_REGS
- before reload so that register allocator will pick the second
- alternative.
-
- - we would like 'D' to be be NO_REGS when the frame pointer isn't
- live, but we the frame pointer may turn out to be needed after
- we start reload, and then we may have already decided we don't
- have a choice, so we can't do that. Forcing the register
- allocator to use er6 if possible might produce better code for
- small functions: it's more efficient to save and restore er6 in
- the prologue & epilogue than to do it in a define_split.
- Hopefully disparaging 'D' will have a similar effect, without
- forcing a reload failure if the frame pointer is found to be
- needed too late. */
-
-enum reg_class
-h8300_reg_class_from_letter (int c)
-{
- switch (c)
- {
- case 'a':
- return MAC_REGS;
-
- case 'c':
- return COUNTER_REGS;
-
- case 'd':
- if (!flag_omit_frame_pointer && !reload_completed)
- return NO_REGS;
- if (frame_pointer_needed && reload_in_progress)
- return NO_REGS;
- return DESTINATION_REGS;
-
- case 'D':
- /* The meaning of a constraint shouldn't change dynamically, so
- we can't make this NO_REGS. */
- return GENERAL_REGS;
-
- case 'f':
- return SOURCE_REGS;
-
- default:
- return NO_REGS;
- }
-}
-
/* Return the byte register name for a register rtx X. B should be 0
if you want a lower byte register. B should be 1 if you want an
upper byte register. */
@@ -2703,7 +2638,7 @@
if (REG_P (src))
return 4;
- if (CONST_DOUBLE_OK_FOR_LETTER_P (src, 'G'))
+ if (satisfies_constraint_G (src))
return 4;
return 8;
@@ -2823,7 +2758,7 @@
if (REG_P (src))
return 2;
- if (CONST_DOUBLE_OK_FOR_LETTER_P (src, 'G'))
+ if (satisfies_constraint_G (src))
return 2;
return 6;
@@ -5036,7 +4971,7 @@
{
/* OK to have a memory dest. */
if (GET_CODE (operands[0]) == MEM
- && !OK_FOR_U (operands[0]))
+ && !satisfies_constraint_U (operands[0]))
{
rtx mem = gen_rtx_MEM (GET_MODE (operands[0]),
copy_to_mode_reg (Pmode,
@@ -5046,7 +4981,7 @@
}
if (GET_CODE (operands[1]) == MEM
- && !OK_FOR_U (operands[1]))
+ && !satisfies_constraint_U (operands[1]))
{
rtx mem = gen_rtx_MEM (GET_MODE (operands[1]),
copy_to_mode_reg (Pmode,
=== config/h8300/h8300.h
==================================================================
--- config/h8300/h8300.h (revision 111546)
+++ config/h8300/h8300.h (local)
@@ -386,76 +386,6 @@
#define INDEX_REG_CLASS (TARGET_H8300SX ? GENERAL_REGS : NO_REGS)
#define BASE_REG_CLASS GENERAL_REGS
-/* Get reg_class from a letter such as appears in the machine description.
-
- 'a' is the MAC register. */
-
-#define REG_CLASS_FROM_LETTER(C) (h8300_reg_class_from_letter (C))
-
-/* The letters I, J, K, L, M, N, O, P in a register constraint string
- can be used to stand for particular ranges of immediate operands.
- This macro defines what the ranges are.
- C is the letter, and VALUE is a constant value.
- Return 1 if VALUE is in the range specified by C. */
-
-#define CONST_OK_FOR_I(VALUE) ((VALUE) == 0)
-#define CONST_OK_FOR_J(VALUE) (((VALUE) & 0xff) == 0)
-#define CONST_OK_FOR_L(VALUE) \
- (TARGET_H8300H || TARGET_H8300S \
- ? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 4 \
- : (VALUE) == 1 || (VALUE) == 2)
-#define CONST_OK_FOR_M(VALUE) \
- ((VALUE) == 1 || (VALUE) == 2)
-#define CONST_OK_FOR_N(VALUE) \
- (TARGET_H8300H || TARGET_H8300S \
- ? (VALUE) == -1 || (VALUE) == -2 || (VALUE) == -4 \
- : (VALUE) == -1 || (VALUE) == -2)
-#define CONST_OK_FOR_O(VALUE) \
- ((VALUE) == -1 || (VALUE) == -2)
-
-/* Multi-letter constraints for constant are always started with P
- (just because it was the only letter in the range left. New
- constraints for constants should be added here. */
-#define CONST_OK_FOR_Ppositive(VALUE, NBITS) \
- ((VALUE) > 0 && (VALUE) < (1 << (NBITS)))
-#define CONST_OK_FOR_Pnegative(VALUE, NBITS) \
- ((VALUE) < 0 && (VALUE) > -(1 << (NBITS)))
-#define CONST_OK_FOR_P(VALUE, STR) \
- ((STR)[1] >= '1' && (STR)[1] <= '9' && (STR)[2] == '<' \
- ? (((STR)[3] == '0' || ((STR)[3] == 'X' && TARGET_H8300SX)) \
- && CONST_OK_FOR_Pnegative ((VALUE), (STR)[1] - '0')) \
- : ((STR)[1] >= '1' && (STR)[1] <= '9' && (STR)[2] == '>') \
- ? (((STR)[3] == '0' || ((STR)[3] == 'X' && TARGET_H8300SX)) \
- && CONST_OK_FOR_Ppositive ((VALUE), (STR)[1] - '0')) \
- : 0)
-#define CONSTRAINT_LEN_FOR_P(STR) \
- ((((STR)[1] >= '1' && (STR)[1] <= '9') \
- && ((STR)[2] == '<' || (STR)[2] == '>') \
- && ((STR)[3] == 'X' || (STR)[3] == '0')) ? 4 \
- : 0)
-
-#define CONST_OK_FOR_CONSTRAINT_P(VALUE, C, STR) \
- ((C) == 'P' ? CONST_OK_FOR_P ((VALUE), (STR)) \
- : CONST_OK_FOR_LETTER_P ((VALUE), (C)))
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'I' ? CONST_OK_FOR_I (VALUE) : \
- (C) == 'J' ? CONST_OK_FOR_J (VALUE) : \
- (C) == 'L' ? CONST_OK_FOR_L (VALUE) : \
- (C) == 'M' ? CONST_OK_FOR_M (VALUE) : \
- (C) == 'N' ? CONST_OK_FOR_N (VALUE) : \
- (C) == 'O' ? CONST_OK_FOR_O (VALUE) : \
- 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
- Here VALUE is the CONST_DOUBLE rtx itself.
-
- `G' is a floating-point zero. */
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'G' ? (VALUE) == CONST0_RTX (SFmode) \
- : 0)
-
/* Given an rtx X being reloaded into a reg required to be
in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines
@@ -796,125 +726,6 @@
#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P (X)
#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P (X)
-
-#else
-
-#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P (X)
-#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P (X)
-
-#endif
-
-/* Extra constraints. */
-
-#define OK_FOR_Q(OP) \
- (TARGET_H8300SX && memory_operand ((OP), VOIDmode))
-
-#define OK_FOR_R(OP) \
- (GET_CODE (OP) == CONST_INT \
- ? !h8300_shift_needs_scratch_p (INTVAL (OP), QImode) \
- : 0)
-
-#define OK_FOR_S(OP) \
- (GET_CODE (OP) == CONST_INT \
- ? !h8300_shift_needs_scratch_p (INTVAL (OP), HImode) \
- : 0)
-
-#define OK_FOR_T(OP) \
- (GET_CODE (OP) == CONST_INT \
- ? !h8300_shift_needs_scratch_p (INTVAL (OP), SImode) \
- : 0)
-
-/* 'U' if valid for a bset destination;
- i.e. a register, register indirect, or the eightbit memory region
- (a SYMBOL_REF with an SYMBOL_REF_FLAG set).
-
- On the H8S 'U' can also be a 16bit or 32bit absolute. */
-#define OK_FOR_U(OP) \
- ((GET_CODE (OP) == REG && REG_OK_FOR_BASE_P (OP)) \
- || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
- && REG_OK_FOR_BASE_P (XEXP (OP, 0))) \
- || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF \
- && TARGET_H8300S) \
- || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST \
- && GET_CODE (XEXP (XEXP (OP, 0), 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (XEXP (OP, 0), 0), 0)) == SYMBOL_REF \
- && GET_CODE (XEXP (XEXP (XEXP (OP, 0), 0), 1)) == CONST_INT \
- && (TARGET_H8300S \
- || SYMBOL_REF_FLAG (XEXP (XEXP (XEXP (OP, 0), 0), 0)))) \
- || (GET_CODE (OP) == MEM \
- && h8300_eightbit_constant_address_p (XEXP (OP, 0))) \
- || (GET_CODE (OP) == MEM && TARGET_H8300S \
- && GET_CODE (XEXP (OP, 0)) == CONST_INT))
-
-/* Multi-letter constraints starting with W are to be used for
- operands that require a memory operand, i.e,. that are never used
- along with register constraints (see EXTRA_MEMORY_CONSTRAINTS).
- For operands that require a memory operand (or not) but that always
- accept a register, a multi-letter constraint starting with Y should
- be used instead. */
-
-#define OK_FOR_WU(OP) \
- (GET_CODE (OP) == MEM && OK_FOR_U (OP))
-
-#define OK_FOR_W(OP, STR) \
- ((STR)[1] == 'U' ? OK_FOR_WU (OP) \
- : 0)
-
-#define CONSTRAINT_LEN_FOR_W(STR) \
- ((STR)[1] == 'U' ? 2 \
- : 0)
-
-/* We don't have any constraint starting with Y yet, but before
- someone uses it for a one-letter constraint and we're left without
- any upper-case constraints left, we reserve it for extensions
- here. */
-#define OK_FOR_Y(OP, STR) \
- (0)
-
-#define CONSTRAINT_LEN_FOR_Y(STR) \
- (0)
-
-#define OK_FOR_Z(OP) \
- (TARGET_H8300SX \
- && GET_CODE (OP) == MEM \
- && CONSTANT_P (XEXP ((OP), 0)))
-
-#define EXTRA_CONSTRAINT_STR(OP, C, STR) \
- ((C) == 'Q' ? OK_FOR_Q (OP) : \
- (C) == 'R' ? OK_FOR_R (OP) : \
- (C) == 'S' ? OK_FOR_S (OP) : \
- (C) == 'T' ? OK_FOR_T (OP) : \
- (C) == 'U' ? OK_FOR_U (OP) : \
- (C) == 'W' ? OK_FOR_W ((OP), (STR)) : \
- (C) == 'Y' ? OK_FOR_Y ((OP), (STR)) : \
- (C) == 'Z' ? OK_FOR_Z (OP) : \
- 0)
-
-#define CONSTRAINT_LEN(C, STR) \
- ((C) == 'P' ? CONSTRAINT_LEN_FOR_P (STR) \
- : (C) == 'W' ? CONSTRAINT_LEN_FOR_W (STR) \
- : (C) == 'Y' ? CONSTRAINT_LEN_FOR_Y (STR) \
- : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
-
-/* Experiments suggest that it's better not add 'Q' or 'U' here. No
- patterns need it for correctness (no patterns use 'Q' and 'U'
- without also providing a register alternative). And defining it
- will mean that a spilled pseudo could be replaced by its frame
- location in several consecutive insns.
-
- Instead, it seems to be better to force pseudos to be reloaded
- into registers and then use peepholes to recombine insns when
- beneficial.
-
- Unfortunately, for WU (unlike plain U, that matches regs as well),
- we must require a memory address. In fact, all multi-letter
- constraints started with W are supposed to have this property, so
- we just test for W here. */
-#define EXTRA_MEMORY_CONSTRAINT(C, STR) \
- ((C) == 'W')
-
-
-#ifndef REG_OK_STRICT
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
do \
{ \
@@ -922,7 +733,11 @@
goto ADDR; \
} \
while (0)
+
#else
+
+#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P (X)
+#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P (X)
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
do \
{ \
@@ -930,7 +745,9 @@
goto ADDR; \
} \
while (0)
+
#endif
+
/* Go to LABEL if ADDR (a legitimate address expression)
has an effect that depends on the machine mode it is used for.
=== config/h8300/h8300.md
==================================================================
--- config/h8300/h8300.md (revision 111546)
+++ config/h8300/h8300.md (local)
@@ -990,7 +990,7 @@
btst\\t%Z1,%Y0
#"
"&& reload_completed
- && !OK_FOR_U (operands[0])"
+ && !satisfies_constraint_U (operands[0])"
[(set (match_dup 2)
(match_dup 0))
(parallel [(set (cc0) (zero_extract:SI (match_dup 2)
@@ -1056,7 +1056,7 @@
btst\\t%w1,%X0
#"
"&& reload_completed
- && !OK_FOR_U (operands[0])"
+ && !satisfies_constraint_U (operands[0])"
[(set (match_dup 2)
(match_dup 0))
(parallel [(set (cc0) (zero_extract:SI (zero_extend:SI (match_dup 2))
@@ -4762,9 +4762,9 @@
(match_operand:HI 2 "register_operand" "")))]
"REG_P (operands[0]) && REG_P (operands[2])
&& REGNO (operands[0]) != REGNO (operands[2])
- && (CONST_OK_FOR_J (INTVAL (operands[1]))
- || CONST_OK_FOR_L (INTVAL (operands[1]))
- || CONST_OK_FOR_N (INTVAL (operands[1])))"
+ && (satisfies_constraint_J (operands[1])
+ || satisfies_constraint_L (operands[1])
+ || satisfies_constraint_N (operands[1]))"
[(set (match_dup 0)
(match_dup 2))
(set (match_dup 0)
@@ -4792,8 +4792,8 @@
"(TARGET_H8300H || TARGET_H8300S)
&& REG_P (operands[0]) && REG_P (operands[2])
&& REGNO (operands[0]) != REGNO (operands[2])
- && (CONST_OK_FOR_L (INTVAL (operands[1]))
- || CONST_OK_FOR_N (INTVAL (operands[1])))"
+ && (satisfies_constraint_L (operands[1])
+ || satisfies_constraint_N (operands[1]))"
[(set (match_dup 0)
(match_dup 2))
(set (match_dup 0)
@@ -4821,8 +4821,8 @@
"(TARGET_H8300H || TARGET_H8300S)
&& REG_P (operands[0]) && REG_P (operands[1])
&& REGNO (operands[0]) != REGNO (operands[1])
- && !CONST_OK_FOR_L (INTVAL (operands[2]))
- && !CONST_OK_FOR_N (INTVAL (operands[2]))
+ && !satisfies_constraint_L (operands[2])
+ && !satisfies_constraint_N (operands[2])
&& ((INTVAL (operands[2]) & 0xff) == INTVAL (operands[2])
|| (INTVAL (operands[2]) & 0xff00) == INTVAL (operands[2])
|| INTVAL (operands[2]) == 0xffff
=== config/h8300/predicates.md
==================================================================
--- config/h8300/predicates.md (revision 111546)
+++ config/h8300/predicates.md (local)
@@ -345,7 +345,7 @@
if (GET_CODE (op) == SUBREG)
return 1;
return (GET_CODE (op) == MEM
- && OK_FOR_U (op));
+ && satisfies_constraint_U (op));
})
;; Return nonzero if OP is a MEM suitable for bit manipulation insns.
@@ -354,7 +354,7 @@
(match_code "mem")
{
return (GET_CODE (op) == MEM
- && OK_FOR_U (op));
+ && satisfies_constraint_U (op));
})
;; Return nonzero if X is a stack pointer.
@@ -409,8 +409,8 @@
(match_code "const_int")
{
return (GET_CODE (op) == CONST_INT
- && (CONST_OK_FOR_M (INTVAL (op))
- || CONST_OK_FOR_O (INTVAL (op))));
+ && (satisfies_constraint_M (op)
+ || satisfies_constraint_O (op)));
})
;; Recognize valid operators for bit instructions.
@@ -481,3 +481,222 @@
return (code == IOR || code == XOR);
})
+
+;; FIXME Many constraint definitions need docstrings.
+
+;; Register constraints:
+;;
+;; Some patterns need to use er6 as a scratch register. This is
+;; difficult to arrange since er6 is the frame pointer and usually
+;; can't be spilled.
+;;
+;; Such patterns should define two alternatives, one which allows only
+;; er6 and one which allows any general register. The former alternative
+;; should have a 'd' constraint while the latter should be disparaged and
+;; use 'D'.
+;;
+;; Normally, 'd' maps to DESTINATION_REGS and 'D' maps to GENERAL_REGS.
+;; However, there are cases where they should be NO_REGS:
+;;
+;; - 'd' should be NO_REGS when reloading a function that uses the
+;; frame pointer. In this case, DESTINATION_REGS won't contain any
+;; spillable registers, so the first alternative can't be used.
+;;
+;; - -fno-omit-frame-pointer means that the frame pointer will
+;; always be in use. It's therefore better to map 'd' to NO_REGS
+;; before reload so that register allocator will pick the second
+;; alternative.
+;;
+;; - we would like 'D' to be be NO_REGS when the frame pointer isn't
+;; live, but we the frame pointer may turn out to be needed after
+;; we start reload, and then we may have already decided we don't
+;; have a choice, so we can't do that. Forcing the register
+;; allocator to use er6 if possible might produce better code for
+;; small functions: it's more efficient to save and restore er6 in
+;; the prologue & epilogue than to do it in a define_split.
+;; Hopefully disparaging 'D' will have a similar effect, without
+;; forcing a reload failure if the frame pointer is found to be
+;; needed too late.
+
+(define_register_constraint "a" "MAC_REGS"
+ "")
+
+(define_register_constraint "c" "COUNTER_REGS"
+ "")
+
+(define_register_constraint "D" "GENERAL_REGS"
+ "")
+
+(define_register_constraint "f" "SOURCE_REGS"
+ "")
+
+(define_register_constraint "d"
+ "(!flag_omit_frame_pointer && !reload_completed) ? NO_REGS
+ : (frame_pointer_needed && reload_in_progress) ? NO_REGS
+ : DESTINATION_REGS"
+ "")
+
+;; Integer constant constraints:
+
+(define_constraint "I"
+ "Integer zero."
+ (and (match_code "const_int")
+ (match_test "ival == 0")))
+
+(define_constraint "J"
+ "Any integer whose low eight bits are zero."
+ (and (match_code "const_int")
+ (match_test "(ival & 0xff) == 0")))
+
+;; K is not used.
+
+(define_constraint "L"
+ "The integers 1, 2, or (on the H/8300H and H/8300S only) 4."
+ (and (match_code "const_int")
+ (ior (match_test "ival == 1")
+ (match_test "ival == 2")
+ (and (match_test "TARGET_H8300H || TARGET_H8300S")
+ (match_test "ival == 4")))))
+
+(define_constraint "M"
+ "The integers 1 or 2."
+ (and (match_code "const_int")
+ (ior (match_test "ival == 1")
+ (match_test "ival == 2"))))
+
+(define_constraint "N"
+ "The integers -1, -2, or (on the H/8300H and H/8300S only) -4."
+ (and (match_code "const_int")
+ (ior (match_test "ival == -1")
+ (match_test "ival == -2")
+ (and (match_test "TARGET_H8300H || TARGET_H8300S")
+ (match_test "ival == -4")))))
+
+(define_constraint "O"
+ "The integers -1 or -2."
+ (and (match_code "const_int")
+ (ior (match_test "ival == -1")
+ (match_test "ival == -2"))))
+
+;; All multi-letter constant constraints start with 'P'. They have
+;; the general form P[0-9][<>][X0] (but, of course, only those that
+;; are used are defined). They all represent a nonzero integer which
+;; fits in a specific number of bits; the second character indicates
+;; how many. The third character is '<' for a negative constant, '>'
+;; for a positive constant. Finally, the fourth letter is '0' for no
+;; special treatment, 'X' for a constraint only allowed to match when
+;; TARGET_H8300SX is true.
+
+(define_constraint "P1>X"
+ ""
+ (and (match_code "const_int")
+ (match_test "TARGET_H8300SX")
+ (match_test "ival > 0 && ival < (1 << 1)")))
+
+(define_constraint "P3>X"
+ ""
+ (and (match_code "const_int")
+ (match_test "TARGET_H8300SX")
+ (match_test "ival > 0 && ival < (1 << 3)")))
+
+(define_constraint "P4>X"
+ ""
+ (and (match_code "const_int")
+ (match_test "TARGET_H8300SX")
+ (match_test "ival > 0 && ival < (1 << 4)")))
+
+(define_constraint "P5>X"
+ ""
+ (and (match_code "const_int")
+ (match_test "TARGET_H8300SX")
+ (match_test "ival > 0 && ival < (1 << 5)")))
+
+(define_constraint "P8>X"
+ ""
+ (and (match_code "const_int")
+ (match_test "TARGET_H8300SX")
+ (match_test "ival > 0 && ival < (1 << 8)")))
+
+(define_constraint "P3<X"
+ ""
+ (and (match_code "const_int")
+ (match_test "TARGET_H8300SX")
+ (match_test "ival < 0 && ival > -(1 << 3)")))
+
+(define_constraint "G"
+ "Single-precision floating-point zero."
+ (and (match_code "const_double")
+ (match_test "op == CONST0_RTX (SFmode)")))
+
+;; Extra constant constraints.
+
+(define_constraint "R"
+ ""
+ (and (match_code "const_int")
+ (not (match_test "h8300_shift_needs_scratch_p (ival, QImode)"))))
+
+(define_constraint "S"
+ ""
+ (and (match_code "const_int")
+ (not (match_test "h8300_shift_needs_scratch_p (ival, HImode)"))))
+
+(define_constraint "T"
+ ""
+ (and (match_code "const_int")
+ (not (match_test "h8300_shift_needs_scratch_p (ival, SImode)"))))
+
+;; Memory constraints.
+;;
+;; Experiments suggest that it's better not to use
+;; define_memory_constraint for 'Q' or 'U'. No patterns need it for
+;; correctness (no patterns use 'Q' or 'U' without also providing a
+;; register alternative). And use of define_memory_constraint means
+;; that a spilled pseudo could be replaced by its frame location in
+;; several consecutive insns.
+;;
+;; Instead, it seems to be better to force pseudos to be reloaded
+;; into registers and then use peepholes to recombine insns when
+;; beneficial.
+
+(define_constraint "Q"
+ ""
+ (and (match_test "TARGET_H8300SX")
+ (match_test "memory_operand (op, VOIDmode)")))
+
+(define_constraint "U"
+ "A valid bset destination; that is, a register, register indirect,
+ or the eightbit memory region (a @code{symbol_ref} with the
+ @code{symbol_ref_flag} set). On H8S, a 16- or 32-bit absolute
+ address is also valid."
+ (ior (and (match_code "reg") (match_test "REG_OK_FOR_BASE_P (op)"))
+ (and (match_code "mem")
+ (ior (and (match_code "reg" "0")
+ (match_test "REG_OK_FOR_BASE_P (XEXP (op, 0))"))
+ (match_test "h8300_eightbit_constant_address_p (XEXP (op, 0))")
+ (and (match_test "TARGET_H8300S")
+ (ior (match_code "symbol_ref" "0")
+ (match_code "const_int" "0"))
+ (and (match_code "const" "0")
+ (match_code "plus" "00")
+ (match_code "symbol_ref" "000")
+ (match_code "const_int" "001")))))))
+
+;; Multi-letter constraints starting with W are to be used for
+;; operands that require a memory operand, i.e,. that are never used
+;; along with register constraints. For operands that require a
+;; memory operand (or not) but that always accept a register, a
+;; multi-letter constraint starting with Y should be used instead.
+;; All W constraints must be appropriate to mark as memory constraints.
+
+(define_memory_constraint "WU"
+ "A bset destination (as 'U'), excluding registers."
+ (and (match_code "mem")
+ (match_test "satisfies_constraint_U (op)")))
+
+;; Y is reserved for future multi-letter constraints.
+
+(define_constraint "Z"
+ ""
+ (and (match_test "TARGET_H8300SX")
+ (match_code "mem")
+ (match_test "CONSTANT_P (XEXP (op, 0))")))
=== reload.c
==================================================================
--- reload.c (revision 111546)
+++ reload.c (local)
@@ -93,7 +93,6 @@
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
-#include "tm_p.h"
#include "insn-config.h"
#include "expr.h"
#include "optabs.h"
@@ -108,6 +107,7 @@
#include "toplev.h"
#include "params.h"
#include "target.h"
+#include "tm_p.h"
/* True if X is a constant that can be forced into the constant pool. */
#define CONST_POOL_OK_P(X) \