forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimdloop.jl
60 lines (53 loc) · 1.48 KB
/
simdloop.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# Support for @simd for
module SimdLoop
export @simd
# Error thrown from ill-formed uses of @simd
type SimdError <: Exception
msg::ASCIIString
end
# Parse iteration space expression
# symbol '=' range
# symbol 'in' range
function parse_iteration_space( x )
if !Meta.isexpr(x,[:(=),:in])
throw( SimdError("= or in expected"))
elseif length(x.args)!=2
throw( SimdError("simd range syntax is wrong"))
elseif !isa(x.args[1],Symbol)
throw( SimdError("simd loop index must be a symbol"))
else
x.args # symbol, range
end
end
# Compile Expr x in context of @simd.
function compile(x)
if !Meta.isexpr(x,:for)
throw(SimdError("for loop expected"))
elseif length(x.args)!=2
throw(SimdError("1D for loop expected"))
else
var,range = parse_iteration_space(x.args[1])
r = gensym() # Range
n = gensym() # Trip count
s = gensym() # Step
i = gensym() # Index variable
# LLVM vectorizer needs to compute a trip count, so make it obvious.
quote
local $r = $range
local $n = length($r)
local $s = step($r)
local $var = first($r)
local $i = zero($n)
while $i < $n
$(x.args[2])
$var += $s
$i += 1
$(Expr(:simdloop)) # Mark loop as SIMD loop
end
end
end
end
macro simd(forloop)
esc(compile(forloop))
end
end # simdloop