public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Aldy Hernandez <aldyh@redhat.com>
To: Ian Lance Taylor <iant@google.com>
Cc: Jakub Jelinek <jakub@redhat.com>,
	gcc-patches <gcc-patches@gcc.gnu.org>,
	       Richard Guenther <richard.guenther@gmail.com>,
	       Ian Lance Taylor <ian@airs.com>,
	Andrew MacLeod <amacleod@redhat.com>
Subject: Re: [path] PR 54900: store data race in if-conversion pass
Date: Fri, 19 Oct 2012 01:41:00 -0000	[thread overview]
Message-ID: <508093A9.9020204@redhat.com> (raw)
In-Reply-To: <CAKOQZ8y4G=6Zx5AfifEFjrh-TuTFDo-3F+EnO8gqcHwdG8tjdQ@mail.gmail.com>

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

On 10/16/12 20:33, Ian Lance Taylor wrote:
> On Tue, Oct 16, 2012 at 4:54 PM, Aldy Hernandez <aldyh@redhat.com> wrote:
>> On 10/16/12 13:28, Jakub Jelinek wrote:

>>>     location of considered if-conversion on mem
>>>     if (some_condition)
>>>       call ();
>>>     mem = something;
>>
>>
>> Are we not currently being conservative in the current code and returning
>> false once we see a volatile or a non-const call?
>
> Jakub's point is that in his example the call will not be a
> post-dominator of the block.  it's a good point.  Would you mind
> trying to create a test case along those lines?

Ah, I see.

Well, I can't come up with a testcase that fits into our testing 
infrastructure because of the aforementioned problems catching an 
addition of zero.  I could scan the assembly, but anything I could come 
up with is not only back-end specific, but extremely fragile.

I am attaching a testcase that I have used to (manually) test the patch 
below.  The relevant parts are in the attached testcase is:

   ...
   TOP_BB
   outerfunc (innerfunc ());
   if (flag_for_funky)
     funky();
   dont_write += 666;

My approach is, once we find the DONT_WRITE block, we generate a list of 
all the blocks at are post-dominated by it, and if there is a 
volatile/call that is between TOP_BB and the write, then a volatile/call 
will occur and we can't perform the speculation.

This works with the testcase at hand, though probably a bit inefficient. 
  For one, we could calculate the dominance info earlier in the pass, 
though I prefer calculating it only if we're actually considering 
speculating.  I'm open to suggestions.

I'm running into a weird verify_dominators() problem during bootstrap-- 
which is odd, because I'm forcing a recompute of the dominance tree. 
But I wanted to post this to make sure I'm at least poking in the right 
direction.

Thoughts?

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 2548 bytes --]


	PR rtl-optimization/54900
	* ifcvt.c (volatile_or_non_const_call): New.
	(noce_can_store_speculate_p): Handle intervening calls.

diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 5654c66..c615efd 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -2388,6 +2388,16 @@ noce_mem_write_may_trap_or_fault_p (const_rtx mem)
   return false;
 }
 
+/* Return TRUE if INSN is a volatile insn or a non const call.  */
+
+static inline bool
+volatile_or_non_const_call (rtx insn)
+{
+  return (INSN_P (insn)
+	  && (volatile_insn_p (PATTERN (insn))
+	      || (CALL_P (insn) && (!RTL_CONST_CALL_P (insn)))));
+}
+
 /* Return whether we can use store speculation for MEM.  TOP_BB is the
    basic block above the conditional block where we are considering
    doing the speculative store.  We look for whether MEM is set
@@ -2410,13 +2420,47 @@ noce_can_store_speculate_p (basic_block top_bb, const_rtx mem)
 	     have to stop looking.  Even if the MEM is set later in
 	     the function, we still don't want to set it
 	     unconditionally before the barrier.  */
-	  if (INSN_P (insn)
-	      && (volatile_insn_p (PATTERN (insn))
-		  || (CALL_P (insn) && (!RTL_CONST_CALL_P (insn)))))
+	  if (volatile_or_non_const_call (insn))
 	    return false;
 
+	  /* We can speculate if the MEM will be set on every path out
+	     of TOP_BB, but we must be careful that there is no
+	     intervening call/volatile between TOP_BB and the set.
+
+	     For the intervening call/volatile case, We are looking
+	     for something akin to:
+
+	        location of considered if-conversion on mem
+		if (condition)
+		  call ();
+		mem = something;  */
 	  if (memory_must_be_modified_in_insn_p (mem, insn))
-	    return true;
+	    {
+	      if (!dom_info_available_p (CDI_DOMINATORS))
+		calculate_dominance_info (CDI_DOMINATORS);
+
+	      /* Get all blocks that are post-dominated by the SET.  */
+	      VEC (basic_block, heap) *bbs =
+		get_all_dominated_blocks (CDI_POST_DOMINATORS,
+					  BLOCK_FOR_INSN (insn));
+	      while (VEC_length (basic_block, bbs))
+		{
+		  rtx call;
+		  basic_block bb = VEC_pop (basic_block, bbs);
+
+		  /* If there is an intervening volatile/call between
+		     TOP_BB and the SET of MEM, bail.  */
+		  FOR_BB_INSNS (bb, call)
+		    if (volatile_or_non_const_call (call)
+			&& dominated_by_p (CDI_DOMINATORS,
+					   BLOCK_FOR_INSN (call),
+					   top_bb))
+		      return false;
+		}
+	      VEC_free (basic_block, heap, bbs);
+	      return true;
+	    }
+
 	  if (modified_in_p (XEXP (mem, 0), insn))
 	    return false;
 

[-- Attachment #3: testcase.c --]
[-- Type: text/plain, Size: 471 bytes --]

/* Compile with -O2.  */
/* There shouldn't be a an unconditional write to dont_write in main().  */

extern int printf(const char *format, ...);

int flag = 1;
int flag_for_funky;
int stuff;
int *stuffp = &stuff;
int dont_write;

extern void funky();

void outerfunc (p1) {
  *stuffp = 0;
}

int innerfunc ()
{
  if (flag)
    return 0;
  ++dont_write;
  return 0;
}

void main () 
{
  outerfunc (innerfunc ());
  if (flag_for_funky)
    funky();
  dont_write += 666;
}

  reply	other threads:[~2012-10-18 23:41 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-15 12:53 Aldy Hernandez
2012-10-15 14:25 ` Andrew MacLeod
2012-10-16 17:32 ` Ian Lance Taylor
2012-10-16 17:33   ` Jakub Jelinek
2012-10-17  0:33     ` Aldy Hernandez
2012-10-17  0:54       ` Ian Lance Taylor
2012-10-19  1:41         ` Aldy Hernandez [this message]
2012-10-17  0:26   ` Aldy Hernandez
2012-10-17  0:54     ` Ian Lance Taylor
2012-10-17  4:54     ` Richard Henderson
2012-10-17  5:18       ` Jeff Law
2012-10-17 21:48         ` Aldy Hernandez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=508093A9.9020204@redhat.com \
    --to=aldyh@redhat.com \
    --cc=amacleod@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=ian@airs.com \
    --cc=iant@google.com \
    --cc=jakub@redhat.com \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).