This patch adds support for the R6 [D]LSA instructions. The support has been structured to allow MSA (when implemented) to turn on the same instructions as they are also added by the MSA ASE.
I have continued to use the idea of 'ghost' options in the testsuite to indicate what features are required rather than arch revisions. Thanks, Matthew gcc/ * config/mips/mips.c (mips_rtx_costs): Set costs for LSA/DLSA. (mips_print_operand): Support 'y' to print exact log2 in decimal of a const_int. * config/mips/mips.h (ISA_HAS_LSA): New define. (ISA_HAS_DLSA): Likewise. * config/mips/mips.md (<GPR:d>lsa): New define_insn. * config/mips/predicates.md (const_immlsa_operand): New predicate. gcc/testsuite/ * gcc.target/mips/lsa.c: New file. * gcc.target/mips/mips64-lsa.c: Likewise. * gcc.target/mips/mulsize-2.c: Require !HAS_LSA. * gcc.target/mips/mulsize-4.c: Likewise. * gcc.target/mips/mulsize-5.c: New file. * gcc.target/mips/mulsize-6.c: Likewise. * gcc.target/mips/mips.exp (mips_option_groups): Support HAS_LSA and !HAS_LSA as ghost options. (mips-dg-options): Require rev 6 for HAS_LSA. Downgrade to rev 5 for !HAS_LSA. --- gcc/config/mips/mips.c | 30 ++++++++++++++++++++++++++++++ gcc/config/mips/mips.h | 6 ++++++ gcc/config/mips/mips.md | 10 ++++++++++ gcc/config/mips/predicates.md | 4 ++++ gcc/testsuite/gcc.target/mips/lsa.c | 11 +++++++++++ gcc/testsuite/gcc.target/mips/mips.exp | 16 ++++++++++++++-- gcc/testsuite/gcc.target/mips/mips64-lsa.c | 11 +++++++++++ gcc/testsuite/gcc.target/mips/mulsize-2.c | 1 + gcc/testsuite/gcc.target/mips/mulsize-4.c | 1 + gcc/testsuite/gcc.target/mips/mulsize-5.c | 13 +++++++++++++ gcc/testsuite/gcc.target/mips/mulsize-6.c | 13 +++++++++++++ 11 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/mips/lsa.c create mode 100644 gcc/testsuite/gcc.target/mips/mips64-lsa.c create mode 100644 gcc/testsuite/gcc.target/mips/mulsize-5.c create mode 100644 gcc/testsuite/gcc.target/mips/mulsize-6.c diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index c2cc76e..a858a84 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -4108,6 +4108,22 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, return false; } + /* If it's an add + mult (which is equivalent to shift left) and + it's immediate operand satisfies const_immlsa_operand predicate. */ + if (((ISA_HAS_LSA && mode == SImode) + || (ISA_HAS_DLSA && mode == DImode)) + && GET_CODE (XEXP (x, 0)) == MULT) + { + rtx op2 = XEXP (XEXP (x, 0), 1); + if (const_immlsa_operand (op2, mode)) + { + *total = (COSTS_N_INSNS (1) + + set_src_cost (XEXP (XEXP (x, 0), 0), speed) + + set_src_cost (XEXP (x, 1), speed)); + return true; + } + } + /* Double-word operations require three single-word operations and an SLTU. The MIPS16 version then needs to move the result of the SLTU from $24 to a MIPS16 register. */ @@ -8413,6 +8429,7 @@ mips_print_operand_punct_valid_p (unsigned char code) 'x' Print the low 16 bits of CONST_INT OP in hexadecimal format. 'd' Print CONST_INT OP in decimal. 'm' Print one less than CONST_INT OP in decimal. + 'y' Print exact log2 of CONST_INT OP in decimal. 'h' Print the high-part relocation associated with OP, after stripping any outermost HIGH. 'R' Print the low-part relocation associated with OP. @@ -8476,6 +8493,19 @@ mips_print_operand (FILE *file, rtx op, int letter) output_operand_lossage ("invalid use of '%%%c'", letter); break; + case 'y': + if (CONST_INT_P (op)) + { + int val = exact_log2 (INTVAL (op)); + if (val != -1) + fprintf (file, "%d", val); + else + output_operand_lossage ("invalid use of '%%%c'", letter); + } + else + output_operand_lossage ("invalid use of '%%%c'", letter); + break; + case 'h': if (code == HIGH) op = XEXP (op, 0); diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 3d95a58..37d4cb4 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -181,6 +181,12 @@ struct mips_cpu_info { #define ISA_HAS_DSP_MULT ISA_HAS_DSPR2 #endif +/* ISA has LSA available. */ +#define ISA_HAS_LSA (mips_isa_rev >= 6) + +/* ISA has DLSA available. */ +#define ISA_HAS_DLSA (TARGET_64BIT && mips_isa_rev >= 6) + /* The ISA compression flags that are currently in effect. */ #define TARGET_COMPRESSION (target_flags & (MASK_MIPS16 | MASK_MICROMIPS)) diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index f7f2687..2fb2786 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -5541,6 +5541,16 @@ (define_insn "*<optab>si3_mips16" (set_attr "mode" "SI") (set_attr "extended_mips16" "no,no,yes")]) +(define_insn "<GPR:d>lsa" + [(set (match_operand:GPR 0 "register_operand" "=d") + (plus:GPR (mult:GPR (match_operand:GPR 1 "register_operand" "d") + (match_operand 2 "const_immlsa_operand" "")) + (match_operand:GPR 3 "register_operand" "d")))] + "ISA_HAS_<GPR:D>LSA" + "<GPR:d>lsa\t%0,%1,%3,%y2" + [(set_attr "type" "arith") + (set_attr "mode" "<GPR:MODE>")]) + ;; We need separate DImode MIPS16 patterns because of the irregularity ;; of right shifts. (define_insn "*ashldi3_mips16" diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index ba5c0e3..fa17ac7 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -33,6 +33,10 @@ (define_predicate "arith_operand" (ior (match_operand 0 "const_arith_operand") (match_operand 0 "register_operand"))) +(define_predicate "const_immlsa_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (exact_log2 (INTVAL (op)), 1, 4)"))) + (define_predicate "const_uimm6_operand" (and (match_code "const_int") (match_test "UIMM6_OPERAND (INTVAL (op))"))) diff --git a/gcc/testsuite/gcc.target/mips/lsa.c b/gcc/testsuite/gcc.target/mips/lsa.c new file mode 100644 index 0000000..d7be174 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/lsa.c @@ -0,0 +1,11 @@ +/* Test MIPS32R6 LSA instruction */ +/* { dg-do compile } */ +/* { dg-options "-mgp32 (HAS_LSA)" } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ + +/* { dg-final { scan-assembler "\tlsa\t" } } */ + +NOMIPS16 signed short test (signed short *a, int index) +{ + return a[index]; +} diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp index 4247cc9..3d6da81 100644 --- a/gcc/testsuite/gcc.target/mips/mips.exp +++ b/gcc/testsuite/gcc.target/mips/mips.exp @@ -253,6 +253,7 @@ set mips_option_groups { movn "HAS_MOVN" madd "HAS_MADD" maddps "HAS_MADDPS" + lsa "(|!)HAS_LSA" } for { set option 0 } { $option < 32 } { incr option } { @@ -1061,11 +1062,21 @@ proc mips-dg-options { args } { # Handle dependencies between the pre-arch options and the arch option. # This should mirror the arch and post-arch code below. if { !$arch_test_option_p } { + # We need a revision 6 or better ISA for: + # + # - When the LSA instruction is required + if { $isa_rev < 6 + && ([mips_have_test_option_p options "HAS_LSA"]) } { + if { $gp_size == 32 } { + mips_make_test_option options "-mips32r6" + } else { + mips_make_test_option options "-mips64r6" + } # We need a revision 2 or better ISA for: # # - the combination of -mgp32 -mfp64 # - the DSP ASE - if { $isa_rev < 2 + } elseif { $isa_rev < 2 && (($gp_size == 32 && [mips_have_test_option_p options "-mfp64"]) || [mips_have_test_option_p options "-msynci"] || [mips_have_test_option_p options "-mdsp"] @@ -1142,7 +1153,8 @@ proc mips-dg-options { args } { || [mips_have_test_option_p options "HAS_MADD"] || [mips_have_test_option_p options "-mpaired-single"] || [mips_have_test_option_p options "-mnan=legacy"] - || [mips_have_test_option_p options "-mabs=legacy"]) } { + || [mips_have_test_option_p options "-mabs=legacy"] + || [mips_have_test_option_p options "!HAS_LSA"]) } { if { $gp_size == 32 } { mips_make_test_option options "-mips32r5" } else { diff --git a/gcc/testsuite/gcc.target/mips/mips64-lsa.c b/gcc/testsuite/gcc.target/mips/mips64-lsa.c new file mode 100644 index 0000000..940847e --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/mips64-lsa.c @@ -0,0 +1,11 @@ +/* Test MIPS64R6 LSA instruction */ +/* { dg-do compile } */ +/* { dg-options "-mabi=64 (HAS_LSA)" } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ + +/* { dg-final { scan-assembler "\tdlsa\t" } } */ + +NOMIPS16 signed long long test (signed long long *a, int index) +{ + return a[index]; +} diff --git a/gcc/testsuite/gcc.target/mips/mulsize-2.c b/gcc/testsuite/gcc.target/mips/mulsize-2.c index 4cc2224..7c84bfd 100644 --- a/gcc/testsuite/gcc.target/mips/mulsize-2.c +++ b/gcc/testsuite/gcc.target/mips/mulsize-2.c @@ -1,3 +1,4 @@ +/* { dg-options "(!HAS_LSA)" } */ /* { dg-final { scan-assembler "\t.globl\tf9" } } */ /* { dg-final { scan-assembler "\tsll\t" } } */ /* { dg-final { scan-assembler "\taddu\t" } } */ diff --git a/gcc/testsuite/gcc.target/mips/mulsize-4.c b/gcc/testsuite/gcc.target/mips/mulsize-4.c index 7694d2c..f8a94a9 100644 --- a/gcc/testsuite/gcc.target/mips/mulsize-4.c +++ b/gcc/testsuite/gcc.target/mips/mulsize-4.c @@ -1,3 +1,4 @@ +/* { dg-options "(!HAS_LSA)" } */ /* { dg-final { scan-assembler "\t.globl\tf17" } } */ /* { dg-final { scan-assembler "\tsll\t" } } */ /* { dg-final { scan-assembler "\taddu\t" } } */ diff --git a/gcc/testsuite/gcc.target/mips/mulsize-5.c b/gcc/testsuite/gcc.target/mips/mulsize-5.c new file mode 100644 index 0000000..1c39a7e --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/mulsize-5.c @@ -0,0 +1,13 @@ +/* { dg-options "(HAS_LSA)" } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ +/* { dg-final { scan-assembler "\t.globl\tf9" } } */ +/* { dg-final { scan-assembler "\tlsa\t" } } */ +/* { dg-final { scan-assembler-not "\tsll\t" } } */ +/* { dg-final { scan-assembler-not "\taddu\t" } } */ +/* { dg-final { scan-assembler-not "\tli\t" } } */ +/* { dg-final { scan-assembler-not "\tmul\t" } } */ +int +f9(int x) +{ + return x * 9; +} diff --git a/gcc/testsuite/gcc.target/mips/mulsize-6.c b/gcc/testsuite/gcc.target/mips/mulsize-6.c new file mode 100644 index 0000000..6e9ca00 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/mulsize-6.c @@ -0,0 +1,13 @@ +/* { dg-options "(HAS_LSA)" } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ +/* { dg-final { scan-assembler "\t.globl\tf17" } } */ +/* { dg-final { scan-assembler "\tlsa\t" } } */ +/* { dg-final { scan-assembler-not "\tsll\t" } } */ +/* { dg-final { scan-assembler-not "\taddu\t" } } */ +/* { dg-final { scan-assembler-not "\tli\t" } } */ +/* { dg-final { scan-assembler-not "\tmul\t" } } */ +int +f17(int x) +{ + return x * 17; +} -- 2.2.1