public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* what can be in a group set?
@ 2011-07-08  7:26 Paolo Bonzini
  2011-07-08 10:51 ` Richard Sandiford
  0 siblings, 1 reply; 6+ messages in thread
From: Paolo Bonzini @ 2011-07-08  7:26 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford; +Cc: Dimitrios Apostolou

[-- Attachment #1: Type: text/plain, Size: 1282 bytes --]

df-scan.c has this code to deal with group sets:

   /* It is legal to have a set destination be a parallel. */
   if (GET_CODE (dst) == PARALLEL)
     {
       int i;

       for (i = XVECLEN (dst, 0) - 1; i >= 0; i--)
         {
           rtx temp = XVECEXP (dst, 0, i);
           if (GET_CODE (temp) == EXPR_LIST || GET_CODE (temp) == CLOBBER
               || GET_CODE (temp) == SET)
             df_def_record_1 (collection_rec,
                              temp, bb, insn_info,
                              GET_CODE (temp) == CLOBBER
                              ? flags | DF_REF_MUST_CLOBBER : flags);
         }
       return;
     }

It seems to me that the case of (set (parallel [(set ...)])) and (set 
(parallel [(clobber ...)])) is bogus.  I would like to simplify it to 
the following:

   /* It is legal to have a set destination be a parallel. */
   if (GET_CODE (dst) == PARALLEL)
     {
       int i;

       for (i = XVECLEN (dst, 0) - 1; i >= 0; i--)
         {
           rtx temp = XVECEXP (dst, 0, i);
           assert (GET_CODE (temp) == EXPR_LIST);
           df_def_record_1 (collection_rec, temp, bb, insn_info, flags);
         }
       return;
     }

Does this make sense?  See the attached patch for the overall thing I 
was thinking of.

Paolo

[-- Attachment #2: cleanup-df-ref-record.patch --]
[-- Type: text/x-patch, Size: 3000 bytes --]

        * df-scan.c (df_def_record_1): Assert a parallel must contain
        an EXPR_LIST at this point.  Receive the LOC and move its
        extraction...
        (df_defs_record): ... here.  Remove superfluous braces.

Index: df-scan.c
===================================================================
--- df-scan.c	(revision 169877)
+++ df-scan.c	(working copy)
@@ -111,7 +111,7 @@ static void df_ref_record (enum df_ref_c
 			   rtx, rtx *,
 			   basic_block, struct df_insn_info *,
 			   enum df_ref_type, int ref_flags);
-static void df_def_record_1 (struct df_collection_rec *, rtx,
+static void df_def_record_1 (struct df_collection_rec *, rtx *,
 			     basic_block, struct df_insn_info *,
 			     int ref_flags);
 static void df_defs_record (struct df_collection_rec *, rtx,
@@ -2922,19 +2922,10 @@ df_read_modify_subreg_p (rtx x)
 
 static void
 df_def_record_1 (struct df_collection_rec *collection_rec,
-                 rtx x, basic_block bb, struct df_insn_info *insn_info,
+                 rtx *loc, basic_block bb, struct df_insn_info *insn_info,
 		 int flags)
 {
-  rtx *loc;
-  rtx dst;
-
- /* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL
-     construct.  */
-  if (GET_CODE (x) == EXPR_LIST || GET_CODE (x) == CLOBBER)
-    loc = &XEXP (x, 0);
-  else
-    loc = &SET_DEST (x);
-  dst = *loc;
+  rtx dst = *loc;
 
   /* It is legal to have a set destination be a parallel. */
   if (GET_CODE (dst) == PARALLEL)
@@ -2944,12 +2935,9 @@ df_def_record_1 (struct df_collection_re
       for (i = XVECLEN (dst, 0) - 1; i >= 0; i--)
 	{
 	  rtx temp = XVECEXP (dst, 0, i);
-	  if (GET_CODE (temp) == EXPR_LIST || GET_CODE (temp) == CLOBBER
-	      || GET_CODE (temp) == SET)
-	    df_def_record_1 (collection_rec,
-                             temp, bb, insn_info,
-			     GET_CODE (temp) == CLOBBER
-			     ? flags | DF_REF_MUST_CLOBBER : flags);
+	  gcc_assert (GET_CODE (temp) == EXPR_LIST);
+	  df_def_record_1 (collection_rec, &XEXP (temp, 0),
+			   bb, insn_info, flags);
 	}
       return;
     }
@@ -3003,18 +2991,16 @@ df_defs_record (struct df_collection_rec
 {
   RTX_CODE code = GET_CODE (x);
 
-  if (code == SET || code == CLOBBER)
-    {
-      /* Mark the single def within the pattern.  */
-      int clobber_flags = flags;
-      clobber_flags |= (code == CLOBBER) ? DF_REF_MUST_CLOBBER : 0;
-      df_def_record_1 (collection_rec, x, bb, insn_info, clobber_flags);
-    }
+  if (code == SET)
+    df_def_record_1 (collection_rec, &SET_DEST (x), bb, insn_info, flags);
+  else if (code == CLOBBER)
+    {
+      flags |= DF_REF_MUST_CLOBBER;
+      df_def_record_1 (collection_rec, &XEXP (x, 0), bb, insn_info, flags);
+    }
   else if (code == COND_EXEC)
-    {
-      df_defs_record (collection_rec, COND_EXEC_CODE (x),
-		      bb, insn_info, DF_REF_CONDITIONAL);
-    }
+    df_defs_record (collection_rec, COND_EXEC_CODE (x),
+		    bb, insn_info, DF_REF_CONDITIONAL);
   else if (code == PARALLEL)
     {
       int i;

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: what can be in a group set?
  2011-07-08  7:26 what can be in a group set? Paolo Bonzini
@ 2011-07-08 10:51 ` Richard Sandiford
  2011-07-08 13:05   ` Paolo Bonzini
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Sandiford @ 2011-07-08 10:51 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: GCC Patches, Dimitrios Apostolou

Paolo Bonzini <bonzini@gnu.org> writes:
> df-scan.c has this code to deal with group sets:
>
>    /* It is legal to have a set destination be a parallel. */
>    if (GET_CODE (dst) == PARALLEL)
>      {
>        int i;
>
>        for (i = XVECLEN (dst, 0) - 1; i >= 0; i--)
>          {
>            rtx temp = XVECEXP (dst, 0, i);
>            if (GET_CODE (temp) == EXPR_LIST || GET_CODE (temp) == CLOBBER
>                || GET_CODE (temp) == SET)
>              df_def_record_1 (collection_rec,
>                               temp, bb, insn_info,
>                               GET_CODE (temp) == CLOBBER
>                               ? flags | DF_REF_MUST_CLOBBER : flags);
>          }
>        return;
>      }
>
> It seems to me that the case of (set (parallel [(set ...)])) and (set 
> (parallel [(clobber ...)])) is bogus.  I would like to simplify it to 
> the following:
>
>    /* It is legal to have a set destination be a parallel. */
>    if (GET_CODE (dst) == PARALLEL)
>      {
>        int i;
>
>        for (i = XVECLEN (dst, 0) - 1; i >= 0; i--)
>          {
>            rtx temp = XVECEXP (dst, 0, i);
>            assert (GET_CODE (temp) == EXPR_LIST);
>            df_def_record_1 (collection_rec, temp, bb, insn_info, flags);
>          }
>        return;
>      }
>
> Does this make sense?

Yeah, the docs seem pretty certain that expr_list is the only valid choice.

The docs also say that the first expr_list can be null:

  If @var{lval} is a @code{parallel}, it is used to represent the case of
  a function returning a structure in multiple registers.  Each element
  of the @code{parallel} is an @code{expr_list} whose first operand is a
  @code{reg} and whose second operand is a @code{const_int} representing the
  offset (in bytes) into the structure at which the data in that register
  corresponds.  The first element may be null to indicate that the structure
  is also passed partly in memory.

but I can't see any code to handle that.  Am I missing something,
or does the lack of a crash here mean that we can remove the last
sentence?

(It might have been added for symmetry with argument passing, where this
sort of thing is needed.  But if it isn't actually used or implemented for
returns, it might be less confusing to remove it.)

> See the attached patch for the overall thing I 
> was thinking of.
>
> Paolo
>
>         * df-scan.c (df_def_record_1): Assert a parallel must contain
>         an EXPR_LIST at this point.  Receive the LOC and move its
>         extraction...
>         (df_defs_record): ... here.  Remove superfluous braces.

Looks good.

Richard

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: what can be in a group set?
  2011-07-08 10:51 ` Richard Sandiford
