[llvm-commits] [dragonegg] r153826 - in /dragonegg/trunk: include/dragonegg/Aliasing.h src/Aliasing.cpp src/Convert.cpp

Duncan Sands baldrick at free.fr
Sat Mar 31 23:58:04 PDT 2012


Author: baldrick
Date: Sun Apr  1 01:58:04 2012
New Revision: 153826

URL: http://llvm.org/viewvc/llvm-project?rev=153826&view=rev
Log:
Attach type-based alias analysis metadata to loads and stores.  The metadata to
use is obtained by reasoning about GCC's alias sets.  Currently it is only used
in the simplest circumstances: scalar load/store to a non-bitfield.  Also, the
metadata itself is extremely conservative.  For example, when compiling gcc-as-
one-big-file, GCC's alias set DAG has about 200 nodes and a complicated topology
but they are all collapsed down to one common metadata node, i.e. the metadata
we produce in this case is completely useless.  I plan to improve both of these
points progressively.  In the meantime, give the code a whirl through the build
bots.

Added:
    dragonegg/trunk/include/dragonegg/Aliasing.h
    dragonegg/trunk/src/Aliasing.cpp
Modified:
    dragonegg/trunk/src/Convert.cpp

Added: dragonegg/trunk/include/dragonegg/Aliasing.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Aliasing.h?rev=153826&view=auto
==============================================================================
--- dragonegg/trunk/include/dragonegg/Aliasing.h (added)
+++ dragonegg/trunk/include/dragonegg/Aliasing.h Sun Apr  1 01:58:04 2012
@@ -0,0 +1,37 @@
+//=------- Aliasing.h - Type-based alias analysis metadata --------*- C++ -*-=//
+//
+// Copyright (C) 2012  Duncan Sands.
+//
+// This file is part of DragonEgg.
+//
+// DragonEgg is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later version.
+//
+// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+// A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// DragonEgg; see the file COPYING.  If not, write to the Free Software
+// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+//
+//===----------------------------------------------------------------------===//
+// This file declares routines for generating TBAA metadata from what GCC knows
+// about pointer aliasing.
+//===----------------------------------------------------------------------===//
+
+#ifndef DRAGONEGG_ALIASING_H
+#define DRAGONEGG_ALIASING_H
+
+// Forward declarations.
+namespace llvm {
+  class MDNode;
+}
+union tree_node;
+
+/// describeAliasSet - Return TBAA metadata describing what a load from or store
+/// to the given tree may alias.
+extern llvm::MDNode *describeAliasSet(tree_node *t);
+
+#endif /* DRAGONEGG_ALIASING_H */

