This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Speed up genattrtab


Hello,

this patch speeds up genattrtab significantly. All timings are done
on i686 (and config/i386/i386.md, of course).

1) Genattrtab spends most of its time simplifying complicated logical
   expressions.  The greatest bulk of them are just used to express
   sets of alternatives.  By adding a special representation of them
   (EQ_ATTR_ALT), genattrtab becomes about 3 times faster! (from 103
   seconds to 36).

   I have tested that I maintain correctness and efficiency
    -- insn-attrtab.c is of course different, since sometimes we
       optimize out things that were not optimized and vice versa,
       and we do checks for membership into a set by checking
       (1 << which_alternative) & set), but the changes I have
       investigated are equivalent
    -- the produced programs are identical
    -- the compilation time is unchanged

2) I have also modified a few functions so that all strings are always
   replaced by canonical copies, so that string equality can be verified
   just by comparing pointers.  This improves speed by another ~2% (to
   35 seconds).

Bootstrapped and tested on i686.

Zdenek

	* genattrtab.c (strcmp_check, DEF_ATTR_STRING): New macros.
	(length_str, delay_type_str, delay_1_0_str, num_delay_slots_str):
	New variables.
	(main): Initialize them.
	(count_sub_rtxs): Remove unused function.
	(find_attr): Canonicalize the attribute name string.
	(attr_alt_subset_p, attr_alt_subset_of_compl_p, attr_alt_intersection,
	attr_alt_union, attr_alt_complement, attr_alt_bit_p, mk_attr_alt): New.
	(attr_rtx_1, copy_boolean, expand_delays, gen_unit): Always canonicalize
	string arguments.
	(attr_printf, attr_eq): Use DEF_ATTR_STRING.
	(check_attr_test, check_attr_value, make_length_attrs,
	write_length_unit_log, simplify_by_exploding, gen_attr,
	write_test_expr, write_attr_value, write_eligible_delay,
	write_complex_function, make_internal_attr,
	write_const_num_delay_slots): Changed due to change of type of
	find_attr.
	(simplify_cond): Update indices correctly.
	(check_attr_test, encode_units_mask, compute_alternative_mask,
	make_alternative_compare, simplify_and_tree,
	attr_rtx_cost, simplify_test_exp, gen_attr,
	write_test_expr, walk_attr_value): Handle EQ_ATTR_ALT.
	(fill_attr, evaluate_eq_attr, simplify_and_tree,
	attr_rtx_cost, simplify_by_exploding, walk_attr_value): Use
	strcmp_check.
	* rtl.def (EQ_ATTR_ALT): New.

Index: genattrtab.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/genattrtab.c,v
retrieving revision 1.136
diff -c -3 -p -r1.136 genattrtab.c
*** genattrtab.c	22 Aug 2003 06:45:14 -0000	1.136
--- genattrtab.c	22 Nov 2003 00:11:32 -0000
*************** Software Foundation, 59 Temple Place - S
*** 100,105 ****
--- 100,114 ----
  #define ATTR_PERMANENT_P(RTX) (RTX_FLAG((RTX), integrated))
  #define ATTR_EQ_ATTR_P(RTX) (RTX_FLAG((RTX), volatil))
  
+ #if 0
+ #define strcmp_check(S1, S2) ((S1) == (S2)		\
+ 			      ? 0			\
+ 			      : (strcmp ((S1), (S2))	\
+ 				 ? 1			\
+ 				 : (abort (), 0)))
+ #endif
+ #define strcmp_check(S1, S2) ((S1) != (S2))
+ 
  #include "bconfig.h"
  #include "system.h"
  #include "coretypes.h"
*************** static rtx true_rtx, false_rtx;
*** 339,344 ****
--- 348,357 ----
  /* Used to reduce calls to `strcmp' */
  
  static char *alternative_name;
+ static const char *length_str;
+ static const char *delay_type_str;
+ static const char *delay_1_0_str;
+ static const char *num_delay_slots_str;
  
  /* Indicate that REG_DEAD notes are valid if dead_or_set_p is ever
     called.  */
*************** int optimize = 0;
*** 365,370 ****
--- 378,385 ----
      (EXP) = (XSTR ((EXP), 1) == current_alternative_string	\
  	    ? true_rtx : false_rtx);
  
+ #define DEF_ATTR_STRING(S) (attr_string ((S), strlen (S)))
+ 
  /* These are referenced by rtlanal.c and hence need to be defined somewhere.
     They won't actually be used.  */
  
