For bstrins, we can merge it into and<mode>3 instead of having a separate define_insn.
For bstrpick, we can use the constraints to ensure the first source register and the destination register are the same hardware register, instead of emitting a move manually. This will simplify the next commit where we'll reassociate bitwise and left shift for better code generation. gcc/ChangeLog: * config/loongarch/constraints.md (Yy): New define_constriant. * config/loongarch/loongarch.cc (loongarch_print_operand): For "%M", output the index of bits to be used with bstrins/bstrpick. * config/loongarch/predicates.md (ins_zero_bitmask_operand): Exclude low_bitmask_operand as for low_bitmask_operand it's always better to use bstrpick instead of bstrins. (and_operand): New define_predicate. * config/loongarch/loongarch.md (any_or): New define_code_iterator. (bitwise_operand): New define_code_attr. (*<optab:any_or><mode:GPR>3): New define_insn. (*and<mode:GPR>3): New define_insn. (<optab:any_bitwise><mode:X>3): New define_expand. (and<mode>3_extended): Remove, replaced by the 3rd alternative of *and<mode:GPR>3. (bstrins_<mode>_for_mask): Remove, replaced by the 4th alternative of *and<mode:GPR>3. (*<optab:any_bitwise>si3_internal): Remove, already covered by the *<optab:any_or><mode:GPR>3 and *and<mode:GPR>3 templates. --- gcc/config/loongarch/constraints.md | 4 ++ gcc/config/loongarch/loongarch.cc | 12 +++++ gcc/config/loongarch/loongarch.md | 77 +++++++++++------------------ gcc/config/loongarch/predicates.md | 8 ++- 4 files changed, 53 insertions(+), 48 deletions(-) diff --git a/gcc/config/loongarch/constraints.md b/gcc/config/loongarch/constraints.md index 547d9161445..a7c31c2c4e0 100644 --- a/gcc/config/loongarch/constraints.md +++ b/gcc/config/loongarch/constraints.md @@ -292,6 +292,10 @@ (define_constraint "Yx" "@internal" (match_operand 0 "low_bitmask_operand")) +(define_constraint "Yy" + "@internal" + (match_operand 0 "ins_zero_bitmask_operand")) + (define_constraint "YI" "@internal A replicated vector const in which the replicated value is in the range diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 3a8e1297bd3..1004b65a1ee 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -6142,6 +6142,8 @@ loongarch_print_operand_reloc (FILE *file, rtx op, bool hi64_part, 'i' Print i if the operand is not a register. 'L' Print the low-part relocation associated with OP. 'm' Print one less than CONST_INT OP in decimal. + 'M' Print the indices of the lowest enabled bit and the highest + enabled bit in a mask (for bstr* instructions). 'N' Print the inverse of the integer branch condition for comparison OP. 'Q' Print R_LARCH_RELAX for TLS IE. 'r' Print address 12-31bit relocation associated with OP. @@ -6268,6 +6270,16 @@ loongarch_print_operand (FILE *file, rtx op, int letter) output_operand_lossage ("invalid use of '%%%c'", letter); break; + case 'M': + if (CONST_INT_P (op)) + { + HOST_WIDE_INT mask = INTVAL (op); + fprintf (file, "%d,%d", floor_log2 (mask), ctz_hwi (mask)); + } + else + output_operand_lossage ("invalid use of '%%%c'", letter); + break; + case 'N': loongarch_print_int_branch_condition (file, reverse_condition (code), letter); diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index 1b46e8e4af0..995df1b8875 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -485,7 +485,11 @@ (define_code_iterator any_shift [ashift ashiftrt lshiftrt]) ;; This code iterator allows the three bitwise instructions to be generated ;; from the same template. (define_code_iterator any_bitwise [and ior xor]) +(define_code_iterator any_or [ior xor]) (define_code_iterator neg_bitwise [and ior]) +(define_code_attr bitwise_operand [(and "and_operand") + (ior "uns_arith_operand") + (xor "uns_arith_operand")]) ;; This code iterator allows unsigned and signed division to be generated ;; from the same template. @@ -1537,23 +1541,37 @@ (define_insn "neg<mode>2" ;; .................... ;; -(define_insn "<optab><mode>3" - [(set (match_operand:X 0 "register_operand" "=r,r") - (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r") - (match_operand:X 2 "uns_arith_operand" "r,K")))] +(define_insn "*<optab><mode>3" + [(set (match_operand:GPR 0 "register_operand" "=r,r") + (any_or:GPR (match_operand:GPR 1 "register_operand" "%r,r") + (match_operand:GPR 2 "uns_arith_operand" "r,K")))] "" "<insn>%i2\t%0,%1,%2" [(set_attr "type" "logical") (set_attr "mode" "<MODE>")]) -(define_insn "*<optab>si3_internal" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r") - (match_operand:SI 2 "uns_arith_operand" " r,K")))] - "TARGET_64BIT" - "<insn>%i2\t%0,%1,%2" - [(set_attr "type" "logical") - (set_attr "mode" "SI")]) +(define_insn "*and<mode>3" + [(set (match_operand:GPR 0 "register_operand" "=r,r,r,r") + (and:GPR (match_operand:GPR 1 "register_operand" "%r,r,r,0") + (match_operand:GPR 2 "and_operand" "r,K,Yx,Yy")))] + "" + "@ + and\t%0,%1,%2 + andi\t%0,%1,%2 + * operands[2] = GEN_INT (INTVAL (operands[2]) \ + & GET_MODE_MASK (<MODE>mode)); \ + return \"bstrpick.<d>\t%0,%1,%M2\"; + * operands[2] = GEN_INT (~INTVAL (operands[2]) \ + & GET_MODE_MASK (<MODE>mode)); \ + return \"bstrins.<d>\t%0,%.,%M2\";" + [(set_attr "move_type" "logical,logical,pick_ins,pick_ins") + (set_attr "mode" "<MODE>")]) + +(define_expand "<optab><mode>3" + [(set (match_operand:X 0 "register_operand") + (any_bitwise:X (match_operand:X 1 "register_operand") + (match_operand:X 2 "<bitwise_operand>")))] + "") (define_insn "one_cmpl<mode>2" [(set (match_operand:X 0 "register_operand" "=r") @@ -1571,41 +1589,6 @@ (define_insn "*one_cmplsi2_internal" [(set_attr "type" "logical") (set_attr "mode" "SI")]) -(define_insn "and<mode>3_extended" - [(set (match_operand:GPR 0 "register_operand" "=r") - (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "r") - (match_operand:GPR 2 "low_bitmask_operand" "Yx")))] - "" -{ - int len; - - len = low_bitmask_len (<MODE>mode, INTVAL (operands[2])); - operands[2] = GEN_INT (len-1); - return "bstrpick.<d>\t%0,%1,%2,0"; -} - [(set_attr "move_type" "pick_ins") - (set_attr "mode" "<MODE>")]) - -(define_insn_and_split "*bstrins_<mode>_for_mask" - [(set (match_operand:GPR 0 "register_operand" "=r") - (and:GPR (match_operand:GPR 1 "register_operand" "r") - (match_operand:GPR 2 "ins_zero_bitmask_operand" "i")))] - "" - "#" - "" - [(set (match_dup 0) (match_dup 1)) - (set (zero_extract:GPR (match_dup 0) (match_dup 2) (match_dup 3)) - (const_int 0))] - { - unsigned HOST_WIDE_INT mask = ~UINTVAL (operands[2]); - int lo = ffs_hwi (mask) - 1; - int len = low_bitmask_len (<MODE>mode, mask >> lo); - - len = MIN (len, GET_MODE_BITSIZE (<MODE>mode) - lo); - operands[2] = GEN_INT (len); - operands[3] = GEN_INT (lo); - }) - (define_insn_and_split "*bstrins_<mode>_for_ior_mask" [(set (match_operand:GPR 0 "register_operand" "=r") (ior:GPR (and:GPR (match_operand:GPR 1 "register_operand" "r") diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md index 68b17376620..b5d6f90678e 100644 --- a/gcc/config/loongarch/predicates.md +++ b/gcc/config/loongarch/predicates.md @@ -405,7 +405,13 @@ (define_predicate "ins_zero_bitmask_operand" (match_test "low_bitmask_len (mode, \ ~UINTVAL (op) | (~UINTVAL(op) - 1)) \ > 0") - (not (match_operand 0 "const_uns_arith_operand")))) + (not (match_operand 0 "const_uns_arith_operand")) + (not (match_operand 0 "low_bitmask_operand")))) + +(define_predicate "and_operand" + (ior (match_operand 0 "uns_arith_operand") + (match_operand 0 "low_bitmask_operand") + (match_operand 0 "ins_zero_bitmask_operand"))) (define_predicate "const_call_insn_operand" (match_code "const,symbol_ref,label_ref") -- 2.48.0