summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-08-03 15:06:44 +0000
committerpatrick <patrick@openbsd.org>2020-08-03 15:06:44 +0000
commitb64793999546ed8adebaeebd9d8345d18db8927d (patch)
tree4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
parentAdd support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff)
downloadwireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz
wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp')
-rw-r--r--gnu/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp333
1 files changed, 0 insertions, 333 deletions
diff --git a/gnu/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp b/gnu/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
deleted file mode 100644
index 11f7afbd229..00000000000
--- a/gnu/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-//===- ThreadSafetyTIL.cpp ------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT in the llvm repository for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
-#include "clang/Basic/LLVM.h"
-#include "llvm/Support/Casting.h"
-#include <cassert>
-#include <cstddef>
-
-using namespace clang;
-using namespace threadSafety;
-using namespace til;
-
-StringRef til::getUnaryOpcodeString(TIL_UnaryOpcode Op) {
- switch (Op) {
- case UOP_Minus: return "-";
- case UOP_BitNot: return "~";
- case UOP_LogicNot: return "!";
- }
- return {};
-}
-
-StringRef til::getBinaryOpcodeString(TIL_BinaryOpcode Op) {
- switch (Op) {
- case BOP_Mul: return "*";
- case BOP_Div: return "/";
- case BOP_Rem: return "%";
- case BOP_Add: return "+";
- case BOP_Sub: return "-";
- case BOP_Shl: return "<<";
- case BOP_Shr: return ">>";
- case BOP_BitAnd: return "&";
- case BOP_BitXor: return "^";
- case BOP_BitOr: return "|";
- case BOP_Eq: return "==";
- case BOP_Neq: return "!=";
- case BOP_Lt: return "<";
- case BOP_Leq: return "<=";
- case BOP_Cmp: return "<=>";
- case BOP_LogicAnd: return "&&";
- case BOP_LogicOr: return "||";
- }
- return {};
-}
-
-SExpr* Future::force() {
- Status = FS_evaluating;
- Result = compute();
- Status = FS_done;
- return Result;
-}
-
-unsigned BasicBlock::addPredecessor(BasicBlock *Pred) {
- unsigned Idx = Predecessors.size();
- Predecessors.reserveCheck(1, Arena);
- Predecessors.push_back(Pred);
- for (auto *E : Args) {
- if (auto *Ph = dyn_cast<Phi>(E)) {
- Ph->values().reserveCheck(1, Arena);
- Ph->values().push_back(nullptr);
- }
- }
- return Idx;
-}
-
-void BasicBlock::reservePredecessors(unsigned NumPreds) {
- Predecessors.reserve(NumPreds, Arena);
- for (auto *E : Args) {
- if (auto *Ph = dyn_cast<Phi>(E)) {
- Ph->values().reserve(NumPreds, Arena);
- }
- }
-}
-
-// If E is a variable, then trace back through any aliases or redundant
-// Phi nodes to find the canonical definition.
-const SExpr *til::getCanonicalVal(const SExpr *E) {
- while (true) {
- if (const auto *V = dyn_cast<Variable>(E)) {
- if (V->kind() == Variable::VK_Let) {
- E = V->definition();
- continue;
- }
- }
- if (const auto *Ph = dyn_cast<Phi>(E)) {
- if (Ph->status() == Phi::PH_SingleVal) {
- E = Ph->values()[0];
- continue;
- }
- }
- break;
- }
- return E;
-}
-
-// If E is a variable, then trace back through any aliases or redundant
-// Phi nodes to find the canonical definition.
-// The non-const version will simplify incomplete Phi nodes.
-SExpr *til::simplifyToCanonicalVal(SExpr *E) {
- while (true) {
- if (auto *V = dyn_cast<Variable>(E)) {
- if (V->kind() != Variable::VK_Let)
- return V;
- // Eliminate redundant variables, e.g. x = y, or x = 5,
- // but keep anything more complicated.
- if (til::ThreadSafetyTIL::isTrivial(V->definition())) {
- E = V->definition();
- continue;
- }
- return V;
- }
- if (auto *Ph = dyn_cast<Phi>(E)) {
- if (Ph->status() == Phi::PH_Incomplete)
- simplifyIncompleteArg(Ph);
- // Eliminate redundant Phi nodes.
- if (Ph->status() == Phi::PH_SingleVal) {
- E = Ph->values()[0];
- continue;
- }
- }
- return E;
- }
-}
-
-// Trace the arguments of an incomplete Phi node to see if they have the same
-// canonical definition. If so, mark the Phi node as redundant.
-// getCanonicalVal() will recursively call simplifyIncompletePhi().
-void til::simplifyIncompleteArg(til::Phi *Ph) {
- assert(Ph && Ph->status() == Phi::PH_Incomplete);
-
- // eliminate infinite recursion -- assume that this node is not redundant.
- Ph->setStatus(Phi::PH_MultiVal);
-
- SExpr *E0 = simplifyToCanonicalVal(Ph->values()[0]);
- for (unsigned i = 1, n = Ph->values().size(); i < n; ++i) {
- SExpr *Ei = simplifyToCanonicalVal(Ph->values()[i]);
- if (Ei == Ph)
- continue; // Recursive reference to itself. Don't count.
- if (Ei != E0) {
- return; // Status is already set to MultiVal.
- }
- }
- Ph->setStatus(Phi::PH_SingleVal);
-}
-
-// Renumbers the arguments and instructions to have unique, sequential IDs.
-unsigned BasicBlock::renumberInstrs(unsigned ID) {
- for (auto *Arg : Args)
- Arg->setID(this, ID++);
- for (auto *Instr : Instrs)
- Instr->setID(this, ID++);
- TermInstr->setID(this, ID++);
- return ID;
-}
-
-// Sorts the CFGs blocks using a reverse post-order depth-first traversal.
-// Each block will be written into the Blocks array in order, and its BlockID
-// will be set to the index in the array. Sorting should start from the entry
-// block, and ID should be the total number of blocks.
-unsigned BasicBlock::topologicalSort(SimpleArray<BasicBlock *> &Blocks,
- unsigned ID) {
- if (Visited) return ID;
- Visited = true;
- for (auto *Block : successors())
- ID = Block->topologicalSort(Blocks, ID);
- // set ID and update block array in place.
- // We may lose pointers to unreachable blocks.
- assert(ID > 0);
- BlockID = --ID;
- Blocks[BlockID] = this;
- return ID;
-}
-
-// Performs a reverse topological traversal, starting from the exit block and
-// following back-edges. The dominator is serialized before any predecessors,
-// which guarantees that all blocks are serialized after their dominator and
-// before their post-dominator (because it's a reverse topological traversal).
-// ID should be initially set to 0.
-//
-// This sort assumes that (1) dominators have been computed, (2) there are no
-// critical edges, and (3) the entry block is reachable from the exit block
-// and no blocks are accessible via traversal of back-edges from the exit that
-// weren't accessible via forward edges from the entry.
-unsigned BasicBlock::topologicalFinalSort(SimpleArray<BasicBlock *> &Blocks,
- unsigned ID) {
- // Visited is assumed to have been set by the topologicalSort. This pass
- // assumes !Visited means that we've visited this node before.
- if (!Visited) return ID;
- Visited = false;
- if (DominatorNode.Parent)
- ID = DominatorNode.Parent->topologicalFinalSort(Blocks, ID);
- for (auto *Pred : Predecessors)
- ID = Pred->topologicalFinalSort(Blocks, ID);
- assert(static_cast<size_t>(ID) < Blocks.size());
- BlockID = ID++;
- Blocks[BlockID] = this;
- return ID;
-}
-
-// Computes the immediate dominator of the current block. Assumes that all of
-// its predecessors have already computed their dominators. This is achieved
-// by visiting the nodes in topological order.
-void BasicBlock::computeDominator() {
- BasicBlock *Candidate = nullptr;
- // Walk backwards from each predecessor to find the common dominator node.
- for (auto *Pred : Predecessors) {
- // Skip back-edges
- if (Pred->BlockID >= BlockID) continue;
- // If we don't yet have a candidate for dominator yet, take this one.
- if (Candidate == nullptr) {
- Candidate = Pred;
- continue;
- }
- // Walk the alternate and current candidate back to find a common ancestor.
- auto *Alternate = Pred;
- while (Alternate != Candidate) {
- if (Candidate->BlockID > Alternate->BlockID)
- Candidate = Candidate->DominatorNode.Parent;
- else
- Alternate = Alternate->DominatorNode.Parent;
- }
- }
- DominatorNode.Parent = Candidate;
- DominatorNode.SizeOfSubTree = 1;
-}
-
-// Computes the immediate post-dominator of the current block. Assumes that all
-// of its successors have already computed their post-dominators. This is
-// achieved visiting the nodes in reverse topological order.
-void BasicBlock::computePostDominator() {
- BasicBlock *Candidate = nullptr;
- // Walk back from each predecessor to find the common post-dominator node.
- for (auto *Succ : successors()) {
- // Skip back-edges
- if (Succ->BlockID <= BlockID) continue;
- // If we don't yet have a candidate for post-dominator yet, take this one.
- if (Candidate == nullptr) {
- Candidate = Succ;
- continue;
- }
- // Walk the alternate and current candidate back to find a common ancestor.
- auto *Alternate = Succ;
- while (Alternate != Candidate) {
- if (Candidate->BlockID < Alternate->BlockID)
- Candidate = Candidate->PostDominatorNode.Parent;
- else
- Alternate = Alternate->PostDominatorNode.Parent;
- }
- }
- PostDominatorNode.Parent = Candidate;
- PostDominatorNode.SizeOfSubTree = 1;
-}
-
-// Renumber instructions in all blocks
-void SCFG::renumberInstrs() {
- unsigned InstrID = 0;
- for (auto *Block : Blocks)
- InstrID = Block->renumberInstrs(InstrID);
-}
-
-static inline void computeNodeSize(BasicBlock *B,
- BasicBlock::TopologyNode BasicBlock::*TN) {
- BasicBlock::TopologyNode *N = &(B->*TN);
- if (N->Parent) {
- BasicBlock::TopologyNode *P = &(N->Parent->*TN);
- // Initially set ID relative to the (as yet uncomputed) parent ID
- N->NodeID = P->SizeOfSubTree;
- P->SizeOfSubTree += N->SizeOfSubTree;
- }
-}
-
-static inline void computeNodeID(BasicBlock *B,
- BasicBlock::TopologyNode BasicBlock::*TN) {
- BasicBlock::TopologyNode *N = &(B->*TN);
- if (N->Parent) {
- BasicBlock::TopologyNode *P = &(N->Parent->*TN);
- N->NodeID += P->NodeID; // Fix NodeIDs relative to starting node.
- }
-}
-
-// Normalizes a CFG. Normalization has a few major components:
-// 1) Removing unreachable blocks.
-// 2) Computing dominators and post-dominators
-// 3) Topologically sorting the blocks into the "Blocks" array.
-void SCFG::computeNormalForm() {
- // Topologically sort the blocks starting from the entry block.
- unsigned NumUnreachableBlocks = Entry->topologicalSort(Blocks, Blocks.size());
- if (NumUnreachableBlocks > 0) {
- // If there were unreachable blocks shift everything down, and delete them.
- for (unsigned I = NumUnreachableBlocks, E = Blocks.size(); I < E; ++I) {
- unsigned NI = I - NumUnreachableBlocks;
- Blocks[NI] = Blocks[I];
- Blocks[NI]->BlockID = NI;
- // FIXME: clean up predecessor pointers to unreachable blocks?
- }
- Blocks.drop(NumUnreachableBlocks);
- }
-
- // Compute dominators.
- for (auto *Block : Blocks)
- Block->computeDominator();
-
- // Once dominators have been computed, the final sort may be performed.
- unsigned NumBlocks = Exit->topologicalFinalSort(Blocks, 0);
- assert(static_cast<size_t>(NumBlocks) == Blocks.size());
- (void) NumBlocks;
-
- // Renumber the instructions now that we have a final sort.
- renumberInstrs();
-
- // Compute post-dominators and compute the sizes of each node in the
- // dominator tree.
- for (auto *Block : Blocks.reverse()) {
- Block->computePostDominator();
- computeNodeSize(Block, &BasicBlock::DominatorNode);
- }
- // Compute the sizes of each node in the post-dominator tree and assign IDs in
- // the dominator tree.
- for (auto *Block : Blocks) {
- computeNodeID(Block, &BasicBlock::DominatorNode);
- computeNodeSize(Block, &BasicBlock::PostDominatorNode);
- }
- // Assign IDs in the post-dominator tree.
- for (auto *Block : Blocks.reverse()) {
- computeNodeID(Block, &BasicBlock::PostDominatorNode);
- }
-}