Skip to content

Commit ca42347

Browse files
committed
recursive conversion to metadata
1 parent 9f69b2e commit ca42347

File tree

3 files changed

+127
-26
lines changed

3 files changed

+127
-26
lines changed

src/cgutils.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,31 @@ static Value *stringConstPtr(IRBuilder<> &irbuilder, const std::string &txt)
171171
}
172172
}
173173

174+
// --- MDNode ---
175+
Metadata *to_md_tree(jl_value_t *val) {
176+
if (val == jl_nothing)
177+
return nullptr;
178+
Metadata *MD = nullptr;
179+
if (jl_is_symbol(val)) {
180+
MD = MDString::get(jl_LLVMContext, jl_symbol_name((jl_sym_t*)val));
181+
} else if (jl_is_bool(val)) {
182+
MD = ConstantAsMetadata::get(ConstantInt::get(T_int1, jl_unbox_bool(val)));
183+
} else if (jl_is_long(val)) {
184+
MD = ConstantAsMetadata::get(ConstantInt::get(T_int64, jl_unbox_long(val)));
185+
} else if (jl_is_tuple(val)) {
186+
SmallVector<Metadata *, 8> MDs;
187+
for (int f = 0, nf = jl_nfields(val); f < nf; ++f) {
188+
MD = to_md_tree(jl_fieldref(val, f));
189+
if (MD)
190+
MDs.push_back(MD);
191+
}
192+
MD = MDNode::get(jl_LLVMContext, MDs);
193+
} else {
194+
jl_error("LLVM metadata needs to Symbol/Bool/Int or Tuple thereof");
195+
}
196+
return MD;
197+
}
198+
174199
// --- Debug info ---
175200

176201
static DIType *julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed = false)

src/codegen.cpp

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4100,34 +4100,9 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval)
41004100
// parse Expr(:loopinfo, "julia.simdloop", ("llvm.loop.vectorize.width", 4))
41014101
SmallVector<Metadata *, 8> MDs;
41024102
for (int i = 0, ie = jl_expr_nargs(ex); i < ie; ++i) {
4103-
jl_value_t *arg = args[i];
4104-
Metadata *MD;
4105-
if (arg == jl_nothing)
4106-
continue;
4107-
if (jl_is_symbol(arg)) {
4108-
MD = MDString::get(jl_LLVMContext, jl_symbol_name((jl_sym_t*)arg));
4109-
} else if (jl_is_tuple(arg)) {
4110-
// TODO: are there loopinfo with more than one field?
4111-
if (jl_nfields(arg) != 2)
4112-
jl_error("loopinfo: only accept 2-arg tuple");
4113-
jl_value_t* name = jl_fieldref(arg, 0);
4114-
jl_value_t* value = jl_fieldref(arg, 1);
4115-
if (!jl_is_symbol(name))
4116-
jl_error("loopinfo: name needs to be a symbol");
4117-
Metadata *MDVal;
4118-
if(jl_is_bool(value))
4119-
MDVal = ConstantAsMetadata::get(ConstantInt::get(T_int1, jl_unbox_bool(value)));
4120-
if(jl_is_long(value))
4121-
MDVal = ConstantAsMetadata::get(ConstantInt::get(T_int64, jl_unbox_long(value)));
4122-
if(!MDVal)
4123-
jl_error("loopinfo: value can only be a bool or a long");
4124-
MD = MDNode::get(jl_LLVMContext,
4125-
{ MDString::get(jl_LLVMContext, jl_symbol_name((jl_sym_t*)name)), MDVal });
4126-
}
4103+
Metadata *MD = to_md_tree(args[i]);
41274104
if (MD)
41284105
MDs.push_back(MD);
4129-
else
4130-
jl_error("loopinfo: argument needs to be either a symbol or a tuple of type (Symbol, Union{Int, Bool}");
41314106
}
41324107

41334108
MDNode* MD = MDNode::get(jl_LLVMContext, MDs);

