pa.md (alternate dbra pattern): Remove incorrect pattern.
authorJeff Law <law@gcc.gnu.org>
Sun, 8 Jun 1997 06:37:08 +0000 (00:37 -0600)
committerJeff Law <law@gcc.gnu.org>
Sun, 8 Jun 1997 06:37:08 +0000 (00:37 -0600)
        * pa.md (alternate dbra pattern): Remove incorrect pattern.

        * pa.c (struct defer_plab): Renamed to struct deferred_plabel.
        Remove "symbol" field and replace with "name" field.
        (output_function_epilogue): Don't output deferred plabels here.
        (output_deferred_labels): New function.  Output them here instead.
        (output_call): Rewrite long call support.
        * pa.h (ASM_FILE_END): Define.
        (LEGITIMATE_CONSTANT_P): Never accept a function_label_operand.
        * pa.md (HIGH and LO_SUM of function address): Remove patterns.

From-SVN: r14171

gcc/config/pa/pa.c
gcc/config/pa/pa.h
gcc/config/pa/pa.md

index 3515e22b312c9384e78112325aa7377579b276ac..0eae0b1c1b666e50c5fae02598706343ca392800 100644 (file)
@@ -70,10 +70,10 @@ unsigned int total_code_bytes;
 /* Variables to handle plabels that we discover are necessary at assembly
    output time.  They are output after the current function.  */
 
-struct defer_plab
+struct deferred_plabel
 {
   rtx internal_label;
-  rtx symbol;
+  char *name;
 } *deferred_plabels = 0;
 int n_deferred_plabels = 0;
 
@@ -2898,23 +2898,6 @@ output_function_epilogue (file, size)
     fputs ("\tnop\n", file);
 
   fputs ("\t.EXIT\n\t.PROCEND\n", file);
-
-  /* If we have deferred plabels, then we need to switch into the data
-     section and align it to a 4 byte boundary before we output the
-     deferred plabels.  */
-  if (n_deferred_plabels)
-    {
-      data_section ();
-      ASM_OUTPUT_ALIGN (file, 2);
-    }
-
-  /* Now output the deferred plabels.  */
-  for (i = 0; i < n_deferred_plabels; i++)
-    {
-      ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
-      assemble_integer (deferred_plabels[i].symbol, 4, 1);
-    }
-  n_deferred_plabels = 0;
 }
 
 void
@@ -3900,6 +3883,29 @@ output_global_address (file, x, round_constant)
     output_addr_const (file, x);
 }
 
+void
+output_deferred_plabels (file)
+     FILE *file;
+{
+  int i;
+  /* If we have deferred plabels, then we need to switch into the data
+     section and align it to a 4 byte boundary before we output the
+     deferred plabels.  */
+  if (n_deferred_plabels)
+    {
+      data_section ();
+      ASM_OUTPUT_ALIGN (file, 2);
+    }
+
+  /* Now output the deferred plabels.  */
+  for (i = 0; i < n_deferred_plabels; i++)
+    {
+      ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
+      assemble_integer (gen_rtx (SYMBOL_REF, VOIDmode,
+                                deferred_plabels[i].name), 4, 1);
+    }
+}
+
 /* HP's millicode routines mean something special to the assembler.
    Keep track of which ones we have used.  */
 
@@ -5039,6 +5045,11 @@ output_millicode_call (insn, call_dest)
   return "";
 }
 
+extern struct obstack permanent_obstack;
+extern struct obstack *saveable_obstack;
+extern struct obstack *rtl_obstack;
+extern struct obstack *current_obstack;
+
 /* INSN is either a function call.  It may have an unconditional jump
    in its delay slot.
 
@@ -5128,70 +5139,109 @@ output_call (insn, call_dest)
                  output_asm_insn ("ldw -12(%%sr0,%%r30),%R1", xoperands);
                  output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands);
                }
-               
            }
        }
 
       /* Don't have to worry about TARGET_PORTABLE_RUNTIME here since
         we don't have any direct calls in that case.  */
