Octeon2 includes the indexed load instructions from the DSP ASE and a few extensions on top of those: lbx, lhux, and lwux. This patch adds to GCC support for the DSP64 instruction ldx and also all of the Octeon2 extensions. I only added the builtin function for ldx to be the same as the other l*x DSP ASE.
Ok? Bootstrapped and tested on mips64-linux-gnu (with {-march=octeon,-march=octeon2}/{-march=n32,-march=64} ). Thanks, Andrew Pinski gcc/ChangeLog: * config/mips/mips.md (size): Add SI and DI. (SIZE): New mode attribute. (U): New code attribute. * config/mips/mips-dsp.md (mips_lbux): Use gen_mips_lbux_extsi. (mips_lbux_<mode>): Delete. (mips_l<SHORT:size><u>x_ext<GPR:mode>_<P:mode>): New pattern. (mips_lhx): Use gen_mips_lhx_extsi. (mips_lhx_<mode>): Delete. (mips_lwx_<mode>): Delete. (mips_ldx): New expand. (mips_l<GPR:size>x_<P:mode>): New pattern. (*mips_lw<u>x_<P:mode>_ext): Likewise. * config/mips/mips-ftypes.def: Add DI f(POINTER, SI) function type. * config/mips/mips.c (mips_loadindexed_address_p): New function. (mips_rtx_costs <case MEM>): Call mips_loadindexed_address_p. (dsp64): New availability predicate. (mips_builtins): Add an entry for __builtin_mips_ldx. * config/mips/mips.h (ISA_HAS_LBX): New define. (ISA_HAS_LBUX): Likewise. (ISA_HAS_LHX): Likewise. (ISA_HAS_LHUX): Likewise. (ISA_HAS_LWX): Likewise. (ISA_HAS_LWUX): Likewise. (ISA_HAS_LDX): Likewise. gcc/testsuite/ChangeLog: * gcc.target/mips/mips64-dsp-ldx1.c: New test. * gcc.target/mips/octeon2-lx-1.c: New test. * gcc.target/mips/mips64-dsp-ldx.c: New test. * gcc.target/mips/octeon2-lx-2.c: New test. * gcc.target/mips/octeon2-lx-3.c: New test.
Index: testsuite/gcc.target/mips/mips64-dsp-ldx1.c =================================================================== --- testsuite/gcc.target/mips/mips64-dsp-ldx1.c (revision 0) +++ testsuite/gcc.target/mips/mips64-dsp-ldx1.c (revision 0) @@ -0,0 +1,10 @@ +/* Test MIPS64 DSP instructions */ +/* { dg-do compile } */ +/* { dg-options "-mgp64 -mdsp" } */ + +/* { dg-final { scan-assembler "\tldx\t" } } */ + +NOMIPS16 signed long long test (signed long long *a, int index) +{ + return __builtin_mips_ldx (a, index); +} Index: testsuite/gcc.target/mips/octeon2-lx-1.c =================================================================== --- testsuite/gcc.target/mips/octeon2-lx-1.c (revision 0) +++ testsuite/gcc.target/mips/octeon2-lx-1.c (revision 0) @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=octeon2 -O -mgp64" } */ + +#define TEST(N, R, T) \ + T f##N (T j, R *b, long long i) { return j + b[i]; } \ + T g##N (T j, unsigned R *b, long long i) { return j + b[i]; } + +TEST (1, char, int) +TEST (2, char, long long) +/* { dg-final { scan-assembler-times "\tlbx\t" 2 } } */ +/* { dg-final { scan-assembler-times "\tlbux\t" 2 } } */ +TEST (3, short, int) +TEST (4, short, long long) +/* { dg-final { scan-assembler-times "\tlhx\t" 2 } } */ +/* { dg-final { scan-assembler-times "\tlhux\t" 2 } } */ +TEST (5, int, long long) +/* { dg-final { scan-assembler-times "\tlwx\t" 1 } } */ +/* { dg-final { scan-assembler-times "\tlwux\t" 1 } } */ Index: testsuite/gcc.target/mips/mips64-dsp-ldx.c =================================================================== --- testsuite/gcc.target/mips/mips64-dsp-ldx.c (revision 0) +++ testsuite/gcc.target/mips/mips64-dsp-ldx.c (revision 0) @@ -0,0 +1,10 @@ +/* Test MIPS64 DSP instructions */ +/* { dg-do compile } */ +/* { dg-options "-mgp64 -mdsp -O" } */ + +/* { dg-final { scan-assembler "\tldx\t" } } */ + +NOMIPS16 signed long long test (signed long long *a, int index) +{ + return a[index]; +} Index: testsuite/gcc.target/mips/octeon2-lx-2.c =================================================================== --- testsuite/gcc.target/mips/octeon2-lx-2.c (revision 0) +++ testsuite/gcc.target/mips/octeon2-lx-2.c (revision 0) @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=octeon2 -O -mgp64" } */ + +#define TEST(N, T) \ + T f##N (T *p, int i) { return p[i]; } \ + unsigned T g##N (unsigned T *p, int i) { return p[i]; } + +TEST (1, char) +/* { dg-final { scan-assembler-times "\tlbu?x\t" 2 } } */ +TEST (2, short) +/* { dg-final { scan-assembler-times "\tlhu?x\t" 2 } } */ +TEST (3, int) +/* { dg-final { scan-assembler-times "\tlwx\t" 2 } } */ +TEST (4, long long) +/* { dg-final { scan-assembler-times "\tldx\t" 2 } } */ Index: testsuite/gcc.target/mips/octeon2-lx-3.c =================================================================== --- testsuite/gcc.target/mips/octeon2-lx-3.c (revision 0) +++ testsuite/gcc.target/mips/octeon2-lx-3.c (revision 0) @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=octeon2 -O -mgp32" } */ + +#define TEST(N, T) \ + T f##N (T *p, int i) { return p[i]; } \ + unsigned T g##N (unsigned T *p, int i) { return p[i]; } + +TEST (1, char) +/* { dg-final { scan-assembler-times "\tlbu?x\t" 2 } } */ +TEST (2, short) +/* { dg-final { scan-assembler-times "\tlhu?x\t" 2 } } */ +TEST (3, int) +/* { dg-final { scan-assembler-times "\tlwx\t" 2 } } */ Index: config/mips/mips-dsp.md =================================================================== --- config/mips/mips-dsp.md (revision 182342) +++ config/mips/mips-dsp.md (working copy) @@ -1105,20 +1105,21 @@ (define_expand "mips_lbux" "ISA_HAS_DSP" { operands[2] = convert_to_mode (Pmode, operands[2], false); - emit_insn (PMODE_INSN (gen_mips_lbux, + emit_insn (PMODE_INSN (gen_mips_lbux_extsi, (operands[0], operands[1], operands[2]))); DONE; }) -(define_insn "mips_lbux_<mode>" - [(set (match_operand:SI 0 "register_operand" "=d") - (zero_extend:SI - (mem:QI (plus:P (match_operand:P 1 "register_operand" "d") - (match_operand:P 2 "register_operand" "d")))))] - "ISA_HAS_DSP" - "lbux\t%0,%2(%1)" +(define_insn "mips_l<SHORT:size><u>x_ext<GPR:mode>_<P:mode>" + [(set (match_operand:GPR 0 "register_operand" "=d") + (any_extend:GPR + (mem:SHORT (plus:P (match_operand:P 1 "register_operand" "d") + (match_operand:P 2 "register_operand" "d")))))] + "ISA_HAS_L<SHORT:SIZE><U>X" + "l<SHORT:size><u>x\t%0,%2(%1)" [(set_attr "type" "load") - (set_attr "mode" "SI")]) + (set_attr "mode" "<GPR:MODE>") + (set_attr "length" "4")]) (define_expand "mips_lhx" [(match_operand:SI 0 "register_operand") @@ -1127,21 +1128,11 @@ (define_expand "mips_lhx" "ISA_HAS_DSP" { operands[2] = convert_to_mode (Pmode, operands[2], false); - emit_insn (PMODE_INSN (gen_mips_lhx, + emit_insn (PMODE_INSN (gen_mips_lhx_extsi, (operands[0], operands[1], operands[2]))); DONE; }) -(define_insn "mips_lhx_<mode>" - [(set (match_operand:SI 0 "register_operand" "=d") - (sign_extend:SI - (mem:HI (plus:P (match_operand:P 1 "register_operand" "d") - (match_operand:P 2 "register_operand" "d")))))] - "ISA_HAS_DSP" - "lhx\t%0,%2(%1)" - [(set_attr "type" "load") - (set_attr "mode" "SI")]) - (define_expand "mips_lwx" [(match_operand:SI 0 "register_operand") (match_operand 1 "pmode_register_operand") @@ -1154,14 +1145,38 @@ (define_expand "mips_lwx" DONE; }) -(define_insn "mips_lwx_<mode>" - [(set (match_operand:SI 0 "register_operand" "=d") - (mem:SI (plus:P (match_operand:P 1 "register_operand" "d") - (match_operand:P 2 "register_operand" "d"))))] - "ISA_HAS_DSP" - "lwx\t%0,%2(%1)" +(define_expand "mips_ldx" + [(match_operand:DI 0 "register_operand") + (match_operand 1 "pmode_register_operand") + (match_operand:SI 2 "register_operand")] + "ISA_HAS_DSP && TARGET_64BIT" +{ + operands[2] = convert_to_mode (Pmode, operands[2], false); + emit_insn (PMODE_INSN (gen_mips_ldx, + (operands[0], operands[1], operands[2]))); + DONE; +}) + +(define_insn "mips_l<GPR:size>x_<P:mode>" + [(set (match_operand:GPR 0 "register_operand" "=d") + (mem:GPR (plus:P (match_operand:P 1 "register_operand" "d") + (match_operand:P 2 "register_operand" "d"))))] + "ISA_HAS_L<GPR:SIZE>X" + "l<GPR:size>x\t%0,%2(%1)" + [(set_attr "type" "load") + (set_attr "mode" "<GPR:MODE>") + (set_attr "length" "4")]) + +(define_insn "*mips_lw<u>x_<P:mode>_ext" + [(set (match_operand:DI 0 "register_operand" "=d") + (any_extend:DI + (mem:SI (plus:P (match_operand:P 1 "register_operand" "d") + (match_operand:P 2 "register_operand" "d")))))] + "ISA_HAS_LW<U>X && TARGET_64BIT" + "lw<u>x\t%0,%2(%1)" [(set_attr "type" "load") - (set_attr "mode" "SI")]) + (set_attr "mode" "DI") + (set_attr "length" "4")]) ;; Table 2-8. MIPS DSP ASE Instructions: Branch ;; BPOSGE32 Index: config/mips/mips-ftypes.def =================================================================== --- config/mips/mips-ftypes.def (revision 182342) +++ config/mips/mips-ftypes.def (working copy) @@ -53,6 +53,7 @@ DEF_MIPS_FTYPE (4, (INT, V2SF, V2SF, V2S DEF_MIPS_FTYPE (2, (SI, DI, SI)) DEF_MIPS_FTYPE (2, (SI, POINTER, SI)) +DEF_MIPS_FTYPE (2, (DI, POINTER, SI)) DEF_MIPS_FTYPE (1, (SI, SI)) DEF_MIPS_FTYPE (2, (SI, SI, SI)) DEF_MIPS_FTYPE (3, (SI, SI, SI, SI)) Index: config/mips/mips.md =================================================================== --- config/mips/mips.md (revision 182342) +++ config/mips/mips.md (working copy) @@ -668,9 +668,10 @@ (define_mode_attr D [(SI "") (DI "D") (HA "") (SA "") (DA "D") (UHA "") (USA "") (UDA "D")]) -;; This attribute gives the length suffix for a sign- or zero-extension -;; instruction. -(define_mode_attr size [(QI "b") (HI "h")]) +;; This attribute gives the length suffix for a sign-, zero-extension +;; load and store instruction. +(define_mode_attr size [(QI "b") (HI "h") (SI "w") (DI "d")]) +(define_mode_attr SIZE [(QI "B") (HI "H") (SI "W") (DI "D")]) ;; This attributes gives the mode mask of a SHORT. (define_mode_attr mask [(QI "0x00ff") (HI "0xffff")]) @@ -790,6 +791,9 @@ (define_code_attr u [(sign_extend "") (z (lt "") (ltu "u") (le "") (leu "u")]) +;; <U> is like <u> except uppercase. +(define_code_attr U [(sign_extend "") (zero_extend "U")]) + ;; <su> is like <u>, but the signed form expands to "s" rather than "". (define_code_attr su [(sign_extend "s") (zero_extend "u")]) Index: config/mips/mips.c =================================================================== --- config/mips/mips.c (revision 182342) +++ config/mips/mips.c (working copy) @@ -2159,6 +2159,29 @@ mips_lwxs_address_p (rtx addr) } return false; } + +/* Return true if ADDR matches the pattern for the L{B,H,W,D}{,U}X load + indexed address instruction. Note that such addresses are + not considered legitimate in the TARGET_LEGITIMATE_ADDRESS_P + sense, because their use is so restricted. */ + +static bool +mips_loadindexed_address_p (rtx addr, enum machine_mode mode) +{ + if (GET_CODE (addr) != PLUS + || !REG_P (XEXP (addr, 0)) + || !REG_P (XEXP (addr, 1))) + return false; + if (ISA_HAS_LBX && mode == QImode) + return true; + if (ISA_HAS_LHX && mode == HImode) + return true; + if (ISA_HAS_LWX && mode == SImode) + return true; + if (ISA_HAS_LDX && mode == DImode) + return true; + return false; +} /* Return true if a value at OFFSET bytes from base register BASE can be accessed using an unextended MIPS16 instruction. MODE is the mode of @@ -3552,6 +3575,11 @@ mips_rtx_costs (rtx x, int code, int out *total = COSTS_N_INSNS (2); return true; } + if (mips_loadindexed_address_p (addr, mode)) + { + *total = COSTS_N_INSNS (2); + return true; + } /* Otherwise use the default handling. */ return false; @@ -12627,6 +12655,7 @@ AVAIL_NON_MIPS16 (mips3d, TARGET_MIPS3D) AVAIL_NON_MIPS16 (dsp, TARGET_DSP) AVAIL_NON_MIPS16 (dspr2, TARGET_DSPR2) AVAIL_NON_MIPS16 (dsp_32, !TARGET_64BIT && TARGET_DSP) +AVAIL_NON_MIPS16 (dsp_64, TARGET_64BIT && TARGET_DSP) AVAIL_NON_MIPS16 (dspr2_32, !TARGET_64BIT && TARGET_DSPR2) AVAIL_NON_MIPS16 (loongson, TARGET_LOONGSON_VECTORS) AVAIL_NON_MIPS16 (cache, TARGET_CACHE_BUILTIN) @@ -12959,6 +12988,9 @@ static const struct mips_builtin_descrip DIRECT_BUILTIN (mult, MIPS_DI_FTYPE_SI_SI, dsp_32), DIRECT_BUILTIN (multu, MIPS_DI_FTYPE_USI_USI, dsp_32), + /* Built-in functions for the DSP ASE (64-bit only). */ + DIRECT_BUILTIN (ldx, MIPS_DI_FTYPE_POINTER_SI, dsp_64), + /* The following are for the MIPS DSP ASE REV 2 (32-bit only). */ DIRECT_BUILTIN (dpa_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32), DIRECT_BUILTIN (dps_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32), Index: config/mips/mips.h =================================================================== --- config/mips/mips.h (revision 182342) +++ config/mips/mips.h (working copy) @@ -996,6 +996,15 @@ struct mips_cpu_info { /* ISA has lwxs instruction (load w/scaled index address. */ #define ISA_HAS_LWXS (TARGET_SMARTMIPS && !TARGET_MIPS16) +/* ISA has lbx, lbux, lhx, lhx, lhux, lwx, lwux, or ldx instruction. */ +#define ISA_HAS_LBX (TARGET_OCTEON2) +#define ISA_HAS_LBUX (ISA_HAS_DSP || TARGET_OCTEON2) +#define ISA_HAS_LHX (ISA_HAS_DSP || TARGET_OCTEON2) +#define ISA_HAS_LHUX (TARGET_OCTEON2) +#define ISA_HAS_LWX (ISA_HAS_DSP || TARGET_OCTEON2) +#define ISA_HAS_LWUX (TARGET_OCTEON2 && TARGET_64BIT) +#define ISA_HAS_LDX ((ISA_HAS_DSP || TARGET_OCTEON2) && TARGET_64BIT) + /* The DSP ASE is available. */ #define ISA_HAS_DSP (TARGET_DSP && !TARGET_MIPS16)