diff options
author | uweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-08-14 10:04:51 +0000 |
---|---|---|
committer | uweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-08-14 10:04:51 +0000 |
commit | a5004c3da9d0b789d68611ec00a1f59d8f62761b (patch) | |
tree | f8955f2da7788407bd35a092c0a414ccd029de11 /gcc | |
parent | c363d230bc0490ec67a7726707d6eea248e5d5c4 (diff) | |
download | gcc-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/ChangeLog | 27 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 31 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 4 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 188 | ||||
-rw-r--r-- | gcc/defaults.h | 12 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 38 | ||||
-rw-r--r-- | gcc/local-alloc.c | 6 | ||||
-rw-r--r-- | gcc/recog.c | 47 | ||||
-rw-r--r-- | gcc/regclass.c | 24 | ||||
-rw-r--r-- | gcc/reload.c | 48 | ||||
-rw-r--r-- | gcc/reload1.c | 8 | ||||
-rw-r--r-- | gcc/stmt.c | 8 |
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 |