@@ -314,6 +314,7 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
{"xcvalu", ISA_SPEC_CLASS_NONE, 1, 0},
{"xcvelw", ISA_SPEC_CLASS_NONE, 1, 0},
{"xcvbi", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"xcvmem", ISA_SPEC_CLASS_NONE, 1, 0},
{"xtheadba", ISA_SPEC_CLASS_NONE, 1, 0},
{"xtheadbb", ISA_SPEC_CLASS_NONE, 1, 0},
@@ -1671,6 +1672,7 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
{"xcvalu", &gcc_options::x_riscv_xcv_subext, MASK_XCVALU},
{"xcvelw", &gcc_options::x_riscv_xcv_subext, MASK_XCVELW},
{"xcvbi", &gcc_options::x_riscv_xcv_subext, MASK_XCVBI},
+ {"xcvmem", &gcc_options::x_riscv_xcv_subext, MASK_XCVMEM},
{"xtheadba", &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBA},
{"xtheadbb", &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBB},
@@ -35,6 +35,17 @@
;; General constraints
+(define_memory_constraint "m"
+ "An address that is not base reg + index reg or post modify."
+ (and (match_code "mem")
+ (and (match_test "memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0),
+ MEM_ADDR_SPACE (op))")
+ (not (match_test "((GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == REG)
+ || GET_CODE (XEXP (op, 0)) == POST_MODIFY)
+ && TARGET_XCVMEM")))))
+
(define_constraint "I"
"An I-type 12-bit signed immediate."
(and (match_code "const_int")
@@ -253,3 +264,20 @@
A 5-bit signed immediate for CORE-V Immediate Branch."
(and (match_code "const_int")
(match_test "IN_RANGE (ival, -16, 15)")))
+
+(define_constraint "CV_mem_plus"
+ "@internal
+ An address for reg+reg stores and loads"
+ (and (match_code "mem")
+ (match_test "GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == REG")))
+
+(define_constraint "CV_mem_post"
+ "@internal
+ An address for post-modify or reg+reg stores and loads"
+ (and (match_code "mem")
+ (match_test "(GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == REG)
+ || GET_CODE (XEXP (op, 0)) == POST_MODIFY")))
@@ -720,3 +720,230 @@
"cv.b%C1imm\t%2,%3,%0"
[(set_attr "type" "branch")
(set_attr "mode" "none")])
+
+;;CORE-V Post Increment Load/ Store
+;; Post Increment Register-Immediate and Register-Register Load/Store
+(define_insn "cv_load<mode>_postinc"
+ [(set (match_operand:ANYI 0 "register_operand" "=r")
+ (match_operand:ANYI 1 "mem_post_inc" "CV_mem_post"))]
+ "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
+ "cv.<load>\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_load_<optab><SHORT:mode>_postinc"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (any_extend:SI (match_operand:SHORT 1 "mem_post_inc" "CV_mem_post")))]
+ "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
+ "cv.<load><u>\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_loadsf_postinc_hardfloat"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (match_operand:SF 1 "mem_post_inc" "CV_mem_post"))]
+ "TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))"
+ "cv.lw\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SF")])
+
+(define_insn "cv_loadsf_postinc_softfloat"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (match_operand:SF 1 "mem_post_inc" "CV_mem_post"))]
+ "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))"
+ "cv.lw\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SF")])
+
+(define_insn "cv_loadhf_postinc_hardfloat"
+ [(set (match_operand:HF 0 "register_operand" "=r")
+ (match_operand:HF 1 "mem_post_inc" "CV_mem_post"))]
+ "TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], HFmode)
+ || reg_or_0_operand (operands[1], HFmode))"
+ "cv.lh\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "HF")])
+
+(define_insn "cv_loadhf_postinc_softfloat"
+ [(set (match_operand:HF 0 "register_operand" "=r")
+ (match_operand:HF 1 "mem_post_inc" "CV_mem_post"))]
+ "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], HFmode)
+ || reg_or_0_operand (operands[1], HFmode))"
+ "cv.lh\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "HF")])
+
+(define_insn "cv_store<mode>_postinc"
+ [(set (match_operand:ANYI 0 "mem_post_inc" "=CV_mem_post")
+ (match_operand:ANYI 1 "register_operand" "r"))]
+ "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))"
+ "cv.<store>\t%1,%0"
+ [(set_attr "type" "store")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_storesf_postinc_hardfloat"
+ [(set (match_operand:SF 0 "mem_post_inc" "=CV_mem_post")
+ (match_operand:SF 1 "register_operand" "r"))]
+ "TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))"
+ "cv.sw\t%1,%0"
+ [(set_attr "type" "store")
+ (set_attr "mode" "SF")])
+
+(define_insn "cv_storesf_postinc_softfloat"
+ [(set (match_operand:SF 0 "mem_post_inc" "=CV_mem_post")
+ (match_operand:SF 1 "register_operand" "r"))]
+ "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))"
+ "cv.sw\t%1,%0"
+ [(set_attr "type" "store")
+ (set_attr "mode" "SF")])
+
+(define_insn "cv_storehf_postinc_hardfloat"
+ [(set (match_operand:HF 0 "mem_post_inc" "=CV_mem_post")
+ (match_operand:HF 1 "register_operand" "r"))]
+ "TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], HFmode)
+ || reg_or_0_operand (operands[1], HFmode))"
+ "cv.sh\t%1,%0"
+ [(set_attr "type" "store")
+ (set_attr "mode" "HF")])
+
+(define_insn "cv_storehf_postinc_softfloat"
+ [(set (match_operand:HF 0 "mem_post_inc" "=CV_mem_post")
+ (match_operand:HF 1 "register_operand" "r"))]
+ "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], HFmode)
+ || reg_or_0_operand (operands[1], HFmode))"
+ "cv.sh\t%1,%0"
+ [(set_attr "type" "store")
+ (set_attr "mode" "HF")])
+
+;; Normal Register-Register Load/Store
+(define_insn "cv_load<mode>"
+ [(set (match_operand:ANYI 0 "register_operand" "=r")
+ (match_operand:ANYI 1 "mem_plus_reg" "CV_mem_plus"))]
+ "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
+ "cv.<load>\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_load_<optab><SHORT:mode>"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (any_extend:SI (match_operand:SHORT 1 "mem_plus_reg" "CV_mem_plus")))]
+ "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
+ "cv.<load><u>\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_loadsf_hardfloat"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (match_operand:SF 1 "mem_plus_reg" "CV_mem_plus"))]
+ "TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))"
+ "cv.lw\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SF")])
+
+(define_insn "cv_loadsf_softfloat"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (match_operand:SF 1 "mem_plus_reg" "CV_mem_plus"))]
+ "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))"
+ "cv.lw\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SF")])
+
+(define_insn "cv_loadhf_hardfloat"
+ [(set (match_operand:HF 0 "register_operand" "=r")
+ (match_operand:HF 1 "mem_plus_reg" "CV_mem_plus"))]
+ "TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], HFmode)
+ || reg_or_0_operand (operands[1], HFmode))"
+ "cv.lh\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "HF")])
+
+(define_insn "cv_loadhf_softfloat"
+ [(set (match_operand:HF 0 "register_operand" "=r")
+ (match_operand:HF 1 "mem_plus_reg" "CV_mem_plus"))]
+ "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], HFmode)
+ || reg_or_0_operand (operands[1], HFmode))"
+ "cv.lh\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "HF")])
+
+(define_insn "cv_store<mode>"
+ [(set (match_operand:ANYI 0 "mem_plus_reg" "=CV_mem_plus")
+ (match_operand:ANYI 1 "register_operand" "r"))]
+ "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))"
+ "cv.<store>\t%1,%0"
+ [(set_attr "type" "store")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_storesf_hardfloat"
+ [(set (match_operand:SF 0 "mem_plus_reg" "=CV_mem_plus")
+ (match_operand:SF 1 "register_operand" " r"))]
+ "TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))"
+ "cv.sw\t%1,%0"
+ [(set_attr "move_type" "store")
+ (set_attr "mode" "SF")])
+
+(define_insn "cv_storesf_softfloat"
+ [(set (match_operand:SF 0 "mem_plus_reg" "=CV_mem_plus")
+ (match_operand:SF 1 "register_operand" " r"))]
+ "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))"
+ "cv.sw\t%1,%0"
+ [(set_attr "move_type" "store")
+ (set_attr "mode" "SF")])
+
+(define_insn "cv_storehf_hardfloat"
+ [(set (match_operand:HF 0 "mem_plus_reg" "=CV_mem_plus")
+ (match_operand:HF 1 "register_operand" " r"))]
+ "TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], HFmode)
+ || reg_or_0_operand (operands[1], HFmode))"
+ "cv.sh\t%1,%0"
+ [(set_attr "move_type" "store")
+ (set_attr "mode" "HF")])
+
+(define_insn "cv_storehf_softfloat"
+ [(set (match_operand:HF 0 "mem_plus_reg" "=CV_mem_plus")
+ (match_operand:HF 1 "register_operand" " r"))]
+ "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+ && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+ && (register_operand (operands[0], HFmode)
+ || reg_or_0_operand (operands[1], HFmode))"
+ "cv.sh\t%1,%0"
+ [(set_attr "move_type" "store")
+ (set_attr "mode" "HF")])
@@ -234,8 +234,22 @@
return false;
})
+(define_predicate "mem_post_inc"
+ (and (match_code "mem")
+ (match_test "TARGET_XCVMEM && GET_CODE (XEXP (op, 0)) == POST_MODIFY
+ && GET_MODE_SIZE (GET_MODE (op)).to_constant () <= 4")))
+
+(define_predicate "mem_plus_reg"
+ (and (match_code "mem")
+ (match_test "TARGET_XCVMEM && GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_MODE_SIZE (GET_MODE (op)).to_constant () <= 4
+ && REG_P (XEXP (XEXP (op, 0), 1))
+ && REG_P (XEXP (XEXP (op, 0), 0))")))
+
(define_predicate "move_operand"
- (match_operand 0 "general_operand")
+ (and (match_operand 0 "general_operand")
+ (and (not (match_operand 0 "mem_post_inc"))
+ (not (match_operand 0 "mem_plus_reg"))))
{
enum riscv_symbol_type symbol_type;
@@ -404,6 +418,10 @@
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), -16, 15)")))
+(define_predicate "nonimmediate_nonpostinc"
+ (and (match_operand 0 "nonimmediate_operand")
+ (not (match_operand 0 "mem_post_inc"))))
+
;; Predicates for the V extension.
(define_special_predicate "vector_length_operand"
(ior (match_operand 0 "pmode_register_operand")
@@ -68,7 +68,8 @@ enum riscv_address_type {
ADDRESS_REG_WB,
ADDRESS_LO_SUM,
ADDRESS_CONST_INT,
- ADDRESS_SYMBOLIC
+ ADDRESS_SYMBOLIC,
+ ADDRESS_REG_INC
};
/* Information about an address described by riscv_address_type.
@@ -91,7 +92,13 @@ enum riscv_address_type {
is the type of symbol it references.
ADDRESS_SYMBOLIC
- SYMBOL_TYPE is the type of symbol that the address references. */
+ SYMBOL_TYPE is the type of symbol that the address references.
+
+ ADDRESS_REG_INC:
+ A base register + offset address access with post modify side-effect
+ (base register += offset). The offset is an immediate or index
+ register.
+ */
struct riscv_address_info {
enum riscv_address_type type;
rtx reg;
@@ -101,6 +108,7 @@ struct riscv_address_info {
};
/* Routines implemented in riscv.cc. */
+bool riscv_legitimate_xcvmem_address_p (machine_mode, rtx, bool);
extern enum riscv_symbol_type riscv_classify_symbolic_expression (rtx);
extern bool riscv_symbolic_constant_p (rtx, enum riscv_symbol_type *);
extern int riscv_float_const_rtx_index_for_fli (rtx);
@@ -1084,7 +1084,7 @@ riscv_regno_mode_ok_for_base_p (int regno,
enum reg_class
riscv_index_reg_class ()
{
- if (TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX)
+ if (TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX || TARGET_XCVMEM)
return GR_REGS;
return NO_REGS;
@@ -1360,6 +1360,16 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
info->offset = const0_rtx;
return riscv_valid_base_register_p (info->reg, mode, strict_p);
+ case POST_MODIFY:
+ /* For instructions using post inc, the offset can either be register
+ * or 12-bit immediate. */
+ info->type = ADDRESS_REG_INC;
+ info->reg = XEXP (x, 0);
+ info->offset = XEXP ((XEXP (x, 1)), 1);
+ return (riscv_valid_base_register_p (info->reg, mode, strict_p)
+ && (riscv_valid_base_register_p (info->offset, mode, strict_p)
+ || riscv_valid_offset_p (info->offset, mode)));
+
case PLUS:
/* RVV load/store disallow any offset. */
if (riscv_v_ext_mode_p (mode))
@@ -1369,7 +1379,8 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
info->reg = XEXP (x, 0);
info->offset = XEXP (x, 1);
return (riscv_valid_base_register_p (info->reg, mode, strict_p)
- && riscv_valid_offset_p (info->offset, mode));
+ && (riscv_valid_offset_p (info->offset, mode)
+ || (TARGET_XCVMEM && riscv_valid_base_register_p (info->offset, mode, strict_p))));
case LO_SUM:
/* RVV load/store disallow LO_SUM. */
@@ -2485,6 +2496,30 @@ riscv_v_adjust_scalable_frame (rtx target, poly_int64 offset, bool epilogue)
REG_NOTES (insn) = dwarf;
}
+/* Check if post inc instructions are valid. If not, make the address
+ * vaild. */
+bool
+riscv_legitimate_xcvmem_address_p (machine_mode mode, rtx x, bool strict_p)
+{
+ struct riscv_address_info addr;
+
+ switch (GET_CODE (x))
+ {
+ case POST_MODIFY:
+ if (riscv_classify_address (&addr, x, mode, strict_p))
+ return addr.type == ADDRESS_REG_INC;
+ return false;
+
+ case PLUS:
+ if (REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)) && riscv_classify_address (&addr, x, mode, strict_p))
+ return addr.type == ADDRESS_REG;
+ return false;
+
+ default:
+ return false;
+ }
+}
+
/* If (set DEST SRC) is not a valid move instruction, emit an equivalent
sequence that is valid. */
@@ -5601,7 +5636,8 @@ riscv_print_operand_address (FILE *file, machine_mode mode ATTRIBUTE_UNUSED, rtx
switch (addr.type)
{
case ADDRESS_REG:
- output_addr_const (file, riscv_strip_unspec_address (addr.offset));
+ if (REG_P (addr.offset)) fprintf (file, "%s", reg_names[REGNO (addr.offset)]);
+ else output_addr_const (file, riscv_strip_unspec_address (addr.offset));
fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]);
return;
@@ -5619,6 +5655,12 @@ riscv_print_operand_address (FILE *file, machine_mode mode ATTRIBUTE_UNUSED, rtx
output_addr_const (file, riscv_strip_unspec_address (x));
return;
+ case ADDRESS_REG_INC:
+ fprintf (file, "(%s),", reg_names[REGNO (addr.reg)]);
+ if (REG_P (addr.offset)) fprintf (file, "%s", reg_names[REGNO (addr.offset)]);
+ else output_addr_const (file, addr.offset);
+ return;
+
default:
gcc_unreachable ();
}
@@ -44,6 +44,8 @@ along with GCC; see the file COPYING3. If not see
#define RISCV_TUNE_STRING_DEFAULT "rocket"
#endif
+#define TARGET_MEM_CONSTRAINT 'w'
+
extern const char *riscv_expand_arch (int argc, const char **argv);
extern const char *riscv_expand_arch_from_cpu (int argc, const char **argv);
extern const char *riscv_default_mtune (int argc, const char **argv);
@@ -1197,7 +1199,9 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
e.g. RVVMF64BI vs RVVMF1BI on zvl512b, which is [1, 1] vs [64, 64]. */
#define MAX_POLY_VARIANT 64
-#define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
+#define HAVE_POST_MODIFY_DISP (TARGET_XTHEADMEMIDX || TARGET_XCVMEM)
#define HAVE_PRE_MODIFY_DISP TARGET_XTHEADMEMIDX
+#define HAVE_POST_MODIFY_REG TARGET_XCVMEM
+
#endif /* ! GCC_RISCV_H */
@@ -1663,13 +1663,13 @@
(define_expand "zero_extendsidi2"
[(set (match_operand:DI 0 "register_operand")
- (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_nonpostinc")))]
"TARGET_64BIT")
(define_insn_and_split "*zero_extendsidi2_internal"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(zero_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+ (match_operand:SI 1 "nonimmediate_nonpostinc" " r,m")))]
"TARGET_64BIT && !TARGET_ZBA && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX
&& !(register_operand (operands[1], SImode)
&& reg_or_subregno (operands[1]) == VL_REGNUM)"
@@ -1691,13 +1691,13 @@
(define_expand "zero_extendhi<GPR:mode>2"
[(set (match_operand:GPR 0 "register_operand")
(zero_extend:GPR
- (match_operand:HI 1 "nonimmediate_operand")))]
+ (match_operand:HI 1 "nonimmediate_nonpostinc")))]
"")
(define_insn_and_split "*zero_extendhi<GPR:mode>2"
[(set (match_operand:GPR 0 "register_operand" "=r,r")
(zero_extend:GPR
- (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
+ (match_operand:HI 1 "nonimmediate_nonpostinc" " r,m")))]
"!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
"@
#
@@ -1720,13 +1720,13 @@
(define_expand "zero_extendqi<SUPERQI:mode>2"
[(set (match_operand:SUPERQI 0 "register_operand")
(zero_extend:SUPERQI
- (match_operand:QI 1 "nonimmediate_operand")))]
+ (match_operand:QI 1 "nonimmediate_nonpostinc")))]
"")
(define_insn "*zero_extendqi<SUPERQI:mode>2_internal"
[(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
(zero_extend:SUPERQI
- (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
+ (match_operand:QI 1 "nonimmediate_nonpostinc" " r,m")))]
"!TARGET_XTHEADMEMIDX"
"@
andi\t%0,%1,0xff
@@ -1745,13 +1745,13 @@
(define_expand "extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(sign_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+ (match_operand:SI 1 "nonimmediate_nonpostinc" " r,m")))]
"TARGET_64BIT")
(define_insn "*extendsidi2_internal"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(sign_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+ (match_operand:SI 1 "nonimmediate_nonpostinc" " r,m")))]
"TARGET_64BIT && !TARGET_XTHEADMEMIDX"
"@
sext.w\t%0,%1
@@ -1762,13 +1762,13 @@
(define_expand "extend<SHORT:mode><SUPERQI:mode>2"
[(set (match_operand:SUPERQI 0 "register_operand")
- (sign_extend:SUPERQI (match_operand:SHORT 1 "nonimmediate_operand")))]
+ (sign_extend:SUPERQI (match_operand:SHORT 1 "nonimmediate_nonpostinc")))]
"")
(define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
[(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
(sign_extend:SUPERQI
- (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
+ (match_operand:SHORT 1 "nonimmediate_nonpostinc" " r,m")))]
"!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
"@
#
@@ -1827,7 +1827,7 @@
})
(define_insn "*movhf_hardfloat"
- [(set (match_operand:HF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
+ [(set (match_operand:HF 0 "nonimmediate_nonpostinc" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
(match_operand:HF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))]
"TARGET_ZFHMIN
&& (register_operand (operands[0], HFmode)
@@ -1838,7 +1838,7 @@
(set_attr "mode" "HF")])
(define_insn "*movhf_softfloat"
- [(set (match_operand:HF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
+ [(set (match_operand:HF 0 "nonimmediate_nonpostinc" "=f, r,r,m,*f,*r")
(match_operand:HF 1 "move_operand" " f,Gr,m,r,*r,*f"))]
"!TARGET_ZFHMIN
&& (register_operand (operands[0], HFmode)
@@ -2062,7 +2062,7 @@
})
(define_insn "*movdi_32bit"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m,r")
+ [(set (match_operand:DI 0 "nonimmediate_nonpostinc" "=r,r,r,m, *f,*f,*r,*f,*m,r")
(match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f,vp"))]
"!TARGET_64BIT
&& (register_operand (operands[0], DImode)
@@ -2074,7 +2074,7 @@
(set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")])
(define_insn "*movdi_64bit"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m,r")
+ [(set (match_operand:DI 0 "nonimmediate_nonpostinc" "=r,r,r, m, *f,*f,*r,*f,*m,r")
(match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f,vp"))]
"TARGET_64BIT
&& (register_operand (operands[0], DImode)
@@ -2097,7 +2097,7 @@
})
(define_insn "*movsi_internal"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m,r")
+ [(set (match_operand:SI 0 "nonimmediate_nonpostinc" "=r,r,r, m, *f,*f,*r,*m,r")
(match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,vp"))]
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))
@@ -2126,7 +2126,7 @@
})
(define_insn "*movhi_internal"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r,r")
+ [(set (match_operand:HI 0 "nonimmediate_nonpostinc" "=r,r,r, m, *f,*r,r")
(match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f,vp"))]
"(register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))"
@@ -2170,7 +2170,7 @@
})
(define_insn "*movqi_internal"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r,r")
+ [(set (match_operand:QI 0 "nonimmediate_nonpostinc" "=r,r,r, m, *f,*r,r")
(match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f,vp"))]
"(register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))"
@@ -2192,7 +2192,7 @@
})
(define_insn "*movsf_hardfloat"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
+ [(set (match_operand:SF 0 "nonimmediate_nonpostinc" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
(match_operand:SF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))]
"TARGET_HARD_FLOAT
&& (register_operand (operands[0], SFmode)
@@ -2203,7 +2203,7 @@
(set_attr "mode" "SF")])
(define_insn "*movsf_softfloat"
- [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
+ [(set (match_operand:SF 0 "nonimmediate_nonpostinc" "= r,r,m")
(match_operand:SF 1 "move_operand" " Gr,m,r"))]
"!TARGET_HARD_FLOAT
&& (register_operand (operands[0], SFmode)
@@ -2228,7 +2228,7 @@
;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
;; (However, we can still use fcvt.d.w to zero a floating-point register.)
(define_insn "*movdf_hardfloat_rv32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*zmvf,*zmvr, *r,*r,*m")
+ [(set (match_operand:DF 0 "nonimmediate_nonpostinc" "=f, f,f,f,m,m,*zmvf,*zmvr, *r,*r,*m")
(match_operand:DF 1 "move_operand" " f,zfli,G,m,f,G,*zmvr,*zmvf,*r*G,*m,*r"))]
"!TARGET_64BIT && TARGET_DOUBLE_FLOAT
&& (register_operand (operands[0], DFmode)
@@ -2239,7 +2239,7 @@
(set_attr "mode" "DF")])
(define_insn "*movdf_hardfloat_rv64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
+ [(set (match_operand:DF 0 "nonimmediate_nonpostinc" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
(match_operand:DF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*r*G,*m,*r"))]
"TARGET_64BIT && TARGET_DOUBLE_FLOAT
&& (register_operand (operands[0], DFmode)
@@ -2250,7 +2250,7 @@
(set_attr "mode" "DF")])
(define_insn "*movdf_softfloat"
- [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
+ [(set (match_operand:DF 0 "nonimmediate_nonpostinc" "= r,r, m")
(match_operand:DF 1 "move_operand" " rG,m,rG"))]
"!TARGET_DOUBLE_FLOAT
&& (register_operand (operands[0], DFmode)
@@ -2297,7 +2297,7 @@
(set_attr "mode" "DF")])
(define_split
- [(set (match_operand:MOVE64 0 "nonimmediate_operand")
+ [(set (match_operand:MOVE64 0 "nonimmediate_nonpostinc")
(match_operand:MOVE64 1 "move_operand"))]
"reload_completed
&& riscv_split_64bit_move_p (operands[0], operands[1])"
@@ -415,6 +415,8 @@ Mask(XCVELW) Var(riscv_xcv_subext)
Mask(XCVBI) Var(riscv_xcv_subext)
+Mask(XCVMEM) Var(riscv_xcv_subext)
+
TargetVariable
int riscv_xthead_subext
@@ -2487,6 +2487,9 @@ Test system has support for the CORE-V ELW extension.
@item cv_bi
Test system has support for the CORE-V BI extension.
+@item cv_mem
+Test system has support for the CORE-V MEM extension.
+
@end table
@subsubsection Other hardware attributes
new file mode 100644
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate loads.
+ */
+
+int
+fooQIsigned (signed char* array_char, int n)
+{
+ int char_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ char_sum += array_char[i];
+ }
+
+ return char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),1" 1 } } */
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register loads.
+ */
+
+int
+fooQIsigned (signed char* array_char, int n, int j)
+{
+ int char_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ char_sum += *array_char;
+ array_char+=j*sizeof(array_char);
+ }
+
+ return char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register loads.
+ */
+
+int
+fooQIsigned (signed char* array_char, int i, int j)
+{
+ return array_char[i+j];
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 1 } } */
new file mode 100644
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate loads.
+ */
+
+int
+fooQIunsigned (unsigned char* array_uchar, int n)
+{
+ int uns_char_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ uns_char_sum += array_uchar[i];
+ }
+
+ return uns_char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lbu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),1" 1 } } */
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register loads.
+ */
+
+int
+fooQIunsigned (unsigned char* array_uchar, int n, int j)
+{
+ int uns_char_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ uns_char_sum += *array_uchar;
+ array_uchar+=j*sizeof(array_uchar);
+ }
+
+ return uns_char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lbu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register loads.
+ */
+
+int
+fooQIunsigned (unsigned char* array_uchar, int i, int j)
+{
+ return array_uchar[i+j];
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lbu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 1 } } */
new file mode 100644
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate loads.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int n)
+{
+ int short_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ short_sum += array_short[i];
+ }
+
+ return short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),2" 1 } } */
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register loads.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int n, int j)
+{
+ int short_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ short_sum += *array_short;
+ array_short+=j*sizeof(array_short);
+ }
+
+ return short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register loads.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int i, int j)
+{
+ return array_short[i+j];
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 1 } } */
new file mode 100644
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate loads.
+ */
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int n)
+{
+ int uns_short_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ uns_short_sum += array_ushort[i];
+ }
+
+ return uns_short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lhu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),2" 1 } } */
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register loads.
+ */
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int n, int j)
+{
+ int uns_short_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ uns_short_sum += *array_ushort;
+ array_ushort+=j*sizeof(array_ushort);
+ }
+
+ return uns_short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lhu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register loads.
+ */
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int i, int j)
+{
+ return array_ushort[i+j];
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lhu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 1 } } */
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* We don't generate for some optimization levels. TODO: should support for Os,
+ Oz and Og */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } { "" } } */
+
+/*
+ * Test for post-inc register-immediate loads.
+ */
+
+int
+fooSIsigned (signed int* array_int, int n)
+{
+ int int_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ int_sum += array_int[i];
+ }
+
+ return int_sum;
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int n)
+{
+ int uns_int_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ uns_int_sum += array_uint[i];
+ }
+
+ return uns_int_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),4" 2 } } */
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register loads.
+ */
+
+int
+fooSIsigned (signed int* array_int, int n, int j)
+{
+ int int_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ int_sum += *array_int;
+ array_int+=j*sizeof(array_int);
+ }
+
+ return int_sum;
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int n, int j)
+{
+ int uns_int_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ uns_int_sum += *array_uint;
+ array_uint+=j*sizeof(array_uint);
+ }
+
+ return uns_int_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 2 } } */
new file mode 100644
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register loads.
+ */
+
+int
+fooSIsigned (signed int* array_int, int i, int j)
+{
+ return array_int[i+j];
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int i, int j)
+{
+ return array_uint[i+j];
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 2 } } */
new file mode 100644
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -g -O2" } */
+
+/*
+ * Test for illegal XCVmem specific operand.
+ * Pattern: `(mem:DF (plus:SI (reg reg)))`.
+ */
+
+struct {
+ double a[3];
+} * b;
+int c;
+
+int
+foo (void)
+{
+ b[0].a[c] -= b[0].a[c];
+}
new file mode 100644
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -g -O2" } */
+
+/*
+ * Test for illegal XCVmem specific operand.
+ * Pattern: `(mem:DF (post_modify:SI (reg reg)))`.
+ */
+
+int bar (double);
+
+int
+foo (void)
+{
+ double *b;
+ int c = 0;
+ for (;; c++)
+ bar (b[c]);
+}
+
new file mode 100644
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -g -O2 -Wno-int-conversion" } */
+
+/*
+ * Test for illegal XCVmem specific operand in loads.
+ * Instruction `lbu reg,reg(reg)`.
+ */
+
+int a;
+int bar (char);
+
+int
+foo (void)
+{
+ short *d;
+ char *e = (char *)foo;
+ for (;;) {
+ char c = d++;
+ bar (c);
+ short b = e[0] + b;
+ if (b)
+ a = 5;
+ e += 2;
+ }
+}
+
+/* { dg-final { scan-assembler-not "lbu\t\[a-z\]\[0-99\],\[a-z\]\[0-99\]\\(\[a-z\]\[0-99\]\\)" } } */
new file mode 100644
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32if_xcvmem" } */
+
+/*
+ * Test for illegal XCVmem specific operand in flw.
+ * Error: illegal operands `flw fa5,a5(a4)'
+ */
+
+int b, e;
+float *m;
+
+int
+foo (void) {
+ m[1] = m[b];
+ m[b] = e;
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "flw\tfa5,a5\\(a4\\)" } } */
new file mode 100644
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32" } */
+
+/*
+ * Tests that stores can generate regular reg:imm operands.
+ */
+
+int a[1];
+int b, c, d, e, f;
+float g;
+
+int
+foo (void)
+{
+ int h;
+ for (;; d++)
+ switch (c) {
+ case 8:
+ g = e == f;
+ a[h + d] = g;
+ g = e < f;
+ b = g;
+ }
+}
new file mode 100644
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+
+/*
+ * Test for illegal XCVmem specific operands in lw.
+ */
+
+int
+fooSIsigned (signed int* array_int)
+{
+ return array_int [3];
+}
+
+int
+fooSIunsigned (unsigned int* array_uint)
+{
+ return array_uint [3];
+}
+
+/* { dg-final { scan-assembler-not "cv\\.lw\t" } } */
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+/*
+ * Test for illegal XCVmem specific operands in register-immediate sw.
+ */
+
+int
+fooSIsigned (signed int* array_int, int i)
+{
+ array_int [3] = i;
+ return array_int [3];
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int i)
+{
+ array_uint [3] = i;
+ return array_uint [3];
+}
+
+/* { dg-final { scan-assembler-not "cv\\.sw\t" } } */
new file mode 100644
@@ -0,0 +1,18 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem" } */
+
+/*
+ * Test for illegal XCVmem specific operand in sw.
+ */
+
+int a;
+float *b;
+
+int
+foo (void)
+{
+ int c;
+ for (c = 0; c < 10; c++)
+ b[c] = a;
+}
new file mode 100644
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops -fno-tree-vectorize" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate saves.
+ */
+
+int
+fooQIsigned (signed char* array_char, int n)
+{
+ int char_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ array_char[i] += char_sum;
+ }
+
+ return char_sum;
+}
+
+int
+fooQIunsigned (unsigned char* array_uchar, int n)
+{
+ int uns_char_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ array_uchar[i] += uns_char_sum;
+ }
+
+ return uns_char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),1" 2 } } */
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops -fno-tree-vectorize" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register saves.
+ */
+
+int
+fooQIsigned (signed char* array_char, int n, int j)
+{
+ int char_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ *array_char += char_sum;
+ array_char+=j*sizeof(array_char);
+ }
+
+ return char_sum;
+}
+
+int
+fooQIunsigned (unsigned char* array_uchar, int n, int j)
+{
+ int uns_char_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ *array_uchar += uns_char_sum;
+ array_uchar+=j*sizeof(array_uchar);
+ }
+
+ return uns_char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 2 } } */
new file mode 100644
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops -fno-tree-vectorize" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register saves.
+ */
+
+int
+fooQIsigned (signed char* array_char, int i, int j)
+{
+ int char_sum = 1;
+
+ array_char[i+j] += char_sum;
+
+ return char_sum;
+}
+
+int
+fooQIunsigned (unsigned char* array_uchar, int i, int j)
+{
+ int uns_char_sum = 1;
+
+ array_uchar[i+j] += uns_char_sum;
+
+ return uns_char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 2 } } */
new file mode 100644
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate saves.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int n)
+{
+ int short_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ array_short[i] += short_sum;
+ }
+
+ return short_sum;
+}
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int n)
+{
+ int uns_short_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ array_ushort[i] += uns_short_sum;
+ }
+
+ return uns_short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),2" 2 } } */
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register saves.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int n, int j)
+{
+ int short_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ *array_short += short_sum;
+ array_short+=j*sizeof(array_short);
+ }
+
+ return short_sum;
+}
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int n, int j)
+{
+ int uns_short_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ *array_ushort += uns_short_sum;
+ array_ushort+=j*sizeof(array_ushort);
+ }
+
+ return uns_short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 2 } } */
new file mode 100644
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register saves.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int i, int j)
+{
+ int short_sum = 1;
+
+ array_short[i+j] = short_sum;
+
+ return short_sum;
+}
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int i, int j)
+{
+ int uns_short_sum = 1;
+
+ array_ushort[i+j] += uns_short_sum;
+
+ return uns_short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 2 } } */
new file mode 100644
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate saves.
+ */
+
+int
+fooSIsigned (signed int* array_int, int n)
+{
+ int int_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ array_int[i] += int_sum;
+ }
+
+ return int_sum;
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int n)
+{
+ int uns_int_sum = 1;
+
+ for(int i=0; i<n; i++)
+ {
+ array_uint[i] += uns_int_sum;
+ }
+
+ return uns_int_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),4" 2 } } */
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register saves.
+ */
+
+int
+fooSIsigned (signed int* array_int, int n, int j)
+{
+ int int_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ *array_int += int_sum;
+ array_int+=j*sizeof(array_int);
+ }
+
+ return int_sum;
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int n, int j)
+{
+ int uns_int_sum = 1;
+
+ for(int i=0; i<n; i+=j)
+ {
+ *array_uint += uns_int_sum;
+ array_uint+=j*sizeof(array_uint);
+ }
+
+ return uns_int_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 2 } } */
new file mode 100644
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register saves.
+ */
+
+int
+fooSIsigned (signed int* array_int, int i, int j)
+{
+ int int_sum = 1;
+
+ array_int[i+j] = int_sum;
+
+ return int_sum;
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int i, int j)
+{
+ int uns_int_sum = 1;
+
+ array_uint[i+j] = uns_int_sum;
+
+ return uns_int_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 2 } } */
@@ -13111,6 +13111,20 @@ proc check_effective_target_cv_bi { } {
} "-march=rv32i_xcvbi" ]
}
+# Return 1 if the CORE-V MEM extension is available.
+proc check_effective_target_cv_mem { } {
+ if { !([istarget riscv*-*-*]) } {
+ return 0
+ }
+ return [check_no_compiler_messages cv_mem object {
+ void foo (void)
+ {
+ asm ("cv.lw t0, (t1), 4");
+ }
+ } "-march=rv32i_xcvmem" ]
+}
+
+
proc check_effective_target_loongarch_sx { } {
return [check_no_compiler_messages loongarch_lsx assembly {
#if !defined(__loongarch_sx)