mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
c2791239be
Summary: The convenience wrapper in STLExtras is available since rL342102. Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits Differential Revision: https://reviews.llvm.org/D52573 llvm-svn: 343163
119 lines
4.0 KiB
C++
119 lines
4.0 KiB
C++
//===- CFGUpdate.h - Encode a CFG Edge Update. ------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines a CFG Edge Update: Insert or Delete, and two Nodes as the
|
|
// Edge ends.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_SUPPORT_CFGUPDATE_H
|
|
#define LLVM_SUPPORT_CFGUPDATE_H
|
|
|
|
#include "llvm/ADT/APInt.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/PointerIntPair.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
namespace llvm {
|
|
namespace cfg {
|
|
enum class UpdateKind : unsigned char { Insert, Delete };
|
|
|
|
template <typename NodePtr> class Update {
|
|
using NodeKindPair = PointerIntPair<NodePtr, 1, UpdateKind>;
|
|
NodePtr From;
|
|
NodeKindPair ToAndKind;
|
|
|
|
public:
|
|
Update(UpdateKind Kind, NodePtr From, NodePtr To)
|
|
: From(From), ToAndKind(To, Kind) {}
|
|
|
|
UpdateKind getKind() const { return ToAndKind.getInt(); }
|
|
NodePtr getFrom() const { return From; }
|
|
NodePtr getTo() const { return ToAndKind.getPointer(); }
|
|
bool operator==(const Update &RHS) const {
|
|
return From == RHS.From && ToAndKind == RHS.ToAndKind;
|
|
}
|
|
|
|
void print(raw_ostream &OS) const {
|
|
OS << (getKind() == UpdateKind::Insert ? "Insert " : "Delete ");
|
|
getFrom()->printAsOperand(OS, false);
|
|
OS << " -> ";
|
|
getTo()->printAsOperand(OS, false);
|
|
}
|
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
|
|
#endif
|
|
};
|
|
|
|
// LegalizeUpdates function simplifies updates assuming a graph structure.
|
|
// This function serves double purpose:
|
|
// a) It removes redundant updates, which makes it easier to reverse-apply
|
|
// them when traversing CFG.
|
|
// b) It optimizes away updates that cancel each other out, as the end result
|
|
// is the same.
|
|
template <typename NodePtr>
|
|
void LegalizeUpdates(ArrayRef<Update<NodePtr>> AllUpdates,
|
|
SmallVectorImpl<Update<NodePtr>> &Result,
|
|
bool InverseGraph) {
|
|
// Count the total number of inserions of each edge.
|
|
// Each insertion adds 1 and deletion subtracts 1. The end number should be
|
|
// one of {-1 (deletion), 0 (NOP), +1 (insertion)}. Otherwise, the sequence
|
|
// of updates contains multiple updates of the same kind and we assert for
|
|
// that case.
|
|
SmallDenseMap<std::pair<NodePtr, NodePtr>, int, 4> Operations;
|
|
Operations.reserve(AllUpdates.size());
|
|
|
|
for (const auto &U : AllUpdates) {
|
|
NodePtr From = U.getFrom();
|
|
NodePtr To = U.getTo();
|
|
if (InverseGraph)
|
|
std::swap(From, To); // Reverse edge for postdominators.
|
|
|
|
Operations[{From, To}] += (U.getKind() == UpdateKind::Insert ? 1 : -1);
|
|
}
|
|
|
|
Result.clear();
|
|
Result.reserve(Operations.size());
|
|
for (auto &Op : Operations) {
|
|
const int NumInsertions = Op.second;
|
|
assert(std::abs(NumInsertions) <= 1 && "Unbalanced operations!");
|
|
if (NumInsertions == 0)
|
|
continue;
|
|
const UpdateKind UK =
|
|
NumInsertions > 0 ? UpdateKind::Insert : UpdateKind::Delete;
|
|
Result.push_back({UK, Op.first.first, Op.first.second});
|
|
}
|
|
|
|
// Make the order consistent by not relying on pointer values within the
|
|
// set. Reuse the old Operations map.
|
|
// In the future, we should sort by something else to minimize the amount
|
|
// of work needed to perform the series of updates.
|
|
for (size_t i = 0, e = AllUpdates.size(); i != e; ++i) {
|
|
const auto &U = AllUpdates[i];
|
|
if (!InverseGraph)
|
|
Operations[{U.getFrom(), U.getTo()}] = int(i);
|
|
else
|
|
Operations[{U.getTo(), U.getFrom()}] = int(i);
|
|
}
|
|
|
|
llvm::sort(Result,
|
|
[&Operations](const Update<NodePtr> &A, const Update<NodePtr> &B) {
|
|
return Operations[{A.getFrom(), A.getTo()}] >
|
|
Operations[{B.getFrom(), B.getTo()}];
|
|
});
|
|
}
|
|
|
|
} // end namespace cfg
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_SUPPORT_CFGUPDATE_H
|