This patch adds absolute jump table support for rs6000.
authorHaochen Gui <guihaoc@gcc.gnu.org>
Thu, 26 Nov 2020 06:23:45 +0000 (14:23 +0800)
committerHaochen Gui <guihaoc@gcc.gnu.org>
Fri, 27 Nov 2020 01:11:20 +0000 (09:11 +0800)
gcc/ChangeLog:

* config/rs6000/rs6000-protos.h (rs6000_output_addr_vec_elt): Declare.
* config/rs6000/rs6000.c (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC):
Define.
(rs6000_gen_pic_addr_diff_vec, rs6000_output_addr_vec_elt): Implement.
* config/rs6000/rs6000.h (CASE_VECTOR_PC_RELATIVE,
CASE_VECTOR_MODE, ASM_OUTPUT_ADDR_VEC_ELT): Define.
* config/rs6000/rs6000.md (tablejump<mode>_absolute,
tablejump<mode>_absolute_nospec): New expanders.
* config/rs6000/rs6000.opt (mrelative-jumptables): New.

gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/rs6000.opt

index 25fa5dd..49ab510 100644 (file)
@@ -155,6 +155,7 @@ extern void rs6000_split_logical (rtx [], enum rtx_code, bool, bool, bool);
 extern bool rs6000_function_pcrel_p (struct function *);
 extern bool rs6000_pcrel_p (void);
 extern bool rs6000_fndecl_pcrel_p (const_tree);
+extern void rs6000_output_addr_vec_elt (FILE *, int);
 
 /* Different PowerPC instruction formats that are used by GCC.  There are
    various other instruction formats used by the PowerPC hardware, but these
index 50261b3..a4979db 100644 (file)
@@ -1367,6 +1367,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA rs6000_output_addr_const_extra
 
+#undef  TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC
+#define TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC rs6000_gen_pic_addr_diff_vec
+
 #undef TARGET_LEGITIMIZE_ADDRESS
 #define TARGET_LEGITIMIZE_ADDRESS rs6000_legitimize_address
 
@@ -27279,6 +27282,26 @@ rs6000_emit_xxspltidp_v2df (rtx dst, long value)
   emit_insn( gen_xxspltidp_v2df_inst (dst, GEN_INT (value)));
 }
 
+/* Implement TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC.  */
+
+static bool
+rs6000_gen_pic_addr_diff_vec (void)
+{
+  return rs6000_relative_jumptables;
+}
+
+void
+rs6000_output_addr_vec_elt (FILE *file, int value)
+{
+  const char *directive = TARGET_64BIT ? DOUBLE_INT_ASM_OP : "\t.long\t";
+  char buf[100];
+
+  fprintf (file, "%s", directive);
+  ASM_GENERATE_INTERNAL_LABEL (buf, "L", value);
+  assemble_name (file, buf);
+  fprintf (file, "\n");
+}
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-rs6000.h"
index f35aaf4..5bf9c83 100644 (file)
@@ -1756,15 +1756,15 @@ typedef struct rs6000_args
 
 /* #define LEGITIMATE_PIC_OPERAND_P (X) */
 \f
-/* Specify the machine mode that this machine uses
-   for the index in the tablejump instruction.  */
-#define CASE_VECTOR_MODE SImode
-
 /* Define as C expression which evaluates to nonzero 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 1
+#define CASE_VECTOR_PC_RELATIVE rs6000_relative_jumptables
+
+/* Specify the machine mode that this machine uses
+   for the index in the tablejump instruction.  */
+#define CASE_VECTOR_MODE (rs6000_relative_jumptables ? SImode : Pmode)
 
 /* Define this as 1 if `char' should by default be signed; else as 0.  */
 #define DEFAULT_SIGNED_CHAR 0
@@ -2194,6 +2194,11 @@ extern char rs6000_reg_names[][8];       /* register names (0 vs. %r0).  */
        putc ('\n', FILE);                              \
      } while (0)
 
