- else if (left != XEXP (exp, 0))
- {
- newexp = attr_rtx (NOT, left);
- }
- break;
-
- case EQ_ATTR:
- if (current_alternative_string && XSTR (exp, 0) == alternative_name)
- return (XSTR (exp, 1) == current_alternative_string
- ? true_rtx : false_rtx);
-
- /* Look at the value for this insn code in the specified attribute.
- We normally can replace this comparison with the condition that
- would give this insn the values being tested for. */
- if (XSTR (exp, 0) != alternative_name
- && (attr = find_attr (XSTR (exp, 0), 0)) != NULL)
- for (av = attr->first_value; av; av = av->next)
- for (ie = av->first_insn; ie; ie = ie->next)
- if (ie->insn_code == insn_code)
- {
- rtx x;
- x = evaluate_eq_attr (exp, av->value, insn_code, insn_index);
- x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index);
- if (attr_rtx_cost(x) < 20)
- return x;
- }
- break;
-
- default:
- break;
- }
-
- /* We have already simplified this expression. Simplifying it again
- won't buy anything unless we weren't given a valid insn code
- to process (i.e., we are canonicalizing something.). */
- if (insn_code != -2 /* Seems wrong: && current_alternative_string. */
- && ! ATTR_IND_SIMPLIFIED_P (newexp))
- return copy_rtx_unchanging (newexp);
-
- return newexp;
-}
-\f
-/* Optimize the attribute lists by seeing if we can determine conditional
- values from the known values of other attributes. This will save subroutine
- calls during the compilation. */
-
-static void
-optimize_attrs ()
-{
- struct attr_desc *attr;
- struct attr_value *av;
- struct insn_ent *ie;
- rtx newexp;
- int i;
- struct attr_value_list
- {
- struct attr_value *av;
- struct insn_ent *ie;
- struct attr_desc *attr;
- struct attr_value_list *next;
- };
- struct attr_value_list **insn_code_values;
- struct attr_value_list *ivbuf;
- struct attr_value_list *iv;
-
- /* For each insn code, make a list of all the insn_ent's for it,
- for all values for all attributes. */
-
- if (num_insn_ents == 0)
- return;
-
- /* Make 2 extra elements, for "code" values -2 and -1. */
- insn_code_values
- = (struct attr_value_list **) xmalloc ((insn_code_number + 2)
- * sizeof (struct attr_value_list *));
- memset ((char *) insn_code_values, 0,
- (insn_code_number + 2) * sizeof (struct attr_value_list *));
-
- /* Offset the table address so we can index by -2 or -1. */
- insn_code_values += 2;
-
- iv = ivbuf = ((struct attr_value_list *)
- xmalloc (num_insn_ents * sizeof (struct attr_value_list)));
-
- for (i = 0; i < MAX_ATTRS_INDEX; i++)
- for (attr = attrs[i]; attr; attr = attr->next)
- for (av = attr->first_value; av; av = av->next)
- for (ie = av->first_insn; ie; ie = ie->next)
- {
- iv->attr = attr;
- iv->av = av;
- iv->ie = ie;
- iv->next = insn_code_values[ie->insn_code];
- insn_code_values[ie->insn_code] = iv;
- iv++;
- }
-
- /* Sanity check on num_insn_ents. */
- if (iv != ivbuf + num_insn_ents)
- abort ();
-
- /* Process one insn code at a time. */
- for (i = -2; i < insn_code_number; i++)
- {
- /* Clear the ATTR_CURR_SIMPLIFIED_P flag everywhere relevant.
- We use it to mean "already simplified for this insn". */
- for (iv = insn_code_values[i]; iv; iv = iv->next)
- clear_struct_flag (iv->av->value);
-
- for (iv = insn_code_values[i]; iv; iv = iv->next)
- {
- struct obstack *old = rtl_obstack;
-
- attr = iv->attr;
- av = iv->av;
- ie = iv->ie;
- if (GET_CODE (av->value) != COND)
- continue;
-
- rtl_obstack = temp_obstack;
-#if 0 /* This was intended as a speed up, but it was slower. */
- if (insn_n_alternatives[ie->insn_code] > 6
- && count_sub_rtxs (av->value, 200) >= 200)
- newexp = simplify_by_alternatives (av->value, ie->insn_code,
- ie->insn_index);
- else
-#endif
- newexp = av->value;
- while (GET_CODE (newexp) == COND)
- {
- rtx newexp2 = simplify_cond (newexp, ie->insn_code,
- ie->insn_index);
- if (newexp2 == newexp)
- break;
- newexp = newexp2;
- }
-
- rtl_obstack = old;
- if (newexp != av->value)
- {
- newexp = attr_copy_rtx (newexp);
- remove_insn_ent (av, ie);
- av = get_attr_value (newexp, attr, ie->insn_code);
- iv->av = av;
- insert_insn_ent (av, ie);
- }
- }
- }
-
- free (ivbuf);
- free (insn_code_values - 2);
-}
-
-#if 0
-static rtx
-simplify_by_alternatives (exp, insn_code, insn_index)
- rtx exp;
- int insn_code, insn_index;
-{
- int i;
- int len = insn_n_alternatives[insn_code];
- rtx newexp = rtx_alloc (COND);
- rtx ultimate;
-
- XVEC (newexp, 0) = rtvec_alloc (len * 2);
-
- /* It will not matter what value we use as the default value
- of the new COND, since that default will never be used.
- Choose something of the right type. */
- for (ultimate = exp; GET_CODE (ultimate) == COND;)
- ultimate = XEXP (ultimate, 1);
- XEXP (newexp, 1) = ultimate;
-
- for (i = 0; i < insn_n_alternatives[insn_code]; i++)
- {
- current_alternative_string = attr_numeral (i);
- XVECEXP (newexp, 0, i * 2) = make_alternative_compare (1 << i);
- XVECEXP (newexp, 0, i * 2 + 1)
- = simplify_cond (exp, insn_code, insn_index);
- }
-
- current_alternative_string = 0;
- return simplify_cond (newexp, insn_code, insn_index);
-}
-#endif
-\f
-/* If EXP is a suitable expression, reorganize it by constructing an
- equivalent expression that is a COND with the tests being all combinations
- of attribute values and the values being simple constants. */
-
-static rtx
-simplify_by_exploding (exp)
- rtx exp;
-{
- rtx list = 0, link, condexp, defval = NULL_RTX;
- struct dimension *space;
- rtx *condtest, *condval;
- int i, j, total, ndim = 0;
- int most_tests, num_marks, new_marks;
- rtx ret;
-
- /* Locate all the EQ_ATTR expressions. */
- if (! find_and_mark_used_attributes (exp, &list, &ndim) || ndim == 0)
- {
- unmark_used_attributes (list, 0, 0);
- return exp;
- }
-
- /* Create an attribute space from the list of used attributes. For each
- dimension in the attribute space, record the attribute, list of values
- used, and number of values used. Add members to the list of values to
- cover the domain of the attribute. This makes the expanded COND form
- order independent. */
-
- space = (struct dimension *) xmalloc (ndim * sizeof (struct dimension));
-
- total = 1;
- for (ndim = 0; list; ndim++)
- {
- /* Pull the first attribute value from the list and record that
- attribute as another dimension in the attribute space. */
- const char *name = XSTR (XEXP (list, 0), 0);
- rtx *prev;
-
- if ((space[ndim].attr = find_attr (name, 0)) == 0
- || space[ndim].attr->is_numeric)
- {
- unmark_used_attributes (list, space, ndim);
- return exp;
- }
-
- /* Add all remaining attribute values that refer to this attribute. */
- space[ndim].num_values = 0;
- space[ndim].values = 0;
- prev = &list;
- for (link = list; link; link = *prev)
- if (! strcmp (XSTR (XEXP (link, 0), 0), name))
- {
- space[ndim].num_values++;
- *prev = XEXP (link, 1);
- XEXP (link, 1) = space[ndim].values;
- space[ndim].values = link;
- }
- else
- prev = &XEXP (link, 1);
-
- /* Add sufficient members to the list of values to make the list
- mutually exclusive and record the total size of the attribute
- space. */
- total *= add_values_to_cover (&space[ndim]);
- }
-
- /* Sort the attribute space so that the attributes go from non-constant
- to constant and from most values to least values. */
- for (i = 0; i < ndim; i++)
- for (j = ndim - 1; j > i; j--)
- if ((space[j-1].attr->is_const && !space[j].attr->is_const)
- || space[j-1].num_values < space[j].num_values)
- {
- struct dimension tmp;
- tmp = space[j];
- space[j] = space[j - 1];
- space[j - 1] = tmp;
- }
-
- /* Establish the initial current value. */
- for (i = 0; i < ndim; i++)
- space[i].current_value = space[i].values;
-
- condtest = (rtx *) xmalloc (total * sizeof (rtx));
- condval = (rtx *) xmalloc (total * sizeof (rtx));
-
- /* Expand the tests and values by iterating over all values in the
- attribute space. */
- for (i = 0;; i++)
- {
- condtest[i] = test_for_current_value (space, ndim);
- condval[i] = simplify_with_current_value (exp, space, ndim);
- if (! increment_current_value (space, ndim))
- break;
- }
- if (i != total - 1)
- abort ();
-
- /* We are now finished with the original expression. */
- unmark_used_attributes (0, space, ndim);
- free (space);
-
- /* Find the most used constant value and make that the default. */
- most_tests = -1;
- for (i = num_marks = 0; i < total; i++)
- if (GET_CODE (condval[i]) == CONST_STRING
- && ! ATTR_EQ_ATTR_P (condval[i]))
- {
- /* Mark the unmarked constant value and count how many are marked. */
- ATTR_EQ_ATTR_P (condval[i]) = 1;
- for (j = new_marks = 0; j < total; j++)
- if (GET_CODE (condval[j]) == CONST_STRING
- && ATTR_EQ_ATTR_P (condval[j]))
- new_marks++;
- if (new_marks - num_marks > most_tests)
- {
- most_tests = new_marks - num_marks;
- defval = condval[i];
- }
- num_marks = new_marks;
- }
- /* Clear all the marks. */
- for (i = 0; i < total; i++)
- ATTR_EQ_ATTR_P (condval[i]) = 0;
-
- /* Give up if nothing is constant. */
- if (num_marks == 0)
- ret = exp;
-
- /* If all values are the default, use that. */
- else if (total == most_tests)
- ret = defval;
-
- /* Make a COND with the most common constant value the default. (A more
- complex method where tests with the same value were combined didn't
- seem to improve things.) */
- else
- {
- condexp = rtx_alloc (COND);
- XVEC (condexp, 0) = rtvec_alloc ((total - most_tests) * 2);
- XEXP (condexp, 1) = defval;
- for (i = j = 0; i < total; i++)
- if (condval[i] != defval)
- {
- XVECEXP (condexp, 0, 2 * j) = condtest[i];
- XVECEXP (condexp, 0, 2 * j + 1) = condval[i];
- j++;
- }
- ret = condexp;
- }
- free (condtest);
- free (condval);
- return ret;
-}
-
-/* Set the ATTR_EQ_ATTR_P flag for all EQ_ATTR expressions in EXP and
- verify that EXP can be simplified to a constant term if all the EQ_ATTR
- tests have known value. */
-
-static int
-find_and_mark_used_attributes (exp, terms, nterms)
- rtx exp, *terms;
- int *nterms;
-{
- int i;
-
- switch (GET_CODE (exp))
- {
- case EQ_ATTR:
- if (! ATTR_EQ_ATTR_P (exp))
- {
- rtx link = rtx_alloc (EXPR_LIST);
- XEXP (link, 0) = exp;
- XEXP (link, 1) = *terms;
- *terms = link;
- *nterms += 1;
- ATTR_EQ_ATTR_P (exp) = 1;
- }
- return 1;
-
- case CONST_STRING:
- case CONST_INT:
- return 1;
-
- case IF_THEN_ELSE:
- if (! find_and_mark_used_attributes (XEXP (exp, 2), terms, nterms))
- return 0;
- case IOR:
- case AND:
- if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))
- return 0;
- case NOT:
- if (! find_and_mark_used_attributes (XEXP (exp, 0), terms, nterms))
- return 0;
- return 1;
-
- case COND:
- for (i = 0; i < XVECLEN (exp, 0); i++)
- if (! find_and_mark_used_attributes (XVECEXP (exp, 0, i), terms, nterms))
- return 0;
- if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))
- return 0;
- return 1;
-
- default:
- return 0;
- }
-}
-
-/* Clear the ATTR_EQ_ATTR_P flag in all EQ_ATTR expressions on LIST and
- in the values of the NDIM-dimensional attribute space SPACE. */
-
-static void
-unmark_used_attributes (list, space, ndim)
- rtx list;
- struct dimension *space;
- int ndim;
-{
- rtx link, exp;
- int i;
-
- for (i = 0; i < ndim; i++)
- unmark_used_attributes (space[i].values, 0, 0);
-
- for (link = list; link; link = XEXP (link, 1))
- {
- exp = XEXP (link, 0);
- if (GET_CODE (exp) == EQ_ATTR)
- ATTR_EQ_ATTR_P (exp) = 0;
- }
-}