diff mbox

Reuse predicate code analysis for constraints

Message ID 87382o4o0b.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford May 22, 2015, 3:42 p.m. UTC
This patch adjusts the fix for PR target/65689 along the lines suggested
in https://gcc.gnu.org/ml/gcc-patches/2015-04/msg01559.html.  The idea
is to reuse the existing gensupport.c routine to work out the codes
accepted by constraints.

I'd originally done this with an eye to using compute_test_codes for
the problem that Andreas found on s390.  I don't think it's going to
be useful for that after all, but it seems worth having for its on sake.

Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?

Thanks,
Richard


gcc/
	* gensupport.h (compute_test_codes): Declare.
	* gensupport.c (compute_predicate_codes): Rename to...
	(compute_test_codes): ...this.  Generalize error message.
	(process_define_predicate): Update accordingly.
	* genpreds.c (compute_maybe_allows): Delete.
	(add_constraint): Use compute_test_codes to determine whether
	something can accept a SUBREG, REG or MEM.

Comments

Jeff Law May 22, 2015, 7:57 p.m. UTC | #1
On 05/22/2015 09:42 AM, Richard Sandiford wrote:
> This patch adjusts the fix for PR target/65689 along the lines suggested
> in https://gcc.gnu.org/ml/gcc-patches/2015-04/msg01559.html.  The idea
> is to reuse the existing gensupport.c routine to work out the codes
> accepted by constraints.
>
> I'd originally done this with an eye to using compute_test_codes for
> the problem that Andreas found on s390.  I don't think it's going to
> be useful for that after all, but it seems worth having for its on sake.
>
> Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?
>
> Thanks,
> Richard
>
>
> gcc/
> 	* gensupport.h (compute_test_codes): Declare.
> 	* gensupport.c (compute_predicate_codes): Rename to...
> 	(compute_test_codes): ...this.  Generalize error message.
> 	(process_define_predicate): Update accordingly.
> 	* genpreds.c (compute_maybe_allows): Delete.
> 	(add_constraint): Use compute_test_codes to determine whether
> 	something can accept a SUBREG, REG or MEM.
OK.
jeff
Bill Schmidt May 26, 2015, 2:22 p.m. UTC | #2
Hi Richard,

Unfortunately this broke the Power builds:

/home/wschmidt/gcc/gcc-mainline-base/gcc/config/rs6000/constraints.md:211: reference to unknown predicate 'mem_operand_gpr'
/home/wschmidt/gcc/gcc-mainline-base/gcc/config/rs6000/constraints.md:242: reference to unknown predicate 'small_data_operand'

I haven't had time to investigate further -- will be in meetings most of
the morning.

Thanks,
Bill

On Fri, 2015-05-22 at 16:42 +0100, Richard Sandiford wrote:
> This patch adjusts the fix for PR target/65689 along the lines suggested
> in https://gcc.gnu.org/ml/gcc-patches/2015-04/msg01559.html.  The idea
> is to reuse the existing gensupport.c routine to work out the codes
> accepted by constraints.
> 
> I'd originally done this with an eye to using compute_test_codes for
> the problem that Andreas found on s390.  I don't think it's going to
> be useful for that after all, but it seems worth having for its on sake.
> 
> Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?
> 
> Thanks,
> Richard
> 
> 
> gcc/
> 	* gensupport.h (compute_test_codes): Declare.
> 	* gensupport.c (compute_predicate_codes): Rename to...
> 	(compute_test_codes): ...this.  Generalize error message.
> 	(process_define_predicate): Update accordingly.
> 	* genpreds.c (compute_maybe_allows): Delete.
> 	(add_constraint): Use compute_test_codes to determine whether
> 	something can accept a SUBREG, REG or MEM.
> 
> Index: gcc/gensupport.h
> ===================================================================
> --- gcc/gensupport.h	2015-05-21 08:45:32.663464769 +0100
> +++ gcc/gensupport.h	2015-05-21 08:45:33.015460604 +0100
> @@ -109,5 +109,6 @@ struct pattern_stats
>  };
>  
>  extern void get_pattern_stats (struct pattern_stats *ranges, rtvec vec);
> +extern void compute_test_codes (rtx, int, char *);
>  
>  #endif /* GCC_GENSUPPORT_H */
> Index: gcc/gensupport.c
> ===================================================================
> --- gcc/gensupport.c	2015-05-21 08:45:32.663464769 +0100
> +++ gcc/gensupport.c	2015-05-21 08:51:12.667438995 +0100
> @@ -204,8 +204,8 @@ #define TRISTATE_NOT(a)				\
>     predicate expression EXP, writing the result to CODES.  LINENO is
>     the line number on which the directive containing EXP appeared.  */
>  
> -static void
> -compute_predicate_codes (rtx exp, int lineno, char codes[NUM_RTX_CODE])
> +void
> +compute_test_codes (rtx exp, int lineno, char *codes)
>  {
>    char op0_codes[NUM_RTX_CODE];
>    char op1_codes[NUM_RTX_CODE];
> @@ -215,29 +215,29 @@ compute_predicate_codes (rtx exp, int li
>    switch (GET_CODE (exp))
>      {
>      case AND:
> -      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
> -      compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
> +      compute_test_codes (XEXP (exp, 0), lineno, op0_codes);
> +      compute_test_codes (XEXP (exp, 1), lineno, op1_codes);
>        for (i = 0; i < NUM_RTX_CODE; i++)
>  	codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
>        break;
>  
>      case IOR:
> -      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
> -      compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
> +      compute_test_codes (XEXP (exp, 0), lineno, op0_codes);
> +      compute_test_codes (XEXP (exp, 1), lineno, op1_codes);
>        for (i = 0; i < NUM_RTX_CODE; i++)
>  	codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
>        break;
>      case NOT:
> -      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
> +      compute_test_codes (XEXP (exp, 0), lineno, op0_codes);
>        for (i = 0; i < NUM_RTX_CODE; i++)
>  	codes[i] = TRISTATE_NOT (op0_codes[i]);
>        break;
>  
>      case IF_THEN_ELSE:
>        /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */
> -      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
> -      compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
> -      compute_predicate_codes (XEXP (exp, 2), lineno, op2_codes);
> +      compute_test_codes (XEXP (exp, 0), lineno, op0_codes);
> +      compute_test_codes (XEXP (exp, 1), lineno, op1_codes);
> +      compute_test_codes (XEXP (exp, 2), lineno, op2_codes);
>        for (i = 0; i < NUM_RTX_CODE; i++)
>  	codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
>  				TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
> @@ -321,7 +321,7 @@ compute_predicate_codes (rtx exp, int li
>  
>      default:
>        error_with_line (lineno,
> -		       "'%s' cannot be used in a define_predicate expression",
> +		       "'%s' cannot be used in predicates or constraints",
>  		       GET_RTX_NAME (GET_CODE (exp)));
>        memset (codes, I, NUM_RTX_CODE);
>        break;
> @@ -373,7 +373,7 @@ process_define_predicate (rtx desc, int
>    if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
>      pred->special = true;
>  
> -  compute_predicate_codes (XEXP (desc, 1), lineno, codes);
> +  compute_test_codes (XEXP (desc, 1), lineno, codes);
>  
>    for (i = 0; i < NUM_RTX_CODE; i++)
>      if (codes[i] != N)
> Index: gcc/genpreds.c
> ===================================================================
> --- gcc/genpreds.c	2015-05-21 08:45:32.663464769 +0100
> +++ gcc/genpreds.c	2015-05-21 08:45:33.015460604 +0100
> @@ -716,34 +716,6 @@ mangle (const char *name)
>    return XOBFINISH (rtl_obstack, const char *);
>  }
>  
> -/* Return a bitmask, bit 1 if EXP maybe allows a REG/SUBREG, 2 if EXP
> -   maybe allows a MEM.  Bits should be clear only when we are sure it
> -   will not allow a REG/SUBREG or a MEM.  */
> -static int
> -compute_maybe_allows (rtx exp)
> -{
> -  switch (GET_CODE (exp))
> -    {
> -    case IF_THEN_ELSE:
> -      /* Conservative answer is like IOR, of the THEN and ELSE branches.  */
> -      return compute_maybe_allows (XEXP (exp, 1))
> -	     | compute_maybe_allows (XEXP (exp, 2));
> -    case AND:
> -      return compute_maybe_allows (XEXP (exp, 0))
> -	     & compute_maybe_allows (XEXP (exp, 1));
> -    case IOR:
> -      return compute_maybe_allows (XEXP (exp, 0))
> -	     | compute_maybe_allows (XEXP (exp, 1));
> -    case MATCH_CODE:
> -      if (*XSTR (exp, 1) == '\0')
> -	return (strstr (XSTR (exp, 0), "reg") != NULL ? 1 : 0)
> -	       | (strstr (XSTR (exp, 0), "mem") != NULL ? 2 : 0);
> -      /* FALLTHRU */
> -    default:
> -      return 3;
> -    }
> -}
> -
>  /* Add one constraint, of any sort, to the tables.  NAME is its name;
>     REGCLASS is the register class, if any; EXP is the expression to
>     test, if any;  IS_MEMORY and IS_ADDRESS indicate memory and address
> @@ -899,12 +871,17 @@ add_constraint (const char *name, const
>    c->is_extra = !(regclass || is_const_int || is_const_dbl);
>    c->is_memory = is_memory;
>    c->is_address = is_address;
> -  int maybe_allows = 3;
> +  c->maybe_allows_reg = true;
> +  c->maybe_allows_mem = true;
>    if (exp)
> -    maybe_allows = compute_maybe_allows (exp);
> -  c->maybe_allows_reg = (maybe_allows & 1) != 0;
> -  c->maybe_allows_mem = (maybe_allows & 2) != 0;
> -
> +    {
> +      char codes[NUM_RTX_CODE];
> +      compute_test_codes (exp, lineno, codes);
> +      if (!codes[REG] && !codes[SUBREG])
> +	c->maybe_allows_reg = false;
> +      if (!codes[MEM])
> +	c->maybe_allows_mem = false;
> +    }
>    c->next_this_letter = *slot;
>    *slot = c;
>  
>
Richard Sandiford May 26, 2015, 2:51 p.m. UTC | #3
Bill Schmidt <wschmidt@linux.vnet.ibm.com> writes:
> Hi Richard,
>
> Unfortunately this broke the Power builds:
>
> /home/wschmidt/gcc/gcc-mainline-base/gcc/config/rs6000/constraints.md:211:
> reference to unknown predicate 'mem_operand_gpr'
> /home/wschmidt/gcc/gcc-mainline-base/gcc/config/rs6000/constraints.md:242:
> reference to unknown predicate 'small_data_operand'
>
> I haven't had time to investigate further -- will be in meetings most of
> the morning.

This is because those functions aren't defined as predicates in the .md file,
but are being used with match_operand.  If they're meant to be "real"
predicates, they should be defined in predicates.md rather than rs6000.c.
If they're just query functions, you can use match_test instead of
match_operand.  (In that case there's probably no point passing the mode.)

Thanks,
Richard
David Edelsohn May 26, 2015, 3:18 p.m. UTC | #4
On Tue, May 26, 2015 at 10:51 AM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> Bill Schmidt <wschmidt@linux.vnet.ibm.com> writes:
>> Hi Richard,
>>
>> Unfortunately this broke the Power builds:
>>
>> /home/wschmidt/gcc/gcc-mainline-base/gcc/config/rs6000/constraints.md:211:
>> reference to unknown predicate 'mem_operand_gpr'
>> /home/wschmidt/gcc/gcc-mainline-base/gcc/config/rs6000/constraints.md:242:
>> reference to unknown predicate 'small_data_operand'
>>
>> I haven't had time to investigate further -- will be in meetings most of
>> the morning.
>
> This is because those functions aren't defined as predicates in the .md file,
> but are being used with match_operand.  If they're meant to be "real"
> predicates, they should be defined in predicates.md rather than rs6000.c.
> If they're just query functions, you can use match_test instead of
> match_operand.  (In that case there's probably no point passing the mode.)

I converted them to match_test to get back to bootstrap.
mem_operand_gpr should be in predicates.md, but requires a little
re-design.

- David
Richard Sandiford May 26, 2015, 3:19 p.m. UTC | #5
David Edelsohn <dje.gcc@gmail.com> writes:
> On Tue, May 26, 2015 at 10:51 AM, Richard Sandiford
> <richard.sandiford@arm.com> wrote:
>> Bill Schmidt <wschmidt@linux.vnet.ibm.com> writes:
>>> Hi Richard,
>>>
>>> Unfortunately this broke the Power builds:
>>>
>>> /home/wschmidt/gcc/gcc-mainline-base/gcc/config/rs6000/constraints.md:211:
>>> reference to unknown predicate 'mem_operand_gpr'
>>> /home/wschmidt/gcc/gcc-mainline-base/gcc/config/rs6000/constraints.md:242:
>>> reference to unknown predicate 'small_data_operand'
>>>
>>> I haven't had time to investigate further -- will be in meetings most of
>>> the morning.
>>
>> This is because those functions aren't defined as predicates in the .md file,
>> but are being used with match_operand.  If they're meant to be "real"
>> predicates, they should be defined in predicates.md rather than rs6000.c.
>> If they're just query functions, you can use match_test instead of
>> match_operand.  (In that case there's probably no point passing the mode.)
>
> I converted them to match_test to get back to bootstrap.
> mem_operand_gpr should be in predicates.md, but requires a little
> re-design.

Thanks David.
diff mbox

Patch

Index: gcc/gensupport.h
===================================================================
--- gcc/gensupport.h	2015-05-21 08:45:32.663464769 +0100
+++ gcc/gensupport.h	2015-05-21 08:45:33.015460604 +0100
@@ -109,5 +109,6 @@  struct pattern_stats
 };
 
 extern void get_pattern_stats (struct pattern_stats *ranges, rtvec vec);
+extern void compute_test_codes (rtx, int, char *);
 
 #endif /* GCC_GENSUPPORT_H */
Index: gcc/gensupport.c
===================================================================
--- gcc/gensupport.c	2015-05-21 08:45:32.663464769 +0100
+++ gcc/gensupport.c	2015-05-21 08:51:12.667438995 +0100
@@ -204,8 +204,8 @@  #define TRISTATE_NOT(a)				\
    predicate expression EXP, writing the result to CODES.  LINENO is
    the line number on which the directive containing EXP appeared.  */
 
-static void
-compute_predicate_codes (rtx exp, int lineno, char codes[NUM_RTX_CODE])
+void
+compute_test_codes (rtx exp, int lineno, char *codes)
 {
   char op0_codes[NUM_RTX_CODE];
   char op1_codes[NUM_RTX_CODE];
@@ -215,29 +215,29 @@  compute_predicate_codes (rtx exp, int li
   switch (GET_CODE (exp))
     {
     case AND:
-      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
-      compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
+      compute_test_codes (XEXP (exp, 0), lineno, op0_codes);
+      compute_test_codes (XEXP (exp, 1), lineno, op1_codes);
       for (i = 0; i < NUM_RTX_CODE; i++)
 	codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
       break;
 
     case IOR:
-      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
-      compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
+      compute_test_codes (XEXP (exp, 0), lineno, op0_codes);
+      compute_test_codes (XEXP (exp, 1), lineno, op1_codes);
       for (i = 0; i < NUM_RTX_CODE; i++)
 	codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
       break;
     case NOT:
-      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
+      compute_test_codes (XEXP (exp, 0), lineno, op0_codes);
       for (i = 0; i < NUM_RTX_CODE; i++)
 	codes[i] = TRISTATE_NOT (op0_codes[i]);
       break;
 
     case IF_THEN_ELSE:
       /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */
-      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
-      compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
-      compute_predicate_codes (XEXP (exp, 2), lineno, op2_codes);
+      compute_test_codes (XEXP (exp, 0), lineno, op0_codes);
+      compute_test_codes (XEXP (exp, 1), lineno, op1_codes);
+      compute_test_codes (XEXP (exp, 2), lineno, op2_codes);
       for (i = 0; i < NUM_RTX_CODE; i++)
 	codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
 				TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
@@ -321,7 +321,7 @@  compute_predicate_codes (rtx exp, int li
 
     default:
       error_with_line (lineno,
-		       "'%s' cannot be used in a define_predicate expression",
+		       "'%s' cannot be used in predicates or constraints",
 		       GET_RTX_NAME (GET_CODE (exp)));
       memset (codes, I, NUM_RTX_CODE);
       break;
@@ -373,7 +373,7 @@  process_define_predicate (rtx desc, int
   if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
     pred->special = true;
 
-  compute_predicate_codes (XEXP (desc, 1), lineno, codes);
+  compute_test_codes (XEXP (desc, 1), lineno, codes);
 
   for (i = 0; i < NUM_RTX_CODE; i++)
     if (codes[i] != N)
Index: gcc/genpreds.c
===================================================================
--- gcc/genpreds.c	2015-05-21 08:45:32.663464769 +0100
+++ gcc/genpreds.c	2015-05-21 08:45:33.015460604 +0100
@@ -716,34 +716,6 @@  mangle (const char *name)
   return XOBFINISH (rtl_obstack, const char *);
 }
 
-/* Return a bitmask, bit 1 if EXP maybe allows a REG/SUBREG, 2 if EXP
-   maybe allows a MEM.  Bits should be clear only when we are sure it
-   will not allow a REG/SUBREG or a MEM.  */
-static int
-compute_maybe_allows (rtx exp)
-{
-  switch (GET_CODE (exp))
-    {
-    case IF_THEN_ELSE:
-      /* Conservative answer is like IOR, of the THEN and ELSE branches.  */
-      return compute_maybe_allows (XEXP (exp, 1))
-	     | compute_maybe_allows (XEXP (exp, 2));
-    case AND:
-      return compute_maybe_allows (XEXP (exp, 0))
-	     & compute_maybe_allows (XEXP (exp, 1));
-    case IOR:
-      return compute_maybe_allows (XEXP (exp, 0))
-	     | compute_maybe_allows (XEXP (exp, 1));
-    case MATCH_CODE:
-      if (*XSTR (exp, 1) == '\0')
-	return (strstr (XSTR (exp, 0), "reg") != NULL ? 1 : 0)
-	       | (strstr (XSTR (exp, 0), "mem") != NULL ? 2 : 0);
-      /* FALLTHRU */
-    default:
-      return 3;
-    }
-}
-
 /* Add one constraint, of any sort, to the tables.  NAME is its name;
    REGCLASS is the register class, if any; EXP is the expression to
    test, if any;  IS_MEMORY and IS_ADDRESS indicate memory and address
@@ -899,12 +871,17 @@  add_constraint (const char *name, const
   c->is_extra = !(regclass || is_const_int || is_const_dbl);
   c->is_memory = is_memory;
   c->is_address = is_address;
-  int maybe_allows = 3;
+  c->maybe_allows_reg = true;
+  c->maybe_allows_mem = true;
   if (exp)
-    maybe_allows = compute_maybe_allows (exp);
-  c->maybe_allows_reg = (maybe_allows & 1) != 0;
-  c->maybe_allows_mem = (maybe_allows & 2) != 0;
-
+    {
+      char codes[NUM_RTX_CODE];
+      compute_test_codes (exp, lineno, codes);
+      if (!codes[REG] && !codes[SUBREG])
+	c->maybe_allows_reg = false;
+      if (!codes[MEM])
+	c->maybe_allows_mem = false;
+    }
   c->next_this_letter = *slot;
   *slot = c;