riscv-toolchain-conventions PR #156 defines separate alignment
policies for RV32 Zilsd/Zclsd doubleword memory accesses. Add
-mzilsd-word-align and -mzilsd-strict-align to let users select
the word-aligned and naturally aligned variants explicitly.
Keep the existing -mstrict-align family in the same last-option-wins
option group so code can opt in or out without depending on option
order surprises. When a 2 * XLEN access is not allowed by the
selected policy, expand through scalar bit-field helpers instead of
selecting Zilsd loads or stores.
gcc/ChangeLog:
* common/config/riscv/riscv-common.cc (riscv_handle_option):
Handle Zilsd alignment options and clear the Zilsd-specific
explicit marker for -mstrict-align.
* config/riscv/riscv-opts.h (riscv_zilsd_align_type): New enum.
* config/riscv/riscv-protos.h
(riscv_expand_zilsd_misaligned_move): Declare as void.
(riscv_zilsd_valid_mem_p): Declare.
* config/riscv/riscv.cc (riscv_zilsd_required_align): New
functions.
(riscv_zilsd_valid_mem_p): New function.
(riscv_rtx_costs): Honor Zilsd alignment policy.
(riscv_split_64bit_move_p): Split invalid Zilsd GPR accesses.
(riscv_expand_zilsd_misaligned_move): New function.
(riscv_can_inline_p): Check effective Zilsd alignment policy.
(riscv_override_options_internal): Reject explicit Zilsd
alignment options for RV64.
* config/riscv/riscv.md (movmisaligndi): New expander.
(movmisaligndf): New expander.
* config/riscv/riscv.opt: Add -mzilsd-word-align and
-mzilsd-strict-align.
* config/riscv/riscv.opt.urls: Regenerate.
* doc/invoke.texi: Document the new options.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/zilsd-align-default-1.c: New test.
* gcc.target/riscv/zilsd-align-df-1.c: New test.
* gcc.target/riscv/zilsd-align-rv64-1.c: New test.
* gcc.target/riscv/zilsd-align-rv64-2.c: New test.
* gcc.target/riscv/zilsd-align-rv64-3.c: New test.
* gcc.target/riscv/zilsd-align-rv64-4.c: New test.
* gcc.target/riscv/zilsd-align-word-1.c: New test.
* gcc.target/riscv/zilsd-align-word-2.c: New test.
* gcc.target/riscv/zilsd-align-word-3.c: New test.
* gcc.target/riscv/zilsd-align-word-4.c: New test.
* gcc.target/riscv/zilsd-align-word-5.c: New test.
Signed-off-by: Christoph Müllner <[email protected]>
---
gcc/common/config/riscv/riscv-common.cc | 33 ++++-
gcc/config/riscv/riscv-opts.h | 8 ++
gcc/config/riscv/riscv-protos.h | 2 +
gcc/config/riscv/riscv.cc | 124 +++++++++++++++++-
gcc/config/riscv/riscv.md | 18 +++
gcc/config/riscv/riscv.opt | 14 ++
gcc/config/riscv/riscv.opt.urls | 7 +-
gcc/doc/invoke.texi | 15 +++
.../gcc.target/riscv/zilsd-align-default-1.c | 17 +++
.../gcc.target/riscv/zilsd-align-df-1.c | 19 +++
.../gcc.target/riscv/zilsd-align-rv64-1.c | 6 +
.../gcc.target/riscv/zilsd-align-rv64-2.c | 6 +
.../gcc.target/riscv/zilsd-align-rv64-3.c | 5 +
.../gcc.target/riscv/zilsd-align-rv64-4.c | 5 +
.../gcc.target/riscv/zilsd-align-word-1.c | 20 +++
.../gcc.target/riscv/zilsd-align-word-2.c | 20 +++
.../gcc.target/riscv/zilsd-align-word-3.c | 20 +++
.../gcc.target/riscv/zilsd-align-word-4.c | 20 +++
.../gcc.target/riscv/zilsd-align-word-5.c | 20 +++
19 files changed, 372 insertions(+), 7 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-default-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-df-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-word-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-word-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-word-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-word-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zilsd-align-word-5.c
diff --git a/gcc/common/config/riscv/riscv-common.cc
b/gcc/common/config/riscv/riscv-common.cc
index 5d3d37c7a7b..b149393e35f 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -1705,12 +1705,43 @@ riscv_find_cpu (const char *cpu)
static bool
riscv_handle_option (struct gcc_options *opts,
- struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+ struct gcc_options *opts_set,
const struct cl_decoded_option *decoded,
location_t loc)
{
switch (decoded->opt_index)
{
+ case OPT_mstrict_align:
+ opts->x_riscv_zilsd_align
+ = decoded->value ? RISCV_ZILSD_ALIGN_STRICT : RISCV_ZILSD_ALIGN_BYTE;
+ opts->x_riscv_zilsd_align_explicit = 0;
+ if (opts_set)
+ {
+ opts_set->x_riscv_zilsd_align = opts->x_riscv_zilsd_align;
+ opts_set->x_riscv_zilsd_align_explicit = 0;
+ }
+ return true;
+
+ case OPT_mzilsd_word_align:
+ opts->x_riscv_zilsd_align = RISCV_ZILSD_ALIGN_WORD;
+ opts->x_riscv_zilsd_align_explicit = 1;
+ if (opts_set)
+ {
+ opts_set->x_riscv_zilsd_align = opts->x_riscv_zilsd_align;
+ opts_set->x_riscv_zilsd_align_explicit = 1;
+ }
+ return true;
+
+ case OPT_mzilsd_strict_align:
+ opts->x_riscv_zilsd_align = RISCV_ZILSD_ALIGN_STRICT;
+ opts->x_riscv_zilsd_align_explicit = 1;
+ if (opts_set)
+ {
+ opts_set->x_riscv_zilsd_align = opts->x_riscv_zilsd_align;
+ opts_set->x_riscv_zilsd_align_explicit = 1;
+ }
+ return true;
+
case OPT_march_:
if (riscv_find_cpu (decoded->arg) == NULL)
riscv_parse_arch_string (decoded->arg, opts, loc);
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 88a4aa33926..036680117c3 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -75,6 +75,14 @@ enum riscv_align_data {
riscv_align_data_type_natural
};
+/* Alignment policy for Zilsd 2 * XLEN memory accesses. */
+enum riscv_zilsd_align_type {
+ RISCV_ZILSD_ALIGN_DEFAULT,
+ RISCV_ZILSD_ALIGN_BYTE,
+ RISCV_ZILSD_ALIGN_WORD,
+ RISCV_ZILSD_ALIGN_STRICT
+};
+
/* Where to get the canary for the stack protector. */
enum stack_protector_guard {
SSP_TLS, /* per-thread canary in TLS block */
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index f8eee0fd844..2b055fac465 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -156,6 +156,8 @@ extern rtx riscv_emit_binary (enum rtx_code code, rtx dest,
rtx x, rtx y);
#endif
extern bool riscv_expand_conditional_move (rtx, rtx, rtx, rtx);
extern rtx riscv_legitimize_call_address (rtx);
+extern void riscv_expand_zilsd_misaligned_move (rtx, rtx);
+extern bool riscv_zilsd_valid_mem_p (rtx, machine_mode);
extern void riscv_set_return_address (rtx, rtx);
extern rtx riscv_return_addr (int, rtx);
extern poly_int64 riscv_initial_elimination_offset (int, int);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 2a2193767c7..1e1e896e6fb 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "expr.h"
#include "optabs.h"
+#include "expmed.h"
#include "bitmap.h"
#include "df.h"
#include "function-abi.h"
@@ -1018,6 +1019,60 @@ riscv_2x_xlen_mode_p (machine_mode mode)
&& (mode_size.to_constant () == UNITS_PER_WORD * 2);
}
+/* Return the required alignment, in bytes, for Zilsd memory accesses. */
+
+static unsigned int
+riscv_zilsd_required_align (enum riscv_zilsd_align_type align,
+ bool strict_align_p)
+{
+ switch (align)
+ {
+ case RISCV_ZILSD_ALIGN_BYTE:
+ return 1;
+
+ case RISCV_ZILSD_ALIGN_WORD:
+ return 4;
+
+ case RISCV_ZILSD_ALIGN_STRICT:
+ return 8;
+
+ case RISCV_ZILSD_ALIGN_DEFAULT:
+ return strict_align_p ? 8 : 1;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return the required alignment, in bytes, for Zilsd memory accesses. */
+
+static unsigned int
+riscv_zilsd_required_align (void)
+{
+ return riscv_zilsd_required_align (riscv_zilsd_align, TARGET_STRICT_ALIGN);
+}
+
+/* Return true if MEM can be accessed by a Zilsd 2 * XLEN load/store. */
+
+bool
+riscv_zilsd_valid_mem_p (rtx mem, machine_mode mode)
+{
+ return (TARGET_ZILSD
+ && !TARGET_64BIT
+ && riscv_2x_xlen_mode_p (mode)
+ && MEM_P (mem)
+ && MEM_ALIGN (mem) >= riscv_zilsd_required_align () * BITS_PER_UNIT);
+}
+
+/* Return the effective Zilsd memory access alignment policy. */
+
+static unsigned int
+riscv_zilsd_required_align (const struct cl_target_option *opts)
+{
+ return riscv_zilsd_required_align
+ (opts->x_riscv_zilsd_align, TARGET_STRICT_ALIGN_P (opts->x_target_flags));
+}
+
/* Implement TARGET_MIN_ARITHMETIC_PRECISION. */
static unsigned int
@@ -4263,8 +4318,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int
outer_code, int opno ATTRIBUTE_UN
}
/* Load for XLEN * 2. */
- if (TARGET_ZILSD && MEM_P (SET_SRC (x))
- && riscv_2x_xlen_mode_p (mode))
+ if (riscv_zilsd_valid_mem_p (SET_SRC (x), mode))
{
/* TODO: Add riscv_tune_param for this. */
*total = COSTS_N_INSNS (1);
@@ -4276,8 +4330,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int
outer_code, int opno ATTRIBUTE_UN
}
/* Store for XLEN * 2. */
- if (TARGET_ZILSD && MEM_P (SET_DEST (x)) && REG_P (SET_SRC (x))
- && riscv_2x_xlen_mode_p (mode))
+ if (REG_P (SET_SRC (x)) && riscv_zilsd_valid_mem_p (SET_DEST (x), mode))
{
/* TODO: Add riscv_tune_param for this. */
*total = COSTS_N_INSNS (1);
@@ -4995,7 +5048,13 @@ riscv_split_64bit_move_p (rtx dest, rtx src)
/* GCC may still generating some load/store with odd-even reg pair
because the ABI handling, but that's fine, just split that later. */
if (GP_REG_P (regno))
- return (regno < FIRST_PSEUDO_REGISTER) && ((regno % 2) != 0);
+ {
+ rtx mem = MEM_P (dest) ? dest : src;
+ if (!riscv_zilsd_valid_mem_p (mem, GET_MODE (mem)))
+ return true;
+
+ return (regno < FIRST_PSEUDO_REGISTER) && ((regno % 2) != 0);
+ }
}
/* There is no need to split if the FLI instruction in the `Zfa` extension
can be used. */
@@ -5014,6 +5073,53 @@ riscv_split_64bit_move_p (rtx dest, rtx src)
return true;
}
+/* Expand a potentially misaligned Zilsd-sized memory move. */
+
+void
+riscv_expand_zilsd_misaligned_move (rtx dest, rtx src)
+{
+ machine_mode mode = GET_MODE (dest);
+ if (mode == VOIDmode)
+ mode = GET_MODE (src);
+
+ gcc_assert (!TARGET_64BIT && TARGET_ZILSD && riscv_2x_xlen_mode_p (mode));
+ gcc_assert (MEM_P (src) || MEM_P (dest));
+
+ if (MEM_P (src) && MEM_P (dest))
+ {
+ rtx tmp = gen_reg_rtx (mode);
+ riscv_expand_zilsd_misaligned_move (tmp, src);
+ riscv_expand_zilsd_misaligned_move (dest, tmp);
+ return;
+ }
+
+ if ((MEM_P (src) && riscv_zilsd_valid_mem_p (src, mode))
+ || (MEM_P (dest) && riscv_zilsd_valid_mem_p (dest, mode)))
+ {
+ emit_move_insn (dest, src);
+ return;
+ }
+
+ if (MEM_P (src))
+ {
+ rtx target = REG_P (dest) ? dest : NULL_RTX;
+ rtx value = extract_bit_field (src, GET_MODE_BITSIZE (mode), 0,
+ false, target, mode, mode, false, NULL);
+ if (value != dest)
+ emit_move_insn (dest, value);
+ return;
+ }
+
+ if (MEM_P (dest))
+ {
+ store_bit_field (dest, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, src,
+ false, false);
+ return;
+ }
+
+ gcc_unreachable ();
+}
+
/* Split a doubleword move from SRC to DEST. On 32-bit targets,
this function handles 64-bit moves for which riscv_split_64bit_move_p
holds. For 64-bit targets, this function handles 128-bit moves. */
@@ -9039,6 +9145,10 @@ riscv_can_inline_p (tree caller, tree callee)
!= callee_opts->x_rvv_vector_strict_align)
return false;
+ if (riscv_zilsd_required_align (caller_opts)
+ != riscv_zilsd_required_align (callee_opts))
+ return false;
+
return true;
}
@@ -11688,6 +11798,10 @@ riscv_override_options_internal (struct gcc_options
*opts)
&& ((target_flags_explicit & MASK_FDIV) == 0))
opts->x_target_flags |= MASK_FDIV;
+ if (TARGET_64BIT && opts->x_riscv_zilsd_align_explicit)
+ error ("%<-mzilsd-word-align%> and %<-mzilsd-strict-align%> are only "
+ "supported for RV32");
+
/* Handle -mtune, use -mcpu if -mtune is not given, and use default -mtune
if both -mtune and -mcpu are not given. */
const char *tune_string = get_tune_str (opts);
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 869061e18ae..7be0181c163 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -2578,6 +2578,15 @@ (define_insn "*movdi_64bit"
(set_attr "type" "move,move,load,store,mtc,fpload,mfc,fmove,fpstore,move")
(set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")])
+(define_expand "movmisaligndi"
+ [(set (match_operand:DI 0 "nonimmediate_operand")
+ (match_operand:DI 1 "general_operand"))]
+ "!TARGET_64BIT && TARGET_ZILSD"
+{
+ riscv_expand_zilsd_misaligned_move (operands[0], operands[1]);
+ DONE;
+})
+
;; 32-bit Integer moves
(define_expand "mov<mode>"
@@ -2752,6 +2761,15 @@ (define_insn "*movdf_softfloat"
(set_attr "type" "fmove,fpload,fpstore")
(set_attr "mode" "DF")])
+(define_expand "movmisaligndf"
+ [(set (match_operand:DF 0 "nonimmediate_operand")
+ (match_operand:DF 1 "general_operand"))]
+ "!TARGET_64BIT && TARGET_ZILSD && !TARGET_DOUBLE_FLOAT"
+{
+ riscv_expand_zilsd_misaligned_move (operands[0], operands[1]);
+ DONE;
+})
+
(define_insn "movsidf2_low_rv32"
[(set (match_operand:SI 0 "register_operand" "= r")
(unspec:SI
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index c6e099eb47e..c2670ad87b2 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -132,6 +132,14 @@ mscalar-strict-align
Target Save Alias(mstrict-align)
Do not generate unaligned scalar memory accesses.
+mzilsd-word-align
+Target RejectNegative
+Allow Zilsd/Zclsd memory accesses to be 4-byte aligned.
+
+mzilsd-strict-align
+Target RejectNegative
+Force Zilsd/Zclsd memory accesses to be 8-byte aligned.
+
mvector-strict-align
Target Save Var(rvv_vector_strict_align) Init(1)
Do not create element-misaligned vector memory accesses.
@@ -171,6 +179,12 @@ Omit the frame pointer in leaf functions.
TargetVariable
int riscv_isa_flags
+TargetVariable
+enum riscv_zilsd_align_type riscv_zilsd_align = RISCV_ZILSD_ALIGN_DEFAULT
+
+TargetVariable
+int riscv_zilsd_align_explicit = 0
+
Mask(64BIT) Var(riscv_isa_flags)
Mask(VECTOR) Var(riscv_isa_flags)
diff --git a/gcc/config/riscv/riscv.opt.urls b/gcc/config/riscv/riscv.opt.urls
index 8111d34b22e..232bf9200e5 100644
--- a/gcc/config/riscv/riscv.opt.urls
+++ b/gcc/config/riscv/riscv.opt.urls
@@ -50,6 +50,12 @@ UrlSuffix(gcc/RISC-V-Options.html#index-mstrict-align-4)
mscalar-strict-align
UrlSuffix(gcc/RISC-V-Options.html#index-mscalar-strict-align)
+mzilsd-word-align
+UrlSuffix(gcc/RISC-V-Options.html#index-mzilsd-word-align)
+
+mzilsd-strict-align
+UrlSuffix(gcc/RISC-V-Options.html#index-mzilsd-strict-align)
+
mvector-strict-align
UrlSuffix(gcc/RISC-V-Options.html#index-mvector-strict-align)
@@ -122,4 +128,3 @@ mautovec-segment
UrlSuffix(gcc/RISC-V-Options.html#index-mautovec-segment)
; skipping UrlSuffix for 'mmpy-option=' due to finding no URLs
-
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 6d1da9f610e..8bfa73598c2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1338,6 +1338,7 @@ See RS/6000 and PowerPC Options.
-msmall-data-limit=@var{N-bytes}
-msave-restore -mno-shorten-memrefs
-mstrict-align -mscalar-strict-align -mno-vector-strict-align
+-mzilsd-word-align -mzilsd-strict-align
-mcmodel=medlow -mcmodel=medany -mcmodel=large
-mexplicit-relocs -mrelax -mriscv-attribute
-malign-data=@var{type}
@@ -31425,6 +31426,20 @@ Do not or do generate unaligned vector memory
accesses. The default is set
to off unless the processor we are optimizing for explicitly supports
element-misaligned vector memory access.
+@opindex mzilsd-word-align
+@item -mzilsd-word-align
+Allow Zilsd/Zclsd memory accesses to be generated when they are known to be
+4-byte aligned.
+
+@opindex mzilsd-strict-align
+@item -mzilsd-strict-align
+Require Zilsd/Zclsd memory accesses to be naturally 8-byte aligned.
+
+The precedence among @option{-mzilsd-word-align},
+@option{-mzilsd-strict-align}, @option{-mstrict-align},
+@option{-mno-strict-align}, @option{-mscalar-strict-align}, and
+@option{-mno-scalar-strict-align} is determined by the last one specified.
+
@opindex mmax-vectorization
@opindex mno-max-vectorization
@item -mmax-vectorization
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-default-1.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-default-1.c
new file mode 100644
index 00000000000..8793cda2f9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-default-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32i_zilsd -mabi=ilp32" } */
+
+long long
+load_ll (long long *p)
+{
+ return *p;
+}
+
+void
+store_ll (long long *p, long long x)
+{
+ *p = x;
+}
+
+/* { dg-final { scan-assembler-times "ld\t" 1 } } */
+/* { dg-final { scan-assembler-times "sd\t" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-df-1.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-df-1.c
new file mode 100644
index 00000000000..6e4b1829ec5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-df-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32i_zilsd -mabi=ilp32 -mzilsd-strict-align" } */
+
+typedef double df4 __attribute__((aligned(4)));
+
+double
+load_df4 (df4 *p)
+{
+ return *p;
+}
+
+void
+store_df4 (df4 *p, double x)
+{
+ *p = x;
+}
+
+/* { dg-final { scan-assembler-not "ld\t" } } */
+/* { dg-final { scan-assembler-not "sd\t" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-1.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-1.c
new file mode 100644
index 00000000000..f68b143f34e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-1.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -mzilsd-word-align" } */
+
+int i;
+
+/* { dg-error "only supported for RV32" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-2.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-2.c
new file mode 100644
index 00000000000..0600fd9c09e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-2.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -mzilsd-strict-align" } */
+
+int i;
+
+/* { dg-error "only supported for RV32" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-3.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-3.c
new file mode 100644
index 00000000000..65eeed377e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-3.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d" } */
+/* { dg-additional-options "-mzilsd-word-align -mstrict-align" } */
+
+int i;
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-4.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-4.c
new file mode 100644
index 00000000000..fea394a466a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-rv64-4.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d" } */
+/* { dg-additional-options "-mzilsd-strict-align -mno-strict-align" } */
+
+int i;
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-word-1.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-word-1.c
new file mode 100644
index 00000000000..eeaed6cba91
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-word-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32i_zilsd -mabi=ilp32" } */
+/* { dg-additional-options "-mstrict-align -mzilsd-word-align" } */
+
+typedef long long ll4 __attribute__((aligned(4)));
+
+long long
+load_ll4 (ll4 *p)
+{
+ return *p;
+}
+
+void
+store_ll4 (ll4 *p, long long x)
+{
+ *p = x;
+}
+
+/* { dg-final { scan-assembler-times "ld\t" 1 } } */
+/* { dg-final { scan-assembler-times "sd\t" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-word-2.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-word-2.c
new file mode 100644
index 00000000000..47d26279c6a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-word-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32i_zilsd -mabi=ilp32" } */
+/* { dg-additional-options "-mzilsd-word-align -mstrict-align" } */
+
+typedef long long ll4 __attribute__((aligned(4)));
+
+long long
+load_ll4 (ll4 *p)
+{
+ return *p;
+}
+
+void
+store_ll4 (ll4 *p, long long x)
+{
+ *p = x;
+}
+
+/* { dg-final { scan-assembler-not "ld\t" } } */
+/* { dg-final { scan-assembler-not "sd\t" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-word-3.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-word-3.c
new file mode 100644
index 00000000000..816bd553b29
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-word-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32i_zilsd -mabi=ilp32" } */
+/* { dg-additional-options "-mstrict-align -mzilsd-word-align" } */
+
+typedef long long ll1 __attribute__((aligned(1)));
+
+long long
+load_ll1 (ll1 *p)
+{
+ return *p;
+}
+
+void
+store_ll1 (ll1 *p, long long x)
+{
+ *p = x;
+}
+
+/* { dg-final { scan-assembler-not "ld\t" } } */
+/* { dg-final { scan-assembler-not "sd\t" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-word-4.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-word-4.c
new file mode 100644
index 00000000000..5babf22e17c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-word-4.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32i_zilsd -mabi=ilp32" } */
+/* { dg-additional-options "-mzilsd-strict-align -mno-strict-align" } */
+
+typedef long long ll1 __attribute__((aligned(1)));
+
+long long
+load_ll1 (ll1 *p)
+{
+ return *p;
+}
+
+void
+store_ll1 (ll1 *p, long long x)
+{
+ *p = x;
+}
+
+/* { dg-final { scan-assembler-times "ld\t" 1 } } */
+/* { dg-final { scan-assembler-times "sd\t" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-align-word-5.c
b/gcc/testsuite/gcc.target/riscv/zilsd-align-word-5.c
new file mode 100644
index 00000000000..990a208cd14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zilsd-align-word-5.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32i_zilsd -mabi=ilp32" } */
+/* { dg-additional-options "-mno-strict-align -mzilsd-strict-align" } */
+
+typedef long long ll4 __attribute__((aligned(4)));
+
+long long
+load_ll4 (ll4 *p)
+{
+ return *p;
+}
+
+void
+store_ll4 (ll4 *p, long long x)
+{
+ *p = x;
+}
+
+/* { dg-final { scan-assembler-not "ld\t" } } */
+/* { dg-final { scan-assembler-not "sd\t" } } */
--
2.54.0