-;); Machine description for RISC-V Bit Manipulation operations.
+;; Machine description for RISC-V Bit Manipulation operations.
;; Copyright (C) 2021-2025 Free Software Foundation, Inc.
;; This file is part of GCC.
[(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"))]
+(define_peephole2
+ [(match_scratch:X 4 "r")
+ (set (match_operand:X 0 "register_operand")
+ (not:X (match_operand:X 1 "register_operand")))
+ (set (match_operand:X 2 "register_operand")
+ (bitmanip_bitwise:X (match_dup 0)
+ (match_operand 3 "const_int_operand")))
+ (match_dup 4)]
"(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")])
+ && !optimize_function_for_size_p (cfun)
+ && rtx_equal_p (operands[0], operands[2])
+ && riscv_const_insns (operands[3], false) == 1"
+ [(set (match_dup 4) (match_dup 3))
+ (set (match_dup 0) (bitmanip_bitwise:X (not:X (match_dup 1)) (match_dup 4)))])
;; '(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
bool speed_p = optimize_insn_for_speed_p ();
if (exact_log2 (val_a + 1) >= 0
&& (rtx_cost (shift_right, mode, SET, 1, speed_p)
- <= rtx_cost (and_form, mode, SET, 1, speed_p)))
+ < rtx_cost (and_form, mode, SET, 1, speed_p)))
temp = expand_simple_binop (mode, LSHIFTRT, temp,
GEN_INT (rshift_count),
if_info->x, false, OPTAB_WIDEN);
else if (exact_log2 (~val_a + 1) >= 0
&& (rtx_cost (shift_left, mode, SET, 1, speed_p)
- <= rtx_cost (and_form, mode, SET, 1, speed_p)))
+ < rtx_cost (and_form, mode, SET, 1, speed_p)))
temp = expand_simple_binop (mode, ASHIFT, temp,
GEN_INT (ctz_hwi (val_a)),
if_info->x, false, OPTAB_WIDEN);
bool speed_p = optimize_insn_for_speed_p ();
if (exact_log2 (val_b + 1) >= 0
&& (rtx_cost (shift_right, mode, SET, 1, speed_p)
- <= rtx_cost (and_form, mode, SET, 1, speed_p)))
+ < rtx_cost (and_form, mode, SET, 1, speed_p)))
temp = expand_simple_binop (mode, LSHIFTRT, temp,
GEN_INT (rshift_count),
if_info->x, false, OPTAB_WIDEN);
else if (exact_log2 (~val_b + 1) >= 0
&& (rtx_cost (shift_left, mode, SET, 1, speed_p)
- <= rtx_cost (and_form, mode, SET, 1, speed_p)))
+ < rtx_cost (and_form, mode, SET, 1, speed_p)))
temp = expand_simple_binop (mode, ASHIFT, temp,
GEN_INT (ctz_hwi (val_b)),
if_info->x, false, OPTAB_WIDEN);
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gcbv_zicond -mabi=lp64d" { target rv64 } } */
+/* { dg-options "-O2 -march=rv32gcbv_zicond -mabi=ilp32" { target rv32 } } */
+
+
+
+unsigned int test0 (unsigned int x) { return ((x >> 4) ^ 1) & 1; }
+
+unsigned int test1 (unsigned int x) { return ((x >> 4) & 1) ^ 1; }
+
+unsigned int test2 (unsigned int x) { return ~(x >> 4) & 1; }
+
+unsigned int test3 (unsigned int x) { return ((~x >> 4) & 1); }
+
+unsigned int test4 (unsigned int x) { return (x >> 4) & 1; }
+
+int test5 (int vi) { return vi - (((vi >> 6) & 0x01) << 1); }
+
+int test6 (int vi) { return vi - (((vi >> 6) & 0x01) << 1) - 1; }
+
+
+/* { dg-final { scan-assembler-times "\\tbexti" 5 } } */
+/* { dg-final { scan-assembler-times "\\txori" 3 } } */
+/* { dg-final { scan-assembler-times "\\tnot" 1 } } */
+/* { dg-final { scan-assembler-times "\\tsrli" 2 } } */
+/* { dg-final { scan-assembler-times "\\tandi" 2 } } */
+/* { dg-final { scan-assembler-times "\\tsub" 2 } } */
+/* { dg-final { scan-assembler-times "\\taddi" 1 } } */
+
+