aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2003-06-27 21:10:17 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2003-06-27 21:10:17 +0000
commitdc65c307c80fc0817b0452685f3e4b804f1d521e (patch)
tree68fab34b88702b49fc7577b098abc9faec381d81 /gcc
parent5bbd6c3ee0886c0dbd5c056aad8c950f13e35e82 (diff)
downloadgcc-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/ChangeLog16
-rw-r--r--gcc/config/s390/s390-protos.h2
-rw-r--r--gcc/config/s390/s390.c59
-rw-r--r--gcc/config/s390/s390.h5
-rw-r--r--gcc/config/s390/s390.md198
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/20030627-1.c20
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);
+}
+