genattrtab bit-rot, and if_then_else in values
authorAlan Modra <amodra@gmail.com>
Mon, 7 Jan 2019 22:54:40 +0000 (09:24 +1030)
committerAlan Modra <amodra@gcc.gnu.org>
Mon, 7 Jan 2019 22:54:40 +0000 (09:24 +1030)
This patch started off just by adding if_then_else support in
write_attr_value to be able to write a saner expression for powerpc
tls_gdld_nomark length.  Then I noticed bit-rot in functions used to
calculate insn_default_length, insn_min_length, and length_unit_log
(which are used by the shorten_branches pass).  These functions
don't handle a const_int length value and return an "unknown" status
that isn't used, or in the case of or_attr_value, doesn't need to be
used.  min_attr_value also attempts to return INT_MAX for the
unhandled rtl case, but this can get lost in recursive calls.  I fixed
that problem by returning INT_MIN instead, and translating that to
INT_MAX in the only caller of min_attr_value.

PR target/88614
* genattrtab.c (max_attr_value, min_attr_value, or_attr_value):
Delete "unknownp" parameter.  Adjust callers.  Handle
CONST_INT, PLUS, MINUS, and MULT.
(attr_value_aligned): Renamed from or_attr_value.
(min_attr_value): Return INT_MIN for unhandled rtl case..
(min_fn): ..and translate to INT_MAX here.
(write_length_unit_log): Modify to cope without "unknown".
(write_attr_value): Handle IF_THEN_ELSE.

From-SVN: r267666

gcc/ChangeLog
gcc/genattrtab.c

index c207457..daf98c3 100644 (file)
@@ -1,3 +1,15 @@
+2019-01-08  Alan Modra  <amodra@gmail.com>
+
+       PR target/88614
+       * genattrtab.c (max_attr_value, min_attr_value, or_attr_value):
+       Delete "unknownp" parameter.  Adjust callers.  Handle
+       CONST_INT, PLUS, MINUS, and MULT.
+       (attr_value_aligned): Renamed from or_attr_value.
+       (min_attr_value): Return INT_MIN for unhandled rtl case..
+       (min_fn): ..and translate to INT_MAX here.
+       (write_length_unit_log): Modify to cope without "unknown".
+       (write_attr_value): Handle IF_THEN_ELSE.
+
 2019-01-07  Richard Sandiford  <richard.sandiford@arm.com>
 
        * tree-vect-stmts.c (vectorizable_store): Don't use the dataref_offset
index 2cd04cd..1dd4f14 100644 (file)
@@ -266,9 +266,9 @@ static int compares_alternatives_p (rtx);
 static void make_internal_attr     (const char *, rtx, int);
 static void insert_insn_ent        (struct attr_value *, struct insn_ent *);
 static void walk_attr_value       (rtx);
-static int max_attr_value         (rtx, int*);
-static int min_attr_value         (rtx, int*);
-static int or_attr_value          (rtx, int*);
+static int max_attr_value         (rtx);
+static int min_attr_value         (rtx);
+static unsigned int attr_value_alignment (rtx);
 static rtx simplify_test_exp      (rtx, int, int);
 static rtx simplify_test_exp_in_temp (rtx, int, int);
 static rtx copy_rtx_unchanging    (rtx);
@@ -1550,15 +1550,16 @@ one_fn (rtx exp ATTRIBUTE_UNUSED)
 static rtx
 max_fn (rtx exp)
 {
-  int unknown;
-  return make_numeric_value (max_attr_value (exp, &unknown));
+  return make_numeric_value (max_attr_value (exp));
 }
 
 static rtx
 min_fn (rtx exp)
 {
-  int unknown;
-  return make_numeric_value (min_attr_value (exp, &unknown));
+  int val = min_attr_value (exp);
+  if (val < 0)
+    val = INT_MAX;
+  return make_numeric_value (val);
 }
 
 static void
@@ -1568,24 +1569,21 @@ write_length_unit_log (FILE *outf)
   struct attr_value *av;
   struct insn_ent *ie;
   unsigned int length_unit_log, length_or;
-  int unknown = 0;
 
   if (length_attr)
     {
-      length_or = or_attr_value (length_attr->default_val->value, &unknown);
+      length_or = attr_value_alignment (length_attr->default_val->value);
       for (av = length_attr->first_value; av; av = av->next)
        for (ie = av->first_insn; ie; ie = ie->next)
-         length_or |= or_attr_value (av->value, &unknown);
-    }
+         length_or |= attr_value_alignment (av->value);
 
