[AArch64][RegisterBankInfo] Add mapping for G_FPEXT.

This fixes http://llvm.org/PR32560. We were missing a description for
half floating point type and as a result were using the FPR 32 mapping.
Because of the size mismatch the generic code was complaining that the
default mapping is not appropriate. Fix the mapping description so that
the default mapping can be properly applied.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317287 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Quentin Colombet 2017-11-02 23:38:19 +00:00
parent 87cdca2231
commit d8375d7368
4 changed files with 193 additions and 1 deletions

View File

@ -98,6 +98,18 @@ RegisterBankInfo::ValueMapping AArch64GenRegisterBankInfo::ValMappings[]{
// LastCrossRegCpyIdx.
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1},
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1},
// 41: FPExt: 16 to 32. <-- This must match FPExt16To32Idx.
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1},
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1},
// 43: FPExt: 16 to 32. <-- This must match FPExt16To64Idx.
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1},
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1},
// 45: FPExt: 32 to 64. <-- This must match FPExt32To64Idx.
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1},
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1},
// 47: FPExt vector: 64 to 128. <-- This must match FPExt64To128Idx.
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1},
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1},
};
bool AArch64GenRegisterBankInfo::checkPartialMap(unsigned Idx,
@ -217,4 +229,35 @@ AArch64GenRegisterBankInfo::getCopyMapping(unsigned DstBankID,
ValMappingIdx <= LastCrossRegCpyIdx && "Mapping out of bound");
return &ValMappings[ValMappingIdx];
}
const RegisterBankInfo::ValueMapping *
AArch64GenRegisterBankInfo::getFPExtMapping(unsigned DstSize,
unsigned SrcSize) {
// We support:
// - For Scalar:
// - 16 to 32.
// - 16 to 64.
// - 32 to 64.
// => FPR 16 to FPR 32|64
// => FPR 32 to FPR 64
// - For vectors:
// - v4f16 to v4f32
// - v2f32 to v2f64
// => FPR 64 to FPR 128
// Check that we have been asked sensible sizes.
if (SrcSize == 16) {
assert((DstSize == 32 || DstSize == 64) && "Unexpected half extension");
if (DstSize == 32)
return &ValMappings[FPExt16To32Idx];
return &ValMappings[FPExt16To64Idx];
}
if (SrcSize == 32) {
assert(DstSize == 64 && "Unexpected float extension");
return &ValMappings[FPExt32To64Idx];
}
assert((SrcSize == 64 || DstSize == 128) && "Unexpected vector extension");
return &ValMappings[FPExt64To128Idx];
}
} // End llvm namespace.

View File

@ -175,6 +175,30 @@ AArch64RegisterBankInfo::AArch64RegisterBankInfo(const TargetRegisterInfo &TRI)
CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 64);
CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 64);
#define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize) \
do { \
unsigned PartialMapDstIdx = PMI_FPR##DstSize - PMI_Min; \
unsigned PartialMapSrcIdx = PMI_FPR##SrcSize - PMI_Min; \
(void)PartialMapDstIdx; \
(void)PartialMapSrcIdx; \
const ValueMapping *Map = getFPExtMapping(DstSize, SrcSize); \
(void)Map; \
assert(Map[0].BreakDown == \
&AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
Map[0].NumBreakDowns == 1 && "FPR" #DstSize \
" Dst is incorrectly initialized"); \
assert(Map[1].BreakDown == \
&AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
Map[1].NumBreakDowns == 1 && "FPR" #SrcSize \
" Src is incorrectly initialized"); \
\
} while (false)
CHECK_VALUEMAP_FPEXT(32, 16);
CHECK_VALUEMAP_FPEXT(64, 16);
CHECK_VALUEMAP_FPEXT(64, 32);
CHECK_VALUEMAP_FPEXT(128, 64);
assert(verify(TRI) && "Invalid register bank information");
}
@ -455,6 +479,14 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
case TargetOpcode::G_FMUL:
case TargetOpcode::G_FDIV:
return getSameKindOfOperandsMapping(MI);
case TargetOpcode::G_FPEXT: {
LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
return getInstructionMapping(
DefaultMappingID, /*Cost*/ 1,
getFPExtMapping(DstTy.getSizeInBits(), SrcTy.getSizeInBits()),
/*NumOperands*/ 2);
}
case TargetOpcode::COPY: {
unsigned DstReg = MI.getOperand(0).getReg();
unsigned SrcReg = MI.getOperand(1).getReg();

View File

@ -53,7 +53,11 @@ protected:
DistanceBetweenRegBanks = 3,
FirstCrossRegCpyIdx = 25,
LastCrossRegCpyIdx = 39,
DistanceBetweenCrossRegCpy = 2
DistanceBetweenCrossRegCpy = 2,
FPExt16To32Idx = 41,
FPExt16To64Idx = 43,
FPExt32To64Idx = 45,
FPExt64To128Idx = 47,
};
static bool checkPartialMap(unsigned Idx, unsigned ValStartIdx,
@ -82,6 +86,15 @@ protected:
static const RegisterBankInfo::ValueMapping *
getCopyMapping(unsigned DstBankID, unsigned SrcBankID, unsigned Size);
/// Get the instruction mapping for G_FPEXT.
///
/// \pre (DstSize, SrcSize) pair is one of the following:
/// (32, 16), (64, 16), (64, 32), (128, 64)
///
/// \return An InstructionMapping with statically allocated OperandsMapping.
static const RegisterBankInfo::ValueMapping *
getFPExtMapping(unsigned DstSize, unsigned SrcSize);
#define GET_TARGET_REGBANK_CLASS
#include "AArch64GenRegisterBank.inc"
};

View File

@ -92,6 +92,10 @@
store double %vres, double* %addr
ret void
}
define void @fp16Ext32() { ret void }
define void @fp16Ext64() { ret void }
define void @fp32Ext64() { ret void }
...
---
@ -742,3 +746,103 @@ body: |
RET_ReallyLR
...
---
# Make sure we map FPEXT on FPR register bank.
# CHECK-LABEL: name: fp16Ext32
name: fp16Ext32
alignment: 2
legalized: true
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
# CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
# CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' }
# CHECK-NEXT: - { id: 3, class: fpr, preferred-register: '' }
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
# CHECK: %1:gpr(s32) = COPY %w0
# CHECK-NEXT: %0:gpr(s16) = G_TRUNC %1
# %0 has been mapped to GPR, we need to repair to match FPR.
# CHECK-NEXT: %3:fpr(s16) = COPY %0
# CHECK-NEXT: %2:fpr(s32) = G_FPEXT %3
# CHECK-NEXT: %s0 = COPY %2
# CHECK-NEXT: RET_ReallyLR
body: |
bb.1:
liveins: %w0
%1(s32) = COPY %w0
%0(s16) = G_TRUNC %1(s32)
%2(s32) = G_FPEXT %0(s16)
%s0 = COPY %2(s32)
RET_ReallyLR implicit %s0
...
---
# Make sure we map FPEXT on FPR register bank.
# CHECK-LABEL: name: fp16Ext64
name: fp16Ext64
alignment: 2
legalized: true
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
# CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
# CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' }
# CHECK-NEXT: - { id: 3, class: fpr, preferred-register: '' }
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
# CHECK: %1:gpr(s32) = COPY %w0
# CHECK-NEXT: %0:gpr(s16) = G_TRUNC %1
# %0 has been mapped to GPR, we need to repair to match FPR.
# CHECK-NEXT: %3:fpr(s16) = COPY %0
# CHECK-NEXT: %2:fpr(s64) = G_FPEXT %3
# CHECK-NEXT: %d0 = COPY %2
# CHECK-NEXT: RET_ReallyLR
body: |
bb.1:
liveins: %w0
%1(s32) = COPY %w0
%0(s16) = G_TRUNC %1(s32)
%2(s64) = G_FPEXT %0(s16)
%d0 = COPY %2(s64)
RET_ReallyLR implicit %d0
...
---
# Make sure we map FPEXT on FPR register bank.
# CHECK-LABEL: name: fp32Ext64
name: fp32Ext64
alignment: 2
legalized: true
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
# CHECK-NEXT: - { id: 1, class: fpr, preferred-register: '' }
# CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' }
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
# CHECK: %0:gpr(s32) = COPY %w0
# %0 has been mapped to GPR, we need to repair to match FPR.
# CHECK-NEXT: %2:fpr(s32) = COPY %0
# CHECK-NEXT: %1:fpr(s64) = G_FPEXT %2
# CHECK-NEXT: %d0 = COPY %1
# CHECK-NEXT: RET_ReallyLR
body: |
bb.1:
liveins: %w0
%0(s32) = COPY %w0
%1(s64) = G_FPEXT %0(s32)
%d0 = COPY %1(s64)
RET_ReallyLR implicit %d0
...