Browse Source

dubhe: Add additional GCC patch files for B v1.0 extension support

Added additional 11 patch files for GCC to support B v1.0 extension for
RISC-V.

Signed-off-by: Jun Yuan Tan <junyuan.tan@starfivetech.com>
Jun Yuan Tan 2 years ago
parent
commit
1eb01a8f63

+ 11 - 0
recipes-devtools/gcc/gcc-11.1.inc

@@ -79,6 +79,17 @@ SRC_URI = "\
            file://0013-remove-b-gcc-options.patch \
            file://0014-fix-incorrect-subext-name.patch \
            file://0015-add-builtin-orc.b-clmul-clmulr-clmulh.patch \
+           file://0016-merge-sifve-change-for-bitmanip.patch \
+           file://0017-Implement-instruction-patterns-for-ZBA-extension.patch \
+           file://0018-Cost-model-for-zba-extension.patch \
+           file://0019-Implement-instruction-patterns-for-ZBB-extension.patch \
+           file://0020-Cost-model-for-zbb-extension.patch \
+           file://0021-Use-li-and-rori-to-load-constants.patch \
+           file://0022-Implement-instruction-patterns-for-ZBS-extension.patch \
+           file://0023-Cost-model-for-ZBS-extension.patch \
+           file://0024-RISC-V-costs-handle-BSWAP.patch \
+           file://0025-RISC-V-costs-support-shift-and-add-in-strength-reduc.patch \
+           file://0026-RISC-V-bitmanip-fix-constant-loading-for-1ULL-31-in-.patch \
            file://0001-Yocto-patch-for-arch-canonicalize-to-use-python3.patch \
 "
 SRC_URI[sha256sum] = "4c4a6fb8a8396059241c2e674b85b351c26a5d678274007f076957afa1cc9ddf"

+ 545 - 0
recipes-devtools/gcc/gcc/0016-merge-sifve-change-for-bitmanip.patch

