Skip to content

Commit f84a934

Browse files
committed
Refactor Expr(:simdloop) to Expr(:loopinfo, ...)
- `Expr(:loopinfo, Symbol("julia.simdloop"))` replaces `Expr(:simdloop, false)` - `Expr(:loopinfo, Symbol("julia.simdloop"), Symbol("julia.ivdep"))` replaces `Expr(:simdloop, true)` While currently not directly exposed users can now pass other [loopinfo](https://llvm.org/docs/LangRef.html#llvm-loop) metadata to LLVM.
1 parent 48e7a35 commit f84a934

File tree

18 files changed

+172
-128
lines changed

18 files changed

+172
-128
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ function typeinf_local(frame::InferenceState)
11541154
if isa(fname, Slot)
11551155
changes = StateUpdate(fname, VarState(Any, false), changes)
11561156
end
1157-
elseif hd === :inbounds || hd === :meta || hd === :simdloop
1157+
elseif hd === :inbounds || hd === :meta || hd === :loopinfo
11581158
else
11591159
t = abstract_eval(stmt, changes, frame)
11601160
t === Bottom && break

base/compiler/optimize.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ function stmt_affects_purity(@nospecialize(stmt), ir)
155155
return !(t Bool)
156156
end
157157
if isa(stmt, Expr)
158-
return stmt.head != :simdloop && stmt.head != :enter
158+
return stmt.head != :loopinfo && stmt.head != :enter
159159
end
160160
return true
161161
end

base/compiler/ssair/queries.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ function stmt_effect_free(@nospecialize(stmt), @nospecialize(rt), src, sptypes::
5050
elseif head === :isdefined || head === :the_exception || head === :copyast || head === :inbounds || head === :boundscheck
5151
return true
5252
else
53-
# e.g. :simdloop
53+
# e.g. :loopinfo
5454
return false
5555
end
5656
end

base/compiler/utilities.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ end
5959

6060
# Meta expression head, these generally can't be deleted even when they are
6161
# in a dead branch but can be ignored when analyzing uses/liveness.
62-
is_meta_expr_head(head::Symbol) = (head === :inbounds || head === :boundscheck || head === :meta || head === :simdloop)
62+
is_meta_expr_head(head::Symbol) = (head === :inbounds || head === :boundscheck || head === :meta || head === :loopinfo)
6363

6464
sym_isless(a::Symbol, b::Symbol) = ccall(:strcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}), a, b) < 0
6565

