In the 32-bit runtime, it is more efficient to do a long call to a non- local function using an indirect call than it is to use the inline sequence currently in pa_output_call. The attached
change modifies the call and call_value expanders to do this.

Tested on hppa-unknown-linux-gnu, hppa2.0w-hp-hpux11.11 and hppa64-hp- hpux11.11.
Committed to trunk.

Dave
--
John David Anglin       dave.ang...@bell.net


2014-01-26  John David Anglin  <dang...@gcc.gnu.org>

        * config/pa/pa.md (call): Generate indirect long calls to non-local
        functions when outputing 32-bit code.
        (call_value): Likewise except for special call to buggy powf function.

Index: config/pa/pa.md
===================================================================
--- config/pa/pa.md     (revision 206844)
+++ config/pa/pa.md     (working copy)
@@ -7087,8 +7087,18 @@
   if (TARGET_PORTABLE_RUNTIME)
     op = force_reg (SImode, XEXP (operands[0], 0));
   else
-    op = XEXP (operands[0], 0);
+    {
+      op = XEXP (operands[0], 0);
 
+      /* Generate indirect long calls to non-local functions. */
+      if (!TARGET_64BIT && TARGET_LONG_CALLS && GET_CODE (op) == SYMBOL_REF)
+       {
+         tree call_decl = SYMBOL_REF_DECL (op);
+         if (!(call_decl && targetm.binds_local_p (call_decl)))
+           op = force_reg (word_mode, op);
+       }
+    }
+
   if (TARGET_64BIT)
     {
       if (!virtuals_instantiated)
@@ -7575,12 +7585,30 @@
   rtx op;
   rtx dst = operands[0];
   rtx nb = operands[2];
+  bool call_powf = false;
 
   if (TARGET_PORTABLE_RUNTIME)
     op = force_reg (SImode, XEXP (operands[1], 0));
   else
-    op = XEXP (operands[1], 0);
+    {
+      op = XEXP (operands[1], 0);
+      if (GET_CODE (op) == SYMBOL_REF)
+       {
+         /* Handle special call to buggy powf function.  */
+         if (TARGET_HPUX && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT
+             && !strcmp (targetm.strip_name_encoding (XSTR (op, 0)), "powf"))
+           call_powf = true;
 
+         /* Generate indirect long calls to non-local functions. */
+         else if (!TARGET_64BIT && TARGET_LONG_CALLS)
+           {
+             tree call_decl = SYMBOL_REF_DECL (op);
+             if (!(call_decl && targetm.binds_local_p (call_decl)))
+               op = force_reg (word_mode, op);
+           }
+       }
+    }
+
   if (TARGET_64BIT)
     {
       if (!virtuals_instantiated)
@@ -7639,8 +7667,7 @@
       rtx r4 = gen_rtx_REG (word_mode, 4);
       if (GET_CODE (op) == SYMBOL_REF)
        {
-         if (TARGET_HPUX && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT
-             && !strcmp (targetm.strip_name_encoding (XSTR (op, 0)), "powf"))
+         if (call_powf)
            emit_call_insn (gen_call_val_powf_64bit (dst, op, nb, r4));
          else
            emit_call_insn (gen_call_val_symref_64bit (dst, op, nb, r4));
@@ -7659,18 +7686,14 @@
            {
              rtx r4 = gen_rtx_REG (word_mode, 4);
 
-             if (TARGET_HPUX && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT
-                 && !strcmp (targetm.strip_name_encoding (XSTR (op, 0)),
-                             "powf"))
+             if (call_powf)
                emit_call_insn (gen_call_val_powf_pic (dst, op, nb, r4));
              else
                emit_call_insn (gen_call_val_symref_pic (dst, op, nb, r4));
            }
          else
            {
-             if (TARGET_HPUX && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT
-                 && !strcmp (targetm.strip_name_encoding (XSTR (op, 0)),
-                             "powf"))
+             if (call_powf)
                emit_call_insn (gen_call_val_powf (dst, op, nb));
              else
                emit_call_insn (gen_call_val_symref (dst, op, nb));

Reply via email to