This is an archive of the discontinued LLVM Phabricator instance.

[profiling] PR31992: Don't skip interesting non-base constructors
ClosedPublic

Authored by vsk on Feb 17 2017, 7:04 PM.

Details

Summary

Fix the fact that we don't assign profile counters to constructors in
classes with virtual bases, or constructors with variadic parameters.

I checked that we get a proper code coverage report for both tests.

Diff Detail

Repository
rL LLVM

Event Timeline

vsk created this revision.Feb 17 2017, 7:04 PM
arphaman added inline comments.Feb 17 2017, 7:15 PM
lib/CodeGen/CodeGenPGO.cpp
631 ↗(On Diff #89006)

I think it would be more appropriate to use the IsConstructorDelegationValid static function from CGClass.cpp instead of using the numVBases check, as some virtual inheritance constructors might get delegated in the future (as stated in the comments inside of IsConstructorDelegationValid).

vsk updated this revision to Diff 89151.Feb 20 2017, 6:30 PM
vsk retitled this revision from [profiling] Don't skip non-base constructors if there is a virtual base (fixes PR31992) to [profiling] PR31992: Don't skip interesting non-base constructors.
vsk edited the summary of this revision. (Show Details)
  • Use IsConstructorDelegationValid per Alex's suggestion. This exposed the variadic constructor case which we had also missed previously.
arphaman accepted this revision.Feb 22 2017, 6:04 PM

LGTM.

One point to note, when we are displaying coverage for constructors that have both the base and complete versions instrumented, e.g.:

class Foo {
public:
    Foo() { }
};

class Bar : virtual public Foo {
public:
   Bar() { }; // llvm-cov will show 2 instantiations for Bar()
};

class BarBar: public Bar {
public:
  BarBar() { }
};

int main (int argc, char* argv[])
{
    BarBar b;
    Bar bb;
}

llvm-cov will treat each constructor as an instantiation (like a template instantiation). Should they be treated as instantiations though?

This revision is now accepted and ready to land.Feb 22 2017, 6:04 PM
vsk added a comment.Feb 23 2017, 5:25 PM

LGTM.

One point to note, when we are displaying coverage for constructors that have both the base and complete versions instrumented, e.g.:

class Foo {
public:
    Foo() { }
};

class Bar : virtual public Foo {
public:
   Bar() { }; // llvm-cov will show 2 instantiations for Bar()
};

class BarBar: public Bar {
public:
  BarBar() { }
};

int main (int argc, char* argv[])
{
    BarBar b;
    Bar bb;
}

llvm-cov will treat each constructor as an instantiation (like a template instantiation). Should they be treated as instantiations though?

No, ideally we'd combine the coverage reporting for Bar's constructors, since it's unlikely that users care about the distinction between them:

/tmp/x.cc:
    1|       |class Foo {
    2|       |public:
    3|      2|    Foo() { }
    4|       |};
    5|       |
    6|       |class Bar : virtual public Foo {
    7|       |public:
    8|      2|   Bar() { }; // llvm-cov will show 2 instantiations for Bar()
  ------------------
  | _ZN3BarC2Ev:        //< It doesn't help that these symbols demangle to the same name..
  |    8|      1|   Bar() { }; // llvm-cov will show 2 instantiations for Bar()
  ------------------
  | _ZN3BarC1Ev:
  |    8|      1|   Bar() { }; // llvm-cov will show 2 instantiations for Bar()
  ------------------
    9|       |};
   10|       |
   11|       |class BarBar: public Bar {
   12|       |public:
   13|      1|  BarBar() { }
   14|       |};
   15|       |
   16|       |int main (int argc, char* argv[])
   17|      1|{
   18|      1|    BarBar b; // calls _ZN6BarBarC1Ev -> {_ZN3FooC2Ev, _ZN3BarC2Ev} (leaves)
   19|      1|    Bar bb; // calls _ZN3BarC1Ev -> _ZN3FooC2Ev (leaf)
   20|      1|}

I don't think this report is 'terrible' though. It's certainly better than saying "BarBar"/"Bar" are executed 0/1 times, which is the status quo.

This revision was automatically updated to reflect the committed changes.