]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/riscv/bitmanip.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / riscv / bitmanip.md
index cfdb9eb4689b6902779791a91ff38180cdee5185..fdab0017a2b9e82f5152635828eb0696713e8a04 100644 (file)
@@ -1,5 +1,5 @@
 ;; Machine description for RISC-V Bit Manipulation operations.
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GCC.
 
 ; implicit sign-extensions.
 (define_split
   [(set (match_operand:DI 0 "register_operand")
-       (sign_extend:DI (div:SI (plus:SI (subreg:SI (ashift:DI (match_operand:DI 1 "register_operand")
-                                                              (match_operand:QI 2 "imm123_operand")) 0)
-                                                   (subreg:SI (match_operand:DI 3 "register_operand") 0))
-               (subreg:SI (match_operand:DI 4 "register_operand") 0))))
+       (sign_extend:DI (div:SI (plus:SI (ashift:SI (subreg:SI (match_operand:DI 1 "register_operand") 0)
+                                                   (match_operand:QI 2 "imm123_operand"))
+                                        (subreg:SI (match_operand:DI 3 "register_operand") 0))
+                               (subreg:SI (match_operand:DI 4 "register_operand") 0))))
    (clobber (match_operand:DI 5 "register_operand"))]
   "TARGET_64BIT && TARGET_ZBA"
    [(set (match_dup 5) (plus:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))
                               (match_dup 4)))]
 {
        operands[3] = GEN_INT (INTVAL (operands[3]) >> INTVAL (operands[2]));
-})
+}
+[(set_attr "type" "bitmanip")])
 
 (define_insn "*shNadduw"
   [(set (match_operand:DI 0 "register_operand" "=r")
 
 ;; ZBB extension.
 
-(define_insn "*<optab>_not<mode>"
+(define_expand "clzdi2"
+  [(set (match_operand:DI 0 "register_operand")
+       (clz:DI (match_operand:DI 1 "register_operand")))]
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_XTHEADBB)")
+
+(define_expand "clzsi2"
+  [(set (match_operand:SI 0 "register_operand")
+       (clz:SI (match_operand:SI 1 "register_operand")))]
+  "TARGET_ZBB || (!TARGET_64BIT && TARGET_XTHEADBB)")
+
+(define_expand "ctz<mode>2"
+  [(set (match_operand:GPR 0 "register_operand")
+       (ctz:GPR (match_operand:GPR 1 "register_operand")))]
+  "TARGET_ZBB")
+
+(define_expand "popcount<mode>2"
+  [(set (match_operand:GPR 0 "register_operand")
+       (popcount:GPR (match_operand:GPR 1 "register_operand")))]
+  "TARGET_ZBB")
+
+(define_insn "<optab>_not<mode>3"
   [(set (match_operand:X 0 "register_operand" "=r")
         (bitmanip_bitwise:X (not:X (match_operand:X 1 "register_operand" "r"))
                             (match_operand:X 2 "register_operand" "r")))]
-  "TARGET_ZBB"
+  "TARGET_ZBB || TARGET_ZBKB"
   "<insn>n\t%0,%2,%1"
   [(set_attr "type" "bitmanip")
    (set_attr "mode" "<X:MODE>")])
 
+(define_insn_and_split "*<optab>_not_const<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+       (bitmanip_bitwise:X (not:X (match_operand:X 1 "register_operand" "r"))
+              (match_operand:X 2 "const_arith_operand" "I")))
+  (clobber (match_scratch:X 3 "=&r"))]
+  "(TARGET_ZBB || TARGET_ZBKB) && !TARGET_ZCB
+   && !optimize_function_for_size_p (cfun)"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 3) (match_dup 2))
+   (set (match_dup 0) (bitmanip_bitwise:X (not:X (match_dup 1)) (match_dup 3)))]
+  ""
+  [(set_attr "type" "bitmanip")])
+
 ;; '(a >= 0) ? b : 0' is emitted branchless (from if-conversion).  Without a
 ;; bit of extra help for combine (i.e., the below split), we end up emitting
 ;; not/srai/and instead of combining the not into an andn.
                               (const_int 0)))
                (match_operand:DI 2 "register_operand")))
    (clobber (match_operand:DI 3 "register_operand"))]
-  "TARGET_ZBB"
+  "TARGET_ZBB || TARGET_ZBKB"
   [(set (match_dup 3) (ashiftrt:DI (match_dup 1) (const_int 63)))
    (set (match_dup 0) (and:DI (not:DI (match_dup 3)) (match_dup 2)))])
 
   [(set (match_operand:X 0 "register_operand" "=r")
         (not:X (xor:X (match_operand:X 1 "register_operand" "r")
                       (match_operand:X 2 "register_operand" "r"))))]
