Index: include/llvm/Analysis/AliasAnalysis.h =================================================================== --- include/llvm/Analysis/AliasAnalysis.h +++ include/llvm/Analysis/AliasAnalysis.h @@ -543,6 +543,8 @@ const ModRefInfo Mode) { return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode); } + /// isVtableLoadFrom - Return true if Vtable is vtable load from Obj + bool isVtableLoadFrom(const Value *Vtable, const Value *Obj); }; /// isNoAliasCall - Return true if this pointer is returned by a noalias Index: lib/Analysis/AliasAnalysis.cpp =================================================================== --- lib/Analysis/AliasAnalysis.cpp +++ lib/Analysis/AliasAnalysis.cpp @@ -446,6 +446,17 @@ return false; } +/// isVtableLoadFrom - Return true if Vtable is vtable load from Obj +bool AliasAnalysis::isVtableLoadFrom(const Value *Vtable, const Value *Obj) { + if (const auto *VtableLd = dyn_cast(Vtable)) { + AAMDNodes AAInfo; + VtableLd->getAAMetadata(AAInfo); + if (AAInfo.TBAA && AAInfo.TBAA->isTBAAVtableAccess()) + return GetUnderlyingObject(VtableLd->getOperand(0), *DL) == Obj; + } + return false; +} + /// isNoAliasCall - Return true if this pointer is returned by a noalias /// function. bool llvm::isNoAliasCall(const Value *V) { Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -791,6 +791,31 @@ if (CI->isTailCall()) return MRI_NoModRef; + // If this is virtual call to obj, considering obj->vtable and obj->vtable->fn as not modifiable + if (CS.getNumArgOperands() > 0) { + const auto *CalleeVal = CS.getCalledValue(); // must be load vtable + offset + const auto *CallObj = CS.getArgOperand(0); // must be obj + + if (const auto *CalleeLd = dyn_cast(CalleeVal)) { + const auto *VtableVal = CalleeLd->getOperand(0); + const auto *VtableValUnder = GetUnderlyingObject(VtableVal, *DL); + if (const auto *VtableLd = dyn_cast(VtableValUnder)) { + AAMDNodes AAInfo; + VtableLd->getAAMetadata(AAInfo); + if (AAInfo.TBAA) { + if (AAInfo.TBAA->isTBAAVtableAccess()) { + const auto *ObjForVtable = VtableLd->getOperand(0); + + if (isMustAlias(GetUnderlyingObject(ObjForVtable, *DL), CallObj)) + if (isMustAlias(VtableValUnder, Object) + || isMustAlias(ObjForVtable, Object)) + return MRI_Ref; + } + } + } + } + } + // If the pointer is to a locally allocated object that does not escape, // then the call can not mod/ref the pointer unless the call takes the pointer // as an argument, and itself doesn't capture it. @@ -1433,6 +1458,10 @@ return NoAlias; if (isEscapeSource(O2) && isNonEscapingLocalObject(O1)) return NoAlias; + + // Considering Object's Vtable can't alias Object + if (isVtableLoadFrom(O1, O2) || isVtableLoadFrom(O2, O1)) + return NoAlias; } // If the size of one access is larger than the entire object on the other