From 3493b0c32815faf003cbd18dd2c1ff30818f5770 Mon Sep 17 00:00:00 2001 From: Haochen Gui Date: Thu, 26 Nov 2020 14:23:45 +0800 Subject: [PATCH] This patch adds absolute jump table support for rs6000. 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_absolute, tablejump_absolute_nospec): New expanders. * config/rs6000/rs6000.opt (mrelative-jumptables): New. --- gcc/config/rs6000/rs6000-protos.h | 1 + gcc/config/rs6000/rs6000.c | 23 ++++++++++++++++++++ gcc/config/rs6000/rs6000.h | 15 ++++++++----- gcc/config/rs6000/rs6000.md | 45 +++++++++++++++++++++++++++++++++------ gcc/config/rs6000/rs6000.opt | 3 +++ 5 files changed, 76 insertions(+), 11 deletions(-) diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 25fa5dd..49ab510 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -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 diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 50261b3..a4979db 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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" diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index f35aaf4..5bf9c83 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1756,15 +1756,15 @@ 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 (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. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 0e79919..b89990f 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -12713,15 +12713,22 @@ "" { 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; @@ -12730,7 +12737,7 @@ (define_expand "@tablejump_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 != SImode) @@ -12748,11 +12755,23 @@ DONE; }) +(define_expand "@tablejump_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_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 != SImode) @@ -12771,6 +12790,20 @@ DONE; }) +(define_expand "@tablejump_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_insn_normal" [(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 b2a70e8..2888172 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -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 -- 2.7.4