Hi Segher,

    Thanks for your advice. I removed macros defined in linux64.h and linux.h. So they take relative jump tables by default. When no-relative-jumptables is set, the absolute jump tables are taken. All things relevant to section relocations are put in another patch. Thanks again.


On 8/9/2020 上午 5:46, Segher Boessenkool wrote:
On Mon, Aug 24, 2020 at 03:48:43PM +0800, HAO CHEN GUI wrote:
I'll try to be quicker at reviewing iterations of this -- there is quite
some way to go, without me slowing things down!
Sigh :-(

        * config/rs6000/linux.h (rs6000_relative_jumptables): Define.
That macro looks like it is variable (or function).  *Make* it a
variable, please?

        * config/rs6000/rs6000.c (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC):
        Define
Period?

        (rs6000_gen_pic_addr_diff_vec, rs6000_output_addr_vec_elt): Implement.
"New function."

        * config/rs6000/rs6000.md (absolute_tablejumpsi,
        absolute_tablejumpsi_nospec, absolute_tablejumpdi,
        absolute_tablejumpdi_nospec): Add four new expansions.
"New define_expands." or "New expanders."

        * config/rs6000/rs6000.opt (mrelative-jumptables): Add a new option and
        set rs6000_relative_jumptables to true by default.
"rs6000.opt: Add -mrelative-jumptables."

+/* Disable relative jump tables for Power Linux.  */
+#undef rs6000_relative_jumptables
+#define rs6000_relative_jumptables 0
Why?

+/* Disable relative jump tables for Power Linux64.  */
+#undef rs6000_relative_jumptables
+#define rs6000_relative_jumptables 0
(That's not what it's called...  Just don't say the "for..." at all?
It is clear from what file it is in.)

  /* Indicate that jump tables go in the text section.  */
  #undef  JUMP_TABLES_IN_TEXT_SECTION
-#define JUMP_TABLES_IN_TEXT_SECTION TARGET_64BIT
+#define JUMP_TABLES_IN_TEXT_SECTION rs6000_relative_jumptables
Not sure that is correct.  Maybe the patch using rodata (.data.rel.ro)
should be a separate patch?

  /* 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 0
This should depend on the new flag?

+/* Specify the machine mode that this machine uses
+   for the index in the tablejump instruction.  */
+#define CASE_VECTOR_MODE \
+  (TARGET_32BIT || rs6000_relative_jumptables ? SImode : DImode)
rs6000_relative_jumptables ? SImode : Pmode;

+      if (rs6000_relative_jumptables)
+       {
+         if (TARGET_32BIT)
+           emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
+         else
+           emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
+       }
Hrm, I guess we should make that a parameterized name (future work,
don't do it now :-) )

+(define_expand "absolute_tablejumpsi"
Don't prefix names; it should start with "tablejump".


Segher
        * 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 (tablejumpsi_absolute,
        tablejumpsi_nospec_absolute, tablejumpdi_absolute,
        tablejumpdi_nospec_absolute): New expanders.
        * config/rs6000/rs6000.opt (mrelative-jumptables): Add
        mrelative-jumptables.
diff --git a/gcc/config/rs6000/rs6000-protos.h 
b/gcc/config/rs6000/rs6000-protos.h
index 5508484ba19..62564dd67f2 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -155,6 +155,8 @@ extern void rs6000_split_logical (rtx [], enum rtx_code, 
bool, bool, bool);
 extern bool rs6000_pcrel_p (struct function *);
 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
    formats are not currently used by GCC.  */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 58f5d780603..94d1e650b94 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1369,6 +1369,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
 
@@ -26494,6 +26497,27 @@ rs6000_cannot_substitute_mem_equiv_p (rtx mem)
   return false;
 }
 
+/* Implement TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC.
+   Return true if rs6000_relative_jumptables is set.  */
+
+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"
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 1209a33173e..6759ac0de11 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1752,15 +1752,16 @@ typedef struct rs6000_args
 
 /* #define LEGITIMATE_PIC_OPERAND_P (X) */
 
-/* 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 \
+  (TARGET_32BIT || rs6000_relative_jumptables ? SImode : Pmode)
 
 /* Define this as 1 if `char' should by default be signed; else as 0.  */
 #define DEFAULT_SIGNED_CHAR 0
@@ -2190,6 +2191,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.  */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 0aa5265d199..7381c4909c3 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -12668,19 +12668,35 @@
 {
   if (rs6000_speculate_indirect_jumps)
     {
-      if (TARGET_32BIT)
-       emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
+      if (rs6000_relative_jumptables)
+       {
+         if (TARGET_32BIT)
+           emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
+         else
+           emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
+       }
+      else if (TARGET_32BIT)
+       emit_jump_insn (gen_tablejumpsi_absolute (operands[0], operands[1]));
       else
-       emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
+       emit_jump_insn (gen_tablejumpdi_absolute (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)
+       {
+         if (TARGET_32BIT)
+           jump = gen_tablejumpsi_nospec (operands[0], operands[1], ccreg);
+         else
+           jump = gen_tablejumpdi_nospec (operands[0], operands[1], ccreg);
+       }
+      else if (TARGET_32BIT)
+       jump = gen_tablejumpsi_nospec_absolute (operands[0], operands[1],
+                                               ccreg);
       else
-       jump = gen_tablejumpdi_nospec (operands[0], operands[1], ccreg);
+       jump = gen_tablejumpdi_nospec_absolute (operands[0], operands[1],
+                                               ccreg);
       emit_jump_insn (jump);
     }
   DONE;
@@ -12693,13 +12709,26 @@
    (parallel [(set (pc)
                   (match_dup 3))
              (use (label_ref (match_operand 1)))])]
-  "TARGET_32BIT && rs6000_speculate_indirect_jumps"
+  "TARGET_32BIT && rs6000_speculate_indirect_jumps
+   && rs6000_relative_jumptables"
 {
   operands[0] = force_reg (SImode, operands[0]);
   operands[2] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1]));
   operands[3] = gen_reg_rtx (SImode);
 })
 