Added: dragonegg/trunk/src/Aliasing.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Aliasing.cpp?rev=153826&view=auto
==============================================================================
--- dragonegg/trunk/src/Aliasing.cpp (added)
+++ dragonegg/trunk/src/Aliasing.cpp Sun Apr  1 01:58:04 2012
@@ -0,0 +1,162 @@
+//=----------- Aliasing.cpp - Type-based alias analysis metadata ----------*-=//
+//
+// Copyright (C) 2012  Duncan Sands.
+//
+// This file is part of DragonEgg.
+//
+// DragonEgg is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later version.
+//
+// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+// A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// DragonEgg; see the file COPYING.  If not, write to the Free Software
+// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+//
+//===----------------------------------------------------------------------===//
+// This file declares routines for generating TBAA metadata from what GCC knows
+// about pointer aliasing.
+//===----------------------------------------------------------------------===//
+
+// Plugin headers
+#include "dragonegg/Aliasing.h"
+
+// LLVM headers
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Metadata.h"
+#include "llvm/ADT/EquivalenceClasses.h"
+
+// System headers
+#include <gmp.h>
+#include <map>
+
+// GCC headers
+extern "C" {
+#include "config.h"
+// Stop GCC declaring 'getopt' as it can clash with the system's declaration.
+#undef HAVE_DECL_GETOPT
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+
+#include "alias.h"
+}
+
+// Trees header.
+#include "dragonegg/Trees.h"
+
+using namespace llvm;
+
+static LLVMContext &Context = getGlobalContext();
+
+/// getTBAARoot - Return the root of the TBAA tree for this compilation unit.
+static MDNode *getTBAARoot() {
+  static MDNode *Root;
+  if (!Root) {
+    // Create the root node.  This must be unique to the compilation unit since
+    // the names of the nodes we hang off it have no intrinsic meaning: nodes
+    // from different compilation units must not be merged even if they have the
+    // same name.  To ensure uniqueness the root node is made self-referential.
+    MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value*>());
+    Root = MDNode::get(Context, Dummy);
+    // At this point we have
+    //   !0 = metadata !{}            <- dummy
+    //   !1 = metadata !{metadata !0} <- root
+    // Replace the dummy operand with the root node itself and delete the dummy.
+    Root->replaceOperandWith(0, Root);
+    MDNode::deleteTemporary(Dummy);
+    // We now have
+    //   !1 = metadata !{metadata !1} <- self-referential root
+  }
+  return Root;
+}
+
+/// describeAliasSet - Return TBAA metadata describing what a load from or store
+/// to the given tree may alias.
+MDNode *describeAliasSet(tree t) {
+  alias_set_type alias_set = get_alias_set(t);
+  // Alias set 0 is the root of the alias graph and can alias anything.  A
+  // negative value represents an unknown alias set, which as far as we know
+  // may also alias anything.
+  if (alias_set <= 0)
+    return 0;
+
+  // The difficulty here is that GCC's alias sets are the nodes of a directed
+  // acyclic graph (DAG) rooted at 0, and in complicated cases it really is a
+  // DAG and not a tree.  On the other hand, LLVM requires TBAA nodes to form
+  // a tree.  In short we need to come up with a tree and a graph map (i.e. a
+  // map that takes nodes to nodes and edges to edges) from GCC's DAG to this
+  // tree.  An additional difficulty is that we don't actually know the edges
+  // in the DAG: GCC's alias analysis interface does not expose them.  All that
+  // we have is alias_set_subset_of(s, t) which returns true iff there is a path
+  // from t to s in the DAG. Finally, we don't know the nodes of the DAG either!
+  // We only discover them progressively as we convert functions.
+  // For the moment we take a very simple approach: the TBAA tree will be only
+  // one level deep: a list of nodes hanging off the root node.  This is not a
+  // good choice in general: it is perfectly possible for a huge alias DAG to
+  // result in just one node hanging off the root.  But it is simple.  We keep
+  // a collection of disjoint sets of DAG nodes seen so far.  The sets represent
+  // the equivalence relation generated by requiring A and B to be in the same
+  // equivalence class if there is a path from A to B or from B to A.
+  typedef EquivalenceClasses<alias_set_type> DisjointSets;
+  static DisjointSets Nodes; // The TBAA nodes hanging off the root.
+  static std::map<alias_set_type, MDNode*> NodeTags; // Node -> metadata map.
+
+  // If alias_set was already seen then return the previously computed metadata.
+  DisjointSets::member_iterator MI = Nodes.findLeader(alias_set);
+  if (MI != Nodes.member_end()) {
+    assert(NodeTags.find(*MI) != NodeTags.end() && "Node has no metadata!");
+    return NodeTags[*MI];
+  }
+
+  // Examine all previously seen nodes and determine which of them, if any, may
+  // alias alias_set.
+  SmallVector<DisjointSets::member_iterator, 8> MayAlias;
+  for (DisjointSets::iterator I = Nodes.begin(); I != Nodes.end(); ++I)
+    for (DisjointSets::member_iterator MI = Nodes.member_begin(I),
+         ME = Nodes.member_end(); MI != ME; ++MI)
+      if (alias_sets_conflict_p(alias_set, *MI)) {
+        // May alias - remember this and move on to the next node.
+        MayAlias.push_back(Nodes.findLeader(I));
+        break;
+      }
+
+  // If none of the existing nodes may be aliased, then create a new node.
+  if (MayAlias.empty()) {
+    // Create metadata describing a new node hanging off root.  The name doesn't
+    // matter much but needs to be unique for the compilation unit.
+    std::string TreeName = ("alias set " + Twine(alias_set) + ": " +
+      getDescriptiveName(TYPE_CANONICAL(main_type(t)))).str();
+    Value *Ops[2] = { MDString::get(Context, TreeName), getTBAARoot() };
+    MDNode *AliasTag = MDNode::get(Context, Ops);
+    NodeTags[alias_set] = AliasTag;
+    // Remember the new node in the equivalence relation.
+    Nodes.insert(alias_set);
+    return AliasTag;
+  }
+
+  // Merge all of the nodes that may alias alias_set into one node.
+  DisjointSets::member_iterator TheChosenOne = MayAlias[0];
+  MDNode *TheChosenTag = NodeTags[*TheChosenOne];
+  for (unsigned i = 1, e = MayAlias.size(); i != e; ++i) {
+    DisjointSets::member_iterator Leader = MayAlias[i];
+    MDNode *AliasTag = NodeTags[*Leader];
+    // Use the chosen node's TBAA metadata instead of this node's.
+    AliasTag->replaceAllUsesWith(TheChosenTag);
+    NodeTags.erase(*Leader);
+    // Merge this node into the chosen node.
+    Leader = Nodes.unionSets(TheChosenOne, Leader);
+    assert(Leader == TheChosenOne && "Union mutated chosen leader!");
+  }
+  // Add alias_set itself to the merged node.
+  Nodes.unionSets(TheChosenOne, Nodes.findLeader(Nodes.insert(alias_set)));
+
+  // Finally, return the metadata for the merged node.
+  return TheChosenTag;
+}

Modified: dragonegg/trunk/src/Convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=153826&r1=153825&r2=153826&view=diff
==============================================================================
--- dragonegg/trunk/src/Convert.cpp (original)
+++ dragonegg/trunk/src/Convert.cpp Sun Apr  1 01:58:04 2012
@@ -23,6 +23,7 @@
 
 // Plugin headers
 #include "dragonegg/ABI.h"
+#include "dragonegg/Aliasing.h"
 #include "dragonegg/Constants.h"
 #include "dragonegg/Debug.h"
 #include "dragonegg/Types.h"
@@ -159,21 +160,27 @@
 }
 
 /// LoadFromLocation - Load a value of the given type from a memory location.
-static LoadInst *LoadFromLocation(MemRef Loc, Type *Ty, LLVMBuilder &Builder) {
+static LoadInst *LoadFromLocation(MemRef Loc, Type *Ty, MDNode *AliasTag,
+                                  LLVMBuilder &Builder) {
   unsigned AddrSpace = cast<PointerType>(Loc.Ptr->getType())->getAddressSpace();
   Value *Ptr = Builder.CreateBitCast(Loc.Ptr, Ty->getPointerTo(AddrSpace));
   LoadInst *LI = Builder.CreateLoad(Ptr, Loc.Volatile);
   LI->setAlignment(Loc.getAlignment());
+  if (AliasTag)
+    LI->setMetadata(LLVMContext::MD_tbaa, AliasTag);
   return LI;
 }
 
 /// StoreToLocation - Store a value to the given memory location.
-static StoreInst *StoreToLocation(Value *V, MemRef Loc, LLVMBuilder &Builder) {
+static StoreInst *StoreToLocation(Value *V, MemRef Loc, MDNode *AliasTag,
+                                  LLVMBuilder &Builder) {
   Type *Ty = V->getType();
   unsigned AddrSpace = cast<PointerType>(Loc.Ptr->getType())->getAddressSpace();
   Value *Ptr = Builder.CreateBitCast(Loc.Ptr, Ty->getPointerTo(AddrSpace));
   StoreInst *SI = Builder.CreateStore(V, Ptr, Loc.Volatile);
   SI->setAlignment(Loc.getAlignment());
+  if (AliasTag)
+    SI->setMetadata(LLVMContext::MD_tbaa, AliasTag);
   return SI;
 }
 
@@ -366,7 +373,7 @@
 /// the memory location pointed to by Loc.  Takes care of adjusting for any
 /// differences between in-memory and in-register types (the returned value
 /// is of in-register type, as returned by getRegType).
-static Value *LoadRegisterFromMemory(MemRef Loc, tree type,
+static Value *LoadRegisterFromMemory(MemRef Loc, tree type, MDNode *AliasTag,
                                      LLVMBuilder &Builder) {
   // NOTE: Needs to be kept in sync with getRegType.
   Type *RegTy = getRegType(type);
@@ -374,7 +381,7 @@
   // If loading the register type directly out of memory gives the right result,
   // then just do that.
   if (isDirectMemoryAccessSafe(RegTy, type))
-    return LoadFromLocation(Loc, RegTy, Builder);
+    return LoadFromLocation(Loc, RegTy, AliasTag, Builder);
 
   // There is a discrepancy between the in-register type and the in-memory type.
   switch (TREE_CODE(type)) {
@@ -392,7 +399,7 @@
     // big endian machines.
     unsigned Size = GET_MODE_BITSIZE(TYPE_MODE(type));
     Type *MemTy = IntegerType::get(Context, Size);
-    LoadInst *LI = LoadFromLocation(Loc, MemTy, Builder);
+    LoadInst *LI = LoadFromLocation(Loc, MemTy, AliasTag, Builder);
     MDNode *Range = describeTypeRange(RegTy, MemTy, !TYPE_UNSIGNED(type));
     LI->setMetadata(LLVMContext::MD_range, Range);
     return Builder.CreateTruncOrBitCast(LI, RegTy);
@@ -402,9 +409,9 @@
     // Load the complex number component by component.
     tree elt_type = main_type(type);
     unsigned Stride = GET_MODE_SIZE(TYPE_MODE(elt_type));
-    Value *RealPart = LoadRegisterFromMemory(Loc, elt_type, Builder);
+    Value *RealPart = LoadRegisterFromMemory(Loc, elt_type, AliasTag, Builder);
     Loc = DisplaceLocationByUnits(Loc, Stride, Builder);
-    Value *ImagPart = LoadRegisterFromMemory(Loc, elt_type, Builder);
+    Value *ImagPart = LoadRegisterFromMemory(Loc, elt_type, AliasTag, Builder);
     Value *Res = UndefValue::get(RegTy);
     Res = Builder.CreateInsertValue(Res, RealPart, 0);
     Res = Builder.CreateInsertValue(Res, ImagPart, 1);
@@ -426,7 +433,7 @@
         // It does!  Load out the memory as a vector of that type then truncate
         // to the register size.
         Type *MemVecTy = VectorType::get(MemTy, NumElts);
-        LoadInst *LI = LoadFromLocation(Loc, MemVecTy, Builder);
+        LoadInst *LI = LoadFromLocation(Loc, MemVecTy, AliasTag, Builder);
         return Builder.CreateTruncOrBitCast(LI, RegTy);
       }
     }
@@ -437,7 +444,7 @@
     IntegerType *IntPtrTy = getTargetData().getIntPtrType(Context);
     for (unsigned i = 0; i != NumElts; ++i) {
       Value *Idx = Builder.getInt32(i);
-      Value *Elt = LoadRegisterFromMemory(Loc, elt_type, Builder);
+      Value *Elt = LoadRegisterFromMemory(Loc, elt_type, AliasTag, Builder);
       // LLVM does not support vectors of pointers, so turn any pointers into
       // integers.
       if (isVectorOfPointers)
@@ -455,14 +462,14 @@
 /// Loc.  Takes care of adjusting for any differences between the value's type
 /// (which is the in-register type given by getRegType) and the in-memory type.
 static void StoreRegisterToMemory(Value *V, MemRef Loc, tree type,
-                                  LLVMBuilder &Builder) {
+                                  MDNode *AliasTag, LLVMBuilder &Builder) {
   // NOTE: Needs to be kept in sync with getRegType.
   assert(V->getType() == getRegType(type) && "Not of register type!");
 
   // If storing the register directly to memory gives the right result, then
   // just do that.
   if (isDirectMemoryAccessSafe(V->getType(), type)) {
-    StoreToLocation(V, Loc, Builder);
+    StoreToLocation(V, Loc, AliasTag, Builder);
     return;
   }
 
@@ -482,7 +489,7 @@
     unsigned Size = GET_MODE_BITSIZE(TYPE_MODE(type));
     Type *MemTy = IntegerType::get(Context, Size);
     V = Builder.CreateIntCast(V, MemTy, /*isSigned*/!TYPE_UNSIGNED(type));
-    StoreToLocation(V, Loc, Builder);
+    StoreToLocation(V, Loc, AliasTag, Builder);
     break;
   }
 
@@ -492,9 +499,9 @@
     unsigned Stride = GET_MODE_SIZE(TYPE_MODE(elt_type));
     Value *RealPart = Builder.CreateExtractValue(V, 0);
     Value *ImagPart = Builder.CreateExtractValue(V, 1);
-    StoreRegisterToMemory(RealPart, Loc, elt_type, Builder);
+    StoreRegisterToMemory(RealPart, Loc, elt_type, AliasTag, Builder);
     Loc = DisplaceLocationByUnits(Loc, Stride, Builder);
-    StoreRegisterToMemory(ImagPart, Loc, elt_type, Builder);
+    StoreRegisterToMemory(ImagPart, Loc, elt_type, AliasTag, Builder);
     break;
   }
 
@@ -515,7 +522,7 @@
         Type *MemVecTy = VectorType::get(MemTy, NumElts);
         V = Builder.CreateIntCast(V, MemVecTy,
                                   /*isSigned*/!TYPE_UNSIGNED(elt_type));
-        StoreToLocation(V, Loc, Builder);
+        StoreToLocation(V, Loc, AliasTag, Builder);
         break;
       }
     }
@@ -524,7 +531,7 @@
     for (unsigned i = 0; i != NumElts; ++i) {
       Value *Idx = Builder.getInt32(i);
       Value *Elt = Builder.CreateExtractElement(V, Idx);
-      StoreRegisterToMemory(Elt, Loc, elt_type, Builder);
+      StoreRegisterToMemory(Elt, Loc, elt_type, AliasTag, Builder);
       if (i + 1 != NumElts)
         Loc = DisplaceLocationByUnits(Loc, Stride, Builder);
     }
@@ -1907,8 +1914,8 @@
                                       tree type) {
   if (!AGGREGATE_TYPE_P(type)) {
     // Copy scalar.
-    StoreRegisterToMemory(LoadRegisterFromMemory(SrcLoc, type, Builder),
-                          DestLoc, type, Builder);
+    StoreRegisterToMemory(LoadRegisterFromMemory(SrcLoc, type, 0, Builder),
+                          DestLoc, type, 0, Builder);
     return;
   }
 
@@ -2006,7 +2013,7 @@
   if (!AGGREGATE_TYPE_P(type)) {
     // Zero scalar.
     StoreRegisterToMemory(Constant::getNullValue(getRegType(type)), DestLoc,
-                          type, Builder);
+                          type, 0, Builder);
     return;
   }
 
@@ -2677,7 +2684,8 @@
 
   if (!LV.isBitfield()) {
     // Scalar value: emit a load.
-    return LoadRegisterFromMemory(LV, TREE_TYPE(exp), Builder);
+    return LoadRegisterFromMemory(LV, TREE_TYPE(exp), describeAliasSet(exp),
+                                  Builder);
   } else {
     // This is a bitfield reference.
     Type *Ty = getRegType(TREE_TYPE(exp));
@@ -2834,7 +2842,7 @@
     } else {
       // Scalar value.  Evaluate to a register, then do the store.
       Value *V = EmitRegister(tree_value);
-      StoreRegisterToMemory(V, *DestLoc, TREE_TYPE(tree_purpose), Builder);
+      StoreRegisterToMemory(V, *DestLoc, TREE_TYPE(tree_purpose), 0, Builder);
     }
     break;
   }
@@ -3210,7 +3218,7 @@
         // A first class value (eg: a complex number).  Push the address of a
         // temporary copy.
         MemRef Copy = CreateTempLoc(ArgTy);
-        StoreRegisterToMemory(EmitRegister(arg), Copy, type, Builder);
+        StoreRegisterToMemory(EmitRegister(arg), Copy, type, 0, Builder);
         Client.pushAddress(Copy.Ptr);
       }
     }