@ 2011-07-08 13:05   ` Paolo Bonzini
  2011-07-08 13:13     ` Dimitrios Apostolou
  0 siblings, 1 reply; 6+ messages in thread
From: Paolo Bonzini @ 2011-07-08 13:05 UTC (permalink / raw)
  To: GCC Patches, Dimitrios Apostolou, richard.sandiford

On 07/08/2011 12:43 PM, Richard Sandiford wrote:
> The docs also say that the first expr_list can be null:
>
>    If @var{lval} is a @code{parallel}, it is used to represent the case of
>    a function returning a structure in multiple registers.  Each element
>    of the @code{parallel} is an @code{expr_list} whose first operand is a
>    @code{reg} and whose second operand is a @code{const_int} representing the
>    offset (in bytes) into the structure at which the data in that register
>    corresponds.  The first element may be null to indicate that the structure
>    is also passed partly in memory.
>
> but I can't see any code to handle that.  Am I missing something,
> or does the lack of a crash here mean that we can remove the last
> sentence?
>
> (It might have been added for symmetry with argument passing, where this
> sort of thing is needed.  But if it isn't actually used or implemented for
> returns, it might be less confusing to remove it.)

Indeed.  Dimitrios, can you pick up the patch since it will somewhat 
simplify your work to eliminate defs_generated?

