diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc index 6c838d7afcc..3f453cda67e 100644 --- a/gcc/emit-rtl.cc +++ b/gcc/emit-rtl.cc @@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "gimple-ssa.h" #include "gimplify.h" +#include "bbitmap.h" struct target_rtl default_target_rtl; #if SWITCHABLE_TARGET @@ -6788,6 +6789,297 @@ gen_int_shift_amount (machine_mode, poly_int64 value) return gen_int_mode (value, shift_mode); } +namespace { +/* Helper class for expanding an rtx using the encoding generated by + genemit.cc. The code needs to be kept in sync with there. */ + +class rtx_expander +{ +public: + rtx_expander (const uint8_t *, rtx *); + + rtx get_rtx (); + rtvec get_rtvec (); + void expand_seq (); + +protected: + uint64_t get_uint (); + machine_mode get_mode () { return machine_mode (get_uint ()); } + char *get_string (); + rtx get_shared_operand (); + rtx get_unshared_operand (); + + rtx get_rtx (expand_opcode); + rtx get_rtx (rtx_code, machine_mode); + + /* Points to the first unread byte. */ + const uint8_t *m_seq; + + /* The operands passed to the gen_* function. */ + rtx *m_operands; + + /* A bitmap of operands that have already been used to replace a + MATCH_OPERAND or MATCH_DUP. In order to ensure correct sharing, + further replacements need to use a copy of the operand, rather than + the original rtx. */ + bbitmap m_used; +}; +} + +rtx_expander::rtx_expander (const uint8_t *seq, rtx *operands) + : m_seq (seq), m_operands (operands), m_used () +{} + +/* Read and return the next encoded "BEB128" integer. */ + +inline uint64_t +rtx_expander::get_uint () +{ + const uint8_t *seq = m_seq; + uint64_t res = 0; + do + res = (res << 7) | (*seq & 127); + while (*seq++ >= 128); + m_seq = seq; + return res; +} + +/* Read an operand number and return the associated operand rtx, + without copying it. */ + +rtx +rtx_expander::get_shared_operand () +{ + return m_operands[get_uint ()]; +} + +/* Read an operand number and return a correctly-shared instance of + the associated operand rtx. This can be either the original rtx + or a copy. */ + +rtx +rtx_expander::get_unshared_operand () +{ + auto opno = get_uint (); + auto mask = m_used.from_index (opno); + if (m_used & mask) + return copy_rtx (m_operands[opno]); + + m_used |= mask; + return m_operands[opno]; +} + +/* Read an encoded rtx. */ + +rtx +rtx_expander::get_rtx () +{ + auto FIRST_CODE = (unsigned) expand_opcode::FIRST_CODE; + auto opcode = get_uint (); + if (opcode < FIRST_CODE) + return get_rtx (expand_opcode (opcode)); + return get_rtx (rtx_code (opcode - FIRST_CODE), NUM_MACHINE_MODES); +} + +/* Read an encoded rtx that starts with the given opcode. */ + +rtx +rtx_expander::get_rtx (expand_opcode opcode) +{ + switch (opcode) + { + case expand_opcode::NO_RTX: + return NULL_RTX; + + case expand_opcode::MATCH_OPERAND: + return get_unshared_operand (); + + case expand_opcode::MATCH_OPERATOR_WITH_MODE: + { + auto mode = get_mode (); + auto op = get_shared_operand (); + return get_rtx (GET_CODE (op), mode); + } + + case expand_opcode::MATCH_OPERATOR: + { + auto op = get_shared_operand (); + return get_rtx (GET_CODE (op), GET_MODE (op)); + } + + case expand_opcode::MATCH_PARALLEL: + return get_shared_operand (); + + case expand_opcode::CLOBBER_REG: + { + auto mode = get_mode (); + auto regno = get_uint (); + return gen_hard_reg_clobber (mode, regno); + } + + case expand_opcode::FIRST_CODE: + break; + } + gcc_unreachable (); +} + +/* Read the rest of an rtx of code CODE. If such rtxes are not always + VOIDmode, MODE is the mode that the rtx should have, or NUM_MACHINE_MODES + if the mode is encoded at the current iterator position. */ + +rtx +rtx_expander::get_rtx (rtx_code code, machine_mode mode) +{ + switch (code) + { + /* Please keep the cases below in sync with gengenrtl.cc:special_rtx. */ + + case EXPR_LIST: + case INSN_LIST: + case INSN: + gcc_unreachable (); + + case CONST_INT: + return GEN_INT (get_uint ()); + + case REG: + if (mode == NUM_MACHINE_MODES) + mode = get_mode (); + return gen_rtx_REG (mode, get_uint ()); + + case SUBREG: + { + if (mode == NUM_MACHINE_MODES) + mode = get_mode (); + auto reg = get_rtx (); + auto byte = get_uint (); + return gen_rtx_SUBREG (mode, reg, byte); + } + + case MEM: + if (mode == NUM_MACHINE_MODES) + mode = get_mode (); + return gen_rtx_MEM (mode, get_rtx ()); + + case PC: + return pc_rtx; + + case RETURN: + return ret_rtx; + + case SIMPLE_RETURN: + return simple_return_rtx; + + case CONST_VECTOR: + if (mode == NUM_MACHINE_MODES) + mode = get_mode (); + return gen_rtx_CONST_VECTOR (mode, get_rtvec ()); + + /* Please keep the cases below in sync with + gengenrtl.cc:excluded_rtx. */ + + case VAR_LOCATION: + gcc_unreachable (); + + case CONST_DOUBLE: + /* genemit.cc only accepts zero const_doubles. */ + if (mode == NUM_MACHINE_MODES) + mode = get_mode (); + return CONST0_RTX (mode); + + case CONST_WIDE_INT: + case CONST_POLY_INT: + case CONST_FIXED: + gcc_unreachable (); + + default: + break; + } + + rtx x = rtx_alloc (code); + if (!always_void_p (code)) + { + if (mode == NUM_MACHINE_MODES) + mode = get_mode (); + PUT_MODE_RAW (x, mode); + } + + const char *fmt = GET_RTX_FORMAT (code); + for (unsigned int i = 0; fmt[i]; ++i) + switch (fmt[i]) + { + /* Please keep these cases in sync with + gengenrtl.cc:type_from_format. */ + + case 'i': + XINT (x, i) = get_uint (); + break; + + case 'L': + case 'w': + case 'p': + case 's': + gcc_unreachable (); + + case 'e': case 'u': + XEXP (x, i) = get_rtx (); + break; + + case 'E': + XVEC (x, i) = get_rtvec (); + break; + + case 't': + case 'B': + default: + gcc_unreachable (); + } + + return x; +} + +/* Read an encoded rtvec. */ + +rtvec +rtx_expander::get_rtvec () +{ + unsigned int len = get_uint (); + rtvec v = rtvec_alloc (len); + for (unsigned int i = 0; i < len; ++i) + RTVEC_ELT (v, i) = get_rtx (); + return v; +} + +/* Read and emit an encoded sequence of instructions. */ + +void +rtx_expander::expand_seq () +{ + unsigned int len = get_uint (); + for (unsigned int i = 0; i < len; ++i) + emit (get_rtx (), i < len - 1); +} + +/* Read an rtx from the bytecode in SEQ, which was generated by genemit.cc. + Replace operand placeholders with the values given in OPERANDS. */ + +rtx +expand_rtx (const uint8_t *seq, rtx *operands) +{ + return rtx_expander (seq, operands).get_rtx (); +} + +/* Read and emit a sequence of instructions from the bytecode in SEQ, + which was generated by genemit.cc. Replace operand placeholders with + the values given in OPERANDS. */ + +rtx_insn * +complete_seq (const uint8_t *seq, rtx *operands) +{ + rtx_expander (seq, operands).expand_seq (); + return end_sequence (); +} + /* Initialize fields of rtl_data related to stack alignment. */ void diff --git a/gcc/genemit.cc b/gcc/genemit.cc index 21eb0f2df7d..21eb212f6e0 100644 --- a/gcc/genemit.cc +++ b/gcc/genemit.cc @@ -57,178 +57,132 @@ static bool nofail_optabs[NUM_OPTABS]; /* A list of the md constructs that need a gen_* function. */ static vec queue; -static void -print_code (RTX_CODE code, FILE *file) -{ - const char *p1; - for (p1 = GET_RTX_NAME (code); *p1; p1++) - fprintf (file, "%c", TOUPPER (*p1)); -} +unsigned FIRST_CODE = (unsigned) expand_opcode::FIRST_CODE; /* A structure used to generate code for a particular expansion. */ struct generator { - generator (rtx_code, char *, const md_rtx_info &, FILE *); + generator (const md_rtx_info &info) : info (info) {} - void gen_rtx_scratch (rtx); - void gen_exp (rtx); - void gen_emit_seq (rtvec); + void add_uint (uint64_t); + void add_opcode (expand_opcode opcode) { add_uint ((unsigned) opcode); } + void add_code (rtx_code code) { add_uint (FIRST_CODE + (unsigned) code); } + void add_match_operator (machine_mode, int, rtvec); + void add_exp (rtx); + void add_vec (rtvec); - /* The type of subroutine that we're expanding. */ - rtx_code subroutine_type; - - /* Index N indicates that the original operand N has already been used to - replace a MATCH_OPERATOR or MATCH_DUP, and so any further replacements - must make a copy. */ - char *used; + const char *gen_table (FILE *, const char *); + const char *gen_exp (FILE *, rtx); + const char *gen_emit_seq (FILE *, rtvec); /* The construct that we're expanding. */ const md_rtx_info info; - /* The output file. */ - FILE *file; + /* Used to build up the encoding of the expanded rtx sequence. */ + auto_vec bytes; }; -generator::generator (rtx_code subroutine_type, char *used, - const md_rtx_info &info, FILE *file) - : subroutine_type (subroutine_type), - used (used), - info (info), - file (file) -{} +/* Add VALUE to the encoding using "BEB128" (big-endian version of LEB128). + This is slightly easier for the consumer. */ void -generator::gen_rtx_scratch (rtx x) +generator::add_uint (uint64_t value) { - if (subroutine_type == DEFINE_PEEPHOLE2) + int shift = 0; + while ((value >> shift >> 7) > 0) + shift += 7; + do { - fprintf (file, "operands[%d]", XINT (x, 0)); - } - else - { - fprintf (file, "gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); + bytes.safe_push (((value >> shift) & 127) | (shift > 0 ? 128 : 0)); + shift -= 7; } + while (shift >= 0); } -/* Print a C expression to construct an RTX just like X, - substituting any operand references appearing within. */ +/* Add the rtx expansion of a MATCH_OPERATOR or MATCH_OP_DUP. OPNO is the + number of the matched operand. MODE is the mode that the rtx should have, + or NUM_MACHINE_MODES if the operand's original mode should be retained. + VEC is the vector of suboperands, which replace those of the original + operand. */ void -generator::gen_exp (rtx x) +generator::add_match_operator (machine_mode mode, int opno, rtvec vec) { - RTX_CODE code; - int i; - int len; - const char *fmt; - const char *sep = ""; + if (mode != NUM_MACHINE_MODES) + { + add_opcode (expand_opcode::MATCH_OPERATOR_WITH_MODE); + add_uint (mode); + } + else + add_opcode (expand_opcode::MATCH_OPERATOR); + add_uint (opno); + for (int i = 0; i < GET_NUM_ELEM (vec); i++) + add_exp (RTVEC_ELT (vec, i)); +} +/* Add the expansion of X to the encoding. */ + +void +generator::add_exp (rtx x) +{ if (x == 0) { - fprintf (file, "NULL_RTX"); + add_opcode (expand_opcode::NO_RTX); return; } - code = GET_CODE (x); - + auto code = GET_CODE (x); switch (code) { case MATCH_OPERAND: case MATCH_DUP: - if (used[XINT (x, 0)]) - { - fprintf (file, "copy_rtx (operands[%d])", XINT (x, 0)); - return; - } - used[XINT (x, 0)] = 1; - fprintf (file, "operands[%d]", XINT (x, 0)); + add_opcode (expand_opcode::MATCH_OPERAND); + add_uint (XINT (x, 0)); return; case MATCH_OP_DUP: - fprintf (file, "gen_rtx_fmt_"); - for (i = 0; i < XVECLEN (x, 1); i++) - fprintf (file, "e"); - fprintf (file, " (GET_CODE (operands[%d]), ", XINT (x, 0)); if (GET_MODE (x) == VOIDmode) - fprintf (file, "GET_MODE (operands[%d])", XINT (x, 0)); + add_match_operator (NUM_MACHINE_MODES, XINT (x, 0), XVEC (x, 1)); else - fprintf (file, "%smode", GET_MODE_NAME (GET_MODE (x))); - for (i = 0; i < XVECLEN (x, 1); i++) - { - fprintf (file, ",\n\t\t"); - gen_exp (XVECEXP (x, 1, i)); - } - fprintf (file, ")"); + add_match_operator (GET_MODE (x), XINT (x, 0), XVEC (x, 1)); return; case MATCH_OPERATOR: - fprintf (file, "gen_rtx_fmt_"); - for (i = 0; i < XVECLEN (x, 2); i++) - fprintf (file, "e"); - fprintf (file, " (GET_CODE (operands[%d])", XINT (x, 0)); - fprintf (file, ", %smode", GET_MODE_NAME (GET_MODE (x))); - for (i = 0; i < XVECLEN (x, 2); i++) - { - fprintf (file, ",\n\t\t"); - gen_exp (XVECEXP (x, 2, i)); - } - fprintf (file, ")"); + add_match_operator (GET_MODE (x), XINT (x, 0), XVEC (x, 2)); return; case MATCH_PARALLEL: case MATCH_PAR_DUP: - fprintf (file, "operands[%d]", XINT (x, 0)); + add_opcode (expand_opcode::MATCH_PARALLEL); + add_uint (XINT (x, 0)); return; case MATCH_SCRATCH: - gen_rtx_scratch (x); + add_code (SCRATCH); + add_uint (GET_MODE (x)); return; - case PC: - fprintf (file, "pc_rtx"); - return; - case RETURN: - fprintf (file, "ret_rtx"); - return; - case SIMPLE_RETURN: - fprintf (file, "simple_return_rtx"); - return; case CLOBBER: if (REG_P (XEXP (x, 0))) { - fprintf (file, "gen_hard_reg_clobber (%smode, %i)", - GET_MODE_NAME (GET_MODE (XEXP (x, 0))), - REGNO (XEXP (x, 0))); + add_opcode (expand_opcode::CLOBBER_REG); + add_uint (GET_MODE (XEXP (x, 0))); + add_uint (REGNO (XEXP (x, 0))); return; } break; case CONST_INT: - if (INTVAL (x) == 0) - fprintf (file, "const0_rtx"); - else if (INTVAL (x) == 1) - fprintf (file, "const1_rtx"); - else if (INTVAL (x) == -1) - fprintf (file, "constm1_rtx"); - else if (-MAX_SAVED_CONST_INT <= INTVAL (x) - && INTVAL (x) <= MAX_SAVED_CONST_INT) - fprintf (file, "const_int_rtx[MAX_SAVED_CONST_INT + (%d)]", - (int) INTVAL (x)); - else if (INTVAL (x) == STORE_FLAG_VALUE) - fprintf (file, "const_true_rtx"); - else - { - fprintf (file, "GEN_INT ("); - fprintf (file, HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x)); - fprintf (file, ")"); - } + add_code (CONST_INT); + add_uint (UINTVAL (x)); return; case CONST_DOUBLE: /* Handle `const_double_zero' rtx. */ if (CONST_DOUBLE_REAL_VALUE (x)->cl == rvc_zero) { - fprintf (file, "CONST_DOUBLE_ATOF (\"0\", %smode)", - GET_MODE_NAME (GET_MODE (x))); + add_code (CONST_DOUBLE); + add_uint (GET_MODE (x)); return; } /* Fall through. */ @@ -242,30 +196,24 @@ generator::gen_exp (rtx x) break; } - fprintf (file, "gen_rtx_"); - print_code (code, file); - fprintf (file, " ("); + add_code (code); if (!always_void_p (code)) - { - fprintf (file, "%smode", GET_MODE_NAME (GET_MODE (x))); - sep = ",\n\t"; - } + add_uint (GET_MODE (x)); - fmt = GET_RTX_FORMAT (code); - len = GET_RTX_LENGTH (code); - for (i = 0; i < len; i++) + auto fmt = GET_RTX_FORMAT (code); + unsigned int len = GET_RTX_LENGTH (code); + for (unsigned int i = 0; i < len; i++) { if (fmt[i] == '0') break; - fputs (sep, file); switch (fmt[i]) { case 'e': case 'u': - gen_exp (XEXP (x, i)); + add_exp (XEXP (x, i)); break; case 'i': - fprintf (file, "%u", XINT (x, i)); + add_uint (XUINT (x, i)); break; case 'L': @@ -275,61 +223,69 @@ generator::gen_exp (rtx x) break; case 'r': - fprintf (file, "%u", REGNO (x)); + add_uint (REGNO (x)); break; case 'p': /* We don't have a way of parsing polynomial offsets yet, and hopefully never will. */ - fprintf (file, "%d", SUBREG_BYTE (x).to_constant ()); + add_uint (SUBREG_BYTE (x).to_constant ()); break; case 'E': - { - int j; - fprintf (file, "gen_rtvec (%d", XVECLEN (x, i)); - for (j = 0; j < XVECLEN (x, i); j++) - { - fprintf (file, ",\n\t\t"); - gen_exp (XVECEXP (x, i, j)); - } - fprintf (file, ")"); - break; - } + add_vec (XVEC (x, i)); + break; default: gcc_unreachable (); } - sep = ",\n\t"; } - fprintf (file, ")"); } -/* Output code to emit the instruction patterns in VEC, with each element - becoming a separate instruction. */ +/* Add the expansion of rtx vector VEC to the encoding. */ void -generator::gen_emit_seq (rtvec vec) +generator::add_vec (rtvec vec) { - for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i) - { - bool last_p = (i == len - 1); - rtx next = RTVEC_ELT (vec, i); - if (const char *name = get_emit_function (next)) - { - fprintf (file, " %s (", name); - gen_exp (next); - fprintf (file, ");\n"); - if (!last_p && needs_barrier_p (next)) - fprintf (file, " emit_barrier ();"); - } - else - { - fprintf (file, " emit ("); - gen_exp (next); - fprintf (file, ", %s);\n", last_p ? "false" : "true"); - } - } + add_uint (GET_NUM_ELEM (vec)); + for (int i = 0; i < GET_NUM_ELEM (vec); ++i) + add_exp (RTVEC_ELT (vec, i)); +} + +/* Emit the encoding as a static C++ array called NAME. Return NAME. */ + +const char * +generator::gen_table (FILE *file, const char *name) +{ + fprintf (file, " static const uint8_t %s[] = {", name); + for (size_t i = 0; i < bytes.length (); ++i) + fprintf (file, "%s%s 0x%02x", + i == 0 ? "" : ",", + i % 8 == 0 ? "\n " : "", + bytes[i]); + fprintf (file, "\n };\n"); + return name; +} + +/* Output the code necessary for generating rtx X and return the name + of the C++ array that contains the encoding. */ + +const char * +generator::gen_exp (FILE *file, rtx x) +{ + add_exp (x); + return gen_table (file, "expand_encoding"); +} + +/* Output the code necessary for emitting each element of VEC as a separate + instruction. Return the name of the C++ array that contains the + encoding. */ + +const char * +generator::gen_emit_seq (FILE *file, rtvec vec) +{ + add_vec (vec); + return gen_table (file, "expand_encoding"); } /* Emit the given C code to the output file. The code is allowed to @@ -340,12 +296,11 @@ static void emit_c_code (const char *code, bool can_fail_p, const char *name, FILE *file) { if (can_fail_p) - fprintf (file, "#define FAIL return (end_sequence (), _val)\n"); + fprintf (file, "#define FAIL return (end_sequence (), nullptr)\n"); else fprintf (file, "#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")" " (void)0\n", name); - fprintf (file, "#define DONE return (_val = get_insns (), " - "end_sequence (), _val)\n"); + fprintf (file, "#define DONE return end_sequence ()\n"); rtx_reader_ptr->print_md_ptr_loc (code, file); fprintf (file, "%s\n", code); @@ -453,9 +408,9 @@ maybe_queue_insn (const md_rtx_info &info) /* Output the function name, argument declarations, and initial function body for a pattern called NAME, given that it has the properties - in STATS. */ + in STATS. Return the C++ expression for the operands array. */ -static void +static const char * start_gen_insn (FILE *file, const char *name, const pattern_stats &stats) { fprintf (file, "rtx\ngen_%s (", name); @@ -473,10 +428,17 @@ start_gen_insn (FILE *file, const char *name, const pattern_stats &stats) for (int i = 0; i < stats.num_generator_args; i++) fprintf (file, "%s operand%d", i == 0 ? "" : ",", i); fprintf (file, " };\n"); + return "operands"; } - else if (stats.num_operand_vars != 0) - fprintf (file, " rtx operands[%d] ATTRIBUTE_UNUSED;\n", - stats.num_operand_vars); + + if (stats.num_operand_vars != 0) + { + fprintf (file, " rtx operands[%d] ATTRIBUTE_UNUSED;\n", + stats.num_operand_vars); + return "operands"; + } + + return "nullptr"; } /* Generate the `gen_...' function for a DEFINE_INSN. */ @@ -493,16 +455,13 @@ gen_insn (const md_rtx_info &info, FILE *file) fatal_at (info.loc, "match_dup operand number has no match_operand"); /* Output the function name and argument declarations. */ - start_gen_insn (file, XSTR (insn, 0), stats); + const char *operands = start_gen_insn (file, XSTR (insn, 0), stats); /* Output code to construct and return the rtl for the instruction body. */ rtx pattern = add_implicit_parallel (XVEC (insn, 1)); - char *used = XCNEWVEC (char, stats.num_generator_args); - fprintf (file, " return "); - generator (DEFINE_INSN, used, info, file).gen_exp (pattern); - fprintf (file, ";\n}\n\n"); - XDELETEVEC (used); + const char *table = generator (info).gen_exp (file, pattern); + fprintf (file, " return expand_rtx (%s, %s);\n}\n\n", table, operands); } /* Process and queue the DEFINE_EXPAND in INFO. */ @@ -525,7 +484,6 @@ static void gen_expand (const md_rtx_info &info, FILE *file) { struct pattern_stats stats; - char *used; /* Find out how many operands this function has. */ rtx expand = info.def; @@ -536,7 +494,7 @@ gen_expand (const md_rtx_info &info, FILE *file) "numbers above all other operands", XSTR (expand, 0)); /* Output the function name and argument declarations. */ - start_gen_insn (file, XSTR (expand, 0), stats); + const char *operands = start_gen_insn (file, XSTR (expand, 0), stats); /* If we don't have any C code to write, only one insn is being written, and no MATCH_DUPs are present, we can just return the desired insn @@ -545,16 +503,12 @@ gen_expand (const md_rtx_info &info, FILE *file) && stats.max_opno >= stats.max_dup_opno && XVECLEN (expand, 1) == 1) { - used = XCNEWVEC (char, stats.num_operand_vars); - fprintf (file, " return "); - generator (DEFINE_EXPAND, used, info, file) - .gen_exp (XVECEXP (expand, 1, 0)); - fprintf (file, ";\n}\n\n"); - XDELETEVEC (used); + rtx pattern = XVECEXP (expand, 1, 0); + const char *table = generator (info).gen_exp (file, pattern); + fprintf (file, " return expand_rtx (%s, %s);\n}\n\n", table, operands); return; } - fprintf (file, " rtx_insn *_val = 0;\n"); fprintf (file, " start_sequence ();\n"); /* The fourth operand of DEFINE_EXPAND is some code to be executed @@ -582,16 +536,8 @@ gen_expand (const md_rtx_info &info, FILE *file) fprintf (file, " }\n"); } - used = XCNEWVEC (char, stats.num_operand_vars); - generator (DEFINE_EXPAND, used, info, file).gen_emit_seq (XVEC (expand, 1)); - XDELETEVEC (used); - - /* Call `get_insns' to extract the list of all the - insns emitted within this gen_... function. */ - - fprintf (file, " _val = get_insns ();\n"); - fprintf (file, " end_sequence ();\n"); - fprintf (file, " return _val;\n}\n\n"); + const char *table = generator (info).gen_emit_seq (file, XVEC (expand, 1)); + fprintf (file, " return complete_seq (%s, %s);\n}\n\n", table, operands); } /* Process and queue the DEFINE_SPLIT or DEFINE_PEEPHOLE2 in INFO. */ @@ -621,13 +567,11 @@ gen_split (const md_rtx_info &info, FILE *file) const char *const name = ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split"); const char *unused; - char *used; /* Find out how many operands this function has. */ get_pattern_stats (&stats, XVEC (split, 2)); unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : ""); - used = XCNEWVEC (char, stats.num_operand_vars); /* Output the prototype, function name and argument declarations. */ if (GET_CODE (split) == DEFINE_PEEPHOLE2) @@ -648,9 +592,6 @@ gen_split (const md_rtx_info &info, FILE *file) } fprintf (file, "{\n"); - /* Declare all local variables. */ - fprintf (file, " rtx_insn *_val = NULL;\n"); - if (GET_CODE (split) == DEFINE_PEEPHOLE2) output_peephole2_scratches (split, file); @@ -671,17 +612,8 @@ gen_split (const md_rtx_info &info, FILE *file) if (XSTR (split, 3)) emit_c_code (XSTR (split, 3), true, name, file); - generator (GET_CODE (split), used, info, file) - .gen_emit_seq (XVEC (split, 2)); - - /* Call `get_insns' to make a list of all the - insns emitted within this gen_... function. */ - - fprintf (file, " _val = get_insns ();\n"); - fprintf (file, " end_sequence ();\n"); - fprintf (file, " return _val;\n}\n\n"); - - free (used); + const char *table = generator (info).gen_emit_seq (file, XVEC (split, 2)); + fprintf (file, " return complete_seq (%s, %s);\n}\n\n", table, "operands"); } /* Write a function, `add_clobbers', that is given a PARALLEL of sufficient diff --git a/gcc/gengenrtl.cc b/gcc/gengenrtl.cc index 8cd9d2832d0..4c1c287ecd7 100644 --- a/gcc/gengenrtl.cc +++ b/gcc/gengenrtl.cc @@ -136,7 +136,10 @@ always_void_p (int idx) /* Return nonzero if the RTL code given by index IDX is one that we should generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO - is a wrapper in emit-rtl.cc). */ + is a wrapper in emit-rtl.cc). + + This list of codes needs to be kept in sync with the switch statement + in emit-rtl.cc:rtx_expander::get_rtx. */ static int special_rtx (int idx) @@ -156,7 +159,10 @@ special_rtx (int idx) /* Return nonzero if the RTL code given by index IDX is one that we should generate no macro for at all (because gen_rtx_FOO is never used or - cannot have the obvious interface). */ + cannot have the obvious interface). + + This list of codes needs to be kept in sync with the switch statement + in emit-rtl.cc:rtx_expander::get_rtx. */ static int excluded_rtx (int idx) diff --git a/gcc/gensupport.cc b/gcc/gensupport.cc index ac0132860a9..b4a2b2b21fc 100644 --- a/gcc/gensupport.cc +++ b/gcc/gensupport.cc @@ -3764,16 +3764,6 @@ get_emit_function (rtx x) } } -/* Return true if we must emit a barrier after pattern X. */ - -bool -needs_barrier_p (rtx x) -{ - return (GET_CODE (x) == SET - && GET_CODE (SET_DEST (x)) == PC - && GET_CODE (SET_SRC (x)) == LABEL_REF); -} - #define NS "NULL" #define ZS "'\\0'" #define OPTAB_CL(o, p, c, b, l) { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 }, diff --git a/gcc/gensupport.h b/gcc/gensupport.h index 7a59dd357b0..c9b07991c09 100644 --- a/gcc/gensupport.h +++ b/gcc/gensupport.h @@ -229,7 +229,6 @@ extern void get_pattern_stats (struct pattern_stats *ranges, rtvec vec); extern void compute_test_codes (rtx, file_location, char *); extern file_location get_file_location (rtx); extern const char *get_emit_function (rtx); -extern bool needs_barrier_p (rtx); extern bool find_optab (optab_pattern *, const char *); extern FILE *choose_output (const vec &, unsigned &); diff --git a/gcc/rtl.h b/gcc/rtl.h index 5623a4b06b4..7049ed775e8 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2074,7 +2074,17 @@ const_vector_encoded_nelts (const_rtx x) inline bool always_void_p (enum rtx_code code) { - return code == SET; + switch (code) + { + case SET: + case PC: + case RETURN: + case SIMPLE_RETURN: + return true; + + default: + return false; + } } /* A structure to hold all available cost information about an rtl @@ -3020,6 +3030,36 @@ extern enum rtx_code classify_insn (rtx); extern void dump_rtx_statistics (void); /* In emit-rtl.cc */ + +/* Opcodes used in the bytecode generated by genemit.cc. */ +enum class expand_opcode { + /* NULL_RTX. */ + NO_RTX, + + /* A (match_operand N) or (match_dup N). Followed by the operand number. */ + MATCH_OPERAND, + + /* A (match_operator N) or (match_op_dup N) that preserves the original mode. + Followed by the operand number. */ + MATCH_OPERATOR, + + /* A (match_operator N) or (match_op_dup N) that overrides the original mode. + Followed by the new mode and by the operand number. */ + MATCH_OPERATOR_WITH_MODE, + + /* A (match_parallel N) or (match_par_dup N). Followed by the operand + number. */ + MATCH_PARALLEL, + + /* A (clobber (reg:M R)). Followed by M and R. */ + CLOBBER_REG, + + /* FIRST_CODE + X represents a normal rtx with code X. */ + FIRST_CODE +}; + +extern rtx expand_rtx (const uint8_t *, rtx *); +extern rtx_insn *complete_seq (const uint8_t *, rtx *); extern rtx copy_rtx_if_shared (rtx); /* In rtl.cc */