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] 'enabled' attribute - revised version 2


Hello,

another update of the 'enabled' attribute patch.  I've now addressed
also the last of Richards comments.

Bootstrapped and regtested on x86_64, s390 and s390x.

OK for mainline?

Bye,

-Andreas-

2008-05-14  Andreas Krebbel  <krebbel1@de.ibm.com>

	* reload.c: (find_reloads): Skip alternatives according to the
	`enabled' attribute.
	Constify the constraint variable.
	* recog.c (get_attr_enabled): Add default implementation.
	(extract_insn): Set the alternative_enabled_p array
	in the recog_data struct.
	(preprocess_constraints, constrain_operands): Skip
	alternatives according to the `enabled' attribute
	* recog.h (struct recog_data): New field alternative_enabled_p.
	(skip_alternative): New inline function.
	* regclass.c: (record_operand_costs): Check the 'enabled'
	attribute.
	(record_reg_classes): Skip alternative according to the
	'enabled' attribute.

	* doc/md.texi: Add documention for the `enabled' attribute.


Index: gcc/reload.c
===================================================================
*** gcc/reload.c.orig	2008-05-13 20:50:01.000000000 +0200
--- gcc/reload.c	2008-05-13 20:55:55.000000000 +0200
*************** find_reloads (rtx insn, int replace, int
*** 2523,2529 ****
    int noperands;
    /* These start out as the constraints for the insn
       and they are chewed up as we consider alternatives.  */
!   char *constraints[MAX_RECOG_OPERANDS];
    /* These are the preferred classes for an operand, or NO_REGS if it isn't
       a register.  */
    enum reg_class preferred_class[MAX_RECOG_OPERANDS];
--- 2523,2529 ----
    int noperands;
    /* These start out as the constraints for the insn
       and they are chewed up as we consider alternatives.  */
!   const char *constraints[MAX_RECOG_OPERANDS];
    /* These are the preferred classes for an operand, or NO_REGS if it isn't
       a register.  */
    enum reg_class preferred_class[MAX_RECOG_OPERANDS];
*************** find_reloads (rtx insn, int replace, int
*** 2630,2636 ****
  
    memcpy (operand_mode, recog_data.operand_mode,
  	  noperands * sizeof (enum machine_mode));
!   memcpy (constraints, recog_data.constraints, noperands * sizeof (char *));
  
    commutative = -1;
  
--- 2630,2637 ----
  
    memcpy (operand_mode, recog_data.operand_mode,
  	  noperands * sizeof (enum machine_mode));
!   memcpy (constraints, recog_data.constraints,
! 	  noperands * sizeof (const char *));
  
    commutative = -1;
  
*************** find_reloads (rtx insn, int replace, int
*** 2641,2648 ****
  
    for (i = 0; i < noperands; i++)
      {
!       char *p;
        int c;
  
        substed_operand[i] = recog_data.operand[i];
        p = constraints[i];
--- 2642,2650 ----
  
    for (i = 0; i < noperands; i++)
      {
!       const char *p;
        int c;
+       char *end;
  
        substed_operand[i] = recog_data.operand[i];
        p = constraints[i];
*************** find_reloads (rtx insn, int replace, int
*** 2686,2692 ****
  	    case '0': case '1': case '2': case '3': case '4':
  	    case '5': case '6': case '7': case '8': case '9':
  	      {
! 		c = strtoul (p - 1, &p, 10);
  
  		operands_match[c][i]
  		  = operands_match_p (recog_data.operand[c],
--- 2688,2695 ----
  	    case '0': case '1': case '2': case '3': case '4':
  	    case '5': case '6': case '7': case '8': case '9':
  	      {
! 		c = strtoul (p - 1, &end, 10);
! 		p = end;
  
  		operands_match[c][i]
  		  = operands_match_p (recog_data.operand[c],
*************** find_reloads (rtx insn, int replace, int
*** 2914,2924 ****
  	 a bad register class to only count 1/3 as much.  */
        int reject = 0;
  
        this_earlyclobber = 0;
  
        for (i = 0; i < noperands; i++)
  	{
! 	  char *p = constraints[i];
  	  char *end;
  	  int len;
  	  int win = 0;
--- 2917,2937 ----
  	 a bad register class to only count 1/3 as much.  */
        int reject = 0;
  
+       if (!recog_data.alternative_enabled_p[this_alternative_number])
+ 	{
+ 	  int i;
+ 
+ 	  for (i = 0; i < recog_data.n_operands; i++)
+ 	    constraints[i] = skip_alternative (constraints[i]);
+ 
+ 	  continue;
+ 	}
+ 
        this_earlyclobber = 0;
  
        for (i = 0; i < noperands; i++)
  	{
! 	  const char *p = constraints[i];
  	  char *end;
  	  int len;
  	  int win = 0;
*************** find_reloads (rtx insn, int replace, int
*** 3717,3723 ****
  	  address_reloaded[commutative + 1] = t;
  
  	  memcpy (constraints, recog_data.constraints,
! 		  noperands * sizeof (char *));
  	  goto try_swapped;
  	}
        else
--- 3730,3736 ----
  	  address_reloaded[commutative + 1] = t;
  
  	  memcpy (constraints, recog_data.constraints,
! 		  noperands * sizeof (const char *));
  	  goto try_swapped;
  	}
        else
Index: gcc/recog.c
===================================================================
*** gcc/recog.c.orig	2008-05-13 20:50:01.000000000 +0200
--- gcc/recog.c	2008-05-13 20:51:47.000000000 +0200
*************** along with GCC; see the file COPYING3.  
*** 60,65 ****
--- 60,73 ----
  #endif
  #endif
  
+ #ifndef HAVE_ATTR_enabled
+ static inline bool
+ get_attr_enabled (rtx insn ATTRIBUTE_UNUSED)
+ {
+   return true;
+ }
+ #endif
+ 
  static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx);
  static void validate_replace_src_1 (rtx *, void *);
  static rtx split_insn (rtx);
*************** extract_insn (rtx insn)
*** 1920,1930 ****
    int noperands;
    rtx body = PATTERN (insn);
  
-   recog_data.insn = NULL;
    recog_data.n_operands = 0;
    recog_data.n_alternatives = 0;
    recog_data.n_dups = 0;
-   which_alternative = -1;
  
    switch (GET_CODE (body))
      {
--- 1928,1936 ----
*************** extract_insn (rtx insn)
*** 2004,2009 ****
--- 2010,2031 ----
  	 : OP_IN);
  
    gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES);
+ 
+   if (INSN_CODE (insn) < 0)
+     for (i = 0; i < recog_data.n_alternatives; i++)
+       recog_data.alternative_enabled_p[i] = true;
+   else
+     {
+       recog_data.insn = insn;
+       for (i = 0; i < recog_data.n_alternatives; i++)
+ 	{
+ 	  which_alternative = i;
+ 	  recog_data.alternative_enabled_p[i] = get_attr_enabled (insn);
+ 	}
+     }
+ 
+   recog_data.insn = NULL;
+   which_alternative = -1;
  }
  
  /* After calling extract_insn, you can use this function to extract some
*************** preprocess_constraints (void)
*** 2033,2038 ****
--- 2055,2066 ----
  	  op_alt[j].matches = -1;
  	  op_alt[j].matched = -1;
  
+ 	  if (!recog_data.alternative_enabled_p[j])
+ 	    {
+ 	      p = skip_alternative (p);
+ 	      continue;
+ 	    }
+ 
  	  if (*p == '\0' || *p == ',')
  	    {
  	      op_alt[j].anything_ok = 1;
*************** constrain_operands (int strict)
*** 2202,2207 ****
--- 2230,2246 ----
        int lose = 0;
        funny_match_index = 0;
  
+       if (!recog_data.alternative_enabled_p[which_alternative])
+ 	{
+ 	  int i;
+ 
+ 	  for (i = 0; i < recog_data.n_operands; i++)
+ 	    constraints[i] = skip_alternative (constraints[i]);
+ 
+ 	  which_alternative++;
+ 	  continue;
+ 	}
+ 
        for (opno = 0; opno < recog_data.n_operands; opno++)
  	{
  	  rtx op = recog_data.operand[opno];
Index: gcc/recog.h
===================================================================
*** gcc/recog.h.orig	2008-05-13 20:50:01.000000000 +0200
--- gcc/recog.h	2008-05-13 20:52:31.000000000 +0200
*************** recog_memoized (rtx insn)
*** 142,147 ****
--- 142,160 ----
  }
  #endif
  
+ /* Skip chars until the next ',' or the end of the string.  This is
+    useful to skip alternatives in a constraint string.  */
+ static inline const char *
+ skip_alternative (const char *p)
+ {
+   const char *r = p;
+   while (*r != '\0' && *r != ',')
+     r++;
+   if (*r == ',')
+     r++;
+   return r;
+ }
+ 
  /* Nonzero means volatile operands are recognized.  */
  extern int volatile_ok;
  
*************** struct recog_data
*** 201,206 ****
--- 214,225 ----
    /* The number of alternatives in the constraints for the insn.  */
    char n_alternatives;
  
+   /* Specifies whether an insn alternative is enabled using the
+      `enabled' attribute in the insn pattern definition.  For back
+      ends not using the `enabled' attribute the array fields are
+      always set to `true' in expand_insn.  */
+   bool alternative_enabled_p [MAX_RECOG_ALTERNATIVES];
+ 
    /* In case we are caching, hold insn data was generated for.  */
    rtx insn;
  };