base/compiler/validation.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const VALID_EXPR_HEADS = IdDict{Any,Any}(
2626
:foreigncall => 3:typemax(Int),
2727
:cfunction => 5:5,
2828
:isdefined => 1:1,
29-
:simdloop => 1:1,
29+
:loopinfo => 0:typemax(Int),
3030
:gc_preserve_begin => 0:typemax(Int),
3131
:gc_preserve_end => 0:typemax(Int),
3232
:thunk => 1:1,
@@ -143,7 +143,7 @@ function validate_code!(errors::Vector{>:InvalidCodeError}, c::CodeInfo, is_top_
143143
head === :inbounds || head === :foreigncall || head === :cfunction ||
144144
head === :const || head === :enter || head === :leave || head == :pop_exception ||
145145
head === :method || head === :global || head === :static_parameter ||
146-
head === :new || head === :splatnew || head === :thunk || head === :simdloop ||
146+
head === :new || head === :splatnew || head === :thunk || head === :loopinfo ||
147147
head === :throw_undef_if_not || head === :unreachable
148148
validate_val!(x)
149149
else

base/meta.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,6 @@ end
293293

294294
_instantiate_type_in_env(x, spsig, spvals) = ccall(:jl_instantiate_type_in_env, Any, (Any, Any, Ptr{Any}), x, spsig, spvals)
295295

296-
is_meta_expr_head(head::Symbol) = (head === :inbounds || head === :boundscheck || head === :meta || head === :simdloop)
296+
is_meta_expr_head(head::Symbol) = (head === :inbounds || head === :boundscheck || head === :meta || head === :loopinfo)
297297

298298
end # module

base/simdloop.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ check_body!(x::QuoteNode) = check_body!(x.value)
3737
check_body!(x) = true
3838

3939
# @simd splits a for loop into two loops: an outer scalar loop and
40-
# an inner loop marked with :simdloop. The simd_... functions define
40+
# an inner loop marked with :loopinfo. The simd_... functions define
4141
# the splitting.
4242
# Custom iterators that do not support random access cannot support
4343
# vectorization. In order to be compatible with `@simd` annotated loops,
@@ -76,7 +76,7 @@ function compile(x, ivdep)
7676
local $var = Base.simd_index($r,$j,$i)
7777
$(x.args[2]) # Body of loop
7878
$i += 1
79-
$(Expr(:simdloop, ivdep)) # Mark loop as SIMD loop
79+
$(Expr(:loopinfo, Symbol("julia.simdloop"), ivdep)) # Mark loop as SIMD loop
8080
end
8181
end
8282
end
@@ -125,12 +125,12 @@ either case, your inner loop should have the following properties to allow vecto
125125
* No iteration ever waits on a previous iteration to make forward progress.
126126
"""
127127
macro simd(forloop)
128-
esc(compile(forloop, false))
128+
esc(compile(forloop, nothing))
129129
end
130130

131131
macro simd(ivdep, forloop)
132132
if ivdep == :ivdep
133-
esc(compile(forloop, true))
133+
esc(compile(forloop, Symbol("julia.ivdep")))
134134
else
135135
throw(SimdError("Only ivdep is valid as the first argument to @simd"))
136136
end

doc/src/devdocs/ast.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ These symbols appear in the `head` field of [`Expr`](@ref)s in lowered form.
452452
Has the value `false` if inlined into a section of code marked with `@inbounds`,
453453
otherwise has the value `true`.
454454

455-
* `simdloop`
455+
* `loopinfo`
456456

457457
Marks the end of the inner loop of a `@simd` expression.
458458

src/ast.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jl_sym_t *global_sym; jl_sym_t *list_sym;
4949
jl_sym_t *dot_sym; jl_sym_t *newvar_sym;
5050
jl_sym_t *boundscheck_sym; jl_sym_t *inbounds_sym;
5151
jl_sym_t *copyast_sym; jl_sym_t *cfunction_sym;
52-
jl_sym_t *pure_sym; jl_sym_t *simdloop_sym;
52+
jl_sym_t *pure_sym; jl_sym_t *loopinfo_sym;
5353
jl_sym_t *meta_sym; jl_sym_t *inert_sym;
5454
jl_sym_t *polly_sym; jl_sym_t *unused_sym;
5555
jl_sym_t *static_parameter_sym; jl_sym_t *inline_sym;
@@ -341,7 +341,7 @@ void jl_init_frontend(void)
341341
inbounds_sym = jl_symbol("inbounds");
342342
newvar_sym = jl_symbol("newvar");
343343
copyast_sym = jl_symbol("copyast");
344-
simdloop_sym = jl_symbol("simdloop");
344+
loopinfo_sym = jl_symbol("loopinfo");
345345
pure_sym = jl_symbol("pure");
346346
meta_sym = jl_symbol("meta");
347347
list_sym = jl_symbol("list");

src/codegen.cpp

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,6 @@
8686
#include <llvm/ExecutionEngine/ExecutionEngine.h>
8787

8888
using namespace llvm;
89-
namespace llvm {
90-
extern bool annotateSimdLoop(BasicBlock *latch);
91-
}
9289

9390
#if defined(_OS_WINDOWS_) && !defined(NOMINMAX)
9491
#define NOMINMAX
@@ -296,8 +293,7 @@ static Function *jlegal_func;
296293
static Function *jl_alloc_obj_func;
297294
static Function *jl_newbits_func;
298295
static Function *jl_typeof_func;
299-
static Function *jl_simdloop_marker_func;
300-
static Function *jl_simdivdep_marker_func;
296+
static Function *jl_loopinfo_marker_func;
301297
static Function *jl_write_barrier_func;
302298
static Function *jlisa_func;
303299
static Function *jlsubtype_func;
@@ -4100,14 +4096,43 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval)
41004096
ctx.builder.CreateCall(prepare_call(jlcopyast_func),
41014097
maybe_decay_untracked(boxed(ctx, ast))), true, jl_expr_type);
41024098
}
4103-
else if (head == simdloop_sym) {
4104-
jl_value_t *ivdep = args[0];
4105-
assert(jl_expr_nargs(ex) == 1 && jl_is_bool(ivdep));
4106-
if (ivdep == jl_false) {
4107-
ctx.builder.CreateCall(prepare_call(jl_simdloop_marker_func));
4108-
} else {
4109-
ctx.builder.CreateCall(prepare_call(jl_simdivdep_marker_func));
4099+
else if (head == loopinfo_sym) {
4100+
// parse Expr(:loopinfo, "julia.simdloop", ("llvm.loop.vectorize.width", 4))
4101+
SmallVector<Metadata *, 8> MDs;
4102+
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+
}
4127+
if (MD)
4128+
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}");
41104131
}
4132+
4133+
MDNode* MD = MDNode::get(jl_LLVMContext, MDs);
4134+
CallInst *I = ctx.builder.CreateCall(prepare_call(jl_loopinfo_marker_func));
4135+
I->setMetadata("julia.loopinfo", MD);
41114136
return jl_cgval_t();
41124137
}
41134138
else if (head == goto_ifnot_sym) {
@@ -7356,19 +7381,12 @@ static void init_julia_llvm_env(Module *m)
73567381
add_return_attr(jl_newbits_func, Attribute::NonNull);
73577382
add_named_global(jl_newbits_func, (void*)jl_new_bits);
73587383

7359-
jl_simdloop_marker_func = Function::Create(FunctionType::get(T_void, {}, false),
7360-
Function::ExternalLinkage,
7361-
"julia.simdloop_marker");
7362-
jl_simdloop_marker_func->addFnAttr(Attribute::NoUnwind);
7363-
jl_simdloop_marker_func->addFnAttr(Attribute::NoRecurse);
7364-
jl_simdloop_marker_func->addFnAttr(Attribute::InaccessibleMemOnly);
7365-
7366-
jl_simdivdep_marker_func = Function::Create(FunctionType::get(T_void, {}, false),
7384+
jl_loopinfo_marker_func = Function::Create(FunctionType::get(T_void, {}, false),
73677385
Function::ExternalLinkage,
7368-
"julia.simdivdep_marker");
7369-
jl_simdivdep_marker_func->addFnAttr(Attribute::NoUnwind);
7370-
jl_simdivdep_marker_func->addFnAttr(Attribute::NoRecurse);
7371-
jl_simdivdep_marker_func->addFnAttr(Attribute::InaccessibleMemOnly);
7386+
"julia.loopinfo_marker");
7387+
jl_loopinfo_marker_func->addFnAttr(Attribute::NoUnwind);
7388+
jl_loopinfo_marker_func->addFnAttr(Attribute::NoRecurse);
7389+
jl_loopinfo_marker_func->addFnAttr(Attribute::InaccessibleMemOnly);
73727390

73737391
jl_typeof_func = Function::Create(FunctionType::get(T_prjlvalue, {T_prjlvalue}, false),
73747392
Function::ExternalLinkage,

0 commit comments

Comments
 (0)