From b2c9d70fd7eb8e39aefb7d6d2329ccbd5da15b36 Mon Sep 17 00:00:00 2001 From: Adam Nemet Date: Tue, 11 Aug 2009 17:41:09 +0000 Subject: [PATCH] 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. (and3): Use and_reg_operand as the second operand's predicate. (*and3): Add alternatives for lbu, lhu, lwu, ext and shift_shift. Remove commutative constraint modifier. (*and3_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 --- gcc/ChangeLog | 20 +++++ gcc/config/mips/constraints.md | 16 ++++ gcc/config/mips/mips-protos.h | 1 + gcc/config/mips/mips.c | 12 +++ gcc/config/mips/mips.md | 146 +++++++++++++++++++------------ gcc/config/mips/predicates.md | 33 +++++++ gcc/testsuite/ChangeLog | 8 ++ gcc/testsuite/gcc.target/mips/ext-5.c | 11 +++ gcc/testsuite/gcc.target/mips/ext-6.c | 11 +++ gcc/testsuite/gcc.target/mips/ext-7.c | 11 +++ gcc/testsuite/gcc.target/mips/ext-8.c | 11 +++ gcc/testsuite/gcc.target/mips/extend-2.c | 12 +++ 12 files changed, 238 insertions(+), 54 deletions(-) create mode 100644 gcc/testsuite/gcc.target/mips/ext-5.c create mode 100644 gcc/testsuite/gcc.target/mips/ext-6.c create mode 100644 gcc/testsuite/gcc.target/mips/ext-7.c create mode 100644 gcc/testsuite/gcc.target/mips/ext-8.c create mode 100644 gcc/testsuite/gcc.target/mips/extend-2.c 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 + * 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. + (and3): Use and_reg_operand as the second operand's + predicate. + (*and3): Add alternatives for lbu, lhu, lwu, ext and + shift_shift. Remove commutative constraint modifier. + (*and3_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 + * 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 + *and3 and *and3_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 "and3" [(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, 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 "*and3" - [(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, 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, INTVAL (operands[2])); + operands[2] = GEN_INT (len); + return "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" "")]) (define_insn "*and3_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, 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" "")]) (define_expand "ior3" @@ -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 *and3 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_extend2" [(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 + + * 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 * 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; +} -- 2.7.4