Skip to content

Commit

Permalink
[Attributor] Track AA dependency using dependency graph
Browse files Browse the repository at this point in the history
This patch added dependency graph to the attributor so that we can dump the dependencies between AAs more easily. We can also apply general graph algorithms to the graph, making it easier for us to create deep wrappers.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D78861
  • Loading branch information
hellobbn committed Jul 28, 2020
1 parent b81fd5a commit 5ee07dc
Show file tree
Hide file tree
Showing 4 changed files with 428 additions and 37 deletions.
103 changes: 89 additions & 14 deletions llvm/include/llvm/Transforms/IPO/Attributor.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@
#ifndef LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H
#define LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H

#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumeBundleQueries.h"
Expand All @@ -116,10 +118,15 @@
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Transforms/Utils/CallGraphUpdater.h"

namespace llvm {

struct AADepGraphNode;
struct AADepGraph;
struct Attributor;
struct AbstractAttribute;
struct InformationCache;
Expand All @@ -144,6 +151,70 @@ enum class DepClassTy {
};
///}

/// The data structure for the nodes of a dependency graph
struct AADepGraphNode {
public:
virtual ~AADepGraphNode(){};
using DepTy = PointerIntPair<AADepGraphNode *, 1>;

protected:
/// Set of dependency graph nodes which this one depends on.
/// The bit encodes if it is optional.
TinyPtrVector<DepTy> Deps;

static AADepGraphNode *DepGetVal(DepTy &DT) { return DT.getPointer(); }
static AbstractAttribute *DepGetValAA(DepTy &DT) {
return cast<AbstractAttribute>(DT.getPointer());
}

operator AbstractAttribute *() { return cast<AbstractAttribute>(this); }

public:
using iterator =
mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetVal)>;
using aaiterator =
mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetValAA)>;

aaiterator begin() { return aaiterator(Deps.begin(), &DepGetValAA); }
aaiterator end() { return aaiterator(Deps.end(), &DepGetValAA); }
iterator child_begin() { return iterator(Deps.begin(), &DepGetVal); }
iterator child_end() { return iterator(Deps.end(), &DepGetVal); }

virtual void print(raw_ostream &OS) const { OS << "AADepNode Impl\n"; }
TinyPtrVector<DepTy> &getDeps() { return Deps; }

friend struct Attributor;
friend struct AADepGraph;
};

struct AADepGraph {
AADepGraph() {}
~AADepGraph() {}

using DepTy = AADepGraphNode::DepTy;
static AADepGraphNode *DepGetVal(DepTy &DT) { return DT.getPointer(); }
using iterator =
mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetVal)>;

/// There is no root node for the dependency graph. But the SCCIterator
/// requires a single entry point, so we maintain a fake("synthetic") root
/// node that depends on every node.
AADepGraphNode SyntheticRoot;

AADepGraphNode *GetEntryNode() { return &SyntheticRoot; }

iterator begin() { return SyntheticRoot.child_begin(); }
iterator end() { return SyntheticRoot.child_end(); }

void viewGraph();

/// Dump graph to file
void dumpGraph();

/// Print dependency graph
void print();
};

/// Helper to describe and deal with positions in the LLVM-IR.
///
/// A position in the IR is described by an anchor value and an "offset" that
Expand Down Expand Up @@ -1020,7 +1091,9 @@ struct Attributor {
assert(!AAPtr && "Attribute already in map!");
AAPtr = &AA;

AllAbstractAttributes.push_back(&AA);
DG.SyntheticRoot.Deps.push_back(
AADepGraphNode::DepTy(&AA, unsigned(DepClassTy::REQUIRED)));

return AA;
}

Expand Down Expand Up @@ -1382,12 +1455,6 @@ struct Attributor {
/// See getOrCreateAAFor.
bool shouldSeedAttribute(AbstractAttribute &AA);

/// The set of all abstract attributes.
///{
using AAVector = SmallVector<AbstractAttribute *, 64>;
AAVector AllAbstractAttributes;
///}

/// A nested map to lookup abstract attributes based on the argument position
/// on the outer level, and the addresses of the static member (AAType::ID) on
/// the inner level.
Expand All @@ -1409,6 +1476,9 @@ struct Attributor {
/// Helper to update an underlying call graph.
CallGraphUpdater &CGUpdater;

/// Abstract Attribute dependency graph
AADepGraph DG;

/// Set of functions for which we modified the content such that it might
/// impact the call graph.
SmallPtrSet<Function *, 8> CGModifiedFunctions;
Expand Down Expand Up @@ -1458,6 +1528,8 @@ struct Attributor {
SmallPtrSet<BasicBlock *, 8> ToBeDeletedBlocks;
SmallDenseSet<WeakVH, 8> ToBeDeletedInsts;
///}

friend AADepGraph;
};

/// An interface to query the internal state of an abstract attribute.
Expand Down Expand Up @@ -2030,14 +2102,22 @@ struct IRAttribute : public BaseType {
/// both directions will be added in the future.
/// NOTE: The mechanics of adding a new "concrete" abstract attribute are
/// described in the file comment.
struct AbstractAttribute : public IRPosition {
struct AbstractAttribute : public IRPosition, public AADepGraphNode {
using StateType = AbstractState;

AbstractAttribute(const IRPosition &IRP) : IRPosition(IRP) {}

/// Virtual destructor.
virtual ~AbstractAttribute() {}

/// This function is used to identify if an \p DGN is of type
/// AbstractAttribute so that the dyn_cast and cast can use such information
/// to cast an AADepGraphNode to an AbstractAttribute.
///
/// We eagerly return true here because all AADepGraphNodes except for the
/// Synthethis Node are of type AbstractAttribute
static bool classof(const AADepGraphNode *DGN) { return true; }

/// Initialize the state with the information in the Attributor \p A.
///
/// This function is called by the Attributor once all abstract attributes
Expand All @@ -2059,6 +2139,7 @@ struct AbstractAttribute : public IRPosition {
/// Helper functions, for debug purposes only.
///{
virtual void print(raw_ostream &OS) const;
virtual void printWithDeps(raw_ostream &OS) const;
void dump() const { print(dbgs()); }

/// This function should return the "summarized" assumed state as string.
Expand Down Expand Up @@ -2106,12 +2187,6 @@ struct AbstractAttribute : public IRPosition {
///
/// \Return CHANGED if the internal state changed, otherwise UNCHANGED.
virtual ChangeStatus updateImpl(Attributor &A) = 0;

private:
/// Set of abstract attributes which were queried by this one. The bit encodes
/// if there is an optional of required dependence.
using DepTy = PointerIntPair<AbstractAttribute *, 1>;
TinyPtrVector<DepTy> Deps;
};

/// Forward declarations of output streams for debug purposes.
Expand Down
Loading

0 comments on commit 5ee07dc

Please sign in to comment.