You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* [circt][arc] Add bufferized array handling
Previously, !hw.array types were lowered directly to !llvm.array types. This
is the obvious lowering, but unfortunately it produces very poor code and can
in some cases bog down LLVM quadratically.
LLVM's ArrayType is aggressively SROA'd - it is really assumed to be more like
a tuple-type - so no matter how we try to avoid it (e.g. HWSpillCache), LLVM
will expand each array into individual scalars. This creates a large number of
instructions, but worse - it creates very difficult scheduling problems with
high connectivity. LLVM's pre-regalloc scheduler has been seen to take hours
on a problem that should be fairly simple.
This PR fixes this issue by introducing an !arc.arrayref<T> type. This mirrors
!hw.array<T>, except that it has buffer semantics rather than value semantics.
That is, !arc.arrayref is to memref as !hw.array is to tensor.
I did heavily look into using the exising bufferization passes in MLIR, but
these are (a) quite hard to use, and (b) heavily tailored to the "tensor" and
"memref" types.
In the end it felt like much less complexity to implement our own barebones
bufferizer.
Each !hw.array op is translatable to an !arrayref op, except that the arrayref
versions take a destination buffer to modify as an operand. They are mostly in
destination passing style.
The translation to LLVMIR dialect is trivial (!arrayref -> !llvm.ptr).
There are other optimizations we can do to reduce the compile time (and runtime)
of array-heavy code but they are left for further PRs:
* Aggressive reduction of arc.arrayref.alloc ops (better bufferization).
* Optimization of hw.array_creates where array permutations/shuffles have been
expanded.
* Proper handling of nested arrays.
* Add dereferenceable(N) attribute
* Apply review comments:
* Inherit ArrayRefType from ShapedType
* Attribute:$size -> uint64_t:$size
* Add traits and predicates to all ops for better verification
* Add missing rewriter.modifyOpInPlace
* Fix erroeous UpperCamelCasing
* Add support for nested arrays and arrays within structs.
We support these by never converting a nested array, or any struct containing an array.
Only "raw" arrays are converted to ArrayRefs.
Introduces `arc.arrayref.from_array` and `arc.arrayref.to_array` as casters because
hw.array is now expected to be legal in some scenarios.
* Switch on by default! (yay!)
* Fix integration test:
* Explicitly declare Struct*Op as legal.
* Plant a local copy of the array in StateReadOp.
Assisted-by: Gemini:experimental to identify the StateReadOp bug.
* Review comments:
* DenseI64ElementsAttr -> ArrayAttr (again)
* Handle OOB load, store and slice.
* Remove extra alloca in slice lowering.
* Replace Load/Store with destructured insertvalue/extractvalue
* Act on review comments
* Add type verifier to disallow !arc.arrayref<0xT>
---------
Co-authored-by: James Molloy <jmolloy@google.com>
0 commit comments