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]

genattrtab enhancement


The following patch allows a target to use more interesting
expressions in numeric attributes, and in particular, make
calls from one attribute to another.


r~


+ 	* genattrtab.c (check_attr_value): Allow negative const_int if
+ 	negative_ok.  Accept integral arithmetic operators.  Accept
+ 	direct references to other attributes.  Accept symbol_ref in
+ 	non-constant attributes.
+ 	(max_attr_value): Add new argument `unknownp'.  Update all callers.
+ 	(or_attr_value): Likewise.
+ 	(simplify_knowing): Don't optimize if max_attr_value unknown.
+ 	(write_length_unit_log): Likewise with or_attr_value.
+ 	(find_and_mark_used_attributes): Don't fallthru case.
+ 	(write_attr_set): Pass thru all non-cond expressions.
+ 	(write_attr_value): Handle symbol_ref, attr, and arithmetic.

Index: genattrtab.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/genattrtab.c,v
retrieving revision 1.45
diff -c -p -d -r1.45 genattrtab.c
*** genattrtab.c	1999/01/22 11:51:53	1.45
--- genattrtab.c	1999/02/22 01:38:23
*************** static void gen_insn		PROTO((rtx));
*** 426,433 ****
  static void gen_delay		PROTO((rtx));
  static void gen_unit		PROTO((rtx));
  static void write_test_expr	PROTO((rtx, int));
! static int max_attr_value	PROTO((rtx));
! static int or_attr_value	PROTO((rtx));
  static void walk_attr_value	PROTO((rtx));
  static void write_attr_get	PROTO((struct attr_desc *));
  static rtx eliminate_known_true PROTO((rtx, rtx, int, int));
--- 426,433 ----
  static void gen_delay		PROTO((rtx));
  static void gen_unit		PROTO((rtx));
  static void write_test_expr	PROTO((rtx, int));
! static int max_attr_value	PROTO((rtx, int*));
! static int or_attr_value	PROTO((rtx, int*));
  static void walk_attr_value	PROTO((rtx));
  static void write_attr_get	PROTO((struct attr_desc *));
  static rtx eliminate_known_true PROTO((rtx, rtx, int, int));
*************** check_attr_value (exp, attr)
*** 1083,1089 ****
  	fatal ("CONST_INT not valid for non-numeric `%s' attribute",
  	       attr->name);
  
!       if (INTVAL (exp) < 0)
  	fatal ("Negative numeric value specified for `%s' attribute",
  	       attr->name);
  
--- 1083,1089 ----
  	fatal ("CONST_INT not valid for non-numeric `%s' attribute",
  	       attr->name);
  
!       if (INTVAL (exp) < 0 && ! attr->negative_ok)
  	fatal ("Negative numeric value specified for `%s' attribute",
  	       attr->name);
  
*************** check_attr_value (exp, attr)
*** 1123,1128 ****
--- 1123,1138 ----
        XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
        break;
  
+     case PLUS:
+     case MINUS:
+     case MULT:
+     case DIV:
+     case MOD:
+       if (attr && !attr->is_numeric)
+ 	fatal ("Invalid operation `%s' for non-numeric attribute value",
+ 	       GET_RTX_NAME (GET_CODE (exp)));
+       /* FALLTHRU */
+ 
      case IOR:
      case AND:
        XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr);
*************** check_attr_value (exp, attr)
*** 1148,1159 ****
        XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
        break;
  
      case SYMBOL_REF:
