This is an archive of the discontinued LLVM Phabricator instance.

[RISCV] Scalarize constant stores of fixed vectors up to 32 bits
ClosedPublic

Authored by luke on May 23 2023, 8:12 AM.

Details

Summary

For stores of small fixed-length vector constants, we can store them
with a sequence of lui/addi/sh/sw to avoid the cost of building the
vector and the vsetivli toggle.

Note that this only handles vectors that are 32 bits or smaller, but
could be expanded to 64 bits if we know that the constant
materialization cost isn't too high.

Diff Detail

Event Timeline

luke created this revision.May 23 2023, 8:12 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 23 2023, 8:12 AM
luke requested review of this revision.May 23 2023, 8:12 AM
luke added inline comments.
llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll
114–122

I'm wondering if we should detect constants that are sequences (BuildVectorSDNode::isConstantSequence) to prevent this.

luke updated this revision to Diff 524738.May 23 2023, 8:23 AM

Include test change

luke added inline comments.May 23 2023, 8:24 AM
llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll
114–122

Gating on if its a sequence seems to make it worse as only some of the stores end up getting scalarized, whilst some of them are kept as vectors.

reames requested changes to this revision.May 23 2023, 9:13 AM
reames added inline comments.
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
12205

Isn't this case now fully covered by the one you added? I think you can delete this.

Ah, I see the problem. Rather than checking that MemVT is less than 32 bits, you can check that the splat constant isUint<32>.

Or if you want, you can directly check materialization cost < 2 using RISCVMatInt.cpp/h

12245

isConstantSplat seems like an odd interface here. I looked for something obviously better and didn't find it though...

llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll
66–75

I think you're loosing the spirit of the test on these. This looks to be intended to exercise materialization of the vector constant, not the store of that constant to memory. Can you adjust the test to keep the prior codegen or something close to it?

You can return the values from individual tests, or use volatile stores.

This revision now requires changes to proceed.May 23 2023, 9:13 AM
luke added inline comments.May 24 2023, 2:34 AM
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
12205

Good idea about checking the constant, will do that. I kept in the zeroes case because isConstantSplat claims to not work on anything smaller than i8, and there are some test cases for i1s that we want this to work on annoyingly.

I agree that it's weird that there's not a better interface for this. Elsewhere in RISCVISelLowering.cpp its just done by hand like:

unsigned EltIdx = 0;
uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
uint64_t SplatValue = 0;
// Construct the amalgamated value which can be splatted as this larger
// vector type.
for (const auto &SeqV : Sequence) {
  if (!SeqV.isUndef())
    SplatValue |= ((cast<ConstantSDNode>(SeqV)->getZExtValue() & EltMask)
                   << (EltIdx * EltBitSize));
  EltIdx++;
}

It might actually be easier to just reuse this instead.

luke updated this revision to Diff 525108.May 24 2023, 4:50 AM

Rework how constant is calculated, rejig buildvec tests to avoid scalarization

luke marked 3 inline comments as done.May 24 2023, 4:51 AM
luke added inline comments.
llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll
66–75

Volatile stores still get scalarized so I've just returned the values in the cases that were affected

reames accepted this revision.May 24 2023, 7:11 AM

LGTM

This revision is now accepted and ready to land.May 24 2023, 7:11 AM
This revision was automatically updated to reflect the committed changes.
luke marked an inline comment as done.