[prev in list] [next in list] [prev in thread] [next in thread] 

List:       llvm-commits
Subject:    [PATCH] D11606: Vtable aliasing improvement: makes obj->vtable noalias obj and modref(obj->virt_call
From:       Andrew Zhogin <andrew.zhogin () gmail ! com>
Date:       2015-07-29 19:46:20
Message-ID: differential-rev-PHID-DREV-xjf5m3lbzmzl47qlq36z-req () reviews ! llvm ! org
[Download RAW message or body]

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


["D11606.30938.patch" (text/x-patch)]

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


_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic