summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>2002-08-14 10:04:51 +0000
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>2002-08-14 10:04:51 +0000
commita5004c3da9d0b789d68611ec00a1f59d8f62761b (patch)
treef8955f2da7788407bd35a092c0a414ccd029de11 /gcc
parentc363d230bc0490ec67a7726707d6eea248e5d5c4 (diff)
downloadgcc-a5004c3da9d0b789d68611ec00a1f59d8f62761b.tar.gz
* reload.c (find_reloads): Handle constraint letters marked by
EXTRA_ADDRESS_CONSTRAINT and EXTRA_MEMORY_CONSTRAINT. (alternative_allows_memconst): Likewise. * reload1.c (maybe_fix_stack_asms): Likewise. * recog.c (asm_operand_ok, preprocess_constraints, constrain_operands): Likewise. * regclass.c (record_operand_costs, record_reg_classes): Likewise. * local-alloc.c (block_alloc, requires_inout): Likewise. * stmt.c (parse_output_constraint, parse_input_constraint): Likewise. * defaults.h (EXTRA_MEMORY_CONSTRAINT): Provide a default. (EXTRA_ADDRESS_CONSTRAINT): Likewise. * doc/tm.texi: Document these two new target macros. * config/s390/s390.c (s390_expand_plus_operand): Accept already valid operands. (q_constraint): New function. config/s390/s390-protos.h (q_constraint): Declare it. config/s390/s390.h (EXTRA_CONSTRAINT): Use it. (EXTRA_MEMORY_CONSTRAINT): New macro. * config/s390/s390.md: Throughout the machine description, replace all instances of the constraint combinations 'Qo' or 'oQ' with simply 'Q'. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@56291 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog27
-rw-r--r--gcc/config/s390/s390-protos.h1
-rw-r--r--gcc/config/s390/s390.c31
-rw-r--r--gcc/config/s390/s390.h4
-rw-r--r--gcc/config/s390/s390.md188
-rw-r--r--gcc/defaults.h12
-rw-r--r--gcc/doc/tm.texi38
-rw-r--r--gcc/local-alloc.c6
-rw-r--r--gcc/recog.c47
-rw-r--r--gcc/regclass.c24
-rw-r--r--gcc/reload.c48
-rw-r--r--gcc/reload1.c8
-rw-r--r--gcc/stmt.c8
13 files changed, 340 insertions, 102 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3df15190cb6..d7348981e52 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,30 @@
+2002-08-14 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * reload.c (find_reloads): Handle constraint letters marked by
+ EXTRA_ADDRESS_CONSTRAINT and EXTRA_MEMORY_CONSTRAINT.
+ (alternative_allows_memconst): Likewise.
+ * reload1.c (maybe_fix_stack_asms): Likewise.
+ * recog.c (asm_operand_ok, preprocess_constraints,
+ constrain_operands): Likewise.
+ * regclass.c (record_operand_costs, record_reg_classes): Likewise.
+ * local-alloc.c (block_alloc, requires_inout): Likewise.
+ * stmt.c (parse_output_constraint, parse_input_constraint): Likewise.
+
+ * defaults.h (EXTRA_MEMORY_CONSTRAINT): Provide a default.
+ (EXTRA_ADDRESS_CONSTRAINT): Likewise.
+ * doc/tm.texi: Document these two new target macros.
+
+ * config/s390/s390.c (s390_expand_plus_operand): Accept already
+ valid operands.
+ (q_constraint): New function.
+ config/s390/s390-protos.h (q_constraint): Declare it.
+ config/s390/s390.h (EXTRA_CONSTRAINT): Use it.
+ (EXTRA_MEMORY_CONSTRAINT): New macro.
+
+ * config/s390/s390.md: Throughout the machine description,
+ replace all instances of the constraint combinations 'Qo'
+ or 'oQ' with simply 'Q'.
+
2002-08-14 Stephane Carrez <stcarrez@nerim.fr>
* config/m68hc11/m68hc11.h (LINK_SPEC): Support -mrelax.
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index a85e350a4da..38c5c0b2035 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -31,6 +31,7 @@ extern void s390_emit_epilogue PARAMS ((void));
extern void s390_function_profiler PARAMS ((FILE *, int));
#ifdef RTX_CODE
+extern int q_constraint PARAMS ((rtx));
extern int const0_operand PARAMS ((rtx, enum machine_mode));
extern int consttable_operand PARAMS ((rtx, enum machine_mode));
extern int larl_operand PARAMS ((rtx, enum machine_mode));
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index b43883b1375..6a29b764f00 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -995,6 +995,28 @@ s_imm_operand (op, mode)
return general_s_operand (op, mode, 1);
}
+/* Return true if OP is a valid operand for a 'Q' constraint.
+ This differs from s_operand in that only memory operands
+ without index register are accepted, nothing else. */
+
+int
+q_constraint (op)
+ register rtx op;
+{
+ struct s390_address addr;
+
+ if (GET_CODE (op) != MEM)
+ return 0;
+
+ if (!s390_decompose_address (XEXP (op, 0), &addr, FALSE))
+ return 0;
+
+ if (addr.indx)
+ return 0;
+
+ return 1;
+}
+
/* Return true if OP is a valid operand for the BRAS instruction.
OP is the current operation.
MODE is the current operation mode. */
@@ -1386,6 +1408,15 @@ s390_expand_plus_operand (target, src, scratch_in)
sum1 = find_replacement (&XEXP (src, 0));
sum2 = find_replacement (&XEXP (src, 1));
+ /* Accept already valid addresses. */
+ src = gen_rtx_PLUS (Pmode, sum1, sum2);
+ if (s390_decompose_address (src, NULL, 1))
+ {
+ src = legitimize_la_operand (src);
+ emit_insn (gen_rtx_SET (VOIDmode, target, src));
+ return;
+ }
+
/* If one of the two operands is equal to the target,
make it the first one. If one is a constant, make
it the second one. */
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 05875b4fd76..c5ba4270d37 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -533,9 +533,11 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; /* smalled clas
/* 'Q' means a memory-reference for a S-type operand. */
#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'Q' ? s_operand (OP, GET_MODE (OP)) : \
+ ((C) == 'Q' ? q_constraint (OP) : \
(C) == 'S' ? larl_operand (OP, GET_MODE (OP)) : 0)
+#define EXTRA_MEMORY_CONSTRAINT(C) ((C) == 'Q')
+
/* 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 in some cases it is preferable to use a more
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 35e2d3edc4f..f8ddc2f82aa 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -278,7 +278,7 @@
(define_insn "*tmqi_ext"
[(set (reg 33)
- (compare (zero_extract:SI (match_operand:QI 0 "s_operand" "Qo")
+ (compare (zero_extract:SI (match_operand:QI 0 "s_operand" "Q")
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))
(const_int 0)))]
@@ -345,7 +345,7 @@
(define_insn "*tmdi_mem"
[(set (reg 33)
- (compare (and:DI (match_operand:DI 0 "s_operand" "%Qo")
+ (compare (and:DI (match_operand:DI 0 "s_operand" "%Q")
(match_operand:DI 1 "immediate_operand" "n"))
(match_operand:DI 2 "immediate_operand" "n")))]
"TARGET_64BIT
@@ -365,7 +365,7 @@
(define_insn "*tmsi_mem"
[(set (reg 33)
- (compare (and:SI (match_operand:SI 0 "s_operand" "%Qo")
+ (compare (and:SI (match_operand:SI 0 "s_operand" "%Q")
(match_operand:SI 1 "immediate_operand" "n"))
(match_operand:SI 2 "immediate_operand" "n")))]
"s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
@@ -384,7 +384,7 @@
(define_insn "*tmhi_mem"
[(set (reg 33)
- (compare (and:SI (subreg:SI (match_operand:HI 0 "s_operand" "%Qo") 0)
+ (compare (and:SI (subreg:SI (match_operand:HI 0 "s_operand" "%Q") 0)
(match_operand:SI 1 "immediate_operand" "n"))
(match_operand:SI 2 "immediate_operand" "n")))]
"s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
@@ -403,7 +403,7 @@
(define_insn "*tmqi_mem"
[(set (reg 33)
- (compare (and:SI (subreg:SI (match_operand:QI 0 "s_operand" "%Qo") 0)
+ (compare (and:SI (subreg:SI (match_operand:QI 0 "s_operand" "%Q") 0)
(match_operand:SI 1 "immediate_operand" "n"))
(match_operand:SI 2 "immediate_operand" "n")))]
"s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))"
@@ -502,7 +502,7 @@
(define_insn "*tsthi"
[(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "Qo")
+ (compare (match_operand:HI 0 "s_operand" "Q")
(match_operand:HI 1 "const0_operand" "")))
(set (match_operand:HI 2 "register_operand" "=d")
(match_dup 0))]
@@ -513,7 +513,7 @@
(define_insn "*tsthi_cconly"
[(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "Qo")
+ (compare (match_operand:HI 0 "s_operand" "Q")
(match_operand:HI 1 "const0_operand" "")))
(clobber (match_scratch:HI 2 "=d"))]
"s390_match_ccmode(insn, CCSmode)"
@@ -523,7 +523,7 @@
(define_insn "*tstqi"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Qo")
+ (compare (match_operand:QI 0 "s_operand" "Q")
(match_operand:QI 1 "const0_operand" "")))
(set (match_operand:QI 2 "register_operand" "=d")
(match_dup 0))]
@@ -534,7 +534,7 @@
(define_insn "*tstqi_cconly"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Qo")
+ (compare (match_operand:QI 0 "s_operand" "Q")
(match_operand:QI 1 "const0_operand" "")))
(clobber (match_scratch:QI 2 "=d"))]
"s390_match_ccmode(insn, CCSmode)"
@@ -628,7 +628,7 @@
(define_insn "*cmphi_ccu"
[(set (reg 33)
(compare (match_operand:HI 0 "register_operand" "d")
- (match_operand:HI 1 "s_imm_operand" "Qo")))]
+ (match_operand:HI 1 "s_imm_operand" "Q")))]
"s390_match_ccmode(insn, CCUmode)"
"clm\\t%0,3,%1"
[(set_attr "op_type" "RS")
@@ -637,7 +637,7 @@
(define_insn "*cmpqi_ccu"
[(set (reg 33)
(compare (match_operand:QI 0 "register_operand" "d")
- (match_operand:QI 1 "s_imm_operand" "Qo")))]
+ (match_operand:QI 1 "s_imm_operand" "Q")))]
"s390_match_ccmode(insn, CCUmode)"
"clm\\t%0,1,%1"
[(set_attr "op_type" "RS")
@@ -645,7 +645,7 @@
(define_insn "*cli"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Qo")
+ (compare (match_operand:QI 0 "s_operand" "Q")
(match_operand:QI 1 "immediate_operand" "n")))]
"s390_match_ccmode (insn, CCUmode)"
"cli\\t%0,%b1"
@@ -654,8 +654,8 @@
(define_insn "*cmpdi_ccu_mem"
[(set (reg 33)
- (compare (match_operand:DI 0 "s_operand" "oQ")
- (match_operand:DI 1 "s_imm_operand" "oQ")))]
+ (compare (match_operand:DI 0 "s_operand" "Q")
+ (match_operand:DI 1 "s_imm_operand" "Q")))]
"s390_match_ccmode(insn, CCUmode)"
"clc\\t%O0(8,%R0),%1"
[(set_attr "op_type" "SS")
@@ -663,8 +663,8 @@
(define_insn "*cmpsi_ccu_mem"
[(set (reg 33)
- (compare (match_operand:SI 0 "s_operand" "oQ")
- (match_operand:SI 1 "s_imm_operand" "oQ")))]
+ (compare (match_operand:SI 0 "s_operand" "Q")
+ (match_operand:SI 1 "s_imm_operand" "Q")))]
"s390_match_ccmode(insn, CCUmode)"
"clc\\t%O0(4,%R0),%1"
[(set_attr "op_type" "SS")
@@ -672,8 +672,8 @@
(define_insn "*cmphi_ccu_mem"
[(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "oQ")
- (match_operand:HI 1 "s_imm_operand" "oQ")))]
+ (compare (match_operand:HI 0 "s_operand" "Q")
+ (match_operand:HI 1 "s_imm_operand" "Q")))]
"s390_match_ccmode(insn, CCUmode)"
"clc\\t%O0(2,%R0),%1"
[(set_attr "op_type" "SS")
@@ -681,8 +681,8 @@
(define_insn "*cmpqi_ccu_mem"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "oQ")
- (match_operand:QI 1 "s_imm_operand" "oQ")))]
+ (compare (match_operand:QI 0 "s_operand" "Q")
+ (match_operand:QI 1 "s_imm_operand" "Q")))]
"s390_match_ccmode(insn, CCUmode)"
"clc\\t%O0(1,%R0),%1"
[(set_attr "op_type" "SS")
@@ -780,8 +780,8 @@
;
(define_insn "*movti_ss"
- [(set (match_operand:TI 0 "s_operand" "=Qo")
- (match_operand:TI 1 "s_imm_operand" "Qo"))]
+ [(set (match_operand:TI 0 "s_operand" "=Q")
+ (match_operand:TI 1 "s_imm_operand" "Q"))]
""
"mvc\\t%O0(16,%R0),%1"
[(set_attr "op_type" "SS")
@@ -914,8 +914,8 @@
(set_attr "type" "la")])
(define_insn "*movdi_ss"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
- (match_operand:DI 1 "s_imm_operand" "Qo"))]
+ [(set (match_operand:DI 0 "s_operand" "=Q")
+ (match_operand:DI 1 "s_imm_operand" "Q"))]
""
"mvc\\t%O0(8,%R0),%1"
[(set_attr "op_type" "SS")
@@ -1067,8 +1067,8 @@
[(set_attr "op_type" "RI")])
(define_insn "*movsi_ss"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
- (match_operand:SI 1 "s_imm_operand" "Qo"))]
+ [(set (match_operand:SI 0 "s_operand" "=Q")
+ (match_operand:SI 1 "s_imm_operand" "Q"))]
""
"mvc\\t%O0(4,%R0),%1"
[(set_attr "op_type" "SS")
@@ -1156,7 +1156,7 @@
(define_insn "*movstricthi"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
- (match_operand:HI 1 "s_imm_operand" "Qo"))
+ (match_operand:HI 1 "s_imm_operand" "Q"))
(clobber (reg:CC 33))]
""
"icm\\t%0,3,%1"
@@ -1197,8 +1197,8 @@
}")
(define_insn "*movdf_ss"
- [(set (match_operand:DF 0 "s_operand" "=Qo")
- (match_operand:DF 1 "s_imm_operand" "Qo"))]
+ [(set (match_operand:DF 0 "s_operand" "=Q")
+ (match_operand:DF 1 "s_imm_operand" "Q"))]
""
"mvc\\t%O0(8,%R0),%1"
[(set_attr "op_type" "SS")
@@ -1300,8 +1300,8 @@
}")
(define_insn "*movsf_ss"
- [(set (match_operand:SF 0 "s_operand" "=Qo")
- (match_operand:SF 1 "s_imm_operand" "Qo"))]
+ [(set (match_operand:SF 0 "s_operand" "=Q")
+ (match_operand:SF 1 "s_imm_operand" "Q"))]
""
"mvc\\t%O0(4,%R0),%1"
[(set_attr "op_type" "SS")
@@ -1388,7 +1388,7 @@
(define_insn "*load_multiple_di"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:DI 1 "register_operand" "=r")
- (match_operand:DI 2 "s_operand" "oQ"))])]
+ (match_operand:DI 2 "s_operand" "Q"))])]
""
"*
{
@@ -1407,7 +1407,7 @@
(define_insn "*load_multiple_si"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "register_operand" "=r")
- (match_operand:SI 2 "s_operand" "oQ"))])]
+ (match_operand:SI 2 "s_operand" "Q"))])]
""
"*
{
@@ -1491,7 +1491,7 @@
(define_insn "*store_multiple_di"
[(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:DI 1 "s_operand" "=oQ")
+ [(set (match_operand:DI 1 "s_operand" "=Q")
(match_operand:DI 2 "register_operand" "r"))])]
""
"*
@@ -1511,7 +1511,7 @@
(define_insn "*store_multiple_si"
[(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_operand" "=oQ")
+ [(set (match_operand:SI 1 "s_operand" "=Q")
(match_operand:SI 2 "register_operand" "r"))])]
""
"*
@@ -1697,8 +1697,8 @@
; The block length is taken as (operands[2] % 256) + 1.
(define_insn "movstrdi_short"
- [(set (match_operand:BLK 0 "s_operand" "=oQ,oQ")
- (match_operand:BLK 1 "s_operand" "oQ,oQ"))
+ [(set (match_operand:BLK 0 "s_operand" "=Q,Q")
+ (match_operand:BLK 1 "s_operand" "Q,Q"))
(use (match_operand:DI 2 "nonmemory_operand" "n,a"))
(clobber (match_scratch:DI 3 "=X,&a"))]
"TARGET_64BIT"
@@ -1723,8 +1723,8 @@
(set_attr "length" "*,14")])
(define_insn "movstrsi_short"
- [(set (match_operand:BLK 0 "s_operand" "=oQ,oQ")
- (match_operand:BLK 1 "s_operand" "oQ,oQ"))
+ [(set (match_operand:BLK 0 "s_operand" "=Q,Q")
+ (match_operand:BLK 1 "s_operand" "Q,Q"))
(use (match_operand:SI 2 "nonmemory_operand" "n,a"))
(clobber (match_scratch:SI 3 "=X,&a"))]
"!TARGET_64BIT"
@@ -1927,7 +1927,7 @@
; Clear memory with length less than 256 bytes
(define_insn "clrstrsico"
- [(set (match_operand:BLK 0 "s_operand" "=Qo")
+ [(set (match_operand:BLK 0 "s_operand" "=Q")
(const_int 0))
(use (match_operand 1 "immediate_operand" "I"))
(clobber (reg:CC 33))]
@@ -2111,8 +2111,8 @@
(define_insn "cmpstr_const"
[(set (reg:CCS 33)
- (compare:CCS (match_operand:BLK 0 "s_operand" "oQ")
- (match_operand:BLK 1 "s_operand" "oQ")))
+ (compare:CCS (match_operand:BLK 0 "s_operand" "Q")
+ (match_operand:BLK 1 "s_operand" "Q")))
(use (match_operand 2 "immediate_operand" "I"))]
"(unsigned) INTVAL (operands[2]) < 256"
"clc\\t%O0(%c2,%R0),%1"
@@ -2193,7 +2193,7 @@
(define_insn "*sethighqisi"
[(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+ (unspec:SI [(match_operand:QI 1 "s_operand" "Q")] 10))
(clobber (reg:CC 33))]
""
"icm\\t%0,8,%1"
@@ -2202,7 +2202,7 @@
(define_insn "*sethighhisi"
[(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(match_operand:HI 1 "s_operand" "Qo")] 10))
+ (unspec:SI [(match_operand:HI 1 "s_operand" "Q")] 10))
(clobber (reg:CC 33))]
""
"icm\\t%0,12,%1"
@@ -2211,7 +2211,7 @@
(define_insn "*sethighqidi_64"
[(set (match_operand:DI 0 "register_operand" "=d")
- (unspec:DI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+ (unspec:DI [(match_operand:QI 1 "s_operand" "Q")] 10))
(clobber (reg:CC 33))]
"TARGET_64BIT"
"icmh\\t%0,8,%1"
@@ -2220,7 +2220,7 @@
(define_insn "*sethighqidi_31"
[(set (match_operand:DI 0 "register_operand" "=d")
- (unspec:DI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+ (unspec:DI [(match_operand:QI 1 "s_operand" "Q")] 10))
(clobber (reg:CC 33))]
"!TARGET_64BIT"
"icm\\t%0,8,%1"
@@ -4486,9 +4486,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*anddi3_ss"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
(and:DI (match_dup 0)
- (match_operand:DI 1 "s_imm_operand" "Qo")))
+ (match_operand:DI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"nc\\t%O0(8,%R0),%1"
@@ -4496,8 +4496,8 @@
(set_attr "atype" "mem")])
(define_insn "*anddi3_ss_inv"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
- (and:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
+ (and:DI (match_operand:DI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4570,9 +4570,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*andsi3_ss"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
(and:SI (match_dup 0)
- (match_operand:SI 1 "s_imm_operand" "Qo")))
+ (match_operand:SI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"nc\\t%O0(4,%R0),%1"
@@ -4580,8 +4580,8 @@
(set_attr "atype" "mem")])
(define_insn "*andsi3_ss_inv"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
- (and:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
+ (and:SI (match_operand:SI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4616,9 +4616,9 @@
(set_attr "atype" "reg")])
(define_insn "*andhi3_ss"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
(and:HI (match_dup 0)
- (match_operand:HI 1 "s_imm_operand" "Qo")))
+ (match_operand:HI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"nc\\t%O0(2,%R0),%1"
@@ -4626,8 +4626,8 @@
(set_attr "atype" "mem")])
(define_insn "*andhi3_ss_inv"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
- (and:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
+ (and:HI (match_operand:HI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4662,9 +4662,9 @@
(set_attr "atype" "reg")])
(define_insn "*andqi3_ss"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
(and:QI (match_dup 0)
- (match_operand:QI 1 "s_imm_operand" "n,Qo")))
+ (match_operand:QI 1 "s_imm_operand" "n,Q")))
(clobber (reg:CC 33))]
""
"@
@@ -4674,8 +4674,8 @@
(set_attr "atype" "mem")])
(define_insn "*andqi3_ss_inv"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
- (and:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
+ (and:QI (match_operand:QI 1 "s_imm_operand" "n,Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4757,9 +4757,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*iordi3_ss"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
(ior:DI (match_dup 0)
- (match_operand:DI 1 "s_imm_operand" "Qo")))
+ (match_operand:DI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"oc\\t%O0(8,%R0),%1"
@@ -4767,8 +4767,8 @@
(set_attr "atype" "mem")])
(define_insn "*iordi3_ss_inv"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
- (ior:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
+ (ior:DI (match_operand:DI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4841,9 +4841,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*iorsi3_ss"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
(ior:SI (match_dup 0)
- (match_operand:SI 1 "s_imm_operand" "Qo")))
+ (match_operand:SI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"oc\\t%O0(4,%R0),%1"
@@ -4851,8 +4851,8 @@
(set_attr "atype" "mem")])
(define_insn "*iorsi3_ss_inv"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
- (ior:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
+ (ior:SI (match_operand:SI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4887,9 +4887,9 @@
(set_attr "atype" "reg")])
(define_insn "*iorhi3_ss"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
(ior:HI (match_dup 0)
- (match_operand:HI 1 "s_imm_operand" "Qo")))
+ (match_operand:HI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"oc\\t%O0(2,%R0),%1"
@@ -4897,8 +4897,8 @@
(set_attr "atype" "mem")])
(define_insn "*iorhi3_ss_inv"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
- (ior:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
+ (ior:HI (match_operand:HI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4933,9 +4933,9 @@
(set_attr "atype" "reg")])
(define_insn "*iorqi3_ss"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
(ior:QI (match_dup 0)
- (match_operand:QI 1 "s_imm_operand" "n,Qo")))
+ (match_operand:QI 1 "s_imm_operand" "n,Q")))
(clobber (reg:CC 33))]
""
"@
@@ -4945,8 +4945,8 @@
(set_attr "atype" "reg,mem")])
(define_insn "*iorqi3_ss_inv"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
- (ior:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
+ (ior:QI (match_operand:QI 1 "s_imm_operand" "n,Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -5005,9 +5005,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*xordi3_ss"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
(xor:DI (match_dup 0)
- (match_operand:DI 1 "s_imm_operand" "Qo")))
+ (match_operand:DI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"xc\\t%O0(8,%R0),%1"
@@ -5015,8 +5015,8 @@
(set_attr "atype" "mem")])
(define_insn "*xordi3_ss_inv"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
- (xor:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
+ (xor:DI (match_operand:DI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -5068,9 +5068,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*xorsi3_ss"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
(xor:SI (match_dup 0)
- (match_operand:SI 1 "s_imm_operand" "Qo")))
+ (match_operand:SI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"xc\\t%O0(4,%R0),%1"
@@ -5078,8 +5078,8 @@
(set_attr "atype" "mem")])
(define_insn "*xorsi3_ss_inv"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
- (xor:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
+ (xor:SI (match_operand:SI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -5102,9 +5102,9 @@
(set_attr "atype" "reg")])
(define_insn "*xorhi3_ss"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
(xor:HI (match_dup 0)
- (match_operand:HI 1 "s_imm_operand" "Qo")))
+ (match_operand:HI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"xc\\t%O0(2,%R0),%1"
@@ -5112,8 +5112,8 @@
(set_attr "atype" "mem")])
(define_insn "*xorhi3_ss_inv"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
- (xor:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
+ (xor:HI (match_operand:HI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -5136,9 +5136,9 @@
(set_attr "atype" "reg")])
(define_insn "*xorqi3_ss"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
(xor:QI (match_dup 0)
- (match_operand:QI 1 "s_imm_operand" "n,Qo")))
+ (match_operand:QI 1 "s_imm_operand" "n,Q")))
(clobber (reg:CC 33))]
""
"@
@@ -5148,8 +5148,8 @@
(set_attr "atype" "mem")])
(define_insn "*xorqi3_ss_inv"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
- (xor:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
+ (xor:QI (match_operand:QI 1 "s_imm_operand" "n,Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 115cc01b403..ae115b887fd 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -590,4 +590,16 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
#define DEFAULT_USE_CXA_ATEXIT 0
#endif
+/* Determine whether extra constraint letter should be handled
+ via address reload (like 'o'). */
+#ifndef EXTRA_MEMORY_CONSTRAINT
+#define EXTRA_MEMORY_CONSTRAINT(C) 0
+#endif
+
+/* Determine whether extra constraint letter should be handled
+ as an address (like 'p'). */
+#ifndef EXTRA_ADDRESS_CONSTRAINT
+#define EXTRA_ADDRESS_CONSTRAINT(C) 0
+#endif
+
#endif /* ! GCC_DEFAULTS_H */
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index d13b53ee4a4..064120d639a 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -2614,6 +2614,44 @@ letter @samp{Q} is defined as representing a memory address that does
a @samp{Q} constraint on the input and @samp{r} on the output. The next
alternative specifies @samp{m} on the input and a register class that
does not include r0 on the output.
+
+@findex EXTRA_MEMORY_CONSTRAINT
+@item EXTRA_MEMORY_CONSTRAINT (@var{c})
+A C expression that defines the optional machine-dependent constraint
+letters, amongst those accepted by @code{EXTRA_CONSTRAINT}, that should
+be treated like memory constraints by the reload pass.
+
+It should return 1 if the operand type represented by the constraint
+letter @var{c} comprises a subset of all memory references including
+all those whose address is simply a base register. This allows the reload
+pass to reload an operand, if it does not directly correspond to the operand
+type of @var{c}, by copying its address into a base register.
+
+For example, on the S/390, some instructions do not accept arbitrary
+memory references, but only those that do not make use of an index
+register. The constraint letter @samp{Q} is defined via
+@code{EXTRA_CONSTRAINT} as representing a memory address of this type.
+If the letter @samp{Q} is marked as @code{EXTRA_MEMORY_CONSTRAINT},
+a @samp{Q} constraint can handle any memory operand, because the
+reload pass knows it can be reloaded by copying the memory address
+into a base register if required. This is analogous to the way
+a @samp{o} constraint can handle any memory operand.
+
+@findex EXTRA_ADDRESS_CONSTRAINT
+@item EXTRA_ADDRESS_CONSTRAINT (@var{c})
+A C expression that defines the optional machine-dependent constraint
+letters, amongst those accepted by @code{EXTRA_CONSTRAINT}, that should
+be treated like address constraints by the reload pass.
+
+It should return 1 if the operand type represented by the constraint
+letter @var{c} comprises a subset of all memory addresses including
+all those that consist of just a base register. This allows the reload
+pass to reload an operand, if it does not directly correspond to the operand
+type of @var{c}, by copying it into a base register.
+
+Any constraint marked as @code{EXTRA_ADDRESS_CONSTRAINT} can only
+be used with the @code{address_operand} predicate. It is treated
+analogously to the @samp{p} constraint.
@end table
@node Stack and Calling
diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c
index 77607ba74be..04e2fbe5a4c 100644
--- a/gcc/local-alloc.c
+++ b/gcc/local-alloc.c
@@ -1342,7 +1342,8 @@ block_alloc (b)
/* If the operand is an address, find a register in it.
There may be more than one register, but we only try one
of them. */
- if (recog_data.constraints[i][0] == 'p')
+ if (recog_data.constraints[i][0] == 'p'
+ || EXTRA_ADDRESS_CONSTRAINT (recog_data.constraints[i][0]))
while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
r1 = XEXP (r1, 0);
@@ -2472,7 +2473,8 @@ requires_inout (p)
break;
default:
- if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
+ if (REG_CLASS_FROM_LETTER (c) == NO_REGS
+ && !EXTRA_ADDRESS_CONSTRAINT (c))
break;
/* FALLTHRU */
case 'p':
diff --git a/gcc/recog.c b/gcc/recog.c
index c56069a053c..6bb8670e166 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -1848,6 +1848,18 @@ asm_operand_ok (op, constraint)
#ifdef EXTRA_CONSTRAINT
if (EXTRA_CONSTRAINT (op, c))
return 1;
+ if (EXTRA_MEMORY_CONSTRAINT (c))
+ {
+ /* Every memory operand can be reloaded to fit. */
+ if (memory_operand (op, VOIDmode))
+ return 1;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ {
+ /* Every address operand can be reloaded to fit. */
+ if (address_operand (op, VOIDmode))
+ return 1;
+ }
#endif
break;
}
@@ -2287,6 +2299,19 @@ preprocess_constraints ()
break;
default:
+ if (EXTRA_MEMORY_CONSTRAINT (c))
+ {
+ op_alt[j].memory_ok = 1;
+ break;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ {
+ op_alt[j].is_address = 1;
+ op_alt[j].class = reg_class_subunion[(int) op_alt[j].class]
+ [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ break;
+ }
+
op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
break;
}
@@ -2600,6 +2625,28 @@ constrain_operands (strict)
#ifdef EXTRA_CONSTRAINT
else if (EXTRA_CONSTRAINT (op, c))
win = 1;
+
+ if (EXTRA_MEMORY_CONSTRAINT (c))
+ {
+ /* Every memory operand can be reloaded to fit,
+ so copy the condition from the 'm' case. */
+ if (GET_CODE (op) == MEM
+ /* Before reload, accept what reload can turn into mem. */
+ || (strict < 0 && CONSTANT_P (op))
+ /* During reload, accept a pseudo */
+ || (reload_in_progress && GET_CODE (op) == REG
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER))
+ win = 1;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ {
+ /* Every address operand can be reloaded to fit,
+ so copy the condition from the 'p' case. */
+ if (strict <= 0
+ || (strict_memory_address_p (recog_data.operand_mode[opno],
+ op)))
+ win = 1;
+ }
#endif
break;
}
diff --git a/gcc/regclass.c b/gcc/regclass.c
index 1451f8a4a75..75335b16030 100644
--- a/gcc/regclass.c
+++ b/gcc/regclass.c
@@ -1007,7 +1007,8 @@ record_operand_costs (insn, op_costs, reg_pref)
if (GET_CODE (recog_data.operand[i]) == MEM)
record_address_regs (XEXP (recog_data.operand[i], 0),
MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
- else if (constraints[i][0] == 'p')
+ else if (constraints[i][0] == 'p'
+ || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
record_address_regs (recog_data.operand[i],
MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
}
@@ -1709,6 +1710,27 @@ record_reg_classes (n_alts, n_ops, ops, modes,
#ifdef EXTRA_CONSTRAINT
else if (EXTRA_CONSTRAINT (op, c))
win = 1;
+
+ if (EXTRA_MEMORY_CONSTRAINT (c))
+ {
+ /* Every MEM can be reloaded to fit. */
+ allows_mem[i] = 1;
+ if (GET_CODE (op) == MEM)
+ win = 1;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (op))
+ {
+ /* Every address can be reloaded to fit. */
+ allows_addr = 1;
+ if (address_operand (op, GET_MODE (op)))
+ win = 1;
+ /* We know this operand is an address, so we want it to be
+ allocated to a register that can be the base of an
+ address, ie BASE_REG_CLASS. */
+ classes[i]
+ = reg_class_subunion[(int) classes[i]]
+ [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ }
#endif
break;
}
diff --git a/gcc/reload.c b/gcc/reload.c
index 41d671d3146..67f411b9040 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -2641,7 +2641,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (*constraints[i] == 0)
/* Ignore things like match_operator operands. */
;
- else if (constraints[i][0] == 'p')
+ else if (constraints[i][0] == 'p'
+ || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
{
find_reloads_address (VOIDmode, (rtx*) 0,
recog_data.operand[i],
@@ -3222,6 +3223,49 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
{
#ifdef EXTRA_CONSTRAINT
+ if (EXTRA_MEMORY_CONSTRAINT (c))
+ {
+ if (force_reload)
+ break;
+ if (EXTRA_CONSTRAINT (operand, c))
+ win = 1;
+ /* If the address was already reloaded,
+ we win as well. */
+ if (GET_CODE (operand) == MEM && address_reloaded[i])
+ win = 1;
+ /* Likewise if the address will be reloaded because
+ reg_equiv_address is nonzero. For reg_equiv_mem
+ we have to check. */
+ if (GET_CODE (operand) == REG
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[REGNO (operand)] < 0
+ && ((reg_equiv_mem[REGNO (operand)] != 0
+ && EXTRA_CONSTRAINT (reg_equiv_mem[REGNO (operand)], c))
+ || (reg_equiv_address[REGNO (operand)] != 0)))
+ win = 1;
+
+ /* If we didn't already win, we can reload
+ constants via force_const_mem, and other
+ MEMs by reloading the address like for 'o'. */
+ if ((CONSTANT_P (operand) && GET_CODE (operand) != HIGH)
+ || GET_CODE (operand) == MEM)
+ badop = 0;
+ constmemok = 1;
+ offmemok = 1;
+ break;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ {
+ if (EXTRA_CONSTRAINT (operand, c))
+ win = 1;
+
+ /* If we didn't already win, we can reload
+ the address into a base register. */
+ this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
+ badop = 0;
+ break;
+ }
+
if (EXTRA_CONSTRAINT (operand, c))
win = 1;
#endif
@@ -4291,7 +4335,7 @@ alternative_allows_memconst (constraint, altnum)
/* Scan the requested alternative for 'm' or 'o'.
If one of them is present, this alternative accepts memory constants. */
while ((c = *constraint++) && c != ',' && c != '#')
- if (c == 'm' || c == 'o')
+ if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c))
return 1;
return 0;
}
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 23ab50f1570..58b0bd04bce 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -1380,8 +1380,12 @@ maybe_fix_stack_asms ()
break;
default:
- cls = (int) reg_class_subunion[cls][(int) REG_CLASS_FROM_LETTER (c)];
-
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ cls = (int) reg_class_subunion[cls]
+ [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ else
+ cls = (int) reg_class_subunion[cls]
+ [(int) REG_CLASS_FROM_LETTER (c)];
}
}
}
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 550e3e7e238..b2e2cad28c2 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -1252,6 +1252,10 @@ parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
if (REG_CLASS_FROM_LETTER (*p) != NO_REGS)
*allows_reg = true;
#ifdef EXTRA_CONSTRAINT
+ else if (EXTRA_ADDRESS_CONSTRAINT (*p))
+ *allows_reg = true;
+ else if (EXTRA_MEMORY_CONSTRAINT (*p))
+ *allows_mem = true;
else
{
/* Otherwise we can't assume anything about the nature of
@@ -1377,6 +1381,10 @@ parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
*allows_reg = true;
#ifdef EXTRA_CONSTRAINT
+ else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j]))
+ *allows_reg = true;
+ else if (EXTRA_MEMORY_CONSTRAINT (constraint[j]))
+ *allows_mem = true;
else
{
/* Otherwise we can't assume anything about the nature of