-  "TARGET_ZBB"
+  "TARGET_ZBB || TARGET_ZBKB"
   "xnor\t%0,%1,%2"
   [(set_attr "type" "bitmanip")
    (set_attr "mode" "<X:MODE>")])
 
-(define_insn "<bitmanip_optab>si2"
+(define_insn "*<bitmanip_optab>si2"
   [(set (match_operand:SI 0 "register_operand" "=r")
         (clz_ctz_pcnt:SI (match_operand:SI 1 "register_operand" "r")))]
   "TARGET_ZBB"
   "<bitmanip_insn>%~\t%0,%1"
-  [(set_attr "type" "bitmanip")
+  [(set_attr "type" "<bitmanip_insn>")
    (set_attr "mode" "SI")])
 
 (define_insn "*<bitmanip_optab>disi2"
   [(set (match_operand:DI 0 "register_operand" "=r")
-        (sign_extend:DI
+        (any_extend:DI
           (clz_ctz_pcnt:SI (match_operand:SI 1 "register_operand" "r"))))]
   "TARGET_64BIT && TARGET_ZBB"
   "<bitmanip_insn>w\t%0,%1"
-  [(set_attr "type" "bitmanip")
+  [(set_attr "type" "<bitmanip_insn>")
    (set_attr "mode" "SI")])
 
-(define_insn "<bitmanip_optab>di2"
+;; A SImode clz_ctz_pcnt may be extended to DImode via subreg.
+(define_insn "*<bitmanip_optab>disi2_sext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (and:DI (subreg:DI
+          (clz_ctz_pcnt:SI (match_operand:SI 1 "register_operand" "r")) 0)
+          (match_operand:DI 2 "const_int_operand")))]
+  "TARGET_64BIT && TARGET_ZBB && ((INTVAL (operands[2]) & 0x3f) == 0x3f)"
+  "<bitmanip_insn>w\t%0,%1"
+  [(set_attr "type" "<bitmanip_insn>")
+   (set_attr "mode" "SI")])
+
+(define_insn "*<bitmanip_optab>di2"
   [(set (match_operand:DI 0 "register_operand" "=r")
         (clz_ctz_pcnt:DI (match_operand:DI 1 "register_operand" "r")))]
   "TARGET_64BIT && TARGET_ZBB"
   "<bitmanip_insn>\t%0,%1"
-  [(set_attr "type" "bitmanip")
+  [(set_attr "type" "<bitmanip_insn>")
    (set_attr "mode" "DI")])
 
 (define_insn "*zero_extendhi<GPR:mode>2_bitmanip"
   [(set (match_operand:GPR 0 "register_operand" "=r,r")
         (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
-  "TARGET_ZBB"
+  "TARGET_ZBB && !TARGET_XTHEADMEMIDX"
   "@
    zext.h\t%0,%1
    lhu\t%0,%1"
   [(set_attr "type" "bitmanip,load")
    (set_attr "mode" "<GPR:MODE>")])
 
-(define_insn "*extend<SHORT:mode><SUPERQI:mode>2_zbb"
+(define_insn "*extend<SHORT:mode><SUPERQI:mode>2_bitmanip"
   [(set (match_operand:SUPERQI   0 "register_operand"     "=r,r")
        (sign_extend:SUPERQI
            (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
-  "TARGET_ZBB"
+  "TARGET_ZBB && !TARGET_XTHEADMEMIDX"
   "@
    sext.<SHORT:size>\t%0,%1
    l<SHORT:size>\t%0,%1"
   [(set_attr "type" "bitmanip,load")
    (set_attr "mode" "<SUPERQI:MODE>")])
 
-(define_insn "*zero_extendhi<GPR:mode>2_zbb"
-  [(set (match_operand:GPR    0 "register_operand"     "=r,r")
-       (zero_extend:GPR
-           (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
-  "TARGET_ZBB"
-  "@
-   zext.h\t%0,%1
-   lhu\t%0,%1"
-  [(set_attr "type" "bitmanip,load")
-   (set_attr "mode" "HI")])
+(define_expand "rotrdi3"
+  [(set (match_operand:DI 0 "register_operand")
+       (rotatert:DI (match_operand:DI 1 "register_operand")
+                    (match_operand:QI 2 "arith_operand")))]
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_XTHEADBB || TARGET_ZBKB)"
+{
+  if (TARGET_XTHEADBB && !immediate_operand (operands[2], VOIDmode))
+    FAIL;
+})
 
-(define_insn "rotrsi3"
+(define_insn "*rotrsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (rotatert:SI (match_operand:SI 1 "register_operand" "r")
                     (match_operand:QI 2 "arith_operand" "rI")))]
-  "TARGET_ZBB"
+  "TARGET_ZBB || TARGET_ZBKB"
   "ror%i2%~\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
-(define_insn "rotrdi3"
+(define_expand "rotrsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (rotatert:SI (match_operand:SI 1 "register_operand" "r")
+                    (match_operand:QI 2 "arith_operand" "rI")))]
+  "TARGET_ZBB || TARGET_ZBKB || TARGET_XTHEADBB"
+{
+  if (TARGET_XTHEADBB && !immediate_operand (operands[2], VOIDmode))
+    FAIL;
+  if (TARGET_64BIT && register_operand (operands[2], QImode))
+    {
+      rtx t = gen_reg_rtx (DImode);
+      emit_insn (gen_rotrsi3_sext (t, operands[1], operands[2]));
+      t = gen_lowpart (SImode, t);
+      SUBREG_PROMOTED_VAR_P (t) = 1;
+      SUBREG_PROMOTED_SET (t, SRP_SIGNED);
+      emit_move_insn (operands[0], t);
+      DONE;
+    }
+})
+
+(define_insn "*rotrdi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (rotatert:DI (match_operand:DI 1 "register_operand" "r")
                     (match_operand:QI 2 "arith_operand" "rI")))]
-  "TARGET_64BIT && TARGET_ZBB"
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)"
   "ror%i2\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
 (define_insn "rotrsi3_sext"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extend:DI (rotatert:SI (match_operand:SI 1 "register_operand" "r")
-                                    (match_operand:QI 2 "register_operand" "r"))))]
-  "TARGET_64BIT && TARGET_ZBB"
-  "rorw\t%0,%1,%2"
+                                 (match_operand:QI 2 "arith_operand" "rI"))))]
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)"
+  "ror%i2%~\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
-(define_insn "rotlsi3"
+(define_insn "*rotlsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (rotate:SI (match_operand:SI 1 "register_operand" "r")
                   (match_operand:QI 2 "register_operand" "r")))]