-  if (length_attr == NULL || unknown)
-    length_unit_log = 0;
-  else
-    {
       length_or = ~length_or;
       for (length_unit_log = 0; length_or & 1; length_or >>= 1)
        length_unit_log++;
     }
+  else
+    length_unit_log = 0;
+
   fprintf (outf, "EXPORTED_CONST int length_unit_log = %u;\n", length_unit_log);
 }
 
@@ -3753,11 +3751,12 @@ write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags,
   return attrs_cached;
 }
 
-/* Given an attribute value, return the maximum CONST_STRING argument
-   encountered.  Set *UNKNOWNP and return INT_MAX if the value is unknown.  */
+/* Given an attribute value expression, return the maximum value that
+   might be evaluated.  Return INT_MAX if the value can't be
+   calculated by this function.  */
 
 static int
-max_attr_value (rtx exp, int *unknownp)
+max_attr_value (rtx exp)
 {
   int current_max;
   int i, n;
@@ -3768,25 +3767,62 @@ max_attr_value (rtx exp, int *unknownp)
       current_max = atoi (XSTR (exp, 0));
       break;
 
+    case CONST_INT:
+      current_max = INTVAL (exp);
+      break;
+
+    case PLUS:
+      current_max = max_attr_value (XEXP (exp, 0));
+      if (current_max != INT_MAX)
+       {
+         n = current_max;
+         current_max = max_attr_value (XEXP (exp, 1));
+         if (current_max != INT_MAX)
+           current_max += n;
+       }
+      break;
+
+    case MINUS:
+      current_max = max_attr_value (XEXP (exp, 0));
+      if (current_max != INT_MAX)
+       {
+         n = min_attr_value (XEXP (exp, 1));
+         if (n == INT_MIN)
+           current_max = INT_MAX;
+         else
+           current_max -= n;
+       }
+      break;
+
+    case MULT:
+      current_max = max_attr_value (XEXP (exp, 0));
+      if (current_max != INT_MAX)
+       {
+         n = current_max;
+         current_max = max_attr_value (XEXP (exp, 1));
+         if (current_max != INT_MAX)
+           current_max *= n;
+       }
+      break;
+
     case COND:
-      current_max = max_attr_value (XEXP (exp, 1), unknownp);
+      current_max = max_attr_value (XEXP (exp, 1));
       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        {
-         n = max_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
+         n = max_attr_value (XVECEXP (exp, 0, i + 1));
          if (n > current_max)
            current_max = n;
        }
       break;
 
     case IF_THEN_ELSE:
-      current_max = max_attr_value (XEXP (exp, 1), unknownp);
-      n = max_attr_value (XEXP (exp, 2), unknownp);
+      current_max = max_attr_value (XEXP (exp, 1));
+      n = max_attr_value (XEXP (exp, 2));
       if (n > current_max)
        current_max = n;
       break;
 
     default:
-      *unknownp = 1;
       current_max = INT_MAX;
       break;
     }
@@ -3794,11 +3830,12 @@ max_attr_value (rtx exp, int *unknownp)
   return current_max;
 }
 
-/* Given an attribute value, return the minimum CONST_STRING argument
-   encountered.  Set *UNKNOWNP and return 0 if the value is unknown.  */
+/* Given an attribute value expression, return the minimum value that
+   might be evaluated.  Return INT_MIN if the value can't be
+   calculated by this function.  */
 
 static int
