summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhongjuzhe <juzhe.zhong@rivai.ai>2022-08-27 19:07:56 +0800
committerKito Cheng <kito.cheng@sifive.com>2022-08-29 10:16:06 +0800
commit31380d4b7925912b9c34afe8cdb8dffe6cd50b94 (patch)
treeecd116c6a4a85decbbe5080821878ccc021a35dd
parentb842690086b588349637125c114d5fdcbb79531f (diff)
downloadgcc-31380d4b7925912b9c34afe8cdb8dffe6cd50b94.tar.gz
RISC-V: Add RVV registers
gcc/ChangeLog: * config/riscv/riscv.cc (riscv_v_ext_vector_mode_p): New function. (riscv_classify_address): Disallow PLUS/LO_SUM/CONST_INT address types for RVV. (riscv_address_insns): Add RVV modes condition. (riscv_binary_cost): Ditto. (riscv_rtx_costs): Adjust cost for RVV. (riscv_secondary_memory_needed): Add RVV modes condition. (riscv_hard_regno_nregs): Add RVV register allocation. (riscv_hard_regno_mode_ok): Add RVV register allocation. (riscv_class_max_nregs): Add RVV register allocation. * config/riscv/riscv.h (DWARF_FRAME_REGNUM): Add VL/VTYPE and vector registers in Dwarf. (UNITS_PER_V_REG): New macro. (FIRST_PSEUDO_REGISTER): Adjust first pseudo num for RVV. (V_REG_FIRST): New macro. (V_REG_LAST): Ditto. (V_REG_NUM): Ditto. (V_REG_P): Ditto. (VL_REG_P): Ditto. (VTYPE_REG_P): Ditto. (RISCV_DWARF_VL): Ditto. (RISCV_DWARF_VTYPE): Ditto. (enum reg_class): Add RVV register types. (REG_CLASS_CONTENTS): Add RVV register types. * config/riscv/riscv.md: Add VL/VTYPE register number constants.
-rw-r--r--gcc/config/riscv/riscv.cc100
-rw-r--r--gcc/config/riscv/riscv.h90
-rw-r--r--gcc/config/riscv/riscv.md2
3 files changed, 173 insertions, 19 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 026c69ce40d..6341dc98daa 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -279,7 +279,22 @@ const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = {
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
- FRAME_REGS, FRAME_REGS,
+ FRAME_REGS, FRAME_REGS, VL_REGS, VTYPE_REGS,
+ NO_REGS, NO_REGS, NO_REGS, NO_REGS,
+ NO_REGS, NO_REGS, NO_REGS, NO_REGS,
+ NO_REGS, NO_REGS, NO_REGS, NO_REGS,
+ NO_REGS, NO_REGS, NO_REGS, NO_REGS,
+ NO_REGS, NO_REGS, NO_REGS, NO_REGS,
+ NO_REGS, NO_REGS, NO_REGS, NO_REGS,
+ NO_REGS, NO_REGS, NO_REGS, NO_REGS,
+ VM_REGS, VD_REGS, VD_REGS, VD_REGS,
+ VD_REGS, VD_REGS, VD_REGS, VD_REGS,
+ VD_REGS, VD_REGS, VD_REGS, VD_REGS,
+ VD_REGS, VD_REGS, VD_REGS, VD_REGS,
+ VD_REGS, VD_REGS, VD_REGS, VD_REGS,
+ VD_REGS, VD_REGS, VD_REGS, VD_REGS,
+ VD_REGS, VD_REGS, VD_REGS, VD_REGS,
+ VD_REGS, VD_REGS, VD_REGS, VD_REGS,
};
/* Costs to use when optimizing for rocket. */
@@ -894,6 +909,14 @@ riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, machine_mode mode,
return true;
}
+/* Return true if mode is the RVV mode. */
+
+static bool
+riscv_v_ext_vector_mode_p (machine_mode mode)
+{
+ return VECTOR_MODE_P (mode);
+}
+
/* Return true if X is a valid address for machine mode MODE. If it is,
fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in
effect. */
@@ -912,6 +935,10 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
return riscv_valid_base_register_p (info->reg, mode, strict_p);
case PLUS:
+ /* RVV load/store disallow any offset. */
+ if (riscv_v_ext_vector_mode_p (mode))
+ return false;
+
info->type = ADDRESS_REG;
info->reg = XEXP (x, 0);
info->offset = XEXP (x, 1);
@@ -919,6 +946,10 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
&& riscv_valid_offset_p (info->offset, mode));
case LO_SUM:
+ /* RVV load/store disallow LO_SUM. */
+ if (riscv_v_ext_vector_mode_p (mode))
+ return false;
+
info->type = ADDRESS_LO_SUM;
info->reg = XEXP (x, 0);
info->offset = XEXP (x, 1);
@@ -937,6 +968,10 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
&& riscv_valid_lo_sum_p (info->symbol_type, mode, info->offset));
case CONST_INT:
+ /* RVV load/store disallow CONST_INT. */
+ if (riscv_v_ext_vector_mode_p (mode))
+ return false;
+
/* Small-integer addresses don't occur very often, but they
are legitimate if x0 is a valid base register. */
info->type = ADDRESS_CONST_INT;
@@ -1022,7 +1057,7 @@ riscv_address_insns (rtx x, machine_mode mode, bool might_split_p)
/* BLKmode is used for single unaligned loads and stores and should
not count as a multiword mode. */
- if (mode != BLKmode && might_split_p)
+ if (!riscv_v_ext_vector_mode_p (mode) && mode != BLKmode && might_split_p)
n += (GET_MODE_SIZE (mode).to_constant () + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
if (addr.type == ADDRESS_LO_SUM)
@@ -1759,7 +1794,8 @@ riscv_immediate_operand_p (int code, HOST_WIDE_INT x)
static int
riscv_binary_cost (rtx x, int single_insns, int double_insns)
{
- if (GET_MODE_SIZE (GET_MODE (x)).to_constant () == UNITS_PER_WORD * 2)
+ if (!riscv_v_ext_vector_mode_p (GET_MODE (x))
+ && GET_MODE_SIZE (GET_MODE (x)).to_constant () == UNITS_PER_WORD * 2)
return COSTS_N_INSNS (double_insns);
return COSTS_N_INSNS (single_insns);
}
@@ -1806,6 +1842,14 @@ static bool
riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UNUSED,
int *total, bool speed)
{
+ /* TODO: We set RVV instruction cost as 1 by default.
+ Cost Model need to be well analyzed and supported in the future. */
+ if (riscv_v_ext_vector_mode_p (mode))
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+
bool float_mode_p = FLOAT_MODE_P (mode);
int cost;
@@ -4869,7 +4913,8 @@ static bool
riscv_secondary_memory_needed (machine_mode mode, reg_class_t class1,
reg_class_t class2)
{
- return (GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD
+ return (!riscv_v_ext_vector_mode_p (mode)
+ && GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD
&& (class1 == FP_REGS) != (class2 == FP_REGS));
}
@@ -4891,6 +4936,25 @@ riscv_register_move_cost (machine_mode mode,
static unsigned int
riscv_hard_regno_nregs (unsigned int regno, machine_mode mode)
{
+ if (riscv_v_ext_vector_mode_p (mode))
+ {
+ /* Handle fractional LMUL, it only occupy part of vector register but
+ still need one vector register to hold. */
+ if (maybe_lt (GET_MODE_SIZE (mode), UNITS_PER_V_REG))
+ return 1;
+
+ return exact_div (GET_MODE_SIZE (mode), UNITS_PER_V_REG).to_constant ();
+ }
+
+ /* mode for VL or VTYPE are just a marker, not holding value,
+ so it always consume one register. */
+ if (regno == VTYPE_REGNUM || regno == VL_REGNUM)
+ return 1;
+
+ /* Assume every valid non-vector mode fits in one vector register. */
+ if (V_REG_P (regno))
+ return 1;
+
if (FP_REG_P (regno))
return (GET_MODE_SIZE (mode).to_constant () + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG;
@@ -4907,11 +4971,17 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
if (GP_REG_P (regno))
{
+ if (riscv_v_ext_vector_mode_p (mode))
+ return false;
+
if (!GP_REG_P (regno + nregs - 1))
return false;
}
else if (FP_REG_P (regno))
{
+ if (riscv_v_ext_vector_mode_p (mode))
+ return false;
+
if (!FP_REG_P (regno + nregs - 1))
return false;
@@ -4926,6 +4996,19 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
&& GET_MODE_UNIT_SIZE (mode) > UNITS_PER_FP_ARG))
return false;
}
+ else if (V_REG_P (regno))
+ {
+ if (!riscv_v_ext_vector_mode_p (mode))
+ return false;
+
+ /* 3.3.2. LMUL = 2,4,8, register numbers should be multiple of 2,4,8.
+ but for mask vector register, register numbers can be any number. */
+ int lmul = 1;
+ if (known_gt (GET_MODE_SIZE (mode), UNITS_PER_V_REG))
+ lmul = exact_div (GET_MODE_SIZE (mode), UNITS_PER_V_REG).to_constant ();
+ if (lmul != 1)
+ return ((regno % lmul) == 0);
+ }
else
return false;
@@ -4962,6 +5045,15 @@ riscv_class_max_nregs (reg_class_t rclass, machine_mode mode)
if (reg_class_subset_p (rclass, GR_REGS))
return riscv_hard_regno_nregs (GP_REG_FIRST, mode);
+ if (reg_class_subset_p (rclass, V_REGS))
+ return riscv_hard_regno_nregs (V_REG_FIRST, mode);
+
+ if (reg_class_subset_p (rclass, VL_REGS))
+ return 1;
+
+ if (reg_class_subset_p (rclass, VTYPE_REGS))
+ return 1;
+
return 0;
}
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 5394776eb50..1d8139c2c9b 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -122,8 +122,13 @@ ASM_MISA_SPEC
#define DWARF_CIE_DATA_ALIGNMENT -4
/* The mapping from gcc register number to DWARF 2 CFA column number. */
-#define DWARF_FRAME_REGNUM(REGNO) \
- (GP_REG_P (REGNO) || FP_REG_P (REGNO) ? REGNO : INVALID_REGNUM)
+#define DWARF_FRAME_REGNUM(REGNO) \
+ (VL_REG_P (REGNO) ? RISCV_DWARF_VL \
+ : VTYPE_REG_P (REGNO) \
+ ? RISCV_DWARF_VTYPE \
+ : (GP_REG_P (REGNO) || FP_REG_P (REGNO) || V_REG_P (REGNO) \
+ ? REGNO \
+ : INVALID_REGNUM))
/* The DWARF 2 CFA column which tracks the return address. */
#define DWARF_FRAME_RETURN_COLUMN RETURN_ADDR_REGNUM
@@ -155,6 +160,8 @@ ASM_MISA_SPEC
/* The `Q' extension is not yet supported. */
#define UNITS_PER_FP_REG (TARGET_DOUBLE_FLOAT ? 8 : 4)
+/* Size per vector register. For zve32*, size = poly (4, 4). Otherwise, size = poly (8, 8). */
+#define UNITS_PER_V_REG (riscv_vector_chunks * riscv_bytes_per_vector_chunk)
/* The largest type that can be passed in floating-point registers. */
#define UNITS_PER_FP_ARG \
@@ -289,9 +296,13 @@ ASM_MISA_SPEC
- 32 floating point registers
- 2 fake registers:
- ARG_POINTER_REGNUM
- - FRAME_POINTER_REGNUM */
+ - FRAME_POINTER_REGNUM
+ - 1 vl register
+ - 1 vtype register
+ - 30 unused registers for future expansion
+ - 32 vector registers */
-#define FIRST_PSEUDO_REGISTER 66
+#define FIRST_PSEUDO_REGISTER 128
/* x0, sp, gp, and tp are fixed. */
@@ -303,7 +314,11 @@ ASM_MISA_SPEC
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
/* Others. */ \
- 1, 1 \
+ 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* Vector registers. */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
}
/* a0-a7, t0-t6, fa0-fa7, and ft0-ft11 are volatile across calls.
@@ -317,7 +332,11 @@ ASM_MISA_SPEC
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, \
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \
/* Others. */ \
- 1, 1 \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* Vector registers. */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \
}
/* Select a register mode required for caller save of hard regno REGNO.
@@ -337,6 +356,10 @@ ASM_MISA_SPEC
#define FP_REG_LAST 63
#define FP_REG_NUM (FP_REG_LAST - FP_REG_FIRST + 1)
+#define V_REG_FIRST 96
+#define V_REG_LAST 127
+#define V_REG_NUM (V_REG_LAST - V_REG_FIRST + 1)
+
/* The DWARF 2 CFA column which tracks the return address from a
signal handler context. This means that to maintain backwards
compatibility, no hard register can be assigned this column if it
@@ -347,6 +370,10 @@ ASM_MISA_SPEC
((unsigned int) ((int) (REGNO) - GP_REG_FIRST) < GP_REG_NUM)
#define FP_REG_P(REGNO) \
((unsigned int) ((int) (REGNO) - FP_REG_FIRST) < FP_REG_NUM)
+#define V_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - V_REG_FIRST) < V_REG_NUM)
+#define VL_REG_P(REGNO) ((REGNO) == VL_REGNUM)
+#define VTYPE_REG_P(REGNO) ((REGNO) == VTYPE_REGNUM)
/* True when REGNO is in SIBCALL_REGS set. */
#define SIBCALL_REG_P(REGNO) \
@@ -364,6 +391,10 @@ ASM_MISA_SPEC
#define ARG_POINTER_REGNUM 64
#define FRAME_POINTER_REGNUM 65
+/* Define Dwarf for RVV. */
+#define RISCV_DWARF_VL (4096 + 0xc20)
+#define RISCV_DWARF_VTYPE (4096 + 0xc21)
+
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM (GP_TEMP_FIRST + 2)
@@ -430,6 +461,11 @@ enum reg_class
GR_REGS, /* integer registers */
FP_REGS, /* floating-point registers */
FRAME_REGS, /* arg pointer and frame pointer */
+ VL_REGS, /* vl register */
+ VTYPE_REGS, /* vype register */
+ VM_REGS, /* v0.t registers */
+ VD_REGS, /* vector registers except v0.t */
+ V_REGS, /* vector registers */
ALL_REGS, /* all registers */
LIM_REG_CLASSES /* max value + 1 */
};
@@ -450,6 +486,11 @@ enum reg_class
"GR_REGS", \
"FP_REGS", \
"FRAME_REGS", \
+ "VL_REGS", \
+ "VTYPE_REGS", \
+ "VM_REGS", \
+ "VD_REGS", \
+ "V_REGS", \
"ALL_REGS" \
}
@@ -466,13 +507,18 @@ enum reg_class
#define REG_CLASS_CONTENTS \
{ \
- { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
- { 0xf003fcc0, 0x00000000, 0x00000000 }, /* SIBCALL_REGS */ \
- { 0xffffffc0, 0x00000000, 0x00000000 }, /* JALR_REGS */ \
- { 0xffffffff, 0x00000000, 0x00000000 }, /* GR_REGS */ \
- { 0x00000000, 0xffffffff, 0x00000000 }, /* FP_REGS */ \
- { 0x00000000, 0x00000000, 0x00000003 }, /* FRAME_REGS */ \
- { 0xffffffff, 0xffffffff, 0x00000003 } /* ALL_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
+ { 0xf003fcc0, 0x00000000, 0x00000000, 0x00000000 }, /* SIBCALL_REGS */ \
+ { 0xffffffc0, 0x00000000, 0x00000000, 0x00000000 }, /* JALR_REGS */ \
+ { 0xffffffff, 0x00000000, 0x00000000, 0x00000000 }, /* GR_REGS */ \
+ { 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }, /* FP_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000003, 0x00000000 }, /* FRAME_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000004, 0x00000000 }, /* VL_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000008, 0x00000000 }, /* VTYPE_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000001 }, /* V0_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0xfffffffe }, /* VNoV0_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0xffffffff }, /* V_REGS */ \
+ { 0xffffffff, 0xffffffff, 0x00000003, 0x00000000 } /* ALL_REGS */ \
}
/* A C expression whose value is a register class containing hard
@@ -512,9 +558,16 @@ enum reg_class
60, 61, 62, 63, \
/* Call-saved FPRs. */ \
40, 41, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, \
+ /* V24 ~ V31. */ \
+ 120, 121, 122, 123, 124, 125, 126, 127, \
+ /* V8 ~ V23. */ \
+ 104, 105, 106, 107, 108, 109, 110, 111, \
+ 112, 113, 114, 115, 116, 117, 118, 119, \
+ /* V0 ~ V7. */ \
+ 96, 97, 98, 99, 100, 101, 102, 103, \
/* None of the remaining classes have defined call-saved \
registers. */ \
- 64, 65 \
+ 64, 65, 66, 67 \
}
/* True if VALUE is a signed 12-bit number. */
@@ -783,7 +836,14 @@ typedef struct {
"fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", \
"fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", \
"fs8", "fs9", "fs10","fs11","ft8", "ft9", "ft10","ft11", \
- "arg", "frame", }
+ "arg", "frame", "vl", "vtype", "N/A", "N/A", "N/A", "N/A", \
+ "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", \
+ "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", \
+ "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", \
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", \
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", \
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", \
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",}
#define ADDITIONAL_REGISTER_NAMES \
{ \
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index ee3e7c53b78..63bb3c8debc 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -118,6 +118,8 @@
(NORMAL_RETURN 0)
(SIBCALL_RETURN 1)
(EXCEPTION_RETURN 2)
+ (VL_REGNUM 66)
+ (VTYPE_REGNUM 67)
])
(include "predicates.md")