[PATCH] D18109: Prevent GlobalOpts from dropping ASANitized global variables
Duncan P. N. Exon Smith via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 15 13:47:25 PDT 2016
I'm concerned that fixing up GlobalOpt::deleteIfDead isn't enough
to avoid affecting CodeGen. There are other places in the
pipeline that will check Value::use_empty and/or have logic like
(or use directly) Function::isDefTriviallyDead. I think it's
important that the call to GV.removeDeadConstantUsers() has the
same effect on use-lists whether or not there's any debug info.
Moreover, GlobalOpt::deleteIfDead should have the same effect on
the entire module (including use-lists) regardless of debug info.
(But in case you can convince me, more comments below.)
> On 2016-Mar-15, at 13:10, Adrian Prantl <aprantl at apple.com> wrote:
>
> aprantl added a comment.
>
> I added a check to catch the case where the GV is only kept alive by a constant that is only kept alive by metadata.
Can you add a testcase that confirms that a GlobalVariable will be
deleted even if it has a metadata use? Please included nested
constant expressions to test recursive descent.
Please test Function too, since it has different code paths.
>
> http://reviews.llvm.org/D18109
>
> Index: lib/Transforms/IPO/GlobalOpt.cpp
> ===================================================================
> --- lib/Transforms/IPO/GlobalOpt.cpp
> +++ lib/Transforms/IPO/GlobalOpt.cpp
> @@ -1683,8 +1683,19 @@
> return true;
> }
>
> +/// Return true if GV is only used by constants which are only used by metadata.
> +static bool onlyUsedByMetadata(GlobalValue &GV) {
I think "hasNonMetadataUsers" might be clearer, if you need this
function at all.
> + for (auto *U : GV.users())
> + if (auto *C = dyn_cast<Constant>(U)) {
> + if (!(C->use_empty() && C->isUsedByMetadata()))
For nested constant expressions, will this do the right thing?
(I don't any recursive descent...)
> + return false;
> + } else
> + return false;
> + return true;
> +}
> +
> bool GlobalOpt::deleteIfDead(GlobalValue &GV) {
> - GV.removeDeadConstantUsers();
> + GV.removeDeadConstantUsers(/* skip metadata uses */false);
Can `removeDeadConstantUsers()` return whether GV only has metadata-
based users left? Then you might avoid the new helper method, and
the compile-time cost it implies.
Also, "skip metadata users" isn't very grep-able; IMO it's better to
name this after the function parameter (`/* SkipMetadataUses = */`).
>
> if (!GV.isDiscardableIfUnused())
> return false;
> @@ -1697,7 +1708,7 @@
> if (auto *F = dyn_cast<Function>(&GV))
> Dead = F->isDefTriviallyDead();
I think the change to `removeDeadConstantUsers()` will affect the
return of `F->isDefTriviallyDead()`. That makes the logic pretty
complicated, since you need to skip `blockaddress()` expressions
as well as metadata expressions.
> else
> - Dead = GV.use_empty();
> + Dead = GV.use_empty() || onlyUsedByMetadata(GV);
> if (!Dead)
> return false;
>
More information about the llvm-commits
mailing list