aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorWilco Dijkstra <wdijkstr@arm.com>2019-03-05 15:04:01 +0000
committerWilco Dijkstra <wilco@gcc.gnu.org>2019-03-05 15:04:01 +0000
commitd7c50d679ffafaf5e7ba105cea765a307f60e2f3 (patch)
tree253d37b987d7417d008a27abf6398beaa5323df8 /gcc
parentdeeec83de4379e253af4f41eaaf8f45d4db17302 (diff)
downloadgcc-d7c50d679ffafaf5e7ba105cea765a307f60e2f3.zip
gcc-d7c50d679ffafaf5e7ba105cea765a307f60e2f3.tar.gz
gcc-d7c50d679ffafaf5e7ba105cea765a307f60e2f3.tar.bz2
[ARM] Fix PR89222
The GCC optimizer can generate symbols with non-zero offset from simple if-statements. Bit zero is used for the Arm/Thumb state bit, so relocations with offsets fail if it changes bit zero and the relocation forces bit zero to true. The fix is to disable offsets on function pointer symbols. gcc/ PR target/89222 * config/arm/arm.md (movsi): Use targetm.cannot_force_const_mem to decide when to split off a non-zero offset from a symbol. * config/arm/arm.c (arm_cannot_force_const_mem): Disallow offsets in function symbols. testsuite/ PR target/89222 * gcc.target/arm/pr89222.c: Add new test. From-SVN: r269390
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/arm/arm.c11
-rw-r--r--gcc/config/arm/arm.md52
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/arm/pr89222.c32
5 files changed, 67 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4fb2792..d4e8cbe 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2019-03-05 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR target/89222
+ * config/arm/arm.md (movsi): Use targetm.cannot_force_const_mem
+ to decide when to split off a non-zero offset from a symbol.
+ * config/arm/arm.c (arm_cannot_force_const_mem): Disallow offsets
+ in function symbols.
+
2019-03-05 Richard Biener <rguenther@suse.de>
PR tree-optimization/89594
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index f07f4cc..69b74a2 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -8940,11 +8940,16 @@ static bool
arm_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
{
rtx base, offset;
+ split_const (x, &base, &offset);
- if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
+ if (SYMBOL_REF_P (base))
{
- split_const (x, &base, &offset);
- if (GET_CODE (base) == SYMBOL_REF
+ /* Function symbols cannot have an offset due to the Thumb bit. */
+ if ((SYMBOL_REF_FLAGS (base) & SYMBOL_FLAG_FUNCTION)
+ && INTVAL (offset) != 0)
+ return true;
+
+ if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P
&& !offset_within_block_p (base, INTVAL (offset)))
return true;
}
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 7ee83a5..1805901 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -6016,53 +6016,29 @@
}
}
- if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
+ split_const (operands[1], &base, &offset);
+ if (INTVAL (offset) != 0
+ && targetm.cannot_force_const_mem (SImode, operands[1]))
{
- split_const (operands[1], &base, &offset);
- if (GET_CODE (base) == SYMBOL_REF
- && !offset_within_block_p (base, INTVAL (offset)))
- {
- tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
- emit_move_insn (tmp, base);
- emit_insn (gen_addsi3 (operands[0], tmp, offset));
- DONE;
- }
+ tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
+ emit_move_insn (tmp, base);
+ emit_insn (gen_addsi3 (operands[0], tmp, offset));
+ DONE;
}
+ tmp = can_create_pseudo_p () ? NULL_RTX : operands[0];
+
/* Recognize the case where operand[1] is a reference to thread-local
- data and load its address to a register. */
+ data and load its address to a register. Offsets have been split off
+ already. */
if (arm_tls_referenced_p (operands[1]))
- {
- rtx tmp = operands[1];
- rtx addend = NULL;
-
- if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
- {
- addend = XEXP (XEXP (tmp, 0), 1);
- tmp = XEXP (XEXP (tmp, 0), 0);
- }
-
- gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
- gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
-
- tmp = legitimize_tls_address (tmp,
- !can_create_pseudo_p () ? operands[0] : 0);
- if (addend)
- {
- tmp = gen_rtx_PLUS (SImode, tmp, addend);
- tmp = force_operand (tmp, operands[0]);
- }
- operands[1] = tmp;
- }
+ operands[1] = legitimize_tls_address (operands[1], tmp);
else if (flag_pic
&& (CONSTANT_P (operands[1])
|| symbol_mentioned_p (operands[1])
|| label_mentioned_p (operands[1])))
- operands[1] = legitimize_pic_address (operands[1], SImode,
- (!can_create_pseudo_p ()
- ? operands[0]
- : NULL_RTX), NULL_RTX,
- false /*compute_now*/);
+ operands[1] =
+ legitimize_pic_address (operands[1], SImode, tmp, NULL_RTX, false);
}
"
)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 529aa3c..7c57390 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-03-05 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR target/89222
+ * gcc.target/arm/pr89222.c: Add new test.
+
2019-03-05 Richard Biener <rguenther@suse.de>
PR tree-optimization/89594
diff --git a/gcc/testsuite/gcc.target/arm/pr89222.c b/gcc/testsuite/gcc.target/arm/pr89222.c
new file mode 100644
index 0000000..d26d7df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr89222.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void g (void);
+
+void f1 (int x)
+{
+ if (x != (int) g + 3)
+ return;
+ g();
+}
+
+void (*a2)(void);
+
+void f2 (void)
+{
+ a2 = &g + 3;
+}
+
+typedef void (*__sighandler_t)(int);
+void handler (int);
+
+void f3 (int x)
+{
+ __sighandler_t h = &handler;
+ if (h != (__sighandler_t) 2 && h != (__sighandler_t) 1)
+ h (x);
+}
+
+/* { dg-final { scan-assembler-times {add(?:s)?\tr[0-9]+, r[0-9]+, #3} 2 } } */
+/* { dg-final { scan-assembler-not {.word\tg\+3} } } */
+/* { dg-final { scan-assembler-not {.word\thandler-1} } } */