-      if (flag_pic)
        {
-         /* We have to load the address of the function using a procedure
-            label (plabel).  The LP and RP relocs don't work reliably for PIC,
-            so we make a plain 32 bit plabel in the data segment instead.  We
-            have to defer outputting it of course...  Not pretty.  */
+         int i;
+         char *name = XSTR (call_dest, 0);
+
+         /* See if we have already put this function on the list
+            of deferred plabels.  This list is generally small,
+            so a liner search is not too ugly.  If it proves too
+            slow replace it with something faster.  */
+         for (i = 0; i < n_deferred_plabels; i++)
+           if (strcmp (name, deferred_plabels[i].name) == 0)
+             break;
+
+         /* If the deferred plabel list is empty, or this entry was
+            not found on the list, create a new entry on the list.  */
+         if (deferred_plabels == NULL || i == n_deferred_plabels)
+           {
+             struct obstack *ambient_obstack = current_obstack;
+             struct obstack *ambient_rtl_obstack = rtl_obstack;
+             char *real_name;
+
+             /* Any RTL we create here needs to live until the end of
+                the compilation unit and therefore must live on the
+                permanent obstack.  */
+             current_obstack = &permanent_obstack;
+             rtl_obstack = &permanent_obstack;
+
+             if (deferred_plabels == 0)
+               deferred_plabels = (struct deferred_plabel *)
+                 xmalloc (1 * sizeof (struct deferred_plabel));
+             else
+               deferred_plabels = (struct deferred_plabel *)
+                 xrealloc (deferred_plabels,
+                           ((n_deferred_plabels + 1)
+                            * sizeof (struct deferred_plabel)));
+
+             i = n_deferred_plabels++;
+             deferred_plabels[i].internal_label = gen_label_rtx ();
+             deferred_plabels[i].name = obstack_alloc (&permanent_obstack,
+                                                       strlen (name) + 1);
+             strcpy (deferred_plabels[i].name, name);
+
+             /* Switch back to normal obstack allocation.  */
+             current_obstack = ambient_obstack;
+             rtl_obstack = ambient_rtl_obstack;
+
+             /* Gross.  We have just implicitly taken the address of this
+                function, mark it as such.  */
+             STRIP_NAME_ENCODING (real_name, name);
+             TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1;
+           }
 
-         xoperands[0] = gen_label_rtx ();
-         xoperands[1] = gen_label_rtx ();
-         output_asm_insn ("addil LT%%%0,%%r19", xoperands);
-         output_asm_insn ("ldw RT%%%0(%%r1),%%r22", xoperands);
-         output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands);
+         /* We have to load the address of the function using a procedure
+            label (plabel).  Inline plabels can lose for PIC and other
+            cases, so avoid them by creating a 32bit plabel in the data
+            segment.  */
+         if (flag_pic)
+           {
+             xoperands[0] = deferred_plabels[i].internal_label;
+             xoperands[1] = gen_label_rtx ();
 
-         if (deferred_plabels == 0)
-           deferred_plabels = (struct defer_plab *)
-             xmalloc (1 * sizeof (struct defer_plab));
-         else
-           deferred_plabels = (struct defer_plab *)
-             xrealloc (deferred_plabels,
-                       (n_deferred_plabels + 1) * sizeof (struct defer_plab));
-         deferred_plabels[n_deferred_plabels].internal_label = xoperands[0];
-         deferred_plabels[n_deferred_plabels].symbol = call_dest;
-         n_deferred_plabels++;
+             output_asm_insn ("addil LT%%%0,%%r19", xoperands);
+             output_asm_insn ("ldw RT%%%0(%%r1),%%r22", xoperands);
+             output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands);
 
-         /* Get our address + 8 into %r1.  */
-         output_asm_insn ("bl .+8,%%r1", xoperands);
+             /* Get our address + 8 into %r1.  */
+             output_asm_insn ("bl .+8,%%r1", xoperands);
 
