Skip to content

Commit 74f5a02

Browse files
authored
Reapply "[AArch64][SVE] Improve fixed-length addressing modes. (#129732)" (#130625)
The original patch from #129732 exposed a bug in `getMemVTFromNode`, which was returning incorrect types for fixed length vectors.
1 parent 614d855 commit 74f5a02

File tree

7 files changed

+553
-58
lines changed

7 files changed

+553
-58
lines changed

clang/test/CodeGen/AArch64/sve-vector-bits-codegen.c

+3-6
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,9 @@
1313

1414
void func(int *restrict a, int *restrict b) {
1515
// CHECK-LABEL: func
16-
// CHECK256-COUNT-1: str
17-
// CHECK256-COUNT-7: st1w
18-
// CHECK512-COUNT-1: str
19-
// CHECK512-COUNT-3: st1w
20-
// CHECK1024-COUNT-1: str
21-
// CHECK1024-COUNT-1: st1w
16+
// CHECK256-COUNT-8: str
17+
// CHECK512-COUNT-4: str
18+
// CHECK1024-COUNT-2: str
2219
// CHECK2048-COUNT-1: st1w
2320
#pragma clang loop vectorize(enable)
2421
for (int i = 0; i < 64; ++i)

llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp

+32-6
Original file line numberDiff line numberDiff line change
@@ -7275,11 +7275,26 @@ static EVT getPackedVectorTypeFromPredicateType(LLVMContext &Ctx, EVT PredVT,
72757275
/// Return the EVT of the data associated to a memory operation in \p
72767276
/// Root. If such EVT cannot be retrived, it returns an invalid EVT.
72777277
static EVT getMemVTFromNode(LLVMContext &Ctx, SDNode *Root) {
7278-
if (isa<MemSDNode>(Root))
7279-
return cast<MemSDNode>(Root)->getMemoryVT();
7278+
if (auto *MemIntr = dyn_cast<MemIntrinsicSDNode>(Root))
7279+
return MemIntr->getMemoryVT();
7280+
7281+
if (isa<MemSDNode>(Root)) {
7282+
EVT MemVT = cast<MemSDNode>(Root)->getMemoryVT();
7283+
7284+
EVT DataVT;
7285+
if (auto *Load = dyn_cast<LoadSDNode>(Root))
7286+
DataVT = Load->getValueType(0);
7287+
else if (auto *Load = dyn_cast<MaskedLoadSDNode>(Root))
7288+
DataVT = Load->getValueType(0);
7289+
else if (auto *Store = dyn_cast<StoreSDNode>(Root))
7290+
DataVT = Store->getValue().getValueType();
7291+
else if (auto *Store = dyn_cast<MaskedStoreSDNode>(Root))
7292+
DataVT = Store->getValue().getValueType();
7293+
else
7294+
llvm_unreachable("Unexpected MemSDNode!");
72807295

7281-
if (isa<MemIntrinsicSDNode>(Root))
7282-
return cast<MemIntrinsicSDNode>(Root)->getMemoryVT();
7296+
return DataVT.changeVectorElementType(MemVT.getVectorElementType());
7297+
}
72837298

72847299
const unsigned Opcode = Root->getOpcode();
72857300
// For custom ISD nodes, we have to look at them individually to extract the
@@ -7380,12 +7395,23 @@ bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root, SDValue N,
73807395
return false;
73817396

73827397
SDValue VScale = N.getOperand(1);
7383-
if (VScale.getOpcode() != ISD::VSCALE)
7398+
int64_t MulImm = std::numeric_limits<int64_t>::max();
7399+
if (VScale.getOpcode() == ISD::VSCALE) {
7400+
MulImm = cast<ConstantSDNode>(VScale.getOperand(0))->getSExtValue();
7401+
} else if (auto C = dyn_cast<ConstantSDNode>(VScale)) {
7402+
int64_t ByteOffset = C->getSExtValue();
7403+
const auto KnownVScale =
7404+
Subtarget->getSVEVectorSizeInBits() / AArch64::SVEBitsPerBlock;
7405+
7406+
if (!KnownVScale || ByteOffset % KnownVScale != 0)
7407+
return false;
7408+
7409+
MulImm = ByteOffset / KnownVScale;
7410+
} else
73847411
return false;
73857412

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

73907416
if ((MulImm % MemWidthBytes) != 0)
73917417
return false;

llvm/lib/Target/AArch64/AArch64Subtarget.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
391391
void mirFileLoaded(MachineFunction &MF) const override;
392392

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

408+
// Return the known bit length of SVE data registers. A value of 0 means the
409+
// length is unkown beyond what's implied by the architecture.
410+
unsigned getSVEVectorSizeInBits() const {
411+
assert(isSVEorStreamingSVEAvailable() &&
412+
"Tried to get SVE vector length without SVE support!");
413+
if (MinSVEVectorSizeInBits == MaxSVEVectorSizeInBits)
414+
return MaxSVEVectorSizeInBits;
415+
return 0;
416+
}
417+
408418
bool useSVEForFixedLengthVectors() const {
409419
if (!isSVEorStreamingSVEAvailable())
410420
return false;

0 commit comments

Comments
 (0)