Shuffle scalable vector in CodeGen_ARM#8898
Conversation
|
With this PR and #8888, Halide tests pass without fail on host machine with SVE2 128 bits vector. I confirmed by |
|
The CI test failure below is a known issue which should be fixed by #8888. I will rebase once #8888 is merged. |
4a40326 to
9c9e621
Compare
Theoretically, these are llvm common and not ARM specific, but for now, keep it for ARM only to avoid any affect to other targets.
The workaround of checking wide_enough in get_vector_type() was causing the issue of mixing FixedVector and ScalableVector in generating a intrinsic instruction in SVE2 codegen. By this change, we select scalable vector for most of the cases. Note the workaround for vscale > 1 case will be addressed in a separate commit.
By design, LLVM shufflevector doesn't accept scalable vectors. So, we try to use llvm.vector.xx intrinsic where possible. However, those are not enough to cover wide usage of shuffles in Halide. To handle arbitrary index pattern, we decompose a shuffle operation to a sequence of multiple native shuffles, which are lowered to Arm SVE2 intrinsic TBL or TBL2. Another approach could be to perform shuffle in fixed sized vector by adding conversion between scalable vector and fixed vector. However, it seems to be only possible via load/store memory, which would presumably be poor performance. This change also includes: - Peep-hole the particular predicate pattern to emit WHILELT instruction - Shuffle 1bit type scalable vectors as 8bit with type casts - Peep-hole concat_vectors for padding to align up vector - Fix redundant broadcast in CodeGen_LLVM
Modified codegen of vector broadcast in SVE2 to emit TBL ARM intrin instead of llvm.vector.insert. Fix performance test failure of nested_vectorization_gemm
9c9e621 to
84ec0ee
Compare
|
Rebased on main to integrate #8888 |
|
@stevesuzuki-arm -- looks like there are some real LLVM integration errors. |
- Fix to cover vector_bits > 128 case appropriately - Add test target with vector_bits = 512 - W is increased to 512 because Bounds given for op_st4b_int8_x512_0 did not cover required region - Refine target compatibility check for can_run_code
alexreinking
left a comment
There was a problem hiding this comment.
See in-line comments for my smaller concerns.
I'm not sure DecomposeVectorShuffle is the right design. I think it's needlessly coupling computing the shuffle plan (which doesn't depend on the codegen backend) with generating the code for the plan (which does).
|
If it's okay with you, @stevesuzuki-arm, I can perform the refactoring I requested myself. I'll just push to this branch. |
Thank you for reviewing this large set of updates. I really appreciate it. |
|
Okay, I made all the changes I requested to DecomposeVectorShuffle... now I will look at CodeGen_ARM 🙂 |
alexreinking
left a comment
There was a problem hiding this comment.
I'd like a little bit more testing, I think. Can you point to a test that covers the new codegen without needing to run SVE2?
In case the caller of shuffle_vectors() set indices of -1, steps_for_dst_slice in shuffle_plan may be empty, which ended up with calling concat_vectors with null element. The fix is to create undef vector for that particular case. The original issue was found in correctness_interleave (transposition with sz=27).
|
@alexreinking Would you tell me if you have any suggestion for me to do in order to move this forward? |
|
Let's rebase this on main. We now have SVE2 testing through GHA and I'm inclined to accept if green. |
|
@stevesuzuki-arm -- Please check to see if the LLVM 21 failures can be easily solved. Otherwise, skip the failing tests on LLVM <22 + SVE2 |
CI failures with llvm-21 are as follows: correctness_interleave correctness_stmt_to_html correctness_predicated_store_load_single_lane Making Workaround in codegen would be tricky, so I'd prefer "we should just say we only support sve2 from llvm 22 up". |
Works for me. Skip the tests for now. In a follow-up PR, we can add a |
|
@alexreinking Can we merge this now? |
I was waiting for you to add Something like this: if (Internal::get_llvm_version() < 220 &&
get_jit_target_from_environment().has_feature(Target::SVE2)) {
printf("[SKIP] LLVM %d has known SVE backend bugs for this test.\n",
Internal::get_llvm_version());
return 0;
} |
|
Thank you for clarifying. I thought the job would be skipped in case of LLVM21. OK, I will do what you suggested. |
SVE2 backend has some LLVM issues which have been fixed in LLVM 22. For now, we skip the tests which fail due to those issues in case LLVM version < 22.
|
Just merged |
|
We might want to hold of on merging this, as this is the type of PR that can bring us a lot of headache. I think it'd be wise to first fully implement our goals in #9044, integrate those strategies here. |
By design, LLVM shufflevector doesn't accept scalable vectors.
So, we try to use llvm.vector.xx intrinsic where possible.
However, those are not enough to cover wide usage of shuffles in Halide.
To handle arbitrary index pattern, we decompose a shuffle operation
to a sequence of multiple native shuffles, which are lowered to
Arm SVE2 intrinsic TBL or TBL2.
Another approach could be to perform shuffle in fixed sized vector
by adding conversion between scalable vector and fixed vector.
However, it seems to be only possible via load/store memory,
which would presumably be poor performance.
This change also includes:
Depends on: