diff options
author | Wilco Dijkstra <wdijkstr@arm.com> | 2019-03-05 15:04:01 +0000 |
---|---|---|
committer | Wilco Dijkstra <wilco@gcc.gnu.org> | 2019-03-05 15:04:01 +0000 |
commit | d7c50d679ffafaf5e7ba105cea765a307f60e2f3 (patch) | |
tree | 253d37b987d7417d008a27abf6398beaa5323df8 /gcc | |
parent | deeec83de4379e253af4f41eaaf8f45d4db17302 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 11 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 52 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arm/pr89222.c | 32 |
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} } } */ |