-min_attr_value (rtx exp, int *unknownp)
+min_attr_value (rtx exp)
 {
   int current_min;
   int i, n;
@@ -3809,40 +3846,77 @@ min_attr_value (rtx exp, int *unknownp)
       current_min = atoi (XSTR (exp, 0));
       break;
 
+    case CONST_INT:
+      current_min = INTVAL (exp);
+      break;
+
+    case PLUS:
+      current_min = min_attr_value (XEXP (exp, 0));
+      if (current_min != INT_MIN)
+       {
+         n = current_min;
+         current_min = min_attr_value (XEXP (exp, 1));
+         if (current_min != INT_MIN)
+           current_min += n;
+       }
+      break;
+
+    case MINUS:
+      current_min = min_attr_value (XEXP (exp, 0));
+      if (current_min != INT_MIN)
+       {
+         n = max_attr_value (XEXP (exp, 1));
+         if (n == INT_MAX)
+           current_min = INT_MIN;
+         else
+           current_min -= n;
+       }
+      break;
+
+    case MULT:
+      current_min = min_attr_value (XEXP (exp, 0));
+      if (current_min != INT_MIN)
+       {
+         n = current_min;
+         current_min = min_attr_value (XEXP (exp, 1));
+         if (current_min != INT_MIN)
+           current_min *= n;
+       }
+      break;
+
     case COND:
-      current_min = min_attr_value (XEXP (exp, 1), unknownp);
+      current_min = min_attr_value (XEXP (exp, 1));
       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        {
-         n = min_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
+         n = min_attr_value (XVECEXP (exp, 0, i + 1));
          if (n < current_min)
            current_min = n;
        }
       break;
 
     case IF_THEN_ELSE:
-      current_min = min_attr_value (XEXP (exp, 1), unknownp);
-      n = min_attr_value (XEXP (exp, 2), unknownp);
+      current_min = min_attr_value (XEXP (exp, 1));
+      n = min_attr_value (XEXP (exp, 2));
       if (n < current_min)
        current_min = n;
       break;
 
     default:
-      *unknownp = 1;
-      current_min = INT_MAX;
+      current_min = INT_MIN;
       break;
     }
 
   return current_min;
 }
 
-/* Given an attribute value, return the result of ORing together all
-   CONST_STRING arguments encountered.  Set *UNKNOWNP and return -1
-   if the numeric value is not known.  */
+/* Given an attribute value expression, return the alignment of values.
+   Return 0 if EXP is known to be zero, and 1 if the value can't be
+   calculated by this function.  */
 
-static int
-or_attr_value (rtx exp, int *unknownp)
+static unsigned int
+attr_value_alignment (rtx exp)
 {
-  int current_or;
+  unsigned int current_or;
   int i;
 
   switch (GET_CODE (exp))
@@ -3851,24 +3925,38 @@ or_attr_value (rtx exp, int *unknownp)
       current_or = atoi (XSTR (exp, 0));
       break;
 
+    case CONST_INT:
+      current_or = INTVAL (exp);
+      break;
+
+    case PLUS:
+    case MINUS:
+      current_or = attr_value_alignment (XEXP (exp, 0));
+      current_or |= attr_value_alignment (XEXP (exp, 1));
+      break;
+
+    case MULT:
+      current_or = attr_value_alignment (XEXP (exp, 0));
+      current_or *= attr_value_alignment (XEXP (exp, 1));
+      break;
+
     case COND:
-      current_or = or_attr_value (XEXP (exp, 1), unknownp);
+      current_or = attr_value_alignment (XEXP (exp, 1));
       for (i = 0; i < XVECLEN (exp, 0); i += 2)
-       current_or |= or_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
+       current_or |= attr_value_alignment (XVECEXP (exp, 0, i + 1));
       break;
 
     case IF_THEN_ELSE:
-      current_or = or_attr_value (XEXP (exp, 1), unknownp);
-      current_or |= or_attr_value (XEXP (exp, 2), unknownp);
+      current_or = attr_value_alignment (XEXP (exp, 1));
+      current_or |= attr_value_alignment (XEXP (exp, 2));
       break;
 
     default:
-      *unknownp = 1;
-      current_or = -1;
+      current_or = 1;
       break;
     }
 
-  return current_or;
+  return current_or & -current_or;
 }
 
 /* Scan an attribute value, possibly a conditional, and record what actions
@@ -4343,6 +4431,16 @@ write_attr_value (FILE *outf, struct attr_desc *attr, rtx value)
       write_attr_value (outf, attr, XEXP (value, 1));
       break;
 
+    case IF_THEN_ELSE:
+      fprintf (outf, "(");
+      write_test_expr (outf, XEXP (value, 0), 0, 0, false);
+      fprintf (outf, " ? ");
+      write_attr_value (outf, attr, XEXP (value, 1));
+      fprintf (outf, " : ");
+      write_attr_value (outf, attr, XEXP (value, 2));
+      fprintf (outf, ")");
+      break;
+
     default:
       gcc_unreachable ();
     }