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