@@ -615,37 +615,140 @@ (define_insn "*bsetdi_2"
;; shift constant. With the limited range we know the SImode sign
;; bit is never set, thus we can treat this as zero extending and
;; generate the bsetdi_2 pattern.
-(define_split
- [(set (match_operand:DI 0 "register_operand")
+(define_insn_and_split ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
(any_extend:DI
(ashift:SI (const_int 1)
(subreg:QI
- (and:DI (not:DI (match_operand:DI 1 "register_operand"))
+ (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
(match_operand 2 "const_int_operand")) 0))))
- (clobber (match_operand:DI 3 "register_operand"))]
+ (clobber (match_scratch:X 3 "=&r"))]
"TARGET_64BIT
&& TARGET_ZBS
&& (TARGET_ZBB || TARGET_ZBKB)
&& (INTVAL (operands[2]) & 0x1f) != 0x1f"
- [(set (match_dup 0) (and:DI (not:DI (match_dup 1)) (match_dup 2)))
- (set (match_dup 0) (zero_extend:DI (ashift:SI
- (const_int 1)
- (subreg:QI (match_dup 0) 0))))])
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 3) (match_dup 2))
+ (set (match_dup 3) (and:DI (not:DI (match_dup 1)) (match_dup 3)))
+ (set (match_dup 0) (zero_extend:DI
+ (ashift:SI (const_int 1) (match_dup 4))))]
+ { operands[4] = gen_lowpart (QImode, operands[3]); }
+ [(set_attr "type" "bitmanip")])
-(define_split
- [(set (match_operand:DI 0 "register_operand")
- (any_extend:DI
+(define_insn_and_split ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (any_extend:DI
(ashift:SI (const_int 1)
(subreg:QI
- (and:DI (match_operand:DI 1 "register_operand")
+ (and:DI (match_operand:DI 1 "register_operand" "r")
(match_operand 2 "const_int_operand")) 0))))]
"TARGET_64BIT
&& TARGET_ZBS
&& (INTVAL (operands[2]) & 0x1f) != 0x1f"
- [(set (match_dup 0) (and:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 0) (zero_extend:DI (ashift:SI
- (const_int 1)
- (subreg:QI (match_dup 0) 0))))])
+ "#"
+ "&& 1"
+ [(set (match_dup 0) (and:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (zero_extend:DI (ashift:SI
+ (const_int 1)
+ (subreg:QI (match_dup 0) 0))))]
+ { }
+ [(set_attr "type" "bitmanip")])
+
+;; Similarly two patterns for IOR/XOR generating bset/binv to
+;; manipulate a bit in a register
+(define_insn_and_split ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (any_or:DI
+ (any_extend:DI
+ (ashift:SI
+ (const_int 1)
+ (subreg:QI
+ (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
+ (match_operand 2 "const_int_operand")) 0)))
+ (match_operand:DI 3 "register_operand" "r")))
+ (clobber (match_scratch:X 4 "=&r"))]
+ "TARGET_64BIT
+ && TARGET_ZBS
+ && (TARGET_ZBB || TARGET_ZBKB)
+ && (INTVAL (operands[2]) & 0x1f) != 0x1f"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 4) (match_dup 2))
+ (set (match_dup 4) (and:DI (not:DI (match_dup 4)) (match_dup 1)))
+ (set (match_dup 0) (any_or:DI (ashift:DI (const_int 1) (match_dup 5)) (match_dup 3)))]
+ { operands[5] = gen_lowpart (QImode, operands[4]); }
+ [(set_attr "type" "bitmanip")])
+
+(define_insn_and_split ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (any_or:DI
+ (any_extend:DI
+ (ashift:SI
+ (const_int 1)
+ (subreg:QI
+ (and:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand 2 "const_int_operand")) 0)))
+ (match_operand:DI 3 "register_operand" "r")))
+ (clobber (match_scratch:X 4 "=&r"))]
+ "TARGET_64BIT
+ && TARGET_ZBS
+ && (INTVAL (operands[2]) & 0x1f) != 0x1f"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 4) (and:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (any_or:DI (ashift:DI (const_int 1) (subreg:QI (match_dup 4) 0)) (match_dup 3)))]
+ { }
+ [(set_attr "type" "bitmanip")])
+
+;; Similarly two patterns for AND generating bclr to
+;; manipulate a bit in a register
+(define_insn_and_split ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI
+ (not:DI
+ (any_extend:DI
+ (ashift:SI
+ (const_int 1)
+ (subreg:QI
+ (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
+ (match_operand 2 "const_int_operand")) 0))))
+ (match_operand:DI 3 "register_operand" "r")))
+ (clobber (match_scratch:X 4 "=&r"))]
+ "TARGET_64BIT
+ && TARGET_ZBS
+ && (TARGET_ZBB || TARGET_ZBKB)
+ && (INTVAL (operands[2]) & 0x1f) != 0x1f"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 4) (match_dup 2))
+ (set (match_dup 4) (and:DI (not:DI (match_dup 1)) (match_dup 4)))
+ (set (match_dup 0) (and:DI (rotate:DI (const_int -2) (match_dup 5)) (match_dup 3)))]
+ { operands[5] = gen_lowpart (QImode, operands[4]); }
+ [(set_attr "type" "bitmanip")])
+
+
+(define_insn_and_split ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI
+ (not:DI
+ (any_extend:DI
+ (ashift:SI
+ (const_int 1)
+ (subreg:QI
+ (and:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand 2 "const_int_operand")) 0))))
+ (match_operand:DI 3 "register_operand" "r")))
+ (clobber (match_scratch:X 4 "=&r"))]
+ "TARGET_64BIT
+ && TARGET_ZBS
+ && (INTVAL (operands[2]) & 0x1f) != 0x1f"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 4) (and:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (and:DI (rotate:DI (const_int -2) (match_dup 5)) (match_dup 3)))]
+ { operands[5] = gen_lowpart (QImode, operands[4]); }
+ [(set_attr "type" "bitmanip")])
(define_insn "*bset<mode>_1_mask"
[(set (match_operand:X 0 "register_operand" "=r")
new file mode 100644
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbb_zbs -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+
+typedef unsigned int uint32_t;
+uint32_t foo(uint32_t pos, uint32_t x)
+{
+ return x & ~(1 <<( pos & 0xf));
+}
+
+typedef unsigned int uint32_t;
+uint32_t foo2(uint32_t pos, uint32_t x)
+{
+ return x & ~(1 <<(7-(pos) % 8));
+}
+
+
+
+/* { dg-final { scan-assembler-not "sll\t" } } */
+/* { dg-final { scan-assembler-times "bclr\t" 2 } } */
+/* { dg-final { scan-assembler-times "andi\t" 1 } } */
+/* { dg-final { scan-assembler-times "andn\t" 1 } } */
+/* { dg-final { scan-assembler-times "ret" 2 } } */
+
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbb_zbs -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+
+typedef unsigned int uint32_t;
+uint32_t foo(uint32_t pos, uint32_t x)
+{
+ return x ^ (1 <<( pos & 0xf));
+}
+
+typedef unsigned int uint32_t;
+uint32_t foo2(uint32_t pos, uint32_t x)
+{
+ return x ^ (1 <<(7-(pos) % 8));
+
+}
+
+/* { dg-final { scan-assembler-not "sll\t" } } */
+/* { dg-final { scan-assembler-times "binv\t" 2 } } */
+/* { dg-final { scan-assembler-times "andi\t" 1 } } */
+/* { dg-final { scan-assembler-times "andn\t" 1 } } */
+/* { dg-final { scan-assembler-times "ret" 2 } } */
+
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbb_zbs -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+
+typedef unsigned int uint32_t;
+uint32_t foo(uint32_t pos, uint32_t x)
+{
+ return x | (1 <<( pos & 0xf));
+}
+
+typedef unsigned int uint32_t;
+uint32_t foo2(uint32_t pos, uint32_t x)
+{
+ return x | (1 <<(7-(pos) % 8));
+
+}
+
+/* { dg-final { scan-assembler-not "sll\t" } } */
+/* { dg-final { scan-assembler-times "bset\t" 2 } } */
+/* { dg-final { scan-assembler-times "andi\t" 1 } } */
+/* { dg-final { scan-assembler-times "andn\t" 1 } } */
+/* { dg-final { scan-assembler-times "ret" 2 } } */
+