Skip to content

Commit

Permalink
recursive conversion to metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
vchuravy committed Mar 15, 2019
1 parent 9f69b2e commit ca42347
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 26 deletions.
25 changes: 25 additions & 0 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,31 @@ static Value *stringConstPtr(IRBuilder<> &irbuilder, const std::string &txt)
}
}

// --- MDNode ---
Metadata *to_md_tree(jl_value_t *val) {
if (val == jl_nothing)
return nullptr;
Metadata *MD = nullptr;
if (jl_is_symbol(val)) {
MD = MDString::get(jl_LLVMContext, jl_symbol_name((jl_sym_t*)val));
} else if (jl_is_bool(val)) {
MD = ConstantAsMetadata::get(ConstantInt::get(T_int1, jl_unbox_bool(val)));
} else if (jl_is_long(val)) {
MD = ConstantAsMetadata::get(ConstantInt::get(T_int64, jl_unbox_long(val)));
} else if (jl_is_tuple(val)) {
SmallVector<Metadata *, 8> MDs;
for (int f = 0, nf = jl_nfields(val); f < nf; ++f) {
MD = to_md_tree(jl_fieldref(val, f));
if (MD)
MDs.push_back(MD);
}
MD = MDNode::get(jl_LLVMContext, MDs);
} else {
jl_error("LLVM metadata needs to Symbol/Bool/Int or Tuple thereof");
}
return MD;
}

// --- Debug info ---

static DIType *julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed = false)
Expand Down
27 changes: 1 addition & 26 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4100,34 +4100,9 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval)
// parse Expr(:loopinfo, "julia.simdloop", ("llvm.loop.vectorize.width", 4))
SmallVector<Metadata *, 8> MDs;
for (int i = 0, ie = jl_expr_nargs(ex); i < ie; ++i) {
jl_value_t *arg = args[i];
Metadata *MD;
if (arg == jl_nothing)
continue;
if (jl_is_symbol(arg)) {
MD = MDString::get(jl_LLVMContext, jl_symbol_name((jl_sym_t*)arg));
} else if (jl_is_tuple(arg)) {
// TODO: are there loopinfo with more than one field?
if (jl_nfields(arg) != 2)
jl_error("loopinfo: only accept 2-arg tuple");
jl_value_t* name = jl_fieldref(arg, 0);
jl_value_t* value = jl_fieldref(arg, 1);
if (!jl_is_symbol(name))
jl_error("loopinfo: name needs to be a symbol");
Metadata *MDVal;
if(jl_is_bool(value))
MDVal = ConstantAsMetadata::get(ConstantInt::get(T_int1, jl_unbox_bool(value)));
if(jl_is_long(value))
MDVal = ConstantAsMetadata::get(ConstantInt::get(T_int64, jl_unbox_long(value)));
if(!MDVal)
jl_error("loopinfo: value can only be a bool or a long");
MD = MDNode::get(jl_LLVMContext,
{ MDString::get(jl_LLVMContext, jl_symbol_name((jl_sym_t*)name)), MDVal });
}
Metadata *MD = to_md_tree(args[i]);
if (MD)
MDs.push_back(MD);
else
jl_error("loopinfo: argument needs to be either a symbol or a tuple of type (Symbol, Union{Int, Bool}");
}

MDNode* MD = MDNode::get(jl_LLVMContext, MDs);
Expand Down
101 changes: 101 additions & 0 deletions test/llvmpasses/loopinfo.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# RUN: julia --startup-file=no %s %t | llvm-link -S %t/* | FileCheck %s
# RUN: julia --startup-file=no %s %t | llvm-link -S %t/* | opt -load libjulia%shlibext -LowerSIMDLoop -S - | FileCheck %s -check-prefix=LOWER
using InteractiveUtils
using Printf

dir = ARGS[1]
rm(dir, force=true, recursive=true)
mkdir(dir)

