Generation support for CLOBBER_HIGH
authorAlan Hayward <alan.hayward@arm.com>
Mon, 6 Aug 2018 09:16:24 +0000 (09:16 +0000)
committerAlan Hayward <alahay01@gcc.gnu.org>
Mon, 6 Aug 2018 09:16:24 +0000 (09:16 +0000)
Ensure clobber high is a register expression.
Info is passed through for the error case.

gcc/
* emit-rtl.c (verify_rtx_sharing): Check for CLOBBER_HIGH.
(copy_insn_1): Likewise.
(gen_hard_reg_clobber_high): New gen function.
* genconfig.c (walk_insn_part): Check for CLOBBER_HIGH.
* genemit.c (gen_exp): Likewise.
(gen_emit_seq): Pass through info.
(gen_insn): Check for CLOBBER_HIGH.
(gen_expand): Pass through info.
(gen_split): Likewise.
(output_add_clobbers): Likewise.
* genrecog.c (validate_pattern): Check for CLOBBER_HIGH.
(remove_clobbers): Likewise.
* rtl.h (gen_hard_reg_clobber_high): New declaration.

From-SVN: r263327

gcc/ChangeLog
gcc/emit-rtl.c
gcc/genconfig.c
gcc/genemit.c
gcc/genrecog.c
gcc/rtl.h

index f8834d9f4328a2dfa6710a3fd3a085d4f6a34525..248a42bce322520a5d5aad4822d0b2985b48370d 100644 (file)
@@ -1,4 +1,21 @@
 2018-08-06  Alan Hayward  <alan.hayward@arm.com>
+
+       * emit-rtl.c (verify_rtx_sharing): Check for CLOBBER_HIGH.
+       (copy_insn_1): Likewise.
+       (gen_hard_reg_clobber_high): New gen function.
+       * genconfig.c (walk_insn_part): Check for CLOBBER_HIGH.
+       * genemit.c (gen_exp): Likewise.
+       (gen_emit_seq): Pass through info.
+       (gen_insn): Check for CLOBBER_HIGH.
+       (gen_expand): Pass through info.
+       (gen_split): Likewise.
+       (output_add_clobbers): Likewise.
+       * genrecog.c (validate_pattern): Check for CLOBBER_HIGH.
+       (remove_clobbers): Likewise.
+       * rtl.h (gen_hard_reg_clobber_high): New declaration.
+
+2018-08-06  Alan Hayward  <alan.hayward@arm.com>
+
        * doc/rtl.texi (clobber_high): Add.
        (parallel): Add in clobber high
        * rtl.c (rtl_check_failed_code3): Add function.
index e4b070486e87e60e069178046f98a19304167128..dacf27e087cedda026c438d540fcfc264dd2f56f 100644 (file)
@@ -2865,6 +2865,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.  */
@@ -3118,6 +3119,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.  */
@@ -5690,6 +5692,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.  */
@@ -6508,6 +6511,21 @@ 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];
+
+/* Return a CLOBBER_HIGH expression for register REGNO that clobbers MODE,
+   caching into HARD_REG_CLOBBERS_HIGH.  */
+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;
 
index c1bfde8d54bbbab76088a243873f599c7cfb31ab..745d5374b39596274bad1377618573666b2c7eb5 100644 (file)
@@ -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;
 
index 675cf04ff4bb51290550728c3c616f80f23ba342..678b9aa39357047dff87dd60604f0e8ab5dcbb6d 100644 (file)
@@ -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");
        }
 
@@ -923,7 +934,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 ();
 
   for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
index 663df8c58af8e51a38aefe2ee86293a8968aa1ec..629e2dc91f3e4dae185e42e9f067941e84709235 100644 (file)
@@ -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;
index 5e07e9bee80ff4ba18a775f8137a14e7c0e99363..f42d749511d8988b77f8f167c22c42ec0c2ef6d5 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -4242,6 +4242,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);