| 1 | //===- AArch64GenRegisterBankInfo.def ----------------------------*- C++ -*-==// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// \file |
| 9 | /// This file defines all the static objects used by AArch64RegisterBankInfo. |
| 10 | /// \todo This should be generated by TableGen. |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | namespace llvm { |
| 14 | const RegisterBankInfo::PartialMapping AArch64GenRegisterBankInfo::PartMappings[]{ |
| 15 | /* StartIdx, Length, RegBank */ |
| 16 | // 0: FPR 16-bit value. |
| 17 | {0, 16, AArch64::FPRRegBank}, |
| 18 | // 1: FPR 32-bit value. |
| 19 | {0, 32, AArch64::FPRRegBank}, |
| 20 | // 2: FPR 64-bit value. |
| 21 | {0, 64, AArch64::FPRRegBank}, |
| 22 | // 3: FPR 128-bit value. |
| 23 | {0, 128, AArch64::FPRRegBank}, |
| 24 | // 4: FPR 256-bit value. |
| 25 | {0, 256, AArch64::FPRRegBank}, |
| 26 | // 5: FPR 512-bit value. |
| 27 | {0, 512, AArch64::FPRRegBank}, |
| 28 | // 6: GPR 32-bit value. |
| 29 | {0, 32, AArch64::GPRRegBank}, |
| 30 | // 7: GPR 64-bit value. |
| 31 | {0, 64, AArch64::GPRRegBank}, |
| 32 | // 8: GPR 128-bit value. |
| 33 | {0, 128, AArch64::GPRRegBank}, |
| 34 | }; |
| 35 | |
| 36 | // ValueMappings. |
| 37 | const RegisterBankInfo::ValueMapping AArch64GenRegisterBankInfo::ValMappings[]{ |
| 38 | /* BreakDown, NumBreakDowns */ |
| 39 | // 0: invalid |
| 40 | {nullptr, 0}, |
| 41 | // 3-operands instructions (all binary operations should end up with one of |
| 42 | // those mapping). |
| 43 | // 1: FPR 16-bit value. <-- This must match First3OpsIdx. |
| 44 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1}, |
| 45 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1}, |
| 46 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1}, |
| 47 | // 4: FPR 32-bit value. <-- This must match First3OpsIdx. |
| 48 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| 49 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| 50 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| 51 | // 7: FPR 64-bit value. |
| 52 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| 53 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| 54 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| 55 | // 10: FPR 128-bit value. |
| 56 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1}, |
| 57 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1}, |
| 58 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1}, |
| 59 | // 13: FPR 256-bit value. |
| 60 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1}, |
| 61 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1}, |
| 62 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1}, |
| 63 | // 16: FPR 512-bit value. |
| 64 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, |
| 65 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, |
| 66 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, |
| 67 | // 19: GPR 32-bit value. |
| 68 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| 69 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| 70 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| 71 | // 22: GPR 64-bit value. |
| 72 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| 73 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| 74 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| 75 | // 25: GPR 128-bit value. <-- This must match Last3OpsIdx. |
| 76 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR128 - PMI_Min], 1}, |
| 77 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR128 - PMI_Min], 1}, |
| 78 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR128 - PMI_Min], 1}, |
| 79 | // Cross register bank copies. |
| 80 | // 28: FPR 16-bit value to GPR 16-bit. <-- This must match |
| 81 | // FirstCrossRegCpyIdx. |
| 82 | // Note: This is the kind of copy we see with physical registers. |
| 83 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1}, |
| 84 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| 85 | // 30: FPR 32-bit value to GPR 32-bit value. |
| 86 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| 87 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| 88 | // 32: FPR 64-bit value to GPR 64-bit value. |
| 89 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| 90 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| 91 | // 34: FPR 128-bit value to GPR 128-bit value (invalid) |
| 92 | {nullptr, 1}, |
| 93 | {nullptr, 1}, |
| 94 | // 36: FPR 256-bit value to GPR 256-bit value (invalid) |
| 95 | {nullptr, 1}, |
| 96 | {nullptr, 1}, |
| 97 | // 38: FPR 512-bit value to GPR 512-bit value (invalid) |
| 98 | {nullptr, 1}, |
| 99 | {nullptr, 1}, |
| 100 | // 40: GPR 32-bit value to FPR 32-bit value. |
| 101 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| 102 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| 103 | // 42: GPR 64-bit value to FPR 64-bit value. <-- This must match |
| 104 | // LastCrossRegCpyIdx. |
| 105 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| 106 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| 107 | // 44: FPExt: 16 to 32. <-- This must match FPExt16To32Idx. |
| 108 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| 109 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1}, |
| 110 | // 46: FPExt: 16 to 32. <-- This must match FPExt16To64Idx. |
| 111 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| 112 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR16 - PMI_Min], 1}, |
| 113 | // 48: FPExt: 32 to 64. <-- This must match FPExt32To64Idx. |
| 114 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| 115 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, |
| 116 | // 50: FPExt vector: 64 to 128. <-- This must match FPExt64To128Idx. |
| 117 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1}, |
| 118 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, |
| 119 | // 52: Shift scalar with 64 bit shift imm |
| 120 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| 121 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, |
| 122 | {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, |
| 123 | }; |
| 124 | |
| 125 | bool AArch64GenRegisterBankInfo::checkPartialMap(unsigned Idx, |
| 126 | unsigned ValStartIdx, |
| 127 | unsigned ValLength, |
| 128 | const RegisterBank &RB) { |
| 129 | const PartialMapping &Map = PartMappings[Idx - PartialMappingIdx::PMI_Min]; |
| 130 | return Map.StartIdx == ValStartIdx && Map.Length == ValLength && |
| 131 | Map.RegBank == &RB; |
| 132 | } |
| 133 | |
| 134 | bool AArch64GenRegisterBankInfo::checkValueMapImpl(unsigned Idx, |
| 135 | unsigned FirstInBank, |
| 136 | unsigned Size, |
| 137 | unsigned Offset) { |
| 138 | unsigned PartialMapBaseIdx = Idx - PartialMappingIdx::PMI_Min; |
| 139 | const ValueMapping &Map = |
| 140 | AArch64GenRegisterBankInfo::getValueMapping( |
| 141 | RBIdx: (PartialMappingIdx)FirstInBank, |
| 142 | Size: TypeSize::getFixed(ExactSize: Size))[Offset]; |
| 143 | return Map.BreakDown == &PartMappings[PartialMapBaseIdx] && |
| 144 | Map.NumBreakDowns == 1; |
| 145 | } |
| 146 | |
| 147 | bool AArch64GenRegisterBankInfo::checkPartialMappingIdx( |
| 148 | PartialMappingIdx FirstAlias, PartialMappingIdx LastAlias, |
| 149 | ArrayRef<PartialMappingIdx> Order) { |
| 150 | if (Order.front() != FirstAlias) |
| 151 | return false; |
| 152 | if (Order.back() != LastAlias) |
| 153 | return false; |
| 154 | if (Order.front() > Order.back()) |
| 155 | return false; |
| 156 | |
| 157 | PartialMappingIdx Previous = Order.front(); |
| 158 | for (const auto &Current : Order.drop_front()) { |
| 159 | if (Previous + 1 != Current) |
| 160 | return false; |
| 161 | Previous = Current; |
| 162 | } |
| 163 | return true; |
| 164 | } |
| 165 | |
| 166 | unsigned AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(unsigned RBIdx, |
| 167 | TypeSize Size) { |
| 168 | if (RBIdx == PMI_FirstGPR) { |
| 169 | if (Size <= 32) |
| 170 | return 0; |
| 171 | if (Size <= 64) |
| 172 | return 1; |
| 173 | if (Size <= 128) |
| 174 | return 2; |
| 175 | return -1; |
| 176 | } |
| 177 | if (RBIdx == PMI_FirstFPR) { |
| 178 | const unsigned MinSize = Size.getKnownMinValue(); |
| 179 | assert((!Size.isScalable() || MinSize >= 128) && |
| 180 | "Scalable vector types should have size of at least 128 bits" ); |
| 181 | if (Size.isScalable()) |
| 182 | return 3; |
| 183 | if (MinSize <= 16) |
| 184 | return 0; |
| 185 | if (MinSize <= 32) |
| 186 | return 1; |
| 187 | if (MinSize <= 64) |
| 188 | return 2; |
| 189 | if (MinSize <= 128) |
| 190 | return 3; |
| 191 | if (MinSize <= 256) |
| 192 | return 4; |
| 193 | if (MinSize <= 512) |
| 194 | return 5; |
| 195 | return -1; |
| 196 | } |
| 197 | return -1; |
| 198 | } |
| 199 | |
| 200 | const RegisterBankInfo::ValueMapping * |
| 201 | AArch64GenRegisterBankInfo::getValueMapping(PartialMappingIdx RBIdx, |
| 202 | const TypeSize Size) { |
| 203 | assert(RBIdx != PartialMappingIdx::PMI_None && "No mapping needed for that" ); |
| 204 | unsigned BaseIdxOffset = getRegBankBaseIdxOffset(RBIdx, Size); |
| 205 | if (BaseIdxOffset == -1u) |
| 206 | return &ValMappings[InvalidIdx]; |
| 207 | |
| 208 | unsigned ValMappingIdx = |
| 209 | First3OpsIdx + (RBIdx - PartialMappingIdx::PMI_Min + BaseIdxOffset) * |
| 210 | ValueMappingIdx::DistanceBetweenRegBanks; |
| 211 | assert(ValMappingIdx >= First3OpsIdx && ValMappingIdx <= Last3OpsIdx && |
| 212 | "Mapping out of bound" ); |
| 213 | |
| 214 | return &ValMappings[ValMappingIdx]; |
| 215 | } |
| 216 | |
| 217 | const AArch64GenRegisterBankInfo::PartialMappingIdx |
| 218 | AArch64GenRegisterBankInfo::BankIDToCopyMapIdx[]{ |
| 219 | PMI_None, // CCR |
| 220 | PMI_FirstFPR, // FPR |
| 221 | PMI_FirstGPR, // GPR |
| 222 | }; |
| 223 | |
| 224 | const RegisterBankInfo::ValueMapping * |
| 225 | AArch64GenRegisterBankInfo::getCopyMapping(unsigned DstBankID, |
| 226 | unsigned SrcBankID, |
| 227 | const TypeSize Size) { |
| 228 | assert(DstBankID < AArch64::NumRegisterBanks && "Invalid bank ID" ); |
| 229 | assert(SrcBankID < AArch64::NumRegisterBanks && "Invalid bank ID" ); |
| 230 | PartialMappingIdx DstRBIdx = BankIDToCopyMapIdx[DstBankID]; |
| 231 | PartialMappingIdx SrcRBIdx = BankIDToCopyMapIdx[SrcBankID]; |
| 232 | assert(DstRBIdx != PMI_None && "No such mapping" ); |
| 233 | assert(SrcRBIdx != PMI_None && "No such mapping" ); |
| 234 | |
| 235 | if (DstRBIdx == SrcRBIdx) |
| 236 | return getValueMapping(RBIdx: DstRBIdx, Size); |
| 237 | |
| 238 | assert(Size <= 64 && "GPR cannot handle that size" ); |
| 239 | unsigned ValMappingIdx = |
| 240 | FirstCrossRegCpyIdx + |
| 241 | (DstRBIdx - PMI_Min + getRegBankBaseIdxOffset(RBIdx: DstRBIdx, Size)) * |
| 242 | ValueMappingIdx::DistanceBetweenCrossRegCpy; |
| 243 | assert(ValMappingIdx >= FirstCrossRegCpyIdx && |
| 244 | ValMappingIdx <= LastCrossRegCpyIdx && "Mapping out of bound" ); |
| 245 | return &ValMappings[ValMappingIdx]; |
| 246 | } |
| 247 | |
| 248 | const RegisterBankInfo::ValueMapping * |
| 249 | AArch64GenRegisterBankInfo::getFPExtMapping(unsigned DstSize, |
| 250 | unsigned SrcSize) { |
| 251 | // We support: |
| 252 | // - For Scalar: |
| 253 | // - 16 to 32. |
| 254 | // - 16 to 64. |
| 255 | // - 32 to 64. |
| 256 | // => FPR 16 to FPR 32|64 |
| 257 | // => FPR 32 to FPR 64 |
| 258 | // - For vectors: |
| 259 | // - v4f16 to v4f32 |
| 260 | // - v2f32 to v2f64 |
| 261 | // => FPR 64 to FPR 128 |
| 262 | |
| 263 | // Check that we have been asked sensible sizes. |
| 264 | if (SrcSize == 16) { |
| 265 | assert((DstSize == 32 || DstSize == 64) && "Unexpected half extension" ); |
| 266 | if (DstSize == 32) |
| 267 | return &ValMappings[FPExt16To32Idx]; |
| 268 | return &ValMappings[FPExt16To64Idx]; |
| 269 | } |
| 270 | |
| 271 | if (SrcSize == 32) { |
| 272 | assert(DstSize == 64 && "Unexpected float extension" ); |
| 273 | return &ValMappings[FPExt32To64Idx]; |
| 274 | } |
| 275 | assert((SrcSize == 64 || DstSize == 128) && "Unexpected vector extension" ); |
| 276 | return &ValMappings[FPExt64To128Idx]; |
| 277 | } |
| 278 | } // End llvm namespace. |
| 279 | |