# CHECK-LABEL: @julia_simdf_
# LOWER-LABEL: @julia_simdf_
function simdf(X)
acc = zero(eltype(X))
@simd for x in X
acc += x
# CHECK: call void @julia.loopinfo_marker(), {{.*}}, !julia.loopinfo [[LOOPINFO:![0-9]+]]
# LOWER-NOT: llvm.mem.parallel_loop_access
# LOWER-NOT: call void @julia.loopinfo_marker()
# LOWER: fadd fast double
# LOWER: br {{.*}}, !llvm.loop [[LOOPID:![0-9]+]]
end
acc
end

# CHECK-LABEL: @julia_simdf2_
# LOWER-LABEL: @julia_simdf2_
function simdf2(X)
acc = zero(eltype(X))
@simd ivdep for x in X
acc += x
# CHECK: call void @julia.loopinfo_marker(), {{.*}}, !julia.loopinfo [[LOOPINFO2:![0-9]+]]
# LOWER: llvm.mem.parallel_loop_access
# LOWER-NOT: call void @julia.loopinfo_marker()
# LOWER: fadd fast double
# LOWER: br {{.*}}, !llvm.loop [[LOOPID2:![0-9]+]]
end
acc
end

@noinline iterate(i) = @show i

# CHECK-LABEL: @julia_loop_unroll
# LOWER-LABEL: @julia_loop_unroll
@eval function loop_unroll(N)
for i in 1:N
iterate(i)
$(Expr(:loopinfo, (Symbol("llvm.loop.unroll.count"), 3)))
# CHECK: call void @julia.loopinfo_marker(), {{.*}}, !julia.loopinfo [[LOOPINFO3:![0-9]+]]
# LOWER-NOT: call void @julia.loopinfo_marker()
# LOWER: br {{.*}}, !llvm.loop [[LOOPID3:![0-9]+]]
end
end

# CHECK-LABEL: @julia_loop_unroll2
# LOWER-LABEL: @julia_loop_unroll2
@eval function loop_unroll2(I)
for i in 1:10
for j in I
j == 2 && continue
iterate(i)
end
$(Expr(:loopinfo, (Symbol("llvm.loop.unroll.full"),)))
# CHECK: call void @julia.loopinfo_marker(), {{.*}}, !julia.loopinfo [[LOOPINFO4:![0-9]+]]
# LOWER-NOT: call void @julia.loopinfo_marker()
# LOWER: br {{.*}}, !llvm.loop [[LOOPID4:![0-9]+]]
end
end

## Check all the MD nodes
# CHECK: [[LOOPINFO]] = !{!"julia.simdloop"}
# CHECK: [[LOOPINFO2]] = !{!"julia.simdloop", !"julia.ivdep"}
# CHECK: [[LOOPINFO3]] = !{[[LOOPUNROLL:![0-9]+]]}
# CHECK: [[LOOPUNROLL]] = !{!"llvm.loop.unroll.count", i64 3}
# CHECK: [[LOOPINFO4]] = !{[[LOOPUNROLL2:![0-9]+]]}
# CHECK: [[LOOPUNROLL2]] = !{!"llvm.loop.unroll.full"}
# LOWER: [[LOOPID]] = distinct !{[[LOOPID]]}
# LOWER: [[LOOPID2]] = distinct !{[[LOOPID2]]}
# LOWER: [[LOOPID3]] = distinct !{[[LOOPID3]], [[LOOPUNROLL:![0-9]+]]}
# LOWER: [[LOOPUNROLL]] = !{!"llvm.loop.unroll.count", i64 3}
# LOWER: [[LOOPID4]] = distinct !{[[LOOPID4]], [[LOOPUNROLL2:![0-9]+]]}
# LOWER: [[LOOPUNROLL2]] = !{!"llvm.loop.unroll.full"}

# Emit LLVM IR to dir
counter = 0
function emit(f, tt...)
global counter
name = nameof(f)
open(joinpath(dir, @sprintf("%05d-%s.ll", counter, name)), "w") do io
code_llvm(io, f, tt, raw=true, optimize=false, dump_module=true, debuginfo=:none)
end
counter+=1
end

# Maintaining the order is important
emit(simdf, Vector{Float64})
emit(simdf2, Vector{Float64})
emit(loop_unroll, Int64)
emit(loop_unroll2, Int64)

0 comments on commit ca42347

Please sign in to comment.