-  "TARGET_ZBB"
+  "TARGET_ZBB || TARGET_ZBKB"
   "rol%~\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
+(define_expand "rotlsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (rotate:SI (match_operand:SI 1 "register_operand" "r")
+                  (match_operand:QI 2 "register_operand" "r")))]
+  "TARGET_ZBB || TARGET_ZBKB"
+{
+  if (TARGET_64BIT)
+    {
+      rtx t = gen_reg_rtx (DImode);
+      emit_insn (gen_rotlsi3_sext (t, operands[1], operands[2]));
+      t = gen_lowpart (SImode, t);
+      SUBREG_PROMOTED_VAR_P (t) = 1;
+      SUBREG_PROMOTED_SET (t, SRP_SIGNED);
+      emit_move_insn (operands[0], t);
+      DONE;
+    }
+})
+
 (define_insn "rotldi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (rotate:DI (match_operand:DI 1 "register_operand" "r")
                   (match_operand:QI 2 "register_operand" "r")))]
-  "TARGET_64BIT && TARGET_ZBB"
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)"
   "rol\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extend:DI (rotate:SI (match_operand:SI 1 "register_operand" "r")
                                   (match_operand:QI 2 "register_operand" "r"))))]
-  "TARGET_64BIT && TARGET_ZBB"
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)"
   "rolw\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