!       if (attr && attr->is_const)
! 	/* A constant SYMBOL_REF is valid as a constant attribute test and
! 	   is expanded later by make_canonical into a COND.  */
! 	return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
!       /* Otherwise, fall through...  */
  
      default:
        fatal ("Invalid operation `%s' for attribute value",
--- 1158,1184 ----
        XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
        break;
  
+     case ATTR:
+       {
+ 	struct attr_desc *attr2 = find_attr (XSTR (exp, 0), 0);
+ 	if (attr2 == NULL)
+ 	  fatal ("Unknown attribute `%s' in ATTR", XSTR (exp, 0));
+ 	else if ((attr && attr->is_const) && ! attr2->is_const)
+ 	  fatal ("Non-constant attribute `%s' referenced from `%s'",
+ 		 XSTR (exp, 0), attr->name);
+ 	else if (attr 
+ 		 && (attr->is_numeric != attr2->is_numeric
+ 		     || (! attr->negative_ok && attr2->negative_ok)))
+ 	  fatal ("Numeric attribute mismatch calling `%s' from `%s'",
+ 		 XSTR (exp, 0), attr->name);
+       }
+       break;
+ 
      case SYMBOL_REF:
!       /* A constant SYMBOL_REF is valid as a constant attribute test and
!          is expanded later by make_canonical into a COND.  In a non-constant
!          attribute test, it is left be.  */
!       return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
  
      default:
        fatal ("Invalid operation `%s' for attribute value",
*************** expand_units ()
*** 2101,2107 ****
  	    }
  
  	  /* Record MAX (BLOCKAGE (*,*)).  */
! 	  unit->max_blockage = max_attr_value (max_blockage);
  
  	  /* See if the upper and lower bounds of BLOCKAGE (E,*) are the
  	     same.  If so, the blockage function carries no additional
--- 2126,2135 ----
  	    }
  
  	  /* Record MAX (BLOCKAGE (*,*)).  */
! 	  {
! 	    int unknown;
! 	    unit->max_blockage = max_attr_value (max_blockage, &unknown);
! 	  }
  
  	  /* See if the upper and lower bounds of BLOCKAGE (E,*) are the
  	     same.  If so, the blockage function carries no additional
*************** simplify_knowing (exp, known_true)
*** 2186,2194 ****
  {
    if (GET_CODE (exp) != CONST_STRING)
      {
!       exp = attr_rtx (IF_THEN_ELSE, known_true, exp,
! 		      make_numeric_value (max_attr_value (exp)));
!       exp = simplify_by_exploding (exp);
      }
    return exp;
  }
--- 2214,2227 ----
  {
    if (GET_CODE (exp) != CONST_STRING)
      {
!       int unknown, max;
!       max = max_attr_value (exp, &unknown);
!       if (! unknown)
! 	{
! 	  exp = attr_rtx (IF_THEN_ELSE, known_true, exp,
! 		          make_numeric_value (max));
!           exp = simplify_by_exploding (exp);
! 	}
      }
    return exp;
  }
*************** static rtx
*** 2458,2464 ****
  max_fn (exp)
       rtx exp;
  {
!   return make_numeric_value (max_attr_value (exp));
  }
  
  static void
--- 2491,2498 ----
  max_fn (exp)
       rtx exp;
  {
!   int unknown;
!   return make_numeric_value (max_attr_value (exp, &unknown));
  }
  
  static void
*************** write_length_unit_log ()
*** 2468,2483 ****
    struct attr_value *av;
    struct insn_ent *ie;
    unsigned int length_unit_log, length_or;
  
    if (length_attr == 0)
      return;
!   length_or = or_attr_value (length_attr->default_val->value);
!     for (av = length_attr->first_value; av; av = av->next)
!       for (ie = av->first_insn; ie; ie = ie->next)
! 	length_or |= or_attr_value (av->value);
!   length_or = ~length_or;
!   for (length_unit_log = 0; length_or & 1; length_or >>= 1)
!     length_unit_log++;
    printf ("int length_unit_log = %u;\n", length_unit_log);
  }
  
--- 2502,2524 ----
    struct attr_value *av;
    struct insn_ent *ie;
    unsigned int length_unit_log, length_or;
+   int unknown = 0;
  
    if (length_attr == 0)
      return;
!   length_or = or_attr_value (length_attr->default_val->value, &unknown);
!   for (av = length_attr->first_value; av; av = av->next)
!     for (ie = av->first_insn; ie; ie = ie->next)
!       length_or |= or_attr_value (av->value, &unknown);
! 
!   if (unknown)
!     length_unit_log = 0;
!   else
!     {
!       length_or = ~length_or;
!       for (length_unit_log = 0; length_or & 1; length_or >>= 1)
!         length_unit_log++;
!     }
    printf ("int length_unit_log = %u;\n", length_unit_log);
  }
  
*************** find_and_mark_used_attributes (exp, term
*** 3703,3708 ****
--- 3744,3751 ----
  	  *nterms += 1;
  	  MEM_VOLATILE_P (exp) = 1;
  	}
+       return 1;
+ 
      case CONST_STRING:
      case CONST_INT:
        return 1;
*************** gen_attr (exp)
*** 4106,4112 ****
      fatal ("Duplicate definition for `%s' attribute", attr->name);
  
    if (*XSTR (exp, 1) == '\0')
!       attr->is_numeric = 1;
    else
      {
        name_ptr = XSTR (exp, 1);
--- 4149,4155 ----
      fatal ("Duplicate definition for `%s' attribute", attr->name);
  
    if (*XSTR (exp, 1) == '\0')
!     attr->is_numeric = 1;
    else
      {
        name_ptr = XSTR (exp, 1);
*************** write_test_expr (exp, flags)
*** 4652,4731 ****
  }
  
  /* Given an attribute value, return the maximum CONST_STRING argument
!    encountered.  It is assumed that they are all numeric.  */
  
  static int
! max_attr_value (exp)
       rtx exp;
  {
!   int current_max = 0;
!   int n;
!   int i;
! 
!   if (GET_CODE (exp) == CONST_STRING)
!     return atoi (XSTR (exp, 0));
  
!   else if (GET_CODE (exp) == COND)
      {
        for (i = 0; i < XVECLEN (exp, 0); i += 2)
  	{
! 	  n = max_attr_value (XVECEXP (exp, 0, i + 1));
  	  if (n > current_max)
  	    current_max = n;
  	}
  
!       n = max_attr_value (XEXP (exp, 1));
        if (n > current_max)
  	current_max = n;
!     }
  
!   else if (GET_CODE (exp) == IF_THEN_ELSE)
!     {
!       current_max = max_attr_value (XEXP (exp, 1));
!       n = max_attr_value (XEXP (exp, 2));
!       if (n > current_max)
! 	current_max = n;
      }
  
-   else
-     abort ();
- 
    return current_max;
  }
  
  /* Given an attribute value, return the result of ORing together all
!    CONST_STRING arguments encountered.  It is assumed that they are
!    all numeric.  */
  
  static int
! or_attr_value (exp)
       rtx exp;
  {
!   int current_or = 0;
    int i;
  
!   if (GET_CODE (exp) == CONST_STRING)
!     return atoi (XSTR (exp, 0));
! 
!   else if (GET_CODE (exp) == COND)
      {
        for (i = 0; i < XVECLEN (exp, 0); i += 2)
! 	{
! 	  current_or |= or_attr_value (XVECEXP (exp, 0, i + 1));
! 	}
  
!       current_or |= or_attr_value (XEXP (exp, 1));
!     }
  
!   else if (GET_CODE (exp) == IF_THEN_ELSE)
!     {
!       current_or = or_attr_value (XEXP (exp, 1));
!       current_or |= or_attr_value (XEXP (exp, 2));
      }
  
-   else
-     abort ();
- 
    return current_or;
  }
  
--- 4695,4777 ----
  }
  
  /* Given an attribute value, return the maximum CONST_STRING argument
!    encountered.  Set *UNKNOWNP and return INT_MAX if the value is unknown.  */
  
  static int