+/* This is how to output an element of a case-vector
+   that is non-relative.  */
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+  rs6000_output_addr_vec_elt ((FILE), (VALUE))
+
 /* This is how to output an assembler line
    that says to advance the location counter
    to a multiple of 2**LOG bytes.  */
index 0e79919..b89990f 100644 (file)
   ""
 {
   if (rs6000_speculate_indirect_jumps)
-    emit_jump_insn (gen_tablejump_normal (Pmode, operands[0], operands[1]));
+    {
+      if (rs6000_relative_jumptables)
+       emit_jump_insn (gen_tablejump_normal (Pmode, operands[0], operands[1]));
+      else
+       emit_jump_insn (gen_tablejump_absolute (Pmode, operands[0],
+                                               operands[1]));
+    }
   else
     {
       rtx ccreg = gen_reg_rtx (CCmode);
       rtx jump;
-      if (TARGET_32BIT)
-       jump = gen_tablejumpsi_nospec (operands[0], operands[1], ccreg);
+      if (rs6000_relative_jumptables)
+       jump = gen_tablejump_nospec (Pmode, operands[0], operands[1], ccreg);
       else
-       jump = gen_tablejumpdi_nospec (operands[0], operands[1], ccreg);
+       jump = gen_tablejump_absolute_nospec (Pmode, operands[0], operands[1],
+                                             ccreg);
       emit_jump_insn (jump);
     }
   DONE;
 (define_expand "@tablejump<mode>_normal"
   [(use (match_operand:SI 0))
    (use (match_operand:P 1))]
-  "rs6000_speculate_indirect_jumps"
+  "rs6000_speculate_indirect_jumps && rs6000_relative_jumptables"
 {
   rtx off = force_reg (SImode, operands[0]);
   if (<MODE>mode != SImode)
   DONE;
 })
 
+(define_expand "@tablejump<mode>_absolute"
+  [(use (match_operand:P 0))
+   (use (match_operand:P 1))]
+  "rs6000_speculate_indirect_jumps && !rs6000_relative_jumptables"
+{
+  rtx addr = gen_reg_rtx (Pmode);
+  emit_move_insn (addr, operands[0]);
+
+  emit_jump_insn (gen_tablejump_insn_normal (Pmode, addr, operands[1]));
+  DONE;
+})
+
 (define_expand "@tablejump<mode>_nospec"
   [(use (match_operand:SI 0))
    (use (match_operand:P 1))
    (use (match_operand:CC 2))]
-  "!rs6000_speculate_indirect_jumps"
+  "!rs6000_speculate_indirect_jumps && rs6000_relative_jumptables"
 {
   rtx off = force_reg (SImode, operands[0]);
   if (<MODE>mode != SImode)
   DONE;
 })
 
+(define_expand "@tablejump<mode>_absolute_nospec"
+  [(use (match_operand:P 0))
+   (use (match_operand:P 1))
+   (use (match_operand:CC 2))]
+  "!rs6000_speculate_indirect_jumps && !rs6000_relative_jumptables"
+{
+  rtx addr = gen_reg_rtx (Pmode);
+  emit_move_insn (addr, operands[0]);
+
+  emit_jump_insn (gen_tablejump_insn_nospec (Pmode, addr, operands[1],
+                                            operands[2]));
+  DONE;
+})
+
 (define_insn "@tablejump<mode>_insn_normal"
   [(set (pc)
        (match_operand:P 0 "register_operand" "c,*l"))
index b2a70e8..2888172 100644 (file)
@@ -589,3 +589,6 @@ Generate (do not generate) pc-relative memory addressing.
 mmma
 Target Report Mask(MMA) Var(rs6000_isa_flags)
 Generate (do not generate) MMA instructions.
+
+mrelative-jumptables
+Target Undocumented Var(rs6000_relative_jumptables) Init(1) Save