From: Wilco Dijkstra Date: Tue, 16 Jul 2019 13:13:26 +0000 (+0000) Subject: [ARM] Fix PR89222 X-Git-Tag: releases/gcc-7.5.0~350 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=560c38ab997af0e4a0e0a00f34b1d0879d52e168;p=thirdparty%2Fgcc.git [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: r273527 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9de8ec77ca2e..9f12f4238153 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2019-07-16 Wilco Dijkstra + + Backport from mainline + 2019-03-05 Wilco Dijkstra + + 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-07-15 Andreas Krebbel Backport from mainline diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 4cbc342e86f8..8cc1be2acf97 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -8712,11 +8712,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 ad5f3874bc74..0839f9ddf11a 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -5999,52 +5999,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] - : 0)); + operands[1] = + legitimize_pic_address (operands[1], SImode, tmp); } " ) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 468cd0928ef7..296f93cb95b1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-07-16 Wilco Dijkstra + + Backport from mainline + 2019-03-05 Wilco Dijkstra + + PR target/89222 + * gcc.target/arm/pr89222.c: Add new test. + 2019-07-15 Andreas Krebbel Backport from mainline diff --git a/gcc/testsuite/gcc.target/arm/pr89222.c b/gcc/testsuite/gcc.target/arm/pr89222.c new file mode 100644 index 000000000000..d26d7df17544 --- /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} } } */