diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2003-06-27 21:10:17 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@gcc.gnu.org> | 2003-06-27 21:10:17 +0000 |
commit | dc65c307c80fc0817b0452685f3e4b804f1d521e (patch) | |
tree | 68fab34b88702b49fc7577b098abc9faec381d81 /gcc | |
parent | 5bbd6c3ee0886c0dbd5c056aad8c950f13e35e82 (diff) | |
download | gcc-dc65c307c80fc0817b0452685f3e4b804f1d521e.zip gcc-dc65c307c80fc0817b0452685f3e4b804f1d521e.tar.gz gcc-dc65c307c80fc0817b0452685f3e4b804f1d521e.tar.bz2 |
s390.h (SECONDARY_OUTPUT_RELOAD_CLASS): Define.
gcc/ChangeLog:
* config/s390/s390.h (SECONDARY_OUTPUT_RELOAD_CLASS): Define.
* config/s390/s390.c (s390_secondary_output_reload_class): New function.
* config/s390/s390-protos.h (s390_secondary_output_reload_class):
Declare it.
* config/s390/s390.md ("reload_outti", "reload_outdi",
"reload_outdf"): New expanders.
* config/s390/s390.md ("movti" + splitters): Handle non-offsettable
memory operands as source.
("movdi" + splitters): Likewise.
("movdf" + splitters): Likewise.
* config/s390/s390.c (s390_split_ok_p): New function.
* config/s390/s390-protos.h (s390_split_ok_p): Declare it.
gcc/testsuite/ChangeLog:
* gcc.dg/20030627-1.c: New test.
From-SVN: r68607
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 59 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 5 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 198 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/20030627-1.c | 20 |
7 files changed, 208 insertions, 96 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 240105d..8a6872f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2003-06-27 Ulrich Weigand <uweigand@de.ibm.com> + + * config/s390/s390.h (SECONDARY_OUTPUT_RELOAD_CLASS): Define. + * config/s390/s390.c (s390_secondary_output_reload_class): New function. + * config/s390/s390-protos.h (s390_secondary_output_reload_class): + Declare it. + * config/s390/s390.md ("reload_outti", "reload_outdi", + "reload_outdf"): New expanders. + + * config/s390/s390.md ("movti" + splitters): Handle non-offsettable + memory operands as source. + ("movdi" + splitters): Likewise. + ("movdf" + splitters): Likewise. + * config/s390/s390.c (s390_split_ok_p): New function. + * config/s390/s390-protos.h (s390_split_ok_p): Declare it. + 2003-06-27 Kazu Hirata <kazu@cs.umass.edu> * combine.c (force_to_mode): Replace the equality comparison diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index e241f28..c33018f 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -42,6 +42,7 @@ extern int s390_single_hi PARAMS ((rtx, enum machine_mode, int)); extern int s390_extract_hi PARAMS ((rtx, enum machine_mode, int)); extern int s390_single_qi PARAMS ((rtx, enum machine_mode, int)); extern int s390_extract_qi PARAMS ((rtx, enum machine_mode, int)); +extern bool s390_split_ok_p PARAMS ((rtx, rtx, enum machine_mode, int)); extern int tls_symbolic_operand PARAMS ((rtx)); extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode)); @@ -60,6 +61,7 @@ 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 enum reg_class s390_secondary_output_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_symbolic_move PARAMS ((rtx *)); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 4f0dd02..dc02d22 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -863,6 +863,42 @@ s390_extract_qi (op, mode, part) abort (); } +/* Check whether we can (and want to) split a double-word + move in mode MODE from SRC to DST into two single-word + moves, moving the subword FIRST_SUBWORD first. */ + +bool +s390_split_ok_p (dst, src, mode, first_subword) + rtx dst; + rtx src; + enum machine_mode mode; + int first_subword; +{ + /* Floating point registers cannot be split. */ + if (FP_REG_P (src) || FP_REG_P (dst)) + return false; + + /* We don't need to split if operands are directly accessable. */ + if (s_operand (src, mode) || s_operand (dst, mode)) + return false; + + /* Non-offsettable memory references cannot be split. */ + if ((GET_CODE (src) == MEM && !offsettable_memref_p (src)) + || (GET_CODE (dst) == MEM && !offsettable_memref_p (dst))) + return false; + + /* Moving the first subword must not clobber a register + needed to move the second subword. */ + if (register_operand (dst, mode)) + { + rtx subreg = operand_subword (dst, first_subword, 0, mode); + if (reg_overlap_mentioned_p (subreg, src)) + return false; + } + + return true; +} + /* Change optimizations to be performed, depending on the optimization level. @@ -1715,6 +1751,29 @@ s390_secondary_input_reload_class (class, mode, in) return NO_REGS; } +/* Return the register class of a scratch register needed to + store a register of class CLASS in MODE into OUT: + + We need a temporary when storing a double-word to a + non-offsettable memory address. */ + +enum reg_class +s390_secondary_output_reload_class (class, mode, out) + enum reg_class class; + enum machine_mode mode; + rtx out; +{ + if ((TARGET_64BIT ? mode == TImode + : (mode == DImode || mode == DFmode)) + && reg_classes_intersect_p (GENERAL_REGS, class) + && GET_CODE (out) == MEM + && !offsettable_memref_p (out) + && !s_operand (out, VOIDmode)) + 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. diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index e0e5901..7848d7d 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -460,6 +460,11 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \ s390_secondary_input_reload_class ((CLASS), (MODE), (IN)) +/* We need a secondary reload when storing a double-word + to a non-offsettable memory address. */ +#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, OUT) \ + s390_secondary_output_reload_class ((CLASS), (MODE), (OUT)) + /* We need secondary memory to move data between GPRs and FPRs. */ #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ ((CLASS1) != (CLASS2) && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS)) diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 244fbc3..b5a222b 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -905,7 +905,7 @@ (define_insn "movti" [(set (match_operand:TI 0 "nonimmediate_operand" "=d,Q,d,o,Q") - (match_operand:TI 1 "general_operand" "Q,d,dKo,d,Q"))] + (match_operand:TI 1 "general_operand" "Q,d,dKm,d,Q"))] "TARGET_64BIT" "@ lmg\\t%0,%N0,%1 @@ -920,36 +920,29 @@ [(set (match_operand:TI 0 "nonimmediate_operand" "") (match_operand:TI 1 "general_operand" ""))] "TARGET_64BIT && reload_completed - && !s_operand (operands[0], VOIDmode) - && !s_operand (operands[1], VOIDmode) - && (register_operand (operands[0], VOIDmode) - || register_operand (operands[1], VOIDmode)) - && (!register_operand (operands[0], VOIDmode) - || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode), - operands[1]) - || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, TImode), - operands[1]))" + && s390_split_ok_p (operands[0], operands[1], TImode, 0)" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] - " { - if (!register_operand (operands[0], VOIDmode) - || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode), - operands[1])) - { - operands[2] = operand_subword (operands[0], 0, 0, TImode); - operands[3] = operand_subword (operands[0], 1, 0, TImode); - operands[4] = operand_subword (operands[1], 0, 0, TImode); - operands[5] = operand_subword (operands[1], 1, 0, TImode); - } - else - { - operands[2] = operand_subword (operands[0], 1, 0, TImode); - operands[3] = operand_subword (operands[0], 0, 0, TImode); - operands[4] = operand_subword (operands[1], 1, 0, TImode); - operands[5] = operand_subword (operands[1], 0, 0, TImode); - } -}") + operands[2] = operand_subword (operands[0], 0, 0, TImode); + operands[3] = operand_subword (operands[0], 1, 0, TImode); + operands[4] = operand_subword (operands[1], 0, 0, TImode); + operands[5] = operand_subword (operands[1], 1, 0, TImode); +}) + +(define_split + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (match_operand:TI 1 "general_operand" ""))] + "TARGET_64BIT && reload_completed + && s390_split_ok_p (operands[0], operands[1], TImode, 1)" + [(set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 5))] +{ + operands[2] = operand_subword (operands[0], 1, 0, TImode); + operands[3] = operand_subword (operands[0], 0, 0, TImode); + operands[4] = operand_subword (operands[1], 1, 0, TImode); + operands[5] = operand_subword (operands[1], 0, 0, TImode); +}) (define_split [(set (match_operand:TI 0 "register_operand" "") @@ -957,12 +950,23 @@ "TARGET_64BIT && reload_completed && !s_operand (operands[1], VOIDmode)" [(set (match_dup 0) (match_dup 1))] - " { rtx addr = operand_subword (operands[0], 1, 0, TImode); s390_load_address (addr, XEXP (operands[1], 0)); operands[1] = replace_equiv_address (operands[1], addr); -}") +}) + +(define_expand "reload_outti" + [(parallel [(match_operand:TI 0 "memory_operand" "") + (match_operand:TI 1 "register_operand" "d") + (match_operand:DI 2 "register_operand" "=&a")])] + "TARGET_64BIT" +{ + s390_load_address (operands[2], XEXP (operands[0], 0)); + operands[0] = replace_equiv_address (operands[0], operands[2]); + emit_move_insn (operands[0], operands[1]); + DONE; +}) ; ; movdi instruction pattern(s). @@ -1044,7 +1048,7 @@ (define_insn "*movdi_31" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,o,!*f,!*f,!m,Q") - (match_operand:DI 1 "general_operand" "Q,d,dKo,d,*f,m,*f,Q"))] + (match_operand:DI 1 "general_operand" "Q,d,dKm,d,*f,m,*f,Q"))] "!TARGET_64BIT" "@ lm\\t%0,%N0,%1 @@ -1062,53 +1066,54 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "") (match_operand:DI 1 "general_operand" ""))] "!TARGET_64BIT && reload_completed - && !FP_REG_P (operands[0]) - && !FP_REG_P (operands[1]) - && !s_operand (operands[0], VOIDmode) - && !s_operand (operands[1], VOIDmode) - && (register_operand (operands[0], VOIDmode) - || register_operand (operands[1], VOIDmode)) - && (!register_operand (operands[0], VOIDmode) - || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode), - operands[1]) - || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DImode), - operands[1]))" + && s390_split_ok_p (operands[0], operands[1], DImode, 0)" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] - " { - if (!register_operand (operands[0], VOIDmode) - || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode), - operands[1])) - { - operands[2] = operand_subword (operands[0], 0, 0, DImode); - operands[3] = operand_subword (operands[0], 1, 0, DImode); - operands[4] = operand_subword (operands[1], 0, 0, DImode); - operands[5] = operand_subword (operands[1], 1, 0, DImode); - } - else - { - operands[2] = operand_subword (operands[0], 1, 0, DImode); - operands[3] = operand_subword (operands[0], 0, 0, DImode); - operands[4] = operand_subword (operands[1], 1, 0, DImode); - operands[5] = operand_subword (operands[1], 0, 0, DImode); - } -}") + operands[2] = operand_subword (operands[0], 0, 0, DImode); + operands[3] = operand_subword (operands[0], 1, 0, DImode); + operands[4] = operand_subword (operands[1], 0, 0, DImode); + operands[5] = operand_subword (operands[1], 1, 0, DImode); +}) + +(define_split + [(set (match_operand:DI 0 "nonimmediate_operand" "") + (match_operand:DI 1 "general_operand" ""))] + "!TARGET_64BIT && reload_completed + && s390_split_ok_p (operands[0], operands[1], DImode, 1)" + [(set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 5))] +{ + operands[2] = operand_subword (operands[0], 1, 0, DImode); + operands[3] = operand_subword (operands[0], 0, 0, DImode); + operands[4] = operand_subword (operands[1], 1, 0, DImode); + operands[5] = operand_subword (operands[1], 0, 0, DImode); +}) (define_split [(set (match_operand:DI 0 "register_operand" "") (match_operand:DI 1 "memory_operand" ""))] "!TARGET_64BIT && reload_completed && !FP_REG_P (operands[0]) - && !FP_REG_P (operands[1]) && !s_operand (operands[1], VOIDmode)" [(set (match_dup 0) (match_dup 1))] - " { rtx addr = operand_subword (operands[0], 1, 0, DImode); s390_load_address (addr, XEXP (operands[1], 0)); operands[1] = replace_equiv_address (operands[1], addr); -}") +}) + +(define_expand "reload_outdi" + [(parallel [(match_operand:DI 0 "memory_operand" "") + (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "=&a")])] + "!TARGET_64BIT" +{ + s390_load_address (operands[2], XEXP (operands[0], 0)); + operands[0] = replace_equiv_address (operands[0], operands[2]); + emit_move_insn (operands[0], operands[1]); + DONE; +}) (define_peephole2 [(set (match_operand:DI 0 "register_operand" "") @@ -1354,7 +1359,7 @@ (define_insn "*movdf_31" [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,Q,d,o,Q") - (match_operand:DF 1 "general_operand" "f,m,f,Q,d,dKo,d,Q"))] + (match_operand:DF 1 "general_operand" "f,m,f,Q,d,dKm,d,Q"))] "!TARGET_64BIT" "@ ldr\\t%0,%1 @@ -1372,53 +1377,54 @@ [(set (match_operand:DF 0 "nonimmediate_operand" "") (match_operand:DF 1 "general_operand" ""))] "!TARGET_64BIT && reload_completed - && !FP_REG_P (operands[0]) - && !FP_REG_P (operands[1]) - && !s_operand (operands[0], VOIDmode) - && !s_operand (operands[1], VOIDmode) - && (register_operand (operands[0], VOIDmode) - || register_operand (operands[1], VOIDmode)) - && (!register_operand (operands[0], VOIDmode) - || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode), - operands[1]) - || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DFmode), - operands[1]))" + && s390_split_ok_p (operands[0], operands[1], DFmode, 0)" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] - " { - if (!register_operand (operands[0], VOIDmode) - || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode), - operands[1])) - { - operands[2] = operand_subword (operands[0], 0, 0, DFmode); - operands[3] = operand_subword (operands[0], 1, 0, DFmode); - operands[4] = operand_subword (operands[1], 0, 0, DFmode); - operands[5] = operand_subword (operands[1], 1, 0, DFmode); - } - else - { - operands[2] = operand_subword (operands[0], 1, 0, DFmode); - operands[3] = operand_subword (operands[0], 0, 0, DFmode); - operands[4] = operand_subword (operands[1], 1, 0, DFmode); - operands[5] = operand_subword (operands[1], 0, 0, DFmode); - } -}") + operands[2] = operand_subword (operands[0], 0, 0, DFmode); + operands[3] = operand_subword (operands[0], 1, 0, DFmode); + operands[4] = operand_subword (operands[1], 0, 0, DFmode); + operands[5] = operand_subword (operands[1], 1, 0, DFmode); +}) + +(define_split + [(set (match_operand:DF 0 "nonimmediate_operand" "") + (match_operand:DF 1 "general_operand" ""))] + "!TARGET_64BIT && reload_completed + && s390_split_ok_p (operands[0], operands[1], DFmode, 1)" + [(set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 5))] +{ + operands[2] = operand_subword (operands[0], 1, 0, DFmode); + operands[3] = operand_subword (operands[0], 0, 0, DFmode); + operands[4] = operand_subword (operands[1], 1, 0, DFmode); + operands[5] = operand_subword (operands[1], 0, 0, DFmode); +}) (define_split [(set (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "memory_operand" ""))] "!TARGET_64BIT && reload_completed && !FP_REG_P (operands[0]) - && !FP_REG_P (operands[1]) && !s_operand (operands[1], VOIDmode)" [(set (match_dup 0) (match_dup 1))] - " { rtx addr = operand_subword (operands[0], 1, 0, DFmode); s390_load_address (addr, XEXP (operands[1], 0)); operands[1] = replace_equiv_address (operands[1], addr); -}") +}) + +(define_expand "reload_outdf" + [(parallel [(match_operand:DF 0 "memory_operand" "") + (match_operand:DF 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "=&a")])] + "!TARGET_64BIT" +{ + s390_load_address (operands[2], XEXP (operands[0], 0)); + operands[0] = replace_equiv_address (operands[0], operands[2]); + emit_move_insn (operands[0], operands[1]); + DONE; +}) ; ; movsf instruction pattern(s). diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 190e0ef..930031b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-06-27 Ulrich Weigand <uweigand@de.ibm.com> + + * gcc.dg/20030627-1.c: New test. + 2003-06-26 Mark Mitchell <mark@codesourcery.com> PR c++/11332 diff --git a/gcc/testsuite/gcc.dg/20030627-1.c b/gcc/testsuite/gcc.dg/20030627-1.c new file mode 100644 index 0000000..4135f71 --- /dev/null +++ b/gcc/testsuite/gcc.dg/20030627-1.c @@ -0,0 +1,20 @@ +/* This tests whether non-offsettable memory operands are reloaded + correctly in certain corner cases on s390 targets. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu89" } */ + +void test_inout (char *bd, int xd, char *bs, int xs) +{ + *(long long *)(bd + xd + 4093) = *(long long *)(bs + xs + 4093); +} + +void test_in (char *bd, int xd, char *bs, int xs) +{ + *(long long *)(bd + xd) = *(long long *)(bs + xs + 4093); +} + +void test_out (char *bd, int xd, char *bs, int xs) +{ + *(long long *)(bd + xd + 4093) = *(long long *)(bs + xs); +} + |