-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
at-simd be messing with my for loops #8613
Comments
The problem seems to be here. julia> function f()
local i
for i = 1:10
i == 2 && break
end
i
end;
julia> f()
2
julia> function f()
local i
@simd for i = 1:10
i == 2 && break
end
i
end;
julia> f()
10 |
Having |
Yes, it should probably be a static error to do that. cc @ArchRobison |
Its a slippery slope if the compiler has to prove these assertions, I think at best we could throw a warning in some cases. |
No, that's not what I mean – I mean if a |
I concur that Can anyone suggest good prior art in |
I haven't rigorously tested this, but it seems sufficient. diff --git a/base/simdloop.jl b/base/simdloop.jl
index 139b10f..5be991c 100644
--- a/base/simdloop.jl
+++ b/base/simdloop.jl
@@ -19,10 +19,28 @@ function parse_iteration_space(x)
x.args # symbol, range
end
+# reject control flow statements in simd loop body
+function no_control_flow(ex::Expr)
+ if ex.head === :break || ex.head == :continue || (ex.head === :macrocall && ex.args[1] === symbol("@goto"))
+ throw(SimdError("$(ex.head) is not allowed inside @simd loop body"))
+ end
+ for arg in ex.args
+ if isa(arg, Expr)
+ no_control_flow(arg)
+ elseif isa(arg, QuoteNode)
+ no_control_flow(arg)
+ end
+ end
+ return true
+end
+no_control_flow(ex::QuoteNode) = no_control_flow(ex.value)
+no_control_flow(ex) = true
+
# Compile Expr x in context of @simd.
function compile(x)
(isa(x, Expr) && x.head == :for) || throw(SimdError("for loop expected"))
length(x.args) == 2 || throw(SimdError("1D for loop expected"))
+ no_control_flow(x)
var,range = parse_iteration_space(x.args[1])
r = gensym("r") # Range value |
I guess what I was thinking about were branches that the compiler can prove are never taken. This should not defeat the vectorizer if the branch is stripped out, so throwing an error in this case doesn't seem to be technically correct but it is probably best to be conservative. |
Are the |
No, they should be stripped out. |
Generally, I don't think x = false
for i = 1:n
x |= v[i]
x && break
end where Now that |
My long term goal is indeed to let us move bounds checks before the loop, or vectorize the checks, so that using While implementing parallel STL for C++, I ran into use cases for break inside a vector loop, but so far I'm not aware of any vectorizer that handles such cases. A sticky point is what the value of the index variable should be after the break. Some use cases will settle for any value that led to a break; other uses cases need the leftmost value. |
Consider the following on commit 215249d, Windows 64-bit:
And with
@simd
@ArchRobison
The text was updated successfully, but these errors were encountered: