[llvm] r176562 - Memory Dependence Analysis (not mem-dep test) take advantage of "invariant.load" metadata.

Shuxin Yang shuxin.llvm at gmail.com
Wed Mar 6 09:48:49 PST 2013


Author: shuxin_yang
Date: Wed Mar  6 11:48:48 2013
New Revision: 176562

URL: http://llvm.org/viewvc/llvm-project?rev=176562&view=rev
Log:
Memory Dependence Analysis (not mem-dep test) take advantage of "invariant.load" metadata.

The "invariant.load" metadata indicates the memory unit being accessed is immutable.
A load annotated with this metadata can be moved across any store.

As I am not sure if it is legal to move such loads across barrier/fence, this
change dose not allow such transformation.

rdar://11311484

Thank Arnold for code review.

Added:
    llvm/trunk/test/Analysis/BasicAA/invariant_load.ll
Modified:
    llvm/trunk/include/llvm/Analysis/MemoryDependenceAnalysis.h
    llvm/trunk/include/llvm/IR/LLVMContext.h
    llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
    llvm/trunk/lib/IR/LLVMContext.cpp

Modified: llvm/trunk/include/llvm/Analysis/MemoryDependenceAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/MemoryDependenceAnalysis.h?rev=176562&r1=176561&r2=176562&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/MemoryDependenceAnalysis.h (original)
+++ llvm/trunk/include/llvm/Analysis/MemoryDependenceAnalysis.h Wed Mar  6 11:48:48 2013
@@ -391,14 +391,17 @@ namespace llvm {
     /// getPointerDependencyFrom - Return the instruction on which a memory
     /// location depends.  If isLoad is true, this routine ignores may-aliases
     /// with read-only operations.  If isLoad is false, this routine ignores
-    /// may-aliases with reads from read-only locations.
+    /// may-aliases with reads from read-only locations. If possible, pass
+    /// the query instruction as well; this function may take advantage of 
+    /// the metadata annotated to the query instruction to refine the result.
     ///
     /// Note that this is an uncached query, and thus may be inefficient.
     ///
     MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc,
                                           bool isLoad,
                                           BasicBlock::iterator ScanIt,
-                                          BasicBlock *BB);
+                                          BasicBlock *BB,
+                                          Instruction *QueryInst = 0);
 
 
     /// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that

Modified: llvm/trunk/include/llvm/IR/LLVMContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/LLVMContext.h?rev=176562&r1=176561&r2=176562&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/LLVMContext.h (original)
+++ llvm/trunk/include/llvm/IR/LLVMContext.h Wed Mar  6 11:48:48 2013
@@ -46,7 +46,8 @@ public:
     MD_prof = 2,  // "prof"
     MD_fpmath = 3,  // "fpmath"
     MD_range = 4, // "range"
-    MD_tbaa_struct = 5 // "tbaa.struct"
+    MD_tbaa_struct = 5, // "tbaa.struct"
+    MD_invariant_load = 6 // "invariant.load"
   };
   
   /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.

Modified: llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=176562&r1=176561&r2=176562&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp Wed Mar  6 11:48:48 2013
@@ -351,15 +351,23 @@ getLoadLoadClobberFullWidthSize(const Va
 /// getPointerDependencyFrom - Return the instruction on which a memory
 /// location depends.  If isLoad is true, this routine ignores may-aliases with
 /// read-only operations.  If isLoad is false, this routine ignores may-aliases
-/// with reads from read-only locations.
+/// with reads from read-only locations.  If possible, pass the query
+/// instruction as well; this function may take advantage of the metadata
+/// annotated to the query instruction to refine the result.
 MemDepResult MemoryDependenceAnalysis::
 getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad, 
-                         BasicBlock::iterator ScanIt, BasicBlock *BB) {
+                         BasicBlock::iterator ScanIt, BasicBlock *BB,
+                         Instruction *QueryInst) {
 
   const Value *MemLocBase = 0;
   int64_t MemLocOffset = 0;
-
   unsigned Limit = BlockScanLimit;
+  bool isInvariantLoad = false;
+  if (isLoad && QueryInst) {
+    LoadInst *LI = dyn_cast<LoadInst>(QueryInst);
+    if (LI && LI->getMetadata(LLVMContext::MD_invariant_load) != 0)
+      isInvariantLoad = true;
+  }
 
   // Walk backwards through the basic block, looking for dependencies.
   while (ScanIt != BB->begin()) {
@@ -474,6 +482,8 @@ getPointerDependencyFrom(const AliasAnal
         continue;
       if (R == AliasAnalysis::MustAlias)
         return MemDepResult::getDef(Inst);
+      if (isInvariantLoad)
+       continue;
       return MemDepResult::getClobber(Inst);
     }
 
@@ -571,7 +581,7 @@ MemDepResult MemoryDependenceAnalysis::g
         isLoad |= II->getIntrinsicID() == Intrinsic::lifetime_start;
 
       LocalCache = getPointerDependencyFrom(MemLoc, isLoad, ScanPos,
-                                            QueryParent);
+                                            QueryParent, QueryInst);
     } else if (isa<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst)) {
       CallSite QueryCS(QueryInst);
       bool isReadOnly = AA->onlyReadsMemory(QueryCS);

Modified: llvm/trunk/lib/IR/LLVMContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContext.cpp?rev=176562&r1=176561&r2=176562&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContext.cpp (original)
+++ llvm/trunk/lib/IR/LLVMContext.cpp Wed Mar  6 11:48:48 2013
@@ -58,6 +58,11 @@ LLVMContext::LLVMContext() : pImpl(new L
   unsigned TBAAStructID = getMDKindID("tbaa.struct");
   assert(TBAAStructID == MD_tbaa_struct && "tbaa.struct kind id drifted");
   (void)TBAAStructID;
+
+  // Create the 'invariant.load' metadata kind.
+  unsigned InvariantLdId = getMDKindID("invariant.load");
+  assert(InvariantLdId == MD_invariant_load && "invariant.load kind id drifted");
+  (void)InvariantLdId;
 }
 LLVMContext::~LLVMContext() { delete pImpl; }
 

Added: llvm/trunk/test/Analysis/BasicAA/invariant_load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/invariant_load.ll?rev=176562&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/BasicAA/invariant_load.ll (added)
+++ llvm/trunk/test/Analysis/BasicAA/invariant_load.ll Wed Mar  6 11:48:48 2013
@@ -0,0 +1,29 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+; The input *.ll is obtained by manually annotating "invariant.load" to the 
+; two loads. With "invariant.load" metadata, the second load is redundant.
+;
+; int foo(int *p, char *q) {
+;     *q = (char)*p;
+;     return *p + 1;
+; }
+
+define i32 @foo(i32* nocapture %p, i8* nocapture %q) {
+entry:
+  %0 = load i32* %p, align 4, !tbaa !0, !invariant.load !3
+  %conv = trunc i32 %0 to i8
+  store i8 %conv, i8* %q, align 1, !tbaa !1
+  %1 = load i32* %p, align 4, !tbaa !0, !invariant.load !3
+  %add = add nsw i32 %1, 1
+  ret i32 %add
+
+; CHECK: foo
+; CHECK: %0 = load i32* %p
+; CHECK: store i8 %conv, i8* %q,
+; CHECK: %add = add nsw i32 %0, 1
+}
+
+!0 = metadata !{metadata !"int", metadata !1}
+!1 = metadata !{metadata !"omnipotent char", metadata !2}
+!2 = metadata !{metadata !"Simple C/C++ TBAA"}
+!3 = metadata !{}





More information about the llvm-commits mailing list