This patch adds support for CLOBBER_HIGH in the generation code. An aarch64 will require 31 clobber high expressions, plus two clobbers.
The exisiting gen code restricts to 26 vector operands by virtue of using the operators [a-z]. This patch extends this to 52 by supporting [a-zA-Z]. Alan. 2017-11-16 Alan Hayward <alan.hayw...@arm.com> * emit-rtl.c (verify_rtx_sharing): Check CLOBBER_HIGH. (copy_insn_1): Likewise. (gen_hard_reg_clobber_high): Add function. * genconfig.c (walk_insn_part): Check CLOBBER_HIGH. * genemit.c (gen_exp): Likewise. (gen_emit_seq): Pass thru info. (gen_insn): Check CLOBBER_HIGH. (gen_expand): Pass thru info. (gen_split): Likewise. (output_add_clobbers): Likewise. * genextract.c (push_pathstr_operand): New function to support [a-zA-Z]. (walk_rtx): Call push_pathstr_operand. (print_path): Support [a-zA-Z]. * genrecog.c (validate_pattern): Check CLOBBER_HIGH. (remove_clobbers): Likewise. * rtl.h (gen_hard_reg_clobber_high): Add declaration. diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index af4a038d75acf17c7b04ad58ab7467f7bd7cd129..64159a82e3f79b792d58166d4307db8751c88980 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -2895,6 +2895,7 @@ verify_rtx_sharing (rtx orig, rtx insn) /* SCRATCH must be shared because they represent distinct values. */ return; case CLOBBER: + case CLOBBER_HIGH: /* Share clobbers of hard registers (like cc0), but do not share pseudo reg clobbers or clobbers of hard registers that originated as pseudos. This is needed to allow safe register renaming. */ @@ -3148,6 +3149,7 @@ repeat: /* SCRATCH must be shared because they represent distinct values. */ return; case CLOBBER: + case CLOBBER_HIGH: /* Share clobbers of hard registers (like cc0), but do not share pseudo reg clobbers or clobbers of hard registers that originated as pseudos. This is needed to allow safe register renaming. */ @@ -5707,6 +5709,7 @@ copy_insn_1 (rtx orig) case SIMPLE_RETURN: return orig; case CLOBBER: + case CLOBBER_HIGH: /* Share clobbers of hard registers (like cc0), but do not share pseudo reg clobbers or clobbers of hard registers that originated as pseudos. This is needed to allow safe register renaming. */ @@ -6529,6 +6532,19 @@ gen_hard_reg_clobber (machine_mode mode, unsigned int regno) gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno))); } +static GTY((deletable)) rtx +hard_reg_clobbers_high[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER]; + +rtx +gen_hard_reg_clobber_high (machine_mode mode, unsigned int regno) +{ + if (hard_reg_clobbers_high[mode][regno]) + return hard_reg_clobbers_high[mode][regno]; + else + return (hard_reg_clobbers_high[mode][regno] + = gen_rtx_CLOBBER_HIGH (VOIDmode, gen_rtx_REG (mode, regno))); +} + location_t prologue_location; location_t epilogue_location; diff --git a/gcc/genconfig.c b/gcc/genconfig.c index 4ff36cb019d427f410d9f251777b9b05217fac36..4108e9c457fce5529ec9a3284d37f933736776ad 100644 --- a/gcc/genconfig.c +++ b/gcc/genconfig.c @@ -72,6 +72,7 @@ walk_insn_part (rtx part, int recog_p, int non_pc_set_src) switch (code) { case CLOBBER: + case CLOBBER_HIGH: clobbers_seen_this_insn++; break; diff --git a/gcc/genemit.c b/gcc/genemit.c index 708da27221546c406030e88a4b07a51fb9df4a14..4e93b6b9831c65fc829fed6367881233b8eddcac 100644 --- a/gcc/genemit.c +++ b/gcc/genemit.c @@ -79,7 +79,7 @@ gen_rtx_scratch (rtx x, enum rtx_code subroutine_type) substituting any operand references appearing within. */ static void -gen_exp (rtx x, enum rtx_code subroutine_type, char *used) +gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) { RTX_CODE code; int i; @@ -123,7 +123,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used) for (i = 0; i < XVECLEN (x, 1); i++) { printf (",\n\t\t"); - gen_exp (XVECEXP (x, 1, i), subroutine_type, used); + gen_exp (XVECEXP (x, 1, i), subroutine_type, used, info); } printf (")"); return; @@ -137,7 +137,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used) for (i = 0; i < XVECLEN (x, 2); i++) { printf (",\n\t\t"); - gen_exp (XVECEXP (x, 2, i), subroutine_type, used); + gen_exp (XVECEXP (x, 2, i), subroutine_type, used, info); } printf (")"); return; @@ -163,12 +163,21 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used) case CLOBBER: if (REG_P (XEXP (x, 0))) { - printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))), - REGNO (XEXP (x, 0))); + printf ("gen_hard_reg_clobber (%smode, %i)", + GET_MODE_NAME (GET_MODE (XEXP (x, 0))), + REGNO (XEXP (x, 0))); return; } break; - + case CLOBBER_HIGH: + if (!REG_P (XEXP (x, 0))) + error ("CLOBBER_HIGH argument is not a register expr, at %s:%d", + info->loc.filename, info->loc.lineno); + printf ("gen_hard_reg_clobber_high (%smode, %i)", + GET_MODE_NAME (GET_MODE (XEXP (x, 0))), + REGNO (XEXP (x, 0))); + return; + break; case CC0: printf ("cc0_rtx"); return; @@ -224,7 +233,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used) switch (fmt[i]) { case 'e': case 'u': - gen_exp (XEXP (x, i), subroutine_type, used); + gen_exp (XEXP (x, i), subroutine_type, used, info); break; case 'i': @@ -252,7 +261,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used) for (j = 0; j < XVECLEN (x, i); j++) { printf (",\n\t\t"); - gen_exp (XVECEXP (x, i, j), subroutine_type, used); + gen_exp (XVECEXP (x, i, j), subroutine_type, used, info); } printf (")"); break; @@ -270,7 +279,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used) becoming a separate instruction. USED is as for gen_exp. */ static void -gen_emit_seq (rtvec vec, char *used) +gen_emit_seq (rtvec vec, char *used, md_rtx_info *info) { for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i) { @@ -279,7 +288,7 @@ gen_emit_seq (rtvec vec, char *used) if (const char *name = get_emit_function (next)) { printf (" %s (", name); - gen_exp (next, DEFINE_EXPAND, used); + gen_exp (next, DEFINE_EXPAND, used, info); printf (");\n"); if (!last_p && needs_barrier_p (next)) printf (" emit_barrier ();"); @@ -287,7 +296,7 @@ gen_emit_seq (rtvec vec, char *used) else { printf (" emit ("); - gen_exp (next, DEFINE_EXPAND, used); + gen_exp (next, DEFINE_EXPAND, used, info); printf (", %s);\n", last_p ? "false" : "true"); } } @@ -334,7 +343,8 @@ gen_insn (md_rtx_info *info) for (i = XVECLEN (insn, 1) - 1; i > 0; i--) { - if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER) + if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER + && GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER_HIGH) break; if (REG_P (XEXP (XVECEXP (insn, 1, i), 0))) @@ -368,7 +378,8 @@ gen_insn (md_rtx_info *info) /* OLD and NEW_INSN are the same if both are to be a SCRATCH of the same mode, or if both are registers of the same mode and number. */ - if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx) + if (! (GET_CODE (old_rtx) == GET_CODE (new_rtx) + && GET_MODE (old_rtx) == GET_MODE (new_rtx) && ((GET_CODE (old_rtx) == MATCH_SCRATCH && GET_CODE (new_rtx) == MATCH_SCRATCH) || (REG_P (old_rtx) && REG_P (new_rtx) @@ -431,7 +442,7 @@ gen_insn (md_rtx_info *info) ? NULL : XCNEWVEC (char, stats.num_generator_args)); printf (" return "); - gen_exp (pattern, DEFINE_INSN, used); + gen_exp (pattern, DEFINE_INSN, used, info); printf (";\n}\n\n"); XDELETEVEC (used); } @@ -480,7 +491,7 @@ gen_expand (md_rtx_info *info) && XVECLEN (expand, 1) == 1) { printf (" return "); - gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL); + gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL, info); printf (";\n}\n\n"); return; } @@ -534,7 +545,7 @@ gen_expand (md_rtx_info *info) } used = XCNEWVEC (char, stats.num_operand_vars); - gen_emit_seq (XVEC (expand, 1), used); + gen_emit_seq (XVEC (expand, 1), used, info); XDELETEVEC (used); /* Call `get_insns' to extract the list of all the @@ -617,7 +628,7 @@ gen_split (md_rtx_info *info) printf (" (void) operand%d;\n", i); } - gen_emit_seq (XVEC (split, 2), used); + gen_emit_seq (XVEC (split, 2), used, info); /* Call `get_insns' to make a list of all the insns emitted within this gen_... function. */ @@ -634,7 +645,7 @@ gen_split (md_rtx_info *info) the end of the vector. */ static void -output_add_clobbers (void) +output_add_clobbers (md_rtx_info *info) { struct clobber_pat *clobber; struct clobber_ent *ent; @@ -654,7 +665,7 @@ output_add_clobbers (void) { printf (" XVECEXP (pattern, 0, %d) = ", i); gen_exp (XVECEXP (clobber->pattern, 1, i), - GET_CODE (clobber->pattern), NULL); + GET_CODE (clobber->pattern), NULL, info); printf (";\n"); } @@ -837,7 +848,7 @@ from the machine description file `md'. */\n\n"); /* Write out the routines to add CLOBBERs to a pattern and say whether they clobber a hard reg. */ - output_add_clobbers (); + output_add_clobbers (&info); output_added_clobbers_hard_reg_p (); fflush (stdout); diff --git a/gcc/genextract.c b/gcc/genextract.c index 258d234d2729bf16b152b90bb1833a37a6eb0bdc..e1fb716e459b9bd219e89cf36c30556d520305a2 100644 --- a/gcc/genextract.c +++ b/gcc/genextract.c @@ -33,9 +33,10 @@ along with GCC; see the file COPYING3. If not see The string for each operand describes that path to the operand and contains `0' through `9' when going into an expression and `a' through - `z' when going into a vector. We assume here that only the first operand - of an rtl expression is a vector. genrecog.c makes the same assumption - (and uses the same representation) and it is currently true. */ + `z' then 'A' through to 'Z' when going into a vector. We assume here that + only the first operand of an rtl expression is a vector. genrecog.c makes + the same assumption (and uses the same representation) and it is currently + true. */ typedef char *locstr; @@ -80,6 +81,22 @@ struct accum_extract /* Forward declarations. */ static void walk_rtx (md_rtx_info *, rtx, struct accum_extract *); +#define UPPER_OFFSET ('A' - ('z' - 'a' + 1)) + +/* Convert OPERAND into a character - either into [a-zA-Z] for vector operands + or [0-9] for integer operands - and push onto the end of the path ACC. */ +static void +push_pathstr_operand (int operand, bool is_vector, + struct accum_extract *acc) +{ + if (is_vector && 'a' + operand > 'z') + acc->pathstr.safe_push (operand + UPPER_OFFSET); + else if (is_vector) + acc->pathstr.safe_push (operand + 'a'); + else + acc->pathstr.safe_push (operand + '0'); +} + static void gen_insn (md_rtx_info *info) { @@ -98,7 +115,7 @@ gen_insn (md_rtx_info *info) else for (i = XVECLEN (insn, 1) - 1; i >= 0; i--) { - acc.pathstr.safe_push ('a' + i); + push_pathstr_operand (i, true, &acc); walk_rtx (info, XVECEXP (insn, 1, i), &acc); acc.pathstr.pop (); } @@ -208,7 +225,7 @@ static void walk_rtx (md_rtx_info *info, rtx x, struct accum_extract *acc) { RTX_CODE code; - int i, len, base; + int i, len; const char *fmt; if (x == 0) @@ -234,10 +251,9 @@ walk_rtx (md_rtx_info *info, rtx x, struct accum_extract *acc) VEC_safe_set_locstr (info, &acc->oplocs, XINT (x, 0), VEC_char_to_string (acc->pathstr)); - base = (code == MATCH_OPERATOR ? '0' : 'a'); for (i = XVECLEN (x, 2) - 1; i >= 0; i--) { - acc->pathstr.safe_push (base + i); + push_pathstr_operand (i, code != MATCH_OPERATOR, acc); walk_rtx (info, XVECEXP (x, 2, i), acc); acc->pathstr.pop (); } @@ -252,10 +268,9 @@ walk_rtx (md_rtx_info *info, rtx x, struct accum_extract *acc) if (code == MATCH_DUP) break; - base = (code == MATCH_OP_DUP ? '0' : 'a'); for (i = XVECLEN (x, 1) - 1; i >= 0; i--) { - acc->pathstr.safe_push (base + i); + push_pathstr_operand (i, code != MATCH_OP_DUP, acc); walk_rtx (info, XVECEXP (x, 1, i), acc); acc->pathstr.pop (); } @@ -271,7 +286,7 @@ walk_rtx (md_rtx_info *info, rtx x, struct accum_extract *acc) { if (fmt[i] == 'e' || fmt[i] == 'u') { - acc->pathstr.safe_push ('0' + i); + push_pathstr_operand (i, false, acc); walk_rtx (info, XEXP (x, i), acc); acc->pathstr.pop (); } @@ -280,7 +295,7 @@ walk_rtx (md_rtx_info *info, rtx x, struct accum_extract *acc) int j; for (j = XVECLEN (x, i) - 1; j >= 0; j--) { - acc->pathstr.safe_push ('a' + j); + push_pathstr_operand (j, true, acc); walk_rtx (info, XVECEXP (x, i, j), acc); acc->pathstr.pop (); } @@ -311,7 +326,7 @@ print_path (const char *path) for (i = len - 1; i >= 0 ; i--) { - if (ISLOWER (path[i])) + if (ISLOWER (path[i]) || ISUPPER (path[i])) fputs ("XVECEXP (", stdout); else if (ISDIGIT (path[i])) fputs ("XEXP (", stdout); @@ -323,7 +338,9 @@ print_path (const char *path) for (i = 0; i < len; i++) { - if (ISLOWER (path[i])) + if (ISUPPER (path[i])) + printf (", 0, %d)", path[i] - UPPER_OFFSET); + else if (ISLOWER (path[i])) printf (", 0, %d)", path[i] - 'a'); else if (ISDIGIT (path[i])) printf (", %d)", path[i] - '0'); diff --git a/gcc/genrecog.c b/gcc/genrecog.c index 695383badab47f8492df380caad0ce371207bce4..cdbe575938367a6e3387e17d45e4fafa21d30fa4 100644 --- a/gcc/genrecog.c +++ b/gcc/genrecog.c @@ -718,6 +718,7 @@ validate_pattern (rtx pattern, md_rtx_info *info, rtx set, int set_code) } case CLOBBER: + case CLOBBER_HIGH: validate_pattern (SET_DEST (pattern), info, pattern, '='); return; @@ -5294,7 +5295,7 @@ remove_clobbers (acceptance_type *acceptance_ptr, rtx *pattern_ptr) for (i = XVECLEN (pattern, 0); i > 0; i--) { rtx x = XVECEXP (pattern, 0, i - 1); - if (GET_CODE (x) != CLOBBER + if ((GET_CODE (x) != CLOBBER && GET_CODE (x) != CLOBBER_HIGH) || (!REG_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 0)) != MATCH_SCRATCH)) break; diff --git a/gcc/rtl.h b/gcc/rtl.h index 71621bdfd67c4ce3dcccc5279456cae841371f97..bdb05d00120e7fadeb7f2d29bd67afc7a77262c1 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -4193,6 +4193,7 @@ extern void vt_equate_reg_base_value (const_rtx, const_rtx); extern bool memory_modified_in_insn_p (const_rtx, const_rtx); extern bool may_be_sp_based_p (rtx); extern rtx gen_hard_reg_clobber (machine_mode, unsigned int); +extern rtx gen_hard_reg_clobber_high (machine_mode, unsigned int); extern rtx get_reg_known_value (unsigned int); extern bool get_reg_known_equiv_p (unsigned int); extern rtx get_reg_base_value (unsigned int);