-         /* Add %r1 to the offset of dyncall from the next insn.  */
-         output_asm_insn ("addil L%%$$dyncall-%1,%%r1", xoperands);
-         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
-                                    CODE_LABEL_NUMBER (xoperands[1]));
-         output_asm_insn ("ldo R%%$$dyncall-%1(%%r1),%%r1", xoperands);
+             /* Add %r1 to the offset of dyncall from the next insn.  */
+             output_asm_insn ("addil L%%$$dyncall-%1,%%r1", xoperands);
+             ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+                                        CODE_LABEL_NUMBER (xoperands[1]));
+             output_asm_insn ("ldo R%%$$dyncall-%1(%%r1),%%r1", xoperands);
 
-         /* Get the return address into %r31.  */
-         output_asm_insn ("blr 0,%%r31", xoperands);
+             /* Get the return address into %r31.  */
+             output_asm_insn ("blr 0,%%r31", xoperands);
 
-         /* Branch to our target which is in %r1.  */
-         output_asm_insn ("bv 0(%%r1)", xoperands);
+             /* Branch to our target which is in %r1.  */
+             output_asm_insn ("bv 0(%%r1)", xoperands);
 
-         /* Copy the return address into %r2 also.  */
-         output_asm_insn ("copy %%r31,%%r2", xoperands);
-       }
-      else
-       {
-         /* No PIC stuff to worry about.  We can use ldil;ble.  */
-         xoperands[0] = call_dest;
+             /* Copy the return address into %r2 also.  */
+             output_asm_insn ("copy %%r31,%%r2", xoperands);
+           }
+         else
+           {
+             xoperands[0] = deferred_plabels[i].internal_label;
 
-         /*  Get the address of our target into %r22.  */
-         output_asm_insn ("ldil LP%%%0,%%r22", xoperands);
-         output_asm_insn ("ldo RP%%%0(%%r22),%%r22", xoperands);
+             /* Get the address of our target into %r22.  */
+             output_asm_insn ("addil LR%%%0-$global$,%%r27", xoperands);
+             output_asm_insn ("ldw RR%%%0-$global$(%%r1),%%r22", xoperands);
 
-         /* Get the high part of the  address of $dyncall into %r2, then
-            add in the low part in the branch instruction.  */
-         output_asm_insn ("ldil L%%$$dyncall,%%r2", xoperands);
-         output_asm_insn ("ble  R%%$$dyncall(%%sr4,%%r2)", xoperands);
+             /* Get the high part of the  address of $dyncall into %r2, then
+                add in the low part in the branch instruction.  */
+             output_asm_insn ("ldil L%%$$dyncall,%%r2", xoperands);
+             output_asm_insn ("ble  R%%$$dyncall(%%sr4,%%r2)", xoperands);
 
-         /* Copy the return pointer into both %r31 and %r2.  */
-         output_asm_insn ("copy %%r31,%%r2", xoperands);
+             /* Copy the return pointer into both %r31 and %r2.  */
+             output_asm_insn ("copy %%r31,%%r2", xoperands);
+           }
        }
 
       /* If we had a jump in the call's delay slot, output it now.  */
@@ -5244,9 +5294,6 @@ output_call (insn, call_dest)
   return "";
 }
 
-extern struct obstack permanent_obstack;
-extern struct obstack *saveable_obstack;
-
 /* In HPUX 8.0's shared library scheme, special relocations are needed
    for function labels if they might be passed to a function
    in a shared library (because shared libraries don't live in code
index 8f838895d67b0d1cd52cad7fc4d7e1b86508a723..25e8d547a051c0ab2c6d14afb7c203855adae97b 100644 (file)
@@ -1376,7 +1376,7 @@ extern struct rtx_def *hppa_builtin_saveregs ();
 #define LEGITIMATE_CONSTANT_P(X)               \
   ((GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT        \
     || (X) == CONST0_RTX (GET_MODE (X)))       \
-   && !(flag_pic && function_label_operand (X, VOIDmode)))
+   && !function_label_operand (X, VOIDmode))
 
 /* Subroutine for EXTRA_CONSTRAINT.
 
@@ -1931,6 +1931,8 @@ do { fputs ("\t.SPACE $PRIVATE$\n\
        output_file_directive ((FILE), main_input_filename); \
    } while (0)
 
+#define ASM_FILE_END(FILE) output_deferred_plabels (FILE)
+
 /* Output to assembler file text saying following lines
    may contain character constants, extra white space, comments, etc.  */
 
