Skip to content

Revert "SIL: add a StackList data structure with zero cost operations." #36871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 97 additions & 2 deletions include/swift/SIL/BasicBlockBits.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_SIL_BASICBLOCKBITS_H
#define SWIFT_SIL_BASICBLOCKBITS_H
#ifndef SWIFT_SIL_SILBITFIELD_H
#define SWIFT_SIL_SILBITFIELD_H

#include "swift/SIL/SILFunction.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -173,6 +173,101 @@ class BasicBlockSet {
void erase(SILBasicBlock *block) { flag.reset(block); }
};

/// An implementation of `llvm::SetVector<SILBasicBlock *,
/// SmallVector<SILBasicBlock *, N>,
/// BasicBlockSet>`.
///
/// Unfortunately it's not possible to use `llvm::SetVector` directly because
/// the BasicBlockSet constructor needs a `SILFunction` argument.
///
/// Note: This class does not provide a `remove` method intentinally, because
/// it would have a O(n) complexity.
template <unsigned N> class BasicBlockSetVector {
using Vector = llvm::SmallVector<SILBasicBlock *, N>;

Vector vector;
BasicBlockSet set;

public:
using iterator = typename Vector::const_iterator;

BasicBlockSetVector(SILFunction *function) : set(function) {}

iterator begin() const { return vector.begin(); }
iterator end() const { return vector.end(); }

unsigned size() const { return vector.size(); }
bool empty() const { return vector.empty(); }

bool contains(SILBasicBlock *block) const { return set.contains(block); }

/// Returns true if \p block was not contained in the set before inserting.
bool insert(SILBasicBlock *block) {
if (set.insert(block)) {
vector.push_back(block);
return true;
}
return false;
}
};

/// A utility for processing basic blocks in a worklist.
///
/// It is basically a combination of a block vector and a block set. It can be
/// used for typical worklist-processing algorithms.
template <unsigned N> class BasicBlockWorklist {
llvm::SmallVector<SILBasicBlock *, N> worklist;
BasicBlockSet visited;

public:
/// Construct an empty worklist.
BasicBlockWorklist(SILFunction *function) : visited(function) {}

/// Initialize the worklist with \p initialBlock.
BasicBlockWorklist(SILBasicBlock *initialBlock)
: visited(initialBlock->getParent()) {
push(initialBlock);
}

/// Pops the last added element from the worklist or returns null, if the
/// worklist is empty.
SILBasicBlock *pop() {
if (worklist.empty())
return nullptr;
return worklist.pop_back_val();
}

/// Pushes \p block onto the worklist if \p block has never been push before.
bool pushIfNotVisited(SILBasicBlock *block) {
if (visited.insert(block)) {
worklist.push_back(block);
return true;
}
return false;
}

/// Like `pushIfNotVisited`, but requires that \p block has never been on the
/// worklist before.
void push(SILBasicBlock *block) {
assert(!visited.contains(block));
visited.insert(block);
worklist.push_back(block);
}

/// Like `pop`, but marks the returned block as "unvisited". This means, that
/// the block can be pushed onto the worklist again.
SILBasicBlock *popAndForget() {
if (worklist.empty())
return nullptr;
SILBasicBlock *block = worklist.pop_back_val();
visited.erase(block);
return block;
}

/// Returns true if \p block was visited, i.e. has been added to the worklist.
bool isVisited(SILBasicBlock *block) const { return visited.contains(block); }
};

} // namespace swift

#endif
120 changes: 0 additions & 120 deletions include/swift/SIL/BasicBlockDatastructures.h

This file was deleted.

65 changes: 0 additions & 65 deletions include/swift/SIL/SILModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,52 +49,10 @@
#include "llvm/Support/raw_ostream.h"
#include <functional>

namespace swift {

/// A fixed size slab of memory, which can be allocated and freed by the
/// SILModule at (basically) zero cost.
class FixedSizeSlab : public llvm::ilist_node<FixedSizeSlab>,
public SILAllocated<FixedSizeSlab> {
public:
/// The capacity of the payload.
static constexpr size_t capacity = 64 * sizeof(uintptr_t);

private:
friend class SILModule;

/// The magic number which is stored in overflowGuard.
static constexpr uintptr_t magicNumber = (uintptr_t)0xdeadbeafdeadbeafull;

/// The payload.
char data[capacity];

/// Used for a cheap buffer overflow check - in the spirit of libgmalloc.
uintptr_t overflowGuard = magicNumber;

public:
/// Returns the payload pointing to \p T.
template<typename T> T *dataFor() { return (T *)(&data[0]); }

/// Returns the payload pointing to const \p T
template<typename T> const T *dataFor() const { return (const T *)(&data[0]); }
};

} // end swift namespace

namespace llvm {
namespace yaml {
class Output;
} // end namespace yaml

template <>
struct ilist_traits<::swift::FixedSizeSlab> :
public ilist_node_traits<::swift::FixedSizeSlab> {
public:
static void deleteNode(::swift::FixedSizeSlab *V) {
llvm_unreachable("cannot delete a slab");
}
};

} // end namespace llvm

namespace swift {
Expand Down Expand Up @@ -171,7 +129,6 @@ class SILModule {
};

using ActionCallback = std::function<void()>;
using SlabList = llvm::ilist<FixedSizeSlab>;

private:
friend KeyPathPattern;
Expand All @@ -194,12 +151,6 @@ class SILModule {
/// Allocator that manages the memory of all the pieces of the SILModule.
mutable llvm::BumpPtrAllocator BPA;

/// The list of freed slabs, which can be reused.
SlabList freeSlabs;

/// For consistency checking.
size_t numAllocatedSlabs = 0;

/// The swift Module associated with this SILModule.
ModuleDecl *TheSwiftModule;

Expand Down Expand Up @@ -782,22 +733,6 @@ class SILModule {
return static_cast<T *>(allocate(sizeof(T) * Count, alignof(T)));
}

/// Allocates a slab of memory.
///
/// This has (almost) zero cost, because for the first time, the allocation is
/// done with the BPA.
/// Subsequent allocations are reusing the already freed slabs.
FixedSizeSlab *allocSlab();

/// Frees a slab.
///
/// This has (almost) zero cost, because the slab is just put into the
/// freeSlabs list.
void freeSlab(FixedSizeSlab *slab);

/// Frees all slabs of a list.
void freeAllSlabs(SlabList &slabs);

template <typename T>
MutableArrayRef<T> allocateCopy(ArrayRef<T> Array) const {
MutableArrayRef<T> result(allocate<T>(Array.size()), Array.size());
Expand Down
Loading