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]

[tree-ssa] PATCH to gimplification of ASM_EXPR


As discussed, this changes gimplification of ASM_EXPRs so that input memory
operands ('m', 'V', 'o') are treated as lvalues.  The complexity comes from
having to handle references to output operands.  I also changed
resolve_asm_operand_names to avoid doing a strdup of the pattern string if
it isn't necessary.

Currently, passing something which is not an lvalue will cause a
gimplification failure.  We ought to give a better diagnostic sooner;
perhaps rth's 3.3.1 patch will do that.

Tested athlon-pc-linux-gnu, applied to tree-ssa.

2003-06-05  Jason Merrill  <jason@redhat.com>

	* stmt.c (asm_op_is_mem_input): New fn.
	(resolve_asm_operand_names): Rename from resolve_operand_names.  No longer 
	static.  Avoid needless copying.  Don't build array of constraints.
	(expand_asm_operands): Build it here.
	* tree.h: Declare new fns.
	* gimplify.c (simplify_asm_expr): Call resolve_asm_operand_names.
	Use is_simple_modify_expr_lhs for mem input ops.

*** tree.h.~1~	2003-06-03 15:55:46.000000000 -0400
--- tree.h	2003-06-05 18:47:37.000000000 -0400
*************** extern bool parse_output_constraint     
*** 3265,3270 ****
--- 3265,3272 ----
  extern void expand_asm_operands		PARAMS ((tree, tree, tree, tree, int,
  						 const char *, int));
  extern void expand_asm_expr		PARAMS ((tree));
+ extern bool asm_op_is_mem_input (tree, tree);
+ extern tree resolve_asm_operand_names (tree, tree, tree);
  extern int any_pending_cleanups		PARAMS ((int));
  extern void init_stmt_for_function	PARAMS ((void));
  extern void expand_start_target_temps	PARAMS ((void));
*** stmt.c.~1~	2003-05-14 15:29:46.000000000 -0400
--- stmt.c	2003-06-05 18:55:44.000000000 -0400
*************** static void fixup_gotos			PARAMS ((struc
*** 404,411 ****
  					       rtx, int));
  static bool check_operand_nalternatives	PARAMS ((tree, tree));
  static bool check_unique_operand_names	PARAMS ((tree, tree));
- static tree resolve_operand_names	PARAMS ((tree, tree, tree,
- 						 const char **));
  static char *resolve_operand_name_1	PARAMS ((char *, tree, tree));
  static void expand_null_return_1	PARAMS ((rtx));
  static enum br_predictor return_prediction PARAMS ((rtx));
--- 404,409 ----
*************** parse_input_constraint (constraint_p, in
*** 1447,1452 ****
--- 1445,1477 ----
    return true;
  }
  
+ /* INPUT is one of the input operands from EXPR, an ASM_EXPR.  Returns true
+    if it is an operand which must be passed in memory (i.e. an "m"
+    constraint), false otherwise.  */
+ 
+ bool
+ asm_op_is_mem_input (tree input, tree expr)
+ {
+   const char *constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (input)));
+   tree outputs = ASM_OUTPUTS (expr);
+   int noutputs = list_length (outputs);
+   const char **constraints
+     = (const char **) alloca ((noutputs) * sizeof (const char *));
+   int i = 0;
+   bool allows_mem, allows_reg;
+   tree t;
+ 
+   /* Collect output constraints.  */
+   for (t = outputs; t ; t = TREE_CHAIN (t), i++)
+     constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
+ 
+   /* We pass 0 for input_num, ninputs and ninout; they are only used for
+      error checking which will be done at expand time.  */
+   parse_input_constraint (&constraint, 0, 0, noutputs, 0, constraints,
+ 			  &allows_mem, &allows_reg);
+   return (!allows_reg && allows_mem);
+ }
+ 
  /* Check for overlap between registers marked in CLOBBERED_REGS and
     anything inappropriate in DECL.  Emit error and return TRUE for error,
     FALSE for ok.  */
