Skip to content

[AArch64][GlobalISel] Add support for extending indexed loads. #70373

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 1 commit into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
91 changes: 91 additions & 0 deletions llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ class AArch64InstructionSelector : public InstructionSelector {
bool selectMOPS(MachineInstr &I, MachineRegisterInfo &MRI);
bool selectUSMovFromExtend(MachineInstr &I, MachineRegisterInfo &MRI);

bool selectIndexedExtLoad(MachineInstr &I, MachineRegisterInfo &MRI);
bool selectIndexedLoad(MachineInstr &I, MachineRegisterInfo &MRI);
bool selectIndexedStore(GIndexedStore &I, MachineRegisterInfo &MRI);

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

case TargetOpcode::G_INDEXED_ZEXTLOAD:
case TargetOpcode::G_INDEXED_SEXTLOAD:
return selectIndexedExtLoad(I, MRI);
case TargetOpcode::G_INDEXED_LOAD:
return selectIndexedLoad(I, MRI);
case TargetOpcode::G_INDEXED_STORE:
Expand Down Expand Up @@ -5648,6 +5652,93 @@ MachineInstr *AArch64InstructionSelector::tryAdvSIMDModImmFP(
return &*Mov;
}

bool AArch64InstructionSelector::selectIndexedExtLoad(
MachineInstr &MI, MachineRegisterInfo &MRI) {
auto &ExtLd = cast<GIndexedExtLoad>(MI);
Register Dst = ExtLd.getDstReg();
Register WriteBack = ExtLd.getWritebackReg();
Register Base = ExtLd.getBaseReg();
Register Offset = ExtLd.getOffsetReg();
LLT Ty = MRI.getType(Dst);
assert(Ty.getSizeInBits() <= 64); // Only for scalar GPRs.
unsigned MemSizeBits = ExtLd.getMMO().getMemoryType().getSizeInBits();
bool IsPre = ExtLd.isPre();
bool IsSExt = isa<GIndexedSExtLoad>(ExtLd);
bool InsertIntoXReg = false;
bool IsDst64 = Ty.getSizeInBits() == 64;

unsigned Opc = 0;
LLT NewLdDstTy;
LLT s32 = LLT::scalar(32);
LLT s64 = LLT::scalar(64);

if (MemSizeBits == 8) {
if (IsSExt) {
if (IsDst64)
Opc = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
else
Opc = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
NewLdDstTy = IsDst64 ? s64 : s32;
} else {
Opc = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
InsertIntoXReg = IsDst64;
NewLdDstTy = s32;
}
} else if (MemSizeBits == 16) {
if (IsSExt) {
if (IsDst64)
Opc = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
else
Opc = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
NewLdDstTy = IsDst64 ? s64 : s32;
} else {
Opc = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
InsertIntoXReg = IsDst64;
NewLdDstTy = s32;
}
} else if (MemSizeBits == 32) {
if (IsSExt) {
Opc = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
NewLdDstTy = s64;
} else {
Opc = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
InsertIntoXReg = IsDst64;
NewLdDstTy = s32;
}
} else {
llvm_unreachable("Unexpected size for indexed load");
}

if (RBI.getRegBank(Dst, MRI, TRI)->getID() == AArch64::FPRRegBankID)
return false; // We should be on gpr.

auto Cst = getIConstantVRegVal(Offset, MRI);
if (!Cst)
return false; // Shouldn't happen, but just in case.

auto LdMI = MIB.buildInstr(Opc, {WriteBack, NewLdDstTy}, {Base})
.addImm(Cst->getSExtValue());
LdMI.cloneMemRefs(ExtLd);
constrainSelectedInstRegOperands(*LdMI, TII, TRI, RBI);

Choose a reason for hiding this comment

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

You ignore the false.

Choose a reason for hiding this comment

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

At least constrainSelectedInstRegOperands should be [[nodiscard]].

// Make sure to select the load with the MemTy as the dest type, and then
// insert into X reg if needed.
if (InsertIntoXReg) {
// Generate a SUBREG_TO_REG.
auto SubToReg = MIB.buildInstr(TargetOpcode::SUBREG_TO_REG, {Dst}, {})
.addImm(0)
.addUse(LdMI.getReg(1))
.addImm(AArch64::sub_32);
RBI.constrainGenericRegister(SubToReg.getReg(0), AArch64::GPR64RegClass,
MRI);
} else {
auto Copy = MIB.buildCopy(Dst, LdMI.getReg(1));
selectCopy(*Copy, TII, MRI, TRI, RBI);

Choose a reason for hiding this comment

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

You ignore the false.

}
MI.eraseFromParent();

return true;
}

bool AArch64InstructionSelector::selectIndexedLoad(MachineInstr &MI,
MachineRegisterInfo &MRI) {
// TODO: extending loads.
Expand Down
19 changes: 18 additions & 1 deletion llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,24 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.legalIf(IndexedLoadBasicPred)
.unsupported();
getActionDefinitionsBuilder({G_INDEXED_SEXTLOAD, G_INDEXED_ZEXTLOAD})
.unsupported(); // TODO: implement
.unsupportedIf(
atomicOrderingAtLeastOrStrongerThan(0, AtomicOrdering::Unordered))
.legalIf(all(typeInSet(0, {s16, s32, s64}),
LegalityPredicate([=](const LegalityQuery &Q) {
LLT LdTy = Q.Types[0];
LLT PtrTy = Q.Types[1];
LLT MemTy = Q.MMODescrs[0].MemoryTy;
if (PtrTy != p0)
return false;
if (LdTy == s16)
return MemTy == s8;
if (LdTy == s32)
return MemTy == s8 || MemTy == s16;
if (LdTy == s64)
return MemTy == s8 || MemTy == s16 || MemTy == s32;
return false;
})))
.unsupported();

// Constants
getActionDefinitionsBuilder(G_CONSTANT)
Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -887,9 +887,12 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
break;
}
break;
case TargetOpcode::G_INDEXED_LOAD:
case TargetOpcode::G_INDEXED_SEXTLOAD:
case TargetOpcode::G_INDEXED_ZEXTLOAD: {
case TargetOpcode::G_INDEXED_ZEXTLOAD:
// These should always be GPR.
OpRegBankIdx[0] = PMI_FirstGPR;
break;
case TargetOpcode::G_INDEXED_LOAD: {
if (isLoadFromFPType(MI))
OpRegBankIdx[0] = PMI_FirstFPR;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,83 @@ body: |
$x0 = COPY %writeback
RET_ReallyLR implicit $x0
...
---
name: post_zextload_s8_to_s64
body: |
bb.0:
liveins: $x0

; CHECK-LABEL: name: post_zextload_s8_to_s64
; CHECK: liveins: $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %ptr:_(p0) = COPY $x0
; CHECK-NEXT: %offset:_(s64) = G_CONSTANT i64 8
; CHECK-NEXT: %dst:_(s64), %writeback:_(p0) = G_INDEXED_ZEXTLOAD %ptr, %offset(s64), 0 :: (load (s8), align 8)
; CHECK-NEXT: $x0 = COPY %writeback(p0)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%ptr:_(p0) = COPY $x0
%offset:_(s64) = G_CONSTANT i64 8
%dst:_(s64), %writeback:_(p0) = G_INDEXED_ZEXTLOAD %ptr, %offset, 0 :: (load (s8), align 8)
$x0 = COPY %writeback
RET_ReallyLR implicit $x0
...
---
name: post_sextload_s8_to_s64
body: |
bb.0:
liveins: $x0

; CHECK-LABEL: name: post_sextload_s8_to_s64
; CHECK: liveins: $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %ptr:_(p0) = COPY $x0
; CHECK-NEXT: %offset:_(s64) = G_CONSTANT i64 8
; CHECK-NEXT: %dst:_(s64), %writeback:_(p0) = G_INDEXED_SEXTLOAD %ptr, %offset(s64), 0 :: (load (s8), align 8)
; CHECK-NEXT: $x0 = COPY %writeback(p0)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%ptr:_(p0) = COPY $x0
%offset:_(s64) = G_CONSTANT i64 8
%dst:_(s64), %writeback:_(p0) = G_INDEXED_SEXTLOAD %ptr, %offset, 0 :: (load (s8), align 8)
$x0 = COPY %writeback
RET_ReallyLR implicit $x0
...
---
name: post_sextload_s32_to_s64
body: |
bb.0:
liveins: $x0

; CHECK-LABEL: name: post_sextload_s32_to_s64
; CHECK: liveins: $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %ptr:_(p0) = COPY $x0
; CHECK-NEXT: %offset:_(s64) = G_CONSTANT i64 8
; CHECK-NEXT: %dst:_(s64), %writeback:_(p0) = G_INDEXED_SEXTLOAD %ptr, %offset(s64), 0 :: (load (s32), align 8)
; CHECK-NEXT: $x0 = COPY %writeback(p0)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%ptr:_(p0) = COPY $x0
%offset:_(s64) = G_CONSTANT i64 8
%dst:_(s64), %writeback:_(p0) = G_INDEXED_SEXTLOAD %ptr, %offset, 0 :: (load (s32), align 8)
$x0 = COPY %writeback
RET_ReallyLR implicit $x0
...
---
name: post_zextload_s32_to_s64
body: |
bb.0:
liveins: $x0

; CHECK-LABEL: name: post_zextload_s32_to_s64
; CHECK: liveins: $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %ptr:_(p0) = COPY $x0
; CHECK-NEXT: %offset:_(s64) = G_CONSTANT i64 8
; CHECK-NEXT: %dst:_(s64), %writeback:_(p0) = G_INDEXED_ZEXTLOAD %ptr, %offset(s64), 0 :: (load (s32), align 8)
; CHECK-NEXT: $x0 = COPY %writeback(p0)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%ptr:_(p0) = COPY $x0
%offset:_(s64) = G_CONSTANT i64 8
%dst:_(s64), %writeback:_(p0) = G_INDEXED_ZEXTLOAD %ptr, %offset, 0 :: (load (s32), align 8)
$x0 = COPY %writeback
RET_ReallyLR implicit $x0
...
Loading