aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAdam Nemet <anemet@caviumnetworks.com>2009-08-11 17:41:09 +0000
committerAdam Nemet <nemet@gcc.gnu.org>2009-08-11 17:41:09 +0000
commitb2c9d70fd7eb8e39aefb7d6d2329ccbd5da15b36 (patch)
tree65c7c636969426abfeb559712330ea2dbb860d4b /gcc
parent842e098c5ff56730b4d84d5560eb4053a12ebd61 (diff)
downloadgcc-b2c9d70fd7eb8e39aefb7d6d2329ccbd5da15b36.zip
gcc-b2c9d70fd7eb8e39aefb7d6d2329ccbd5da15b36.tar.gz
gcc-b2c9d70fd7eb8e39aefb7d6d2329ccbd5da15b36.tar.bz2
predicates.md (qi_mask_operand, [...]): New predicates.
* config/mips/predicates.md (qi_mask_operand, hi_mask_operand, si_mask_operand, and_load_operand, low_bitmask_operand, and_reg_operand, and_operand): New predicates. * config/mips/constraints.md (Yb, Yh, Yw, Yz): New constraints. * config/mips/mips.c (and_operands_ok): New function. * config/mips/mips-protos.h (and_operands_ok): Declare it. * config/mips/mips.md (move_type): Add ext_ins and logical. (type): Handle them. (and<mode>3): Use and_reg_operand as the second operand's predicate. (*and<mode>3): Add alternatives for lbu, lhu, lwu, <d>ext and shift_shift. Remove commutative constraint modifier. (*and<mode>3_mips16): Add alternatives for lbu, lhu, lwu and shift_shift. (*clear_upper32_dext): Remove define_insn_and_split. (*clear_upper32): Turn this define_insn_and_split ... (splitter for ANDing register with 0xffff_ffff): .. into this. testsuite/ * gcc.target/mips/ext-5.c: New test. * gcc.target/mips/ext-6.c: New test. * gcc.target/mips/ext-7.c: New test. * gcc.target/mips/ext-8.c: New test. * gcc.target/mips/extend-2.c: New test. From-SVN: r150657
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/config/mips/constraints.md16
-rw-r--r--gcc/config/mips/mips-protos.h1
-rw-r--r--gcc/config/mips/mips.c12
-rw-r--r--gcc/config/mips/mips.md146
-rw-r--r--gcc/config/mips/predicates.md33
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.target/mips/ext-5.c11
-rw-r--r--gcc/testsuite/gcc.target/mips/ext-6.c11
-rw-r--r--gcc/testsuite/gcc.target/mips/ext-7.c11
-rw-r--r--gcc/testsuite/gcc.target/mips/ext-8.c11
-rw-r--r--gcc/testsuite/gcc.target/mips/extend-2.c12
12 files changed, 238 insertions, 54 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2691d51..d146a2e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,25 @@
2009-08-11 Adam Nemet <anemet@caviumnetworks.com>
+ * config/mips/predicates.md (qi_mask_operand, hi_mask_operand,
+ si_mask_operand, and_load_operand, low_bitmask_operand,
+ and_reg_operand, and_operand): New predicates.
+ * config/mips/constraints.md (Yb, Yh, Yw, Yz): New constraints.
+ * config/mips/mips.c (and_operands_ok): New function.
+ * config/mips/mips-protos.h (and_operands_ok): Declare it.
+ * config/mips/mips.md (move_type): Add ext_ins and logical.
+ (type): Handle them.
+ (and<mode>3): Use and_reg_operand as the second operand's
+ predicate.
+ (*and<mode>3): Add alternatives for lbu, lhu, lwu, <d>ext and
+ shift_shift. Remove commutative constraint modifier.
+ (*and<mode>3_mips16): Add alternatives for lbu, lhu, lwu and
+ shift_shift.
+ (*clear_upper32_dext): Remove define_insn_and_split.
+ (*clear_upper32): Turn this define_insn_and_split ...
+ (splitter for ANDing register with 0xffff_ffff): .. into this.
+
+2009-08-11 Adam Nemet <anemet@caviumnetworks.com>
+
* combine.c (try_widen_shift_mode): Factor out code to check if an
integer constant is a low-order bitmask from here ...
* rtlanal.c (low_bitmask_len): ... to here.
diff --git a/gcc/config/mips/constraints.md b/gcc/config/mips/constraints.md
index a749855..a29d2c9 100644
--- a/gcc/config/mips/constraints.md
+++ b/gcc/config/mips/constraints.md
@@ -215,3 +215,19 @@
A signed 10-bit constant."
(and (match_code "const_int")
(match_test "IMM10_OPERAND (ival)")))
+
+(define_constraint "Yb"
+ "@internal"
+ (match_operand 0 "qi_mask_operand"))
+
+(define_constraint "Yh"
+ "@internal"
+ (match_operand 0 "hi_mask_operand"))
+
+(define_constraint "Yw"
+ "@internal"
+ (match_operand 0 "si_mask_operand"))
+
+(define_constraint "Yx"
+ "@internal"
+ (match_operand 0 "low_bitmask_operand"))
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index c96ecae..40ffd7f 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -316,6 +316,7 @@ extern bool mips16e_save_restore_pattern_p (rtx, HOST_WIDE_INT,
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);
+extern bool and_operands_ok (enum machine_mode, rtx, rtx);
union mips_gen_fn_ptrs
{
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 1b9c6e7..2dd0118 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -6786,6 +6786,18 @@ 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);
}
+/* Return true iff OP1 and OP2 are valid operands together for the
+ *and<MODE>3 and *and<MODE>3_mips16 patterns. For the cases to consider,
+ see the table in the comment before the pattern. */
+
+bool
+and_operands_ok (enum machine_mode mode, rtx op1, rtx op2)
+{
+ return (memory_operand (op1, mode)
+ ? and_load_operand (op2, mode)
+ : and_reg_operand (op2, mode));
+}
+
/* 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
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 02e9937..bbea6f3 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -301,6 +301,7 @@
;; sll0 "sll DEST,SRC,0", which on 64-bit targets is guaranteed
;; to produce a sign-extended DEST, even if SRC is not
;; properly sign-extended
+;; ext_ins EXT, DEXT, INS or DINS instruction
;; andi a single ANDI instruction
;; loadpool move a constant into a MIPS16 register by loading it
;; from the pool
@@ -313,7 +314,8 @@
;; scheduling type to be "multi" instead.
(define_attr "move_type"
"unknown,load,fpload,store,fpstore,mtc,mfc,mthilo,mfhilo,move,fmove,
- const,constN,signext,arith,sll0,andi,loadpool,shift_shift,lui_movf"
+ const,constN,signext,ext_ins,logical,arith,sll0,andi,loadpool,
+ shift_shift,lui_movf"
(const_string "unknown"))
;; Main data type used by the insn
@@ -408,7 +410,9 @@
(eq_attr "move_type" "fmove") (const_string "fmove")
(eq_attr "move_type" "loadpool") (const_string "load")
(eq_attr "move_type" "signext") (const_string "signext")
+ (eq_attr "move_type" "ext_ins") (const_string "arith")
(eq_attr "move_type" "arith") (const_string "arith")
+ (eq_attr "move_type" "logical") (const_string "logical")
(eq_attr "move_type" "sll0") (const_string "shift")
(eq_attr "move_type" "andi") (const_string "logical")
@@ -2561,31 +2565,91 @@
(define_expand "and<mode>3"
[(set (match_operand:GPR 0 "register_operand")
(and:GPR (match_operand:GPR 1 "register_operand")
- (match_operand:GPR 2 "uns_arith_operand")))]
- ""
-{
- if (TARGET_MIPS16)
- operands[2] = force_reg (<MODE>mode, operands[2]);
-})
+ (match_operand:GPR 2 "and_reg_operand")))])
+
+;; The middle-end is not allowed to convert ANDing with 0xffff_ffff into a
+;; zero_extendsidi2 because of TRULY_NOOP_TRUNCATION, so handle these here.
+;; Note that this variant does not trigger for SI mode because we require
+;; a 64-bit HOST_WIDE_INT and 0xffff_ffff wouldn't be a canonical
+;; sign-extended SImode value.
+;;
+;; These are possible combinations for operand 1 and 2. The table
+;; includes both MIPS and MIPS16 cases. (r=register, mem=memory,
+;; 16=MIPS16, x=match, S=split):
+;;
+;; \ op1 r/EXT r/!EXT mem r/16 mem/16
+;; op2
+;;
+;; andi x x
+;; 0xff x x x x
+;; 0xffff x x x x
+;; 0xffff_ffff x S x S x
+;; low-bitmask x
+;; register x x
+;; register =op1 x
(define_insn "*and<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (and:GPR (match_operand:GPR 1 "register_operand" "%d,d")
- (match_operand:GPR 2 "uns_arith_operand" "d,K")))]
- "!TARGET_MIPS16"
- "@
- and\t%0,%1,%2
- andi\t%0,%1,%x2"
- [(set_attr "type" "logical")
+ [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d,d,d")
+ (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "o,o,W,d,d,d,d")
+ (match_operand:GPR 2 "and_operand" "Yb,Yh,Yw,K,Yx,Yw,d")))]
+ "!TARGET_MIPS16 && and_operands_ok (<MODE>mode, operands[1], operands[2])"
+{
+ int len;
+
+ switch (which_alternative)
+ {
+ case 0:
+ operands[1] = gen_lowpart (QImode, operands[1]);
+ return "lbu\t%0,%1";
+ case 1:
+ operands[1] = gen_lowpart (HImode, operands[1]);
+ return "lhu\t%0,%1";
+ case 2:
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ return "lwu\t%0,%1";
+ case 3:
+ return "andi\t%0,%1,%x2";
+ case 4:
+ len = low_bitmask_len (<MODE>mode, INTVAL (operands[2]));
+ operands[2] = GEN_INT (len);
+ return "<d>ext\t%0,%1,0,%2";
+ case 5:
+ return "#";
+ case 6:
+ return "and\t%0,%1,%2";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "move_type" "load,load,load,andi,ext_ins,shift_shift,logical")
(set_attr "mode" "<MODE>")])
(define_insn "*and<mode>3_mips16"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (and:GPR (match_operand:GPR 1 "register_operand" "%0")
- (match_operand:GPR 2 "register_operand" "d")))]
- "TARGET_MIPS16"
- "and\t%0,%2"
- [(set_attr "type" "logical")
+ [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+ (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "%o,o,W,d,0")
+ (match_operand:GPR 2 "and_operand" "Yb,Yh,Yw,Yw,d")))]
+ "TARGET_MIPS16 && and_operands_ok (<MODE>mode, operands[1], operands[2])"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ operands[1] = gen_lowpart (QImode, operands[1]);
+ return "lbu\t%0,%1";
+ case 1:
+ operands[1] = gen_lowpart (HImode, operands[1]);
+ return "lhu\t%0,%1";
+ case 2:
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ return "lwu\t%0,%1";
+ case 3:
+ return "#";
+ case 4:
+ return "and\t%0,%2";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "move_type" "load,load,load,shift_shift,logical")
(set_attr "mode" "<MODE>")])
(define_expand "ior<mode>3"
@@ -2778,44 +2842,18 @@
[(set_attr "move_type" "arith,load")
(set_attr "mode" "DI")])
-;; Combine is not allowed to convert this insn into a zero_extendsidi2
-;; because of TRULY_NOOP_TRUNCATION.
+;; See the comment before the *and<mode>3 pattern why this is generated by
+;; combine.
-(define_insn_and_split "*clear_upper32"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,W")
+(define_split
+ [(set (match_operand:DI 0 "register_operand")
+ (and:DI (match_operand:DI 1 "register_operand")
(const_int 4294967295)))]
- "TARGET_64BIT && !ISA_HAS_EXT_INS"
-{
- if (which_alternative == 0)
- return "#";
-
- operands[1] = gen_lowpart (SImode, operands[1]);
- return "lwu\t%0,%1";
-}
- "&& reload_completed && REG_P (operands[1])"
+ "TARGET_64BIT && !ISA_HAS_EXT_INS && reload_completed"
[(set (match_dup 0)
(ashift:DI (match_dup 1) (const_int 32)))
(set (match_dup 0)
- (lshiftrt:DI (match_dup 0) (const_int 32)))]
- ""
- [(set_attr "move_type" "shift_shift,load")
- (set_attr "mode" "DI")])
-
-(define_insn "*clear_upper32_dext"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,W")
- (const_int 4294967295)))]
- "TARGET_64BIT && ISA_HAS_EXT_INS"
-{
- if (which_alternative == 0)
- return "dext\t%0,%1,0,32";
-
- operands[1] = gen_lowpart (SImode, operands[1]);
- return "lwu\t%0,%1";
-}
- [(set_attr "move_type" "arith,load")
- (set_attr "mode" "DI")])
+ (lshiftrt:DI (match_dup 0) (const_int 32)))])
(define_expand "zero_extend<SHORT:mode><GPR:mode>2"
[(set (match_operand:GPR 0 "register_operand")
diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md
index d32eaf1..a9a0177 100644
--- a/gcc/config/mips/predicates.md
+++ b/gcc/config/mips/predicates.md
@@ -76,6 +76,39 @@
(ior (match_test "op == CONST0_RTX (GET_MODE (op))")
(match_test "op == CONST1_RTX (GET_MODE (op))"))))
+(define_predicate "qi_mask_operand"
+ (and (match_code "const_int")
+ (match_test "UINTVAL (op) == 0xff")))
+
+(define_predicate "hi_mask_operand"
+ (and (match_code "const_int")
+ (match_test "UINTVAL (op) == 0xffff")))
+
+(define_predicate "si_mask_operand"
+ (and (match_code "const_int")
+ (match_test "UINTVAL (op) == 0xffffffff")))
+
+(define_predicate "and_load_operand"
+ (ior (match_operand 0 "qi_mask_operand")
+ (match_operand 0 "hi_mask_operand")
+ (match_operand 0 "si_mask_operand")))
+
+(define_predicate "low_bitmask_operand"
+ (and (match_test "ISA_HAS_EXT_INS")
+ (match_code "const_int")
+ (match_test "low_bitmask_len (mode, INTVAL (op)) > 16")))
+
+(define_predicate "and_reg_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (match_test "!TARGET_MIPS16")
+ (match_operand 0 "const_uns_arith_operand"))
+ (match_operand 0 "low_bitmask_operand")
+ (match_operand 0 "si_mask_operand")))
+
+(define_predicate "and_operand"
+ (ior (match_operand 0 "and_load_operand")
+ (match_operand 0 "and_reg_operand")))
+
(define_predicate "d_operand"
(and (match_code "reg")
(match_test "TARGET_MIPS16
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bea2eaa..017a12b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2009-08-11 Adam Nemet <anemet@caviumnetworks.com>
+
+ * gcc.target/mips/ext-5.c: New test.
+ * gcc.target/mips/ext-6.c: New test.
+ * gcc.target/mips/ext-7.c: New test.
+ * gcc.target/mips/ext-8.c: New test.
+ * gcc.target/mips/extend-2.c: New test.
+
2009-08-10 Jason Merrill <jason@redhat.com>
* g++.dg/other/linkage2.C: New test for types-without-linkage
diff --git a/gcc/testsuite/gcc.target/mips/ext-5.c b/gcc/testsuite/gcc.target/mips/ext-5.c
new file mode 100644
index 0000000..6418638
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/ext-5.c
@@ -0,0 +1,11 @@
+/* For MIPS32r2 use EXT when ANDing with low-order bitmasks. */
+/* { dg-do compile } */
+/* { dg-options "-O isa_rev>=2" } */
+/* { dg-final { scan-assembler "\text\t" } } */
+/* { dg-final { scan-assembler-not "\tandi?\t" } } */
+
+NOMIPS16 unsigned
+f (unsigned i)
+{
+ return i & 0x7ffffff;
+}
diff --git a/gcc/testsuite/gcc.target/mips/ext-6.c b/gcc/testsuite/gcc.target/mips/ext-6.c
new file mode 100644
index 0000000..b4a7dd2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/ext-6.c
@@ -0,0 +1,11 @@
+/* For MIPS64r2 use DEXT when ANDing with low-order bitmasks. */
+/* { dg-do compile } */
+/* { dg-options "-O isa_rev>=2 -mgp64" } */
+/* { dg-final { scan-assembler "\tdext\t" } } */
+/* { dg-final { scan-assembler-not "\tandi?\t" } } */
+
+NOMIPS16 unsigned long long
+f (unsigned long long i)
+{
+ return i & 0x7ffffffffff;
+}
diff --git a/gcc/testsuite/gcc.target/mips/ext-7.c b/gcc/testsuite/gcc.target/mips/ext-7.c
new file mode 100644
index 0000000..394d41f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/ext-7.c
@@ -0,0 +1,11 @@
+/* No need to use ext if we can use andi. */
+/* { dg-do compile } */
+/* { dg-options "-O isa_rev>=2" } */
+/* { dg-final { scan-assembler "\tandi\t" } } */
+/* { dg-final { scan-assembler-not "\td?ext\t" } } */
+
+NOMIPS16 unsigned
+f (unsigned i)
+{
+ return i & 0x7fff;
+}
diff --git a/gcc/testsuite/gcc.target/mips/ext-8.c b/gcc/testsuite/gcc.target/mips/ext-8.c
new file mode 100644
index 0000000..90241dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/ext-8.c
@@ -0,0 +1,11 @@
+/* Also make sure we don't use ext for MIPS*r1. */
+/* { dg-do compile } */
+/* { dg-options "-O isa_rev<=1" } */
+/* { dg-final { scan-assembler "\tand\t" } } */
+/* { dg-final { scan-assembler-not "\td?ext\t" } } */
+
+unsigned
+f (unsigned i)
+{
+ return i & 0x7fffff;
+}
diff --git a/gcc/testsuite/gcc.target/mips/extend-2.c b/gcc/testsuite/gcc.target/mips/extend-2.c
new file mode 100644
index 0000000..b91ae20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/extend-2.c
@@ -0,0 +1,12 @@
+/* Check the shift_shift alternative of the AND patterns. */
+/* { dg-do compile } */
+/* { dg-options "-O isa_rev<=1 -mgp64" } */
+/* { dg-final { scan-assembler "\tdsrl\t" } } */
+/* { dg-final { scan-assembler "\tdsll\t" } } */
+/* { dg-final { scan-assembler-not "\td?ext\t" } } */
+
+unsigned long long
+f (unsigned long long i)
+{
+ return i & 0xffffffff;
+}