Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
35294 views
//===- PPCInstructionSelector.cpp --------------------------------*- C++ -*-==//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8/// This file implements the targeting of the InstructionSelector class for9/// PowerPC.10//===----------------------------------------------------------------------===//1112#include "PPC.h"13#include "PPCInstrInfo.h"14#include "PPCMachineFunctionInfo.h"15#include "PPCRegisterBankInfo.h"16#include "PPCSubtarget.h"17#include "PPCTargetMachine.h"18#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"19#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"20#include "llvm/CodeGen/GlobalISel/InstructionSelector.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"2627#define DEBUG_TYPE "ppc-gisel"2829using namespace llvm;3031namespace {3233#define GET_GLOBALISEL_PREDICATE_BITSET34#include "PPCGenGlobalISel.inc"35#undef GET_GLOBALISEL_PREDICATE_BITSET3637class PPCInstructionSelector : public InstructionSelector {38public:39PPCInstructionSelector(const PPCTargetMachine &TM, const PPCSubtarget &STI,40const PPCRegisterBankInfo &RBI);4142bool select(MachineInstr &I) override;43static const char *getName() { return DEBUG_TYPE; }4445private:46/// tblgen generated 'select' implementation that is used as the initial47/// selector for the patterns that do not require complex C++.48bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;4950bool selectFPToInt(MachineInstr &I, MachineBasicBlock &MBB,51MachineRegisterInfo &MRI) const;52bool selectIntToFP(MachineInstr &I, MachineBasicBlock &MBB,53MachineRegisterInfo &MRI) const;5455bool selectZExt(MachineInstr &I, MachineBasicBlock &MBB,56MachineRegisterInfo &MRI) const;57bool selectConstantPool(MachineInstr &I, MachineBasicBlock &MBB,58MachineRegisterInfo &MRI) const;5960std::optional<bool> selectI64ImmDirect(MachineInstr &I,61MachineBasicBlock &MBB,62MachineRegisterInfo &MRI, Register Reg,63uint64_t Imm) const;64bool selectI64Imm(MachineInstr &I, MachineBasicBlock &MBB,65MachineRegisterInfo &MRI) const;6667const PPCTargetMachine &TM;68const PPCSubtarget &STI;69const PPCInstrInfo &TII;70const PPCRegisterInfo &TRI;71const PPCRegisterBankInfo &RBI;7273#define GET_GLOBALISEL_PREDICATES_DECL74#include "PPCGenGlobalISel.inc"75#undef GET_GLOBALISEL_PREDICATES_DECL7677#define GET_GLOBALISEL_TEMPORARIES_DECL78#include "PPCGenGlobalISel.inc"79#undef GET_GLOBALISEL_TEMPORARIES_DECL80};8182} // end anonymous namespace8384#define GET_GLOBALISEL_IMPL85#include "PPCGenGlobalISel.inc"86#undef GET_GLOBALISEL_IMPL8788PPCInstructionSelector::PPCInstructionSelector(const PPCTargetMachine &TM,89const PPCSubtarget &STI,90const PPCRegisterBankInfo &RBI)91: TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),92RBI(RBI),93#define GET_GLOBALISEL_PREDICATES_INIT94#include "PPCGenGlobalISel.inc"95#undef GET_GLOBALISEL_PREDICATES_INIT96#define GET_GLOBALISEL_TEMPORARIES_INIT97#include "PPCGenGlobalISel.inc"98#undef GET_GLOBALISEL_TEMPORARIES_INIT99{100}101102static const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank *RB) {103if (RB->getID() == PPC::GPRRegBankID) {104if (Ty.getSizeInBits() == 64)105return &PPC::G8RCRegClass;106if (Ty.getSizeInBits() <= 32)107return &PPC::GPRCRegClass;108}109if (RB->getID() == PPC::FPRRegBankID) {110if (Ty.getSizeInBits() == 32)111return &PPC::F4RCRegClass;112if (Ty.getSizeInBits() == 64)113return &PPC::F8RCRegClass;114}115if (RB->getID() == PPC::VECRegBankID) {116if (Ty.getSizeInBits() == 128)117return &PPC::VSRCRegClass;118}119if (RB->getID() == PPC::CRRegBankID) {120if (Ty.getSizeInBits() == 1)121return &PPC::CRBITRCRegClass;122if (Ty.getSizeInBits() == 4)123return &PPC::CRRCRegClass;124}125126llvm_unreachable("Unknown RegBank!");127}128129static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,130MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,131const RegisterBankInfo &RBI) {132Register DstReg = I.getOperand(0).getReg();133134if (DstReg.isPhysical())135return true;136137const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI);138const TargetRegisterClass *DstRC =139getRegClass(MRI.getType(DstReg), DstRegBank);140141// No need to constrain SrcReg. It will get constrained when we hit another of142// its use or its defs.143// Copies do not have constraints.144if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {145LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())146<< " operand\n");147return false;148}149150return true;151}152153static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID,154unsigned OpSize) {155const bool IsStore = GenericOpc == TargetOpcode::G_STORE;156switch (RegBankID) {157case PPC::GPRRegBankID:158switch (OpSize) {159case 32:160return IsStore ? PPC::STW : PPC::LWZ;161case 64:162return IsStore ? PPC::STD : PPC::LD;163default:164llvm_unreachable("Unexpected size!");165}166break;167case PPC::FPRRegBankID:168switch (OpSize) {169case 32:170return IsStore ? PPC::STFS : PPC::LFS;171case 64:172return IsStore ? PPC::STFD : PPC::LFD;173default:174llvm_unreachable("Unexpected size!");175}176break;177default:178llvm_unreachable("Unexpected register bank!");179}180return GenericOpc;181}182183bool PPCInstructionSelector::selectIntToFP(MachineInstr &I,184MachineBasicBlock &MBB,185MachineRegisterInfo &MRI) const {186if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())187return false;188189const DebugLoc &DbgLoc = I.getDebugLoc();190const Register DstReg = I.getOperand(0).getReg();191const Register SrcReg = I.getOperand(1).getReg();192193Register MoveReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);194195// For now, only handle the case for 64 bit integer.196BuildMI(MBB, I, DbgLoc, TII.get(PPC::MTVSRD), MoveReg).addReg(SrcReg);197198bool IsSingle = MRI.getType(DstReg).getSizeInBits() == 32;199bool IsSigned = I.getOpcode() == TargetOpcode::G_SITOFP;200unsigned ConvOp = IsSingle ? (IsSigned ? PPC::XSCVSXDSP : PPC::XSCVUXDSP)201: (IsSigned ? PPC::XSCVSXDDP : PPC::XSCVUXDDP);202203MachineInstr *MI =204BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), DstReg).addReg(MoveReg);205206I.eraseFromParent();207return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);208}209210bool PPCInstructionSelector::selectFPToInt(MachineInstr &I,211MachineBasicBlock &MBB,212MachineRegisterInfo &MRI) const {213if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())214return false;215216const DebugLoc &DbgLoc = I.getDebugLoc();217const Register DstReg = I.getOperand(0).getReg();218const Register SrcReg = I.getOperand(1).getReg();219220Register CopyReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);221BuildMI(MBB, I, DbgLoc, TII.get(TargetOpcode::COPY), CopyReg).addReg(SrcReg);222223Register ConvReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);224225bool IsSigned = I.getOpcode() == TargetOpcode::G_FPTOSI;226227// single-precision is stored as double-precision on PPC in registers, so228// always use double-precision convertions.229unsigned ConvOp = IsSigned ? PPC::XSCVDPSXDS : PPC::XSCVDPUXDS;230231BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), ConvReg).addReg(CopyReg);232233MachineInstr *MI =234BuildMI(MBB, I, DbgLoc, TII.get(PPC::MFVSRD), DstReg).addReg(ConvReg);235236I.eraseFromParent();237return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);238}239240bool PPCInstructionSelector::selectZExt(MachineInstr &I, MachineBasicBlock &MBB,241MachineRegisterInfo &MRI) const {242const Register DstReg = I.getOperand(0).getReg();243const LLT DstTy = MRI.getType(DstReg);244const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI);245246const Register SrcReg = I.getOperand(1).getReg();247248assert(DstTy.getSizeInBits() == 64 && "Unexpected dest size!");249assert(MRI.getType(SrcReg).getSizeInBits() == 32 && "Unexpected src size!");250251Register ImpDefReg =252MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank));253BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::IMPLICIT_DEF),254ImpDefReg);255256Register NewDefReg =257MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank));258BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::INSERT_SUBREG),259NewDefReg)260.addReg(ImpDefReg)261.addReg(SrcReg)262.addImm(PPC::sub_32);263264MachineInstr *MI =265BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), DstReg)266.addReg(NewDefReg)267.addImm(0)268.addImm(32);269270I.eraseFromParent();271return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);272}273274// For any 32 < Num < 64, check if the Imm contains at least Num consecutive275// zeros and return the number of bits by the left of these consecutive zeros.276static uint32_t findContiguousZerosAtLeast(uint64_t Imm, unsigned Num) {277uint32_t HiTZ = llvm::countr_zero<uint32_t>(Hi_32(Imm));278uint32_t LoLZ = llvm::countl_zero<uint32_t>(Lo_32(Imm));279if ((HiTZ + LoLZ) >= Num)280return (32 + HiTZ);281return 0;282}283284// Direct materialization of 64-bit constants by enumerated patterns.285// Similar to PPCISelDAGToDAG::selectI64ImmDirect().286std::optional<bool> PPCInstructionSelector::selectI64ImmDirect(MachineInstr &I,287MachineBasicBlock &MBB,288MachineRegisterInfo &MRI,289Register Reg,290uint64_t Imm) const {291unsigned TZ = llvm::countr_zero<uint64_t>(Imm);292unsigned LZ = llvm::countl_zero<uint64_t>(Imm);293unsigned TO = llvm::countr_one<uint64_t>(Imm);294unsigned LO = llvm::countl_one<uint64_t>(Imm);295uint32_t Hi32 = Hi_32(Imm);296uint32_t Lo32 = Lo_32(Imm);297uint32_t Shift = 0;298299// Following patterns use 1 instructions to materialize the Imm.300301// 1-1) Patterns : {zeros}{15-bit valve}302// {ones}{15-bit valve}303if (isInt<16>(Imm))304return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), Reg)305.addImm(Imm)306.constrainAllUses(TII, TRI, RBI);307// 1-2) Patterns : {zeros}{15-bit valve}{16 zeros}308// {ones}{15-bit valve}{16 zeros}309if (TZ > 15 && (LZ > 32 || LO > 32))310return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), Reg)311.addImm((Imm >> 16) & 0xffff)312.constrainAllUses(TII, TRI, RBI);313314// Following patterns use 2 instructions to materialize the Imm.315316assert(LZ < 64 && "Unexpected leading zeros here.");317// Count of ones follwing the leading zeros.318unsigned FO = llvm::countl_one<uint64_t>(Imm << LZ);319// 2-1) Patterns : {zeros}{31-bit value}320// {ones}{31-bit value}321if (isInt<32>(Imm)) {322uint64_t ImmHi16 = (Imm >> 16) & 0xffff;323unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;324Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);325if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)326.addImm((Imm >> 16) & 0xffff)327.constrainAllUses(TII, TRI, RBI))328return false;329return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Reg)330.addReg(TmpReg, RegState::Kill)331.addImm(Imm & 0xffff)332.constrainAllUses(TII, TRI, RBI);333}334// 2-2) Patterns : {zeros}{ones}{15-bit value}{zeros}335// {zeros}{15-bit value}{zeros}336// {zeros}{ones}{15-bit value}337// {ones}{15-bit value}{zeros}338// We can take advantage of LI's sign-extension semantics to generate leading339// ones, and then use RLDIC to mask off the ones in both sides after rotation.340if ((LZ + FO + TZ) > 48) {341Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);342if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)343.addImm((Imm >> TZ) & 0xffff)344.constrainAllUses(TII, TRI, RBI))345return false;346return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg)347.addReg(TmpReg, RegState::Kill)348.addImm(TZ)349.addImm(LZ)350.constrainAllUses(TII, TRI, RBI);351}352// 2-3) Pattern : {zeros}{15-bit value}{ones}353// Shift right the Imm by (48 - LZ) bits to construct a negtive 16 bits value,354// therefore we can take advantage of LI's sign-extension semantics, and then355// mask them off after rotation.356//357// +--LZ--||-15-bit-||--TO--+ +-------------|--16-bit--+358// |00000001bbbbbbbbb1111111| -> |00000000000001bbbbbbbbb1|359// +------------------------+ +------------------------+360// 63 0 63 0361// Imm (Imm >> (48 - LZ) & 0xffff)362// +----sext-----|--16-bit--+ +clear-|-----------------+363// |11111111111111bbbbbbbbb1| -> |00000001bbbbbbbbb1111111|364// +------------------------+ +------------------------+365// 63 0 63 0366// LI8: sext many leading zeros RLDICL: rotate left (48 - LZ), clear left LZ367if ((LZ + TO) > 48) {368// Since the immediates with (LZ > 32) have been handled by previous369// patterns, here we have (LZ <= 32) to make sure we will not shift right370// the Imm by a negative value.371assert(LZ <= 32 && "Unexpected shift value.");372Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);373if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)374.addImm(Imm >> (48 - LZ) & 0xffff)375.constrainAllUses(TII, TRI, RBI))376return false;377return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)378.addReg(TmpReg, RegState::Kill)379.addImm(48 - LZ)380.addImm(LZ)381.constrainAllUses(TII, TRI, RBI);382}383// 2-4) Patterns : {zeros}{ones}{15-bit value}{ones}384// {ones}{15-bit value}{ones}385// We can take advantage of LI's sign-extension semantics to generate leading386// ones, and then use RLDICL to mask off the ones in left sides (if required)387// after rotation.388//389// +-LZ-FO||-15-bit-||--TO--+ +-------------|--16-bit--+390// |00011110bbbbbbbbb1111111| -> |000000000011110bbbbbbbbb|391// +------------------------+ +------------------------+392// 63 0 63 0393// Imm (Imm >> TO) & 0xffff394// +----sext-----|--16-bit--+ +LZ|---------------------+395// |111111111111110bbbbbbbbb| -> |00011110bbbbbbbbb1111111|396// +------------------------+ +------------------------+397// 63 0 63 0398// LI8: sext many leading zeros RLDICL: rotate left TO, clear left LZ399if ((LZ + FO + TO) > 48) {400Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);401if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)402.addImm((Imm >> TO) & 0xffff)403.constrainAllUses(TII, TRI, RBI))404return false;405return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)406.addReg(TmpReg, RegState::Kill)407.addImm(TO)408.addImm(LZ)409.constrainAllUses(TII, TRI, RBI);410}411// 2-5) Pattern : {32 zeros}{****}{0}{15-bit value}412// If Hi32 is zero and the Lo16(in Lo32) can be presented as a positive 16 bit413// value, we can use LI for Lo16 without generating leading ones then add the414// Hi16(in Lo32).415if (LZ == 32 && ((Lo32 & 0x8000) == 0)) {416Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);417if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)418.addImm(Lo32 & 0xffff)419.constrainAllUses(TII, TRI, RBI))420return false;421return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), Reg)422.addReg(TmpReg, RegState::Kill)423.addImm(Lo32 >> 16)424.constrainAllUses(TII, TRI, RBI);425}426// 2-6) Patterns : {******}{49 zeros}{******}427// {******}{49 ones}{******}428// If the Imm contains 49 consecutive zeros/ones, it means that a total of 15429// bits remain on both sides. Rotate right the Imm to construct an int<16>430// value, use LI for int<16> value and then use RLDICL without mask to rotate431// it back.432//433// 1) findContiguousZerosAtLeast(Imm, 49)434// +------|--zeros-|------+ +---ones--||---15 bit--+435// |bbbbbb0000000000aaaaaa| -> |0000000000aaaaaabbbbbb|436// +----------------------+ +----------------------+437// 63 0 63 0438//439// 2) findContiguousZerosAtLeast(~Imm, 49)440// +------|--ones--|------+ +---ones--||---15 bit--+441// |bbbbbb1111111111aaaaaa| -> |1111111111aaaaaabbbbbb|442// +----------------------+ +----------------------+443// 63 0 63 0444if ((Shift = findContiguousZerosAtLeast(Imm, 49)) ||445(Shift = findContiguousZerosAtLeast(~Imm, 49))) {446uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();447Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);448if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)449.addImm(RotImm & 0xffff)450.constrainAllUses(TII, TRI, RBI))451return false;452return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)453.addReg(TmpReg, RegState::Kill)454.addImm(Shift)455.addImm(0)456.constrainAllUses(TII, TRI, RBI);457}458459// Following patterns use 3 instructions to materialize the Imm.460461// 3-1) Patterns : {zeros}{ones}{31-bit value}{zeros}462// {zeros}{31-bit value}{zeros}463// {zeros}{ones}{31-bit value}464// {ones}{31-bit value}{zeros}465// We can take advantage of LIS's sign-extension semantics to generate leading466// ones, add the remaining bits with ORI, and then use RLDIC to mask off the467// ones in both sides after rotation.468if ((LZ + FO + TZ) > 32) {469uint64_t ImmHi16 = (Imm >> (TZ + 16)) & 0xffff;470unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;471Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);472Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);473if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)474.addImm(ImmHi16)475.constrainAllUses(TII, TRI, RBI))476return false;477if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)478.addReg(TmpReg, RegState::Kill)479.addImm((Imm >> TZ) & 0xffff)480.constrainAllUses(TII, TRI, RBI))481return false;482return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg)483.addReg(Tmp2Reg, RegState::Kill)484.addImm(TZ)485.addImm(LZ)486.constrainAllUses(TII, TRI, RBI);487}488// 3-2) Pattern : {zeros}{31-bit value}{ones}489// Shift right the Imm by (32 - LZ) bits to construct a negative 32 bits490// value, therefore we can take advantage of LIS's sign-extension semantics,491// add the remaining bits with ORI, and then mask them off after rotation.492// This is similar to Pattern 2-3, please refer to the diagram there.493if ((LZ + TO) > 32) {494// Since the immediates with (LZ > 32) have been handled by previous495// patterns, here we have (LZ <= 32) to make sure we will not shift right496// the Imm by a negative value.497assert(LZ <= 32 && "Unexpected shift value.");498Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);499Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);500if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg)501.addImm((Imm >> (48 - LZ)) & 0xffff)502.constrainAllUses(TII, TRI, RBI))503return false;504if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)505.addReg(TmpReg, RegState::Kill)506.addImm((Imm >> (32 - LZ)) & 0xffff)507.constrainAllUses(TII, TRI, RBI))508return false;509return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)510.addReg(Tmp2Reg, RegState::Kill)511.addImm(32 - LZ)512.addImm(LZ)513.constrainAllUses(TII, TRI, RBI);514}515// 3-3) Patterns : {zeros}{ones}{31-bit value}{ones}516// {ones}{31-bit value}{ones}517// We can take advantage of LIS's sign-extension semantics to generate leading518// ones, add the remaining bits with ORI, and then use RLDICL to mask off the519// ones in left sides (if required) after rotation.520// This is similar to Pattern 2-4, please refer to the diagram there.521if ((LZ + FO + TO) > 32) {522Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);523Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);524if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg)525.addImm((Imm >> (TO + 16)) & 0xffff)526.constrainAllUses(TII, TRI, RBI))527return false;528if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)529.addReg(TmpReg, RegState::Kill)530.addImm((Imm >> TO) & 0xffff)531.constrainAllUses(TII, TRI, RBI))532return false;533return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)534.addReg(Tmp2Reg, RegState::Kill)535.addImm(TO)536.addImm(LZ)537.constrainAllUses(TII, TRI, RBI);538}539// 3-4) Patterns : High word == Low word540if (Hi32 == Lo32) {541// Handle the first 32 bits.542uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff;543unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;544Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);545Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);546if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)547.addImm(ImmHi16)548.constrainAllUses(TII, TRI, RBI))549return false;550if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)551.addReg(TmpReg, RegState::Kill)552.addImm(Lo32 & 0xffff)553.constrainAllUses(TII, TRI, RBI))554return false;555return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIMI), Reg)556.addReg(Tmp2Reg)557.addReg(Tmp2Reg, RegState::Kill)558.addImm(32)559.addImm(0)560.constrainAllUses(TII, TRI, RBI);561}562// 3-5) Patterns : {******}{33 zeros}{******}563// {******}{33 ones}{******}564// If the Imm contains 33 consecutive zeros/ones, it means that a total of 31565// bits remain on both sides. Rotate right the Imm to construct an int<32>566// value, use LIS + ORI for int<32> value and then use RLDICL without mask to567// rotate it back.568// This is similar to Pattern 2-6, please refer to the diagram there.569if ((Shift = findContiguousZerosAtLeast(Imm, 33)) ||570(Shift = findContiguousZerosAtLeast(~Imm, 33))) {571uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();572uint64_t ImmHi16 = (RotImm >> 16) & 0xffff;573unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;574Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);575Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);576if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)577.addImm(ImmHi16)578.constrainAllUses(TII, TRI, RBI))579return false;580if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)581.addReg(TmpReg, RegState::Kill)582.addImm(RotImm & 0xffff)583.constrainAllUses(TII, TRI, RBI))584return false;585return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)586.addReg(Tmp2Reg, RegState::Kill)587.addImm(Shift)588.addImm(0)589.constrainAllUses(TII, TRI, RBI);590}591592// If we end up here then no instructions were inserted.593return std::nullopt;594}595596// Derived from PPCISelDAGToDAG::selectI64Imm().597// TODO: Add support for prefixed instructions.598bool PPCInstructionSelector::selectI64Imm(MachineInstr &I,599MachineBasicBlock &MBB,600MachineRegisterInfo &MRI) const {601assert(I.getOpcode() == TargetOpcode::G_CONSTANT && "Unexpected G code");602603Register DstReg = I.getOperand(0).getReg();604int64_t Imm = I.getOperand(1).getCImm()->getValue().getZExtValue();605// No more than 3 instructions are used if we can select the i64 immediate606// directly.607if (std::optional<bool> Res = selectI64ImmDirect(I, MBB, MRI, DstReg, Imm)) {608I.eraseFromParent();609return *Res;610}611612// Calculate the last bits as required.613uint32_t Hi16 = (Lo_32(Imm) >> 16) & 0xffff;614uint32_t Lo16 = Lo_32(Imm) & 0xffff;615616Register Reg =617(Hi16 || Lo16) ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;618619// Handle the upper 32 bit value.620std::optional<bool> Res =621selectI64ImmDirect(I, MBB, MRI, Reg, Imm & 0xffffffff00000000);622if (!Res || !*Res)623return false;624625// Add in the last bits as required.626if (Hi16) {627Register TmpReg =628Lo16 ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;629if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), TmpReg)630.addReg(Reg, RegState::Kill)631.addImm(Hi16)632.constrainAllUses(TII, TRI, RBI))633return false;634Reg = TmpReg;635}636if (Lo16) {637if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), DstReg)638.addReg(Reg, RegState::Kill)639.addImm(Lo16)640.constrainAllUses(TII, TRI, RBI))641return false;642}643I.eraseFromParent();644return true;645}646647bool PPCInstructionSelector::selectConstantPool(648MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const {649const DebugLoc &DbgLoc = I.getDebugLoc();650MachineFunction *MF = MBB.getParent();651652// TODO: handle 32-bit.653// TODO: Enabling floating point constant pool selection on AIX requires654// global isel on big endian target enabled first.655// See CallLowering::enableBigEndian().656if (!STI.isPPC64() || !STI.isLittleEndian())657return false;658659MF->getInfo<PPCFunctionInfo>()->setUsesTOCBasePtr();660661const Register DstReg = I.getOperand(0).getReg();662unsigned CPI = I.getOperand(1).getIndex();663664// Address stored in the TOC entry. This is related to code model and the ABI665// we are currently using. For now we only handle 64-bit Linux LE. PowerPC666// only supports small, medium and large code model.667const CodeModel::Model CModel = TM.getCodeModel();668assert(!(CModel == CodeModel::Tiny || CModel == CodeModel::Kernel) &&669"PowerPC doesn't support tiny or kernel code models.");670671const MCRegister TOCReg = STI.getTOCPointerRegister();672MachineMemOperand *MMO = MF->getMachineMemOperand(673MachinePointerInfo::getGOT(*MF), MachineMemOperand::MOLoad,674MRI.getType(DstReg), MF->getDataLayout().getPointerABIAlignment(0));675676MachineInstr *MI = nullptr;677// For now we only handle 64-bit Linux.678if (CModel == CodeModel::Small) {679// For small code model, generate LDtocCPT(CPI, X2).680MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::LDtocCPT), DstReg)681.addConstantPoolIndex(CPI)682.addReg(TOCReg)683.addMemOperand(MMO);684} else {685Register HaAddrReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);686BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDIStocHA8), HaAddrReg)687.addReg(TOCReg)688.addConstantPoolIndex(CPI);689690if (CModel == CodeModel::Large)691// For large code model, generate LDtocL(CPI, ADDIStocHA8(X2, CPI))692MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::LDtocL), DstReg)693.addConstantPoolIndex(CPI)694.addReg(HaAddrReg)695.addMemOperand(MMO);696else697// For medium code model, generate ADDItocL8(CPI, ADDIStocHA8(X2, CPI))698MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDItocL8), DstReg)699.addReg(HaAddrReg)700.addConstantPoolIndex(CPI);701}702703I.eraseFromParent();704return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);705}706707bool PPCInstructionSelector::select(MachineInstr &I) {708auto &MBB = *I.getParent();709auto &MF = *MBB.getParent();710auto &MRI = MF.getRegInfo();711712if (!isPreISelGenericOpcode(I.getOpcode())) {713if (I.isCopy())714return selectCopy(I, TII, MRI, TRI, RBI);715716return true;717}718719if (selectImpl(I, *CoverageInfo))720return true;721722unsigned Opcode = I.getOpcode();723724switch (Opcode) {725default:726return false;727case TargetOpcode::G_LOAD:728case TargetOpcode::G_STORE: {729GLoadStore &LdSt = cast<GLoadStore>(I);730LLT PtrTy = MRI.getType(LdSt.getPointerReg());731732if (PtrTy != LLT::pointer(0, 64)) {733LLVM_DEBUG(dbgs() << "Load/Store pointer has type: " << PtrTy734<< ", expected: " << LLT::pointer(0, 64) << '\n');735return false;736}737738auto SelectLoadStoreAddressingMode = [&]() -> MachineInstr * {739const unsigned NewOpc = selectLoadStoreOp(740I.getOpcode(), RBI.getRegBank(LdSt.getReg(0), MRI, TRI)->getID(),741LdSt.getMemSizeInBits().getValue());742743if (NewOpc == I.getOpcode())744return nullptr;745746// For now, simply use DForm with load/store addr as base and 0 as imm.747// FIXME: optimize load/store with some specific address patterns.748I.setDesc(TII.get(NewOpc));749Register AddrReg = I.getOperand(1).getReg();750bool IsKill = I.getOperand(1).isKill();751I.getOperand(1).ChangeToImmediate(0);752I.addOperand(*I.getParent()->getParent(),753MachineOperand::CreateReg(AddrReg, /* isDef */ false,754/* isImp */ false, IsKill));755return &I;756};757758MachineInstr *LoadStore = SelectLoadStoreAddressingMode();759if (!LoadStore)760return false;761762return constrainSelectedInstRegOperands(*LoadStore, TII, TRI, RBI);763}764case TargetOpcode::G_SITOFP:765case TargetOpcode::G_UITOFP:766return selectIntToFP(I, MBB, MRI);767case TargetOpcode::G_FPTOSI:768case TargetOpcode::G_FPTOUI:769return selectFPToInt(I, MBB, MRI);770// G_SEXT will be selected in tb-gen pattern.771case TargetOpcode::G_ZEXT:772return selectZExt(I, MBB, MRI);773case TargetOpcode::G_CONSTANT:774return selectI64Imm(I, MBB, MRI);775case TargetOpcode::G_CONSTANT_POOL:776return selectConstantPool(I, MBB, MRI);777}778return false;779}780781namespace llvm {782InstructionSelector *783createPPCInstructionSelector(const PPCTargetMachine &TM,784const PPCSubtarget &Subtarget,785const PPCRegisterBankInfo &RBI) {786return new PPCInstructionSelector(TM, Subtarget, RBI);787}788} // end namespace llvm789790791