From fa21a761a6e3d63bfddbd722e3d754c67b49b832 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 1 Jun 2008 13:01:23 +0000 Subject: [PATCH] mips.c (mips_valid_offset_p): New function. gcc/ * config/mips/mips.c (mips_valid_offset_p): New function. (mips_valid_lo_sum_p): Likewise. (mips_classify_address): Use them. (mips_force_address): New function. (mips_legitimize_address): Use it. * config/mips/mips.md (MOVE128): New mode iterator. (movtf): Require TARGET_64BIT. Remove empty strings. (*movtf_internal): Rename to... (*movtf): ...this and require !TARGET_MIPS16. Use "m" instead of "R" and use {,fp}{load,store} attributes instead of "multi". Use a separate define_split. (*movtf_mips16): New pattern. gcc/testsuite/ * gcc.target/mips/fpr-moves-7.c: New test. * gcc.target/mips/fpr-moves-8.c: New test. From-SVN: r136253 --- gcc/ChangeLog | 15 +++++ gcc/config/mips/mips.c | 72 +++++++++++++++++++-- gcc/config/mips/mips.md | 51 ++++++++++----- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.target/mips/fpr-moves-7.c | 38 +++++++++++ gcc/testsuite/gcc.target/mips/fpr-moves-8.c | 38 +++++++++++ 6 files changed, 197 insertions(+), 22 deletions(-) create mode 100644 gcc/testsuite/gcc.target/mips/fpr-moves-7.c create mode 100644 gcc/testsuite/gcc.target/mips/fpr-moves-8.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 624d3386f46..cd13a87e68f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2008-06-01 Richard Sandiford + + * config/mips/mips.c (mips_valid_offset_p): New function. + (mips_valid_lo_sum_p): Likewise. + (mips_classify_address): Use them. + (mips_force_address): New function. + (mips_legitimize_address): Use it. + * config/mips/mips.md (MOVE128): New mode iterator. + (movtf): Require TARGET_64BIT. Remove empty strings. + (*movtf_internal): Rename to... + (*movtf): ...this and require !TARGET_MIPS16. Use "m" instead + of "R" and use {,fp}{load,store} attributes instead of "multi". + Use a separate define_split. + (*movtf_mips16): New pattern. + 2008-06-01 Richard Sandiford * config/mips/mips-protos.h (mips_expand_before_return): Declare. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 246600d8b35..551159c9e94 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -1809,6 +1809,51 @@ mips_valid_base_register_p (rtx x, enum machine_mode mode, bool strict_p) && mips_regno_mode_ok_for_base_p (REGNO (x), mode, strict_p)); } +/* Return true if, for every base register BASE_REG, (plus BASE_REG X) + can address a value of mode MODE. */ + +static bool +mips_valid_offset_p (rtx x, enum machine_mode mode) +{ + /* Check that X is a signed 16-bit number. */ + if (!const_arith_operand (x, Pmode)) + return false; + + /* We may need to split multiword moves, so make sure that every word + is accessible. */ + if (GET_MODE_SIZE (mode) > UNITS_PER_WORD + && !SMALL_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD)) + return false; + + return true; +} + +/* Return true if a LO_SUM can address a value of mode MODE when the + LO_SUM symbol has type SYMBOL_TYPE. */ + +static bool +mips_valid_lo_sum_p (enum mips_symbol_type symbol_type, enum machine_mode mode) +{ + /* Check that symbols of type SYMBOL_TYPE can be used to access values + of mode MODE. */ + if (mips_symbol_insns (symbol_type, mode) == 0) + return false; + + /* Check that there is a known low-part relocation. */ + if (mips_lo_relocs[symbol_type] == NULL) + return false; + + /* We may need to split multiword moves, so make sure that each word + can be accessed without inducing a carry. This is mainly needed + for o64, which has historically only guaranteed 64-bit alignment + for 128-bit types. */ + if (GET_MODE_SIZE (mode) > UNITS_PER_WORD + && GET_MODE_BITSIZE (mode) > GET_MODE_ALIGNMENT (mode)) + return false; + + return true; +} + /* Return true if X is a valid address for machine mode MODE. If it is, fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in effect. */ @@ -1831,7 +1876,7 @@ mips_classify_address (struct mips_address_info *info, rtx x, info->reg = XEXP (x, 0); info->offset = XEXP (x, 1); return (mips_valid_base_register_p (info->reg, mode, strict_p) - && const_arith_operand (info->offset, VOIDmode)); + && mips_valid_offset_p (info->offset, mode)); case LO_SUM: info->type = ADDRESS_LO_SUM; @@ -1849,8 +1894,7 @@ mips_classify_address (struct mips_address_info *info, rtx x, info->symbol_type = mips_classify_symbolic_expression (info->offset, SYMBOL_CONTEXT_MEM); return (mips_valid_base_register_p (info->reg, mode, strict_p) - && mips_symbol_insns (info->symbol_type, mode) > 0 - && mips_lo_relocs[info->symbol_type] != 0); + && mips_valid_lo_sum_p (info->symbol_type, mode)); case CONST_INT: /* Small-integer addresses don't occur very often, but they @@ -2473,6 +2517,16 @@ mips_legitimize_tls_address (rtx loc) return dest; } +/* If X is not a valid address for mode MODE, force it into a register. */ + +static rtx +mips_force_address (rtx x, enum machine_mode mode) +{ + if (!mips_legitimate_address_p (mode, x, false)) + x = force_reg (Pmode, x); + return x; +} + /* This function is used to implement LEGITIMIZE_ADDRESS. If *XLOC can be legitimized in a way that the generic machinery might not expect, put the new address in *XLOC and return true. MODE is the mode of @@ -2481,7 +2535,7 @@ mips_legitimize_tls_address (rtx loc) bool mips_legitimize_address (rtx *xloc, enum machine_mode mode) { - rtx base; + rtx base, addr; HOST_WIDE_INT offset; if (mips_tls_symbol_p (*xloc)) @@ -2491,8 +2545,11 @@ mips_legitimize_address (rtx *xloc, enum machine_mode mode) } /* See if the address can split into a high part and a LO_SUM. */ - if (mips_split_symbol (NULL, *xloc, mode, xloc)) - return true; + if (mips_split_symbol (NULL, *xloc, mode, &addr)) + { + *xloc = mips_force_address (addr, mode); + return true; + } /* Handle BASE + OFFSET using mips_add_offset. */ mips_split_plus (*xloc, &base, &offset); @@ -2500,7 +2557,8 @@ mips_legitimize_address (rtx *xloc, enum machine_mode mode) { if (!mips_valid_base_register_p (base, mode, false)) base = copy_to_mode_reg (Pmode, base); - *xloc = mips_add_offset (NULL, base, offset); + addr = mips_add_offset (NULL, base, offset); + *xloc = mips_force_address (addr, mode); return true; } return false; diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 55e1cd0ece3..3370d9958c8 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -496,6 +496,9 @@ (define_mode_iterator MOVE64 [DI DF (V2SF "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT")]) +;; 128-bit modes for which we provide move patterns on 64-bit targets. +(define_mode_iterator MOVE128 [TF]) + ;; This mode iterator allows the QI and HI extension patterns to be ;; defined from the same template. (define_mode_iterator SHORT [QI HI]) @@ -4064,28 +4067,36 @@ ;; 128-bit floating point moves (define_expand "movtf" - [(set (match_operand:TF 0 "") - (match_operand:TF 1 ""))] - "" + [(set (match_operand:TF 0) + (match_operand:TF 1))] + "TARGET_64BIT" { if (mips_legitimize_move (TFmode, operands[0], operands[1])) DONE; }) ;; This pattern handles both hard- and soft-float cases. -(define_insn_and_split "*movtf_internal" - [(set (match_operand:TF 0 "nonimmediate_operand" "=d,R,f,dR") - (match_operand:TF 1 "move_operand" "dGR,dG,dGR,f"))] - "" +(define_insn "*movtf" + [(set (match_operand:TF 0 "nonimmediate_operand" "=d,d,m,f,d,f,m") + (match_operand:TF 1 "move_operand" "dG,m,dG,dG,f,m,f"))] + "TARGET_64BIT + && !TARGET_MIPS16 + && (register_operand (operands[0], TFmode) + || reg_or_0_operand (operands[1], TFmode))" "#" - "&& reload_completed" - [(const_int 0)] -{ - mips_split_doubleword_move (operands[0], operands[1]); - DONE; -} - [(set_attr "type" "multi") - (set_attr "length" "16")]) + [(set_attr "type" "multi,load,store,multi,multi,fpload,fpstore") + (set_attr "length" "8,*,*,8,8,*,*")]) + +(define_insn "*movtf_mips16" + [(set (match_operand:TF 0 "nonimmediate_operand" "=d,y,d,d,m") + (match_operand:TF 1 "move_operand" "d,d,y,m,d"))] + "TARGET_64BIT + && TARGET_MIPS16 + && (register_operand (operands[0], TFmode) + || register_operand (operands[1], TFmode))" + "#" + [(set_attr "type" "multi,multi,multi,load,store") + (set_attr "length" "8,8,8,*,*")]) (define_split [(set (match_operand:MOVE64 0 "nonimmediate_operand") @@ -4098,6 +4109,16 @@ DONE; }) +(define_split + [(set (match_operand:MOVE128 0 "nonimmediate_operand") + (match_operand:MOVE128 1 "move_operand"))] + "TARGET_64BIT && reload_completed" + [(const_int 0)] +{ + mips_split_doubleword_move (operands[0], operands[1]); + DONE; +}) + ;; When generating mips16 code, split moves of negative constants into ;; a positive "li" followed by a negation. (define_split diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4a3d5ca9107..a53fdd73f9e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-06-01 Richard Sandiford + + * gcc.target/mips/fpr-moves-7.c: New test. + * gcc.target/mips/fpr-moves-8.c: New test. + 2008-05-30 Bernd Schmidt * gcc.target/bfin/mcpu-default.c: Adjust for recent changes: default diff --git a/gcc/testsuite/gcc.target/mips/fpr-moves-7.c b/gcc/testsuite/gcc.target/mips/fpr-moves-7.c new file mode 100644 index 00000000000..4736edd24ee --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/fpr-moves-7.c @@ -0,0 +1,38 @@ +/* { dg-do compile { target mips16_attribute } } */ +/* { dg-mips-options "-mabi=64 -msoft-float -O2 -EL" } */ +/* { dg-add-options mips16_attribute } */ + +extern long double g[16]; +extern unsigned char gstuff[0x10000]; + +NOMIPS16 long double +foo (long double i1, long double i2, long double i3, long double i4, + long double *x, unsigned char *lstuff) +{ + g[0] = i1; + g[1] = i2; + g[2] = i3; + g[3] = i4; + x[0] = x[4]; + x[1] = 0; + x[2] = 1.0; + x[3] = g[4]; + x[4] = *(long double *) (lstuff + 0x7fff); + return *(long double *) (gstuff + 0x7fff); +} + +MIPS16 long double +bar (long double i1, long double i2, long double i3, long double i4, + long double *x, unsigned char *lstuff) +{ + g[0] = i1; + g[1] = i2; + g[2] = i3; + g[3] = i4; + x[0] = x[4]; + x[1] = 0; + x[2] = 1.0; + x[3] = g[4]; + x[4] = *(long double *) (lstuff + 0x7fff); + return *(long double *) (gstuff + 0x7fff); +} diff --git a/gcc/testsuite/gcc.target/mips/fpr-moves-8.c b/gcc/testsuite/gcc.target/mips/fpr-moves-8.c new file mode 100644 index 00000000000..ade9e5e9c0a --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/fpr-moves-8.c @@ -0,0 +1,38 @@ +/* { dg-do compile { target mips16_attribute } } */ +/* { dg-mips-options "-mabi=64 -msoft-float -O2 -EB" } */ +/* { dg-add-options mips16_attribute } */ + +extern long double g[16]; +extern unsigned char gstuff[0x10000]; + +NOMIPS16 long double +foo (long double i1, long double i2, long double i3, long double i4, + long double *x, unsigned char *lstuff) +{ + g[0] = i1; + g[1] = i2; + g[2] = i3; + g[3] = i4; + x[0] = x[4]; + x[1] = 0; + x[2] = 1.0; + x[3] = g[4]; + x[4] = *(long double *) (lstuff + 0x7fff); + return *(long double *) (gstuff + 0x7fff); +} + +MIPS16 long double +bar (long double i1, long double i2, long double i3, long double i4, + long double *x, unsigned char *lstuff) +{ + g[0] = i1; + g[1] = i2; + g[2] = i3; + g[3] = i4; + x[0] = x[4]; + x[1] = 0; + x[2] = 1.0; + x[3] = g[4]; + x[4] = *(long double *) (lstuff + 0x7fff); + return *(long double *) (gstuff + 0x7fff); +} -- 2.30.2