[PATCH] D11606: Vtable aliasing improvement: makes obj->vtable noalias obj and modref(obj->virt_call, obj->vtable) = REF

Andrew Zhogin andrew.zhogin at gmail.com
Wed Jul 29 12:46:20 PDT 2015


andrew.zhogin created this revision.
andrew.zhogin added reviewers: hfinkel, reames, sanjoy.
andrew.zhogin added a subscriber: llvm-commits.

This patch contains two improvements for basicaa alias analysis:
* Knowledge that object pointer can't be aliased with vtable loaded from this object (obj->vtable noalias obj).
* Knowledge that virtual call to object can't change this object's vtable.
  modrefinfo(obj->virt_call, obj->vtable) = REF; modrefinfo(obj->virt_call, obj->vtable->fn) = REF;

Vtable is identified by TBAA metadata (isTBAAVtableAccess - already existing function).

Combined with this patch (http://reviews.llvm.org/D11547) it makes very simple in-loop devirtualization works. This bug's example is fixed: https://llvm.org/bugs/show_bug.cgi?id=20801

But just a bit more complex samples require AliasSetTracker's merge sets problem to be fixed.
"alias set collapse and LICM": https://groups.google.com/forum/#!topic/llvm-dev/Qy66vhi5NaY


http://reviews.llvm.org/D11606

Files:
  include/llvm/Analysis/AliasAnalysis.h
  lib/Analysis/AliasAnalysis.cpp
  lib/Analysis/BasicAliasAnalysis.cpp

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<LoadInst>(CalleeVal)) {
+      const auto *VtableVal = CalleeLd->getOperand(0);
+      const auto *VtableValUnder = GetUnderlyingObject(VtableVal, *DL);
+      if (const auto *VtableLd = dyn_cast<LoadInst>(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
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<LoadInst>(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: 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


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D11606.30938.patch
Type: text/x-patch
Size: 3301 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150729/efd4771b/attachment.bin>


More information about the llvm-commits mailing list