gensupport.c (add_define_attr): New static function.
authorBernd Schmidt <bernds@codesourcery.com>
Tue, 21 Jun 2011 14:38:38 +0000 (14:38 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Tue, 21 Jun 2011 14:38:38 +0000 (14:38 +0000)
* gensupport.c (add_define_attr): New static function.
(is_predicable): Allow multi-alternative lists for the "predicable"
attribute.
(modify_attr_enabled_ce, alter_attrs_for_insn): New static functions.
(process_one_cond_exec): Call alter_attrs_for_insn.
* doc/md.texi (Defining Attributes): Mention some standard names.
(Conditional Execution): Update documentation for "predicable".

From-SVN: r175263

gcc/ChangeLog
gcc/doc/md.texi
gcc/gensupport.c

index af173123600745eb701cb969433759d77e612f62..26bfc6f5c1a11a05bffffbb44fb5a6428dc198a7 100644 (file)
@@ -1,5 +1,13 @@
 2011-06-21  Bernd Schmidt  <bernds@codesourcery.com>
 
+       * gensupport.c (add_define_attr): New static function.
+       (is_predicable): Allow multi-alternative lists for the "predicable"
+       attribute.
+       (modify_attr_enabled_ce, alter_attrs_for_insn): New static functions.
+       (process_one_cond_exec): Call alter_attrs_for_insn.
+       * doc/md.texi (Defining Attributes): Mention some standard names.
+       (Conditional Execution): Update documentation for "predicable".
+
        * doc/extend.texi (__builtin_clrsb, __builtin_clrsbl,
        __builtin_clrsbll): Document.
        * doc/rtl.texi (clrsb): New entry.
index 0023405bea6378dbabefc1703efa9d41f9837d80..65e4070d91da83184c1f4d8579c4faf57fb62137 100644 (file)
@@ -6745,6 +6745,14 @@ by the target machine.  It looks like:
 @end smallexample
 
 @var{name} is a string specifying the name of the attribute being defined.
+Some attributes are used in a special way by the rest of the compiler. The
+@code{enabled} attribute can be used to conditionally enable or disable
+insn alternatives (@pxref{Disable Insn Alternatives}). The @code{predicable}
+attribute, together with a suitable @code{define_cond_exec}
+(@pxref{Conditional Execution}), can be used to automatically generate
+conditional variants of instruction patterns. The compiler internally uses
+the names @code{ce_enabled} and @code{nonce_enabled}, so they should not be
+used elsewhere as alternative names.
 
 @var{list-of-values} is either a string that specifies a comma-separated
 list of values that can be assigned to the attribute, or a null string to
@@ -7954,11 +7962,14 @@ if the current insn is predicated, and will otherwise be @code{NULL}.
 
 When @code{define_cond_exec} is used, an implicit reference to
 the @code{predicable} instruction attribute is made.
-@xref{Insn Attributes}.  This attribute must be boolean (i.e.@: have
-exactly two elements in its @var{list-of-values}).  Further, it must
-not be used with complex expressions.  That is, the default and all
-uses in the insns must be a simple constant, not dependent on the
-alternative or anything else.
+@xref{Insn Attributes}.  This attribute must be a boolean (i.e.@: have
+exactly two elements in its @var{list-of-values}), with the possible
+values being @code{no} and @code{yes}.  The default and all uses in
+the insns must be a simple constant, not a complex expressions.  It
+may, however, depend on the alternative, by using a comma-separated
+list of values.  If that is the case, the port should also define an
+@code{enabled} attribute (@pxref{Disable Insn Alternatives}), which
+should also allow only @code{no} and @code{yes} as its values.
 
 For each @code{define_insn} for which the @code{predicable}
 attribute is true, a new @code{define_insn} pattern will be
index cd72e770d75eb4687e54064ce6e66bd0d5d8fb67..e56291e3a383297084dd0116090557e56fc903f9 100644 (file)
@@ -368,6 +368,25 @@ queue_pattern (rtx pattern, struct queue_elem ***list_tail,
   return e;
 }
 
+/* Build a define_attr for an binary attribute with name NAME and
+   possible values "yes" and "no", and queue it.  */
+static void
+add_define_attr (const char *name)
+{
+  struct queue_elem *e = XNEW(struct queue_elem);
+  rtx t1 = rtx_alloc (DEFINE_ATTR);
+  XSTR (t1, 0) = name;
+  XSTR (t1, 1) = "no,yes";
+  XEXP (t1, 2) = rtx_alloc (CONST_STRING);
+  XSTR (XEXP (t1, 2), 0) = "yes";
+  e->data = t1;
+  e->filename = "built-in";
+  e->lineno = -1;
+  e->next = define_attr_queue;
+  define_attr_queue = e;
+
+}
+
 /* Recursively remove constraints from an rtx.  */
 
 static void
@@ -547,17 +566,10 @@ is_predicable (struct queue_elem *elem)
   return predicable_default;
 
  found:
-  /* Verify that predicability does not vary on the alternative.  */
-  /* ??? It should be possible to handle this by simply eliminating
-     the non-predicable alternatives from the insn.  FRV would like
-     to do this.  Delay this until we've got the basics solid.  */
+  /* Find out which value we're looking at.  Multiple alternatives means at
+     least one is predicable.  */
   if (strchr (value, ',') != NULL)
-    {
-      error_with_line (elem->lineno, "multiple alternatives for `predicable'");
-      return 0;
-    }
-
-  /* Find out which value we're looking at.  */
+    return 1;
   if (strcmp (value, predicable_true) == 0)
     return 1;
   if (strcmp (value, predicable_false) == 0)
@@ -798,6 +810,146 @@ alter_test_for_insn (struct queue_elem *ce_elem,
                            XSTR (insn_elem->data, 2));
 }
 
+/* Modify VAL, which is an attribute expression for the "enabled" attribute,
+   to take "ce_enabled" into account.  Return the new expression.  */
+static rtx
+modify_attr_enabled_ce (rtx val)
+{
+  rtx eq_attr, str;
+  rtx ite;
+  eq_attr = rtx_alloc (EQ_ATTR);
+  ite = rtx_alloc (IF_THEN_ELSE);
+  str = rtx_alloc (CONST_STRING);
+
+  XSTR (eq_attr, 0) = "ce_enabled";
+  XSTR (eq_attr, 1) = "yes";
+  XSTR (str, 0) = "no";
+  XEXP (ite, 0) = eq_attr;
+  XEXP (ite, 1) = val;
+  XEXP (ite, 2) = str;
+
+  return ite;
+}
+
+/* Alter the attribute vector of INSN, which is a COND_EXEC variant created
+   from a define_insn pattern.  We must modify the "predicable" attribute
+   to be named "ce_enabled", and also change any "enabled" attribute that's
+   present so that it takes ce_enabled into account.
+   We rely on the fact that INSN was created with copy_rtx, and modify data
+   in-place.  */
+
+static void
+alter_attrs_for_insn (rtx insn)
+{
+  static bool global_changes_made = false;
+  rtvec vec = XVEC (insn, 4);
+  rtvec new_vec;
+  rtx val, set;
+  int num_elem;
+  int predicable_idx = -1;
+  int enabled_idx = -1;
+  int i;
+
+  if (! vec)
+    return;
+
+  num_elem = GET_NUM_ELEM (vec);
+  for (i = num_elem - 1; i >= 0; --i)
+    {
+      rtx sub = RTVEC_ELT (vec, i);
+      switch (GET_CODE (sub))
+       {
+       case SET_ATTR:
+         if (strcmp (XSTR (sub, 0), "predicable") == 0)
+           {
+             predicable_idx = i;
+             XSTR (sub, 0) = "ce_enabled";
+           }
+         else if (strcmp (XSTR (sub, 0), "enabled") == 0)
+           {
+             enabled_idx = i;
+             XSTR (sub, 0) = "nonce_enabled";
+           }
+         break;
+
+       case SET_ATTR_ALTERNATIVE:
+         if (strcmp (XSTR (sub, 0), "predicable") == 0)
+           /* We already give an error elsewhere.  */
+           return;
+         else if (strcmp (XSTR (sub, 0), "enabled") == 0)
+           {
+             enabled_idx = i;
+             XSTR (sub, 0) = "nonce_enabled";
+           }
+         break;
+
+       case SET:
+         if (GET_CODE (SET_DEST (sub)) != ATTR)
+           break;
+         if (strcmp (XSTR (SET_DEST (sub), 0), "predicable") == 0)
+           {
+             sub = SET_SRC (sub);
+             if (GET_CODE (sub) == CONST_STRING)
+               {
+                 predicable_idx = i;
+                 XSTR (sub, 0) = "ce_enabled";
+               }
+             else
+               /* We already give an error elsewhere.  */
+               return;
+             break;
+           }
+         if (strcmp (XSTR (SET_DEST (sub), 0), "enabled") == 0)
+           {
+             enabled_idx = i;
+             XSTR (SET_DEST (sub), 0) = "nonce_enabled";
+           }
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+    }
+  if (predicable_idx == -1)
+    return;
+
+  if (!global_changes_made)
+    {
+      struct queue_elem *elem;
+      
+      global_changes_made = true;
+      add_define_attr ("ce_enabled");
+      add_define_attr ("nonce_enabled");
+
+      for (elem = define_attr_queue; elem ; elem = elem->next)
+       if (strcmp (XSTR (elem->data, 0), "enabled") == 0)
+         {
+           XEXP (elem->data, 2)
+             = modify_attr_enabled_ce (XEXP (elem->data, 2));
+         }
+    }
+  if (enabled_idx == -1)
+    return;
+
+  new_vec = rtvec_alloc (num_elem + 1);
+  for (i = 0; i < num_elem; i++)
+    RTVEC_ELT (new_vec, i) = RTVEC_ELT (vec, i);
+  val = rtx_alloc (IF_THEN_ELSE);
+  XEXP (val, 0) = rtx_alloc (EQ_ATTR);
+  XEXP (val, 1) = rtx_alloc (CONST_STRING);
+  XEXP (val, 2) = rtx_alloc (CONST_STRING);
+  XSTR (XEXP (val, 0), 0) = "nonce_enabled";
+  XSTR (XEXP (val, 0), 1) = "yes";
+  XSTR (XEXP (val, 1), 0) = "yes";
+  XSTR (XEXP (val, 2), 0) = "no";
+  set = rtx_alloc (SET);
+  SET_DEST (set) = rtx_alloc (ATTR);
+  XSTR (SET_DEST (set), 0) = "enabled";
+  SET_SRC (set) = modify_attr_enabled_ce (val);
+  RTVEC_ELT (new_vec, i) = set;
+  XVEC (insn, 4) = new_vec;
+}
+
 /* Adjust all of the operand numbers in SRC to match the shift they'll
    get from an operand displacement of DISP.  Return a pointer after the
    adjusted string.  */
@@ -943,9 +1095,7 @@ process_one_cond_exec (struct queue_elem *ce_elem)
       XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
       XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
                                              alternatives, max_operand);
-
-      /* ??? Set `predicable' to false.  Not crucial since it's really
-         only used here, and we won't reprocess this new pattern.  */
+      alter_attrs_for_insn (insn);
 
       /* Put the new pattern on the `other' list so that it
         (a) is not reprocessed by other define_cond_exec patterns