diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2002-02-04 15:51:18 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@gcc.gnu.org> | 2002-02-04 15:51:18 +0000 |
commit | f3e9edff6a370713067611836309c614a7a6b66a (patch) | |
tree | 7b439dbd1120cc295cc4e3e8cbffe9eac9defac0 /gcc | |
parent | 3c9a08ec8e37707e3e973bfc419067937ebb9a20 (diff) | |
download | gcc-f3e9edff6a370713067611836309c614a7a6b66a.zip gcc-f3e9edff6a370713067611836309c614a7a6b66a.tar.gz gcc-f3e9edff6a370713067611836309c614a7a6b66a.tar.bz2 |
s390-protos.h (legitimize_la_operand, [...]): Add prototypes.
* config/s390/s390-protos.h (legitimize_la_operand,
s390_secondary_input_reload_class, s390_plus_operand,
s390_expand_plus_operand): Add prototypes.
config/s390/s390.c (s390_secondary_input_reload_class,
s390_plus_operand, s390_expand_plus_operand): New functions.
(struct s390_address): New member 'pointer'.
(s390_decompose_address): Compute it.
(legitimate_la_operand_p): Use it.
(legitimize_la_operand): New function.
(movti, movdi, movdf splitters): Call it.
config/s390/s390.h (SECONDARY_INPUT_RELOAD_CLASS): Define.
(PREDICATE_CODES): Add s390_plus_operand.
config/s390/s390.md (adddi3_inv_64, addaddr_ccclobber): Delete.
(la_ccclobber): Allow GENERAL_REGS as output operand.
(reload_load_address, *reload_load_address_reg_0, *la, *do_la_reg_0,
*reload_la_64, *reload_la_31 and splitters): Delete, replace by ...
(*la_64, *la_31, reload_indi, reload_insi): ... these.
From-SVN: r49476
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 25 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 175 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 9 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 162 |
5 files changed, 217 insertions, 158 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 43c4703..19dd639 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,30 @@ 2002-02-04 Ulrich Weigand <uweigand@de.ibm.com> + * config/s390/s390-protos.h (legitimize_la_operand, + s390_secondary_input_reload_class, s390_plus_operand, + s390_expand_plus_operand): Add prototypes. + + config/s390/s390.c (s390_secondary_input_reload_class, + s390_plus_operand, s390_expand_plus_operand): New functions. + + (struct s390_address): New member 'pointer'. + (s390_decompose_address): Compute it. + (legitimate_la_operand_p): Use it. + (legitimize_la_operand): New function. + (movti, movdi, movdf splitters): Call it. + + config/s390/s390.h (SECONDARY_INPUT_RELOAD_CLASS): Define. + (PREDICATE_CODES): Add s390_plus_operand. + + config/s390/s390.md (adddi3_inv_64, addaddr_ccclobber): Delete. + (la_ccclobber): Allow GENERAL_REGS as output operand. + + (reload_load_address, *reload_load_address_reg_0, *la, *do_la_reg_0, + *reload_la_64, *reload_la_31 and splitters): Delete, replace by ... + (*la_64, *la_31, reload_indi, reload_insi): ... these. + +2002-02-04 Ulrich Weigand <uweigand@de.ibm.com> + * gcc/config/s390/s390.h (CRT_CALL_STATIC_FUNCTION): Fixed register names for regular asm () construct. diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index b426dac..2ab387a 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -48,6 +48,7 @@ extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode)); extern enum machine_mode s390_select_ccmode PARAMS ((enum rtx_code, rtx, rtx)); extern int symbolic_reference_mentioned_p PARAMS ((rtx)); extern int legitimate_la_operand_p PARAMS ((rtx)); +extern rtx legitimize_la_operand PARAMS ((rtx)); extern int legitimate_pic_operand_p PARAMS ((rtx)); extern int legitimate_constant_p PARAMS ((rtx)); extern int legitimate_reload_constant_p PARAMS ((rtx)); @@ -55,6 +56,9 @@ extern int legitimate_address_p PARAMS ((enum machine_mode, rtx, int)); extern rtx legitimize_pic_address PARAMS ((rtx, rtx)); extern rtx legitimize_address PARAMS ((rtx, rtx, enum machine_mode)); extern enum reg_class s390_preferred_reload_class PARAMS ((rtx, enum reg_class)); +extern enum reg_class s390_secondary_input_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx)); +extern int s390_plus_operand PARAMS ((rtx, enum machine_mode)); +extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx)); extern void emit_pic_move PARAMS ((rtx *, enum machine_mode)); extern void s390_output_symbolic_const PARAMS ((FILE *, rtx)); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 2cf2e41..0167ab8 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -103,6 +103,7 @@ struct s390_address rtx base; rtx indx; rtx disp; + int pointer; }; /* Structure containing information for prologue and epilogue. */ @@ -1125,6 +1126,107 @@ s390_preferred_reload_class (op, class) return class; } +/* Return the register class of a scratch register needed to + load IN into a register of class CLASS in MODE. + + We need a temporary when loading a PLUS expression which + is not a legitimate operand of the LOAD ADDRESS instruction. */ + +enum reg_class +s390_secondary_input_reload_class (class, mode, in) + enum reg_class class ATTRIBUTE_UNUSED; + enum machine_mode mode; + rtx in; +{ + if (s390_plus_operand (in, mode)) + return ADDR_REGS; + + return NO_REGS; +} + +/* Return true if OP is a PLUS that is not a legitimate + operand for the LA instruction. + OP is the current operation. + MODE is the current operation mode. */ + +int +s390_plus_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + if (!check_mode (op, &mode) || mode != Pmode) + return FALSE; + + if (GET_CODE (op) != PLUS) + return FALSE; + + if (legitimate_la_operand_p (op)) + return FALSE; + + return TRUE; +} + +/* Generate code to load SRC, which is PLUS that is not a + legitimate operand for the LA instruction, into TARGET. + SCRATCH may be used as scratch register. */ + +void +s390_expand_plus_operand (target, src, scratch) + register rtx target; + register rtx src; + register rtx scratch; +{ + /* src must be a PLUS; get its two operands. */ + rtx sum1, sum2; + + if (GET_CODE (src) != PLUS || GET_MODE (src) != Pmode) + abort (); + + sum1 = XEXP (src, 0); + sum2 = XEXP (src, 1); + + /* If one of the two operands is equal to the target, + make it the first one. */ + if (rtx_equal_p (target, sum2)) + { + sum2 = XEXP (src, 0); + sum1 = XEXP (src, 1); + } + + /* If the first operand is not an address register, + we reload it into the target. */ + if (true_regnum (sum1) < 1 || true_regnum (sum1) > 15) + { + emit_move_insn (target, sum1); + sum1 = target; + } + + /* Likewise for the second operand. However, take + care not to clobber the target if we already used + it for the first operand. Use the scratch instead. */ + if (true_regnum (sum2) < 1 || true_regnum (sum2) > 15) + { + if (!rtx_equal_p (target, sum1)) + { + emit_move_insn (target, sum2); + sum2 = target; + } + else + { + emit_move_insn (scratch, sum2); + sum2 = scratch; + } + } + + /* Emit the LOAD ADDRESS pattern. Note that reload of PLUS + is only ever performed on addresses, so we can mark the + sum as legitimate for LA in any case. */ + src = gen_rtx_PLUS (Pmode, sum1, sum2); + src = legitimize_la_operand (src); + emit_insn (gen_rtx_SET (VOIDmode, target, src)); +} + + /* Decompose a RTL expression ADDR for a memory address into its components, returned in OUT. The boolean STRICT specifies whether strict register checking applies. @@ -1145,6 +1247,7 @@ s390_decompose_address (addr, out, strict) rtx base = NULL_RTX; rtx indx = NULL_RTX; rtx disp = NULL_RTX; + int pointer = FALSE; /* Decompose address into base + index + displacement. */ @@ -1198,6 +1301,7 @@ s390_decompose_address (addr, out, strict) if (XVECLEN (base, 0) != 1 || XINT (base, 1) != 101) return FALSE; base = XVECEXP (base, 0, 0); + pointer = TRUE; } if (GET_CODE (base) != REG || GET_MODE (base) != Pmode) @@ -1206,6 +1310,16 @@ s390_decompose_address (addr, out, strict) if ((strict && ! REG_OK_FOR_BASE_STRICT_P (base)) || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (base))) return FALSE; + + if (REGNO (base) == BASE_REGISTER + || REGNO (base) == STACK_POINTER_REGNUM + || REGNO (base) == FRAME_POINTER_REGNUM + || ((reload_completed || reload_in_progress) + && frame_pointer_needed + && REGNO (base) == HARD_FRAME_POINTER_REGNUM) + || (flag_pic + && REGNO (base) == PIC_OFFSET_TABLE_REGNUM)) + pointer = TRUE; } /* Validate index register. */ @@ -1216,6 +1330,7 @@ s390_decompose_address (addr, out, strict) if (XVECLEN (indx, 0) != 1 || XINT (indx, 1) != 101) return FALSE; indx = XVECEXP (indx, 0, 0); + pointer = TRUE; } if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode) @@ -1224,6 +1339,16 @@ s390_decompose_address (addr, out, strict) if ((strict && ! REG_OK_FOR_BASE_STRICT_P (indx)) || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (indx))) return FALSE; + + if (REGNO (indx) == BASE_REGISTER + || REGNO (indx) == STACK_POINTER_REGNUM + || REGNO (indx) == FRAME_POINTER_REGNUM + || ((reload_completed || reload_in_progress) + && frame_pointer_needed + && REGNO (indx) == HARD_FRAME_POINTER_REGNUM) + || (flag_pic + && REGNO (indx) == PIC_OFFSET_TABLE_REGNUM)) + pointer = TRUE; } /* Validate displacement. */ @@ -1244,6 +1369,8 @@ s390_decompose_address (addr, out, strict) { if (flag_pic != 1) return FALSE; + + pointer = TRUE; } /* We can convert literal pool addresses to @@ -1295,14 +1422,20 @@ s390_decompose_address (addr, out, strict) if (offset) disp = plus_constant (disp, offset); + + pointer = TRUE; } } + if (!base && !indx) + pointer = TRUE; + if (out) { out->base = base; out->indx = indx; out->disp = disp; + out->pointer = pointer; } return TRUE; @@ -1332,28 +1465,36 @@ legitimate_la_operand_p (op) if (!s390_decompose_address (op, &addr, FALSE)) return FALSE; - if (TARGET_64BIT) + if (TARGET_64BIT || addr.pointer) return TRUE; - /* Use of the base or stack pointer implies address. */ + return FALSE; +} - if (addr.base && GET_CODE (addr.base) == REG) - { - if (REGNO (addr.base) == BASE_REGISTER - || REGNO (addr.base) == STACK_POINTER_REGNUM - || REGNO (addr.base) == FRAME_POINTER_REGNUM) - return TRUE; - } +/* Return a modified variant of OP that is guaranteed to + be accepted by legitimate_la_operand_p. */ - if (addr.indx && GET_CODE (addr.indx) == REG) - { - if (REGNO (addr.indx) == BASE_REGISTER - || REGNO (addr.indx) == STACK_POINTER_REGNUM - || REGNO (addr.base) == FRAME_POINTER_REGNUM) - return TRUE; - } +rtx +legitimize_la_operand (op) + register rtx op; +{ + struct s390_address addr; + if (!s390_decompose_address (op, &addr, FALSE)) + abort (); - return FALSE; + if (TARGET_64BIT || addr.pointer) + return op; + + if (!addr.base) + abort (); + + op = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr.base), 101); + if (addr.indx) + op = gen_rtx_PLUS (Pmode, op, addr.indx); + if (addr.disp) + op = gen_rtx_PLUS (Pmode, op, addr.disp); + + return op; } /* Return a legitimate reference for ORIG (an address) using the diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index f26cd65..f648505 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -577,6 +577,12 @@ extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; /* smalled class cont (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT ? 2 : 1) : \ (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) +/* We need a secondary reload when loading a PLUS which is + not a valid operand for LOAD ADDRESS. */ + +#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \ + s390_secondary_input_reload_class ((CLASS), (MODE), (IN)) + /* If we are copying between FP registers and anything else, we need a memory location. */ @@ -1293,7 +1299,8 @@ extern struct rtx_def *s390_compare_op0, *s390_compare_op1; {"larl_operand", { SYMBOL_REF, CONST, CONST_INT, CONST_DOUBLE }}, \ {"load_multiple_operation", {PARALLEL}}, \ {"store_multiple_operation", {PARALLEL}}, \ - {"const0_operand", { CONST_INT, CONST_DOUBLE }}, + {"const0_operand", { CONST_INT, CONST_DOUBLE }}, \ + {"s390_plus_operand", { PLUS }}, /* S/390 constant pool breaks the devices in crtstuff.c to control section diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 0208eff..905092b 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -867,7 +867,7 @@ [(set (match_dup 2) (match_dup 3)) (set (match_dup 0) (mem:TI (match_dup 2)))] "operands[2] = operand_subword (operands[0], 1, 0, TImode); - operands[3] = XEXP (operands[1], 0);") + operands[3] = legitimize_la_operand (XEXP (operands[1], 0));") ; ; movdi instruction pattern(s). @@ -1022,7 +1022,7 @@ [(set (match_dup 2) (match_dup 3)) (set (match_dup 0) (mem:DI (match_dup 2)))] "operands[2] = operand_subword (operands[0], 1, 0, DImode); - operands[3] = XEXP (operands[1], 0);") + operands[3] = legitimize_la_operand (XEXP (operands[1], 0));") ; ; movsi instruction pattern(s). @@ -1305,7 +1305,7 @@ [(set (match_dup 2) (match_dup 3)) (set (match_dup 0) (mem:DI (match_dup 2)))] "operands[2] = operand_subword (operands[0], 1, 0, DFmode); - operands[3] = XEXP (operands[1], 0);") + operands[3] = legitimize_la_operand (XEXP (operands[1], 0));") ; ; movsf instruction pattern(s). @@ -3093,23 +3093,6 @@ [(set_attr "op_type" "RRE,RI,RXE") (set_attr "atype" "reg,reg,mem")]) -; -; For weakness of reload, need (set (reg x) (plus (reg y) (reg x))) -; - -(define_insn "adddi3_inv_64" - [(set (match_operand:DI 0 "register_operand" "=d,d,d") - (plus:DI (match_operand:DI 1 "general_operand" "%d,K,m") - (match_operand:DI 2 "register_operand" "0,0,0") ) ) - (clobber (reg:CC 33))] - "TARGET_64BIT" - "@ - agr\\t%0,%1 - aghi\\t%0,%h1 - ag\\t%0,%1" - [(set_attr "op_type" "RRE,RI,RXE") - (set_attr "atype" "reg,reg,mem")]) - (define_insn "adddi3_31" [(set (match_operand:DI 0 "register_operand" "=d,d") (plus:DI (match_operand:DI 1 "register_operand" "0,0") @@ -3156,8 +3139,8 @@ DONE; }") -(define_insn "reload_load_address" - [(set (match_operand:DI 0 "register_operand" "=a") +(define_insn "*la_64" + [(set (match_operand:DI 0 "register_operand" "=d") (match_operand:QI 1 "address_operand" "p"))] "TARGET_64BIT" "la\\t%0,%a1" @@ -3165,65 +3148,24 @@ (set_attr "atype" "mem") (set_attr "type" "la")]) -(define_insn "*reload_load_address_reg_0" - [(set (match_operand:DI 0 "register_operand" "=d") - (plus:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "register_operand" "d")))] +(define_expand "reload_indi" + [(parallel [(match_operand:DI 0 "register_operand" "=a") + (match_operand:DI 1 "s390_plus_operand" "") + (match_operand:DI 2 "register_operand" "=&a")])] "TARGET_64BIT" - "brxlg\\t%0,%2,.+6" - [(set_attr "op_type" "RIE") - (set_attr "atype" "reg")]) - -(define_insn "*reload_la_64" - [(set (match_operand:DI 0 "register_operand" "=d") - (plus:DI (match_operand:DI 1 "general_operand" "g") - (match_operand:DI 2 "general_operand" "g")))] - "TARGET_64BIT && reload_in_progress - && !address_operand (gen_rtx_PLUS (DImode, operands[1], operands[2]), QImode) - && !rtx_equal_p (operands[0], operands[1]) - && !rtx_equal_p (operands[0], operands[2])" - "#") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "register_operand" "")))] - "TARGET_64BIT && reload_completed - && !address_operand (gen_rtx_PLUS (DImode, operands[1], operands[2]), QImode) - && !rtx_equal_p (operands[0], operands[1]) - && !rtx_equal_p (operands[0], operands[2])" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))] " { - if (CONSTANT_P (operands[1]) - && !legitimate_reload_constant_p (operands[1])) - operands[1] = force_const_mem (DImode, operands[1]); + s390_expand_plus_operand (operands[0], operands[1], operands[2]); + DONE; }") -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "general_operand" "")))] - "TARGET_64BIT && reload_completed - && !address_operand (gen_rtx_PLUS (DImode, operands[1], operands[2]), QImode) - && !rtx_equal_p (operands[0], operands[1]) - && !rtx_equal_p (operands[0], operands[2])" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))] - " -{ - if (CONSTANT_P (operands[2]) - && !legitimate_reload_constant_p (operands[2])) - operands[2] = force_const_mem (DImode, operands[2]); -}") ; ; addsi3 instruction pattern(s). ; (define_insn "*la_ccclobber" - [(set (match_operand:SI 0 "register_operand" "=a") + [(set (match_operand:SI 0 "register_operand" "=d") (match_operand:QI 1 "address_operand" "p")) (clobber (reg:CC 33))] "legitimate_la_operand_p (operands[1])" @@ -3232,23 +3174,6 @@ (set_attr "atype" "mem") (set_attr "type" "la")]) -(define_insn "*addaddr_ccclobber" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (plus:SI (match_operand:SI 1 "register_operand" "%a,a") - (match_operand:SI 2 "nonmemory_operand" "J,a"))) - (clobber (reg:CC 33))] - "(((REGNO (operands[1]) == STACK_POINTER_REGNUM ) || - (REGNO (operands[1]) == FRAME_POINTER_REGNUM ) || - (REGNO (operands[1]) == BASE_REGISTER)) && - (GET_CODE (operands[2]) == REG || - CONST_OK_FOR_LETTER_P (INTVAL (operands[2]),'J')))" - "@ - la\\t%0,%c2(,%1) - la\\t%0,0(%1,%2)" - [(set_attr "op_type" "RX") - (set_attr "atype" "mem") - (set_attr "type" "la")]) - (define_insn "*addsi3_cc" [(set (reg 33) (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0") @@ -3301,67 +3226,24 @@ [(set_attr "op_type" "RR,RI,RX") (set_attr "atype" "reg,reg,mem")]) -(define_insn "*la" - [(set (match_operand:SI 0 "register_operand" "=a") +(define_insn "*la_31" + [(set (match_operand:SI 0 "register_operand" "=d") (match_operand:QI 1 "address_operand" "p"))] - "reload_in_progress || reload_completed - || legitimate_la_operand_p (operands[1])" + "legitimate_la_operand_p (operands[1])" "la\\t%0,%a1" [(set_attr "op_type" "RX") (set_attr "atype" "mem") (set_attr "type" "la")]) -(define_insn "*do_la_reg_0" - [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "register_operand" "d")))] - "reload_in_progress || reload_completed" - "brxle\\t%0,%2,.+4" - [(set_attr "op_type" "RSI") - (set_attr "atype" "reg")]) - -(define_insn "*reload_la_31" - [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (match_operand:SI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")))] - "reload_in_progress - && !address_operand (gen_rtx_PLUS (SImode, operands[1], operands[2]), QImode) - && !rtx_equal_p (operands[0], operands[1]) - && !rtx_equal_p (operands[0], operands[2])" - "#") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "register_operand" "")))] - "reload_completed - && !address_operand (gen_rtx_PLUS (SImode, operands[1], operands[2]), QImode) - && !rtx_equal_p (operands[0], operands[1]) - && !rtx_equal_p (operands[0], operands[2])" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] - " -{ - if (CONSTANT_P (operands[1]) - && !legitimate_reload_constant_p (operands[1])) - operands[1] = force_const_mem (SImode, operands[1]); -}") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "reload_completed - && !address_operand (gen_rtx_PLUS (SImode, operands[1], operands[2]), QImode) - && !rtx_equal_p (operands[0], operands[1]) - && !rtx_equal_p (operands[0], operands[2])" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] +(define_expand "reload_insi" + [(parallel [(match_operand:SI 0 "register_operand" "=a") + (match_operand:SI 1 "s390_plus_operand" "") + (match_operand:SI 2 "register_operand" "=&a")])] + "!TARGET_64BIT" " { - if (CONSTANT_P (operands[2]) - && !legitimate_reload_constant_p (operands[2])) - operands[2] = force_const_mem (SImode, operands[2]); + s390_expand_plus_operand (operands[0], operands[1], operands[2]); + DONE; }") |