diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9fcf3ca1dbe4..f161d63f41dd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2012-07-03 Oleg Endo + + * config/sh/predicates.md (logical_and_operand): New predicate. + * config/sh/constraints.md (Jmb, Jmw): New constraints. + * config/sh/sh.md (andsi3): Move expander above insns. Add handling + of 0xFFFF constant. Use logical_and_operand predicate and + satisfies_constraint_Jmb, satisfies_constraint_Jmw. + (*andsi3_compact): Make it an insn_and_split. Use + logical_and_operand predicate. Add Jmb,Jmw alternatives. + 2012-07-03 Jason Merrill PR c++/53826 diff --git a/gcc/config/sh/constraints.md b/gcc/config/sh/constraints.md index 6c9bc5ecc95d..8642ea808a73 100644 --- a/gcc/config/sh/constraints.md +++ b/gcc/config/sh/constraints.md @@ -31,6 +31,8 @@ ;; IJKLMNOP: CONT_INT constants ;; Ixx: signed xx bit ;; J16: 0xffffffff00000000 | 0x00000000ffffffff +;; Jmb: 0x000000FF +;; Jmw: 0x0000FFFF ;; Kxx: unsigned xx bit ;; M: 1 ;; N: 0 @@ -135,6 +137,16 @@ (and (match_code "const_int") (match_test "CONST_OK_FOR_J16 (ival)"))) +(define_constraint "Jmb" + "Low byte mask constant 0x000000FF" + (and (match_code "const_int") + (match_test "ival == 0xFF"))) + +(define_constraint "Jmw" + "Low word mask constant 0x0000FFFF" + (and (match_code "const_int") + (match_test "ival == 0xFFFF"))) + (define_constraint "K03" "An unsigned 3-bit constant, as used in SH2A bclr, bset, etc." (and (match_code "const_int") diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index d58f657c857d..3e7efd350448 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -574,6 +574,21 @@ return 0; }) +;; Like logical_operand but allows additional constant values which can be +;; done with zero extensions. Used for the second operand of and insns. +(define_predicate "logical_and_operand" + (match_code "subreg,reg,const_int") +{ + if (logical_operand (op, mode)) + return 1; + + if (! TARGET_SHMEDIA + && (satisfies_constraint_Jmb (op) || satisfies_constraint_Jmw (op))) + return 1; + + return 0; +}) + ;; TODO: Add a comment here. (define_predicate "logical_operator" diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 4e2425f4888e..1dda1943cba7 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -3113,12 +3113,55 @@ label: ;; Logical operations ;; ------------------------------------------------------------------------- -(define_insn "*andsi3_compact" - [(set (match_operand:SI 0 "arith_reg_dest" "=z,r") - (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") - (match_operand:SI 2 "logical_operand" "K08,r")))] +(define_expand "andsi3" + [(set (match_operand:SI 0 "arith_reg_operand" "") + (and:SI (match_operand:SI 1 "logical_reg_operand" "") + (match_operand:SI 2 "logical_and_operand" "")))] + "" +{ + /* If it is possible to turn the and insn into a zero extension + already, redundant zero extensions will be folded, which results + in better code. + Ideally the splitter of *andsi_compact would be enough, if reundant + zero extensions were detected after the combine pass, which does not + happen at the moment. */ + if (TARGET_SH1) + { + if (satisfies_constraint_Jmb (operands[2])) + { + emit_insn (gen_zero_extendqisi2 (operands[0], + gen_lowpart (QImode, operands[1]))); + DONE; + } + else if (satisfies_constraint_Jmw (operands[2])) + { + emit_insn (gen_zero_extendhisi2 (operands[0], + gen_lowpart (HImode, operands[1]))); + DONE; + } + } +}) + +(define_insn_and_split "*andsi_compact" + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r") + (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0") + (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))] "TARGET_SH1" - "and %2,%0" + "@ + extu.b %1,%0 + extu.w %1,%0 + and %2,%0 + and %2,%0" + "&& 1" + [(set (match_dup 0) (zero_extend:SI (match_dup 1)))] +{ + if (satisfies_constraint_Jmb (operands[2])) + operands[1] = gen_lowpart (QImode, operands[1]); + else if (satisfies_constraint_Jmw (operands[2])) + operands[1] = gen_lowpart (HImode, operands[1]); + else + FAIL; +} [(set_attr "type" "arith")]) (define_insn "*andsi3_media" @@ -3139,24 +3182,6 @@ label: "bclr\\t%W2,%0" [(set_attr "type" "arith")]) -;; If the constant is 255, then emit an extu.b instruction instead of an -;; and, since that will give better code. - -(define_expand "andsi3" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (and:SI (match_operand:SI 1 "logical_reg_operand" "") - (match_operand:SI 2 "logical_operand" "")))] - "" -{ - if (TARGET_SH1 - && CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 255) - { - emit_insn (gen_zero_extendqisi2 (operands[0], - gen_lowpart (QImode, operands[1]))); - DONE; - } -}) - (define_insn_and_split "anddi3" [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r") (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")