pa.h (MACHINE_DEPENDENT_REORG): Define.
authorJeff Law <law@gcc.gnu.org>
Fri, 7 Apr 1995 04:56:45 +0000 (22:56 -0600)
committerJeff Law <law@gcc.gnu.org>
Fri, 7 Apr 1995 04:56:45 +0000 (22:56 -0600)
* pa.h (MACHINE_DEPENDENT_REORG): Define.
* pa.md (switch_jump): New pattern for jumps which implement
a switch table.
* pa.c (pa_reorg): New function to explode jump tables.
(pa_adjust_insn_length): Account for jumps in switch tables with
unfilled delay slots.

From-SVN: r9318

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

index a164cd0..6d6a165 100644 (file)
@@ -2759,6 +2759,12 @@ pa_adjust_insn_length (insn, length)
       else
        return 0;
     }
+  /* Jumps inside switch tables which have unfilled delay slots 
+     also need adjustment.  */
+  else if (GET_CODE (insn) == JUMP_INSN
+          && simplejump_p (insn)
+          && GET_MODE (PATTERN (insn)) == DImode)
+    return 4;
   /* Millicode insn with an unfilled delay slot.  */
   else if (GET_CODE (insn) == INSN
           && GET_CODE (pat) != SEQUENCE
@@ -4392,3 +4398,77 @@ jump_in_call_delay (insn)
   else
     return 0;
 }
+
+
+/* We use this hook to perform a PA specific optimization which is difficult
+   to do in earlier passes.
+
+   We want the delay slots of branches within jump tables to be filled.
+   None of the compiler passes at the moment even has the notion that a
+   PA jump table doesn't contain addresses, but instead contains actual
+   instructions!
+
+   Because we actually jump into the table, the addresses of each entry
+   must stay contant in relation to the beginning of the table (which
+   itself must stay constant relative to the instruction to jump into
+   it).  I don't believe we can guarantee earlier passes of the compiler
+   will adhere to those rules.
+
+   So, late in the compilation process we find all the jump tables, and
+   expand them into real code -- eg each entry in the jump table vector
+   will get an appropriate label followed by a jump to the final target.
+
+   Reorg and the final jump pass can then optimize these branches and
+   fill their delay slots.  We end up with smaller, more efficient code.
+
+   The jump instructions within the table are special; we must be able 
+   to identify them during assembly output (if the jumps don't get filled
+   we need to emit a nop rather than nullifying the delay slot)).  We
+   identify jumps in switch tables by marking the SET with DImode.  */
+
+pa_reorg (insns)
+     rtx insns;
+{
+  rtx insn;
+
+  /* This is fairly cheap, so always run it if optimizing.  */
+  if (optimize > 0)
+    {
+      /* Find and explode all ADDR_VEC insns.  */
+      insns = get_insns ();
+      for (insn = insns; insn; insn = NEXT_INSN (insn))
+       {
+         rtx pattern, tmp, location;
+         unsigned int length, i;
+
+         /* Find an ADDR_VEC insn to explode.  */
+         if (GET_CODE (insn) != JUMP_INSN
+             || GET_CODE (PATTERN (insn)) != ADDR_VEC)
+           continue;
+
+         pattern = PATTERN (insn);
+         location = PREV_INSN (insn);
+          length = XVECLEN (pattern, 0);
+         for (i = 0; i < length; i++)
+           {
+             /* Emit the jump itself.  */
+             tmp = gen_switch_jump (XEXP (XVECEXP (pattern, 0, i), 0));
+             tmp = emit_jump_insn_after (tmp, location);
+             JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0);
+
+             /* Emit a BARRIER after the jump.  */
+             location = NEXT_INSN (location);
+             emit_barrier_after (location);
+
+             /* Put a CODE_LABEL before each so jump.c does not optimize
+                the jumps away.  */
+             location = NEXT_INSN (location);
+             tmp = gen_label_rtx ();
+             LABEL_NUSES (tmp) = 1;
+             emit_label_after (tmp, location);
+             location = NEXT_INSN (location);
+           }
+         /* Delete the ADDR_VEC.  */
+         delete_insn (insn);
+       }
+    }
index 792af84..f6d8c83 100644 (file)
@@ -239,6 +239,9 @@ extern int target_flags;
 /* Show we can debug even without a frame pointer.  */
 #define CAN_DEBUG_WITHOUT_FP
 
+/* Machine dependent reorg pass.  */
+#define MACHINE_DEPENDENT_REORG(X) pa_reorg(X)
+
 /* Names to predefine in the preprocessor for this target machine.  */
 
 #define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -Dunix -D_HPUX_SOURCE -Dhp9000 -Dhp800 -Dspectrum -DREVARGV -Asystem(unix) -Asystem(bsd) -Acpu(hppa) -Amachine(hppa)"
index b01a504..ff80e61 100644 (file)
   ""
   [(set_attr "length" "0")])
 
+(define_insn "switch_jump"
+  [(set:DI (pc) (label_ref (match_operand 0 "" "")))]
+  ""
+  "bl %l0,0%#"
+  [(set_attr "type" "uncond_branch")
+   (set_attr "length" "4")])
+
 (define_insn "jump"
   [(set (pc) (label_ref (match_operand 0 "" "")))]
   ""