From 04877dac622082a4b927c88f686c7332a7846a50 Mon Sep 17 00:00:00 2001 From: nemet Date: Thu, 4 Sep 2008 21:02:30 +0000 Subject: [PATCH] * config/mips/mips.h (ISA_HAS_CINS): New macro. * config/mips/mips-protos.h (mask_low_and_shift_p, mask_low_and_shift_len): Declare. * config/mips/mips.c (mask_low_and_shift_p, mask_low_and_shift_len): New functions. (mips_print_operand): Handle new operand prefix "m". * config/mips/mips.md (*cins): New pattern. testsuite/ * gcc.target/mips/octeon-cins-1.c: New test. * gcc.target/mips/octeon-cins-2.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@140008 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 10 ++++++++ gcc/config/mips/mips-protos.h | 4 ++++ gcc/config/mips/mips.c | 34 +++++++++++++++++++++++++++ gcc/config/mips/mips.h | 3 +++ gcc/config/mips/mips.md | 22 +++++++++++++++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.target/mips/octeon-cins-1.c | 24 +++++++++++++++++++ gcc/testsuite/gcc.target/mips/octeon-cins-2.c | 15 ++++++++++++ 8 files changed, 117 insertions(+) create mode 100644 gcc/testsuite/gcc.target/mips/octeon-cins-1.c create mode 100644 gcc/testsuite/gcc.target/mips/octeon-cins-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9146cfb945a..2350a47c9eb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2008-09-04 Adam Nemet + + * config/mips/mips.h (ISA_HAS_CINS): New macro. + * config/mips/mips-protos.h (mask_low_and_shift_p, + mask_low_and_shift_len): Declare. + * config/mips/mips.c (mask_low_and_shift_p, + mask_low_and_shift_len): New functions. + (mips_print_operand): Handle new operand prefix "m". + * config/mips/mips.md (*cins): New pattern. + 2008-09-04 Bernd Schmidt * config/bfin/bfin.c (gen_one_bundle): Don't create new nops when diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 01645a1ebc2..9403945a4f3 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -314,6 +314,10 @@ extern bool mips_use_ins_ext_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT); extern const char *mips16e_output_save_restore (rtx, HOST_WIDE_INT); extern bool mips16e_save_restore_pattern_p (rtx, HOST_WIDE_INT, struct mips16e_save_restore_info *); + +extern bool mask_low_and_shift_p (enum machine_mode, rtx, rtx, int); +extern int mask_low_and_shift_len (enum machine_mode, rtx, rtx); + union mips_gen_fn_ptrs { rtx (*fn_6) (rtx, rtx, rtx, rtx, rtx, rtx); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index dea7ffe57fa..911f93c2b4f 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -6659,6 +6659,32 @@ mips_use_ins_ext_p (rtx op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos) return true; } + +/* Check if MASK and SHIFT are valid in mask-low-and-shift-left + operation if MAXLEN is the maxium length of consecutive bits that + can make up MASK. MODE is the mode of the operation. See + mask_low_and_shift_len for the actual definition. */ + +bool +mask_low_and_shift_p (enum machine_mode mode, rtx mask, rtx shift, int maxlen) +{ + return IN_RANGE (mask_low_and_shift_len (mode, mask, shift), 1, maxlen); +} + +/* The canonical form of a mask-low-and-shift-left operation is + (and (ashift X SHIFT) MASK) where MASK has the lower SHIFT number of bits + cleared. Thus we need to shift MASK to the right before checking if it + is a valid mask value. MODE is the mode of the operation. If true + return the length of the mask, otherwise return -1. */ + +int +mask_low_and_shift_len (enum machine_mode mode, rtx mask, rtx shift) +{ + HOST_WIDE_INT shval; + + shval = INTVAL (shift) & (GET_MODE_BITSIZE (mode) - 1); + return exact_log2 ((UINTVAL (mask) >> shval) + 1); +} /* Return true if -msplit-addresses is selected and should be honored. @@ -7026,6 +7052,7 @@ mips_print_float_branch_condition (FILE *file, enum rtx_code code, int letter) 'X' Print CONST_INT OP in hexadecimal format. '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. 'h' Print the high-part relocation associated with OP, after stripping any outermost HIGH. 'R' Print the low-part relocation associated with OP. @@ -7081,6 +7108,13 @@ mips_print_operand (FILE *file, rtx op, int letter) output_operand_lossage ("invalid use of '%%%c'", letter); break; + case 'm': + if (GET_CODE (op) == CONST_INT) + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op) - 1); + 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 86b886a373f..a3f47f79dcf 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1009,6 +1009,9 @@ enum mips_code_readable_setting { /* ISA includes the bbit* instructions. */ #define ISA_HAS_BBIT TARGET_OCTEON +/* ISA includes the cins instruction. */ +#define ISA_HAS_CINS TARGET_OCTEON + /* ISA includes the pop instruction. */ #define ISA_HAS_POP TARGET_OCTEON diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 0aba384144d..04dd30a1e10 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -3441,6 +3441,28 @@ [(set_attr "type" "arith") (set_attr "mode" "")]) +;; Combiner pattern for cins (clear and insert bit field). We can +;; implement mask-and-shift-left operation with this. Note that if +;; the upper bit of the mask is set in an SImode operation, the mask +;; itself will be sign-extended. mask_low_and_shift_len will +;; therefore be greater than our threshold of 32. + +(define_insn "*cins" + [(set (match_operand:GPR 0 "register_operand" "=d") + (and:GPR + (ashift:GPR (match_operand:GPR 1 "register_operand" "d") + (match_operand:GPR 2 "const_int_operand" "")) + (match_operand:GPR 3 "const_int_operand" "")))] + "ISA_HAS_CINS + && mask_low_and_shift_p (mode, operands[3], operands[2], 32)" +{ + operands[3] = + GEN_INT (mask_low_and_shift_len (mode, operands[3], operands[2])); + return "cins\t%0,%1,%2,%m3"; +} + [(set_attr "type" "shift") + (set_attr "mode" "")]) + ;; Unaligned word moves generated by the bit field patterns. ;; ;; As far as the rtl is concerned, both the left-part and right-part diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6849f7c9af1..b6f573e7fc0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-09-04 Adam Nemet + + * gcc.target/mips/octeon-cins-1.c: New test. + * gcc.target/mips/octeon-cins-2.c: New test. + 2008-09-04 Richard Guenther * gfortran.dg/internal_pack_4.f90: Adjust pattern. diff --git a/gcc/testsuite/gcc.target/mips/octeon-cins-1.c b/gcc/testsuite/gcc.target/mips/octeon-cins-1.c new file mode 100644 index 00000000000..27dc6b3d2b7 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/octeon-cins-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* The tests also work with -mgp32. For long long tests, only one of + the 32-bit parts is used. */ +/* { dg-mips-options "-O -march=octeon" } */ +/* { dg-final { scan-assembler-times "\tcins\t" 3 } } */ +/* { dg-final { scan-assembler-not "\tandi\t|sll\t" } } */ + +NOMIPS16 long long +f (long long i) +{ + return (i & 0xff) << 34; +} + +NOMIPS16 int +g (int i) +{ + return (i << 4) & 0xff0; +} + +NOMIPS16 long long +h (long long i) +{ + return (i << 4) & 0xfff; +} diff --git a/gcc/testsuite/gcc.target/mips/octeon-cins-2.c b/gcc/testsuite/gcc.target/mips/octeon-cins-2.c new file mode 100644 index 00000000000..c60ee933ffa --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/octeon-cins-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-O -march=octeon -mgp64" } */ +/* { dg-final { scan-assembler-not "\tcins\t" } } */ + +NOMIPS16 unsigned +f (unsigned i) +{ + return (i & 0xff) << 24; +} + +NOMIPS16 unsigned long long +g (unsigned long long i) +{ + return (i & 0x1ffffffffULL) << 4; +} -- 2.11.4.GIT