llvm-project/llvm/lib/IR/LLVMContextImpl.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

243 lines
7.9 KiB
C++
Raw Normal View History

//===- LLVMContextImpl.cpp - Implement LLVMContextImpl --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the opaque LLVMContextImpl.
//
//===----------------------------------------------------------------------===//
#include "LLVMContextImpl.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include <cassert>
#include <utility>
using namespace llvm;
static cl::opt<bool>
OpaquePointersCL("opaque-pointers", cl::desc("Use opaque pointers"),
cl::init(false));
LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
: DiagHandler(std::make_unique<DiagnosticHandler>()),
VoidTy(C, Type::VoidTyID), LabelTy(C, Type::LabelTyID),
HalfTy(C, Type::HalfTyID), BFloatTy(C, Type::BFloatTyID),
FloatTy(C, Type::FloatTyID), DoubleTy(C, Type::DoubleTyID),
MetadataTy(C, Type::MetadataTyID), TokenTy(C, Type::TokenTyID),
X86_FP80Ty(C, Type::X86_FP80TyID), FP128Ty(C, Type::FP128TyID),
PPC_FP128Ty(C, Type::PPC_FP128TyID), X86_MMXTy(C, Type::X86_MMXTyID),
X86_AMXTy(C, Type::X86_AMXTyID), Int1Ty(C, 1), Int8Ty(C, 8),
Int16Ty(C, 16), Int32Ty(C, 32), Int64Ty(C, 64), Int128Ty(C, 128) {}
LLVMContextImpl::~LLVMContextImpl() {
// NOTE: We need to delete the contents of OwnedModules, but Module's dtor
// will call LLVMContextImpl::removeModule, thus invalidating iterators into
// the container. Avoid iterators during this operation:
while (!OwnedModules.empty())
delete *OwnedModules.begin();
#ifndef NDEBUG
// Check for metadata references from leaked Values.
for (auto &Pair : ValueMetadata)
Pair.first->dump();
assert(ValueMetadata.empty() && "Values with metadata have been leaked");
#endif
// Drop references for MDNodes. Do this before Values get deleted to avoid
// unnecessary RAUW when nodes are still unresolved.
for (auto *I : DistinctMDNodes) {
// We may have DIArgList that were uniqued, and as it has a custom
// implementation of dropAllReferences, it needs to be explicitly invoked.
if (auto *AL = dyn_cast<DIArgList>(I)) {
AL->dropAllReferences();
continue;
}
I->dropAllReferences();
}
#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \
for (auto *I : CLASS##s) \
I->dropAllReferences();
#include "llvm/IR/Metadata.def"
// Also drop references that come from the Value bridges.
for (auto &Pair : ValuesAsMetadata)
Pair.second->dropUsers();
for (auto &Pair : MetadataAsValues)
Pair.second->dropUse();
// Destroy MDNodes.
for (MDNode *I : DistinctMDNodes)
I->deleteAsSubclass();
#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \
for (CLASS * I : CLASS##s) \
delete I;
#include "llvm/IR/Metadata.def"
// Free the constants.
for (auto *I : ExprConstants)
I->dropAllReferences();
for (auto *I : ArrayConstants)
I->dropAllReferences();
for (auto *I : StructConstants)
I->dropAllReferences();
for (auto *I : VectorConstants)
I->dropAllReferences();
ExprConstants.freeConstants();
ArrayConstants.freeConstants();
StructConstants.freeConstants();
VectorConstants.freeConstants();
InlineAsms.freeConstants();
CAZConstants.clear();
CPNConstants.clear();
UVConstants.clear();
PVConstants.clear();
IntConstants.clear();
FPConstants.clear();
CDSConstants.clear();
// Destroy attribute node lists.
for (FoldingSetIterator<AttributeSetNode> I = AttrsSetNodes.begin(),
E = AttrsSetNodes.end(); I != E; ) {
FoldingSetIterator<AttributeSetNode> Elem = I++;
delete &*Elem;
}
IR: Split Metadata from Value Split `Metadata` away from the `Value` class hierarchy, as part of PR21532. Assembly and bitcode changes are in the wings, but this is the bulk of the change for the IR C++ API. I have a follow-up patch prepared for `clang`. If this breaks other sub-projects, I apologize in advance :(. Help me compile it on Darwin I'll try to fix it. FWIW, the errors should be easy to fix, so it may be simpler to just fix it yourself. This breaks the build for all metadata-related code that's out-of-tree. Rest assured the transition is mechanical and the compiler should catch almost all of the problems. Here's a quick guide for updating your code: - `Metadata` is the root of a class hierarchy with three main classes: `MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from the `Value` class hierarchy. It is typeless -- i.e., instances do *not* have a `Type`. - `MDNode`'s operands are all `Metadata *` (instead of `Value *`). - `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively. If you're referring solely to resolved `MDNode`s -- post graph construction -- just use `MDNode*`. - `MDNode` (and the rest of `Metadata`) have only limited support for `replaceAllUsesWith()`. As long as an `MDNode` is pointing at a forward declaration -- the result of `MDNode::getTemporary()` -- it maintains a side map of its uses and can RAUW itself. Once the forward declarations are fully resolved RAUW support is dropped on the ground. This means that uniquing collisions on changing operands cause nodes to become "distinct". (This already happened fairly commonly, whenever an operand went to null.) If you're constructing complex (non self-reference) `MDNode` cycles, you need to call `MDNode::resolveCycles()` on each node (or on a top-level node that somehow references all of the nodes). Also, don't do that. Metadata cycles (and the RAUW machinery needed to construct them) are expensive. - An `MDNode` can only refer to a `Constant` through a bridge called `ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`). As a side effect, accessing an operand of an `MDNode` that is known to be, e.g., `ConstantInt`, takes three steps: first, cast from `Metadata` to `ConstantAsMetadata`; second, extract the `Constant`; third, cast down to `ConstantInt`. The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have metadata schema owners transition away from using `Constant`s when the type isn't important (and they don't care about referring to `GlobalValue`s). In the meantime, I've added transitional API to the `mdconst` namespace that matches semantics with the old code, in order to avoid adding the error-prone three-step equivalent to every call site. If your old code was: MDNode *N = foo(); bar(isa <ConstantInt>(N->getOperand(0))); baz(cast <ConstantInt>(N->getOperand(1))); bak(cast_or_null <ConstantInt>(N->getOperand(2))); bat(dyn_cast <ConstantInt>(N->getOperand(3))); bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4))); you can trivially match its semantics with: MDNode *N = foo(); bar(mdconst::hasa <ConstantInt>(N->getOperand(0))); baz(mdconst::extract <ConstantInt>(N->getOperand(1))); bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2))); bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3))); bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4))); and when you transition your metadata schema to `MDInt`: MDNode *N = foo(); bar(isa <MDInt>(N->getOperand(0))); baz(cast <MDInt>(N->getOperand(1))); bak(cast_or_null <MDInt>(N->getOperand(2))); bat(dyn_cast <MDInt>(N->getOperand(3))); bay(dyn_cast_or_null<MDInt>(N->getOperand(4))); - A `CallInst` -- specifically, intrinsic instructions -- can refer to metadata through a bridge called `MetadataAsValue`. This is a subclass of `Value` where `getType()->isMetadataTy()`. `MetadataAsValue` is the *only* class that can legally refer to a `LocalAsMetadata`, which is a bridged form of non-`Constant` values like `Argument` and `Instruction`. It can also refer to any other `Metadata` subclass. (I'll break all your testcases in a follow-up commit, when I propagate this change to assembly.) llvm-svn: 223802
2014-12-10 02:38:53 +08:00
// Destroy MetadataAsValues.
{
SmallVector<MetadataAsValue *, 8> MDVs;
MDVs.reserve(MetadataAsValues.size());
for (auto &Pair : MetadataAsValues)
MDVs.push_back(Pair.second);
MetadataAsValues.clear();
for (auto *V : MDVs)
delete V;
}
// Destroy ValuesAsMetadata.
for (auto &Pair : ValuesAsMetadata)
delete Pair.second;
}
void LLVMContextImpl::dropTriviallyDeadConstantArrays() {
Reduce dropTriviallyDeadConstantArrays cumulative time percentage from 17% to 4% The history of dropTriviallyDeadConstantArrays is like this. Because the appending linkage uses too much memory (http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20150105/251381.html), dropTriviallyDeadConstantArrays was introduced (https://reviews.llvm.org/rG81f385b0c6ea37dd7195a65be162c75bbdef29d2) to release unused constant arrays. Recently, dropTriviallyDeadConstantArrays was improved (https://reviews.llvm.org/rG81f385b0c6ea37dd7195a65be162c75bbdef29d2) to reduce its quadratic cost. Our recent LTO profiling shows that when a target is large, 15-20% of time cost is from the SetVector::insert called by dropTriviallyDeadConstantArrays. A large application has hundreds or thousands of modules; each module calls dropTriviallyDeadConstantArrays once for cleaning up tens of thousands of ConstantArrays a module has. In those ConstantArrays, usually around 5 can be deleted; a very very few deleted ConstantArrays reference other ConstantArrays: less than 10 out of millions. Given this, the cost of SetVector::insert is mainly from the construction of WorkList from ArrayConstants. This motivated the fix that iterates ArrayConstants directly, and uses WorkList only when necessary. Our evaluation shows that 1) The cumulative time percentage of dropTriviallyDeadConstantArrays is reduced from 15-17% to 4-6%. 2) For targets with LTO time > 20min, the time reduction is about 20%. 3) No observable performance impact for build without using LTO. {F12506218} {F12506221} Reviewed By: mehdi_amini, tejohnson, jdoerfert Differential Revision: https://reviews.llvm.org/D85379
2020-08-08 00:30:26 +08:00
SmallSetVector<ConstantArray *, 4> WorkList;
// When ArrayConstants are of substantial size and only a few in them are
// dead, starting WorkList with all elements of ArrayConstants can be
// wasteful. Instead, starting WorkList with only elements that have empty
// uses.
for (ConstantArray *C : ArrayConstants)
if (C->use_empty())
WorkList.insert(C);
while (!WorkList.empty()) {
ConstantArray *C = WorkList.pop_back_val();
if (C->use_empty()) {
for (const Use &Op : C->operands()) {
if (auto *COp = dyn_cast<ConstantArray>(Op))
WorkList.insert(COp);
}
C->destroyConstant();
}
}
}
void Module::dropTriviallyDeadConstantArrays() {
Context.pImpl->dropTriviallyDeadConstantArrays();
}
namespace llvm {
/// Make MDOperand transparent for hashing.
///
/// This overload of an implementation detail of the hashing library makes
/// MDOperand hash to the same value as a \a Metadata pointer.
///
/// Note that overloading \a hash_value() as follows:
///
/// \code
/// size_t hash_value(const MDOperand &X) { return hash_value(X.get()); }
/// \endcode
///
/// does not cause MDOperand to be transparent. In particular, a bare pointer
/// doesn't get hashed before it's combined, whereas \a MDOperand would.
static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
} // end namespace llvm
unsigned MDNodeOpsKey::calculateHash(MDNode *N, unsigned Offset) {
unsigned Hash = hash_combine_range(N->op_begin() + Offset, N->op_end());
#ifndef NDEBUG
{
SmallVector<Metadata *, 8> MDs(drop_begin(N->operands(), Offset));
unsigned RawHash = calculateHash(MDs);
assert(Hash == RawHash &&
"Expected hash of MDOperand to equal hash of Metadata*");
}
#endif
return Hash;
}
unsigned MDNodeOpsKey::calculateHash(ArrayRef<Metadata *> Ops) {
return hash_combine_range(Ops.begin(), Ops.end());
}
StringMapEntry<uint32_t> *LLVMContextImpl::getOrInsertBundleTag(StringRef Tag) {
uint32_t NewIdx = BundleTagCache.size();
return &*(BundleTagCache.insert(std::make_pair(Tag, NewIdx)).first);
}
void LLVMContextImpl::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const {
Tags.resize(BundleTagCache.size());
for (const auto &T : BundleTagCache)
Tags[T.second] = T.first();
}
uint32_t LLVMContextImpl::getOperandBundleTagID(StringRef Tag) const {
auto I = BundleTagCache.find(Tag);
assert(I != BundleTagCache.end() && "Unknown tag!");
return I->second;
}
SyncScope::ID LLVMContextImpl::getOrInsertSyncScopeID(StringRef SSN) {
auto NewSSID = SSC.size();
assert(NewSSID < std::numeric_limits<SyncScope::ID>::max() &&
"Hit the maximum number of synchronization scopes allowed!");
return SSC.insert(std::make_pair(SSN, SyncScope::ID(NewSSID))).first->second;
}
void LLVMContextImpl::getSyncScopeNames(
SmallVectorImpl<StringRef> &SSNs) const {
SSNs.resize(SSC.size());
for (const auto &SSE : SSC)
SSNs[SSE.second] = SSE.first();
}
/// Gets the OptPassGate for this LLVMContextImpl, which defaults to the
/// singleton OptBisect if not explicitly set.
OptPassGate &LLVMContextImpl::getOptPassGate() const {
if (!OPG)
OPG = &(*OptBisector);
return *OPG;
}
void LLVMContextImpl::setOptPassGate(OptPassGate& OPG) {
this->OPG = &OPG;
}
bool LLVMContextImpl::getOpaquePointers() {
if (LLVM_UNLIKELY(!(OpaquePointers.hasValue())))
OpaquePointers = OpaquePointersCL;
return *OpaquePointers;
}
void LLVMContextImpl::setOpaquePointers(bool OP) { OpaquePointers = OP; }