Index: gcc/regclass.c
===================================================================
*** gcc/regclass.c.orig	2008-05-13 20:50:01.000000000 +0200
--- gcc/regclass.c	2008-05-13 20:51:47.000000000 +0200
*************** record_operand_costs (rtx insn, struct c
*** 1143,1150 ****
  	record_address_regs (GET_MODE (recog_data.operand[i]),
  			     XEXP (recog_data.operand[i], 0),
  			     0, MEM, SCRATCH, frequency * 2);
!       else if (constraints[i][0] == 'p'
! 	       || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
  	record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS,
  			     SCRATCH, frequency * 2);
      }
--- 1143,1151 ----
  	record_address_regs (GET_MODE (recog_data.operand[i]),
  			     XEXP (recog_data.operand[i], 0),
  			     0, MEM, SCRATCH, frequency * 2);
!       else if (recog_data.alternative_enabled_p[0]
! 	       && (constraints[i][0] == 'p'
! 		   || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i])))
  	record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS,
  			     SCRATCH, frequency * 2);
      }
*************** record_reg_classes (int n_alts, int n_op
*** 1932,1937 ****
--- 1933,1941 ----
        if (alt_fail)
  	continue;
  
+       if (!recog_data.alternative_enabled_p[alt])
+ 	continue;
+ 
        /* Finally, update the costs with the information we've calculated
  	 about this alternative.  */
  
Index: gcc/doc/md.texi
===================================================================
*** gcc/doc/md.texi.orig	2008-05-13 20:50:01.000000000 +0200
--- gcc/doc/md.texi	2008-05-13 20:51:47.000000000 +0200
*************** have.  Constraints can also require two 
*** 1050,1055 ****
--- 1050,1056 ----
  * Multi-Alternative::   When an insn has two alternative constraint-patterns.
  * Class Preferences::   Constraints guide which hard register to put things in.
  * Modifiers::           More precise control over effects of constraints.
+ * Disable Insn Alternatives:: Disable insn alternatives using the @code{enabled} attribute.
  * Machine Constraints:: Existing constraints for some particular machines.
  * Define Constraints::  How to define machine-specific constraints.
  * C Constraint Interface:: How to test constraints from C code.
*************** Unsigned constant valid for BccUI instru
*** 3087,3092 ****
--- 3088,3185 ----
  @end table
  
  @ifset INTERNALS
+ @node Disable Insn Alternatives
+ @subsection Disable insn alternatives using the @code{enabled} attribute
+ @cindex enabled
+ 
+ The @code{enabled} insn attribute might be used to disable certain insn
+ alternatives for machine-specific reasons.  This is useful when adding
+ new instructions to an existing pattern which are only available for
+ certain cpu architecture levels as specified with the @code{-march=}
+ option.
+ 
+ A disabled insn alternative will be handled by the middle end as having
+ a never-matching constraint.
+ 
+ In order to make use of the @code{enabled} attribute a back end has to add
+ in the machine description files:
+ 
+ @enumerate
+ @item
+ A definition of the @code{enabled} insn attribute.  The attribute is
+ defined as usual using the @code{define_attr} command.  This
+ definition should be based on other insn attributes and/or target flags.
+ The @code{enabled} attribute is a numeric attribute and should evaluate to
+ @code{(const_int 1)} for an enabled alternative and to
+ @code{(const_int 0)} otherwise.
+ @item
+ A definition of another insn attribute used to describe for what
+ reason an insn alternative might be available or
+ not.  E.g. @code{cpu_facility} as in the example below.
+ @item
+ An assignement for the second attribute to each insn definition
+ combining instructions which are not all available under the same
+ circumstances.  (Note: It obviously only makes sense for definitions
+ with more than one alternative.  Otherwise the insn pattern should be
+ disabled or enabled using the insn condition.)
+ @end enumerate
+ 
+ E.g. the following two patterns could easily be merged using the @code{enabled}
+ attribute:
+ 
+ @smallexample
+ 
+ (define_insn "*movdi_old"
+   [(set (match_operand:DI 0 "register_operand" "=d")
+         (match_operand:DI 1 "register_operand" " d"))]
+   "!TARGET_NEW"
+   "lgr %0,%1")
+ 
+ (define_insn "*movdi_new"
+   [(set (match_operand:DI 0 "register_operand" "=d,f,d")
+         (match_operand:DI 1 "register_operand" " d,d,f"))]
+   "TARGET_NEW"
+   "@@
+    lgr  %0,%1
+    ldgr %0,%1
+    lgdr %0,%1")
+ 
+ @end smallexample
+ 
+ to:
+ 
+ @smallexample
+ 
+ (define_insn "*movdi_combined"
+   [(set (match_operand:DI 0 "register_operand" "=d,f,d")
+         (match_operand:DI 1 "register_operand" " d,d,f"))]
+   ""
+   "@@
+    lgr  %0,%1
+    ldgr %0,%1
+    lgdr %0,%1"
+   [(set_attr "cpu_facility" "*,new,new")])
+ 
+ @end smallexample
+ 
+ with the @code{enabled} attribute defined like this:
+ 
+ @smallexample
+ 
+ (define_attr "cpu_facility" "standard,new" (const_string "standard"))
+ 
+ (define_attr "enabled" ""
+   (cond [(eq_attr "cpu_facility" "standard") (const_int 1)
+          (and (eq_attr "cpu_facility" "new")
+               (ne (symbol_ref "TARGET_NEW") (const_int 0)))
+          (const_int 1)]
+         (const_int 0)))
+ 
+ @end smallexample
+ 
+ @end ifset
+ 
+ @ifset INTERNALS
  @node Define Constraints
  @subsection Defining Machine-Specific Constraints
  @cindex defining constraints
*************** If the attribute takes numeric values, n
*** 6510,6515 ****
--- 6603,6624 ----
  defined and the function to obtain the attribute's value will return
  @code{int}.
  
+ There are attributes which are tied to a specific meaning.  These
+ attributes are not free to use for other purposes:
+ 
+ @table @code
+ @item length
+ The @code{length} attribute is used to calculate the length of emitted
+ code chunks.  This is especially important when verifying branch
+ distances. @xref{Insn Lengths}.
+ 
+ @item enabled
+ The @code{enabled} attribute can be defined to prevent certain
+ alternatives of an insn definition from being used during code
+ generation. @xref{Disable Insn Alternatives}.
+ 
+ @end table
+ 
  @end ifset
  @ifset INTERNALS
  @node Expressions


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