! max_attr_value (exp, unknownp)
       rtx exp;
+      int *unknownp;
  {
!   int current_max;
!   int i, n;
  
!   switch (GET_CODE (exp))
      {
+     case CONST_STRING:
+       current_max = atoi (XSTR (exp, 0));
+       break;
+ 
+     case COND:
+       current_max = max_attr_value (XEXP (exp, 1), unknownp);
        for (i = 0; i < XVECLEN (exp, 0); i += 2)
  	{
! 	  n = max_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
  	  if (n > current_max)
  	    current_max = n;
  	}
+       break;
  
!     case IF_THEN_ELSE:
!       current_max = max_attr_value (XEXP (exp, 1), unknownp);
!       n = max_attr_value (XEXP (exp, 2), unknownp);
        if (n > current_max)
  	current_max = n;
!       break;
  
!     default:
!       *unknownp = 1;
!       current_max = INT_MAX;
!       break;
      }
  
    return current_max;
  }
  
  /* Given an attribute value, return the result of ORing together all
!    CONST_STRING arguments encountered.  Set *UNKNOWNP and return -1
!    if the numeric value is not known.  */
  
  static int
! or_attr_value (exp, unknownp)
       rtx exp;
+      int *unknownp;
  {
!   int current_or;
    int i;
  
!   switch (GET_CODE (exp))
      {
+     case CONST_STRING:
+       current_or = atoi (XSTR (exp, 0));
+       break;
+ 
+     case COND:
+       current_or = or_attr_value (XEXP (exp, 1), unknownp);
        for (i = 0; i < XVECLEN (exp, 0); i += 2)
! 	current_or |= or_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
!       break;
  
!     case IF_THEN_ELSE:
!       current_or = or_attr_value (XEXP (exp, 1), unknownp);
!       current_or |= or_attr_value (XEXP (exp, 2), unknownp);
!       break;
  
!     default:
!       *unknownp = 1;
!       current_or = -1;
!       break;
      }
  
    return current_or;
  }
  
