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 25fa5dd57cd2a771dfdb5b50c638e03567099b3c..49ab51042c55334349189c33e4594d7e56925f06 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 50261b3ad7f70afbce21aab357832f81178c18f9..a4979dbdd42391798d7669ffb3b5bc07db43ff3b 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 f35aaf4ffd12df834284227d4e3ac8ef396acac4..5bf9c83fc1ec724ec1f3e3579c62298a99cbbbe5 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 0e799198a50cc4f92060aa1c81079cc4850518ae..b89990f46bf142edca8102ba1b552ccefce77b7b 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 b2a70e88ca8ff057bda03e79d219b0a4d7911edf..2888172cb27334090dcebffb1732895be1c487bb 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