test/llvmpasses/loopinfo.jl

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
# RUN: julia --startup-file=no %s %t | llvm-link -S %t/* | FileCheck %s
4+
# RUN: julia --startup-file=no %s %t | llvm-link -S %t/* | opt -load libjulia%shlibext -LowerSIMDLoop -S - | FileCheck %s -check-prefix=LOWER
5+
using InteractiveUtils
6+
using Printf
7+
8+
dir = ARGS[1]
9+
rm(dir, force=true, recursive=true)
10+
mkdir(dir)
11+
12+
# CHECK-LABEL: @julia_simdf_
13+
# LOWER-LABEL: @julia_simdf_
14+
function simdf(X)
15+
acc = zero(eltype(X))
16+
@simd for x in X
17+
acc += x
18+
# CHECK: call void @julia.loopinfo_marker(), {{.*}}, !julia.loopinfo [[LOOPINFO:![0-9]+]]
19+
# LOWER-NOT: llvm.mem.parallel_loop_access
20+
# LOWER-NOT: call void @julia.loopinfo_marker()
21+
# LOWER: fadd fast double
22+
# LOWER: br {{.*}}, !llvm.loop [[LOOPID:![0-9]+]]
23+
end
24+
acc
25+
end
26+
27+
# CHECK-LABEL: @julia_simdf2_
28+
# LOWER-LABEL: @julia_simdf2_
29+
function simdf2(X)
30+
acc = zero(eltype(X))
31+
@simd ivdep for x in X
32+
acc += x
33+
# CHECK: call void @julia.loopinfo_marker(), {{.*}}, !julia.loopinfo [[LOOPINFO2:![0-9]+]]
34+
# LOWER: llvm.mem.parallel_loop_access
35+
# LOWER-NOT: call void @julia.loopinfo_marker()
36+
# LOWER: fadd fast double
37+
# LOWER: br {{.*}}, !llvm.loop [[LOOPID2:![0-9]+]]
38+
end
39+
acc
40+
end
41+
42+
@noinline iterate(i) = @show i
43+
44+
# CHECK-LABEL: @julia_loop_unroll
45+
# LOWER-LABEL: @julia_loop_unroll
46+
@eval function loop_unroll(N)
47+
for i in 1:N
48+
iterate(i)
49+
$(Expr(:loopinfo, (Symbol("llvm.loop.unroll.count"), 3)))
50+
# CHECK: call void @julia.loopinfo_marker(), {{.*}}, !julia.loopinfo [[LOOPINFO3:![0-9]+]]
51+
# LOWER-NOT: call void @julia.loopinfo_marker()
52+
# LOWER: br {{.*}}, !llvm.loop [[LOOPID3:![0-9]+]]
53+
end
54+
end
55+
56+
# CHECK-LABEL: @julia_loop_unroll2
57+
# LOWER-LABEL: @julia_loop_unroll2
58+
@eval function loop_unroll2(I)
59+
for i in 1:10
60+
for j in I
61+
j == 2 && continue
62+
iterate(i)
63+
end
64+
$(Expr(:loopinfo, (Symbol("llvm.loop.unroll.full"),)))
65+
# CHECK: call void @julia.loopinfo_marker(), {{.*}}, !julia.loopinfo [[LOOPINFO4:![0-9]+]]
66+
# LOWER-NOT: call void @julia.loopinfo_marker()
67+
# LOWER: br {{.*}}, !llvm.loop [[LOOPID4:![0-9]+]]
68+
end
69+
end
70+
71+
## Check all the MD nodes
72+
# CHECK: [[LOOPINFO]] = !{!"julia.simdloop"}
73+
# CHECK: [[LOOPINFO2]] = !{!"julia.simdloop", !"julia.ivdep"}
74+
# CHECK: [[LOOPINFO3]] = !{[[LOOPUNROLL:![0-9]+]]}
75+
# CHECK: [[LOOPUNROLL]] = !{!"llvm.loop.unroll.count", i64 3}
76+
# CHECK: [[LOOPINFO4]] = !{[[LOOPUNROLL2:![0-9]+]]}
77+
# CHECK: [[LOOPUNROLL2]] = !{!"llvm.loop.unroll.full"}
78+
# LOWER: [[LOOPID]] = distinct !{[[LOOPID]]}
79+
# LOWER: [[LOOPID2]] = distinct !{[[LOOPID2]]}
80+
# LOWER: [[LOOPID3]] = distinct !{[[LOOPID3]], [[LOOPUNROLL:![0-9]+]]}
81+
# LOWER: [[LOOPUNROLL]] = !{!"llvm.loop.unroll.count", i64 3}
82+
# LOWER: [[LOOPID4]] = distinct !{[[LOOPID4]], [[LOOPUNROLL2:![0-9]+]]}
83+
# LOWER: [[LOOPUNROLL2]] = !{!"llvm.loop.unroll.full"}
84+
85+
# Emit LLVM IR to dir
86+
counter = 0
87+
function emit(f, tt...)
88+
global counter
89+
name = nameof(f)
90+
open(joinpath(dir, @sprintf("%05d-%s.ll", counter, name)), "w") do io
91+
code_llvm(io, f, tt, raw=true, optimize=false, dump_module=true, debuginfo=:none)
92+
end
93+
counter+=1
94+
end
95+
96+
# Maintaining the order is important
97+
emit(simdf, Vector{Float64})
98+
emit(simdf2, Vector{Float64})
99+
emit(loop_unroll, Int64)
100+
emit(loop_unroll2, Int64)
101+

0 commit comments

Comments
 (0)