+(define_insn_and_split "*<bitmanip_optab><GPR:mode>3_mask"
+  [(set (match_operand:GPR     0 "register_operand" "= r")
+        (bitmanip_rotate:GPR
+            (match_operand:GPR 1 "register_operand" "  r")
+            (match_operator 4 "subreg_lowpart_operator"
+             [(and:GPR2
+               (match_operand:GPR2 2 "register_operand"  "r")
+               (match_operand 3 "<GPR:shiftm1>" "<GPR:shiftm1p>"))])))]
+  "TARGET_ZBB || TARGET_ZBKB"
+  "#"
+  "&& 1"
+  [(set (match_dup 0)
+        (bitmanip_rotate:GPR (match_dup 1)
+                             (match_dup 2)))]
+  "operands[2] = gen_lowpart (QImode, operands[2]);"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn_and_split "*<bitmanip_optab>si3_sext_mask"
+  [(set (match_operand:DI     0 "register_operand" "= r")
+  (sign_extend:DI (bitmanip_rotate:SI
+            (match_operand:SI 1 "register_operand" "  r")
+            (match_operator 4 "subreg_lowpart_operator"
+             [(and:GPR
+               (match_operand:GPR 2 "register_operand"  "r")
+               (match_operand 3 "const_si_mask_operand"))]))))]
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)"
+  "#"
+  "&& 1"
+  [(set (match_dup 0)
+  (sign_extend:DI (bitmanip_rotate:SI (match_dup 1)
+                           (match_dup 2))))]
+  "operands[2] = gen_lowpart (QImode, operands[2]);"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "DI")])
+
 ;; orc.b (or-combine) is added as an unspec for the benefit of the support
 ;; for optimized string functions (such as strcmp).
 (define_insn "orcb<mode>2"
   [(set (match_operand:X 0 "register_operand" "=r")
        (unspec:X [(match_operand:X 1 "register_operand" "r")] UNSPEC_ORC_B))]
   "TARGET_ZBB"
-  "orc.b\t%0,%1")
+  "orc.b\t%0,%1"
+  [(set_attr "type" "bitmanip")])
+
+(define_expand "bswapdi2"
+  [(set (match_operand:DI 0 "register_operand")
+       (bswap:DI (match_operand:DI 1 "register_operand")))]
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_XTHEADBB || TARGET_ZBKB)")
+
+(define_expand "bswapsi2"
+  [(set (match_operand:SI 0 "register_operand")
+       (bswap:SI (match_operand:SI 1 "register_operand")))]
+  "TARGET_ZBB || TARGET_ZBKB || TARGET_XTHEADBB"
+{
+  /* Expose bswapsi2 on TARGET_64BIT so that the gimple store
+     merging pass will create suitable bswap insns.  We can actually
+     just FAIL that case when generating RTL and let the generic code
+     handle it.  */
+  if (TARGET_64BIT && !TARGET_XTHEADBB)
+    FAIL;
+})
+
 
-(define_insn "bswap<mode>2"
+(define_insn "*bswap<mode>2"
   [(set (match_operand:X 0 "register_operand" "=r")
         (bswap:X (match_operand:X 1 "register_operand" "r")))]
-  "TARGET_ZBB"
+  "TARGET_ZBB || TARGET_ZBKB"
   "rev8\t%0,%1"
   [(set_attr "type" "bitmanip")])
 
   DONE;
 })
 
-(define_insn "<bitmanip_optab><mode>3"
+(define_expand "<bitmanip_optab>di3"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (bitmanip_minmax:DI (match_operand:DI 1 "register_operand" "r")
+                            (match_operand:DI 2 "register_operand" "r")))]
+  "TARGET_64BIT && TARGET_ZBB")
+
+(define_expand "<bitmanip_optab>si3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (bitmanip_minmax:SI (match_operand:SI 1 "register_operand" "r")
+                            (match_operand:SI 2 "register_operand" "r")))]
+  "TARGET_ZBB"
+{
+  if (TARGET_64BIT)
+    {
+      rtx t = gen_reg_rtx (DImode);
+      operands[1] = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, operands[1]));
+      operands[2] = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, operands[2]));
+      emit_insn (gen_<bitmanip_optab>di3 (t, operands[1], operands[2]));
+      emit_move_insn (operands[0], gen_lowpart (SImode, t));
+      DONE;
+    }
+})
+
+(define_insn "*<bitmanip_optab><mode>3"
   [(set (match_operand:X 0 "register_operand" "=r")
         (bitmanip_minmax:X (match_operand:X 1 "register_operand" "r")
                           (match_operand:X 2 "reg_or_0_operand" "rJ")))]
   "TARGET_ZBB"
   "<bitmanip_insn>\t%0,%1,%z2"
-  [(set_attr "type" "bitmanip")])
+  [(set_attr "type" "<bitmanip_insn>")])
 
 ;; Optimize the common case of a SImode min/max against a constant
 ;; that is safe both for sign- and zero-extension.
   "&& reload_completed"
   [(set (match_dup 3) (sign_extend:DI (match_dup 1)))
    (set (match_dup 4) (match_dup 2))
-   (set (match_dup 0) (<minmax_optab>:DI (match_dup 3) (match_dup 4)))])
+   (set (match_dup 0) (<minmax_optab>:DI (match_dup 3) (match_dup 4)))]
+  ""
+  [(set_attr "type" "bitmanip")])
 
 ;; ZBS extension.
 
 (define_insn_and_split "*bclri<mode>_nottwobits"
   [(set (match_operand:X 0 "register_operand" "=r")
        (and:X (match_operand:X 1 "register_operand" "r")
-              (match_operand:X 2 "const_nottwobits_operand" "i")))]
+              (match_operand:X 2 "const_nottwobits_not_arith_operand" "i")))]
   "TARGET_ZBS && !paradoxical_subreg_p (operands[1])"
   "#"
   "&& reload_completed"
 
        operands[3] = GEN_INT (~bits | topbit);
        operands[4] = GEN_INT (~topbit);
