pa.c (pa_reorg): If TARGET_BIG_SWITCH, then do not explode ADDR_VEC insns.
authorJeff Law <law@gcc.gnu.org>
Fri, 25 Jul 1997 17:02:37 +0000 (11:02 -0600)
committerJeff Law <law@gcc.gnu.org>
Fri, 25 Jul 1997 17:02:37 +0000 (11:02 -0600)
        * pa.c (pa_reorg): If TARGET_BIG_SWITCH, then do not explode
        ADDR_VEC insns.  Slightly rework code which explodes ADDR_VEC
        insns.
        * pa.h (TARGET_BIG_SWITCH): Define.
        (TARGET_SWITCHES): Add "big-switch" and "no-big-switch".
        (CASE_VECTOR_MODE): Use TI or DI depending on TARGET_BIG_SWITCH.
        (CASE_DROPS_THROUGH): Remove definition.
        (ASM_OUTPUT_ADDR_VEC_ELT): Rewrite to handle TARGET_BIG_SWITCH.
        (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
        * pa.md (casesi): Rework to avoid some potential long branch
        problems (also makes generated code faster!).  Handle
        TARGET_BIG_SWITCH.
        (casesi0): Corresponding changes.

From-SVN: r14528

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

index 5297cad7b46c702913dde5503132f53a58639c82..db6c4957489a699bccbe31df40ea446d0cd0f695 100644 (file)
@@ -5807,7 +5807,7 @@ pa_reorg (insns)
   pa_combine_instructions (get_insns ());
 
   /* This is fairly cheap, so always run it if optimizing.  */
-  if (optimize > 0)
+  if (optimize > 0 && !TARGET_BIG_SWITCH)
     {
       /* Find and explode all ADDR_VEC insns.  */
       insns = get_insns ();
@@ -5831,28 +5831,33 @@ pa_reorg (insns)
 
          for (i = 0; i < length; i++)
            {
+             /* Emit a label before each jump to keep jump.c from
+                removing this code.  */
+             tmp = gen_label_rtx ();
+             LABEL_NUSES (tmp) = 1;
+             emit_label_after (tmp, location);
+             location = NEXT_INSN (location);
+
              /* 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);
              LABEL_NUSES (JUMP_LABEL (tmp))++;
+             location = NEXT_INSN (location);
 
              /* 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);
            }
 
          /* If needed, emit marker for the end of the branch table.  */
          if (TARGET_GAS)
-           emit_insn_before (gen_end_brtab (), location);
+           {
+             emit_insn_before (gen_end_brtab (), location);
+             location = NEXT_INSN (location);
+             emit_barrier_after (location);
+           }
+
          /* Delete the ADDR_VEC.  */
          delete_insn (insn);
        }
index 7855904b4961e12268d61d06ab8de5a310c9490f..daf63c7e24d0641ff24eb459befde053145cd622 100644 (file)
@@ -112,6 +112,10 @@ extern int target_flags;
 /* Use a faster sequence for indirect calls.  */
 #define TARGET_FAST_INDIRECT_CALLS (target_flags & 1024)
 
+/* Generate code with big switch statements to avoid out of range branches
+   occuring within the switch table.  */
+#define TARGET_BIG_SWITCH (target_flags & 2048)
+
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
    each pair being { "NAME", VALUE }
@@ -143,6 +147,8 @@ extern int target_flags;
    {"no-long-load-store", -512},\
    {"fast-indirect-calls", 1024},\
    {"no-fast-indirect-calls", -1024},\
+   {"big-switch", 2048},       \
+   {"no-big-switch", -2048},   \
    {"linker-opt", 0},          \
    { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
 
@@ -1677,14 +1683,8 @@ while (0)
 
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
-#define CASE_VECTOR_MODE DImode
-
-/* Define this if the tablejump instruction expects the table
-   to contain offsets from the address of the table.
-   Do not define this if the table should contain absolute addresses.  */
-/* #define CASE_VECTOR_PC_RELATIVE */
+#define CASE_VECTOR_MODE (TARGET_BIG_SWITCH ? TImode : DImode)
 
-#define CASE_DROPS_THROUGH
 /* Specify the tree operation to be used to convert reals to integers.  */
 #define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
 
@@ -2205,7 +2205,10 @@ DTORS_SECTION_FUNCTION
    impossible.  */
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
-  fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
+  if (TARGET_BIG_SWITCH)                                       \
+    fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldil LR'L$%04d,%%r1\n\tbe RR'L$%04d(%%sr4,%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE, VALUE);         \
+  else                                                         \
+    fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
 
 /* Jump tables are executable code and live in the TEXT section on the PA.  */
 #define JUMP_TABLES_IN_TEXT_SECTION
@@ -2218,7 +2221,10 @@ DTORS_SECTION_FUNCTION
    rather than a table of absolute addresses.  */
 
 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
-  fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
+  if (TARGET_BIG_SWITCH)                                       \
+    fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldw T'L$%04d(%%r19),%%r1\n\tbv 0(%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE);                         \
+  else                                                         \
+    fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
 
 /* This is how to output an assembler line
    that says to advance the location counter
index 35519740ba439031bb924cbe20f93cbc2f92bea8..848567a5175f65ac2835ff48faa011d287bc55d7 100644 (file)
       operands[0] = reg;
     }
 
-  if (!INT_11_BITS (operands[2]))
+  if (!INT_5_BITS (operands[2]))
     operands[2] = force_reg (SImode, operands[2]);
 
-  emit_jump_insn (gen_casesi0 (operands[0], operands[2],
-                              operands[3], operands[4]));
+  emit_insn (gen_cmpsi (operands[0], operands[2]));
+  emit_jump_insn (gen_bgtu (operands[4]));
+  if (TARGET_BIG_SWITCH)
+    {
+      rtx temp = gen_reg_rtx (SImode);
+      emit_move_insn (temp, gen_rtx (PLUS, SImode, operands[0], operands[0]));
+      operands[0] = temp;
+    }
+  emit_jump_insn (gen_casesi0 (operands[0], operands[3]));
   DONE;
 }")
 
 (define_insn "casesi0"
-  [(set (pc)
-       (if_then_else (leu (match_operand:SI 0 "register_operand" "r")
-                          (match_operand:SI 1 "arith11_operand" "rI"))
-                     (plus:SI (mem:SI (plus:SI (pc) (match_dup 0)))
-                              (label_ref (match_operand 2 "" "")))
-                     (pc)))
-   (use (label_ref (match_operand 3 "" "")))]
+  [(set (pc) (plus:SI
+              (mem:SI (plus:SI (pc) (match_operand 0 "register_operand" "r")))
+              (label_ref (match_operand 1 "" ""))))]
   ""
-  "*
-{
-  if (GET_CODE (operands[1]) == CONST_INT)
-    {
-      operands[1] = GEN_INT (~INTVAL (operands[1]));
-      return \"addi,uv %1,%0,0\;blr,n %0,0\;b,n %l3\";
-    }
-  else
-    {
-      return \"sub,>> %0,%1,0\;blr,n %0,0\;b,n %l3\";
-    }
-}"
+  "blr %0,0\;nop"
   [(set_attr "type" "multi")
-   (set_attr "length" "12")])
+   (set_attr "length" "8")])
 
 ;; Need nops for the calls because execution is supposed to continue
 ;; past; we don't want to nullify an instruction that we need.