+find_attrs_to_cache (rtx exp, bool create)
+{
+ int i;
+ const char *name;
+ struct attr_desc *attr;
+
+ if (exp == NULL)
+ return;
+
+ switch (GET_CODE (exp))
+ {
+ case NOT:
+ if (GET_CODE (XEXP (exp, 0)) == EQ_ATTR)
+ find_attrs_to_cache (XEXP (exp, 0), create);
+ return;
+
+ case EQ_ATTR:
+ name = XSTR (exp, 0);
+ if (name == alternative_name)
+ return;
+ for (i = 0; i < cached_attr_count; i++)
+ if (name == cached_attrs[i])
+ {
+ if ((attrs_seen_once & (1U << i)) != 0)
+ attrs_seen_more_than_once |= (1U << i);
+ else
+ attrs_seen_once |= (1U << i);
+ return;
+ }
+ if (!create)
+ return;
+ attr = find_attr (&name, 0);
+ gcc_assert (attr);
+ if (attr->is_const)
+ return;
+ if (cached_attr_count == 32)
+ return;
+ cached_attrs[cached_attr_count] = XSTR (exp, 0);
+ attrs_seen_once |= (1U << cached_attr_count);
+ cached_attr_count++;
+ return;
+
+ case AND:
+ case IOR:
+ find_attrs_to_cache (XEXP (exp, 0), create);
+ find_attrs_to_cache (XEXP (exp, 1), create);
+ return;
+
+ case COND:
+ for (i = 0; i < XVECLEN (exp, 0); i += 2)
+ find_attrs_to_cache (XVECEXP (exp, 0, i), create);
+ return;
+
+ default:
+ return;
+ }
+}
+
+/* Given a piece of RTX, print a C expression to test its truth value.
+ We use AND and IOR both for logical and bit-wise operations, so
+ interpret them as logical unless they are inside a comparison expression. */
+
+/* Interpret AND/IOR as bit-wise operations instead of logical. */
+#define FLG_BITWISE 1
+/* Set if cached attribute will be known initialized in else block after
+ this condition. This is true for LHS of toplevel && and || and
+ even for RHS of ||, but not for RHS of &&. */
+#define FLG_AFTER 2
+/* Set if cached attribute will be known initialized in then block after
+ this condition. This is true for LHS of toplevel && and || and
+ even for RHS of &&, but not for RHS of ||. */
+#define FLG_INSIDE 4
+/* Cleared when an operand of &&. */
+#define FLG_OUTSIDE_AND 8
+
+static unsigned int
+write_test_expr (rtx exp, unsigned int attrs_cached, int flags)