| //===- AArch64GenRegisterBankInfo.def ----------------------------*- C++ -*-==// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// \file |
| /// This file defines all the static objects used by AArch64RegisterBankInfo. |
| /// \todo This should be generated by TableGen. |
| //===----------------------------------------------------------------------===// |
| |
| namespace llvm { |
| RegisterBankInfo::PartialMapping AArch64GenRegisterBankInfo::PartMappings[]{ |
| /* StartIdx, Length, RegBank */ |
| // 0: FPR 16-bit value. |
| {0, 16, AArch64::FPRRegBank}, |
| // 1: FPR 32-bit value. |
| {0, 32, AArch64::FPRRegBank}, |
| // 2: FPR 64-bit value. |
| {0, 64, AArch64::FPRRegBank}, |
| // 3: FPR 128-bit value. |
| {0, 128, AArch64::FPRRegBank}, |
| // 4: FPR 256-bit value. |
| {0, 256, AArch64::FPRRegBank}, |
| // 5: FPR 512-bit value. |
| {0, 512, AArch64::FPRRegBank}, |
| // 6: GPR 32-bit value. |
| {0, 32, AArch64::GPRRegBank}, |
| // 7: GPR 64-bit value. |
| {0, 64, AArch64::GPRRegBank}, |
| }; |
| |
| // ValueMappings. |
| RegisterBankInfo::ValueMapping AArch64GenRegisterBankInfo::ValMappings[]{ |
| /* BreakDown, NumBreakDowns */ |
| // 0: invalid |
| {nullptr, 0}, |
| // 3-operands instructions (all binary operations should end up with one of |
| // those mapping). |
| // 1: FPR 16-bit value. <-- This must match First3OpsIdx. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1}, |
| // 4: FPR 32-bit value. <-- This must match First3OpsIdx. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| // 7: FPR 64-bit value. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| // 10: FPR 128-bit value. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1}, |
| // 13: FPR 256-bit value. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1}, |
| // 16: FPR 512-bit value. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, |
| // 19: GPR 32-bit value. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| // 22: GPR 64-bit value. <-- This must match Last3OpsIdx. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| // Cross register bank copies. |
| // 25: FPR 16-bit value to GPR 16-bit. <-- This must match |
| // FirstCrossRegCpyIdx. |
| // Note: This is the kind of copy we see with physical registers. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| // 27: FPR 32-bit value to GPR 32-bit value. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| // 29: FPR 64-bit value to GPR 64-bit value. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| // 31: FPR 128-bit value to GPR 128-bit value (invalid) |
| {nullptr, 1}, |
| {nullptr, 1}, |
| // 33: FPR 256-bit value to GPR 256-bit value (invalid) |
| {nullptr, 1}, |
| {nullptr, 1}, |
| // 35: FPR 512-bit value to GPR 512-bit value (invalid) |
| {nullptr, 1}, |
| {nullptr, 1}, |
| // 37: GPR 32-bit value to FPR 32-bit value. |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| // 39: GPR 64-bit value to FPR 64-bit value. <-- This must match |
| // 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}, |
| // 49: Shift scalar with 64 bit shift imm |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| }; |
| |
| bool AArch64GenRegisterBankInfo::checkPartialMap(unsigned Idx, |
| unsigned ValStartIdx, |
| unsigned ValLength, |
| const RegisterBank &RB) { |
| const PartialMapping &Map = PartMappings[Idx - PartialMappingIdx::PMI_Min]; |
| return Map.StartIdx == ValStartIdx && Map.Length == ValLength && |
| Map.RegBank == &RB; |
| } |
| |
| bool AArch64GenRegisterBankInfo::checkValueMapImpl(unsigned Idx, |
| unsigned FirstInBank, |
| unsigned Size, |
| unsigned Offset) { |
| unsigned PartialMapBaseIdx = Idx - PartialMappingIdx::PMI_Min; |
| const ValueMapping &Map = |
| AArch64GenRegisterBankInfo::getValueMapping((PartialMappingIdx)FirstInBank, Size)[Offset]; |
| return Map.BreakDown == &PartMappings[PartialMapBaseIdx] && |
| Map.NumBreakDowns == 1; |
| } |
| |
| bool AArch64GenRegisterBankInfo::checkPartialMappingIdx( |
| PartialMappingIdx FirstAlias, PartialMappingIdx LastAlias, |
| ArrayRef<PartialMappingIdx> Order) { |
| if (Order.front() != FirstAlias) |
| return false; |
| if (Order.back() != LastAlias) |
| return false; |
| if (Order.front() > Order.back()) |
| return false; |
| |
| PartialMappingIdx Previous = Order.front(); |
| bool First = true; |
| for (const auto &Current : Order) { |
| if (First) { |
| First = false; |
| continue; |
| } |
| if (Previous + 1 != Current) |
| return false; |
| Previous = Current; |
| } |
| return true; |
| } |
| |
| unsigned AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(unsigned RBIdx, |
| unsigned Size) { |
| if (RBIdx == PMI_FirstGPR) { |
| if (Size <= 32) |
| return 0; |
| if (Size <= 64) |
| return 1; |
| return -1; |
| } |
| if (RBIdx == PMI_FirstFPR) { |
| if (Size <= 16) |
| return 0; |
| if (Size <= 32) |
| return 1; |
| if (Size <= 64) |
| return 2; |
| if (Size <= 128) |
| return 3; |
| if (Size <= 256) |
| return 4; |
| if (Size <= 512) |
| return 5; |
| return -1; |
| } |
| return -1; |
| } |
| |
| const RegisterBankInfo::ValueMapping * |
| AArch64GenRegisterBankInfo::getValueMapping(PartialMappingIdx RBIdx, |
| unsigned Size) { |
| assert(RBIdx != PartialMappingIdx::PMI_None && "No mapping needed for that"); |
| unsigned BaseIdxOffset = getRegBankBaseIdxOffset(RBIdx, Size); |
| if (BaseIdxOffset == -1u) |
| return &ValMappings[InvalidIdx]; |
| |
| unsigned ValMappingIdx = |
| First3OpsIdx + (RBIdx - PartialMappingIdx::PMI_Min + BaseIdxOffset) * |
| ValueMappingIdx::DistanceBetweenRegBanks; |
| assert(ValMappingIdx >= First3OpsIdx && ValMappingIdx <= Last3OpsIdx && |
| "Mapping out of bound"); |
| |
| return &ValMappings[ValMappingIdx]; |
| } |
| |
| AArch64GenRegisterBankInfo::PartialMappingIdx |
| AArch64GenRegisterBankInfo::BankIDToCopyMapIdx[]{ |
| PMI_None, // CCR |
| PMI_FirstFPR, // FPR |
| PMI_FirstGPR, // GPR |
| }; |
| |
| const RegisterBankInfo::ValueMapping * |
| AArch64GenRegisterBankInfo::getCopyMapping(unsigned DstBankID, |
| unsigned SrcBankID, unsigned Size) { |
| assert(DstBankID < AArch64::NumRegisterBanks && "Invalid bank ID"); |
| assert(SrcBankID < AArch64::NumRegisterBanks && "Invalid bank ID"); |
| PartialMappingIdx DstRBIdx = BankIDToCopyMapIdx[DstBankID]; |
| PartialMappingIdx SrcRBIdx = BankIDToCopyMapIdx[SrcBankID]; |
| assert(DstRBIdx != PMI_None && "No such mapping"); |
| assert(SrcRBIdx != PMI_None && "No such mapping"); |
| |
| if (DstRBIdx == SrcRBIdx) |
| return getValueMapping(DstRBIdx, Size); |
| |
| assert(Size <= 64 && "GPR cannot handle that size"); |
| unsigned ValMappingIdx = |
| FirstCrossRegCpyIdx + |
| (DstRBIdx - PMI_Min + getRegBankBaseIdxOffset(DstRBIdx, Size)) * |
| ValueMappingIdx::DistanceBetweenCrossRegCpy; |
| assert(ValMappingIdx >= FirstCrossRegCpyIdx && |
| 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. |