diff options
author | Xi Ruoyao <xry111@xry111.site> | 2024-09-05 17:53:41 +0800 |
---|---|---|
committer | Xi Ruoyao <xry111@xry111.site> | 2025-01-20 21:27:52 +0800 |
commit | f3bedc9a3b8b7dd3911272731a1ea595621e13cd (patch) | |
tree | f3a956db1e876ead7471772654de605f61e4accd /gcc/config/loongarch | |
parent | 67b10ee872197ba53524db4f0ca777899e27b151 (diff) | |
download | gcc-f3bedc9a3b8b7dd3911272731a1ea595621e13cd.zip gcc-f3bedc9a3b8b7dd3911272731a1ea595621e13cd.tar.gz gcc-f3bedc9a3b8b7dd3911272731a1ea595621e13cd.tar.bz2 |
LoongArch: Simplify using bstr{ins,pick} instructions for and
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.
Diffstat (limited to 'gcc/config/loongarch')
-rw-r--r-- | gcc/config/loongarch/constraints.md | 4 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch.cc | 12 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch.md | 77 | ||||
-rw-r--r-- | 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 547d916..a7c31c2 100644 --- a/gcc/config/loongarch/constraints.md +++ b/gcc/config/loongarch/constraints.md @@ -292,6 +292,10 @@ "@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 3a8e129..1004b65 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 1b46e8e..995df1b 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -485,7 +485,11 @@ ;; 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 "<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 @@ [(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 68b1737..b5d6f90 100644 --- a/gcc/config/loongarch/predicates.md +++ b/gcc/config/loongarch/predicates.md @@ -405,7 +405,13 @@ (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") |