summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGClass.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-11-03 18:55:18 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-11-03 18:55:18 +0000
commit4d47937a5393428157049587bb361e36ccd197ca (patch)
tree5d3e2676f399de8fa7ae88d5ad85ed5d92d747a4 /lib/CodeGen/CGClass.cpp
parentf1b760ebd6aaea8b930aa076a36db0768b80c1f2 (diff)
Improve obvious-most-derived-type devirtualization:
* if the base is produced by a series of derived-to-base conversions, check the expression inside them when looking for an expression with a known dynamic type * step past MaterializeTemporaryExprs when checking for a known dynamic type * when checking for a known dynamic type, treat all class prvalues as having a known dynamic type after skipping all relevant rvalue subobject adjustments * treat callees formed by pointer-to-member access for a non-reference member type like callees formed by member access. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285954 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGClass.cpp')
-rw-r--r--lib/CodeGen/CGClass.cpp52
1 files changed, 15 insertions, 37 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 99eb5d5c03..2f5855f89b 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -2842,31 +2842,6 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
cast<llvm::PointerType>(VTable->getType())->getElementType());
}
-// FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do
-// quite what we want.
-static const Expr *skipNoOpCastsAndParens(const Expr *E) {
- while (true) {
- if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
- E = PE->getSubExpr();
- continue;
- }
-
- if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
- if (CE->getCastKind() == CK_NoOp) {
- E = CE->getSubExpr();
- continue;
- }
- }
- if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
- if (UO->getOpcode() == UO_Extension) {
- E = UO->getSubExpr();
- continue;
- }
- }
- return E;
- }
-}
-
bool
CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
const CXXMethodDecl *MD) {
@@ -2880,6 +2855,12 @@ CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
if (MD->hasAttr<FinalAttr>())
return true;
+ // If the base expression (after skipping derived-to-base conversions) is a
+ // class prvalue, then we can devirtualize.
+ Base = Base->getBestDynamicClassTypeExpr();
+ if (Base->isRValue() && Base->getType()->isRecordType())
+ return true;
+
// If the most derived class is marked final, we know that no subclass can
// override this member function and so we can devirtualize it. For example:
//
@@ -2907,7 +2888,6 @@ CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
if (MD->getParent()->hasAttr<FinalAttr>())
return true;
- Base = skipNoOpCastsAndParens(Base);
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
// This is a record decl. We know the type and can devirtualize it.
@@ -2924,17 +2904,15 @@ CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl()))
return VD->getType()->isRecordType();
- // We can always devirtualize calls on temporary object expressions.
- if (isa<CXXConstructExpr>(Base))
- return true;
-
- // And calls on bound temporaries.
- if (isa<CXXBindTemporaryExpr>(Base))
- return true;
-
- // Check if this is a call expr that returns a record type.
- if (const CallExpr *CE = dyn_cast<CallExpr>(Base))
- return CE->getCallReturnType(getContext())->isRecordType();
+ // Likewise for calls on an object accessed by a (non-reference) pointer to
+ // member access.
+ if (auto *BO = dyn_cast<BinaryOperator>(Base)) {
+ if (BO->isPtrMemOp()) {
+ auto *MPT = BO->getRHS()->getType()->castAs<MemberPointerType>();
+ if (MPT->getPointeeType()->isRecordType())
+ return true;
+ }
+ }
// We can't devirtualize the call.
return false;