*************** static rtx test_for_current_value (struc
*** 407,413 ****
  static rtx simplify_with_current_value (rtx, struct dimension *, int);
  static rtx simplify_with_current_value_aux (rtx);
  static void clear_struct_flag (rtx);
- static int count_sub_rtxs    (rtx, int);
  static void remove_insn_ent  (struct attr_value *, struct insn_ent *);
  static void insert_insn_ent  (struct attr_value *, struct insn_ent *);
  static rtx insert_right_side	(enum rtx_code, rtx, rtx, int, int);
--- 422,427 ----
*************** static int write_expr_attr_cache (rtx, s
*** 450,456 ****
  static void write_toplevel_expr	(rtx);
  static void write_const_num_delay_slots (void);
  static char *next_comma_elt	(const char **);
! static struct attr_desc *find_attr (const char *, int);
  static struct attr_value *find_most_used  (struct attr_desc *);
  static rtx find_single_value	(struct attr_desc *);
  static void extend_range	(struct range *, int, int);
--- 464,470 ----
  static void write_toplevel_expr	(rtx);
  static void write_const_num_delay_slots (void);
  static char *next_comma_elt	(const char **);
! static struct attr_desc *find_attr (const char **, int);
  static struct attr_value *find_most_used  (struct attr_desc *);
  static rtx find_single_value	(struct attr_desc *);
  static void extend_range	(struct range *, int, int);
*************** static const char *attr_numeral	(int);
*** 459,464 ****
--- 473,485 ----
  static int attr_equal_p		(rtx, rtx);
  static rtx attr_copy_rtx	(rtx);
  static int attr_rtx_cost	(rtx);
+ static bool attr_alt_subset_p (rtx, rtx);
+ static bool attr_alt_subset_of_compl_p (rtx, rtx);
+ static rtx attr_alt_intersection (rtx, rtx);
+ static rtx attr_alt_union (rtx, rtx);
+ static rtx attr_alt_complement (rtx);
+ static bool attr_alt_bit_p (rtx, int);
+ static rtx mk_attr_alt (int);
  
  #define oballoc(size) obstack_alloc (hash_obstack, size)
  
*************** attr_rtx_1 (enum rtx_code code, va_list 
*** 606,613 ****
      {
        char *arg0 = va_arg (p, char *);
  
!       if (code == SYMBOL_REF)
! 	arg0 = attr_string (arg0, strlen (arg0));
  
        hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
        for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
--- 627,633 ----
      {
        char *arg0 = va_arg (p, char *);
  
!       arg0 = DEF_ATTR_STRING (arg0);
  
        hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
        for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
*************** attr_printf (unsigned int len, const cha
*** 736,749 ****
    vsprintf (str, fmt, p);
    va_end (p);
  
!   return attr_string (str, strlen (str));
  }
  
  static rtx
  attr_eq (const char *name, const char *value)
  {
    return attr_rtx (EQ_ATTR, attr_string (name, strlen (name)),
! 		   attr_string (value, strlen (value)));
  }
  
  static const char *
--- 756,769 ----
    vsprintf (str, fmt, p);
    va_end (p);
  
!   return DEF_ATTR_STRING (str);
  }
  
  static rtx
  attr_eq (const char *name, const char *value)
  {
    return attr_rtx (EQ_ATTR, attr_string (name, strlen (name)),
! 		   DEF_ATTR_STRING (value));
  }
  
  static const char *
*************** check_attr_test (rtx exp, int is_const, 
*** 916,931 ****
  
        else if (n_comma_elts (XSTR (exp, 1)) == 1)
  	{
! 	  attr = find_attr (XSTR (exp, 0), 0);
  	  if (attr == NULL)
  	    {
  	      if (! strcmp (XSTR (exp, 0), "alternative"))
! 		{
! 		  XSTR (exp, 0) = alternative_name;
! 		  /* This can't be simplified any further.  */
! 		  ATTR_IND_SIMPLIFIED_P (exp) = 1;
! 		  return exp;
! 		}
  	      else
  		fatal ("unknown attribute `%s' in EQ_ATTR", XSTR (exp, 0));
  	    }
--- 936,946 ----
  
        else if (n_comma_elts (XSTR (exp, 1)) == 1)
  	{
! 	  attr = find_attr (&XSTR (exp, 0), 0);
  	  if (attr == NULL)
  	    {
  	      if (! strcmp (XSTR (exp, 0), "alternative"))
! 		return mk_attr_alt (1 << atoi (XSTR (exp, 1)));
  	      else
  		fatal ("unknown attribute `%s' in EQ_ATTR", XSTR (exp, 0));
  	    }
*************** check_attr_test (rtx exp, int is_const, 
*** 965,980 ****
  	}
        else
  	{
! 	  /* Make an IOR tree of the possible values.  */
! 	  orexp = false_rtx;
! 	  name_ptr = XSTR (exp, 1);
! 	  while ((p = next_comma_elt (&name_ptr)) != NULL)
  	    {
! 	      newexp = attr_eq (XSTR (exp, 0), p);
! 	      orexp = insert_right_side (IOR, orexp, newexp, -2, -2);
  	    }
  
! 	  return check_attr_test (orexp, is_const, lineno);
  	}
        break;
  
--- 980,1008 ----
  	}
        else
  	{
! 	  if (! strcmp (XSTR (exp, 0), "alternative"))
  	    {
! 	      int set = 0;
! 
! 	      name_ptr = XSTR (exp, 1);
! 	      while ((p = next_comma_elt (&name_ptr)) != NULL)
! 		set |= 1 << atoi (p);
! 
! 	      return mk_attr_alt (set);
  	    }
+ 	  else
+ 	    {
+ 	      /* Make an IOR tree of the possible values.  */
+ 	      orexp = false_rtx;
+ 	      name_ptr = XSTR (exp, 1);
+ 	      while ((p = next_comma_elt (&name_ptr)) != NULL)
+ 		{
+ 		  newexp = attr_eq (XSTR (exp, 0), p);
+ 		  orexp = insert_right_side (IOR, orexp, newexp, -2, -2);
+ 		}
  
! 	      return check_attr_test (orexp, is_const, lineno);
! 	    }
  	}
        break;
  
*************** check_attr_value (rtx exp, struct attr_d
*** 1166,1172 ****
  
      case ATTR:
        {
! 	struct attr_desc *attr2 = find_attr (XSTR (exp, 0), 0);
  	if (attr2 == NULL)
  	  {
  	    message_with_line (attr ? attr->lineno : 0,
--- 1194,1200 ----
  
      case ATTR:
        {
! 	struct attr_desc *attr2 = find_attr (&XSTR (exp, 0), 0);
  	if (attr2 == NULL)
  	  {
  	    message_with_line (attr ? attr->lineno : 0,
*************** check_defs (void)
*** 1326,1332 ****
  	  if (value == NULL_RTX)
  	    continue;
  
! 	  if ((attr = find_attr (XSTR (XEXP (value, 0), 0), 0)) == NULL)
  	    {
  	      message_with_line (id->lineno, "unknown attribute %s",
  				 XSTR (XEXP (value, 0), 0));
--- 1354,1360 ----
  	  if (value == NULL_RTX)
  	    continue;
  
! 	  if ((attr = find_attr (&XSTR (XEXP (value, 0), 0), 0)) == NULL)
  	    {
  	      message_with_line (id->lineno, "unknown attribute %s",
  				 XSTR (XEXP (value, 0), 0));
*************** make_canonical (struct attr_desc *attr, 
*** 1364,1369 ****
--- 1392,1399 ----
  	    fatal ("(attr_value \"*\") used in invalid context");
  	  exp = attr->default_val->value;
  	}
+       else
+ 	XSTR (exp, 0) = DEF_ATTR_STRING (XSTR (exp, 0));
  
        break;
  
*************** copy_boolean (rtx exp)
*** 1424,1429 ****
--- 1454,1470 ----
    if (GET_CODE (exp) == AND || GET_CODE (exp) == IOR)
      return attr_rtx (GET_CODE (exp), copy_boolean (XEXP (exp, 0)),
  		     copy_boolean (XEXP (exp, 1)));
+   if (GET_CODE (exp) == MATCH_OPERAND)
+     {
+       XSTR (exp, 1) = DEF_ATTR_STRING (XSTR (exp, 1));
+       XSTR (exp, 2) = DEF_ATTR_STRING (XSTR (exp, 2));
+     }
+   else if (GET_CODE (exp) == EQ_ATTR)
+     {
+       XSTR (exp, 0) = DEF_ATTR_STRING (XSTR (exp, 0));
+       XSTR (exp, 1) = DEF_ATTR_STRING (XSTR (exp, 1));
+     }
+ 
    return exp;
  }
  
*************** expand_delays (void)
*** 1504,1510 ****
  	= make_numeric_value (XVECLEN (delay->def, 1) / 3);
      }
  
!   make_internal_attr ("*num_delay_slots", condexp, ATTR_NONE);
  
    /* If more than one delay type, do the same for computing the delay type.  */
    if (num_delays > 1)
--- 1545,1551 ----
  	= make_numeric_value (XVECLEN (delay->def, 1) / 3);
      }
  
!   make_internal_attr (num_delay_slots_str, condexp, ATTR_NONE);
  
    /* If more than one delay type, do the same for computing the delay type.  */
    if (num_delays > 1)
*************** expand_delays (void)
*** 1519,1525 ****
  	  XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);
  	}
  
!       make_internal_attr ("*delay_type", condexp, ATTR_SPECIAL);
      }
  
    /* For each delay possibility and delay slot, compute an eligibility
--- 1560,1566 ----
  	  XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);
  	}
  
!       make_internal_attr (delay_type_str, condexp, ATTR_SPECIAL);
      }
  
    /* For each delay possibility and delay slot, compute an eligibility
*************** encode_units_mask (rtx x)
*** 2186,2191 ****
--- 2227,2233 ----
      case PC:
      case CC0:
      case EQ_ATTR:
+     case EQ_ATTR_ALT:
        return x;
  
      default:
*************** fill_attr (struct attr_desc *attr)
*** 2239,2246 ****
        value = NULL;
        if (XVEC (id->def, id->vec_idx))
  	for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
! 	  if (! strcmp (XSTR (XEXP (XVECEXP (id->def, id->vec_idx, i), 0), 0),
! 			attr->name))
  	    value = XEXP (XVECEXP (id->def, id->vec_idx, i), 1);
  
        if (value == NULL)
--- 2281,2288 ----
        value = NULL;
        if (XVEC (id->def, id->vec_idx))
  	for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
! 	  if (! strcmp_check (XSTR (XEXP (XVECEXP (id->def, id->vec_idx, i), 0), 0),
! 			      attr->name))
  	    value = XEXP (XVECEXP (id->def, id->vec_idx, i), 1);
  
        if (value == NULL)
*************** substitute_address (rtx exp, rtx (*no_ad
*** 2337,2345 ****
  static void
  make_length_attrs (void)
  {
!   static const char *const new_names[] = {"*insn_default_length",
! 				      "*insn_variable_length_p",
! 				      "*insn_current_length"};
    static rtx (*const no_address_fn[]) (rtx) = {identity_fn, zero_fn, zero_fn};
    static rtx (*const address_fn[]) (rtx) = {max_fn, one_fn, identity_fn};
    size_t i;
--- 2379,2390 ----
  static void
  make_length_attrs (void)
  {
!   static const char *new_names[] =
!     {
!       "*insn_default_length",
!       "*insn_variable_length_p",
!       "*insn_current_length"
!     };
    static rtx (*const no_address_fn[]) (rtx) = {identity_fn, zero_fn, zero_fn};
    static rtx (*const address_fn[]) (rtx) = {max_fn, one_fn, identity_fn};
    size_t i;
*************** make_length_attrs (void)
*** 2349,2355 ****
  
    /* See if length attribute is defined.  If so, it must be numeric.  Make
       it special so we don't output anything for it.  */
!   length_attr = find_attr ("length", 0);
    if (length_attr == 0)
      return;
  
--- 2394,2400 ----
  
    /* See if length attribute is defined.  If so, it must be numeric.  Make
       it special so we don't output anything for it.  */
!   length_attr = find_attr (&length_str, 0);
    if (length_attr == 0)
      return;
  
*************** make_length_attrs (void)
*** 2366,2372 ****
  			  substitute_address (length_attr->default_val->value,
  					      no_address_fn[i], address_fn[i]),
  			  ATTR_NONE);
!       new_attr = find_attr (new_names[i], 0);
        for (av = length_attr->first_value; av; av = av->next)
  	for (ie = av->first_insn; ie; ie = ie->next)
  	  {
--- 2411,2417 ----
  			  substitute_address (length_attr->default_val->value,
  					      no_address_fn[i], address_fn[i]),
  			  ATTR_NONE);
!       new_attr = find_attr (&new_names[i], 0);
        for (av = length_attr->first_value; av; av = av->next)
  	for (ie = av->first_insn; ie; ie = ie->next)
  	  {
*************** max_fn (rtx exp)
*** 2412,2418 ****
  static void
  write_length_unit_log (void)
  {
!   struct attr_desc *length_attr = find_attr ("length", 0);
    struct attr_value *av;
    struct insn_ent *ie;
    unsigned int length_unit_log, length_or;
--- 2457,2463 ----
  static void
  write_length_unit_log (void)
  {
!   struct attr_desc *length_attr = find_attr (&length_str, 0);
    struct attr_value *av;
    struct insn_ent *ie;
    unsigned int length_unit_log, length_or;
*************** simplify_cond (rtx exp, int insn_code, i
*** 2496,2501 ****
--- 2541,2547 ----
  	  /* If test is false, discard it and its value.  */
  	  for (j = i; j < len - 2; j++)
  	    tests[j] = tests[j + 2];
+ 	  i -= 2;
  	  len -= 2;
  	}
  
*************** simplify_cond (rtx exp, int insn_code, i
*** 2512,2517 ****
--- 2558,2564 ----
  	  for (j = i; j < len - 2; j++)
  	    tests[j] = tests[j + 2];
  	  len -= 2;
+ 	  i -= 2;
  	}
  
        else
*************** compute_alternative_mask (rtx exp, enum 
*** 2682,2687 ****
--- 2729,2744 ----
  	   && XSTR (exp, 0) == alternative_name)
      string = XSTR (exp, 1);
  
+   else if (GET_CODE (exp) == EQ_ATTR_ALT)
+     {
+       if (code == AND && XINT (exp, 1))
+ 	return XINT (exp, 0);
+ 
+       if (code == IOR && !XINT (exp, 1))
+ 	return XINT (exp, 0);
+ 
+       return 0;
+     }
    else
      return 0;
  
*************** compute_alternative_mask (rtx exp, enum 
*** 2696,2712 ****
  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
--- 2753,2759 ----
  static rtx
  make_alternative_compare (int mask)
  {
!   return mk_attr_alt (mask);
  }
  
  /* If we are processing an (eq_attr "attr" "value") test, we find the value
*************** evaluate_eq_attr (rtx exp, rtx value, in
*** 2728,2734 ****
  
    if (GET_CODE (value) == CONST_STRING)
      {
!       if (! strcmp (XSTR (value, 0), XSTR (exp, 1)))
  	newexp = true_rtx;
        else
  	newexp = false_rtx;
--- 2775,2781 ----
  
    if (GET_CODE (value) == CONST_STRING)
      {
!       if (! strcmp_check (XSTR (value, 0), XSTR (exp, 1)))
  	newexp = true_rtx;
        else
  	newexp = false_rtx;
*************** evaluate_eq_attr (rtx exp, rtx value, in
*** 2752,2758 ****
  
        newexp = attr_rtx (EQ, value,
  			 attr_rtx (SYMBOL_REF,
! 				   attr_string (string, strlen (string))));
      }
    else if (GET_CODE (value) == COND)
      {
--- 2799,2805 ----
  
        newexp = attr_rtx (EQ, value,
  			 attr_rtx (SYMBOL_REF,
! 				   DEF_ATTR_STRING (string)));
      }
    else if (GET_CODE (value) == COND)
      {
*************** simplify_and_tree (rtx exp, rtx *pterm, 
*** 2853,2859 ****
        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);
  	}
--- 2900,2906 ----
        right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
        if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
  	{
! 	  newexp = attr_rtx (AND, left, right);
  
  	  exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
  	}
*************** simplify_and_tree (rtx exp, rtx *pterm, 
*** 2876,2882 ****
  
        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);
  	}
--- 2923,2929 ----
  
        if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
  	{
! 	  newexp = attr_rtx (IOR, left, right);
  
  	  exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
  	}
*************** simplify_and_tree (rtx exp, rtx *pterm, 
*** 2894,2905 ****
    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;
--- 2941,2966 ----
    else if (GET_CODE (*pterm) == NOT && exp == XEXP (*pterm, 0))
      return false_rtx;
  
+   else if (GET_CODE (exp) == EQ_ATTR_ALT && GET_CODE (*pterm) == EQ_ATTR_ALT)
+     {
+       if (attr_alt_subset_p (*pterm, exp))
+ 	return true_rtx;
+ 
+       if (attr_alt_subset_of_compl_p (*pterm, exp))
+ 	return false_rtx;
+ 
+       if (attr_alt_subset_p (exp, *pterm))
+ 	*pterm = true_rtx;
+ 	
+       return exp;
+     }
+ 
    else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == EQ_ATTR)
      {
        if (XSTR (exp, 0) != XSTR (*pterm, 0))
  	return exp;
  
!       if (! strcmp_check (XSTR (exp, 1), XSTR (*pterm, 1)))
  	return true_rtx;
        else
  	return false_rtx;
*************** simplify_and_tree (rtx exp, rtx *pterm, 
*** 2911,2917 ****
        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;
--- 2972,2978 ----
        if (XSTR (*pterm, 0) != XSTR (XEXP (exp, 0), 0))
  	return exp;
  
!       if (! strcmp_check (XSTR (*pterm, 1), XSTR (XEXP (exp, 0), 1)))
  	return false_rtx;
        else
  	return true_rtx;
*************** simplify_and_tree (rtx exp, rtx *pterm, 
*** 2923,2929 ****
        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;
--- 2984,2990 ----
        if (XSTR (exp, 0) != XSTR (XEXP (*pterm, 0), 0))
  	return exp;
  
!       if (! strcmp_check (XSTR (exp, 1), XSTR (XEXP (*pterm, 0), 1)))
  	return false_rtx;
        else
  	*pterm = true_rtx;
*************** attr_rtx_cost (rtx x)
*** 3037,3045 ****
  	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;
--- 3098,3109 ----
  	return 10;
        else
  	return 0;
+ 
+     case EQ_ATTR_ALT:
+       return 0;
      case EQ_ATTR:
        /* Alternatives don't result into function call.  */
!       if (!strcmp_check (XSTR (x, 0), alternative_name))
  	return 0;
        else
  	return 5;
*************** simplify_test_exp_in_temp (rtx exp, int 
*** 3087,3092 ****
--- 3151,3296 ----
    return attr_copy_rtx (x);
  }
  
+ /* Returns true if S1 is a subset of S2.  */
+ 
+ static bool
+ attr_alt_subset_p (rtx s1, rtx s2)
+ {
+   switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
+     {
+     case (0 << 1) | 0:
+       return !(XINT (s1, 0) &~ XINT (s2, 0));
+ 
+     case (0 << 1) | 1:
+       return !(XINT (s1, 0) & XINT (s2, 0));
+ 
+     case (1 << 1) | 0:
+       return false;
+ 
+     case (1 << 1) | 1:
+       return !(XINT (s2, 0) &~ XINT (s1, 0));
+ 
+     default:
+       abort ();
+     }
+ }
+ 
+ /* Returns true if S1 is a subset of complement of S2.  */
+ 
+ static bool attr_alt_subset_of_compl_p (rtx s1, rtx s2)
+ {
+   switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
+     {
+     case (0 << 1) | 0:
+       return !(XINT (s1, 0) & XINT (s2, 0));
+ 
+     case (0 << 1) | 1:
+       return !(XINT (s1, 0) & ~XINT (s2, 0));
+ 
+     case (1 << 1) | 0:
+       return !(XINT (s2, 0) &~ XINT (s1, 0));
+ 
+     case (1 << 1) | 1:
+       return false;
+ 
+     default:
+       abort ();
+     }
+ }
+ 
+ /* Return EQ_ATTR_ALT expression representing intersection of S1 and S2.  */
+ 
+ static rtx
+ attr_alt_intersection (rtx s1, rtx s2)
+ {
+   rtx result = rtx_alloc (EQ_ATTR_ALT);
+ 
+   switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
+     {
+     case (0 << 1) | 0:
+       XINT (result, 0) = XINT (s1, 0) & XINT (s2, 0);
+       break;
+     case (0 << 1) | 1:
+       XINT (result, 0) = XINT (s1, 0) & ~XINT (s2, 0);
+       break;
+     case (1 << 1) | 0:
+       XINT (result, 0) = XINT (s2, 0) & ~XINT (s1, 0);
+       break;
+     case (1 << 1) | 1:
+       XINT (result, 0) = XINT (s1, 0) | XINT (s2, 0);
+       break;
+     default:
+       abort ();
+     }
+   XINT (result, 1) = XINT (s1, 1) & XINT (s2, 1);
+ 
+   return result;
+ }
+ 
+ /* Return EQ_ATTR_ALT expression representing union of S1 and S2.  */
+ 
+ static rtx
+ attr_alt_union (rtx s1, rtx s2)
+ {
+   rtx result = rtx_alloc (EQ_ATTR_ALT);
+ 
+   switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
+     {
+     case (0 << 1) | 0:
+       XINT (result, 0) = XINT (s1, 0) | XINT (s2, 0);
+       break;
+     case (0 << 1) | 1:
+       XINT (result, 0) = XINT (s2, 0) & ~XINT (s1, 0);
+       break;
+     case (1 << 1) | 0:
+       XINT (result, 0) = XINT (s1, 0) & ~XINT (s2, 0);
+       break;
+     case (1 << 1) | 1:
+       XINT (result, 0) = XINT (s1, 0) & XINT (s2, 0);
+       break;
+     default:
+       abort ();
+     }
+ 
+   XINT (result, 1) = XINT (s1, 1) | XINT (s2, 1);
+   return result;
+ }
+ 
+ /* Return EQ_ATTR_ALT expression representing complement of S.  */
+ 
+ static rtx
+ attr_alt_complement (rtx s)
+ {
+   rtx result = rtx_alloc (EQ_ATTR_ALT);
+ 
+   XINT (result, 0) = XINT (s, 0);
+   XINT (result, 1) = 1 - XINT (s, 1);
+ 
+   return result;
+ }
+ 
+ /* Tests whether a bit B belongs to the set represented by S.  */
+ 
+ static bool
+ attr_alt_bit_p (rtx s, int b)
+ {
+   return XINT (s, 1) ^ ((XINT (s, 0) >> b) & 1);
+ }
+ 
+ /* Return EQ_ATTR_ALT expression representing set containing elements set
+    in E.  */
+ 
+ static rtx
+ mk_attr_alt (int e)
+ {
+   rtx result = rtx_alloc (EQ_ATTR_ALT);
+ 
+   XINT (result, 0) = e;
+   XINT (result, 1) = 0;
+ 
+   return result;
+ }
+ 
  /* 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.
*************** simplify_test_exp (rtx exp, int insn_cod
*** 3105,3110 ****
--- 3309,3315 ----
    struct insn_ent *ie;
    int i;
    rtx newexp = exp;
+   bool left_alt, right_alt;
  
    /* Don't re-simplify something we already simplified.  */
    if (ATTR_IND_SIMPLIFIED_P (exp) || ATTR_CURR_SIMPLIFIED_P (exp))
*************** simplify_test_exp (rtx exp, int insn_cod
*** 3122,3127 ****
--- 3327,3339 ----
        if (left == false_rtx)
  	return false_rtx;
  
+       if (GET_CODE (left) == EQ_ATTR_ALT
+ 	  && GET_CODE (right) == EQ_ATTR_ALT)
+ 	{
+ 	  exp = attr_alt_intersection (left, right);
+ 	  return simplify_test_exp (exp, insn_code, insn_index);
+ 	}
+ 
        /* 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.  */
*************** simplify_test_exp (rtx exp, int insn_cod
*** 3161,3175 ****
        /* 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])
--- 3373,3397 ----
        /* See if all or all but one of the insn's alternatives are specified
  	 in this tree.  Optimize if so.  */
  
!       if (GET_CODE (left) == NOT)
! 	left_alt = (GET_CODE (XEXP (left, 0)) == EQ_ATTR
! 		    && XSTR (XEXP (left, 0), 0) == alternative_name);
!       else
! 	left_alt = (GET_CODE (left) == EQ_ATTR_ALT
! 		    && XINT (left, 1));
! 
!       if (GET_CODE (right) == NOT)
! 	right_alt = (GET_CODE (XEXP (right, 0)) == EQ_ATTR
! 		     && XSTR (XEXP (right, 0), 0) == alternative_name);
!       else
! 	right_alt = (GET_CODE (right) == EQ_ATTR_ALT
! 		     && XINT (right, 1));
! 
!       if (insn_code >= 0
! 	  && (GET_CODE (left) == AND
! 	      || left_alt
! 	      || GET_CODE (right) == AND
! 	      || right_alt))
  	{
  	  i = compute_alternative_mask (exp, AND);
  	  if (i & ~insn_alternatives[insn_code])
*************** simplify_test_exp (rtx exp, int insn_cod
*** 3211,3216 ****
--- 3433,3445 ----
        if (right == true_rtx)
  	return true_rtx;
  
+       if (GET_CODE (left) == EQ_ATTR_ALT
+ 	  && GET_CODE (right) == EQ_ATTR_ALT)
+ 	{
+ 	  exp = attr_alt_union (left, right);
+ 	  return simplify_test_exp (exp, insn_code, insn_index);
+ 	}
+ 
        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);
*************** simplify_test_exp (rtx exp, int insn_cod
*** 3249,3257 ****
--- 3478,3490 ----
  
        else if (insn_code >= 0
  	       && (GET_CODE (left) == IOR
+ 		   || (GET_CODE (left) == EQ_ATTR_ALT
+ 		       && !XINT (left, 1))
  		   || (GET_CODE (left) == EQ_ATTR
  		       && XSTR (left, 0) == alternative_name)
  		   || GET_CODE (right) == IOR
+ 		   || (GET_CODE (right) == EQ_ATTR_ALT
+ 		       && !XINT (right, 1))
  		   || (GET_CODE (right) == EQ_ATTR
  		       && XSTR (right, 0) == alternative_name)))
  	{
*************** simplify_test_exp (rtx exp, int insn_cod
*** 3301,3311 ****
  
        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)),
--- 3534,3550 ----
  
        if (left == false_rtx)
  	return true_rtx;
!       if (left == true_rtx)
  	return false_rtx;
  
+       if (GET_CODE (left) == EQ_ATTR_ALT)
+ 	{
+ 	  exp = attr_alt_complement (left);
+ 	  return simplify_test_exp (exp, insn_code, insn_index);
+ 	}
+ 
        /* Try to apply De`Morgan's laws.  */
!       if (GET_CODE (left) == IOR)
  	{
  	  newexp = attr_rtx (AND,
  			     attr_rtx (NOT, XEXP (left, 0)),
*************** simplify_test_exp (rtx exp, int insn_cod
*** 3327,3342 ****
  	}
        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)
--- 3566,3595 ----
  	}
        break;
  
+     case EQ_ATTR_ALT:
+       if (current_alternative_string)
+ 	return attr_alt_bit_p (exp, atoi (current_alternative_string)) ? true_rtx : false_rtx;
+ 
+       if (!XINT (exp, 0))
+ 	return XINT (exp, 1) ? true_rtx : false_rtx;
+       break;
+ 
      case EQ_ATTR:
        if (current_alternative_string && XSTR (exp, 0) == alternative_name)
  	return (XSTR (exp, 1) == current_alternative_string
  		? true_rtx : false_rtx);
  
+       if (XSTR (exp, 0) == alternative_name)
+ 	{
+ 	  newexp = mk_attr_alt (1 << atoi (XSTR (exp, 1)));
+ 	  break;
+ 	}
+ 
        /* 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)
*************** simplify_by_exploding (rtx exp)
*** 3500,3506 ****
        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);
--- 3753,3762 ----
        const char *name = XSTR (XEXP (list, 0), 0);
        rtx *prev;
  
!       space[ndim].attr = find_attr (&name, 0);
!       XSTR (XEXP (list, 0), 0) = name;
! 
!       if (space[ndim].attr == 0
  	  || space[ndim].attr->is_numeric)
  	{
  	  unmark_used_attributes (list, space, ndim);
*************** simplify_by_exploding (rtx exp)
*** 3512,3518 ****
        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);
--- 3768,3774 ----
        space[ndim].values = 0;
        prev = &list;
        for (link = list; link; link = *prev)
! 	if (! strcmp_check (XSTR (XEXP (link, 0), 0), name))
  	  {
  	    space[ndim].num_values++;
  	    *prev = XEXP (link, 1);
*************** clear_struct_flag (rtx x)
*** 3954,4018 ****
      }
  }
  
- /* Return the number of RTX objects making up the expression X.
-    But if we count more than MAX objects, stop counting.  */
- 
- static int
- count_sub_rtxs (rtx x, int max)
- {
-   int i;
-   int j;
-   enum rtx_code code;
-   const char *fmt;
-   int total = 0;
- 
-   code = GET_CODE (x);
- 
-   switch (code)
-     {
-     case REG:
-     case QUEUED:
-     case CONST_INT:
-     case CONST_DOUBLE:
-     case CONST_VECTOR:
-     case SYMBOL_REF:
-     case CODE_LABEL:
-     case PC:
-     case CC0:
-     case EQ_ATTR:
-     case ATTR_FLAG:
-       return 1;
- 
-     default:
-       break;
-     }
- 
-   /* Compare the elements.  If any pair of corresponding elements
-      fail to match, return 0 for the whole things.  */
- 
-   fmt = GET_RTX_FORMAT (code);
-   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-     {
-       if (total >= max)
- 	return total;
- 
-       switch (fmt[i])
- 	{
- 	case 'V':
- 	case 'E':
- 	  for (j = 0; j < XVECLEN (x, i); j++)
- 	    total += count_sub_rtxs (XVECEXP (x, i, j), max);
- 	  break;
- 
- 	case 'e':
- 	  total += count_sub_rtxs (XEXP (x, i), max);
- 	  break;
- 	}
-     }
-   return total;
- 
- }
- 
  /* Create table entries for DEFINE_ATTR.  */
  
  static void
--- 4210,4215 ----
*************** gen_attr (rtx exp, int lineno)
*** 4025,4031 ****
  
    /* Make a new attribute structure.  Check for duplicate by looking at
       attr->default_val, since it is initialized by this routine.  */
!   attr = find_attr (XSTR (exp, 0), 1);
    if (attr->default_val)
      {
        message_with_line (lineno, "duplicate definition for attribute %s",
--- 4222,4228 ----
  
    /* Make a new attribute structure.  Check for duplicate by looking at
       attr->default_val, since it is initialized by this routine.  */
!   attr = find_attr (&XSTR (exp, 0), 1);
    if (attr->default_val)
      {
        message_with_line (lineno, "duplicate definition for attribute %s",
*************** gen_attr (rtx exp, int lineno)
*** 4067,4073 ****
        XEXP (exp, 2) = XEXP (XEXP (exp, 2), 0);
      }
  
!   if (! strcmp (attr->name, "length") && ! attr->is_numeric)
      {
        message_with_line (lineno,
  			 "`length' attribute must take numeric values");
--- 4264,4270 ----
        XEXP (exp, 2) = XEXP (XEXP (exp, 2), 0);
      }
  
!   if (! strcmp_check (attr->name, length_str) && ! attr->is_numeric)
      {
        message_with_line (lineno,
  			 "`length' attribute must take numeric values");
*************** gen_unit (rtx def, int lineno)
*** 4311,4316 ****
--- 4508,4515 ----
        unit->first_lineno = lineno;
        units = unit;
      }
+   else
+     XSTR (def, 0) = unit->name;
  
    /* Make a new operation class structure entry and initialize it.  */
    op = oballoc (sizeof (struct function_unit_op));
*************** write_test_expr (rtx exp, int flags)
*** 4490,4495 ****
--- 4689,4740 ----
        write_test_expr (XEXP (exp, 0), flags);
        break;
  
+     case EQ_ATTR_ALT:
+ 	{
+ 	  int set = XINT (exp, 0), bit = 0;
+ 
+ 	  if (flags & 1)
+ 	    fatal ("EQ_ATTR_ALT not valid inside comparison");
+ 
+ 	  if (!set)
+ 	    fatal ("Empty EQ_ATTR_ALT should be optimized out");
+ 
+ 	  if (!(set & (set - 1)))
+ 	    {
+ 	      if (!(set & 0xffff))
+ 		{
+ 		  bit += 16;
+ 		  set >>= 16;
+ 		}
+ 	      if (!(set & 0xff))
+ 		{
+ 		  bit += 8;
+ 		  set >>= 8;
+ 		}
+ 	      if (!(set & 0xf))
+ 		{
+ 		  bit += 4;
+ 		  set >>= 4;
+ 		}
+ 	      if (!(set & 0x3))
+ 		{
+ 		  bit += 2;
+ 		  set >>= 2;
+ 		}
+ 	      if (!(set & 1))
+ 		bit++;
+ 
+ 	      printf ("which_alternative %s= %d",
+ 		      XINT (exp, 1) ? "!" : "=", bit);
+ 	    }
+ 	  else
+ 	    {
+ 	      printf ("%s((1 << which_alternative) & 0x%x)",
+ 		      XINT (exp, 1) ? "!" : "", set);
+ 	    }
+ 	}
+       break;
+ 
      /* Comparison test of an attribute with a value.  Most of these will
         have been removed by optimization.   Handle "alternative"
         specially and give error if EQ_ATTR present inside a comparison.  */
*************** write_test_expr (rtx exp, int flags)
*** 4503,4509 ****
  	  break;
  	}
  
!       attr = find_attr (XSTR (exp, 0), 0);
        if (! attr)
  	abort ();
  
--- 4748,4754 ----
  	  break;
  	}
  
!       attr = find_attr (&XSTR (exp, 0), 0);
        if (! attr)
  	abort ();
  
*************** walk_attr_value (rtx exp)
*** 4710,4719 ****
        must_extract = 1;
        return;
  
      case EQ_ATTR:
        if (XSTR (exp, 0) == alternative_name)
  	must_extract = must_constrain = 1;
!       else if (strcmp (XSTR (exp, 0), "length") == 0)
  	length_used = 1;
        return;
  
--- 4955,4968 ----
        must_extract = 1;
        return;
  
+     case EQ_ATTR_ALT:
+       must_extract = must_constrain = 1;
+       break;
+ 
      case EQ_ATTR:
        if (XSTR (exp, 0) == alternative_name)
  	must_extract = must_constrain = 1;
!       else if (strcmp_check (XSTR (exp, 0), length_str) == 0)
  	length_used = 1;
        return;
  
*************** write_attr_value (struct attr_desc *attr
*** 5176,5182 ****
  
      case ATTR:
        {
! 	struct attr_desc *attr2 = find_attr (XSTR (value, 0), 0);
  	printf ("get_attr_%s (%s)", attr2->name,
  		(attr2->is_const ? "" : "insn"));
        }
--- 5425,5431 ----
  
      case ATTR:
        {
! 	struct attr_desc *attr2 = find_attr (&XSTR (value, 0), 0);
  	printf ("get_attr_%s (%s)", attr2->name,
  		(attr2->is_const ? "" : "insn"));
        }
*************** write_eligible_delay (const char *kind)
*** 5250,5255 ****
--- 5499,5505 ----
    struct delay_desc *delay;
    int max_slots;
    char str[50];
+   const char *pstr;
    struct attr_desc *attr;
    struct attr_value *av, *common_av;
    int i;
*************** write_eligible_delay (const char *kind)
*** 5278,5284 ****
  
    if (num_delays > 1)
      {
!       attr = find_attr ("*delay_type", 0);
        if (! attr)
  	abort ();
        common_av = find_most_used (attr);
--- 5528,5534 ----
  
    if (num_delays > 1)
      {
!       attr = find_attr (&delay_type_str, 0);
        if (! attr)
  	abort ();
        common_av = find_most_used (attr);
*************** write_eligible_delay (const char *kind)
*** 5307,5313 ****
        printf ("  switch (recog_memoized (insn))\n");
        printf ("    {\n");
  
!       attr = find_attr ("*delay_1_0", 0);
        if (! attr)
  	abort ();
        common_av = find_most_used (attr);
--- 5557,5563 ----
        printf ("  switch (recog_memoized (insn))\n");
        printf ("    {\n");
  
!       attr = find_attr (&delay_1_0_str, 0);
        if (! attr)
  	abort ();
        common_av = find_most_used (attr);
*************** write_eligible_delay (const char *kind)
*** 5337,5343 ****
  	    printf ("\t{\n");
  
  	    sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3);
! 	    attr = find_attr (str, 0);
  	    if (! attr)
  	      abort ();
  	    common_av = find_most_used (attr);
--- 5587,5594 ----
  	    printf ("\t{\n");
  
  	    sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3);
! 	    pstr = str;
! 	    attr = find_attr (&pstr, 0);
  	    if (! attr)
  	      abort ();
  	    common_av = find_most_used (attr);
*************** write_complex_function (struct function_
*** 5441,5446 ****
--- 5692,5698 ----
    struct attr_value *av, *common_av;
    rtx value;
    char str[256];
+   const char *pstr;
    int using_case;
    int i;
  
*************** write_complex_function (struct function_
*** 5458,5464 ****
    if (strlen (unit->name) + sizeof "*_cases" > 256)
      abort ();
    sprintf (str, "*%s_cases", unit->name);
!   case_attr = find_attr (str, 0);
    if (! case_attr)
      abort ();
    common_av = find_most_used (case_attr);
--- 5710,5717 ----
    if (strlen (unit->name) + sizeof "*_cases" > 256)
      abort ();
    sprintf (str, "*%s_cases", unit->name);
!   pstr = str;
!   case_attr = find_attr (&pstr, 0);
    if (! case_attr)
      abort ();
    common_av = find_most_used (case_attr);
*************** write_complex_function (struct function_
*** 5492,5498 ****
  
        printf ("    case %d:\n", i);
        sprintf (str, "*%s_%s_%d", unit->name, connection, i);
!       attr = find_attr (str, 0);
        if (! attr)
  	abort ();
  
--- 5745,5752 ----
  
        printf ("    case %d:\n", i);
        sprintf (str, "*%s_%s_%d", unit->name, connection, i);
!       pstr = str;
!       attr = find_attr (&pstr, 0);
        if (! attr)
  	abort ();
  
*************** next_comma_elt (const char **pstr)
*** 5547,5556 ****
     is nonzero, build a new attribute, if one does not exist.  */
  
  static struct attr_desc *
! find_attr (const char *name, int create)
  {
    struct attr_desc *attr;
    int index;
  
    /* Before we resort to using `strcmp', see if the string address matches
       anywhere.  In most cases, it should have been canonicalized to do so.  */
--- 5801,5811 ----
     is nonzero, build a new attribute, if one does not exist.  */
  
  static struct attr_desc *
! find_attr (const char **name_p, int create)
  {
    struct attr_desc *attr;
    int index;
+   const char *name = *name_p;
  
    /* Before we resort to using `strcmp', see if the string address matches
       anywhere.  In most cases, it should have been canonicalized to do so.  */
*************** find_attr (const char *name, int create)
*** 5565,5583 ****
    /* Otherwise, do it the slow way.  */
    for (attr = attrs[index]; attr; attr = attr->next)
      if (name[0] == attr->name[0] && ! strcmp (name, attr->name))
!       return attr;
  
    if (! create)
      return NULL;
  
    attr = oballoc (sizeof (struct attr_desc));
!   attr->name = attr_string (name, strlen (name));
    attr->first_value = attr->default_val = NULL;
    attr->is_numeric = attr->negative_ok = attr->is_const = attr->is_special = 0;
    attr->unsigned_p = attr->func_units_p = attr->blockage_p = attr->static_p = 0;
    attr->next = attrs[index];
    attrs[index] = attr;
  
    return attr;
  }
  
--- 5820,5843 ----
    /* Otherwise, do it the slow way.  */
    for (attr = attrs[index]; attr; attr = attr->next)
      if (name[0] == attr->name[0] && ! strcmp (name, attr->name))
!       {
! 	*name_p = attr->name;
! 	return attr;
!       }
  
    if (! create)
      return NULL;
  
    attr = oballoc (sizeof (struct attr_desc));
!   attr->name = DEF_ATTR_STRING (name);
    attr->first_value = attr->default_val = NULL;
    attr->is_numeric = attr->negative_ok = attr->is_const = attr->is_special = 0;
    attr->unsigned_p = attr->func_units_p = attr->blockage_p = attr->static_p = 0;
    attr->next = attrs[index];
    attrs[index] = attr;
  
+   *name_p = attr->name;
+ 
    return attr;
  }
  
*************** make_internal_attr (const char *name, rt
*** 5588,5594 ****
  {
    struct attr_desc *attr;
  
!   attr = find_attr (name, 1);
    if (attr->default_val)
      abort ();
  
--- 5848,5854 ----
  {
    struct attr_desc *attr;
  
!   attr = find_attr (&name, 1);
    if (attr->default_val)
      abort ();
  
*************** copy_rtx_unchanging (rtx orig)
*** 5693,5699 ****
  static void
  write_const_num_delay_slots (void)
  {
!   struct attr_desc *attr = find_attr ("*num_delay_slots", 0);
    struct attr_value *av;
    struct insn_ent *ie;
  
--- 5953,5959 ----
  static void
  write_const_num_delay_slots (void)
  {
!   struct attr_desc *attr = find_attr (&num_delay_slots_str, 0);
    struct attr_value *av;
    struct insn_ent *ie;
  
*************** main (int argc, char **argv)
*** 5751,5757 ****
    ATTR_IND_SIMPLIFIED_P (true_rtx) = ATTR_IND_SIMPLIFIED_P (false_rtx) = 1;
    ATTR_PERMANENT_P (true_rtx) = ATTR_PERMANENT_P (false_rtx) = 1;
  
!   alternative_name = attr_string ("alternative", strlen ("alternative"));
  
    printf ("/* Generated automatically by the program `genattrtab'\n\
  from the machine description file `md'.  */\n\n");
--- 6011,6021 ----
    ATTR_IND_SIMPLIFIED_P (true_rtx) = ATTR_IND_SIMPLIFIED_P (false_rtx) = 1;
    ATTR_PERMANENT_P (true_rtx) = ATTR_PERMANENT_P (false_rtx) = 1;
  
!   alternative_name = DEF_ATTR_STRING ("alternative");
!   length_str = DEF_ATTR_STRING ("length");
!   delay_type_str = DEF_ATTR_STRING ("*delay_type");
!   delay_1_0_str = DEF_ATTR_STRING ("*delay_1_0");
!   num_delay_slots_str = DEF_ATTR_STRING ("*num_delay_slots");
  
    printf ("/* Generated automatically by the program `genattrtab'\n\
  from the machine description file `md'.  */\n\n");
*************** from the machine description file `md'. 
*** 5934,5940 ****
  
  	    insn_alts_p
  	      = (attr->name [0] == '*'
! 		 && strcmp (&attr->name [1], INSN_ALTS_FUNC_NAME) == 0);
  	    if (insn_alts_p)
  	      printf ("\n#if AUTOMATON_ALTS\n");
  	    write_attr_get (attr);
--- 6198,6204 ----
  
  	    insn_alts_p
  	      = (attr->name [0] == '*'
! 		 && strcmp (&attr->name[1], INSN_ALTS_FUNC_NAME) == 0);
  	    if (insn_alts_p)
  	      printf ("\n#if AUTOMATON_ALTS\n");
  	    write_attr_get (attr);
Index: rtl.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.def,v
retrieving revision 1.74
diff -c -3 -p -r1.74 rtl.def
*** rtl.def	21 Nov 2003 04:05:05 -0000	1.74
--- rtl.def	22 Nov 2003 00:11:33 -0000
*************** DEF_RTL_EXPR(SET_ATTR_ALTERNATIVE, "set_
*** 582,587 ****
--- 582,591 ----
     attribute name and the second is the comparison value.  */
  DEF_RTL_EXPR(EQ_ATTR, "eq_attr", "ss", 'x')
  
+ /* A special case of the above representing a set of alternatives.  The first
+    operand is bitmap of the set, the second one is the default value.  */
+ DEF_RTL_EXPR(EQ_ATTR_ALT, "eq_attr_alt", "ii", 'x')
+ 
  /* A conditional expression which is true if the specified flag is
     true for the insn being scheduled in reorg.
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]