Skip to content

[AArch64][SVE] Improve fixed-length addressing modes. #129732

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

Merged
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions clang/test/CodeGen/AArch64/sve-vector-bits-codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,9 @@

void func(int *restrict a, int *restrict b) {
// CHECK-LABEL: func
// CHECK256-COUNT-1: str
// CHECK256-COUNT-7: st1w
// CHECK512-COUNT-1: str
// CHECK512-COUNT-3: st1w
// CHECK1024-COUNT-1: str
// CHECK1024-COUNT-1: st1w
// CHECK256-COUNT-8: str
// CHECK512-COUNT-4: str
// CHECK1024-COUNT-2: str
// CHECK2048-COUNT-1: st1w
#pragma clang loop vectorize(enable)
for (int i = 0; i < 64; ++i)
Expand Down
18 changes: 16 additions & 2 deletions llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7380,12 +7380,26 @@ bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root, SDValue N,
return false;

SDValue VScale = N.getOperand(1);
if (VScale.getOpcode() != ISD::VSCALE)
int64_t MulImm = std::numeric_limits<int64_t>::max();
if (VScale.getOpcode() == ISD::VSCALE) {
MulImm = cast<ConstantSDNode>(VScale.getOperand(0))->getSExtValue();
} else if (auto C = dyn_cast<ConstantSDNode>(VScale)) {
int64_t ByteOffset = C->getSExtValue();
const auto KnownVScale =
Subtarget->getSVEVectorSizeInBits() / AArch64::SVEBitsPerBlock;

if (!KnownVScale || ByteOffset % KnownVScale != 0)
return false;

MulImm = ByteOffset / KnownVScale;
} else
return false;

assert(MulImm != std::numeric_limits<int64_t>::max() &&
"Uninitialized MulImm.");

TypeSize TS = MemVT.getSizeInBits();
int64_t MemWidthBytes = static_cast<int64_t>(TS.getKnownMinValue()) / 8;
int64_t MulImm = cast<ConstantSDNode>(VScale.getOperand(0))->getSExtValue();

if ((MulImm % MemWidthBytes) != 0)
return false;
Expand Down
13 changes: 12 additions & 1 deletion llvm/lib/Target/AArch64/AArch64Subtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
void mirFileLoaded(MachineFunction &MF) const override;

// Return the known range for the bit length of SVE data registers. A value
// of 0 means nothing is known about that particular limit beyong what's
// of 0 means nothing is known about that particular limit beyond what's
// implied by the architecture.
unsigned getMaxSVEVectorSizeInBits() const {
assert(isSVEorStreamingSVEAvailable() &&
Expand All @@ -405,6 +405,17 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
return MinSVEVectorSizeInBits;
}

// Return the known bit length of SVE data registers. A value of 0 means the
// length is unkown beyond what's implied by the architecture.
unsigned getSVEVectorSizeInBits() const {
assert(isSVEorStreamingSVEAvailable() &&
"Tried to get SVE vector length without SVE support!");
if (MaxSVEVectorSizeInBits &&
MinSVEVectorSizeInBits == MaxSVEVectorSizeInBits)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be just MinSVEVectorSizeInBits == MaxSVEVectorSizeInBits given that returning zero when both are zero is valid?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for the suggestion; that looks much better.
Should we let through the case !MinSVEVectorSizeInBits && MaxSVEVectorSizeInBits == 128 too?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this can happen outside of handwritten IR but otherwise it sounds like a reasonable suggestion to me.

Copy link
Contributor Author

@rj-jesus rj-jesus Mar 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left it as is for now due to the lack of a motivating example and to keep it consistent with getMinSVEVectorSizeInBits/getMaxSVEVectorSizeInBits, which presumably could return 128/2048 as the architecture bounds and avoid this problem altogether. Please let me know if you'd rather I add it.

I'll let the tests run and assuming they are OK merge it.

return MaxSVEVectorSizeInBits;
return 0;
}

bool useSVEForFixedLengthVectors() const {
if (!isSVEorStreamingSVEAvailable())
return false;
Expand Down
Loading