Skip to content

Commit 5dc1c6e

Browse files
artemiy-volkovMichielDerhaeg
authored andcommitted
arcv: implement bit-extract fusion
The bitfield zero_extract operation is normally expanded into an srai followed by an andi. (With the ZBS extension enabled, the special case of 1-bit zero-extract is implemented with the bexti insn.) However, since the RHX core can execute a shift-left and a shift-right of the same register in 1 cycle, we would prefer to emit those two instructions instead, and schedule them together so that macro fusion can take place. The required steps to achieve this are: (1) Create an insn_and_split that handles the zero_extract RTX; (2) Tell the combiner to use that split by lowering the cost of the zero_extract RTX when the target is the RHX core; (3) Designate the resulting slli + srli pair as fusable by the scheduler. Attached is a small testcase demonstrating the split, and that the bexti insn still takes priority over the shift pair. Signed-off-by: Artemiy Volkov <artemiy@synopsys.com>
1 parent 8bf79f3 commit 5dc1c6e

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

gcc/config/riscv/arcv-rhx100.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
(eq_attr "type" "imul_fused"))
4848
"(arcv_rhx100_issueA_fuse0 + arcv_rhx100_issueA_fuse1 + arcv_rhx100_ALU_A_fuse0_early + arcv_rhx100_ALU_A_fuse1_early + arcv_rhx100_MPY32), nothing*3")
4949

50+
(define_insn_reservation "arcv_rhx100_alu_fused" 1
51+
(and (eq_attr "tune" "arcv_rhx100")
52+
(eq_attr "type" "alu_fused"))
53+
"(arcv_rhx100_issueA_fuse0 + arcv_rhx100_issueA_fuse1 + arcv_rhx100_ALU_A_fuse0_early + arcv_rhx100_ALU_A_fuse1_early) | (arcv_rhx100_issueB_fuse0 + arcv_rhx100_issueB_fuse1 + arcv_rhx100_ALU_B_fuse0_early + arcv_rhx100_ALU_B_fuse1_early)")
54+
5055
(define_insn_reservation "arcv_rhx100_jmp_insn" 1
5156
(and (eq_attr "tune" "arcv_rhx100")
5257
(eq_attr "type" "branch,jump,call,jalr,ret,trap"))

gcc/config/riscv/riscv.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4337,7 +4337,8 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
43374337
}
43384338
gcc_fallthrough ();
43394339
case SIGN_EXTRACT:
4340-
if (TARGET_XTHEADBB && outer_code == SET
4340+
if ((riscv_is_micro_arch (arcv_rhx100) || TARGET_XTHEADBB)
4341+
&& outer_code == SET
43414342
&& CONST_INT_P (XEXP (x, 1))
43424343
&& CONST_INT_P (XEXP (x, 2)))
43434344
{
@@ -11198,6 +11199,13 @@ arcv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
1119811199
|| REGNO (SET_DEST (prev_set)) == REGNO (XEXP (SET_SRC (curr_set), 1))))
1119911200
return true;
1120011201

11202+
/* Fuse logical shift left with logical shift right (bit-extract pattern). */
11203+
if (GET_CODE (SET_SRC (prev_set)) == ASHIFT
11204+
&& GET_CODE (SET_SRC (curr_set)) == LSHIFTRT
11205+
&& REGNO (SET_DEST (prev_set)) == REGNO (SET_DEST (curr_set))
11206+
&& REGNO (SET_DEST (prev_set)) == REGNO (XEXP (SET_SRC (curr_set), 0)))
11207+
return true;
11208+
1120111209
return false;
1120211210
}
1120311211

gcc/config/riscv/riscv.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@
518518
vslideup,vslidedown,vislide1up,vislide1down,vfslide1up,vfslide1down,
519519
vgather,vcompress,vmov,vector,vandn,vbrev,vbrev8,vrev8,vclz,vctz,vcpop,vrol,vror,vwsll,
520520
vclmul,vclmulh,vghsh,vgmul,vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz,
521-
vsha2ms,vsha2ch,vsha2cl,vsm4k,vsm4r,vsm3me,vsm3c,vfncvtbf16,vfwcvtbf16,vfwmaccbf16,imul_fused,
521+
vsha2ms,vsha2ch,vsha2cl,vsm4k,vsm4r,vsm3me,vsm3c,vfncvtbf16,vfwcvtbf16,vfwmaccbf16,imul_fused,alu_fused,
522522
sf_vc,sf_vc_se"
523523
(cond [(eq_attr "got" "load") (const_string "load")
524524

@@ -4564,6 +4564,23 @@
45644564
[(set_attr "type" "imul_fused")]
45654565
)
45664566

4567+
(define_insn "*zero_extract_fused"
4568+
[(set (match_operand:SI 0 "register_operand" "=r")
4569+
(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
4570+
(match_operand 2 "const_int_operand")
4571+
(match_operand 3 "const_int_operand")))]
4572+
"riscv_is_micro_arch (arcv_rhx100) && !TARGET_64BIT
4573+
&& (INTVAL (operands[2]) > 1 || !TARGET_ZBS)"
4574+
{
4575+
int amount = INTVAL (operands[2]);
4576+
int end = INTVAL (operands[3]) + amount;
4577+
operands[2] = GEN_INT (BITS_PER_WORD - end);
4578+
operands[3] = GEN_INT (BITS_PER_WORD - amount);
4579+
return "slli\t%0,%1,%2\n\tsrli\t%0,%0,%3";
4580+
}
4581+
[(set_attr "type" "alu_fused")]
4582+
)
4583+
45674584
;; String compare with length insn.
45684585
;; Argument 0 is the target (result)
45694586
;; Argument 1 is the source1
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* { dg-do compile } */
2+
/* { dg-require-effective-target rv32 } */
3+
/* { dg-skip-if "" { *-*-* } { "-g" "-flto" "-O0" "-Oz" "-Os" } } */
4+
/* { dg-options "-mtune=arc-v-rhx-100-series -march=rv32im_zbs -mabi=ilp32" } */
5+
6+
#define bit_extract(x,start,amt) (((x)>>(start)) & (~(0xffffffff << (amt))))
7+
8+
int
9+
f (int x)
10+
{
11+
return bit_extract(x,10,14) + bit_extract(x,1,1);
12+
}
13+
14+
/* { dg-final { scan-assembler {\sslli\s([ast][0-9]+),a0,8\n\ssrli\s([ast][0-9]+),\1,18\n\sbexti\sa0,a0,1\n\sadd\sa0,\2,a0\n} } } */

0 commit comments

Comments
 (0)