@@ -5133,7 +5141,7 @@
     } else {
       // Push the address of a temporary copy.
       MemRef Copy = CreateTempLoc(CplxTy);
-      StoreRegisterToMemory(CplxArg, Copy, cplx_type, Builder);
+      StoreRegisterToMemory(CplxArg, Copy, cplx_type, 0, Builder);
       Client.pushAddress(Copy.Ptr);
       PassedInMemory = true;
     }
@@ -6571,7 +6579,7 @@
 
   // Use it to load the parameter value.
   MemRef ParamLoc(DECL_LOCAL_IF_SET(var), Alignment, false);
-  Value *Def = LoadRegisterFromMemory(ParamLoc, TREE_TYPE(reg), SSABuilder);
+  Value *Def = LoadRegisterFromMemory(ParamLoc, TREE_TYPE(reg), 0, SSABuilder);
 
   if (flag_verbose_asm)
     NameValue(Def, reg);
@@ -8100,7 +8108,7 @@
   for (unsigned i = 0, e = (unsigned)SSADefinitions.size(); i != e; ++i) {
     tree Name = SSADefinitions[i].first;
     MemRef Loc = SSADefinitions[i].second;
-    Value *Val = LoadRegisterFromMemory(Loc, TREE_TYPE(Name), Builder);
+    Value *Val = LoadRegisterFromMemory(Loc, TREE_TYPE(Name), 0, Builder);
     DefineSSAName(Name, Val);
   }
 
@@ -8329,7 +8337,7 @@
     } else {
       Value *Val = Builder.CreateBitCast(EmitRegister(retval),
                                          getRegType(TREE_TYPE(result)));
-      StoreRegisterToMemory(Val, DestLoc, TREE_TYPE(result), Builder);
+      StoreRegisterToMemory(Val, DestLoc, TREE_TYPE(result), 0, Builder);
     }
   }
 
@@ -8708,7 +8716,8 @@
   // TODO: Arrange for Volatile to already be set in the LValue.
   if (!LV.isBitfield()) {
     // Non-bitfield, scalar value.  Just emit a store.
-    StoreRegisterToMemory(RHS, LV, TREE_TYPE(lhs), Builder);
+    StoreRegisterToMemory(RHS, LV, TREE_TYPE(lhs), describeAliasSet(lhs),
+                          Builder);
     return;
   }
 





More information about the llvm-commits mailing list