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 <[email protected]> wrote:
> On Thu, Nov 3, 2011 at 12:41, Delesley Hutchins <[email protected]> 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 | [email protected] | 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. */