Skip to content

Commit

Permalink
Fix performance problem in root coloring
Browse files Browse the repository at this point in the history
By originally using a vector, rather than a set, neighbors would
end up getting duplicated in the list. This blew up the size of
the list, causing excessive performance problems in the ColorRoots
function.
  • Loading branch information
Keno committed Jun 20, 2017
1 parent bd2878f commit 6674011
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 13 deletions.
13 changes: 13 additions & 0 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#include <llvm/Support/SourceMgr.h> // for llvmcall
#include <llvm/Transforms/Utils/Cloning.h> // for llvmcall inlining
#include <llvm/IR/Verifier.h> // for llvmcall validation
#include <llvm/Bitcode/ReaderWriter.h>

// C API
#include <llvm-c/Types.h>
Expand Down Expand Up @@ -7145,3 +7146,15 @@ extern "C" void jl_dump_llvm_type(void *v)
#endif
putchar('\n');
}

extern void jl_write_bitcode_func(void *F, char *fname) {
std::error_code EC;
raw_fd_ostream OS(fname, EC, sys::fs::F_None);
llvm::WriteBitcodeToFile(((llvm::Function*)F)->getParent(), OS);
}

extern void jl_write_bitcode_module(void *M, char *fname) {
std::error_code EC;
raw_fd_ostream OS(fname, EC, sys::fs::F_None);
llvm::WriteBitcodeToFile((llvm::Module*)M, OS);
}
23 changes: 13 additions & 10 deletions src/llvm-late-gc-lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <llvm/ADT/BitVector.h>
#include <llvm/ADT/PostOrderIterator.h>
#include <llvm/ADT/SetVector.h>
#include "llvm/Analysis/CFG.h"
#include <llvm/IR/Value.h>
#include <llvm/IR/Constants.h>
Expand Down Expand Up @@ -248,7 +249,7 @@ struct State {
std::map<int, Value *> ReversePtrNumbering;
// Neighbors in the coloring interference graph. I.e. for each value, the
// indices of other values that are used simultaneously at some safe point.
std::vector<std::vector<int>> Neighbors;
std::vector<SetVector<int>> Neighbors;
// The result of the local analysis
std::map<BasicBlock *, BBState> BBStates;

Expand Down Expand Up @@ -823,17 +824,19 @@ void LateLowerGCFrame::ComputeLiveSets(Function &F, State &S) {
}
// Compute the interference graph
for (int i = 0; i <= S.MaxPtrNumber; ++i) {
std::vector<int> Neighbors;
SetVector<int> Neighbors;
BitVector NeighborBits(S.MaxPtrNumber);
for (auto it : S.SafepointNumbering) {
const BitVector &LS = S.LiveSets[it.second];
if ((unsigned)i >= LS.size() || !LS[i])
continue;
for (int Idx = LS.find_first(); Idx >= 0; Idx = LS.find_next(Idx)) {
// We explicitly let i be a neighbor of itself, to distinguish
// between being the only value live at a safepoint, vs not
// being live at any safepoint.
Neighbors.push_back(Idx);
}
NeighborBits |= LS;
}
for (int Idx = NeighborBits.find_first(); Idx >= 0; Idx = NeighborBits.find_next(Idx)) {
// We explicitly let i be a neighbor of itself, to distinguish
// between being the only value live at a safepoint, vs not
// being live at any safepoint.
Neighbors.insert(Idx);
}
S.Neighbors.push_back(Neighbors);
}
Expand Down Expand Up @@ -886,8 +889,8 @@ struct PEOIterator {
};
std::vector<Element> Elements;
std::vector<std::vector<int>> Levels;
const std::vector<std::vector<int>> &Neighbors;
PEOIterator(const std::vector<std::vector<int>> &Neighbors) : Neighbors(Neighbors) {
const std::vector<SetVector<int>> &Neighbors;
PEOIterator(const std::vector<SetVector<int>> &Neighbors) : Neighbors(Neighbors) {
// Initialize State
std::vector<int> FirstLevel;
for (unsigned i = 0; i < Neighbors.size(); ++i) {
Expand Down
7 changes: 4 additions & 3 deletions test/llvmpasses/lit.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import lit.util
import lit.formats

config.name = 'Julia'
config.suffixes = ['.ll']
config.suffixes = ['.ll','.jl']
config.test_source_root = os.path.dirname(__file__)
config.test_format = lit.formats.ShTest(False)
config.test_format = lit.formats.ShTest(True)

path = os.path.pathsep.join((os.path.join(os.path.dirname(__file__),"../../usr/tools"), config.environment['PATH']))
path = os.path.pathsep.join((os.path.join(os.path.dirname(__file__),"../../usr/tools"), os.path.join(os.path.dirname(__file__),"../../usr/bin"), config.environment['PATH']))
config.environment['PATH'] = path
config.environment['HOME'] = "/tmp"
25 changes: 25 additions & 0 deletions test/llvmpasses/safepoint_stress.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# RUN: julia --startup-file=no %s | opt -load libjulia.so -LateLowerGCFrame -S - | FileCheck %s

println("""
%jl_value_t = type opaque
declare %jl_value_t addrspace(10)* @alloc()
declare void @one_arg_boxed(%jl_value_t addrspace(10)*)
declare %jl_value_t*** @jl_get_ptls_states()
define void @stress(i64 %a, i64 %b) {
%ptls = call %jl_value_t*** @jl_get_ptls_states()
""")

# CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 10002
for i = 1:10000
println("\t%arg$i = call %jl_value_t addrspace(10)* @alloc()")
end

for i = 1:10000
println("\tcall void @one_arg_boxed(%jl_value_t addrspace(10)* %arg$i)")
end

println("""
ret void
}
""")

0 comments on commit 6674011

Please sign in to comment.