[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