]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[ARM] Fix PR89222
authorWilco Dijkstra <wdijkstr@arm.com>
Tue, 16 Jul 2019 13:13:26 +0000 (13:13 +0000)
committerWilco Dijkstra <wilco@gcc.gnu.org>
Tue, 16 Jul 2019 13:13:26 +0000 (13:13 +0000)
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

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/pr89222.c [new file with mode: 0644]

index 9de8ec77ca2eb45ec0547effd7f47633f0da46b7..9f12f4238153fe15901479b49bd7ac69cf6d72eb 100644 (file)
@@ -1,3 +1,14 @@
+2019-07-16  Wilco Dijkstra  <wdijkstr@arm.com>
+
+       Backport from mainline
+       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-07-15  Andreas Krebbel  <krebbel@linux.ibm.com>
 
        Backport from mainline
index 4cbc342e86f8d541b8b72c0e3a4721d7a07bb24d..8cc1be2acf975e6db631f1346b3f8d90c8d2b1da 100644 (file)
@@ -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;
     }
index ad5f3874bc74faf7ba03cc13d68494279a6b0f6d..0839f9ddf11ab0f1f3bd164c62bbcbafec92cc46 100644 (file)
         }
     }
 
-  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);
   }
   "
 )
index 468cd0928ef7c699d4627e91765c7cd74c0de533..296f93cb95b139f34a2cb4e20ad50f2f809a7db0 100644 (file)
@@ -1,3 +1,11 @@
+2019-07-16  Wilco Dijkstra  <wdijkstr@arm.com>
+
+       Backport from mainline
+       2019-03-05  Wilco Dijkstra  <wdijkstr@arm.com>
+
+       PR target/89222
+       * gcc.target/arm/pr89222.c: Add new test.
+
 2019-07-15  Andreas Krebbel  <krebbel@linux.ibm.com>
 
        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 (file)
index 0000000..d26d7df
--- /dev/null
@@ -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} } } */