aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Wilson <jimw@sifive.com>2019-03-19 22:33:34 +0000
committerJim Wilson <wilson@gcc.gnu.org>2019-03-19 15:33:34 -0700
commit026216a753ef0a757a9e368a59fa667ea422cf09 (patch)
tree222389407fc02c0fe6d9412bf3dbebd20859fc61
parent2a23a1c39fb33df0277abd4486a3da64ae5e62c2 (diff)
downloadgcc-026216a753ef0a757a9e368a59fa667ea422cf09.zip
gcc-026216a753ef0a757a9e368a59fa667ea422cf09.tar.gz
gcc-026216a753ef0a757a9e368a59fa667ea422cf09.tar.bz2
RISC-V: Fix %lo overflow with BLKmode references.
gcc/ PR target/89411 * config/riscv/riscv.c (riscv_valid_lo_sum_p): New arg x. New locals align, size, offset. Use them to handle a BLKmode reference. Update comment. (riscv_classify_address): Pass info->offset to riscv_valid_lo_sum_p. gcc/testsuite/ PR target/89411 * gcc.target/riscv/losum-overflow.c: New test. From-SVN: r269813
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/riscv/riscv.c43
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/riscv/losum-overflow.c29
4 files changed, 79 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f4b59d7..adf1382 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2019-03-19 Jim Wilson <jimw@sifive.com>
+
+ PR target/89411
+ * config/riscv/riscv.c (riscv_valid_lo_sum_p): New arg x. New locals
+ align, size, offset. Use them to handle a BLKmode reference. Update
+ comment.
+ (riscv_classify_address): Pass info->offset to riscv_valid_lo_sum_p.
+
2019-03-19 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/89768
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 8e78ab7..d8446f8 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -708,11 +708,15 @@ riscv_split_symbol_type (enum riscv_symbol_type symbol_type)
}
/* Return true if a LO_SUM can address a value of mode MODE when the
- LO_SUM symbol has type SYM_TYPE. */
+ LO_SUM symbol has type SYM_TYPE. X is the LO_SUM second operand, which
+ is used when the mode is BLKmode. */
static bool
-riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, machine_mode mode)
+riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, machine_mode mode,
+ rtx x)
{
+ int align, size;
+
/* Check that symbols of type SYMBOL_TYPE can be used to access values
of mode MODE. */
if (riscv_symbol_insns (sym_type) == 0)
@@ -722,11 +726,38 @@ riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, machine_mode mode)
if (!riscv_split_symbol_type (sym_type))
return false;
+ /* We can't tell size or alignment when we have BLKmode, so try extracing a
+ decl from the symbol if possible. */
+ if (mode == BLKmode)
+ {
+ rtx offset;
+
+ /* Extract the symbol from the LO_SUM operand, if any. */
+ split_const (x, &x, &offset);
+
+ /* Might be a CODE_LABEL. We can compute align but not size for that,
+ so don't bother trying to handle it. */
+ if (!SYMBOL_REF_P (x))
+ return false;
+
+ /* Use worst case assumptions if we don't have a SYMBOL_REF_DECL. */
+ align = (SYMBOL_REF_DECL (x)
+ ? DECL_ALIGN (SYMBOL_REF_DECL (x))
+ : 1);
+ size = (SYMBOL_REF_DECL (x) && DECL_SIZE (SYMBOL_REF_DECL (x))
+ ? tree_to_uhwi (DECL_SIZE (SYMBOL_REF_DECL (x)))
+ : 2*BITS_PER_WORD);
+ }
+ else
+ {
+ align = GET_MODE_ALIGNMENT (mode);
+ size = GET_MODE_BITSIZE (mode);
+ }
+
/* We may need to split multiword moves, so make sure that each word
can be accessed without inducing a carry. */
- if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
- && (!TARGET_STRICT_ALIGN
- || GET_MODE_BITSIZE (mode) > GET_MODE_ALIGNMENT (mode)))
+ if (size > BITS_PER_WORD
+ && (!TARGET_STRICT_ALIGN || size > align))
return false;
return true;
@@ -772,7 +803,7 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
info->symbol_type
= riscv_classify_symbolic_expression (info->offset);
return (riscv_valid_base_register_p (info->reg, mode, strict_p)
- && riscv_valid_lo_sum_p (info->symbol_type, mode));
+ && riscv_valid_lo_sum_p (info->symbol_type, mode, info->offset));
case CONST_INT:
/* Small-integer addresses don't occur very often, but they
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cf01b2f..7ad6ccc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-03-19 Jim Wilson <jimw@sifive.com>
+
+ PR target/89411
+ * gcc.target/riscv/losum-overflow.c: New test.
+
2019-03-19 Martin Sebor <msebor@redhat.com>
PR tree-optimization/89644
diff --git a/gcc/testsuite/gcc.target/riscv/losum-overflow.c b/gcc/testsuite/gcc.target/riscv/losum-overflow.c
new file mode 100644
index 0000000..9c01c7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/losum-overflow.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc -mabi=ilp32 -O2 -fno-section-anchors" } */
+
+/* Check for %lo overflow. Adding an offset larger than the alignment can
+ overflow if the data is allocated to an address mod 4KB that is between
+ 2KB-offset+1 and 2KB-1. */
+typedef long long int int64_t;
+
+#pragma pack(push)
+#pragma pack(1)
+struct S0 {
+ signed f0 : 4;
+ const volatile int64_t f1;
+ volatile signed f2 : 1;
+ signed f3 : 31;
+ unsigned f4 : 8;
+ signed f5 : 20;
+ unsigned f6 : 5;
+};
+#pragma pack(pop)
+
+struct S0 g_3030 = {0,-9L,-0,-22553,7,-841,1};
+
+int64_t
+sub (void)
+{
+ return g_3030.f1;
+}
+/* { dg-final { scan-assembler-not "%lo\\(g_3030\\+4\\)" } } */