Commit b2c9d70f by Adam Nemet Committed by Adam Nemet

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
parent 842e098c
2009-08-11 Adam Nemet <anemet@caviumnetworks.com> 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 * combine.c (try_widen_shift_mode): Factor out code to check if an
integer constant is a low-order bitmask from here ... integer constant is a low-order bitmask from here ...
* rtlanal.c (low_bitmask_len): ... to here. * rtlanal.c (low_bitmask_len): ... to here.
......
...@@ -215,3 +215,19 @@ ...@@ -215,3 +215,19 @@
A signed 10-bit constant." A signed 10-bit constant."
(and (match_code "const_int") (and (match_code "const_int")
(match_test "IMM10_OPERAND (ival)"))) (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, ...@@ -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 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 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 union mips_gen_fn_ptrs
{ {
......
...@@ -6786,6 +6786,18 @@ mask_low_and_shift_p (enum machine_mode mode, rtx mask, rtx shift, int maxlen) ...@@ -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 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 /* 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 (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 cleared. Thus we need to shift MASK to the right before checking if it
......
...@@ -301,6 +301,7 @@ ...@@ -301,6 +301,7 @@
;; sll0 "sll DEST,SRC,0", which on 64-bit targets is guaranteed ;; sll0 "sll DEST,SRC,0", which on 64-bit targets is guaranteed
;; to produce a sign-extended DEST, even if SRC is not ;; to produce a sign-extended DEST, even if SRC is not
;; properly sign-extended ;; properly sign-extended
;; ext_ins EXT, DEXT, INS or DINS instruction
;; andi a single ANDI instruction ;; andi a single ANDI instruction
;; loadpool move a constant into a MIPS16 register by loading it ;; loadpool move a constant into a MIPS16 register by loading it
;; from the pool ;; from the pool
...@@ -313,7 +314,8 @@ ...@@ -313,7 +314,8 @@
;; scheduling type to be "multi" instead. ;; scheduling type to be "multi" instead.
(define_attr "move_type" (define_attr "move_type"
"unknown,load,fpload,store,fpstore,mtc,mfc,mthilo,mfhilo,move,fmove, "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")) (const_string "unknown"))
;; Main data type used by the insn ;; Main data type used by the insn
...@@ -408,7 +410,9 @@ ...@@ -408,7 +410,9 @@
(eq_attr "move_type" "fmove") (const_string "fmove") (eq_attr "move_type" "fmove") (const_string "fmove")
(eq_attr "move_type" "loadpool") (const_string "load") (eq_attr "move_type" "loadpool") (const_string "load")
(eq_attr "move_type" "signext") (const_string "signext") (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" "arith") (const_string "arith")
(eq_attr "move_type" "logical") (const_string "logical")
(eq_attr "move_type" "sll0") (const_string "shift") (eq_attr "move_type" "sll0") (const_string "shift")
(eq_attr "move_type" "andi") (const_string "logical") (eq_attr "move_type" "andi") (const_string "logical")
...@@ -2561,31 +2565,91 @@ ...@@ -2561,31 +2565,91 @@
(define_expand "and<mode>3" (define_expand "and<mode>3"
[(set (match_operand:GPR 0 "register_operand") [(set (match_operand:GPR 0 "register_operand")
(and:GPR (match_operand:GPR 1 "register_operand") (and:GPR (match_operand:GPR 1 "register_operand")
(match_operand:GPR 2 "uns_arith_operand")))] (match_operand:GPR 2 "and_reg_operand")))])
""
{ ;; The middle-end is not allowed to convert ANDing with 0xffff_ffff into a
if (TARGET_MIPS16) ;; zero_extendsidi2 because of TRULY_NOOP_TRUNCATION, so handle these here.
operands[2] = force_reg (<MODE>mode, operands[2]); ;; 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" (define_insn "*and<mode>3"
[(set (match_operand:GPR 0 "register_operand" "=d,d") [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d,d,d")
(and:GPR (match_operand:GPR 1 "register_operand" "%d,d") (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "o,o,W,d,d,d,d")
(match_operand:GPR 2 "uns_arith_operand" "d,K")))] (match_operand:GPR 2 "and_operand" "Yb,Yh,Yw,K,Yx,Yw,d")))]
"!TARGET_MIPS16" "!TARGET_MIPS16 && and_operands_ok (<MODE>mode, operands[1], operands[2])"
"@ {
and\t%0,%1,%2 int len;
andi\t%0,%1,%x2"
[(set_attr "type" "logical") 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>")]) (set_attr "mode" "<MODE>")])
(define_insn "*and<mode>3_mips16" (define_insn "*and<mode>3_mips16"
[(set (match_operand:GPR 0 "register_operand" "=d") [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
(and:GPR (match_operand:GPR 1 "register_operand" "%0") (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "%o,o,W,d,0")
(match_operand:GPR 2 "register_operand" "d")))] (match_operand:GPR 2 "and_operand" "Yb,Yh,Yw,Yw,d")))]
"TARGET_MIPS16" "TARGET_MIPS16 && and_operands_ok (<MODE>mode, operands[1], operands[2])"
"and\t%0,%2" {
[(set_attr "type" "logical") 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>")]) (set_attr "mode" "<MODE>")])
(define_expand "ior<mode>3" (define_expand "ior<mode>3"
...@@ -2778,44 +2842,18 @@ ...@@ -2778,44 +2842,18 @@
[(set_attr "move_type" "arith,load") [(set_attr "move_type" "arith,load")
(set_attr "mode" "DI")]) (set_attr "mode" "DI")])
;; Combine is not allowed to convert this insn into a zero_extendsidi2 ;; See the comment before the *and<mode>3 pattern why this is generated by
;; because of TRULY_NOOP_TRUNCATION. ;; combine.
(define_insn_and_split "*clear_upper32" (define_split
[(set (match_operand:DI 0 "register_operand" "=d,d") [(set (match_operand:DI 0 "register_operand")
(and:DI (match_operand:DI 1 "nonimmediate_operand" "d,W") (and:DI (match_operand:DI 1 "register_operand")
(const_int 4294967295)))] (const_int 4294967295)))]
"TARGET_64BIT && !ISA_HAS_EXT_INS" "TARGET_64BIT && !ISA_HAS_EXT_INS && reload_completed"
{
if (which_alternative == 0)
return "#";
operands[1] = gen_lowpart (SImode, operands[1]);
return "lwu\t%0,%1";
}
"&& reload_completed && REG_P (operands[1])"
[(set (match_dup 0) [(set (match_dup 0)
(ashift:DI (match_dup 1) (const_int 32))) (ashift:DI (match_dup 1) (const_int 32)))
(set (match_dup 0) (set (match_dup 0)
(lshiftrt:DI (match_dup 0) (const_int 32)))] (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")])
(define_expand "zero_extend<SHORT:mode><GPR:mode>2" (define_expand "zero_extend<SHORT:mode><GPR:mode>2"
[(set (match_operand:GPR 0 "register_operand") [(set (match_operand:GPR 0 "register_operand")
......
...@@ -76,6 +76,39 @@ ...@@ -76,6 +76,39 @@
(ior (match_test "op == CONST0_RTX (GET_MODE (op))") (ior (match_test "op == CONST0_RTX (GET_MODE (op))")
(match_test "op == CONST1_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" (define_predicate "d_operand"
(and (match_code "reg") (and (match_code "reg")
(match_test "TARGET_MIPS16 (match_test "TARGET_MIPS16
......
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> 2009-08-10 Jason Merrill <jason@redhat.com>
* g++.dg/other/linkage2.C: New test for types-without-linkage * g++.dg/other/linkage2.C: New test for types-without-linkage
......
/* 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;
}
/* 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;
}
/* 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;
}
/* 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;
}
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment