- right = insert_right_side (AND, andexp, this,
- insn_code, insn_index);
- right = insert_right_side (AND, right,
- evaluate_eq_attr (exp,
- XVECEXP (value, 0,
- i + 1),
- insn_code, insn_index),
- insn_code, insn_index);
- orexp = insert_right_side (IOR, orexp, right,
- insn_code, insn_index);
-
- /* Add this condition into the AND expression. */
- newexp = attr_rtx (NOT, this);
- andexp = insert_right_side (AND, andexp, newexp,
- insn_code, insn_index);
- }
-
- /* Handle the default case. */
- right = insert_right_side (AND, andexp,
- evaluate_eq_attr (exp, XEXP (value, 1),
- insn_code, insn_index),
- insn_code, insn_index);
- newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
- }
- else
- abort ();
-
- /* If uses an address, must return original expression. But set the
- RTX_UNCHANGING_P bit so we don't try to simplify it again. */
-
- address_used = 0;
- walk_attr_value (newexp);
-
- if (address_used)
- {
- /* This had `&& current_alternative_string', which seems to be wrong. */
- if (! RTX_UNCHANGING_P (exp))
- return copy_rtx_unchanging (exp);
- return exp;
- }
- else
- return newexp;
-}
-\f
-/* This routine is called when an AND of a term with a tree of AND's is
- encountered. If the term or its complement is present in the tree, it
- can be replaced with TRUE or FALSE, respectively.
-
- Note that (eq_attr "att" "v1") and (eq_attr "att" "v2") cannot both
- be true and hence are complementary.
-
- There is one special case: If we see
- (and (not (eq_attr "att" "v1"))
- (eq_attr "att" "v2"))
- this can be replaced by (eq_attr "att" "v2"). To do this we need to
- replace the term, not anything in the AND tree. So we pass a pointer to
- the term. */
-
-static rtx
-simplify_and_tree (exp, pterm, insn_code, insn_index)
- rtx exp;
- rtx *pterm;
- int insn_code, insn_index;
-{
- rtx left, right;
- rtx newexp;
- rtx temp;
- int left_eliminates_term, right_eliminates_term;
-
- if (GET_CODE (exp) == AND)
- {
- left = simplify_and_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
- right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
- if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
- {
- newexp = attr_rtx (GET_CODE (exp), left, right);
-
- exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
- }
- }
-
- else if (GET_CODE (exp) == IOR)
- {
- /* For the IOR case, we do the same as above, except that we can
- only eliminate `term' if both sides of the IOR would do so. */
- temp = *pterm;
- left = simplify_and_tree (XEXP (exp, 0), &temp, insn_code, insn_index);
- left_eliminates_term = (temp == true_rtx);
-
- temp = *pterm;
- right = simplify_and_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
- right_eliminates_term = (temp == true_rtx);
-
- if (left_eliminates_term && right_eliminates_term)
- *pterm = true_rtx;
-
- if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
- {
- newexp = attr_rtx (GET_CODE (exp), left, right);
-
- exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
- }
- }
-
- /* Check for simplifications. Do some extra checking here since this
- routine is called so many times. */
-
- if (exp == *pterm)
- return true_rtx;
-
- else if (GET_CODE (exp) == NOT && XEXP (exp, 0) == *pterm)
- return false_rtx;
-
- else if (GET_CODE (*pterm) == NOT && exp == XEXP (*pterm, 0))
- return false_rtx;
-
- else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == EQ_ATTR)
- {
- if (XSTR (exp, 0) != XSTR (*pterm, 0))
- return exp;
-
- if (! strcmp (XSTR (exp, 1), XSTR (*pterm, 1)))
- return true_rtx;
- else
- return false_rtx;
- }
-
- else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
- && GET_CODE (XEXP (exp, 0)) == EQ_ATTR)
- {
- if (XSTR (*pterm, 0) != XSTR (XEXP (exp, 0), 0))
- return exp;
-
- if (! strcmp (XSTR (*pterm, 1), XSTR (XEXP (exp, 0), 1)))
- return false_rtx;
- else
- return true_rtx;
- }
-
- else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
- && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR)
- {
- if (XSTR (exp, 0) != XSTR (XEXP (*pterm, 0), 0))
- return exp;
-
- if (! strcmp (XSTR (exp, 1), XSTR (XEXP (*pterm, 0), 1)))
- return false_rtx;
- else
- *pterm = true_rtx;
- }
-
- else if (GET_CODE (exp) == NOT && GET_CODE (*pterm) == NOT)
- {
- if (attr_equal_p (XEXP (exp, 0), XEXP (*pterm, 0)))
- return true_rtx;
- }
-
- else if (GET_CODE (exp) == NOT)
- {
- if (attr_equal_p (XEXP (exp, 0), *pterm))
- return false_rtx;
- }
-
- else if (GET_CODE (*pterm) == NOT)
- {
- if (attr_equal_p (XEXP (*pterm, 0), exp))
- return false_rtx;
- }
-
- else if (attr_equal_p (exp, *pterm))
- return true_rtx;
-
- return exp;
-}
-\f
-/* Similar to `simplify_and_tree', but for IOR trees. */
-
-static rtx
-simplify_or_tree (exp, pterm, insn_code, insn_index)
- rtx exp;
- rtx *pterm;
- int insn_code, insn_index;
-{
- rtx left, right;
- rtx newexp;
- rtx temp;
- int left_eliminates_term, right_eliminates_term;
-
- if (GET_CODE (exp) == IOR)
- {
- left = simplify_or_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
- right = simplify_or_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
- if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
- {
- newexp = attr_rtx (GET_CODE (exp), left, right);
-
- exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
- }
- }
-
- else if (GET_CODE (exp) == AND)
- {
- /* For the AND case, we do the same as above, except that we can
- only eliminate `term' if both sides of the AND would do so. */
- temp = *pterm;
- left = simplify_or_tree (XEXP (exp, 0), &temp, insn_code, insn_index);
- left_eliminates_term = (temp == false_rtx);
-
- temp = *pterm;
- right = simplify_or_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
- right_eliminates_term = (temp == false_rtx);
-
- if (left_eliminates_term && right_eliminates_term)
- *pterm = false_rtx;
-
- if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
- {
- newexp = attr_rtx (GET_CODE (exp), left, right);
-
- exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
- }
- }
-
- if (attr_equal_p (exp, *pterm))
- return false_rtx;
-
- else if (GET_CODE (exp) == NOT && attr_equal_p (XEXP (exp, 0), *pterm))
- return true_rtx;
-
- else if (GET_CODE (*pterm) == NOT && attr_equal_p (XEXP (*pterm, 0), exp))
- return true_rtx;
-
- else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
- && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
- && XSTR (*pterm, 0) == XSTR (XEXP (exp, 0), 0))
- *pterm = false_rtx;
-
- else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
- && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR
- && XSTR (exp, 0) == XSTR (XEXP (*pterm, 0), 0))
- return false_rtx;
-
- return exp;
-}
-/* Compute approximate cost of the expression. Used to decide whether
- expression is cheap enough for inline. */
-static int
-attr_rtx_cost (x)
- rtx x;
-{
- int cost = 0;
- enum rtx_code code;
- if (!x)
- return 0;
- code = GET_CODE (x);
- switch (code)
- {
- case MATCH_OPERAND:
- if (XSTR (x, 1)[0])
- return 10;
- else
- return 0;
- case EQ_ATTR:
- /* Alternatives don't result into function call. */
- if (!strcmp (XSTR (x, 0), "alternative"))
- return 0;
- else
- return 5;
- default:
- {
- int i, j;
- const char *fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- switch (fmt[i])
- {
- case 'V':
- case 'E':
- for (j = 0; j < XVECLEN (x, i); j++)
- cost += attr_rtx_cost (XVECEXP (x, i, j));
- break;
- case 'e':
- cost += attr_rtx_cost (XEXP (x, i));
- break;
- }
- }
- }
- break;
- }
- return cost;
-}
-\f
-
-/* Simplify test expression and use temporary obstack in order to avoid
- memory bloat. Use RTX_UNCHANGING_P to avoid unnecesary simplifications
- and avoid unnecesary copying if possible. */
-
-static rtx
-simplify_test_exp_in_temp (exp, insn_code, insn_index)
- rtx exp;
- int insn_code, insn_index;
-{
- rtx x;
- struct obstack *old;
- if (RTX_UNCHANGING_P (exp))
- return exp;
- old = rtl_obstack;
- rtl_obstack = temp_obstack;
- x = simplify_test_exp (exp, insn_code, insn_index);
- rtl_obstack = old;
- if (x == exp || rtl_obstack == temp_obstack)
- return x;
- return attr_copy_rtx (x);
-}
-
-/* Given an expression, see if it can be simplified for a particular insn
- code based on the values of other attributes being tested. This can
- eliminate nested get_attr_... calls.
-
- Note that if an endless recursion is specified in the patterns, the
- optimization will loop. However, it will do so in precisely the cases where
- an infinite recursion loop could occur during compilation. It's better that
- it occurs here! */
-
-static rtx
-simplify_test_exp (exp, insn_code, insn_index)
- rtx exp;
- int insn_code, insn_index;
-{
- rtx left, right;
- struct attr_desc *attr;
- struct attr_value *av;
- struct insn_ent *ie;
- int i;
- rtx newexp = exp;
-
- /* Don't re-simplify something we already simplified. */
- if (RTX_UNCHANGING_P (exp) || MEM_IN_STRUCT_P (exp))
- return exp;
-
- switch (GET_CODE (exp))
- {
- case AND:
- left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (left);
- if (left == false_rtx)
- return false_rtx;
- right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (right);
- if (left == false_rtx)
- return false_rtx;
-
- /* If either side is an IOR and we have (eq_attr "alternative" ..")
- present on both sides, apply the distributive law since this will
- yield simplifications. */
- if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR)
- && compute_alternative_mask (left, IOR)
- && compute_alternative_mask (right, IOR))
- {
- if (GET_CODE (left) == IOR)
- {
- rtx tem = left;
- left = right;
- right = tem;
- }
-
- newexp = attr_rtx (IOR,
- attr_rtx (AND, left, XEXP (right, 0)),
- attr_rtx (AND, left, XEXP (right, 1)));
-
- return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
- }
-
- /* Try with the term on both sides. */
- right = simplify_and_tree (right, &left, insn_code, insn_index);
- if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
- left = simplify_and_tree (left, &right, insn_code, insn_index);
-
- if (left == false_rtx || right == false_rtx)
- return false_rtx;
- else if (left == true_rtx)
- {
- return right;
- }
- else if (right == true_rtx)
- {
- return left;
- }
- /* See if all or all but one of the insn's alternatives are specified
- in this tree. Optimize if so. */
-
- else if (insn_code >= 0
- && (GET_CODE (left) == AND
- || (GET_CODE (left) == NOT
- && GET_CODE (XEXP (left, 0)) == EQ_ATTR
- && XSTR (XEXP (left, 0), 0) == alternative_name)
- || GET_CODE (right) == AND
- || (GET_CODE (right) == NOT
- && GET_CODE (XEXP (right, 0)) == EQ_ATTR
- && XSTR (XEXP (right, 0), 0) == alternative_name)))
- {
- i = compute_alternative_mask (exp, AND);
- if (i & ~insn_alternatives[insn_code])
- fatal ("Invalid alternative specified for pattern number %d",
- insn_index);
-
- /* If all alternatives are excluded, this is false. */
- i ^= insn_alternatives[insn_code];
- if (i == 0)
- return false_rtx;
- else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
- {
- /* If just one excluded, AND a comparison with that one to the
- front of the tree. The others will be eliminated by
- optimization. We do not want to do this if the insn has one
- alternative and we have tested none of them! */
- left = make_alternative_compare (i);
- right = simplify_and_tree (exp, &left, insn_code, insn_index);
- newexp = attr_rtx (AND, left, right);
-
- return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
- }
- }
-
- if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
- {
- newexp = attr_rtx (AND, left, right);
- return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
- }
- break;
-
- case IOR:
- left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (left);
- if (left == true_rtx)
- return true_rtx;
- right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (right);
- if (right == true_rtx)
- return true_rtx;
-
- right = simplify_or_tree (right, &left, insn_code, insn_index);
- if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
- left = simplify_or_tree (left, &right, insn_code, insn_index);
-
- if (right == true_rtx || left == true_rtx)
- return true_rtx;
- else if (left == false_rtx)
- {
- return right;
- }
- else if (right == false_rtx)
- {
- return left;
- }
-
- /* Test for simple cases where the distributive law is useful. I.e.,
- convert (ior (and (x) (y))
- (and (x) (z)))
- to (and (x)
- (ior (y) (z)))
- */
-
- else if (GET_CODE (left) == AND && GET_CODE (right) == AND
- && attr_equal_p (XEXP (left, 0), XEXP (right, 0)))
- {
- newexp = attr_rtx (IOR, XEXP (left, 1), XEXP (right, 1));
-
- left = XEXP (left, 0);
- right = newexp;
- newexp = attr_rtx (AND, left, right);
- return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
- }
-
- /* See if all or all but one of the insn's alternatives are specified
- in this tree. Optimize if so. */
-
- else if (insn_code >= 0
- && (GET_CODE (left) == IOR
- || (GET_CODE (left) == EQ_ATTR
- && XSTR (left, 0) == alternative_name)
- || GET_CODE (right) == IOR
- || (GET_CODE (right) == EQ_ATTR
- && XSTR (right, 0) == alternative_name)))
- {
- i = compute_alternative_mask (exp, IOR);
- if (i & ~insn_alternatives[insn_code])
- fatal ("Invalid alternative specified for pattern number %d",
- insn_index);
-
- /* If all alternatives are included, this is true. */
- i ^= insn_alternatives[insn_code];
- if (i == 0)
- return true_rtx;
- else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
- {
- /* If just one excluded, IOR a comparison with that one to the
- front of the tree. The others will be eliminated by
- optimization. We do not want to do this if the insn has one
- alternative and we have tested none of them! */
- left = make_alternative_compare (i);
- right = simplify_and_tree (exp, &left, insn_code, insn_index);
- newexp = attr_rtx (IOR, attr_rtx (NOT, left), right);
-
- return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
- }
- }
-
- if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
- {
- newexp = attr_rtx (IOR, left, right);
- return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
- }
- break;
-
- case NOT:
- if (GET_CODE (XEXP (exp, 0)) == NOT)
- {
- left = SIMPLIFY_TEST_EXP (XEXP (XEXP (exp, 0), 0),
- insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (left);
- return left;
- }
-
- left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (left);
- if (GET_CODE (left) == NOT)
- return XEXP (left, 0);
-
- if (left == false_rtx)
- return true_rtx;
- else if (left == true_rtx)
- return false_rtx;
-
- /* Try to apply De`Morgan's laws. */
- else if (GET_CODE (left) == IOR)
- {
- newexp = attr_rtx (AND,
- attr_rtx (NOT, XEXP (left, 0)),
- attr_rtx (NOT, XEXP (left, 1)));
-
- newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
- }
- else if (GET_CODE (left) == AND)
- {
- newexp = attr_rtx (IOR,
- attr_rtx (NOT, XEXP (left, 0)),
- attr_rtx (NOT, XEXP (left, 1)));
-
- newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
- }
- 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;