diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index e36f2bc8ed9..66428427dd2 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -3454,7 +3454,8 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN } gcc_fallthrough (); case SIGN_EXTRACT: - if (TARGET_XTHEADBB && outer_code == SET + if ((riscv_is_micro_arch (rhx) || TARGET_XTHEADBB) + && outer_code == SET && CONST_INT_P (XEXP (x, 1)) && CONST_INT_P (XEXP (x, 2))) { @@ -8860,6 +8861,13 @@ arcv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr) || REGNO (SET_DEST (prev_set)) == REGNO (XEXP (SET_SRC (curr_set), 1)))) return true; + /* Fuse logical shift left with logical shift right (bit-extract pattern). */ + if (GET_CODE (SET_SRC (prev_set)) == ASHIFT + && GET_CODE (SET_SRC (curr_set)) == LSHIFTRT + && REGNO (SET_DEST (prev_set)) == REGNO (SET_DEST (curr_set)) + && REGNO (SET_DEST (prev_set)) == REGNO (XEXP (SET_SRC (curr_set), 0))) + return true; + return false; } diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 77a3c823ffd..6f8526aac4a 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -3786,6 +3786,26 @@ [(set_attr "type" "imul")] ) +(define_insn_and_split "*zero_extract_split" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extract:SI (match_operand:SI 1 "register_operand" "r") + (match_operand 2 "const_int_operand") + (match_operand 3 "const_int_operand")))] + "riscv_is_micro_arch (rhx) && !TARGET_64BIT + && (INTVAL (operands[2]) > 1 || !TARGET_ZBS)" + "#" + "&& 1" + [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) + (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 3)))] + "{ + int amount = INTVAL (operands[2]); + int end = INTVAL (operands[3]) + amount; + operands[2] = GEN_INT (BITS_PER_WORD - end); + operands[3] = GEN_INT (BITS_PER_WORD - amount); + }" + [(set_attr "type" "bitmanip")] +) + ;; String compare with length insn. ;; Argument 0 is the target (result) ;; Argument 1 is the source1 diff --git a/gcc/testsuite/gcc.target/riscv/arcv-fusion-xbfu.c b/gcc/testsuite/gcc.target/riscv/arcv-fusion-xbfu.c new file mode 100644 index 00000000000..1224b6facd4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/arcv-fusion-xbfu.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv32 } */ +/* { dg-skip-if "" { *-*-* } { "-g" "-flto" "-O0" "-Oz" "-Os" } } */ +/* { dg-options "-mtune=rhx -march=rv32im_zbs -mabi=ilp32" } */ + +#define bit_extract(x,start,amt) (((x)>>(start)) & (~(0xffffffff << (amt)))) + +int +f (int x) +{ + return bit_extract(x,10,14) + bit_extract(x,1,1); +} + +/* { dg-final { scan-assembler {\sslli\s([ast][0-9]+),a0,8\n\ssrli\s\1,\1,18\n\sbexti\sa0,a0,1\n\sadd\sa0,\1,a0\n} } } */