@@ -854,6 +854,18 @@ (define_insn_and_split "*bextseqzdisi"
"operands[1] = gen_lowpart (word_mode, operands[1]);"
[(set_attr "type" "bitmanip")])
+;; The logical-and against 0x1 implicitly extends the result. So we can treat
+;; an SImode bext as-if it's DImode without any explicit extension.
+(define_insn "*bextdisi"
+ [(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"
+ "bext\t%0,%1,%2"
+ [(set_attr "type" "bitmanip")])
+
;; When performing `(a & (1UL << bitno)) ? 0 : -1` the combiner
;; usually has the `bitno` typed as X-mode (i.e. no further
;; zero-extension is performed around the bitno).
new file mode 100644
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbs -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-O1" } } */
+typedef unsigned long uint64_t;
+typedef unsigned int uint32_t;
+
+uint64_t bext1 (int dst, const uint32_t i)
+{
+ uint64_t checks = 1U;
+ checks &= dst >> i;
+ return checks;
+}
+
+int bext2 (int dst, int i_denom)
+{
+ dst = 1 & (dst >> i_denom);
+ return dst;
+}
+
+const uint32_t bext3 (uint32_t bit_count, uint32_t symbol)
+{
+ return (symbol >> bit_count) & 1;
+}
+
+/* { dg-final { scan-assembler-times "bext\t" 3 } } */
+/* { dg-final { scan-assembler-not "sllw\t"} } */
+/* { dg-final { scan-assembler-not "srlw\t"} } */