Skip to content

Commit c9e8b73

Browse files
authored
[AArch64][GlobalISel] Add support for extending indexed loads. (#70373)
1 parent e3ecdf7 commit c9e8b73

File tree

5 files changed

+269
-273
lines changed

5 files changed

+269
-273
lines changed

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ class AArch64InstructionSelector : public InstructionSelector {
230230
bool selectMOPS(MachineInstr &I, MachineRegisterInfo &MRI);
231231
bool selectUSMovFromExtend(MachineInstr &I, MachineRegisterInfo &MRI);
232232

233+
bool selectIndexedExtLoad(MachineInstr &I, MachineRegisterInfo &MRI);
233234
bool selectIndexedLoad(MachineInstr &I, MachineRegisterInfo &MRI);
234235
bool selectIndexedStore(GIndexedStore &I, MachineRegisterInfo &MRI);
235236

@@ -3047,6 +3048,9 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
30473048
return constrainSelectedInstRegOperands(*LoadStore, TII, TRI, RBI);
30483049
}
30493050

3051+
case TargetOpcode::G_INDEXED_ZEXTLOAD:
3052+
case TargetOpcode::G_INDEXED_SEXTLOAD:
3053+
return selectIndexedExtLoad(I, MRI);
30503054
case TargetOpcode::G_INDEXED_LOAD:
30513055
return selectIndexedLoad(I, MRI);
30523056
case TargetOpcode::G_INDEXED_STORE:
@@ -5648,6 +5652,93 @@ MachineInstr *AArch64InstructionSelector::tryAdvSIMDModImmFP(
56485652
return &*Mov;
56495653
}
56505654

5655+
bool AArch64InstructionSelector::selectIndexedExtLoad(
5656+
MachineInstr &MI, MachineRegisterInfo &MRI) {
5657+
auto &ExtLd = cast<GIndexedExtLoad>(MI);
5658+
Register Dst = ExtLd.getDstReg();
5659+
Register WriteBack = ExtLd.getWritebackReg();
5660+
Register Base = ExtLd.getBaseReg();
5661+
Register Offset = ExtLd.getOffsetReg();
5662+
LLT Ty = MRI.getType(Dst);
5663+
assert(Ty.getSizeInBits() <= 64); // Only for scalar GPRs.
5664+
unsigned MemSizeBits = ExtLd.getMMO().getMemoryType().getSizeInBits();
5665+
bool IsPre = ExtLd.isPre();
5666+
bool IsSExt = isa<GIndexedSExtLoad>(ExtLd);
5667+
bool InsertIntoXReg = false;
5668+
bool IsDst64 = Ty.getSizeInBits() == 64;
5669+
5670+
unsigned Opc = 0;
5671+
LLT NewLdDstTy;
5672+
LLT s32 = LLT::scalar(32);
5673+
LLT s64 = LLT::scalar(64);
5674+
5675+
if (MemSizeBits == 8) {
5676+
if (IsSExt) {
5677+
if (IsDst64)
5678+
Opc = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
5679+
else
5680+
Opc = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
5681+
NewLdDstTy = IsDst64 ? s64 : s32;
5682+
} else {
5683+
Opc = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
5684+
InsertIntoXReg = IsDst64;
5685+
NewLdDstTy = s32;
5686+
}
5687+
} else if (MemSizeBits == 16) {
5688+
if (IsSExt) {
5689+
if (IsDst64)
5690+
Opc = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
5691+
else
5692+
Opc = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
5693+
NewLdDstTy = IsDst64 ? s64 : s32;
5694+
} else {
5695+
Opc = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
5696+
InsertIntoXReg = IsDst64;
5697+
NewLdDstTy = s32;
5698+
}
5699+
} else if (MemSizeBits == 32) {
5700+
if (IsSExt) {
5701+
Opc = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
5702+
NewLdDstTy = s64;
5703+
} else {
5704+
Opc = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
5705+
InsertIntoXReg = IsDst64;
5706+
NewLdDstTy = s32;
5707+
}
5708+
} else {
5709+
llvm_unreachable("Unexpected size for indexed load");
5710+
}
5711+
5712+
if (RBI.getRegBank(Dst, MRI, TRI)->getID() == AArch64::FPRRegBankID)
5713+
return false; // We should be on gpr.
5714+
5715+
auto Cst = getIConstantVRegVal(Offset, MRI);
5716+
if (!Cst)
5717+
return false; // Shouldn't happen, but just in case.
5718+
5719+
auto LdMI = MIB.buildInstr(Opc, {WriteBack, NewLdDstTy}, {Base})
5720+
.addImm(Cst->getSExtValue());
5721+
LdMI.cloneMemRefs(ExtLd);
5722+
constrainSelectedInstRegOperands(*LdMI, TII, TRI, RBI);
5723+
// Make sure to select the load with the MemTy as the dest type, and then
5724+
// insert into X reg if needed.
5725+
if (InsertIntoXReg) {
5726+
// Generate a SUBREG_TO_REG.
5727+
auto SubToReg = MIB.buildInstr(TargetOpcode::SUBREG_TO_REG, {Dst}, {})
5728+
.addImm(0)
5729+
.addUse(LdMI.getReg(1))
5730+
.addImm(AArch64::sub_32);
5731+
RBI.constrainGenericRegister(SubToReg.getReg(0), AArch64::GPR64RegClass,
5732+
MRI);
5733+
} else {
5734+
auto Copy = MIB.buildCopy(Dst, LdMI.getReg(1));
5735+
selectCopy(*Copy, TII, MRI, TRI, RBI);
5736+
}
5737+
MI.eraseFromParent();
5738+
5739+
return true;
5740+
}
5741+
56515742
bool AArch64InstructionSelector::selectIndexedLoad(MachineInstr &MI,
56525743
MachineRegisterInfo &MRI) {
56535744
// TODO: extending loads.

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,24 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
459459
.legalIf(IndexedLoadBasicPred)
460460
.unsupported();
461461
getActionDefinitionsBuilder({G_INDEXED_SEXTLOAD, G_INDEXED_ZEXTLOAD})
462-
.unsupported(); // TODO: implement
462+
.unsupportedIf(
463+
atomicOrderingAtLeastOrStrongerThan(0, AtomicOrdering::Unordered))
464+
.legalIf(all(typeInSet(0, {s16, s32, s64}),
465+
LegalityPredicate([=](const LegalityQuery &Q) {
466+
LLT LdTy = Q.Types[0];
467+
LLT PtrTy = Q.Types[1];
468+
LLT MemTy = Q.MMODescrs[0].MemoryTy;
469+
if (PtrTy != p0)
470+
return false;
471+
if (LdTy == s16)
472+
return MemTy == s8;
473+
if (LdTy == s32)
474+
return MemTy == s8 || MemTy == s16;
475+
if (LdTy == s64)
476+
return MemTy == s8 || MemTy == s16 || MemTy == s32;
477+
return false;
478+
})))
479+
.unsupported();
463480

464481
// Constants
465482
getActionDefinitionsBuilder(G_CONSTANT)

llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -887,9 +887,12 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
887887
break;
888888
}
889889
break;
890-
case TargetOpcode::G_INDEXED_LOAD:
891890
case TargetOpcode::G_INDEXED_SEXTLOAD:
892-
case TargetOpcode::G_INDEXED_ZEXTLOAD: {
891+
case TargetOpcode::G_INDEXED_ZEXTLOAD:
892+
// These should always be GPR.
893+
OpRegBankIdx[0] = PMI_FirstGPR;
894+
break;
895+
case TargetOpcode::G_INDEXED_LOAD: {
893896
if (isLoadFromFPType(MI))
894897
OpRegBankIdx[0] = PMI_FirstFPR;
895898
break;

llvm/test/CodeGen/AArch64/GlobalISel/legalize-indexed-load-stores.mir

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,83 @@ body: |
109109
$x0 = COPY %writeback
110110
RET_ReallyLR implicit $x0
111111
...
112+
---
113+
name: post_zextload_s8_to_s64
114+
body: |
115+
bb.0:
116+
liveins: $x0
117+
118+
; CHECK-LABEL: name: post_zextload_s8_to_s64
119+
; CHECK: liveins: $x0
120+
; CHECK-NEXT: {{ $}}
121+
; CHECK-NEXT: %ptr:_(p0) = COPY $x0
122+
; CHECK-NEXT: %offset:_(s64) = G_CONSTANT i64 8
123+
; CHECK-NEXT: %dst:_(s64), %writeback:_(p0) = G_INDEXED_ZEXTLOAD %ptr, %offset(s64), 0 :: (load (s8), align 8)
124+
; CHECK-NEXT: $x0 = COPY %writeback(p0)
125+
; CHECK-NEXT: RET_ReallyLR implicit $x0
126+
%ptr:_(p0) = COPY $x0
127+
%offset:_(s64) = G_CONSTANT i64 8
128+
%dst:_(s64), %writeback:_(p0) = G_INDEXED_ZEXTLOAD %ptr, %offset, 0 :: (load (s8), align 8)
129+
$x0 = COPY %writeback
130+
RET_ReallyLR implicit $x0
131+
...
132+
---
133+
name: post_sextload_s8_to_s64
134+
body: |
135+
bb.0:
136+
liveins: $x0
137+
138+
; CHECK-LABEL: name: post_sextload_s8_to_s64
139+
; CHECK: liveins: $x0
140+
; CHECK-NEXT: {{ $}}
141+
; CHECK-NEXT: %ptr:_(p0) = COPY $x0
142+
; CHECK-NEXT: %offset:_(s64) = G_CONSTANT i64 8
143+
; CHECK-NEXT: %dst:_(s64), %writeback:_(p0) = G_INDEXED_SEXTLOAD %ptr, %offset(s64), 0 :: (load (s8), align 8)
144+
; CHECK-NEXT: $x0 = COPY %writeback(p0)
145+
; CHECK-NEXT: RET_ReallyLR implicit $x0
146+
%ptr:_(p0) = COPY $x0
147+
%offset:_(s64) = G_CONSTANT i64 8
148+
%dst:_(s64), %writeback:_(p0) = G_INDEXED_SEXTLOAD %ptr, %offset, 0 :: (load (s8), align 8)
149+
$x0 = COPY %writeback
150+
RET_ReallyLR implicit $x0
151+
...
152+
---
153+
name: post_sextload_s32_to_s64
154+
body: |
155+
bb.0:
156+
liveins: $x0
157+
158+
; CHECK-LABEL: name: post_sextload_s32_to_s64
159+
; CHECK: liveins: $x0
160+
; CHECK-NEXT: {{ $}}
161+
; CHECK-NEXT: %ptr:_(p0) = COPY $x0
162+
; CHECK-NEXT: %offset:_(s64) = G_CONSTANT i64 8
163+
; CHECK-NEXT: %dst:_(s64), %writeback:_(p0) = G_INDEXED_SEXTLOAD %ptr, %offset(s64), 0 :: (load (s32), align 8)
164+
; CHECK-NEXT: $x0 = COPY %writeback(p0)
165+
; CHECK-NEXT: RET_ReallyLR implicit $x0
166+
%ptr:_(p0) = COPY $x0
167+
%offset:_(s64) = G_CONSTANT i64 8
168+
%dst:_(s64), %writeback:_(p0) = G_INDEXED_SEXTLOAD %ptr, %offset, 0 :: (load (s32), align 8)
169+
$x0 = COPY %writeback
170+
RET_ReallyLR implicit $x0
171+
...
172+
---
173+
name: post_zextload_s32_to_s64
174+
body: |
175+
bb.0:
176+
liveins: $x0
177+
178+
; CHECK-LABEL: name: post_zextload_s32_to_s64
179+
; CHECK: liveins: $x0
180+
; CHECK-NEXT: {{ $}}
181+
; CHECK-NEXT: %ptr:_(p0) = COPY $x0
182+
; CHECK-NEXT: %offset:_(s64) = G_CONSTANT i64 8
183+
; CHECK-NEXT: %dst:_(s64), %writeback:_(p0) = G_INDEXED_ZEXTLOAD %ptr, %offset(s64), 0 :: (load (s32), align 8)
184+
; CHECK-NEXT: $x0 = COPY %writeback(p0)
185+
; CHECK-NEXT: RET_ReallyLR implicit $x0
186+
%ptr:_(p0) = COPY $x0
187+
%offset:_(s64) = G_CONSTANT i64 8
188+
%dst:_(s64), %writeback:_(p0) = G_INDEXED_ZEXTLOAD %ptr, %offset, 0 :: (load (s32), align 8)
189+
$x0 = COPY %writeback
190+
RET_ReallyLR implicit $x0
191+
...

0 commit comments

Comments
 (0)