-})
+}
+[(set_attr "type" "bitmanip")])
 
 ;; In case of a paradoxical subreg, the sign bit and the high bits are
 ;; not allowed to be changed
 (define_insn_and_split "*bclridisi_nottwobits"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (and:DI (match_operand:DI 1 "register_operand" "r")
-               (match_operand:DI 2 "const_nottwobits_operand" "i")))]
+               (match_operand:DI 2 "const_nottwobits_not_arith_operand" "i")))]
   "TARGET_64BIT && TARGET_ZBS
    && clz_hwi (~UINTVAL (operands[2])) > 33"
   "#"
 
        operands[3] = GEN_INT (~bits | topbit);
        operands[4] = GEN_INT (~topbit);
-})
+}
+[(set_attr "type" "bitmanip")])
 
 (define_insn "*binv<mode>"
   [(set (match_operand:X 0 "register_operand" "=r")
 
        operands[3] = GEN_INT (bits &~ topbit);
        operands[4] = GEN_INT (topbit);
-})
+}
+[(set_attr "type" "bitmanip")])
 
 ;; Same to use blcri + andi and blcri + bclri
 (define_insn_and_split "*andi<mode>_extrabit"
 
        operands[3] = GEN_INT (bits | topbit);
        operands[4] = GEN_INT (~topbit);
-})
+}
+[(set_attr "type" "bitmanip")])
 
 ;; IF_THEN_ELSE: test for 2 bits of opposite polarity
 (define_insn_and_split "*branch<X:mode>_mask_twobits_equals_singlebit"
 
    operands[8] = GEN_INT (setbit);
    operands[9] = GEN_INT (clearbit);
-})
+}
+[(set_attr "type" "bitmanip")])
+
+;; IF_THEN_ELSE: test for (a & (1 << BIT_NO))
+(define_insn_and_split "*branch<X:mode>_bext"
+  [(set (pc)
+       (if_then_else
+         (match_operator 1 "equality_operator"
+         [(zero_extract:X (match_operand:X 2 "register_operand" "r")
+                          (const_int 1)
+                          (zero_extend:X
+                            (match_operand:QI 3 "register_operand" "r")))
+           (const_int 0)])
+       (label_ref (match_operand 0 "" ""))
+       (pc)))
+  (clobber (match_scratch:X 4 "=&r"))]
+  "TARGET_ZBS"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 4) (zero_extract:X (match_dup 2)
+                                       (const_int 1)
+                                       (zero_extend:X (match_dup 3))))
+   (set (pc) (if_then_else (match_op_dup 1 [(match_dup 4) (const_int 0)])
+                          (label_ref (match_dup 0))
+                          (pc)))]
+   ""
+  [(set_attr "type" "bitmanip")])
+
+;; ZBKC or ZBC extension
+(define_insn "riscv_clmul_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec:X [(match_operand:X 1 "register_operand" "r")
+                  (match_operand:X 2 "register_operand" "r")]
+                  UNSPEC_CLMUL))]
+  "TARGET_ZBKC || TARGET_ZBC"
+  "clmul\t%0,%1,%2"
+  [(set_attr "type" "clmul")])
+
+(define_insn "riscv_clmulh_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec:X [(match_operand:X 1 "register_operand" "r")
+                  (match_operand:X 2 "register_operand" "r")]
+                  UNSPEC_CLMULH))]
+  "TARGET_ZBKC || TARGET_ZBC"
+  "clmulh\t%0,%1,%2"
+  [(set_attr "type" "clmul")])
+
+;; ZBC extension
+(define_insn "riscv_clmulr_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec:X [(match_operand:X 1 "register_operand" "r")
+                  (match_operand:X 2 "register_operand" "r")]
+                  UNSPEC_CLMULR))]
+  "TARGET_ZBC"
+  "clmulr\t%0,%1,%2"
+  [(set_attr "type" "clmul")])