alpha.c (alpha_pad_noreturn): Rename to ...
authorUros Bizjak <uros@gcc.gnu.org>
Thu, 9 Aug 2012 15:02:36 +0000 (17:02 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Thu, 9 Aug 2012 15:02:36 +0000 (17:02 +0200)
        * config/alpha/alpha.c (alpha_pad_noreturn): Rename to ...
        (alpha_pad_function_end): ... this.  Also insert NOP between
        sibling call and GP load.
        (alpha_reorg): Update call to alpha_pad_function_end.  Expand comment.

From-SVN: r190255

gcc/ChangeLog
gcc/config/alpha/alpha.c

index db6dbd5f7cd90ad9843e37c53f77fccf9c040c01..c3392e9a869cc7ce553ec391f48ed86a17966048 100644 (file)
@@ -1,3 +1,10 @@
+2012-08-09  Uros Bizjak  <ubizjak@gmail.com>
+
+        * config/alpha/alpha.c (alpha_pad_noreturn): Rename to ...
+        (alpha_pad_function_end): ... this.  Also insert NOP between
+        sibling call and GP load.
+        (alpha_reorg): Update call to alpha_pad_function_end.  Expand comment.
+
 2012-08-09  Michael Zolotukhin  <michael.v.zolotukhin@intel.com>
 
        * config/i386/adxintrin.h: Remove guarding __ADX__ check.
@@ -14,7 +21,7 @@
        * sel-sched.c (vinsn_vec_has_expr_p): Clarify function comment.
        Process not only expr's vinsns but all old vinsns from expr's
        history of changes.
-       (update_and_record_unavailable_insns): Clarify comment. 
+       (update_and_record_unavailable_insns): Clarify comment.
 
 2012-08-09  Bernd Schmidt  <bernds@codesourcery.com>
 
index 6d455eff0a41893bd4ba67204be7148e6e1076b5..2d6ba95d1a9cee903b80143440578877ec1fb0cb 100644 (file)
@@ -9258,17 +9258,18 @@ alpha_align_insns (unsigned int max_align,
     }
 }
 
-/* Insert an unop between a noreturn function call and GP load.  */
+/* Insert an unop between sibcall or noreturn function call and GP load.  */
 
 static void
-alpha_pad_noreturn (void)
+alpha_pad_function_end (void)
 {
   rtx insn, next;
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     {
       if (! (CALL_P (insn)
-            && find_reg_note (insn, REG_NORETURN, NULL_RTX)))
+            && (SIBLING_CALL_P (insn)
+                || find_reg_note (insn, REG_NORETURN, NULL_RTX))))
         continue;
 
       /* Make sure we do not split a call and its corresponding
@@ -9300,8 +9301,28 @@ alpha_pad_noreturn (void)
 static void
 alpha_reorg (void)
 {
-  /* Workaround for a linker error that triggers when an
-     exception handler immediatelly follows a noreturn function.
+  /* Workaround for a linker error that triggers when an exception
+     handler immediatelly follows a sibcall or a noreturn function.
+
+In the sibcall case:
+
+     The instruction stream from an object file:
+
+ 1d8:   00 00 fb 6b     jmp     (t12)
+ 1dc:   00 00 ba 27     ldah    gp,0(ra)
+ 1e0:   00 00 bd 23     lda     gp,0(gp)
+ 1e4:   00 00 7d a7     ldq     t12,0(gp)
+ 1e8:   00 40 5b 6b     jsr     ra,(t12),1ec <__funcZ+0x1ec>
+
+     was converted in the final link pass to:
+
+   12003aa88:   67 fa ff c3     br      120039428 <...>
+   12003aa8c:   00 00 fe 2f     unop
+   12003aa90:   00 00 fe 2f     unop
+   12003aa94:   48 83 7d a7     ldq     t12,-31928(gp)
+   12003aa98:   00 40 5b 6b     jsr     ra,(t12),12003aa9c <__func+0x1ec>
+
+And in the noreturn case:
 
      The instruction stream from an object file:
 
@@ -9321,11 +9342,11 @@ alpha_reorg (void)
 
      GP load instructions were wrongly cleared by the linker relaxation
      pass.  This workaround prevents removal of GP loads by inserting
-     an unop instruction between a noreturn function call and
+     an unop instruction between a sibcall or noreturn function call and
      exception handler prologue.  */
 
   if (current_function_has_exception_handlers ())
-    alpha_pad_noreturn ();
+    alpha_pad_function_end ();
 
   if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
     alpha_handle_trap_shadows ();