- This routine is passed an expression and either AND or IOR. It returns a
- bitmask indicating which alternatives are mentioned within EXP. */
-
-static int
-compute_alternative_mask (rtx exp, enum rtx_code code)
-{
- const char *string;
- if (GET_CODE (exp) == code)
- return compute_alternative_mask (XEXP (exp, 0), code)
- | compute_alternative_mask (XEXP (exp, 1), code);
-
- else if (code == AND && GET_CODE (exp) == NOT
- && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
- && XSTR (XEXP (exp, 0), 0) == alternative_name)
- string = XSTR (XEXP (exp, 0), 1);
-
- else if (code == IOR && GET_CODE (exp) == EQ_ATTR
- && XSTR (exp, 0) == alternative_name)
- string = XSTR (exp, 1);
-
- else
- return 0;
-
- if (string[1] == 0)
- return 1 << (string[0] - '0');
- return 1 << atoi (string);
-}
-
-/* Given I, a single-bit mask, return RTX to compare the `alternative'
- attribute with the value represented by that bit. */
-
-static rtx
-make_alternative_compare (int mask)
-{
- rtx newexp;
- int i;
-
- /* Find the bit. */
- for (i = 0; (mask & (1 << i)) == 0; i++)
- ;
-
- newexp = attr_rtx (EQ_ATTR, alternative_name, attr_numeral (i));
- ATTR_IND_SIMPLIFIED_P (newexp) = 1;
-
- return newexp;
-}
-
-/* If we are processing an (eq_attr "attr" "value") test, we find the value
- of "attr" for this insn code. From that value, we can compute a test
- showing when the EQ_ATTR will be true. This routine performs that
- computation. If a test condition involves an address, we leave the EQ_ATTR
- intact because addresses are only valid for the `length' attribute.
-
- EXP is the EQ_ATTR expression and VALUE is the value of that attribute
- for the insn corresponding to INSN_CODE and INSN_INDEX. */
-
-static rtx
-evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
-{
- rtx orexp, andexp;
- rtx right;
- rtx newexp;
- int i;
-
- if (GET_CODE (value) == CONST_STRING)
- {
- if (! strcmp (XSTR (value, 0), XSTR (exp, 1)))
- newexp = true_rtx;
- else
- newexp = false_rtx;
- }
- else if (GET_CODE (value) == SYMBOL_REF)
- {
- char *p;
- char string[256];
-
- if (GET_CODE (exp) != EQ_ATTR)
- abort ();
-
- if (strlen (XSTR (exp, 0)) + strlen (XSTR (exp, 1)) + 2 > 256)
- abort ();
-
- strcpy (string, XSTR (exp, 0));
- strcat (string, "_");
- strcat (string, XSTR (exp, 1));
- for (p = string; *p; p++)
- *p = TOUPPER (*p);
-
- newexp = attr_rtx (EQ, value,
- attr_rtx (SYMBOL_REF,
- attr_string (string, strlen (string))));
- }
- else if (GET_CODE (value) == COND)
- {
- /* We construct an IOR of all the cases for which the requested attribute
- value is present. Since we start with FALSE, if it is not present,
- FALSE will be returned.
-
- Each case is the AND of the NOT's of the previous conditions with the
- current condition; in the default case the current condition is TRUE.
-
- For each possible COND value, call ourselves recursively.
-
- The extra TRUE and FALSE expressions will be eliminated by another
- call to the simplification routine. */
-
- orexp = false_rtx;
- andexp = true_rtx;
-
- if (current_alternative_string)
- clear_struct_flag (value);
-
- for (i = 0; i < XVECLEN (value, 0); i += 2)
- {
- rtx this = simplify_test_exp_in_temp (XVECEXP (value, 0, i),
- insn_code, insn_index);
-
- SIMPLIFY_ALTERNATIVE (this);
-
- 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
- ATTR_IND_SIMPLIFIED_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 (! ATTR_IND_SIMPLIFIED_P (exp))
- return copy_rtx_unchanging (exp);
- return exp;
- }
- else
- return newexp;
-}
-
-/* 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 (rtx exp, rtx *pterm, int insn_code, int 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)))