+(define_expand "tablejumpsi_absolute"
+  [(set (match_dup 2)
+       (match_operand:SI 0 "gpc_reg_operand" "r"))
+   (parallel [(set (pc)
+                  (match_dup 2))
+             (use (label_ref (match_operand 1)))])]
+   "TARGET_32BIT && rs6000_speculate_indirect_jumps
+    && !rs6000_relative_jumptables"
+{
+  operands[2] = gen_reg_rtx (SImode);
+})
+
 (define_expand "tablejumpsi_nospec"
   [(set (match_dup 4)
        (plus:SI (match_operand:SI 0)
@@ -12708,32 +12737,59 @@
                   (match_dup 4))
              (use (label_ref (match_operand 1)))
              (clobber (match_operand 2))])]
-  "TARGET_32BIT && !rs6000_speculate_indirect_jumps"
+  "TARGET_32BIT && !rs6000_speculate_indirect_jumps
+   && rs6000_relative_jumptables"
 {
   operands[0] = force_reg (SImode, operands[0]);
   operands[3] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1]));
   operands[4] = gen_reg_rtx (SImode);
 })
 
+(define_expand "tablejumpsi_nospec_absolute"
+  [(set (match_dup 3)
+       (match_operand:SI 0 "gpc_reg_operand" "r"))
+   (parallel [(set (pc)
+                  (match_dup 3))
+             (use (label_ref (match_operand 1)))
+             (clobber (match_operand 2))])]
+  "TARGET_32BIT && !rs6000_speculate_indirect_jumps
+   && !rs6000_relative_jumptables"
+{
+  operands[3] = gen_reg_rtx (SImode);
+})
+
 (define_expand "tablejumpdi"
   [(set (match_dup 4)
-        (sign_extend:DI (match_operand:SI 0 "lwa_operand")))
+       (sign_extend:DI (match_operand:SI 0 "lwa_operand")))
    (set (match_dup 3)
        (plus:DI (match_dup 4)
                 (match_dup 2)))
    (parallel [(set (pc)
                   (match_dup 3))
              (use (label_ref (match_operand 1)))])]
-  "TARGET_64BIT && rs6000_speculate_indirect_jumps"
+  "TARGET_64BIT && rs6000_speculate_indirect_jumps
+   && rs6000_relative_jumptables"
 {
   operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1]));
   operands[3] = gen_reg_rtx (DImode);
   operands[4] = gen_reg_rtx (DImode);
 })
 
+(define_expand "tablejumpdi_absolute"
+  [(set (match_dup 2)
+       (match_operand:DI 0 "gpc_reg_operand" "r"))
+   (parallel [(set (pc)
+                  (match_dup 2))
+             (use (label_ref (match_operand 1)))])]
+   "TARGET_64BIT && rs6000_speculate_indirect_jumps
+    && !rs6000_relative_jumptables"
+{
+  operands[2] = gen_reg_rtx (DImode);
+})
+
 (define_expand "tablejumpdi_nospec"
   [(set (match_dup 5)
-        (sign_extend:DI (match_operand:SI 0 "lwa_operand")))
+       (sign_extend:DI (match_operand:SI 0 "lwa_operand")))
    (set (match_dup 4)
        (plus:DI (match_dup 5)
                 (match_dup 3)))
@@ -12741,13 +12797,27 @@
                   (match_dup 4))
              (use (label_ref (match_operand 1)))
              (clobber (match_operand 2))])]
-  "TARGET_64BIT && !rs6000_speculate_indirect_jumps"
+  "TARGET_64BIT && !rs6000_speculate_indirect_jumps
+   && rs6000_relative_jumptables"
 {
   operands[3] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1]));
   operands[4] = gen_reg_rtx (DImode);
   operands[5] = gen_reg_rtx (DImode);
 })
 
+(define_expand "tablejumpdi_nospec_absolute"
+  [(set (match_dup 3)
+       (match_operand:DI 0 "gpc_reg_operand" "r"))
+   (parallel [(set (pc)
+                  (match_dup 3))
+             (use (label_ref (match_operand 1)))
+             (clobber (match_operand 2))])]
+  "TARGET_64BIT && !rs6000_speculate_indirect_jumps
+   && !rs6000_relative_jumptables"
+{
+  operands[3] = gen_reg_rtx (DImode);
+})
+
 (define_insn "*tablejump<mode>_internal1"
   [(set (pc)
        (match_operand:P 0 "register_operand" "c,*l"))
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index f95b8279270..7cf8bdb1faa 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -578,3 +578,6 @@ Generate (do not generate) prefixed memory instructions.
 mpcrel
 Target Report Mask(PCREL) Var(rs6000_isa_flags)
 Generate (do not generate) pc-relative memory addressing.
+
+mrelative-jumptables
+Target Undocumented Var(rs6000_relative_jumptables) Init(1) Save

Reply via email to