*************** write_attr_set (attr, indent, value, pre
*** 4928,4941 ****
       rtx known_true;
       int insn_code, insn_index;
  {
!   if (GET_CODE (value) == CONST_STRING)
!     {
!       write_indent (indent);
!       printf ("%s ", prefix);
!       write_attr_value (attr, value);
!       printf ("%s\n", suffix);
!     }
!   else if (GET_CODE (value) == COND)
      {
        /* Assume the default value will be the default of the COND unless we
  	 find an always true expression.  */
--- 4974,4980 ----
       rtx known_true;
       int insn_code, insn_index;
  {
!   if (GET_CODE (value) == COND)
      {
        /* Assume the default value will be the default of the COND unless we
  	 find an always true expression.  */
*************** write_attr_set (attr, indent, value, pre
*** 5009,5015 ****
  	}
      }
    else
!     abort ();
  }
  
  /* Write out the computation for one attribute value.  */
--- 5048,5059 ----
  	}
      }
    else
!     {
!       write_indent (indent);
!       printf ("%s ", prefix);
!       write_attr_value (attr, value);
!       printf ("%s\n", suffix);
!     }
  }
  
  /* Write out the computation for one attribute value.  */
*************** write_attr_value (attr, value)
*** 5244,5253 ****
       struct attr_desc *attr;
       rtx value;
  {
!   if (GET_CODE (value) != CONST_STRING)
!     abort ();
  
!   write_attr_valueq (attr, XSTR (value, 0));
  }
  
  static void
--- 5288,5340 ----
       struct attr_desc *attr;
       rtx value;
  {
!   int op;
  
!   switch (GET_CODE (value))
!     {
!     case CONST_STRING:
!       write_attr_valueq (attr, XSTR (value, 0));
!       break;
! 
!     case SYMBOL_REF:
!       fputs (XSTR (value, 0), stdout);
!       break;
! 
!     case ATTR:
!       {
! 	struct attr_desc *attr2 = find_attr (XSTR (value, 0), 0);
! 	printf ("get_attr_%s (%s)", attr2->name, 
! 		(attr2->is_const ? "" : "insn"));
!       }
!       break;
! 
!     case PLUS:
!       op = '+';
!       goto do_operator;
!     case MINUS:
!       op = '-';
!       goto do_operator;
!     case MULT:
!       op = '*';
!       goto do_operator;
!     case DIV:
!       op = '/';
!       goto do_operator;
!     case MOD:
!       op = '%';
!       goto do_operator;
! 
!     do_operator:
!       write_attr_value (attr, XEXP (value, 0));
!       putchar (' ');
!       putchar (op);
!       putchar (' ');
!       write_attr_value (attr, XEXP (value, 1));
!       break;
! 
!     default:
!       abort ();
!     }
  }
  
  static void
Index: md.texi
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/md.texi,v
retrieving revision 1.22
diff -c -p -d -r1.22 md.texi
*** md.texi	1998/12/16 20:57:22	1.22
--- md.texi	1999/02/22 02:39:12
*************** The integer @var{i} specifies the value 
*** 3555,3563 ****
  must be non-negative.
  
  The value of a numeric attribute can be specified either with a
! @code{const_int} or as an integer represented as a string in
! @code{const_string}, @code{eq_attr} (see below), and @code{set_attr}
! (@pxref{Tagging Insns}) expressions.
  
  @cindex @code{const_string} and attributes
  @item (const_string @var{value})
--- 3555,3564 ----
  must be non-negative.
  
  The value of a numeric attribute can be specified either with a
! @code{const_int}, or as an integer represented as a string in
! @code{const_string}, @code{eq_attr} (see below), @code{attr},
! @code{symbol_ref}, simple arithmetic expressions, and @code{set_attr}
! overrides on specific instructions (@pxref{Tagging Insns}).
  
  @cindex @code{const_string} and attributes
  @item (const_string @var{value})
*************** The @code{very_unlikely} and @code{unlik
*** 3740,3745 ****
--- 3741,3752 ----
  
  @code{attr_flag} is only used during delay slot scheduling and has no
  meaning to other passes of the compiler.
+ 
+ @findex attr
+ @item (attr @var{name})
+ The value of another attribute is returned.  This is most useful
+ for numeric attributes, as @code{eq_attr} and @code{attr_flag}
+ produce more efficient code for non-numeric attributes.
  @end table
  
  @node Tagging Insns


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