Paolo

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: what can be in a group set?
  2011-07-08 13:05   ` Paolo Bonzini
@ 2011-07-08 13:13     ` Dimitrios Apostolou
  2011-07-08 13:23       ` Paolo Bonzini
  0 siblings, 1 reply; 6+ messages in thread
From: Dimitrios Apostolou @ 2011-07-08 13:13 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: GCC Patches, richard.sandiford

On Fri, 8 Jul 2011, Paolo Bonzini wrote:
> On 07/08/2011 12:43 PM, Richard Sandiford wrote:
>> The docs also say that the first expr_list can be null:
>>
>>    If @var{lval} is a @code{parallel}, it is used to represent the case of
>>    a function returning a structure in multiple registers.  Each element
>>    of the @code{parallel} is an @code{expr_list} whose first operand is a
>>    @code{reg} and whose second operand is a @code{const_int} representing 
>> the
>>    offset (in bytes) into the structure at which the data in that register
>>    corresponds.  The first element may be null to indicate that the 
>> structure
>>    is also passed partly in memory.
>> 
>> but I can't see any code to handle that.  Am I missing something,
>> or does the lack of a crash here mean that we can remove the last
>> sentence?
>> 
>> (It might have been added for symmetry with argument passing, where this
>> sort of thing is needed.  But if it isn't actually used or implemented for
>> returns, it might be less confusing to remove it.)
>
> Indeed.  Dimitrios, can you pick up the patch since it will somewhat simplify 
> your work to eliminate defs_generated?

I'll certainly try :-)

Paolo, something else, in df_mark_reg() is it ever possible for regno to 
be >= FIRST_PSEUDO_REGISTER? An assert I've put doesn't trigger for my 
simple test :-)


Thanks,
Dimitris

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: what can be in a group set?
  2011-07-08 13:13     ` Dimitrios Apostolou
@ 2011-07-08 13:23       ` Paolo Bonzini
  2011-07-08 13:46         ` Dimitrios Apostolou
  0 siblings, 1 reply; 6+ messages in thread
From: Paolo Bonzini @ 2011-07-08 13:23 UTC (permalink / raw)
  To: Dimitrios Apostolou; +Cc: GCC Patches, richard.sandiford

On 07/08/2011 03:05 PM, Dimitrios Apostolou wrote:
> 
> Paolo, something else, in df_mark_reg() is it ever possible for regno to 
> be >= FIRST_PSEUDO_REGISTER? An assert I've put doesn't trigger for my 
> simple test :-)

From reading the docs of EH_RETURN_STACKADJ_RTX and EH_RETURN_HANDLER_RTX,
it seems you're safe.

This in df-problems.c also suggests the same:

      if (bb_index == EXIT_BLOCK)
        {
          unsigned regno;
          bitmap_iterator bi;
          EXECUTE_IF_SET_IN_BITMAP (df->exit_block_uses, FIRST_PSEUDO_REGISTER,
                                    regno, bi)
            gcc_unreachable ();
        }

A more solid reasoning is that a pseudo cannot be considered live at exit or
at entry to a function, because the caller would not know where it lives.

That said, changing exit_block_uses and entry_block_defs to HARD_REG_SET would
be a nice cleanup, but it would also touch target code due to

  targetm.extra_live_on_entry (entry_block_defs);

I wouldn't bother for now until you're a bit more experienced.  Unlike
invalidated_by_call it shouldn't show up in profiles, or does it?

Paolo

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: what can be in a group set?
  2011-07-08 13:23       ` Paolo Bonzini
@ 2011-07-08 13:46         ` Dimitrios Apostolou
  0 siblings, 0 replies; 6+ messages in thread
From: Dimitrios Apostolou @ 2011-07-08 13:46 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: GCC Patches, richard.sandiford

Thanks Paolo for the detailed explanation!

On Fri, 8 Jul 2011, Paolo Bonzini wrote:
>
> That said, changing exit_block_uses and entry_block_defs to HARD_REG_SET would
> be a nice cleanup, but it would also touch target code due to
>
>  targetm.extra_live_on_entry (entry_block_defs);
>

I've already done that :-p

> I wouldn't bother for now until you're a bit more experienced.  Unlike
> invalidated_by_call it shouldn't show up in profiles, or does it?

Indeed it doesn't show, I just wanted to do it as a clean-up for 
transitioning to HARD_REG_SET all relevant sets in struct df_d.

The only problem remaining is I need a bitmap_copy_from_hard_reg_set() 
function for df_lr_local_compute(), where the bb_info->use bitmap is 
initialised from the exit_block_uses HARD_REG_SET.


Dimitris

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-07-08 13:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-08  7:26 what can be in a group set? Paolo Bonzini
2011-07-08 10:51 ` Richard Sandiford
2011-07-08 13:05   ` Paolo Bonzini
2011-07-08 13:13     ` Dimitrios Apostolou
2011-07-08 13:23       ` Paolo Bonzini
2011-07-08 13:46         ` Dimitrios Apostolou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).