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
This commit is contained in:
parent
842e098c5f
commit
b2c9d70fd7
@ -1,3 +1,23 @@
|
||||
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
|
||||
|
@ -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"))
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
11
gcc/testsuite/gcc.target/mips/ext-5.c
Normal file
11
gcc/testsuite/gcc.target/mips/ext-5.c
Normal file
@ -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;
|
||||
}
|
11
gcc/testsuite/gcc.target/mips/ext-6.c
Normal file
11
gcc/testsuite/gcc.target/mips/ext-6.c
Normal file
@ -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;
|
||||
}
|
11
gcc/testsuite/gcc.target/mips/ext-7.c
Normal file
11
gcc/testsuite/gcc.target/mips/ext-7.c
Normal file
@ -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;
|
||||
}
|
11
gcc/testsuite/gcc.target/mips/ext-8.c
Normal file
11
gcc/testsuite/gcc.target/mips/ext-8.c
Normal file
@ -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;
|
||||
}
|
12
gcc/testsuite/gcc.target/mips/extend-2.c
Normal file
12
gcc/testsuite/gcc.target/mips/extend-2.c
Normal file
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user