Last patch in this round of bitmanip work... At least I think I'm going to pause here and switch gears to other projects that need attention :-)

This patch introduces the ability to generate bitmanip instructions for rv64 when operating on SI objects when we know something about the range of the bit position (due to masking of the position).

I've got note that the (7-pos % 8) bit position form was discovered by RAU in 500.perl. I took that and expanded it to the simple (pos & mask) form as well as covering bset, binv and bclr.

As far as the implementation is concerned....

This turns the recently added define_splits into define_insn_and_split constructs. This allows combine to "see" enough RTL to realize a sign extension is unnecessary. Otherwise we get undesirable sign extensions for the new testcases.

Second it adds new patterns for the logical operations. Two patterns for IOR/XOR and two patterns for AND.

I think a key concept to keep in mind is that once we determine a Zbs operation is safe to perform on a SI value, we can rewrite the RTL in 64bit form. If we were ever to try and use range information at expand time for this stuff (and we probably should investigate that), that's the path I'd suggest.

This is notably cleaner than my original implementation which actually kept the more complex RTL form through final and emitted 2/3 instructions (mask the bit position, then the bset/bclr/binv).


Tested in my tester, but waiting for pre-commit CI to report back before taking further action.

jeff


    This patch introduces a bit_optab iterator that maps IOR/XOR to bset and
    binv (and one day bclr if we need it).  That allows us to combine some
    patterns that only differed in the RTL opcode (IOR vs XOR) and in the
    name/assembly (bset vs binv).
    
    Additionally this also allow us to use the iterator in the
    bset<mode>mask and bsetidisi patterns thus potentially fixing a missed
    optimization.
    
    This has gone through my tester.  I'll wait for a verdict from
    pre-commit CI before moving forward.
    
diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index ae5e7e510c0..3eedabffca0 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -569,24 +569,26 @@ (define_insn_and_split "*minmax"
 
 ;; ZBS extension.
 
-(define_insn "*bset<mode>"
+(define_insn "*<bit_optab><mode>"
   [(set (match_operand:X 0 "register_operand" "=r")
-       (ior:X (ashift:X (const_int 1)
-                        (match_operand:QI 2 "register_operand" "r"))
-              (match_operand:X 1 "register_operand" "r")))]
+       (any_or:X (ashift:X (const_int 1)
+                           (match_operand:QI 2 "register_operand" "r"))
+                 (match_operand:X 1 "register_operand" "r")))]
   "TARGET_ZBS"
-  "bset\t%0,%1,%2"
+  "<bit_optab>\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
-(define_insn "*bset<mode>_mask"
+(define_insn "*<bit_optab><mode>_mask"
   [(set (match_operand:X 0 "register_operand" "=r")
-       (ior:X (ashift:X (const_int 1)
-                        (subreg:QI
-                         (and:X (match_operand:X 2 "register_operand" "r")
-                                (match_operand 3 "<X:shiftm1>" 
"<X:shiftm1p>")) 0))
-              (match_operand:X 1 "register_operand" "r")))]
+       (any_or:X
+         (ashift:X
+           (const_int 1)
+           (subreg:QI
+             (and:X (match_operand:X 2 "register_operand" "r")
+                    (match_operand 3 "<X:shiftm1>" "<X:shiftm1p>")) 0))
+         (match_operand:X 1 "register_operand" "r")))]
   "TARGET_ZBS"
-  "bset\t%0,%1,%2"
+  "<bit_optab>\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
 (define_insn "*bset<mode>_1"
@@ -655,24 +657,24 @@ (define_insn "*bset<mode>_1_mask"
   "bset\t%0,x0,%1"
   [(set_attr "type" "bitmanip")])
 
-(define_insn "*bseti<mode>"
+(define_insn "*<bit_optab>i<mode>"
   [(set (match_operand:X 0 "register_operand" "=r")
-       (ior:X (match_operand:X 1 "register_operand" "r")
-              (match_operand:X 2 "single_bit_mask_operand" "DbS")))]
+       (any_or:X (match_operand:X 1 "register_operand" "r")
+                 (match_operand:X 2 "single_bit_mask_operand" "DbS")))]
   "TARGET_ZBS"
-  "bseti\t%0,%1,%S2"
+  "<bit_optab>i\t%0,%1,%S2"
   [(set_attr "type" "bitmanip")])
 
 ;; As long as the SImode operand is not a partial subreg, we can use a
 ;; bseti without postprocessing, as the middle end is smart enough to
 ;; stay away from the signbit.
-(define_insn "*bsetidisi"
+(define_insn "*<bit_optab>idisi"
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (ior:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
-               (match_operand 2 "single_bit_mask_operand" "i")))]
+       (any_or:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
+                  (match_operand 2 "single_bit_mask_operand" "i")))]
   "TARGET_ZBS && TARGET_64BIT
    && !partial_subreg_p (operands[1])"
-  "bseti\t%0,%1,%S2"
+  "<bit_optab>i\t%0,%1,%S2"
   [(set_attr "type" "bitmanip")])
 
 ;; We can easily handle zero extensions
@@ -781,23 +783,6 @@ (define_split
          (and:DI (rotate:DI (const_int -2) (match_dup 1))
                  (match_dup 3)))])
 
-(define_insn "*binv<mode>"
-  [(set (match_operand:X 0 "register_operand" "=r")
-       (xor:X (ashift:X (const_int 1)
-                        (match_operand:QI 2 "register_operand" "r"))
-              (match_operand:X 1 "register_operand" "r")))]
-  "TARGET_ZBS"
-  "binv\t%0,%1,%2"
-  [(set_attr "type" "bitmanip")])
-
-(define_insn "*binvi<mode>"
-  [(set (match_operand:X 0 "register_operand" "=r")
-       (xor:X (match_operand:X 1 "register_operand" "r")
-              (match_operand:X 2 "single_bit_mask_operand" "DbS")))]
-  "TARGET_ZBS"
-  "binvi\t%0,%1,%S2"
-  [(set_attr "type" "bitmanip")])
-
 (define_insn "*bext<mode>"
   [(set (match_operand:X 0 "register_operand" "=r")
        (zero_extract:X (match_operand:X 1 "register_operand" "r")
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 1e37e843023..20745faa55e 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -275,6 +275,9 @@ (define_code_attr optab [(ashift "ashl")
                         (fix "fix_trunc")
                         (unsigned_fix "fixuns_trunc")])
 
+(define_code_attr bit_optab [(ior "bset")
+                            (xor "binv")])
+
 ;; <or_optab> code attributes
 (define_code_attr or_optab [(ior "ior")
                            (xor "xor")])

Reply via email to