@@ -0,0 +1,545 @@
+From e243539f72938317c85bb9859576c39b1baf011d Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Thu, 18 Nov 2021 14:25:18 +0800
+Subject: [PATCH 16/26] merge sifve change for bitmanip
+
+---
+ gcc/config/riscv/bitmanip.md | 446 ++++++++++++++---------------------
+ 1 file changed, 173 insertions(+), 273 deletions(-)
+
+diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
+index ceb5c89dd47..d2e1d6c936b 100644
+--- a/gcc/config/riscv/bitmanip.md
++++ b/gcc/config/riscv/bitmanip.md
+@@ -1,5 +1,5 @@
+ ;; Machine description for RISC-V Bit Manipulation operations.
+-;; Copyright (C) 2019 Free Software Foundation, Inc.
++;; Copyright (C) 2021 Free Software Foundation, Inc.
+ 
+ ;; This file is part of GCC.
+ 
+@@ -19,7 +19,7 @@
+ 
+ (define_code_iterator bitmanip_bitwise [and ior])
+ 
+-(define_code_iterator any_minmax [smin smax umin umax])
++(define_code_iterator bitmanip_minmax [smin umin smax umax])
+ 
+ (define_code_iterator clz_ctz_pcnt [clz ctz popcount])
+ 
+@@ -31,6 +31,7 @@
+ 				  (ctz "ctz")
+ 				  (popcount "popcount")])
+ 
++
+ (define_code_attr bitmanip_insn [(smin "min")
+ 				 (smax "max")
+ 				 (umin "minu")
+@@ -41,74 +42,206 @@
+ 
+ (define_mode_attr shiftm1 [(SI "const31_operand") (DI "const63_operand")])
+ 
++;; ZBA extension.
++
++(define_insn "*zero_extendsidi2_bitmanip"
++  [(set (match_operand:DI 0 "register_operand" "=r,r")
++	(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
++  "TARGET_64BIT && TARGET_ZBA"
++  "@
++   zext.w\t%0,%1
++   lwu\t%0,%1"
++  [(set_attr "type" "bitmanip,load")
++   (set_attr "mode" "DI")])
++
++(define_insn "*shNadd"
++  [(set (match_operand:X 0 "register_operand" "=r")
++	(plus:X (ashift:X (match_operand:X 1 "register_operand" "r")
++			  (match_operand:QI 2 "immediate_operand" "I"))
++		(match_operand:X 3 "register_operand" "r")))]
++  "TARGET_ZBA
++   && (INTVAL (operands[2]) >= 1) && (INTVAL (operands[2]) <= 3)"
++  "sh%2add\t%0,%1,%3"
++  [(set_attr "type" "bitmanip")
++   (set_attr "mode" "<X:MODE>")])
++
++(define_insn "*shNadduw"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++	(plus:DI
++	  (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
++			     (match_operand:QI 2 "immediate_operand" "I"))
++		 (match_operand 3 "immediate_operand" ""))
++	  (match_operand:DI 4 "register_operand" "r")))]
++  "TARGET_64BIT && TARGET_ZBA
++   && (INTVAL (operands[2]) >= 1) && (INTVAL (operands[2]) <= 3)
++   && (INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff"
++  "sh%2add.uw\t%0,%1,%4"
++  [(set_attr "type" "bitmanip")
++   (set_attr "mode" "DI")])
++
++(define_insn "*add.uw"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++	(plus:DI (zero_extend:DI
++		   (match_operand:SI 1 "register_operand" "r"))
++		 (match_operand:DI 2 "register_operand" "r")))]
++  "TARGET_64BIT && TARGET_ZBA"
++  "add.uw\t%0,%1,%2"
++  [(set_attr "type" "bitmanip")
++   (set_attr "mode" "DI")])
++
++(define_insn "*slliuw"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++	(and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
++			   (match_operand:QI 2 "immediate_operand" "I"))
++		(match_operand 3 "immediate_operand" "")))]
++  "TARGET_64BIT && TARGET_ZBA
++   && (INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff"
++  "slli.uw\t%0,%1,%2"
++  [(set_attr "type" "bitmanip")
++   (set_attr "mode" "DI")])
++
++;; ZBB extension.
++
++(define_insn "*<optab>_not<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 "register_operand" "r")))]
++  "TARGET_ZBB"
++  "<insn>n\t%0,%2,%1"
++  [(set_attr "type" "bitmanip")
++   (set_attr "mode" "<X:MODE>")])
++
++(define_insn "*xor_not<mode>"
++  [(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"
++  "xnor\t%0,%1,%2"
++  [(set_attr "type" "bitmanip")
++   (set_attr "mode" "<X:MODE>")])
++
+ (define_insn "<bitmanip_optab>si2"
+   [(set (match_operand:SI 0 "register_operand" "=r")
+-	(clz_ctz_pcnt:SI (match_operand:SI 1 "register_operand" "r")))]
++        (clz_ctz_pcnt:SI (match_operand:SI 1 "register_operand" "r")))]
+   "TARGET_ZBB"
+   { return TARGET_64BIT ? "<bitmanip_insn>w\t%0,%1" : "<bitmanip_insn>\t%0,%1"; }
+-  [(set_attr "type" "bitmanip")])
++  [(set_attr "type" "bitmanip")
++   (set_attr "mode" "SI")])
+ 
+-;; TODO: In theory zero_extend should be OK to combine too, since the output
+-;;       range is 0 ~ 32, zero_extend or sign_extend will get same result.
+ (define_insn "*<bitmanip_optab>disi2"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+-	(sign_extend:DI
+-	  (clz_ctz_pcnt:SI (match_operand:SI 1 "register_operand" "r"))))]
++        (sign_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")
++   (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")))]
++        (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")
++   (set_attr "mode" "DI")])
+ 
+-(define_insn "*<optab>_not<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 "register_operand" "r")))]
++(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"
+-  "<insn>n\t%0,%2,%1"
+-  [(set_attr "type" "bitmanip")])
++  "@
++   zext.h\t%0,%1
++   lhu\t%0,%1"
++  [(set_attr "type" "bitmanip,load")
++   (set_attr "mode" "<GPR:MODE>")])
+ 
+-(define_insn "*xor_not<mode>"
+-  [(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"))))]
++(define_insn "*extend<SHORT:mode><SUPERQI:mode>2_zbb"
++  [(set (match_operand:SUPERQI   0 "register_operand"     "=r,r")
++	(sign_extend:SUPERQI
++	    (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
+   "TARGET_ZBB"
+-  "xnor\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+- 
+-;;; ??? pack
++  "@
++   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_bitmanip"
+-  [(set (match_operand:GPR 0 "register_operand" "=r,r")
+-	(zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
++(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 "type" "bitmanip,load")
++   (set_attr "mode" "HI")])
+ 
+-(define_insn "*zero_extendsidi2_bitmanip"
+-  [(set (match_operand:DI 0 "register_operand" "=r,r")
+-	(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
+-  "TARGET_64BIT && (TARGET_ZBB || TARGET_ZBA)"
+-  "@
+-   zext.w\t%0,%1
+-   lwu\t%0,%1"
+-  [(set_attr "type" "bitmanip,load")])
++(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"
++  { return TARGET_64BIT ? "ror%i2w\t%0,%1,%2" : "ror%i2\t%0,%1,%2"; }
++  [(set_attr "type" "bitmanip")])
++
++(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"
++  "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"
++  [(set_attr "type" "bitmanip")])
++
++(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"
++  { return TARGET_64BIT ? "rolw\t%0,%1,%2" : "rol\t%0,%1,%2"; }
++  [(set_attr "type" "bitmanip")])
++
++(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"
++  "rol\t%0,%1,%2"
++  [(set_attr "type" "bitmanip")])
++
++(define_insn "rotlsi3_sext"
++  [(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"
++  "rolw\t%0,%1,%2"
++  [(set_attr "type" "bitmanip")])
++
++(define_insn "bswap<mode>2"
++  [(set (match_operand:X 0 "register_operand" "=r")
++        (bswap:X (match_operand:X 1 "register_operand" "r")))]
++  "TARGET_64BIT && TARGET_ZBB"
++  "rev8\t%0,%1"
++  [(set_attr "type" "bitmanip")])
+ 
+ (define_insn "<bitmanip_optab><mode>3"
+   [(set (match_operand:X 0 "register_operand" "=r")
+-	(any_minmax:X (match_operand:X 1 "register_operand" "r")
+-		      (match_operand:X 2 "register_operand" "r")))]
++        (bitmanip_minmax:X (match_operand:X 1 "register_operand" "r")
++			   (match_operand:X 2 "register_operand" "r")))]
+   "TARGET_ZBB"
+   "<bitmanip_insn>\t%0,%1,%2"
+   [(set_attr "type" "bitmanip")])
+ 
++;; ZBS extension.
++
+ (define_insn "*bset<mode>"
+   [(set (match_operand:X 0 "register_operand" "=r")
+ 	(ior:X (ashift:X (const_int 1)
+@@ -155,41 +288,6 @@
+   "bseti\t%0,%1,%S2"
+   [(set_attr "type" "bitmanip")])
+ 
+-(define_insn "*bsetw"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(sign_extend:DI
+-	 (subreg:SI
+-	  (ior:DI (subreg:DI
+-		   (ashift:SI (const_int 1)
+-			      (match_operand:QI 2 "register_operand" "r")) 0)
+-		  (match_operand:DI 1 "register_operand" "r")) 0)))]
+-  "TARGET_64BIT && TARGET_ZBS"
+-  "bsetw\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_insn "*bsetw_mask"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(sign_extend:DI
+-	 (subreg:SI
+-	  (ior:DI (subreg:DI
+-		   (ashift:SI
+-		    (const_int 1)
+-		    (subreg:QI
+-		     (and:DI (match_operand:DI 2 "register_operand" "r")
+-			     (match_operand 3 "const31_operand" "i")) 0)) 0)
+-		  (match_operand:DI 1 "register_operand" "r")) 0)))]
+-  "TARGET_64BIT && TARGET_ZBS"
+-  "bsetw\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_insn "*bsetiw"
+-  [(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")))]
+-  "TARGET_64BIT && TARGET_ZBS"
+-  "bsetiw\t%0,%1,%S2"
+-  [(set_attr "type" "bitmanip")])
+-
+ (define_insn "*bclr<mode>"
+   [(set (match_operand:X 0 "register_operand" "=r")
+ 	(and:X (rotate:X (const_int -2)
+@@ -207,27 +305,6 @@
+   "bclri\t%0,%1,%T2"
+   [(set_attr "type" "bitmanip")])
+ 
+-(define_insn "*bclrw"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(sign_extend:DI
+-	 (subreg:SI
+-	  (and:DI
+-	   (not:DI (subreg:DI
+-		    (ashift:SI (const_int 1)
+-			       (match_operand:QI 2 "register_operand" "r")) 0))
+-	   (match_operand:DI 1 "register_operand" "r")) 0)))]
+-  "TARGET_64BIT && TARGET_ZBS"
+-  "bclrw\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_insn "*bclriw"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(and:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
+-		(match_operand 2 "not_single_bit_mask_operand" "i")))]
+-  "TARGET_64BIT && TARGET_ZBS"
+-  "bclriw\t%0,%1,%T2"
+-  [(set_attr "type" "bitmanip")])
+-
+ (define_insn "*binv<mode>"
+   [(set (match_operand:X 0 "register_operand" "=r")
+ 	(xor:X (ashift:X (const_int 1)
+@@ -245,26 +322,6 @@
+   "binvi\t%0,%1,%S2"
+   [(set_attr "type" "bitmanip")])
+ 
+-(define_insn "*binvw"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(sign_extend:DI
+-	 (subreg:SI
+-	  (xor:DI (subreg:DI
+-		   (ashift:SI (const_int 1)
+-			      (match_operand:QI 2 "register_operand" "r")) 0)
+-		  (match_operand:DI 1 "register_operand" "r")) 0)))]
+-  "TARGET_64BIT && TARGET_ZBS"
+-  "binvw\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_insn "*binviw"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(xor:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
+-		(match_operand 2 "single_bit_mask_operand" "i")))]
+-  "TARGET_64BIT && TARGET_ZBS"
+-  "binviw\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")
+@@ -282,161 +339,4 @@
+ 			(match_operand 2 "immediate_operand" "i")))]
+   "TARGET_ZBS"
+   "bexti\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_insn "*bextw"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(and:DI
+-	 (subreg:DI
+-	  (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+-		       (match_operand:QI 2 "register_operand" "r")) 0)
+-	 (const_int 1)))]
+-  "TARGET_64BIT && TARGET_ZBS"
+-  "bextw\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-;;; ??? s[lr]o*
+-
+-(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"
+-  { return TARGET_64BIT ? "ror%i2w\t%0,%1,%2" : "ror%i2\t%0,%1,%2"; }
+-  [(set_attr "type" "bitmanip")])
+-
+-(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"
+-  "ror%i2\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_expand "riscv_rolw"
+-  [(match_operand:SI 0 "register_operand" "=r")
+-   (match_operand:SI 1 "register_operand" "r")
+-   (match_operand:SI 2 "register_operand" "r")]
+-  "TARGET_64BIT && TARGET_ZBB"
+-{
+-  emit_insn (gen_rotlsi3 (operands[0], operands[1], operands[2]));
+-  DONE;
+-})
+-
+-(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"
+-  { return TARGET_64BIT ? "rolw\t%0,%1,%2" : "rol\t%0,%1,%2"; }
+-  [(set_attr "type" "bitmanip")])
+-
+-(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"
+-  "rol\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_insn "rotlsi3_sext"
+-  [(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"
+-  "rolw\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-;;; ??? grev
+-
+-(define_insn "bswapsi2"
+-  [(set (match_operand:SI 0 "register_operand" "=r")
+-        (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
+-  "TARGET_ZBB"
+-{
+-  if (TARGET_64BIT)
+-    return TARGET_ZBB ? "rev8\t%0,%1\n\tsrai\t%0,%0,32" : "rev8.w\t%0,%1";
+-  else
+-    return "rev8\t%0,%1";
+-}
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_insn "bswapdi2"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(bswap:DI (match_operand:DI 1 "register_operand" "r")))]
+-  "TARGET_64BIT && TARGET_ZBB"
+-  "rev8\t%0,%1"
+-  [(set_attr "type" "bitmanip")])
+-
+-;;; ??? shfl/unshfl
+-
+-;;; ??? bext/bdep
+-
+-;;; ??? clmul
+-
+-;;; ??? crc
+-
+-;;; ??? bmat
+-
+-;; ??? Can we do this by using the % communtative constraint?
+-
+-;;; ??? cmov
+-
+-;;; ??? fs[lr]
+-
+-(define_insn "*shNadd"
+-  [(set (match_operand:X 0 "register_operand" "=r")
+-	(plus:X (ashift:X (match_operand:X 1 "register_operand" "r")
+-			  (match_operand:QI 2 "immediate_operand" "I"))
+-		(match_operand:X 3 "register_operand" "r")))]
+-  "TARGET_ZBA
+-   && (INTVAL (operands[2]) >= 1) && (INTVAL (operands[2]) <= 3)"
+-  "sh%2add\t%0,%1,%3"
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_insn "*shNadduw"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(plus:DI
+-	 (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
+-			    (match_operand:QI 2 "immediate_operand" "I"))
+-		 (match_operand 3 "immediate_operand" ""))
+-	 (match_operand:DI 4 "register_operand" "r")))]
+-  "TARGET_64BIT && TARGET_ZBA
+-   && (INTVAL (operands[2]) >= 1) && (INTVAL (operands[2]) <= 3)
+-   && (INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff"
+-  "sh%2add.uw\t%0,%1,%4"
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_insn "*add.uw"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(plus:DI (zero_extend:DI
+-		  (match_operand:SI 1 "register_operand" "r"))
+-		 (match_operand:DI 2 "register_operand" "r")))]
+-  "TARGET_64BIT && TARGET_ZBA"
+-  "add.uw\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-(define_insn "*slliuw"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-	(and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
+-			   (match_operand:QI 2 "immediate_operand" "I"))
+-		(match_operand 3 "immediate_operand" "")))]
+-  "TARGET_64BIT && TARGET_ZBA
+-   && (INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff"
+-  "slli.uw\t%0,%1,%2"
+-  [(set_attr "type" "bitmanip")])
+-
+-;; ??? bfxp
+-
+-;; sext
+-
+-(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"
+-  "@
+-   sext.<SHORT:size>\t%0,%1
+-   l<SHORT:size>\t%0,%1"
+-  [(set_attr "type" "bitmanip")
+-   (set_attr "length" "4")])
++  [(set_attr "type" "bitmanip")])
+\ No newline at end of file
+-- 
+2.33.1
+

+ 208 - 0
recipes-devtools/gcc/gcc/0017-Implement-instruction-patterns-for-ZBA-extension.patch

@@ -0,0 +1,208 @@
+From 3b7112d4b773768af0da81e7c9575fc9a0d90062 Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Thu, 18 Nov 2021 14:42:41 +0800
+Subject: [PATCH 17/26] Implement instruction patterns for ZBA extension
+
+---
+ gcc/config/riscv/riscv.md                     | 12 +++++--
+ gcc/testsuite/gcc.target/riscv/zba-adduw.c    | 12 +++++++
+ .../gcc.target/riscv/zba-shNadd-01.c          | 19 ++++++++++++
+ .../gcc.target/riscv/zba-shNadd-02.c          | 19 ++++++++++++
+ .../gcc.target/riscv/zba-shNadd-03.c          | 31 +++++++++++++++++++
+ gcc/testsuite/gcc.target/riscv/zba-slliuw.c   | 11 +++++++
+ gcc/testsuite/gcc.target/riscv/zba-zextw.c    | 10 ++++++
+ 7 files changed, 111 insertions(+), 3 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zba-adduw.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zba-shNadd-01.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zba-shNadd-02.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zba-shNadd-03.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zba-slliuw.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zba-zextw.c
+
+diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
+index 26003ac5df7..34702af3aff 100644
+--- a/gcc/config/riscv/riscv.md
++++ b/gcc/config/riscv/riscv.md
+@@ -1057,11 +1057,16 @@
+ 
+ ;; Extension insns.
+ 
+-(define_insn_and_split "zero_extendsidi2"
++(define_expand "zero_extendsidi2"
++  [(set (match_operand:DI 0 "register_operand")
++	(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
++  "TARGET_64BIT")
++
++(define_insn_and_split "*zero_extendsidi2_internal"
+   [(set (match_operand:DI     0 "register_operand"     "=r,r")
+ 	(zero_extend:DI
+ 	    (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+-  "TARGET_64BIT"
++  "TARGET_64BIT && !(TARGET_ZBA || TARGET_ZBB)"
+   "@
+    #
+    lwu\t%0,%1"
+@@ -1833,7 +1838,7 @@
+ 			   (match_operand:QI 2 "immediate_operand" "I"))
+ 		(match_operand 3 "immediate_operand" "")))
+    (clobber (match_scratch:DI 4 "=&r"))]
+-  "TARGET_64BIT
++  "TARGET_64BIT && !TARGET_ZBA
+    && ((INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff)"
+   "#"
+   "&& reload_completed"
+@@ -2642,6 +2647,7 @@
+   "<load>\t%3, %1\;<load>\t%0, %2\;xor\t%0, %3, %0\;li\t%3, 0"
+   [(set_attr "length" "12")])
+ 
++(include "bitmanip.md")
+ (include "sync.md")
+ (include "peephole.md")
+ (include "pic.md")
+diff --git a/gcc/testsuite/gcc.target/riscv/zba-adduw.c b/gcc/testsuite/gcc.target/riscv/zba-adduw.c
+new file mode 100644
+index 00000000000..480d62c884d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zba-adduw.c
+@@ -0,0 +1,12 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zba_zbs -mabi=lp64 -O2" } */
++
++int foo(int n, unsigned char *arr, unsigned y){
++  int s = 0;
++  unsigned x = 0;
++  for (;x<n;x++)
++    s += arr[x+y];
++  return s;
++}
++
++/* { dg-final { scan-assembler "add.uw" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zba-shNadd-01.c b/gcc/testsuite/gcc.target/riscv/zba-shNadd-01.c
+new file mode 100644
+index 00000000000..9893fb6c451
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zba-shNadd-01.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zba -mabi=lp64 -O2" } */
++
++long test_1(long a, long b)
++{
++  return a + (b << 1);
++}
++long test_2(long a, long b)
++{
++  return a + (b << 2);
++}
++long test_3(long a, long b)
++{
++  return a + (b << 3);
++}
++
++/* { dg-final { scan-assembler-times "sh1add" 1 } } */
++/* { dg-final { scan-assembler-times "sh2add" 1 } } */
++/* { dg-final { scan-assembler-times "sh3add" 1 } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zba-shNadd-02.c b/gcc/testsuite/gcc.target/riscv/zba-shNadd-02.c
+new file mode 100644
+index 00000000000..f025849dc27
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zba-shNadd-02.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv32gc_zba -mabi=ilp32 -O2" } */
++
++long test_1(long a, long b)
++{
++  return a + (b << 1);
++}
++long test_2(long a, long b)
++{
++  return a + (b << 2);
++}
++long test_3(long a, long b)
++{
++  return a + (b << 3);
++}
++
++/* { dg-final { scan-assembler-times "sh1add" 1 } } */
++/* { dg-final { scan-assembler-times "sh2add" 1 } } */
++/* { dg-final { scan-assembler-times "sh3add" 1 } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zba-shNadd-03.c b/gcc/testsuite/gcc.target/riscv/zba-shNadd-03.c
+new file mode 100644
+index 00000000000..ef75e7fc486
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zba-shNadd-03.c
+@@ -0,0 +1,31 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zba -mabi=lp64 -O2" } */
++
++/* RV64 only.  */
++int foos(short *x, int n){
++  return x[n];
++}
++int fooi(int *x, int n){
++  return x[n];
++}
++int fooll(long long *x, int n){
++  return x[n];
++}
++
++/* RV64 only.  */
++int ufoos(short *x, unsigned int n){
++  return x[n];
++}
++int ufooi(int *x, unsigned int n){
++  return x[n];
++}
++int ufooll(long long *x, unsigned int n){
++  return x[n];
++}
++
++/* { dg-final { scan-assembler-times "sh1add\t" 1 } } */
++/* { dg-final { scan-assembler-times "sh2add\t" 1 } } */
++/* { dg-final { scan-assembler-times "sh3add\t" 1 } } */
++/* { dg-final { scan-assembler-times "sh3add.uw" 1 } } */
++/* { dg-final { scan-assembler-times "sh3add.uw" 1 } } */
++/* { dg-final { scan-assembler-times "sh3add.uw" 1 } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zba-slliuw.c b/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
+new file mode 100644
+index 00000000000..55ebc1c81ce
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
+@@ -0,0 +1,11 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zba -mabi=lp64 -O2" } */
++
++long
++foo (long i)
++{
++  return (long)(unsigned int)i << 10;
++}
++/* XXX: This pattern need combine improvement or intermediate instruction
++ *      from zbs.   */
++/* { dg-final { scan-assembler-not "slli.uw" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zba-zextw.c b/gcc/testsuite/gcc.target/riscv/zba-zextw.c
+new file mode 100644
+index 00000000000..e8cccd0e374
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zba-zextw.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zba_zbs -mabi=lp64 -O2" } */
++
++long
++foo (long i)
++{
++  return (long)(unsigned int)i;
++}
++/* XXX: This pattern require combine improvement.   */
++/* { dg-final { scan-assembler-not "slli.uw" } } */
+\ No newline at end of file
+-- 
+2.33.1
+

+ 119 - 0
recipes-devtools/gcc/gcc/0018-Cost-model-for-zba-extension.patch

@@ -0,0 +1,119 @@
+From b58a42aac28becb118a8482d41c4188e00ad0c3a Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Thu, 18 Nov 2021 14:55:04 +0800
+Subject: [PATCH 18/26] Cost model for zba extension
+
+---
+ gcc/config/riscv/riscv.c | 82 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 82 insertions(+)
+
+diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
+index 17cdf705c32..7d5e22d9fe2 100644
+--- a/gcc/config/riscv/riscv.c
++++ b/gcc/config/riscv/riscv.c
+@@ -1680,6 +1680,10 @@ riscv_extend_cost (rtx op, bool unsigned_p)
+     /* We can use ANDI.  */
+     return COSTS_N_INSNS (1);
+ 
++  /* ZBA provide zext.w.  */
++  if (TARGET_ZBA && TARGET_64BIT && unsigned_p && GET_MODE (op) == SImode)
++    return COSTS_N_INSNS (1);
++
+   if (!unsigned_p && GET_MODE (op) == SImode)
+     /* We can use SEXT.W.  */
+     return COSTS_N_INSNS (1);
+@@ -1753,6 +1757,22 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
+       return false;
+ 
+     case AND:
++      /* slli.uw pattern for zba.  */
++      if (TARGET_ZBA && TARGET_64BIT && mode == DImode
++	  && GET_CODE (XEXP (x, 0)) == ASHIFT)
++	{
++	  rtx and_rhs = XEXP (x, 1);
++	  rtx ashift_lhs = XEXP (XEXP (x, 0), 0);
++	  rtx ashift_rhs = XEXP (XEXP (x, 0), 1);
++	  if (REG_P (ashift_lhs)
++	      && CONST_INT_P (ashift_rhs)
++	      && CONST_INT_P (and_rhs)
++	      && ((INTVAL (and_rhs) >> INTVAL (ashift_rhs)) == 0xffffffff))
++	    *total = COSTS_N_INSNS (1);
++	    return true;
++	}
++      gcc_fallthrough ();
++
+     case IOR:
+     case XOR:
+       /* Double-word operations use two single-word operations.  */
+@@ -1844,6 +1864,68 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
+ 
+     case MINUS:
+     case PLUS:
++      /* add.uw pattern for zba.  */
++      if (TARGET_ZBA
++	  && (TARGET_64BIT && (mode == DImode))
++	  && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
++	  && REG_P (XEXP (XEXP (x, 0), 0))
++	  && GET_MODE (XEXP (XEXP (x, 0), 0)) == SImode)
++	{
++	  *total = COSTS_N_INSNS (1);
++	  return true;
++	}
++      /* shNadd pattern for zba.  */
++      if (TARGET_ZBA
++	  && ((!TARGET_64BIT && (mode == SImode)) ||
++	      (TARGET_64BIT && (mode == DImode)))
++	  && (GET_CODE (XEXP (x, 0)) == ASHIFT)
++	  && REG_P (XEXP (XEXP (x, 0), 0))
++	  && CONST_INT_P (XEXP (XEXP (x, 0), 0))
++	  && IN_RANGE (INTVAL (XEXP (XEXP (x, 0), 0)), 1, 3))
++	{
++	  *total = COSTS_N_INSNS (1);
++	  return true;
++	}
++      /* shNadd.uw pattern for zba.
++	 [(set (match_operand:DI 0 "register_operand" "=r")
++	       (plus:DI
++		 (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
++				    (match_operand:QI 2 "immediate_operand" "I"))
++			 (match_operand 3 "immediate_operand" ""))
++		 (match_operand:DI 4 "register_operand" "r")))]
++	 "TARGET_64BIT && TARGET_ZBA
++	  && (INTVAL (operands[2]) >= 1) && (INTVAL (operands[2]) <= 3)
++	  && (INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff"
++      */
++      if (TARGET_ZBA
++	  && (TARGET_64BIT && (mode == DImode))
++	  && (GET_CODE (XEXP (x, 0)) == AND)
++	  && (REG_P (XEXP (x, 1))))
++	{
++	  do {
++	    rtx and_lhs = XEXP (XEXP (x, 0), 0);
++	    rtx and_rhs = XEXP (XEXP (x, 0), 1);
++	    if (GET_CODE (and_lhs) != ASHIFT)
++	      break;
++	    if (!CONST_INT_P (and_rhs))
++	      break;
++
++	    rtx ashift_lhs = XEXP (and_lhs, 0);
++	    rtx ashift_rhs = XEXP (and_lhs, 1);
++
++	    if (!CONST_INT_P (ashift_rhs)
++		|| !IN_RANGE (INTVAL (ashift_rhs), 1, 3))
++	      break;
++
++	    if (CONST_INT_P (and_rhs)
++		&& ((INTVAL (and_rhs) >> INTVAL (ashift_rhs)) == 0xffffffff))
++	      {
++		*total = COSTS_N_INSNS (1);
++		return true;
++	      }
++	  } while (false);
++	}
++
+       if (float_mode_p)
+ 	*total = tune_param->fp_add[mode == DFmode];
+       else
+-- 
+2.33.1
+

+ 274 - 0
recipes-devtools/gcc/gcc/0019-Implement-instruction-patterns-for-ZBB-extension.patch

@@ -0,0 +1,274 @@
+From adb47e7bb51c1725f36b9b92ba5b0bd2f7a1d74d Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Thu, 18 Nov 2021 15:16:54 +0800
+Subject: [PATCH 19/26] Implement instruction patterns for ZBB extension
+
+---
+ gcc/config/riscv/riscv.md                     | 21 ++++++++++---
+ .../gcc.target/riscv/zbb-andn-orn-xnor-01.c   | 21 +++++++++++++
+ .../gcc.target/riscv/zbb-andn-orn-xnor-02.c   | 21 +++++++++++++
+ gcc/testsuite/gcc.target/riscv/zbb-min-max.c  | 31 +++++++++++++++++++
+ .../gcc.target/riscv/zbb-rol-ror-01.c         | 16 ++++++++++
+ .../gcc.target/riscv/zbb-rol-ror-02.c         | 16 ++++++++++
+ .../gcc.target/riscv/zbb-rol-ror-03.c         | 17 ++++++++++
+ gcc/testsuite/gcc.target/riscv/zbbw.c         | 25 +++++++++++++++
+ 8 files changed, 163 insertions(+), 5 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbb-andn-orn-xnor-01.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbb-andn-orn-xnor-02.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbb-min-max.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbb-rol-ror-01.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbb-rol-ror-02.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbb-rol-ror-03.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbbw.c
+
+diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
+index 34702af3aff..143a83eec83 100644
+--- a/gcc/config/riscv/riscv.md
++++ b/gcc/config/riscv/riscv.md
+@@ -170,7 +170,7 @@
+ (define_attr "type"
+   "unknown,branch,jump,call,load,fpload,store,fpstore,
+    mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
+-   fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip"
++   fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate"
+   (cond [(eq_attr "got" "load") (const_string "load")
+ 
+ 	 ;; If a doubleword move uses these expensive instructions,
+@@ -1081,11 +1081,17 @@
+   [(set_attr "move_type" "shift_shift,load")
+    (set_attr "mode" "DI")])
+ 
+-(define_insn_and_split "zero_extendhi<GPR:mode>2"
++(define_expand "zero_extendhi<GPR:mode>2"
++  [(set (match_operand:GPR    0 "register_operand")
++	(zero_extend:GPR
++	    (match_operand:HI 1 "nonimmediate_operand")))]
++  "")
++
++(define_insn_and_split "*zero_extendhi<GPR:mode>2"
+   [(set (match_operand:GPR    0 "register_operand"     "=r,r")
+ 	(zero_extend:GPR
+ 	    (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
+-  ""
++  "!TARGET_ZBB"
+   "@
+    #
+    lhu\t%0,%1"
+@@ -1132,11 +1138,16 @@
+   [(set_attr "move_type" "move,load")
+    (set_attr "mode" "DI")])
+ 
+-(define_insn_and_split "extend<SHORT:mode><SUPERQI:mode>2"
++(define_expand "extend<SHORT:mode><SUPERQI:mode>2"
++  [(set (match_operand:SUPERQI 0 "register_operand")
++	(sign_extend:SUPERQI (match_operand:SHORT 1 "nonimmediate_operand")))]
++  "")
++
++(define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
+   [(set (match_operand:SUPERQI   0 "register_operand"     "=r,r")
+ 	(sign_extend:SUPERQI
+ 	    (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
+-  ""
++  "!TARGET_ZBB"
+   "@
+    #
+    l<SHORT:size>\t%0,%1"
+diff --git a/gcc/testsuite/gcc.target/riscv/zbb-andn-orn-xnor-01.c b/gcc/testsuite/gcc.target/riscv/zbb-andn-orn-xnor-01.c
+new file mode 100644
+index 00000000000..0037dea5647
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbb-andn-orn-xnor-01.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zbb -mabi=lp64 -O2" } */
++
++unsigned long long foo1(unsigned long long rs1, unsigned long long rs2)
++{
++return rs1 & ~rs2;
++}
++
++unsigned long long foo2(unsigned long long rs1, unsigned long long rs2)
++{
++return rs1 | ~rs2;
++}
++
++unsigned long long foo3(unsigned long long rs1, unsigned long long rs2)
++{
++return rs1 ^ ~rs2;
++}
++
++/* { dg-final { scan-assembler-times "andn" 2 } } */
++/* { dg-final { scan-assembler-times "orn" 2 } } */
++/* { dg-final { scan-assembler-times "xnor" 2 } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zbb-andn-orn-xnor-02.c b/gcc/testsuite/gcc.target/riscv/zbb-andn-orn-xnor-02.c
+new file mode 100644
+index 00000000000..b0c1e40c554
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbb-andn-orn-xnor-02.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv32gc_zbb -mabi=ilp32 -O2" } */
++
++unsigned int foo1(unsigned int rs1, unsigned int rs2)
++{
++return rs1 & ~rs2;
++}
++
++unsigned int foo2(unsigned  int rs1, unsigned  int rs2)
++{
++return rs1 | ~rs2;
++}
++
++unsigned int foo3(unsigned int rs1, unsigned int rs2)
++{
++return rs1 ^ ~rs2;
++}
++
++/* { dg-final { scan-assembler-times "andn" 2 } } */
++/* { dg-final { scan-assembler-times "orn" 2 } } */
++/* { dg-final { scan-assembler-times "xnor" 2 } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zbb-min-max.c b/gcc/testsuite/gcc.target/riscv/zbb-min-max.c
+new file mode 100644
+index 00000000000..dc72bb4ad71
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbb-min-max.c
+@@ -0,0 +1,31 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zbb -mabi=lp64 -O2" } */
++
++long
++foo1 (long i, long j)
++{
++  return i < j ? i : j;
++}
++
++long
++foo2 (long i, long j)
++{
++  return i > j ? i : j;
++}
++
++unsigned long
++foo3 (unsigned long i, unsigned long j)
++{
++  return i < j ? i : j;
++}
++
++unsigned long
++foo4 (unsigned long i, unsigned long j)
++{
++  return i > j ? i : j;
++}
++
++/* { dg-final { scan-assembler-times "min" 3 } } */
++/* { dg-final { scan-assembler-times "max" 3 } } */
++/* { dg-final { scan-assembler-times "minu" 1 } } */
++/* { dg-final { scan-assembler-times "maxu" 1 } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zbb-rol-ror-01.c b/gcc/testsuite/gcc.target/riscv/zbb-rol-ror-01.c
+new file mode 100644
+index 00000000000..958966289df
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbb-rol-ror-01.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zbb -mabi=lp64 -O2" } */
++
++unsigned long foo1(unsigned long rs1, unsigned long rs2)
++{
++    long shamt = rs2 & (64 - 1);
++    return (rs1 << shamt) | (rs1 >> ((64 - shamt) & (64 - 1)));
++}
++unsigned long foo2(unsigned long rs1, unsigned long rs2)
++{
++    unsigned long shamt = rs2 & (64 - 1);
++    return (rs1 >> shamt) | (rs1 << ((64 - shamt) & (64 - 1)));
++}
++
++/* { dg-final { scan-assembler-times "rol" 2 } } */
++/* { dg-final { scan-assembler-times "ror" 2 } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zbb-rol-ror-02.c b/gcc/testsuite/gcc.target/riscv/zbb-rol-ror-02.c
+new file mode 100644
+index 00000000000..24b482f2145
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbb-rol-ror-02.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv32gc_zbb -mabi=ilp32 -O2" } */
++
++unsigned int foo1(unsigned int rs1, unsigned int rs2)
++{
++    unsigned int shamt = rs2 & (32 - 1);
++    return (rs1 << shamt) | (rs1 >> ((32 - shamt) & (32 - 1)));
++}
++unsigned int foo2(unsigned int rs1, unsigned int rs2)
++{
++    unsigned int shamt = rs2 & (32 - 1);
++    return (rs1 >> shamt) | (rs1 << ((32 - shamt) & (32 - 1)));
++}
++
++/* { dg-final { scan-assembler-times "rol" 2 } } */
++/* { dg-final { scan-assembler-times "ror" 2 } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zbb-rol-ror-03.c b/gcc/testsuite/gcc.target/riscv/zbb-rol-ror-03.c
+new file mode 100644
+index 00000000000..ffde7c9cd58
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbb-rol-ror-03.c
+@@ -0,0 +1,17 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zbb -mabi=lp64 -O2" } */
++
++/* RV64 only*/
++unsigned int rol(unsigned int rs1, unsigned int rs2)
++{
++    int shamt = rs2 & (32 - 1);
++    return (rs1 << shamt) | (rs1 >> ((64 - shamt) & (32 - 1)));
++}
++unsigned int ror(unsigned int rs1, unsigned int rs2)
++{
++    int shamt = rs2 & (64 - 1);
++    return (rs1 >> shamt) | (rs1 << ((32 - shamt) & (32 - 1)));
++}
++
++/* { dg-final { scan-assembler-times "rolw" 1 } } */
++/* { dg-final { scan-assembler-times "rorw" 1 } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zbbw.c b/gcc/testsuite/gcc.target/riscv/zbbw.c
+new file mode 100644
+index 00000000000..ed88ca5cceb
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbbw.c
+@@ -0,0 +1,25 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zbb -mabi=lp64 -O2" } */
++
++int
++clz (int i)
++{
++  return __builtin_clz (i);
++}
++
++int
++ctz (int i)
++{
++  return __builtin_ctz (i);
++}
++
++int
++popcount (int i)
++{
++  return __builtin_popcount (i);
++}
++
++
++/* { dg-final { scan-assembler-times "clzw" 1 } } */
++/* { dg-final { scan-assembler-times "ctzw" 1 } } */
++/* { dg-final { scan-assembler-times "cpopw" 1 } } */
+\ No newline at end of file
+-- 
+2.33.1
+

+ 48 - 0
recipes-devtools/gcc/gcc/0020-Cost-model-for-zbb-extension.patch

@@ -0,0 +1,48 @@
+From c1eaf07b4e8a7ea6c3f053003a8ebd9a1e933f22 Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Thu, 18 Nov 2021 15:37:45 +0800
+Subject: [PATCH 20/26] Cost model for zbb extension
+
+---
+ gcc/config/riscv/riscv.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
+index 7d5e22d9fe2..bf91d8c7371 100644
+--- a/gcc/config/riscv/riscv.c
++++ b/gcc/config/riscv/riscv.c
+@@ -1684,6 +1684,16 @@ riscv_extend_cost (rtx op, bool unsigned_p)
+   if (TARGET_ZBA && TARGET_64BIT && unsigned_p && GET_MODE (op) == SImode)
+     return COSTS_N_INSNS (1);
+ 
++  /* ZBB provide zext.h, sext.b and sext.h.  */
++  if (TARGET_ZBB)
++    {
++      if (!unsigned_p && GET_MODE (op) == QImode)
++	return COSTS_N_INSNS (1);
++
++      if (GET_MODE (op) == HImode)
++	return COSTS_N_INSNS (1);
++    }
++
+   if (!unsigned_p && GET_MODE (op) == SImode)
+     /* We can use SEXT.W.  */
+     return COSTS_N_INSNS (1);
+@@ -1775,6 +1785,14 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
+ 
+     case IOR:
+     case XOR:
++      /* orn, andn and xorn pattern for zbb.  */
++      if (TARGET_ZBB
++	  && GET_CODE (XEXP (x, 0)) == NOT)
++	{
++	  *total = riscv_binary_cost (x, 1, 2);
++	  return true;
++	}
++
+       /* Double-word operations use two single-word operations.  */
+       *total = riscv_binary_cost (x, 1, 2);
+       return false;
+-- 
+2.33.1
+

+ 108 - 0
recipes-devtools/gcc/gcc/0021-Use-li-and-rori-to-load-constants.patch

@@ -0,0 +1,108 @@
+From b302f25e1f472cfe8b8e1867fc7499757c6ec4f0 Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Thu, 18 Nov 2021 15:47:00 +0800
+Subject: [PATCH 21/26] Use li and rori to load constants
+
+---
+ gcc/config/riscv/riscv.c                     | 41 ++++++++++++++++++++
+ gcc/testsuite/gcc.target/riscv/zbb-li-rotr.c | 35 +++++++++++++++++
+ 2 files changed, 76 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbb-li-rotr.c
+
+diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
+index bf91d8c7371..9e45c1ff9be 100644
+--- a/gcc/config/riscv/riscv.c
++++ b/gcc/config/riscv/riscv.c
+@@ -439,6 +439,47 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
+ 	}
+     }
+ 
++  if (cost > 2 && TARGET_64BIT && TARGET_ZBB)
++    {
++      int leading_ones = clz_hwi (~value);
++      int trailing_ones = ctz_hwi (~value);
++
++      /* If all bits are one except a few that are zero, and the zero bits
++	 are within a range of 11 bits, and at least one of the upper 32-bits
++	 is a zero, then we can generate a constant by loading a small
++	 negative constant and rotating.  */
++      if (leading_ones < 32
++	  && ((64 - leading_ones - trailing_ones) < 12))
++	{
++	  codes[0].code = UNKNOWN;
++	  /* The sign-bit might be zero, so just rotate to be safe.  */
++	  codes[0].value = (((unsigned HOST_WIDE_INT) value >> trailing_ones)
++			    | (value << (64 - trailing_ones)));
++	  codes[1].code = ROTATERT;
++	  codes[1].value = 64 - trailing_ones;
++	  cost = 2;
++	}
++      /* Handle the case where the 11 bit range of zero bits wraps around.  */
++      else
++	{
++	  int upper_trailing_ones = ctz_hwi (~value >> 32);
++	  int lower_leading_ones = clz_hwi (~value << 32);
++
++	  if (upper_trailing_ones < 32 && lower_leading_ones < 32
++	      && ((64 - upper_trailing_ones - lower_leading_ones) < 12))
++	    {
++	      codes[0].code = UNKNOWN;
++	      /* The sign-bit might be zero, so just rotate to be safe.  */
++	      codes[0].value = ((value << (32 - upper_trailing_ones))
++				| ((unsigned HOST_WIDE_INT) value
++				   >> (32 + upper_trailing_ones)));
++	      codes[1].code = ROTATERT;
++	      codes[1].value = 32 - upper_trailing_ones;
++	      cost = 2;
++	    }
++	}
++    }
++
+   gcc_assert (cost <= RISCV_MAX_INTEGER_OPS);
+   return cost;
+ }
+diff --git a/gcc/testsuite/gcc.target/riscv/zbb-li-rotr.c b/gcc/testsuite/gcc.target/riscv/zbb-li-rotr.c
+new file mode 100644
+index 00000000000..ab8138cd874
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbb-li-rotr.c
+@@ -0,0 +1,35 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zbb -mabi=lp64 -O2" } */
++
++long
++li_rori (void)
++{
++  return 0xffff77ffffffffffL;
++}
++
++long
++li_rori_2 (void)
++{
++  return 0x77ffffffffffffffL;
++}
++
++long
++li_rori_3 (void)
++{
++  return 0xfffffffeefffffffL;
++}
++
++long
++li_rori_4 (void)
++{
++  return 0x5ffffffffffffff5L;
++}
++
++long
++li_rori_5 (void)
++{
++  return 0xaffffffffffffffaL;
++}
++
++
++/* { dg-final { scan-assembler-times "rori\t" 5 } } */
+\ No newline at end of file
+-- 
+2.33.1
+

+ 297 - 0
recipes-devtools/gcc/gcc/0022-Implement-instruction-patterns-for-ZBS-extension.patch

@@ -0,0 +1,297 @@
+From d3bc6ead74d78d367c0d6cc53efc57c05d8133e9 Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Thu, 18 Nov 2021 16:08:45 +0800
+Subject: [PATCH 22/26] Implement instruction patterns for ZBS extension
+
+---
+ gcc/config/riscv/predicates.md              | 22 +++++++++++
+ gcc/config/riscv/riscv.c                    | 37 ++++++++++++++++++-
+ gcc/config/riscv/riscv.h                    |  8 ++++
+ gcc/testsuite/gcc.target/riscv/zba-slliuw.c |  4 +-
+ gcc/testsuite/gcc.target/riscv/zbs-bclr.c   | 20 ++++++++++
+ gcc/testsuite/gcc.target/riscv/zbs-bext.c   | 20 ++++++++++
+ gcc/testsuite/gcc.target/riscv/zbs-binv.c   | 20 ++++++++++
+ gcc/testsuite/gcc.target/riscv/zbs-bset.c   | 41 +++++++++++++++++++++
+ 8 files changed, 168 insertions(+), 4 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-bclr.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-bext.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-binv.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-bset.c
+
+diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
+index 23211513554..7a079ebd175 100644
+--- a/gcc/config/riscv/predicates.md
++++ b/gcc/config/riscv/predicates.md
+@@ -74,6 +74,11 @@
+   if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+     return false;
+ 
++  /* Check whether the constant can be loaded in a single
++     instruction with zbs extensions.  */
++  if (TARGET_64BIT && TARGET_ZBS && SINGLE_BIT_MASK_OPERAND (INTVAL (op)))
++    return false;
++
+   /* Otherwise check whether the constant can be loaded in a single
+      instruction.  */
+   return !LUI_OPERAND (INTVAL (op)) && !SMALL_OPERAND (INTVAL (op));
+@@ -217,3 +222,20 @@
+ {
+   return riscv_gpr_save_operation_p (op);
+ })
++
++;; Predicates for the ZBS extension.
++(define_predicate "single_bit_mask_operand"
++  (and (match_code "const_int")
++       (match_test "pow2p_hwi (INTVAL (op))")))
++
++(define_predicate "not_single_bit_mask_operand"
++  (and (match_code "const_int")
++       (match_test "pow2p_hwi (~INTVAL (op))")))
++
++(define_predicate "const31_operand"
++  (and (match_code "const_int")
++       (match_test "INTVAL (op) == 31")))
++
++(define_predicate "const63_operand"
++  (and (match_code "const_int")
++       (match_test "INTVAL (op) == 63")))
+\ No newline at end of file
+diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
+index 9e45c1ff9be..0978666a366 100644
+--- a/gcc/config/riscv/riscv.c
++++ b/gcc/config/riscv/riscv.c
+@@ -388,6 +388,14 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
+       return 1;
+     }
+ 
++  if (TARGET_ZBS && SINGLE_BIT_MASK_OPERAND (value))
++    {
++      /* Simply BSETI.  */
++      codes[0].code = UNKNOWN;
++      codes[0].value = value;
++      return 1;
++    }
++
+   /* End with ADDI.  When constructing HImode constants, do not generate any
+      intermediate value that is not itself a valid HImode constant.  The
+      XORI case below will handle those remaining HImode constants.  */
+@@ -2199,7 +2207,17 @@ riscv_output_move (rtx dest, rtx src)
+ 	  }
+ 
+       if (src_code == CONST_INT)
+-	return "li\t%0,%1";
++  	{
++  	  if (SMALL_OPERAND (INTVAL (src)) || LUI_OPERAND (INTVAL (src)))
++  	    return "li\t%0,%1";
++  
++  	  if (TARGET_ZBS
++  	      && SINGLE_BIT_MASK_OPERAND (INTVAL (src)))
++  	    return "bseti\t%0,zero,%S1";
++  
++  	  /* Should never reach here.  */
++  	  abort ();
++  	}
+ 
+       if (src_code == HIGH)
+ 	return "lui\t%0,%h1";
+@@ -3543,7 +3561,9 @@ riscv_memmodel_needs_release_fence (enum memmodel model)
+    'A'	Print the atomic operation suffix for memory model OP.
+    'F'	Print a FENCE if the memory model requires a release.
+    'z'	Print x0 if OP is zero, otherwise print OP normally.
+-   'i'	Print i if the operand is not a register.  */
++   'i'	Print i if the operand is not a register.
++   'S'	Print shift-index of single-bit mask OP.
++   'T'	Print shift-index of inverted single-bit mask OP.  */
+ 
+ static void
+ riscv_print_operand (FILE *file, rtx op, int letter)
+@@ -3583,6 +3603,19 @@ riscv_print_operand (FILE *file, rtx op, int letter)
+         fputs ("i", file);
+       break;
+ 
++    case 'S':
++      {
++      rtx newop = GEN_INT (ctz_hwi (INTVAL (op)));
++      output_addr_const (file, newop);
++      break;
++      }
++    case 'T':
++      {
++      rtx newop = GEN_INT (ctz_hwi (~INTVAL (op)));
++      output_addr_const (file, newop);
++      break;
++      }
++
+     default:
+       switch (code)
+ 	{
+diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
+index d17096e1dfa..ff6729aedac 100644
+--- a/gcc/config/riscv/riscv.h
++++ b/gcc/config/riscv/riscv.h
+@@ -521,6 +521,14 @@ enum reg_class
+   (((VALUE) | ((1UL<<31) - IMM_REACH)) == ((1UL<<31) - IMM_REACH)	\
+    || ((VALUE) | ((1UL<<31) - IMM_REACH)) + IMM_REACH == 0)
+ 
++/* If this is a single bit mask, then we can load it with bseti.  But this
++   is not useful for any of the low 31 bits because we can use addi or lui
++   to load them.  It is wrong for loading SImode 0x80000000 on rv64 because it
++   needs to be sign-extended.  So we restrict this to the upper 32-bits
++   only.  */
++#define SINGLE_BIT_MASK_OPERAND(VALUE) \
++  (pow2p_hwi (VALUE) && (ctz_hwi (VALUE) >= 32))
++
+ /* Stack layout; function entry, exit and calling.  */
+ 
+ #define STACK_GROWS_DOWNWARD 1
+diff --git a/gcc/testsuite/gcc.target/riscv/zba-slliuw.c b/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
+index 55ebc1c81ce..2c86e446272 100644
+--- a/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
++++ b/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-march=rv64gc_zba -mabi=lp64 -O2" } */
++/* { dg-options "-march=rv64gc_zba_zbs -mabi=lp64 -O2" } */
+ 
+ long
+ foo (long i)
+@@ -8,4 +8,4 @@ foo (long i)
+ }
+ /* XXX: This pattern need combine improvement or intermediate instruction
+  *      from zbs.   */
+-/* { dg-final { scan-assembler-not "slli.uw" } } */
+\ No newline at end of file
++/* { dg-final { scan-assembler "slli.uw" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bclr.c b/gcc/testsuite/gcc.target/riscv/zbs-bclr.c
+new file mode 100644
+index 00000000000..fdf75b039b9
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbs-bclr.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
++
++/* bclr */
++long
++foo0 (long i, long j)
++{
++  return i & ~(1L << j);
++}
++
++/* bclri */
++long
++foo1 (long i)
++{
++  return i & ~(1L << 20);
++}
++
++/* { dg-final { scan-assembler-times "bclr\t" 1 } } */
++/* { dg-final { scan-assembler-times "bclri\t" 1 } } */
++/* { dg-final { scan-assembler-not "andi" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bext.c b/gcc/testsuite/gcc.target/riscv/zbs-bext.c
+new file mode 100644
+index 00000000000..766a7c4423a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbs-bext.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
++
++/* bext */
++long
++foo0 (long i, long j)
++{
++  return 1L & (i >> j);
++}
++
++/* bexti */
++long
++foo1 (long i)
++{
++  return 1L & (i >> 20);
++}
++
++/* { dg-final { scan-assembler-times "bexti\t" 1 } } */
++/* { dg-final { scan-assembler-times "bext\t" 1 } } */
++/* { dg-final { scan-assembler-not "andi" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zbs-binv.c b/gcc/testsuite/gcc.target/riscv/zbs-binv.c
+new file mode 100644
+index 00000000000..d90a6301103
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbs-binv.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
++
++/* binv */
++long
++foo0 (long i, long j)
++{
++  return i ^ (1L << j);
++}
++
++/* binvi */
++long
++foo1 (long i)
++{
++  return i ^ (1L << 20);
++}
++
++/* { dg-final { scan-assembler-times "binv\t" 1 } } */
++/* { dg-final { scan-assembler-times "binvi\t" 1 } } */
++/* { dg-final { scan-assembler-not "andi" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bset.c b/gcc/testsuite/gcc.target/riscv/zbs-bset.c
+new file mode 100644
+index 00000000000..c3107270153
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/zbs-bset.c
+@@ -0,0 +1,41 @@
++/* { dg-do compile } */
++/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
++
++/* bset */
++long
++sub0 (long i, long j)
++{
++  return i | (1L << j);
++}
++
++/* bset_mask */
++long
++sub1 (long i, long j)
++{
++  return i | (1L << (j & 0x3f));
++}
++
++/* bset_1 */
++long
++sub2 (long i)
++{
++  return 1L << i;
++}
++
++/* bset_1_mask */
++long
++sub3 (long i)
++{
++  return 1L << (i & 0x3f);
++}
++
++/* bseti */
++long
++sub4 (long i)
++{
++  return i | (1L << 20);
++}
++
++/* { dg-final { scan-assembler-times "bset\t" 4 } } */
++/* { dg-final { scan-assembler-times "bseti\t" 1 } } */
++/* { dg-final { scan-assembler-not "andi" } } */
+\ No newline at end of file
+-- 
+2.33.1
+

+ 88 - 0
recipes-devtools/gcc/gcc/0023-Cost-model-for-ZBS-extension.patch

@@ -0,0 +1,88 @@
+From 254eef43b7f99cc3308d02343c603286ba121816 Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Thu, 18 Nov 2021 16:13:59 +0800
+Subject: [PATCH 23/26] Cost model for ZBS extension
+
+---
+ gcc/config/riscv/riscv.c | 47 +++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 46 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
+index 0978666a366..61666b8b2f6 100644
+--- a/gcc/config/riscv/riscv.c
++++ b/gcc/config/riscv/riscv.c
+@@ -1830,8 +1830,25 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
+ 	    *total = COSTS_N_INSNS (1);
+ 	    return true;
+ 	}
+-      gcc_fallthrough ();
++      /* bclri pattern for zbs.  */
++      if (TARGET_ZBS
++	  && not_single_bit_mask_operand (XEXP (x, 1), VOIDmode))
++	{
++	  *total = COSTS_N_INSNS (1);
++	  return true;
++	}
++      /* bclr pattern for zbs.  */
++      if (TARGET_ZBS
++	  && REG_P (XEXP (x, 1))
++	  && GET_CODE (XEXP (x, 0)) == ROTATE
++	  && CONST_INT_P (XEXP ((XEXP (x, 0)), 0))
++	  && INTVAL (XEXP ((XEXP (x, 0)), 0)) == -2)
++	{
++	  *total = COSTS_N_INSNS (1);
++	  return true;
++	}
+ 
++      gcc_fallthrough ();
+     case IOR:
+     case XOR:
+       /* orn, andn and xorn pattern for zbb.  */
+@@ -1842,6 +1859,17 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
+ 	  return true;
+ 	}
+ 
++      /* bset[i] and binv[i] pattern for zbs.  */
++      if ((GET_CODE (x) == IOR || GET_CODE (x) == XOR)
++	  && TARGET_ZBS
++	  && ((GET_CODE (XEXP (x, 0)) == ASHIFT
++	      && CONST_INT_P (XEXP (XEXP (x, 0), 0)))
++	      || single_bit_mask_operand (XEXP (x, 1), VOIDmode)))
++	{
++	  *total = COSTS_N_INSNS (1);
++	  return true;
++	}
++
+       /* Double-word operations use two single-word operations.  */
+       *total = riscv_binary_cost (x, 1, 2);
+       return false;
+@@ -1857,9 +1885,26 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
+ 	  *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
+ 	  return true;
+ 	}
++      /* bext pattern for zbs.  */
++      if (TARGET_ZBS && outer_code == SET
++	  && GET_CODE (XEXP (x, 1)) == CONST_INT
++	  && INTVAL (XEXP (x, 1)) == 1)
++	{
++	  *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
++	  return true;
++	}
+       return false;
+ 
+     case ASHIFT:
++      /* bset pattern for zbs.  */
++      if (TARGET_ZBS
++	  && CONST_INT_P (XEXP (x, 0))
++	  && INTVAL (XEXP (x, 0)) == 1)
++	{
++	  *total = COSTS_N_INSNS (1);
++	  return true;
++	}
++      gcc_fallthrough ();
+     case ASHIFTRT:
+     case LSHIFTRT:
+       *total = riscv_binary_cost (x, SINGLE_SHIFT_COST,
+-- 
+2.33.1
+

+ 31 - 0
recipes-devtools/gcc/gcc/0024-RISC-V-costs-handle-BSWAP.patch

@@ -0,0 +1,31 @@
+From 167a062d1a8162b9441a6c0327722e77c8afa01a Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Sun, 21 Nov 2021 21:56:18 -0800
+Subject: [PATCH 24/26] RISC-V: costs: handle BSWAP
+
+---
+ gcc/config/riscv/riscv.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
+index 61666b8b2f6..8e22e36eaaf 100644
+--- a/gcc/config/riscv/riscv.c
++++ b/gcc/config/riscv/riscv.c
+@@ -2110,6 +2110,14 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
+       *total = riscv_extend_cost (XEXP (x, 0), GET_CODE (x) == ZERO_EXTEND);
+       return false;
+ 
++    case BSWAP:
++      if (TARGET_ZBB)
++	{
++	  *total = COSTS_N_INSNS (1);
++	  return true;
++	}
++      return false;
++
+     case FLOAT:
+     case UNSIGNED_FLOAT:
+     case FIX:
+-- 
+2.33.1
+

+ 54 - 0
recipes-devtools/gcc/gcc/0025-RISC-V-costs-support-shift-and-add-in-strength-reduc.patch

@@ -0,0 +1,54 @@
+From a545eb2c28726d0a574a7c6953a809362f6237e6 Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Tue, 23 Nov 2021 11:41:12 +0800
+Subject: [PATCH 25/26] RISC-V: costs: support shift-and-add in
+ strength-reduction
+
+---
+ gcc/config/riscv/riscv.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
+index 8e22e36eaaf..f832fb44d7e 100644
+--- a/gcc/config/riscv/riscv.c
++++ b/gcc/config/riscv/riscv.c
+@@ -393,6 +393,15 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
+       /* Simply BSETI.  */
+       codes[0].code = UNKNOWN;
+       codes[0].value = value;
++
++      /* RISC-V sign-extends all 32bit values that life in a 32bit
++	 register.  To avoid paradoxes, we thus need to use the
++	 sign-extended (negative) representation for the value, if we
++	 want to build 0x80000000 in SImode.  This will then expand
++	 to an ADDI/LI instruction.  */
++      if (mode == SImode && value == 0x80000000)
++	    codes[0].value = -2147483648;
++
+       return 1;
+     }
+ 
+@@ -1998,6 +2007,20 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
+ 	  *total = COSTS_N_INSNS (1);
+ 	  return true;
+ 	}
++    /* Before strength-reduction, the shNadd can be expressed as the addition
++	 of a multiplication with a power-of-two.  If this case is not handled,
++	 the strength-reduction in expmed.c will calculate an inflated cost. */
++      if (TARGET_ZBA
++	  && ((!TARGET_64BIT && (mode == SImode)) ||
++	      (TARGET_64BIT && (mode == DImode)))
++	  && (GET_CODE (XEXP (x, 0)) == MULT)
++	  && REG_P (XEXP (XEXP (x, 0), 0))
++	  && CONST_INT_P (XEXP (XEXP (x, 0), 1))
++	  && IN_RANGE (pow2p_hwi (INTVAL (XEXP (XEXP (x, 0), 1))), 1, 3))
++	{
++	  *total = COSTS_N_INSNS (1);
++	  return true;
++	}
+       /* shNadd.uw pattern for zba.
+ 	 [(set (match_operand:DI 0 "register_operand" "=r")
+ 	       (plus:DI
+-- 
+2.33.1
+

+ 35 - 0
recipes-devtools/gcc/gcc/0026-RISC-V-bitmanip-fix-constant-loading-for-1ULL-31-in-.patch

@@ -0,0 +1,35 @@
+From 4ecb7207eb15ac1a955cd6333d24bf7eecd33213 Mon Sep 17 00:00:00 2001
+From: "yilun.xie" <yilun.xie@starfivetech.com>
+Date: Tue, 23 Nov 2021 13:55:44 +0800
+Subject: [PATCH 26/26] RISC-V: bitmanip: fix constant-loading for (1ULL << 31)
+ in DImode
+
+---
+ gcc/config/riscv/riscv.h | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
+index ff6729aedac..27ecc4830b2 100644
+--- a/gcc/config/riscv/riscv.h
++++ b/gcc/config/riscv/riscv.h
+@@ -521,13 +521,10 @@ enum reg_class
+   (((VALUE) | ((1UL<<31) - IMM_REACH)) == ((1UL<<31) - IMM_REACH)	\
+    || ((VALUE) | ((1UL<<31) - IMM_REACH)) + IMM_REACH == 0)
+ 
+-/* If this is a single bit mask, then we can load it with bseti.  But this
+-   is not useful for any of the low 31 bits because we can use addi or lui
+-   to load them.  It is wrong for loading SImode 0x80000000 on rv64 because it
+-   needs to be sign-extended.  So we restrict this to the upper 32-bits
+-   only.  */
+-#define SINGLE_BIT_MASK_OPERAND(VALUE) \
+-  (pow2p_hwi (VALUE) && (ctz_hwi (VALUE) >= 32))
++/* If this is a single bit mask, then we can load it with bseti.  Special
++   handling of SImode 0x80000000 on RV64 is done in riscv_build_integer_1. */
++#define SINGLE_BIT_MASK_OPERAND(VALUE)					\
++  (pow2p_hwi (VALUE))
+ 
+ /* Stack layout; function entry, exit and calling.  */
+ 
+-- 
+2.33.1
+