index e0d599683a5407135f9b30216eae0c3477a3b626..9a4165c6fff758ca5fb567f33acc0188f6af5bcc 100644 (file)
   [(set_attr "type" "binary,binary")
    (set_attr "length" "4,8")])
 
-;; For function addresses.
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (high:SI (match_operand:SI 1 "function_label_operand" "")))]
-  "!TARGET_PORTABLE_RUNTIME"
-  "ldil LP'%G1,%0"
-  [(set_attr "type" "move")
-   (set_attr "length" "4")])
-
-;; This version is used only for the portable runtime conventions model
-;; (it does not use/support plabels)
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (high:SI (match_operand:SI 1 "function_label_operand" "")))]
-  "TARGET_PORTABLE_RUNTIME"
-  "ldil L'%G1,%0"
-  [(set_attr "type" "move")
-   (set_attr "length" "4")])
-
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
        (high:SI (match_operand 1 "" "")))]
   [(set_attr "type" "move")
    (set_attr "length" "4")])
 
-;; lo_sum of a function address.
-;;
-;; Note since we are not supporting MPE style external calls we can
-;; use the short ldil;ldo sequence.  If one wanted to support
-;; MPE external calls you would want to generate something like
-;; ldil;ldo;extru;ldw;add.  See the HP compiler's output for details.
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
-                  (match_operand:SI 2 "function_label_operand" "")))]
-  "!TARGET_PORTABLE_RUNTIME"
-  "ldo RP'%G2(%1),%0"
-  [(set_attr "type" "move")
-   (set_attr "length" "4")])
-
-;; This version is used only for the portable runtime conventions model
-;; (it does not use/support plabels)
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
-                  (match_operand:SI 2 "function_label_operand" "")))]
-  "TARGET_PORTABLE_RUNTIME"
-  "ldo R'%G2(%1),%0"
-  [(set_attr "type" "move")
-   (set_attr "length" "4")])
-
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
        (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
            (const_int 12)
            (const_int 16))))))])
 
-;; Simply another variant of the dbra pattern.  More restrictive
-;; in testing the comparison operator as it must worry about overflow
-;; problems.
-(define_insn ""
-  [(set (pc)
-       (if_then_else
-         (match_operator 2 "eq_neq_comparison_operator"
-          [(match_operand:SI 0 "register_operand" "+!r,!*f,!*m")
-           (match_operand:SI 5 "const_int_operand" "")])
-         (label_ref (match_operand 3 "" ""))
-         (pc)))
-   (set (match_dup 0)
-       (plus:SI (match_dup 0) (match_operand:SI 1 "int5_operand" "L,L,L")))
-   (clobber (match_scratch:SI 4 "=X,r,r"))]
-  "INTVAL (operands[5]) == - INTVAL (operands[1])"
-"* return output_dbra (operands, insn, which_alternative);"
-;; Do not expect to understand this the first time through.
-[(set_attr "type" "cbranch,multi,multi")
- (set (attr "length")
-      (if_then_else (eq_attr "alternative" "0")
-;; Loop counter in register case
-;; Short branch has length of 4
-;; Long branch has length of 8
-       (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                     (const_int 8184))
-           (const_int 4)
-          (const_int 8))
-
-;; Loop counter in FP reg case.
-;; Extra goo to deal with additional reload insns.
-       (if_then_else (eq_attr "alternative" "1")
-         (if_then_else (lt (match_dup 3) (pc))
-           (if_then_else
-             (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24))))
-                 (const_int 8184))
-             (const_int 24)
-             (const_int 28))
-           (if_then_else
-             (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                 (const_int 8184))
-             (const_int 24)
-             (const_int 28)))
-;; Loop counter in memory case.
-;; Extra goo to deal with additional reload insns.
-       (if_then_else (lt (match_dup 3) (pc))
-         (if_then_else
-           (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
-               (const_int 8184))
-           (const_int 12)
-           (const_int 16))
-         (if_then_else
-           (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-               (const_int 8184))
-           (const_int 12)
-           (const_int 16))))))])
-
 (define_insn ""
   [(set (pc)
        (if_then_else