re PR target/50305 (Inline asm reload failure when building Linux kernel)
authorUlrich Weigand <ulrich.weigand@linaro.org>
Thu, 6 Oct 2011 11:50:26 +0000 (11:50 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Thu, 6 Oct 2011 11:50:26 +0000 (11:50 +0000)
gcc/
PR target/50305
* config/arm/arm.c (arm_legitimize_reload_address): Recognize
output of a previous pass through legitimize_reload_address.
Do not attempt to optimize addresses if the base register is
equivalent to a constant.

gcc/testsuite/
PR target/50305
* gcc.target/arm/pr50305.c: New test.

From-SVN: r179603

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

index f8d41cc59c760a940e1a9a3cd556bc3454c69288..8c54eaf5b5013c313ad349b78509ef48645eaddf 100644 (file)
@@ -1,3 +1,11 @@
+2011-10-06  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+       PR target/50305
+       * config/arm/arm.c (arm_legitimize_reload_address): Recognize
+       output of a previous pass through legitimize_reload_address.
+       Do not attempt to optimize addresses if the base register is
+       equivalent to a constant.
+
 2011-10-06  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
 
        * function.c (thread_prologue_and_epilogue_insns): Mark
index 51614396da4de4ec58b2f76a8e48627011ffca77..2feac6f45e1db945348f28e75eda6445abc4c643 100644 (file)
@@ -6550,9 +6550,26 @@ arm_legitimize_reload_address (rtx *p,
                               int opnum, int type,
                               int ind_levels ATTRIBUTE_UNUSED)
 {
+  /* We must recognize output that we have already generated ourselves.  */
+  if (GET_CODE (*p) == PLUS
+      && GET_CODE (XEXP (*p, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (*p, 0), 0)) == REG
+      && GET_CODE (XEXP (XEXP (*p, 0), 1)) == CONST_INT
+      && GET_CODE (XEXP (*p, 1)) == CONST_INT)
+    {
+      push_reload (XEXP (*p, 0), NULL_RTX, &XEXP (*p, 0), NULL,
+                  MODE_BASE_REG_CLASS (mode), GET_MODE (*p),
+                  VOIDmode, 0, 0, opnum, (enum reload_type) type);
+      return true;
+    }
+
   if (GET_CODE (*p) == PLUS
       && GET_CODE (XEXP (*p, 0)) == REG
       && ARM_REGNO_OK_FOR_BASE_P (REGNO (XEXP (*p, 0)))
+      /* If the base register is equivalent to a constant, let the generic
+        code handle it.  Otherwise we will run into problems if a future
+        reload pass decides to rematerialize the constant.  */
+      && !reg_equiv_constant (ORIGINAL_REGNO (XEXP (*p, 0)))
       && GET_CODE (XEXP (*p, 1)) == CONST_INT)
     {
       HOST_WIDE_INT val = INTVAL (XEXP (*p, 1));
index 458bacb456c2cf1d9b20c639ef9d339e780c51eb..27f774624015941c2b9284a21134f2895b98ac61 100644 (file)
@@ -1,3 +1,8 @@
+2011-10-06  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+       PR target/50305
+       * gcc.target/arm/pr50305.c: New test.
+
 2011-10-06  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/38884
diff --git a/gcc/testsuite/gcc.target/arm/pr50305.c b/gcc/testsuite/gcc.target/arm/pr50305.c
new file mode 100644 (file)
index 0000000..2f6ad5c
--- /dev/null
@@ -0,0 +1,60 @@
+/* { dg-do compile } */
+/* { dg-skip-if "incompatible options" { arm*-*-* } { "-march=*" } { "-march=armv7-a" } } */
+/* { dg-options "-O2 -fno-omit-frame-pointer -marm -march=armv7-a -mfpu=vfp3" } */
+
+struct event {
+ unsigned long long id;
+ unsigned int flag;
+};
+
+void dummy(void)
+{
+  /* This is here to ensure that the offset of perf_event_id below
+     relative to the LANCHOR symbol exceeds the allowed displacement.  */
+  static int __warned[300];
+ __warned[0] = 1;
+}
+
+extern void *kmem_cache_alloc_trace (void *cachep);
+extern void *cs_cachep;
+extern int nr_cpu_ids;
+
+struct event *
+event_alloc (int cpu)
+{
+ static unsigned long long __attribute__((aligned(8))) perf_event_id;
+ struct event *event;
+ unsigned long long result;
+ unsigned long tmp;
+
+ if (cpu >= nr_cpu_ids)
+  return 0;
+
+ event = kmem_cache_alloc_trace (cs_cachep);
+
+ __asm__ __volatile__ ("dmb" : : : "memory");
+
+ __asm__ __volatile__("@ atomic64_add_return\n"
+"1:    ldrexd  %0, %H0, [%3]\n"
+"      adds    %0, %0, %4\n"
+"      adc     %H0, %H0, %H4\n"
+"      strexd  %1, %0, %H0, [%3]\n"
+"      teq     %1, #0\n"
+"      bne     1b"
+ : "=&r" (result), "=&r" (tmp), "+Qo" (perf_event_id)
+ : "r" (&perf_event_id), "r" (1LL)
+ : "cc");
+
+ __asm__ __volatile__ ("dmb" : : : "memory");
+
+ event->id = result;
+
+ if (cpu)
+  event->flag = 1;
+
+ for (cpu = 0; cpu < nr_cpu_ids; cpu++)
+   kmem_cache_alloc_trace (cs_cachep);
+
+ return event;
+}
+