Hello, On SH a logical and with constants 0xFFFF or 0xFF can be done with the respective zero-extension operations. The attached patch improves the utilization of the zero-extension operations a little bit, resulting in slightly better code.
Tested against rev 189081 with make -k check RUNTESTFLAGS="--target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m2a-single/-mb,-m4/-ml,-m4/-mb, -m4-single/-ml,-m4-single/-mb,-m4a-single/-ml,-m4a-single/-mb}" and no new failures. Cheers, Oleg ChangeLog: * 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.
Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 189081) +++ gcc/config/sh/sh.md (working copy) @@ -3113,12 +3113,55 @@ ;; 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 @@ "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") Index: gcc/config/sh/predicates.md =================================================================== --- gcc/config/sh/predicates.md (revision 189081) +++ gcc/config/sh/predicates.md (working copy) @@ -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" Index: gcc/config/sh/constraints.md =================================================================== --- gcc/config/sh/constraints.md (revision 189081) +++ gcc/config/sh/constraints.md (working copy) @@ -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")