1 //===- PPCInstructionSelector.cpp --------------------------------*- 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 implements the targeting of the InstructionSelector class for 10 /// PowerPC. 11 //===----------------------------------------------------------------------===// 12 13 #include "PPC.h" 14 #include "PPCInstrInfo.h" 15 #include "PPCRegisterBankInfo.h" 16 #include "PPCSubtarget.h" 17 #include "PPCTargetMachine.h" 18 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" 19 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" 20 #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" 21 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 22 #include "llvm/CodeGen/MachineConstantPool.h" 23 #include "llvm/CodeGen/MachineFunction.h" 24 #include "llvm/IR/IntrinsicsPowerPC.h" 25 #include "llvm/Support/Debug.h" 26 27 #define DEBUG_TYPE "ppc-gisel" 28 29 using namespace llvm; 30 31 namespace { 32 33 #define GET_GLOBALISEL_PREDICATE_BITSET 34 #include "PPCGenGlobalISel.inc" 35 #undef GET_GLOBALISEL_PREDICATE_BITSET 36 37 class PPCInstructionSelector : public InstructionSelector { 38 public: 39 PPCInstructionSelector(const PPCTargetMachine &TM, const PPCSubtarget &STI, 40 const PPCRegisterBankInfo &RBI); 41 42 bool select(MachineInstr &I) override; 43 static const char *getName() { return DEBUG_TYPE; } 44 45 private: 46 /// tblgen generated 'select' implementation that is used as the initial 47 /// selector for the patterns that do not require complex C++. 48 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const; 49 50 bool selectFPToInt(MachineInstr &I, MachineBasicBlock &MBB, 51 MachineRegisterInfo &MRI) const; 52 bool selectIntToFP(MachineInstr &I, MachineBasicBlock &MBB, 53 MachineRegisterInfo &MRI) const; 54 55 bool selectZExt(MachineInstr &I, MachineBasicBlock &MBB, 56 MachineRegisterInfo &MRI) const; 57 58 std::optional<bool> selectI64ImmDirect(MachineInstr &I, 59 MachineBasicBlock &MBB, 60 MachineRegisterInfo &MRI, Register Reg, 61 uint64_t Imm) const; 62 bool selectI64Imm(MachineInstr &I, MachineBasicBlock &MBB, 63 MachineRegisterInfo &MRI) const; 64 65 const PPCSubtarget &STI; 66 const PPCInstrInfo &TII; 67 const PPCRegisterInfo &TRI; 68 const PPCRegisterBankInfo &RBI; 69 70 #define GET_GLOBALISEL_PREDICATES_DECL 71 #include "PPCGenGlobalISel.inc" 72 #undef GET_GLOBALISEL_PREDICATES_DECL 73 74 #define GET_GLOBALISEL_TEMPORARIES_DECL 75 #include "PPCGenGlobalISel.inc" 76 #undef GET_GLOBALISEL_TEMPORARIES_DECL 77 }; 78 79 } // end anonymous namespace 80 81 #define GET_GLOBALISEL_IMPL 82 #include "PPCGenGlobalISel.inc" 83 #undef GET_GLOBALISEL_IMPL 84 85 PPCInstructionSelector::PPCInstructionSelector(const PPCTargetMachine &TM, 86 const PPCSubtarget &STI, 87 const PPCRegisterBankInfo &RBI) 88 : STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI), 89 #define GET_GLOBALISEL_PREDICATES_INIT 90 #include "PPCGenGlobalISel.inc" 91 #undef GET_GLOBALISEL_PREDICATES_INIT 92 #define GET_GLOBALISEL_TEMPORARIES_INIT 93 #include "PPCGenGlobalISel.inc" 94 #undef GET_GLOBALISEL_TEMPORARIES_INIT 95 { 96 } 97 98 static const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank *RB) { 99 if (RB->getID() == PPC::GPRRegBankID) { 100 if (Ty.getSizeInBits() == 64) 101 return &PPC::G8RCRegClass; 102 if (Ty.getSizeInBits() <= 32) 103 return &PPC::GPRCRegClass; 104 } 105 if (RB->getID() == PPC::FPRRegBankID) { 106 if (Ty.getSizeInBits() == 32) 107 return &PPC::F4RCRegClass; 108 if (Ty.getSizeInBits() == 64) 109 return &PPC::F8RCRegClass; 110 } 111 if (RB->getID() == PPC::CRRegBankID) { 112 if (Ty.getSizeInBits() == 1) 113 return &PPC::CRBITRCRegClass; 114 if (Ty.getSizeInBits() == 4) 115 return &PPC::CRRCRegClass; 116 } 117 118 llvm_unreachable("Unknown RegBank!"); 119 } 120 121 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, 122 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, 123 const RegisterBankInfo &RBI) { 124 Register DstReg = I.getOperand(0).getReg(); 125 126 if (DstReg.isPhysical()) 127 return true; 128 129 const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI); 130 const TargetRegisterClass *DstRC = 131 getRegClass(MRI.getType(DstReg), DstRegBank); 132 133 // No need to constrain SrcReg. It will get constrained when we hit another of 134 // its use or its defs. 135 // Copies do not have constraints. 136 if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) { 137 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 138 << " operand\n"); 139 return false; 140 } 141 142 return true; 143 } 144 145 static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID, 146 unsigned OpSize) { 147 const bool IsStore = GenericOpc == TargetOpcode::G_STORE; 148 switch (RegBankID) { 149 case PPC::GPRRegBankID: 150 switch (OpSize) { 151 case 32: 152 return IsStore ? PPC::STW : PPC::LWZ; 153 case 64: 154 return IsStore ? PPC::STD : PPC::LD; 155 default: 156 llvm_unreachable("Unexpected size!"); 157 } 158 break; 159 case PPC::FPRRegBankID: 160 switch (OpSize) { 161 case 32: 162 return IsStore ? PPC::STFS : PPC::LFS; 163 case 64: 164 return IsStore ? PPC::STFD : PPC::LFD; 165 default: 166 llvm_unreachable("Unexpected size!"); 167 } 168 break; 169 default: 170 llvm_unreachable("Unexpected register bank!"); 171 } 172 return GenericOpc; 173 } 174 175 bool PPCInstructionSelector::selectIntToFP(MachineInstr &I, 176 MachineBasicBlock &MBB, 177 MachineRegisterInfo &MRI) const { 178 if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT()) 179 return false; 180 181 const DebugLoc &DbgLoc = I.getDebugLoc(); 182 const Register DstReg = I.getOperand(0).getReg(); 183 const Register SrcReg = I.getOperand(1).getReg(); 184 185 Register MoveReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass); 186 187 // For now, only handle the case for 64 bit integer. 188 BuildMI(MBB, I, DbgLoc, TII.get(PPC::MTVSRD), MoveReg).addReg(SrcReg); 189 190 bool IsSingle = MRI.getType(DstReg).getSizeInBits() == 32; 191 bool IsSigned = I.getOpcode() == TargetOpcode::G_SITOFP; 192 unsigned ConvOp = IsSingle ? (IsSigned ? PPC::XSCVSXDSP : PPC::XSCVUXDSP) 193 : (IsSigned ? PPC::XSCVSXDDP : PPC::XSCVUXDDP); 194 195 MachineInstr *MI = 196 BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), DstReg).addReg(MoveReg); 197 198 I.eraseFromParent(); 199 return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 200 } 201 202 bool PPCInstructionSelector::selectFPToInt(MachineInstr &I, 203 MachineBasicBlock &MBB, 204 MachineRegisterInfo &MRI) const { 205 if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT()) 206 return false; 207 208 const DebugLoc &DbgLoc = I.getDebugLoc(); 209 const Register DstReg = I.getOperand(0).getReg(); 210 const Register SrcReg = I.getOperand(1).getReg(); 211 212 Register CopyReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass); 213 BuildMI(MBB, I, DbgLoc, TII.get(TargetOpcode::COPY), CopyReg).addReg(SrcReg); 214 215 Register ConvReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass); 216 217 bool IsSigned = I.getOpcode() == TargetOpcode::G_FPTOSI; 218 219 // single-precision is stored as double-precision on PPC in registers, so 220 // always use double-precision convertions. 221 unsigned ConvOp = IsSigned ? PPC::XSCVDPSXDS : PPC::XSCVDPUXDS; 222 223 BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), ConvReg).addReg(CopyReg); 224 225 MachineInstr *MI = 226 BuildMI(MBB, I, DbgLoc, TII.get(PPC::MFVSRD), DstReg).addReg(ConvReg); 227 228 I.eraseFromParent(); 229 return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 230 } 231 232 bool PPCInstructionSelector::selectZExt(MachineInstr &I, MachineBasicBlock &MBB, 233 MachineRegisterInfo &MRI) const { 234 const Register DstReg = I.getOperand(0).getReg(); 235 const LLT DstTy = MRI.getType(DstReg); 236 const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI); 237 238 const Register SrcReg = I.getOperand(1).getReg(); 239 240 assert(DstTy.getSizeInBits() == 64 && "Unexpected dest size!"); 241 assert(MRI.getType(SrcReg).getSizeInBits() == 32 && "Unexpected src size!"); 242 243 Register ImpDefReg = 244 MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank)); 245 BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::IMPLICIT_DEF), 246 ImpDefReg); 247 248 Register NewDefReg = 249 MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank)); 250 BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::INSERT_SUBREG), 251 NewDefReg) 252 .addReg(ImpDefReg) 253 .addReg(SrcReg) 254 .addImm(PPC::sub_32); 255 256 MachineInstr *MI = 257 BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), DstReg) 258 .addReg(NewDefReg) 259 .addImm(0) 260 .addImm(32); 261 262 I.eraseFromParent(); 263 return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 264 } 265 266 // For any 32 < Num < 64, check if the Imm contains at least Num consecutive 267 // zeros and return the number of bits by the left of these consecutive zeros. 268 static uint32_t findContiguousZerosAtLeast(uint64_t Imm, unsigned Num) { 269 uint32_t HiTZ = countTrailingZeros<uint32_t>(Hi_32(Imm)); 270 uint32_t LoLZ = countLeadingZeros<uint32_t>(Lo_32(Imm)); 271 if ((HiTZ + LoLZ) >= Num) 272 return (32 + HiTZ); 273 return 0; 274 } 275 276 // Direct materialization of 64-bit constants by enumerated patterns. 277 // Similar to PPCISelDAGToDAG::selectI64ImmDirect(). 278 std::optional<bool> PPCInstructionSelector::selectI64ImmDirect(MachineInstr &I, 279 MachineBasicBlock &MBB, 280 MachineRegisterInfo &MRI, 281 Register Reg, 282 uint64_t Imm) const { 283 unsigned TZ = countTrailingZeros<uint64_t>(Imm); 284 unsigned LZ = countLeadingZeros<uint64_t>(Imm); 285 unsigned TO = countTrailingOnes<uint64_t>(Imm); 286 unsigned LO = countLeadingOnes<uint64_t>(Imm); 287 uint32_t Hi32 = Hi_32(Imm); 288 uint32_t Lo32 = Lo_32(Imm); 289 uint32_t Shift = 0; 290 291 // Following patterns use 1 instructions to materialize the Imm. 292 293 // 1-1) Patterns : {zeros}{15-bit valve} 294 // {ones}{15-bit valve} 295 if (isInt<16>(Imm)) 296 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), Reg) 297 .addImm(Imm) 298 .constrainAllUses(TII, TRI, RBI); 299 // 1-2) Patterns : {zeros}{15-bit valve}{16 zeros} 300 // {ones}{15-bit valve}{16 zeros} 301 if (TZ > 15 && (LZ > 32 || LO > 32)) 302 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), Reg) 303 .addImm((Imm >> 16) & 0xffff) 304 .constrainAllUses(TII, TRI, RBI); 305 306 // Following patterns use 2 instructions to materialize the Imm. 307 308 assert(LZ < 64 && "Unexpected leading zeros here."); 309 // Count of ones follwing the leading zeros. 310 unsigned FO = countLeadingOnes<uint64_t>(Imm << LZ); 311 // 2-1) Patterns : {zeros}{31-bit value} 312 // {ones}{31-bit value} 313 if (isInt<32>(Imm)) { 314 uint64_t ImmHi16 = (Imm >> 16) & 0xffff; 315 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8; 316 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 317 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg) 318 .addImm((Imm >> 16) & 0xffff) 319 .constrainAllUses(TII, TRI, RBI)) 320 return false; 321 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Reg) 322 .addReg(TmpReg, RegState::Kill) 323 .addImm(Imm & 0xffff) 324 .constrainAllUses(TII, TRI, RBI); 325 } 326 // 2-2) Patterns : {zeros}{ones}{15-bit value}{zeros} 327 // {zeros}{15-bit value}{zeros} 328 // {zeros}{ones}{15-bit value} 329 // {ones}{15-bit value}{zeros} 330 // We can take advantage of LI's sign-extension semantics to generate leading 331 // ones, and then use RLDIC to mask off the ones in both sides after rotation. 332 if ((LZ + FO + TZ) > 48) { 333 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 334 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg) 335 .addImm((Imm >> TZ) & 0xffff) 336 .constrainAllUses(TII, TRI, RBI)) 337 return false; 338 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg) 339 .addReg(TmpReg, RegState::Kill) 340 .addImm(TZ) 341 .addImm(LZ) 342 .constrainAllUses(TII, TRI, RBI); 343 } 344 // 2-3) Pattern : {zeros}{15-bit value}{ones} 345 // Shift right the Imm by (48 - LZ) bits to construct a negtive 16 bits value, 346 // therefore we can take advantage of LI's sign-extension semantics, and then 347 // mask them off after rotation. 348 // 349 // +--LZ--||-15-bit-||--TO--+ +-------------|--16-bit--+ 350 // |00000001bbbbbbbbb1111111| -> |00000000000001bbbbbbbbb1| 351 // +------------------------+ +------------------------+ 352 // 63 0 63 0 353 // Imm (Imm >> (48 - LZ) & 0xffff) 354 // +----sext-----|--16-bit--+ +clear-|-----------------+ 355 // |11111111111111bbbbbbbbb1| -> |00000001bbbbbbbbb1111111| 356 // +------------------------+ +------------------------+ 357 // 63 0 63 0 358 // LI8: sext many leading zeros RLDICL: rotate left (48 - LZ), clear left LZ 359 if ((LZ + TO) > 48) { 360 // Since the immediates with (LZ > 32) have been handled by previous 361 // patterns, here we have (LZ <= 32) to make sure we will not shift right 362 // the Imm by a negative value. 363 assert(LZ <= 32 && "Unexpected shift value."); 364 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 365 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg) 366 .addImm(Imm >> (48 - LZ) & 0xffff) 367 .constrainAllUses(TII, TRI, RBI)) 368 return false; 369 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 370 .addReg(TmpReg, RegState::Kill) 371 .addImm(48 - LZ) 372 .addImm(LZ) 373 .constrainAllUses(TII, TRI, RBI); 374 } 375 // 2-4) Patterns : {zeros}{ones}{15-bit value}{ones} 376 // {ones}{15-bit value}{ones} 377 // We can take advantage of LI's sign-extension semantics to generate leading 378 // ones, and then use RLDICL to mask off the ones in left sides (if required) 379 // after rotation. 380 // 381 // +-LZ-FO||-15-bit-||--TO--+ +-------------|--16-bit--+ 382 // |00011110bbbbbbbbb1111111| -> |000000000011110bbbbbbbbb| 383 // +------------------------+ +------------------------+ 384 // 63 0 63 0 385 // Imm (Imm >> TO) & 0xffff 386 // +----sext-----|--16-bit--+ +LZ|---------------------+ 387 // |111111111111110bbbbbbbbb| -> |00011110bbbbbbbbb1111111| 388 // +------------------------+ +------------------------+ 389 // 63 0 63 0 390 // LI8: sext many leading zeros RLDICL: rotate left TO, clear left LZ 391 if ((LZ + FO + TO) > 48) { 392 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 393 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg) 394 .addImm((Imm >> TO) & 0xffff) 395 .constrainAllUses(TII, TRI, RBI)) 396 return false; 397 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 398 .addReg(TmpReg, RegState::Kill) 399 .addImm(TO) 400 .addImm(LZ) 401 .constrainAllUses(TII, TRI, RBI); 402 } 403 // 2-5) Pattern : {32 zeros}{****}{0}{15-bit value} 404 // If Hi32 is zero and the Lo16(in Lo32) can be presented as a positive 16 bit 405 // value, we can use LI for Lo16 without generating leading ones then add the 406 // Hi16(in Lo32). 407 if (LZ == 32 && ((Lo32 & 0x8000) == 0)) { 408 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 409 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg) 410 .addImm(Lo32 & 0xffff) 411 .constrainAllUses(TII, TRI, RBI)) 412 return false; 413 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), Reg) 414 .addReg(TmpReg, RegState::Kill) 415 .addImm(Lo32 >> 16) 416 .constrainAllUses(TII, TRI, RBI); 417 } 418 // 2-6) Patterns : {******}{49 zeros}{******} 419 // {******}{49 ones}{******} 420 // If the Imm contains 49 consecutive zeros/ones, it means that a total of 15 421 // bits remain on both sides. Rotate right the Imm to construct an int<16> 422 // value, use LI for int<16> value and then use RLDICL without mask to rotate 423 // it back. 424 // 425 // 1) findContiguousZerosAtLeast(Imm, 49) 426 // +------|--zeros-|------+ +---ones--||---15 bit--+ 427 // |bbbbbb0000000000aaaaaa| -> |0000000000aaaaaabbbbbb| 428 // +----------------------+ +----------------------+ 429 // 63 0 63 0 430 // 431 // 2) findContiguousZerosAtLeast(~Imm, 49) 432 // +------|--ones--|------+ +---ones--||---15 bit--+ 433 // |bbbbbb1111111111aaaaaa| -> |1111111111aaaaaabbbbbb| 434 // +----------------------+ +----------------------+ 435 // 63 0 63 0 436 if ((Shift = findContiguousZerosAtLeast(Imm, 49)) || 437 (Shift = findContiguousZerosAtLeast(~Imm, 49))) { 438 uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue(); 439 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 440 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg) 441 .addImm(RotImm & 0xffff) 442 .constrainAllUses(TII, TRI, RBI)) 443 return false; 444 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 445 .addReg(TmpReg, RegState::Kill) 446 .addImm(Shift) 447 .addImm(0) 448 .constrainAllUses(TII, TRI, RBI); 449 } 450 451 // Following patterns use 3 instructions to materialize the Imm. 452 453 // 3-1) Patterns : {zeros}{ones}{31-bit value}{zeros} 454 // {zeros}{31-bit value}{zeros} 455 // {zeros}{ones}{31-bit value} 456 // {ones}{31-bit value}{zeros} 457 // We can take advantage of LIS's sign-extension semantics to generate leading 458 // ones, add the remaining bits with ORI, and then use RLDIC to mask off the 459 // ones in both sides after rotation. 460 if ((LZ + FO + TZ) > 32) { 461 uint64_t ImmHi16 = (Imm >> (TZ + 16)) & 0xffff; 462 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8; 463 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 464 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 465 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg) 466 .addImm(ImmHi16) 467 .constrainAllUses(TII, TRI, RBI)) 468 return false; 469 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg) 470 .addReg(TmpReg, RegState::Kill) 471 .addImm((Imm >> TZ) & 0xffff) 472 .constrainAllUses(TII, TRI, RBI)) 473 return false; 474 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg) 475 .addReg(Tmp2Reg, RegState::Kill) 476 .addImm(TZ) 477 .addImm(LZ) 478 .constrainAllUses(TII, TRI, RBI); 479 } 480 // 3-2) Pattern : {zeros}{31-bit value}{ones} 481 // Shift right the Imm by (32 - LZ) bits to construct a negative 32 bits 482 // value, therefore we can take advantage of LIS's sign-extension semantics, 483 // add the remaining bits with ORI, and then mask them off after rotation. 484 // This is similar to Pattern 2-3, please refer to the diagram there. 485 if ((LZ + TO) > 32) { 486 // Since the immediates with (LZ > 32) have been handled by previous 487 // patterns, here we have (LZ <= 32) to make sure we will not shift right 488 // the Imm by a negative value. 489 assert(LZ <= 32 && "Unexpected shift value."); 490 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 491 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 492 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg) 493 .addImm((Imm >> (48 - LZ)) & 0xffff) 494 .constrainAllUses(TII, TRI, RBI)) 495 return false; 496 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg) 497 .addReg(TmpReg, RegState::Kill) 498 .addImm((Imm >> (32 - LZ)) & 0xffff) 499 .constrainAllUses(TII, TRI, RBI)) 500 return false; 501 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 502 .addReg(Tmp2Reg, RegState::Kill) 503 .addImm(32 - LZ) 504 .addImm(LZ) 505 .constrainAllUses(TII, TRI, RBI); 506 } 507 // 3-3) Patterns : {zeros}{ones}{31-bit value}{ones} 508 // {ones}{31-bit value}{ones} 509 // We can take advantage of LIS's sign-extension semantics to generate leading 510 // ones, add the remaining bits with ORI, and then use RLDICL to mask off the 511 // ones in left sides (if required) after rotation. 512 // This is similar to Pattern 2-4, please refer to the diagram there. 513 if ((LZ + FO + TO) > 32) { 514 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 515 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 516 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg) 517 .addImm((Imm >> (TO + 16)) & 0xffff) 518 .constrainAllUses(TII, TRI, RBI)) 519 return false; 520 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg) 521 .addReg(TmpReg, RegState::Kill) 522 .addImm((Imm >> TO) & 0xffff) 523 .constrainAllUses(TII, TRI, RBI)) 524 return false; 525 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 526 .addReg(Tmp2Reg, RegState::Kill) 527 .addImm(TO) 528 .addImm(LZ) 529 .constrainAllUses(TII, TRI, RBI); 530 } 531 // 3-4) Patterns : High word == Low word 532 if (Hi32 == Lo32) { 533 // Handle the first 32 bits. 534 uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff; 535 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8; 536 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 537 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 538 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg) 539 .addImm(ImmHi16) 540 .constrainAllUses(TII, TRI, RBI)) 541 return false; 542 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg) 543 .addReg(TmpReg, RegState::Kill) 544 .addImm(Lo32 & 0xffff) 545 .constrainAllUses(TII, TRI, RBI)) 546 return false; 547 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIMI), Reg) 548 .addReg(Tmp2Reg) 549 .addReg(Tmp2Reg, RegState::Kill) 550 .addImm(32) 551 .addImm(0) 552 .constrainAllUses(TII, TRI, RBI); 553 } 554 // 3-5) Patterns : {******}{33 zeros}{******} 555 // {******}{33 ones}{******} 556 // If the Imm contains 33 consecutive zeros/ones, it means that a total of 31 557 // bits remain on both sides. Rotate right the Imm to construct an int<32> 558 // value, use LIS + ORI for int<32> value and then use RLDICL without mask to 559 // rotate it back. 560 // This is similar to Pattern 2-6, please refer to the diagram there. 561 if ((Shift = findContiguousZerosAtLeast(Imm, 33)) || 562 (Shift = findContiguousZerosAtLeast(~Imm, 33))) { 563 uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue(); 564 uint64_t ImmHi16 = (RotImm >> 16) & 0xffff; 565 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8; 566 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 567 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 568 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg) 569 .addImm(ImmHi16) 570 .constrainAllUses(TII, TRI, RBI)) 571 return false; 572 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg) 573 .addReg(TmpReg, RegState::Kill) 574 .addImm(RotImm & 0xffff) 575 .constrainAllUses(TII, TRI, RBI)) 576 return false; 577 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 578 .addReg(Tmp2Reg, RegState::Kill) 579 .addImm(Shift) 580 .addImm(0) 581 .constrainAllUses(TII, TRI, RBI); 582 } 583 584 // If we end up here then no instructions were inserted. 585 return std::nullopt; 586 } 587 588 // Derived from PPCISelDAGToDAG::selectI64Imm(). 589 // TODO: Add support for prefixed instructions. 590 bool PPCInstructionSelector::selectI64Imm(MachineInstr &I, 591 MachineBasicBlock &MBB, 592 MachineRegisterInfo &MRI) const { 593 assert(I.getOpcode() == TargetOpcode::G_CONSTANT && "Unexpected G code"); 594 595 Register DstReg = I.getOperand(0).getReg(); 596 int64_t Imm = I.getOperand(1).getCImm()->getValue().getZExtValue(); 597 // No more than 3 instructions are used if we can select the i64 immediate 598 // directly. 599 if (std::optional<bool> Res = selectI64ImmDirect(I, MBB, MRI, DstReg, Imm)) { 600 I.eraseFromParent(); 601 return *Res; 602 } 603 604 // Calculate the last bits as required. 605 uint32_t Hi16 = (Lo_32(Imm) >> 16) & 0xffff; 606 uint32_t Lo16 = Lo_32(Imm) & 0xffff; 607 608 Register Reg = 609 (Hi16 || Lo16) ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg; 610 611 // Handle the upper 32 bit value. 612 std::optional<bool> Res = 613 selectI64ImmDirect(I, MBB, MRI, Reg, Imm & 0xffffffff00000000); 614 if (!Res || !*Res) 615 return false; 616 617 // Add in the last bits as required. 618 if (Hi16) { 619 Register TmpReg = 620 Lo16 ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg; 621 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), TmpReg) 622 .addReg(Reg, RegState::Kill) 623 .addImm(Hi16) 624 .constrainAllUses(TII, TRI, RBI)) 625 return false; 626 Reg = TmpReg; 627 } 628 if (Lo16) { 629 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), DstReg) 630 .addReg(Reg, RegState::Kill) 631 .addImm(Lo16) 632 .constrainAllUses(TII, TRI, RBI)) 633 return false; 634 } 635 I.eraseFromParent(); 636 return true; 637 } 638 639 bool PPCInstructionSelector::select(MachineInstr &I) { 640 auto &MBB = *I.getParent(); 641 auto &MF = *MBB.getParent(); 642 auto &MRI = MF.getRegInfo(); 643 644 if (!isPreISelGenericOpcode(I.getOpcode())) { 645 if (I.isCopy()) 646 return selectCopy(I, TII, MRI, TRI, RBI); 647 648 return true; 649 } 650 651 if (selectImpl(I, *CoverageInfo)) 652 return true; 653 654 unsigned Opcode = I.getOpcode(); 655 656 switch (Opcode) { 657 default: 658 return false; 659 case TargetOpcode::G_LOAD: 660 case TargetOpcode::G_STORE: { 661 GLoadStore &LdSt = cast<GLoadStore>(I); 662 LLT PtrTy = MRI.getType(LdSt.getPointerReg()); 663 664 if (PtrTy != LLT::pointer(0, 64)) { 665 LLVM_DEBUG(dbgs() << "Load/Store pointer has type: " << PtrTy 666 << ", expected: " << LLT::pointer(0, 64) << '\n'); 667 return false; 668 } 669 670 auto SelectLoadStoreAddressingMode = [&]() -> MachineInstr * { 671 const unsigned NewOpc = selectLoadStoreOp( 672 I.getOpcode(), RBI.getRegBank(LdSt.getReg(0), MRI, TRI)->getID(), 673 LdSt.getMemSizeInBits()); 674 675 if (NewOpc == I.getOpcode()) 676 return nullptr; 677 678 // For now, simply use DForm with load/store addr as base and 0 as imm. 679 // FIXME: optimize load/store with some specific address patterns. 680 I.setDesc(TII.get(NewOpc)); 681 Register AddrReg = I.getOperand(1).getReg(); 682 bool IsKill = I.getOperand(1).isKill(); 683 I.getOperand(1).ChangeToImmediate(0); 684 I.addOperand(*I.getParent()->getParent(), 685 MachineOperand::CreateReg(AddrReg, /* isDef */ false, 686 /* isImp */ false, IsKill)); 687 return &I; 688 }; 689 690 MachineInstr *LoadStore = SelectLoadStoreAddressingMode(); 691 if (!LoadStore) 692 return false; 693 694 return constrainSelectedInstRegOperands(*LoadStore, TII, TRI, RBI); 695 } 696 case TargetOpcode::G_SITOFP: 697 case TargetOpcode::G_UITOFP: 698 return selectIntToFP(I, MBB, MRI); 699 case TargetOpcode::G_FPTOSI: 700 case TargetOpcode::G_FPTOUI: 701 return selectFPToInt(I, MBB, MRI); 702 // G_SEXT will be selected in tb-gen pattern. 703 case TargetOpcode::G_ZEXT: 704 return selectZExt(I, MBB, MRI); 705 case TargetOpcode::G_CONSTANT: 706 return selectI64Imm(I, MBB, MRI); 707 } 708 return false; 709 } 710 711 namespace llvm { 712 InstructionSelector * 713 createPPCInstructionSelector(const PPCTargetMachine &TM, 714 const PPCSubtarget &Subtarget, 715 const PPCRegisterBankInfo &RBI) { 716 return new PPCInstructionSelector(TM, Subtarget, RBI); 717 } 718 } // end namespace llvm 719