[PATCH 0/3] c++: Devirtualization of constant pointer to member function call

Chi Wang <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
GCC has barely any devirtualization support for pointer to member function
(PMF) call. The only possible devirtualization is by constant propagation of
virtual table to a known object that is taken address of:

  T t;
  ((&t)->*member) ();

However, PMFs are useful to simplify repetitive call patterns or use as
callbacks in functions or templates. In these usages, the PMFs are clearly
constants but do not benefit from trivial devirtualization. Even for a simple
call:

  T* t;
  (t->*&T::func) ();
  // or
  std::invoke (&T::func, t);

cannot be devirtualized if func is a virtual function and marked final, while in
practice it should be the same as calling t->func ().

This patch series tries to address this gap. We use an internal function
IFN_PTRMEMFUNC_OBJ to mark the calling object in the virtual branch of PMF
decoding. The motivation behind this is that both IFN_PTRMEMFUNC_OBJ can
preserve more C++ FE type information and guard folding pointer type cast and
pointer plus expressions, which can obfuscate the offsets in PMF object
adjustments and vtable lookup.

In a PMF call, two pointer adjustments happen: one is when front end adjusts the
object pointer to the base type of the PMF, and the other is at runtime, the PMF
*this object adjustment. The design is that IFN_PTRMEMFUNC_OBJ will hold the
casted object, the type of PMF, the original type of the object, the front end
cast offset, and whether the front end cast is through any virtual base lookup
(which makes the previous offset not reliable for derived classes).

This marker drives a tree pass that tries to convert to direct call to final
polymorphic target, similar to how C++ FE does for plain polymorphic call, and
also lets IPA and WPA discover inlining and cloning opportunities. These are
simply extending the existing code path for simple indirect call and simple
polymorphic call to also recognize the PMF call patterns. The main result is
that most simple PMF constant calls are now possible to be a direct call or even
inlined.

Testing results:
* x86_64 native: bootstrapped and regression tested on all languages
* x86_64 -m32: bootstrapped and regression tested on all languages except golang
  (cannot build because of 32 bit system call issues)
* aarch64: bootstrapped and regression tested on C and C++
* ia64: tested non-LTO devirtualization tests, on a cross-compiler build that
  disables all libraries, shared libraries linking, and threading support. I ran
  this because it was still in the codebase and is the only target using
  function descriptors, although it is marked obsolete now.

Ok for trunk?

Chi Wang (3):
  Add a pass to devirtualize polymorphic PMF calls
  ipa: New indirect info kind and optimization for PMF
  lto: Keep vtable definition for PMF calls

 gcc/Makefile.in                         |   1 +
 gcc/cgraph.cc                           |  73 ++-
 gcc/cgraph.h                            |  81 ++-
 gcc/cgraphclones.cc                     |   5 +
 gcc/cgraphunit.cc                       |  24 +
 gcc/cp/constexpr.cc                     |   2 +
 gcc/cp/method.cc                        |   1 +
 gcc/cp/typeck.cc                        |  32 +-
 gcc/doc/ifn.texi                        |   5 +
 gcc/gimple-ptrmemfunc.cc                | 656 ++++++++++++++++++++++++
 gcc/gimple-ptrmemfunc.h                 |  29 ++
 gcc/internal-fn.cc                      |  11 +
 gcc/internal-fn.def                     |   3 +
 gcc/ipa-cp.cc                           |  26 +-
 gcc/ipa-devirt.cc                       |  55 ++
 gcc/ipa-fnsummary.cc                    |   2 +-
 gcc/ipa-prop.cc                         | 279 ++++++++--
 gcc/ipa-prop.h                          |   3 +-
 gcc/ipa-utils.h                         |   2 +
 gcc/ipa.cc                              |  49 +-
 gcc/lto-cgraph.cc                       |  86 +++-
 gcc/passes.def                          |   2 +
 gcc/testsuite/g++.dg/lto/devirtpmf1_0.C |  13 +
 gcc/testsuite/g++.dg/lto/devirtpmf1_1.C |  16 +
 gcc/testsuite/g++.dg/lto/devirtpmf2_0.C |  13 +
 gcc/testsuite/g++.dg/lto/devirtpmf2_1.C |  11 +
 gcc/testsuite/g++.dg/lto/devirtpmf2_2.C |   7 +
 gcc/testsuite/g++.dg/lto/devirtpmf3_0.C |  13 +
 gcc/testsuite/g++.dg/lto/devirtpmf3_1.C |  24 +
 gcc/testsuite/g++.dg/opt/devirtpmf1.C   | 128 +++++
 gcc/testsuite/g++.dg/opt/devirtpmf2.C   |  63 +++
 gcc/testsuite/g++.dg/opt/devirtpmf3.C   |  57 ++
 gcc/testsuite/g++.dg/opt/devirtpmf4.C   |  45 ++
 gcc/testsuite/g++.dg/opt/devirtpmf5.C   |  72 +++
 gcc/testsuite/g++.dg/opt/devirtpmf6.C   |  62 +++
 gcc/testsuite/g++.dg/opt/devirtpmf7.C   |  23 +
 gcc/testsuite/g++.dg/opt/devirtpmf8.C   |  28 +
 gcc/timevar.def                         |   1 +
 gcc/tree-pass.h                         |   1 +
 gcc/varpool.cc                          |   2 +
 40 files changed, 1920 insertions(+), 86 deletions(-)
 create mode 100644 gcc/gimple-ptrmemfunc.cc
 create mode 100644 gcc/gimple-ptrmemfunc.h
 create mode 100644 gcc/testsuite/g++.dg/lto/devirtpmf1_0.C
 create mode 100644 gcc/testsuite/g++.dg/lto/devirtpmf1_1.C
 create mode 100644 gcc/testsuite/g++.dg/lto/devirtpmf2_0.C
 create mode 100644 gcc/testsuite/g++.dg/lto/devirtpmf2_1.C
 create mode 100644 gcc/testsuite/g++.dg/lto/devirtpmf2_2.C
 create mode 100644 gcc/testsuite/g++.dg/lto/devirtpmf3_0.C
 create mode 100644 gcc/testsuite/g++.dg/lto/devirtpmf3_1.C
 create mode 100644 gcc/testsuite/g++.dg/opt/devirtpmf1.C
 create mode 100644 gcc/testsuite/g++.dg/opt/devirtpmf2.C
 create mode 100644 gcc/testsuite/g++.dg/opt/devirtpmf3.C
 create mode 100644 gcc/testsuite/g++.dg/opt/devirtpmf4.C
 create mode 100644 gcc/testsuite/g++.dg/opt/devirtpmf5.C
 create mode 100644 gcc/testsuite/g++.dg/opt/devirtpmf6.C
 create mode 100644 gcc/testsuite/g++.dg/opt/devirtpmf7.C
 create mode 100644 gcc/testsuite/g++.dg/opt/devirtpmf8.C

-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.