*************** expand_asm_operands (string, outputs, in
*** 1517,1522 ****
--- 1542,1548 ----
    HARD_REG_SET clobbered_regs;
    int clobber_conflict_found = 0;
    tree tail;
+   tree t;
    int i;
    /* Vector of RTX's of evaluated output operands.  */
    rtx *output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
*************** expand_asm_operands (string, outputs, in
*** 1538,1544 ****
    if (! check_unique_operand_names (outputs, inputs))
      return;
  
!   string = resolve_operand_names (string, outputs, inputs, constraints);
  
  #ifdef MD_ASM_CLOBBERS
    /* Sometimes we wish to automatically clobber registers across an asm.
--- 1564,1577 ----
    if (! check_unique_operand_names (outputs, inputs))
      return;
  
!   string = resolve_asm_operand_names (string, outputs, inputs);
! 
!   /* Collect constraints.  */
!   i = 0;
!   for (t = outputs; t ; t = TREE_CHAIN (t), i++)
!     constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
!   for (t = inputs; t ; t = TREE_CHAIN (t), i++)
!     constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
  
  #ifdef MD_ASM_CLOBBERS
    /* Sometimes we wish to automatically clobber registers across an asm.
*************** check_unique_operand_names (outputs, inp
*** 2079,2099 ****
     in *POUTPUTS and *PINPUTS to numbers, and replace the name expansions in
     STRING and in the constraints to those numbers.  */
  
! static tree
! resolve_operand_names (string, outputs, inputs, pconstraints)
!      tree string;
!      tree outputs, inputs;
!      const char **pconstraints;
  {
!   char *buffer = xstrdup (TREE_STRING_POINTER (string));
    char *p;
    tree t;
  
    /* Assume that we will not need extra space to perform the substitution.
       This because we get to remove '[' and ']', which means we cannot have
       a problem until we have more than 999 operands.  */
  
!   p = buffer;
    while ((p = strchr (p, '%')) != NULL)
      {
        if (p[1] == '[')
--- 2112,2148 ----
     in *POUTPUTS and *PINPUTS to numbers, and replace the name expansions in
     STRING and in the constraints to those numbers.  */
  
! tree
! resolve_asm_operand_names (tree string, tree outputs, tree inputs)
  {
!   char *buffer;
    char *p;
    tree t;
  
+   /* Substitute [<name>] in input constraint strings.  There should be no
+      named operands in output constraints.  */
+   for (t = inputs; t ; t = TREE_CHAIN (t))
+     {
+       const char *c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
+       if (strchr (c, '[') != NULL)
+ 	{
+ 	  p = buffer = xstrdup (c);
+ 	  while ((p = strchr (p, '[')) != NULL)
+ 	    p = resolve_operand_name_1 (p, outputs, inputs);
+ 	  TREE_VALUE (TREE_PURPOSE (t))
+ 	    = build_string (strlen (buffer), buffer);
+ 	  free (buffer);
+ 	}
+     }
+ 
+   if (strchr (TREE_STRING_POINTER (string), '[') == NULL)
+     return string;
+ 
    /* Assume that we will not need extra space to perform the substitution.
       This because we get to remove '[' and ']', which means we cannot have
       a problem until we have more than 999 operands.  */
  
!   p = buffer = xstrdup (TREE_STRING_POINTER (string));
    while ((p = strchr (p, '%')) != NULL)
      {
        if (p[1] == '[')
*************** resolve_operand_names (string, outputs, 
*** 2112,2140 ****
    string = build_string (strlen (buffer), buffer);
    free (buffer);
  
-   /* Collect output constraints here because it's convenient.
-      There should be no named operands here; this is verified
-      in expand_asm_operand.  */
-   for (t = outputs; t ; t = TREE_CHAIN (t), pconstraints++)
-     *pconstraints = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
- 
-   /* Substitute [<name>] in input constraint strings.  */
-   for (t = inputs; t ; t = TREE_CHAIN (t), pconstraints++)
-     {
-       const char *c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
-       if (strchr (c, '[') == NULL)
- 	*pconstraints = c;
-       else
- 	{
- 	  p = buffer = xstrdup (c);
- 	  while ((p = strchr (p, '[')) != NULL)
- 	    p = resolve_operand_name_1 (p, outputs, inputs);
- 
- 	  *pconstraints = ggc_alloc_string (buffer, -1);
- 	  free (buffer);
- 	}
-     }
- 
    return string;
  }
  
--- 2161,2166 ----
*** gimplify.c.~1~	2003-06-03 16:02:29.000000000 -0400
--- gimplify.c	2003-06-06 11:29:06.000000000 -0400
*************** simplify_asm_expr (expr, pre_p)
*** 2037,2049 ****
  {
    tree link;
  
!   for (link = ASM_INPUTS (expr); link; link = TREE_CHAIN (link))
!     simplify_expr (&TREE_VALUE (link), pre_p, NULL,
! 		   is_simple_val, fb_rvalue);
  
    for (link = ASM_OUTPUTS (expr); link; link = TREE_CHAIN (link))
      simplify_expr (&TREE_VALUE (link), pre_p, NULL,
  		   is_simple_modify_expr_lhs, fb_lvalue);
  }
  
  /* Apply FN to each statement under *STMT_P, which may be a COMPOUND_EXPR
--- 2047,2071 ----
  {
    tree link;
  
!   ASM_STRING (expr)
!     = resolve_asm_operand_names (ASM_STRING (expr), ASM_OUTPUTS (expr),
! 				 ASM_INPUTS (expr));
  
    for (link = ASM_OUTPUTS (expr); link; link = TREE_CHAIN (link))
      simplify_expr (&TREE_VALUE (link), pre_p, NULL,
  		   is_simple_modify_expr_lhs, fb_lvalue);
+ 
+   for (link = ASM_INPUTS (expr); link; link = TREE_CHAIN (link))
+     {
+       /* If the operand is a memory input, it should be an lvalue.  */
+       if (asm_op_is_mem_input (link, expr))
+ 	simplify_expr (&TREE_VALUE (link), pre_p, NULL,
+ 		       is_simple_modify_expr_lhs, fb_lvalue);
+       else
+ 	simplify_expr (&TREE_VALUE (link), pre_p, NULL,
+ 		       is_simple_val, fb_rvalue);
+     }
+ 
  }
  
  /* Apply FN to each statement under *STMT_P, which may be a COMPOUND_EXPR

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