Esempio n. 1
0
static void addInstructionToGraph(CFLAliasAnalysis &Analysis, Instruction &Inst,
                                  SmallVectorImpl<Value *> &ReturnedValues,
                                  NodeMapT &Map, GraphT &Graph) {
  const auto findOrInsertNode = [&Map, &Graph](Value *Val) {
    auto Pair = Map.insert(std::make_pair(Val, GraphT::Node()));
    auto &Iter = Pair.first;
    if (Pair.second) {
      auto NewNode = Graph.addNode();
      Iter->second = NewNode;
    }
    return Iter->second;
  };

  // We don't want the edges of most "return" instructions, but we *do* want
  // to know what can be returned.
  if (isa<ReturnInst>(&Inst))
    ReturnedValues.push_back(&Inst);

  if (!hasUsefulEdges(&Inst))
    return;

  SmallVector<Edge, 8> Edges;
  argsToEdges(Analysis, &Inst, Edges);

  // In the case of an unused alloca (or similar), edges may be empty. Note
  // that it exists so we can potentially answer NoAlias.
  if (Edges.empty()) {
    auto MaybeVal = getTargetValue(&Inst);
    assert(MaybeVal.hasValue());
    auto *Target = *MaybeVal;
    findOrInsertNode(Target);
    return;
  }

  const auto addEdgeToGraph = [&Graph, &findOrInsertNode](const Edge &E) {
    auto To = findOrInsertNode(E.To);
    auto From = findOrInsertNode(E.From);
    auto FlippedWeight = flipWeight(E.Weight);
    auto Attrs = E.AdditionalAttrs;
    Graph.addEdge(From, To, std::make_pair(E.Weight, Attrs),
                  std::make_pair(FlippedWeight, Attrs));
  };

  SmallVector<ConstantExpr *, 4> ConstantExprs;
  for (const Edge &E : Edges) {
    addEdgeToGraph(E);
    if (auto *Constexpr = dyn_cast<ConstantExpr>(E.To))
      ConstantExprs.push_back(Constexpr);
    if (auto *Constexpr = dyn_cast<ConstantExpr>(E.From))
      ConstantExprs.push_back(Constexpr);
  }

  for (ConstantExpr *CE : ConstantExprs) {
    Edges.clear();
    constexprToEdges(Analysis, *CE, Edges);
    std::for_each(Edges.begin(), Edges.end(), addEdgeToGraph);
  }
}
// Aside: We may remove graph construction entirely, because it doesn't really
// buy us much that we don't already have. I'd like to add interprocedural
// analysis prior to this however, in case that somehow requires the graph
// produced by this for efficient execution
static void buildGraphFrom(CFLAliasAnalysis &Analysis, Function *Fn,
                           SmallVectorImpl<Value *> &ReturnedValues,
                           NodeMapT &Map, GraphT &Graph) {
  const auto findOrInsertNode = [&Map, &Graph](Value *Val) {
    auto Pair = Map.insert(std::make_pair(Val, GraphT::Node()));
    auto &Iter = Pair.first;
    if (Pair.second) {
      auto NewNode = Graph.addNode();
      Iter->second = NewNode;
    }
    return Iter->second;
  };

  SmallVector<Edge, 8> Edges;
  for (auto &Bb : Fn->getBasicBlockList()) {
    for (auto &Inst : Bb.getInstList()) {
      // We don't want the edges of most "return" instructions, but we *do* want
      // to know what can be returned.
      if (auto *Ret = dyn_cast<ReturnInst>(&Inst))
        ReturnedValues.push_back(Ret);

      if (!hasUsefulEdges(&Inst))
        continue;

      Edges.clear();
      argsToEdges(Analysis, &Inst, Edges);

      // In the case of an unused alloca (or similar), edges may be empty. Note
      // that it exists so we can potentially answer NoAlias.
      if (Edges.empty()) {
        auto MaybeVal = getTargetValue(&Inst);
        assert(MaybeVal.hasValue());
        auto *Target = *MaybeVal;
        findOrInsertNode(Target);
        continue;
      }

      for (const Edge &E : Edges) {
        auto To = findOrInsertNode(E.To);
        auto From = findOrInsertNode(E.From);
        auto FlippedWeight = flipWeight(E.Weight);
        auto Attrs = E.AdditionalAttrs;
        Graph.addEdge(From, To, std::make_pair(E.Weight, Attrs),
                                std::make_pair(FlippedWeight, Attrs));
      }
    }
  }
}
static FunctionInfo buildSetsFrom(CFLAliasAnalysis &Analysis, Function *Fn) {
  NodeMapT Map;
  GraphT Graph;
  SmallVector<Value *, 4> ReturnedValues;

  buildGraphFrom(Analysis, Fn, ReturnedValues, Map, Graph);

  DenseMap<GraphT::Node, Value *> NodeValueMap;
  NodeValueMap.resize(Map.size());
  for (const auto &Pair : Map)
    NodeValueMap.insert(std::make_pair(Pair.second, Pair.first));

  const auto findValueOrDie = [&NodeValueMap](GraphT::Node Node) {
    auto ValIter = NodeValueMap.find(Node);
    assert(ValIter != NodeValueMap.end());
    return ValIter->second;
  };

  StratifiedSetsBuilder<Value *> Builder;

  SmallVector<GraphT::Node, 16> Worklist;
  for (auto &Pair : Map) {
    Worklist.clear();

    auto *Value = Pair.first;
    Builder.add(Value);
    auto InitialNode = Pair.second;
    Worklist.push_back(InitialNode);
    while (!Worklist.empty()) {
      auto Node = Worklist.pop_back_val();
      auto *CurValue = findValueOrDie(Node);
      if (isa<Constant>(CurValue) && !isa<GlobalValue>(CurValue))
        continue;

      for (const auto &EdgeTuple : Graph.edgesFor(Node)) {
        auto Weight = std::get<0>(EdgeTuple);
        auto Label = Weight.first;
        auto &OtherNode = std::get<1>(EdgeTuple);
        auto *OtherValue = findValueOrDie(OtherNode);

        if (isa<Constant>(OtherValue) && !isa<GlobalValue>(OtherValue))
          continue;

        bool Added;
        switch (directionOfEdgeType(Label)) {
        case Level::Above:
          Added = Builder.addAbove(CurValue, OtherValue);
          break;
        case Level::Below:
          Added = Builder.addBelow(CurValue, OtherValue);
          break;
        case Level::Same:
          Added = Builder.addWith(CurValue, OtherValue);
          break;
        }

        if (Added) {
          auto Aliasing = Weight.second;
          if (auto MaybeCurIndex = valueToAttrIndex(CurValue))
            Aliasing.set(*MaybeCurIndex);
          if (auto MaybeOtherIndex = valueToAttrIndex(OtherValue))
            Aliasing.set(*MaybeOtherIndex);
          Builder.noteAttributes(CurValue, Aliasing);
          Builder.noteAttributes(OtherValue, Aliasing);
          Worklist.push_back(OtherNode);
        }
      }
    }
  }

  // There are times when we end up with parameters not in our graph (i.e. if
  // it's only used as the condition of a branch). Other bits of code depend on
  // things that were present during construction being present in the graph.
  // So, we add all present arguments here.
  for (auto &Arg : Fn->args()) {
    Builder.add(&Arg);
  }

  return FunctionInfo(Builder.build(), std::move(ReturnedValues));
}