[Libre-soc-bugs] [Bug 558] gcc SV intrinsics concept

bugzilla-daemon at libre-soc.org bugzilla-daemon at libre-soc.org
Wed Dec 30 22:52:13 GMT 2020


https://bugs.libre-soc.org/show_bug.cgi?id=558

--- Comment #31 from Alexandre Oliva <oliva at libre-soc.org> ---
luke, knowing what was or wasn't available in the cray implementation wouldn't
tell me something was part of our plans.  I had happened to come across setvli,
but I had not seen any mention (that I recall) of setvl, that's all.

also, the output of setvl is not really what I was interested in, though the
responses have made me realize that, if we're to model VL in GCC at all, we
can't just assume it will hold whatever value we store in it.

what I was interested in was the dynamic setting of vl after a fail-on-first. 
the compiler may have to save it and restore it even in the absence of function
calls.  an intervening use of a different vector may require a setvl, and then,
when we go back to the original vector, we'd better restore the vl that it had
at the end, rather than assume it's the same as in the beginning.

now, you could say "don't do that", but I'm just trying to model things in the
compiler, and once you model vl as a register in the compiler, and state the
register has to be set before an instruction can operate on this object as a
vector, there is a possibility it will vectorize stuff in a loop that calls a
function that happens to use a different vector type, and even that the
function is inlined.  as an ISA designer, you may not expect this sort of
behavior, but as a compiler writer, I expect arbitrary code to be thrown at it,
so I have to take these possibilities into account.


now, the mention of setting sub-pc is confusing when all I'm asking for is a
means to load and restore the vl.  I suppose the mention was because they're
all expected to be represented in the same special-purpose register, and an
interrupt handler may very well have to preserve it, restore it, and even
attempt to tinker with it; so might a signal handler.  but I was talking about
userland exception handling.  think setjmp/longjmp, not iret.  you won't
longjmp into the middle of the execution of a vector-prefixed instruction,
indeed, but you might want to restore the maxvl and the vl to those of the
enclosing context.  and, indeed, one could argue a signal handler *must* do
that whether it returns to the point of execution, or it raises an exception. 
some languages  rely heavily on raising exceptions for certain kinds of error
recovery (Ada comes to mind), and that's often implemented as raising
exceptions from within signal handlers.  now, if the compiler were to assume
that at an exception landing pad the vector state is preserved from what it set
up before a loop (without any function calls), and we don't preserve it, that
would be a problem.  consider:

  setvli
  for (int i = 0; i < e; i += VL) {
    try:
      __builtin_vector_intrinsic(...); // not a function call
      __builtin_vector_intrinsic(...); // not a function call
      __builtin_vector_intrinsic(...); // not a function call
    except:
      log the problem, recover or skip, then continue on to the next iteration
  }

do you see the problem of not restoring vector state there?

I assume you do.  now let's take this one step further.  consider any of these
intrinsics actually modify VL (e.g. fail-on-first); assume VL is an asm
register variable or a macro that reads from the VL part of the special-purpose
vector status registers somehow.

after we continue, we add VL to the loop counter.  it may have been modified
within the loop body, or even in an earlier loop iteration.  do you see the
problem if the exception raised out of the signal handler doesn't restore the
VL that was in effect, and instead leaks unrelated MAXVL and VL, set up within
the signal handler, to the exception handler within your vector loop?

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the libre-soc-bugs mailing list