New patch with suggested changes incorporated.  Warning now on by
default, asserts put back if ipa-sra not enabled, and style fixes.

  -DeLesley

On Thu, Nov 3, 2011 at 11:06 AM, Diego Novillo <dnovi...@google.com> wrote:
> On Thu, Nov 3, 2011 at 12:41, Delesley Hutchins <deles...@google.com> wrote:
>>> I wonder... how about disabling IPA-SRA when annotalysis is enabled?
>>
>> That would certainly make my life a lot easier -- IPA-SRA is not
>> really compatible with annotalysis.  The only problem I can see   is
>> that people may be unhappy if turning on annotalysis makes their code
>> runs slower.  We need a good way to communicate the issue to users.
>> Is there a way to print a note that will be reported by the build
>> system, e.g. "Thread safety analysis enabled, some optimizations are
>> disabled?"
>
> Certainly, you could call inform() with a diagnostic.  Though, it's
> true that analysis should not affect optimization levels.  I think I
> prefer making the analysis tolerate the optimizers than affecting code
> generation.
>
>>
>>> Also, why not turn OPT_Wthread_safety on by default?
>>
>> We certainly could.  However, it generates extra warnings, which may
>> break the build for some users.  Which would users prefer: knowing
>> that annotalysis is suppressing warnings, or having to update their
>> build files to pass in an extra flag to turn off the warnings?
>
> What is the effect of your patch on annotalysis warnings?  Does it
> produce false negatives?  If so, I think we should turn this warning
> by default.  I'd rather break the build than let a false negative
> through.
>
>
> Diego.
>



-- 
DeLesley Hutchins | Software Engineer | deles...@google.com | 505-206-0315
Index: testsuite/g++.dg/thread-ann/thread_annot_lock-82.C
===================================================================
--- testsuite/g++.dg/thread-ann/thread_annot_lock-82.C	(revision 180716)
+++ testsuite/g++.dg/thread-ann/thread_annot_lock-82.C	(working copy)
@@ -1,5 +1,5 @@
-// Test template methods in the presence of cloned constructors.
-// Regression test for bugfix.  
+// Regression tests: fix ICE issues when IPA-SRA deletes formal 
+// function parameters. 
 // { dg-do compile }
 // { dg-options "-Wthread-safety -O3" }
 
@@ -10,6 +10,7 @@ void do_something(void* a);
 
 class Foo {
   Mutex mu_;
+  int a GUARDED_BY(mu_);
 
   // with optimization turned on, ipa-sra should eliminate the hidden 
   // "this" argument, thus invalidating EXCLUSIVE_LOCKS_REQUIRED.
@@ -18,6 +19,7 @@ class Foo {
   }
   
   void foo(Foo* f);
+  void bar();
 };
 
 void Foo::foo(Foo* f) {
@@ -28,3 +30,17 @@ void Foo::foo(Foo* f) {
   mu_.Unlock();
 }
 
+
+class SCOPED_LOCKABLE DummyMutexLock {
+public:
+  // IPA-SRA should kill the parameters to these functions
+  explicit DummyMutexLock(Mutex* mutex) EXCLUSIVE_LOCK_FUNCTION(mutex) {}
+  ~DummyMutexLock() UNLOCK_FUNCTION() {}
+};
+
+
+void Foo::bar() {
+  // Matches two warnings:
+  DummyMutexLock dlock(&mu_);  // { dg-warning "attribute has been removed by optimization." } 
+  a = 1;  // warning here should be suppressed, due to errors handling dlock
+}
Index: common.opt
===================================================================
--- common.opt	(revision 180716)
+++ common.opt	(working copy)
@@ -680,6 +680,10 @@ Wthread-attr-bind-param
 Common Var(warn_thread_attr_bind_param) Init(1) Warning
 Make the thread safety analysis try to bind the function parameters used in the attributes
 
+Wthread-warn-optimization
+Common Var(warn_thread_optimization) Init(1) Warning
+Warn when optimizations invalidate the thread safety analysis.
+
 Wtype-limits
 Common Var(warn_type_limits) Init(-1) Warning
 Warn if a comparison is always true or always false due to the limited range of the data type
Index: tree-threadsafe-analyze.c
===================================================================
--- tree-threadsafe-analyze.c	(revision 180716)
+++ tree-threadsafe-analyze.c	(working copy)
@@ -1594,7 +1594,15 @@ get_actual_argument_from_position (gimple call, tr
 
   lock_pos = TREE_INT_CST_LOW (pos_arg);
 
-  gcc_assert (lock_pos >= 1 && lock_pos <= num_args);
+  /* The ipa-sra optimization can occasionally delete arguments, thus
+     invalidating the index. */
+  if (lock_pos < 1 || lock_pos > num_args)
+    {
+      if (flag_ipa_sra)
+        return NULL_TREE;  /* Attempt to recover gracefully. */
+      else
+        gcc_unreachable ();
+    }
 
   /* The lock position specified in the attributes is 1-based, so we need to
      subtract 1 from it when accessing the call arguments.  */
@@ -1734,7 +1742,27 @@ handle_lock_primitive_attrs (gimple call, tree fde
      a formal parameter, we need to grab the corresponding actual argument
      of the call.  */
   else if (TREE_CODE (arg) == INTEGER_CST)
-    arg = get_actual_argument_from_position (call, arg);
+    {
+      arg = get_actual_argument_from_position (call, arg);
+      /* If ipa-sra has rewritten the call, then recover as gracefully as
+         possible.  */
+      if (!arg)
+        {
+          /* Add the universal lock to the lockset to suppress subsequent
+             errors.  */
+          if (is_exclusive_lock)
+            pointer_set_insert (live_excl_locks, error_mark_node);
+          else
+            pointer_set_insert (live_shared_locks, error_mark_node);
+
+          if (warn_thread_optimization)
+            warning_at (*locus, OPT_Wthread_safety,
+                        G_("Lock attribute has been removed by "
+                           "optimization"));
+
+          return;
+        }
+    }
   else if (TREE_CODE (get_leftmost_base_var (arg)) == PARM_DECL)
     {
       tree new_base
@@ -1890,7 +1918,19 @@ handle_unlock_primitive_attr (gimple call, tree fd
          a formal parameter, we need to grab the corresponding actual argument
          of the call.  */
       if (TREE_CODE (arg) == INTEGER_CST)
-        lockable = get_actual_argument_from_position (call, arg);
+        {
+          lockable = get_actual_argument_from_position (call, arg);
+          /* If ipa-sra has rewritten the call, then fail as gracefully as
+             possible -- just leave the lock in the lockset.  */
+          if (!lockable)
+            {
+              if (warn_thread_optimization)
+                warning_at (*locus, OPT_Wthread_safety,
+                            G_("Unlock attribute has been removed by "
+                               "optimization"));
+              return;
+            }
+        }
       else if (TREE_CODE (get_leftmost_base_var (arg)) == PARM_DECL)
         {
           tree fdecl = gimple_call_fndecl (call);
@@ -1908,7 +1948,18 @@ handle_unlock_primitive_attr (gimple call, tree fd
     }
   else
     {
-      gcc_assert (base_obj);
+      /* If ipa-sra has killed arguments, then base_obj may be NULL.
+         Attempt to recover gracefully by leaving the lock in the lockset.  */
+      if (!base_obj)
+        {
+          if (!flag_ipa_sra)
+            gcc_unreachable ();
+          else if (warn_thread_optimization)
+            warning_at (*locus, OPT_Wthread_safety,
+                        G_("Unlock attribute has been removed by "
+                           "optimization"));
+          return;
+        }
 
       /* Check if the primitive is an unlock routine (e.g. the destructor or
          a release function) of a scoped_lock. If so, get the lock that is 
@@ -2099,6 +2150,9 @@ handle_function_lock_requirement (gimple call, tre
       else if (TREE_CODE (lock) == INTEGER_CST)
         {
           lock = get_actual_argument_from_position (call, lock);
+          /* Ignore attribute if ipa-sra has killed the argument. */
+          if (!lock)
+            return;
           /* If the lock is a function argument, we don't want to
              prepend the base object to the lock name. Set the
              TMP_BASE_OBJ to NULL.  */

Reply via email to