xref: /llvm-project/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp (revision 601e102bdb55e12a2f791e0d68fd6f81ffc21e21)
1009cd4e4SKit Barton //===- PPCInstructionSelector.cpp --------------------------------*- C++ -*-==//
2009cd4e4SKit Barton //
3009cd4e4SKit Barton // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4009cd4e4SKit Barton // See https://llvm.org/LICENSE.txt for license information.
5009cd4e4SKit Barton // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009cd4e4SKit Barton //
7009cd4e4SKit Barton //===----------------------------------------------------------------------===//
8009cd4e4SKit Barton /// \file
9009cd4e4SKit Barton /// This file implements the targeting of the InstructionSelector class for
10009cd4e4SKit Barton /// PowerPC.
11009cd4e4SKit Barton //===----------------------------------------------------------------------===//
12009cd4e4SKit Barton 
130a9b1c59SChen Zheng #include "PPC.h"
14009cd4e4SKit Barton #include "PPCInstrInfo.h"
156ee2f770SChen Zheng #include "PPCMachineFunctionInfo.h"
16009cd4e4SKit Barton #include "PPCRegisterBankInfo.h"
17009cd4e4SKit Barton #include "PPCSubtarget.h"
18009cd4e4SKit Barton #include "PPCTargetMachine.h"
191fe7d9c7Spvanhout #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
20503a935dSChen Zheng #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
21009cd4e4SKit Barton #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
22503a935dSChen Zheng #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
23503a935dSChen Zheng #include "llvm/CodeGen/MachineConstantPool.h"
24009cd4e4SKit Barton #include "llvm/CodeGen/MachineFunction.h"
25009cd4e4SKit Barton #include "llvm/IR/IntrinsicsPowerPC.h"
26009cd4e4SKit Barton #include "llvm/Support/Debug.h"
27009cd4e4SKit Barton 
28009cd4e4SKit Barton #define DEBUG_TYPE "ppc-gisel"
29009cd4e4SKit Barton 
30009cd4e4SKit Barton using namespace llvm;
31009cd4e4SKit Barton 
32009cd4e4SKit Barton namespace {
33009cd4e4SKit Barton 
34009cd4e4SKit Barton #define GET_GLOBALISEL_PREDICATE_BITSET
35009cd4e4SKit Barton #include "PPCGenGlobalISel.inc"
36009cd4e4SKit Barton #undef GET_GLOBALISEL_PREDICATE_BITSET
37009cd4e4SKit Barton 
38009cd4e4SKit Barton class PPCInstructionSelector : public InstructionSelector {
39009cd4e4SKit Barton public:
40009cd4e4SKit Barton   PPCInstructionSelector(const PPCTargetMachine &TM, const PPCSubtarget &STI,
41009cd4e4SKit Barton                          const PPCRegisterBankInfo &RBI);
42009cd4e4SKit Barton 
43009cd4e4SKit Barton   bool select(MachineInstr &I) override;
getName()44009cd4e4SKit Barton   static const char *getName() { return DEBUG_TYPE; }
45009cd4e4SKit Barton 
46009cd4e4SKit Barton private:
47009cd4e4SKit Barton   /// tblgen generated 'select' implementation that is used as the initial
48009cd4e4SKit Barton   /// selector for the patterns that do not require complex C++.
49009cd4e4SKit Barton   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
50009cd4e4SKit Barton 
510a9b1c59SChen Zheng   bool selectFPToInt(MachineInstr &I, MachineBasicBlock &MBB,
520a9b1c59SChen Zheng                   MachineRegisterInfo &MRI) const;
530a9b1c59SChen Zheng   bool selectIntToFP(MachineInstr &I, MachineBasicBlock &MBB,
540a9b1c59SChen Zheng                   MachineRegisterInfo &MRI) const;
550a9b1c59SChen Zheng 
56b41d22dbSChen Zheng   bool selectZExt(MachineInstr &I, MachineBasicBlock &MBB,
57b41d22dbSChen Zheng                   MachineRegisterInfo &MRI) const;
586ee2f770SChen Zheng   bool selectConstantPool(MachineInstr &I, MachineBasicBlock &MBB,
596ee2f770SChen Zheng                           MachineRegisterInfo &MRI) const;
60b41d22dbSChen Zheng 
61110340c6SKai Nacke   std::optional<bool> selectI64ImmDirect(MachineInstr &I,
62110340c6SKai Nacke                                          MachineBasicBlock &MBB,
63110340c6SKai Nacke                                          MachineRegisterInfo &MRI, Register Reg,
64110340c6SKai Nacke                                          uint64_t Imm) const;
65110340c6SKai Nacke   bool selectI64Imm(MachineInstr &I, MachineBasicBlock &MBB,
66110340c6SKai Nacke                     MachineRegisterInfo &MRI) const;
67110340c6SKai Nacke 
686ee2f770SChen Zheng   const PPCTargetMachine &TM;
690a9b1c59SChen Zheng   const PPCSubtarget &STI;
70009cd4e4SKit Barton   const PPCInstrInfo &TII;
71009cd4e4SKit Barton   const PPCRegisterInfo &TRI;
72009cd4e4SKit Barton   const PPCRegisterBankInfo &RBI;
73009cd4e4SKit Barton 
74009cd4e4SKit Barton #define GET_GLOBALISEL_PREDICATES_DECL
75009cd4e4SKit Barton #include "PPCGenGlobalISel.inc"
76009cd4e4SKit Barton #undef GET_GLOBALISEL_PREDICATES_DECL
77009cd4e4SKit Barton 
78009cd4e4SKit Barton #define GET_GLOBALISEL_TEMPORARIES_DECL
79009cd4e4SKit Barton #include "PPCGenGlobalISel.inc"
80009cd4e4SKit Barton #undef GET_GLOBALISEL_TEMPORARIES_DECL
81009cd4e4SKit Barton };
82009cd4e4SKit Barton 
83009cd4e4SKit Barton } // end anonymous namespace
84009cd4e4SKit Barton 
85009cd4e4SKit Barton #define GET_GLOBALISEL_IMPL
86009cd4e4SKit Barton #include "PPCGenGlobalISel.inc"
87009cd4e4SKit Barton #undef GET_GLOBALISEL_IMPL
88009cd4e4SKit Barton 
PPCInstructionSelector(const PPCTargetMachine & TM,const PPCSubtarget & STI,const PPCRegisterBankInfo & RBI)89009cd4e4SKit Barton PPCInstructionSelector::PPCInstructionSelector(const PPCTargetMachine &TM,
90009cd4e4SKit Barton                                                const PPCSubtarget &STI,
91009cd4e4SKit Barton                                                const PPCRegisterBankInfo &RBI)
926ee2f770SChen Zheng     : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
936ee2f770SChen Zheng       RBI(RBI),
94009cd4e4SKit Barton #define GET_GLOBALISEL_PREDICATES_INIT
95009cd4e4SKit Barton #include "PPCGenGlobalISel.inc"
96009cd4e4SKit Barton #undef GET_GLOBALISEL_PREDICATES_INIT
97009cd4e4SKit Barton #define GET_GLOBALISEL_TEMPORARIES_INIT
98009cd4e4SKit Barton #include "PPCGenGlobalISel.inc"
99009cd4e4SKit Barton #undef GET_GLOBALISEL_TEMPORARIES_INIT
100009cd4e4SKit Barton {
101009cd4e4SKit Barton }
102009cd4e4SKit Barton 
getRegClass(LLT Ty,const RegisterBank * RB)103be4a1dfbSKai Nacke static const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank *RB) {
104be4a1dfbSKai Nacke   if (RB->getID() == PPC::GPRRegBankID) {
105be4a1dfbSKai Nacke     if (Ty.getSizeInBits() == 64)
106be4a1dfbSKai Nacke       return &PPC::G8RCRegClass;
107ac93a4e7SChen Zheng     if (Ty.getSizeInBits() <= 32)
108b41d22dbSChen Zheng       return &PPC::GPRCRegClass;
109be4a1dfbSKai Nacke   }
110d9143ce3SChen Zheng   if (RB->getID() == PPC::FPRRegBankID) {
111d9143ce3SChen Zheng     if (Ty.getSizeInBits() == 32)
112d9143ce3SChen Zheng       return &PPC::F4RCRegClass;
113d9143ce3SChen Zheng     if (Ty.getSizeInBits() == 64)
114d9143ce3SChen Zheng       return &PPC::F8RCRegClass;
115d9143ce3SChen Zheng   }
1163508f123SAmy Kwan   if (RB->getID() == PPC::VECRegBankID) {
1173508f123SAmy Kwan     if (Ty.getSizeInBits() == 128)
1183508f123SAmy Kwan       return &PPC::VSRCRegClass;
1193508f123SAmy Kwan   }
120ac93a4e7SChen Zheng   if (RB->getID() == PPC::CRRegBankID) {
121ac93a4e7SChen Zheng     if (Ty.getSizeInBits() == 1)
122ac93a4e7SChen Zheng       return &PPC::CRBITRCRegClass;
123ac93a4e7SChen Zheng     if (Ty.getSizeInBits() == 4)
124ac93a4e7SChen Zheng       return &PPC::CRRCRegClass;
125ac93a4e7SChen Zheng   }
126be4a1dfbSKai Nacke 
127be4a1dfbSKai Nacke   llvm_unreachable("Unknown RegBank!");
128be4a1dfbSKai Nacke }
129be4a1dfbSKai Nacke 
selectCopy(MachineInstr & I,const TargetInstrInfo & TII,MachineRegisterInfo & MRI,const TargetRegisterInfo & TRI,const RegisterBankInfo & RBI)130be4a1dfbSKai Nacke static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
131be4a1dfbSKai Nacke                        MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
132be4a1dfbSKai Nacke                        const RegisterBankInfo &RBI) {
133be4a1dfbSKai Nacke   Register DstReg = I.getOperand(0).getReg();
134be4a1dfbSKai Nacke 
135be4a1dfbSKai Nacke   if (DstReg.isPhysical())
136be4a1dfbSKai Nacke     return true;
137be4a1dfbSKai Nacke 
138be4a1dfbSKai Nacke   const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI);
139be4a1dfbSKai Nacke   const TargetRegisterClass *DstRC =
140be4a1dfbSKai Nacke       getRegClass(MRI.getType(DstReg), DstRegBank);
141be4a1dfbSKai Nacke 
142be4a1dfbSKai Nacke   // No need to constrain SrcReg. It will get constrained when we hit another of
143be4a1dfbSKai Nacke   // its use or its defs.
144be4a1dfbSKai Nacke   // Copies do not have constraints.
145be4a1dfbSKai Nacke   if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
146be4a1dfbSKai Nacke     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
147be4a1dfbSKai Nacke                       << " operand\n");
148be4a1dfbSKai Nacke     return false;
149be4a1dfbSKai Nacke   }
150be4a1dfbSKai Nacke 
151be4a1dfbSKai Nacke   return true;
152be4a1dfbSKai Nacke }
153be4a1dfbSKai Nacke 
selectLoadStoreOp(unsigned GenericOpc,unsigned RegBankID,unsigned OpSize)154503a935dSChen Zheng static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID,
155503a935dSChen Zheng                                   unsigned OpSize) {
156503a935dSChen Zheng   const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
157503a935dSChen Zheng   switch (RegBankID) {
158503a935dSChen Zheng   case PPC::GPRRegBankID:
159503a935dSChen Zheng     switch (OpSize) {
160b41d22dbSChen Zheng     case 32:
161b41d22dbSChen Zheng       return IsStore ? PPC::STW : PPC::LWZ;
162503a935dSChen Zheng     case 64:
163503a935dSChen Zheng       return IsStore ? PPC::STD : PPC::LD;
164503a935dSChen Zheng     default:
165503a935dSChen Zheng       llvm_unreachable("Unexpected size!");
166503a935dSChen Zheng     }
167503a935dSChen Zheng     break;
168503a935dSChen Zheng   case PPC::FPRRegBankID:
169503a935dSChen Zheng     switch (OpSize) {
170b41d22dbSChen Zheng     case 32:
171b41d22dbSChen Zheng       return IsStore ? PPC::STFS : PPC::LFS;
172503a935dSChen Zheng     case 64:
173503a935dSChen Zheng       return IsStore ? PPC::STFD : PPC::LFD;
174503a935dSChen Zheng     default:
175503a935dSChen Zheng       llvm_unreachable("Unexpected size!");
176503a935dSChen Zheng     }
177503a935dSChen Zheng     break;
178503a935dSChen Zheng   default:
179503a935dSChen Zheng     llvm_unreachable("Unexpected register bank!");
180503a935dSChen Zheng   }
181503a935dSChen Zheng   return GenericOpc;
182503a935dSChen Zheng }
183503a935dSChen Zheng 
selectIntToFP(MachineInstr & I,MachineBasicBlock & MBB,MachineRegisterInfo & MRI) const1840a9b1c59SChen Zheng bool PPCInstructionSelector::selectIntToFP(MachineInstr &I,
1850a9b1c59SChen Zheng                                            MachineBasicBlock &MBB,
1860a9b1c59SChen Zheng                                            MachineRegisterInfo &MRI) const {
1870a9b1c59SChen Zheng   if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())
1880a9b1c59SChen Zheng     return false;
1890a9b1c59SChen Zheng 
1900a9b1c59SChen Zheng   const DebugLoc &DbgLoc = I.getDebugLoc();
1910a9b1c59SChen Zheng   const Register DstReg = I.getOperand(0).getReg();
1920a9b1c59SChen Zheng   const Register SrcReg = I.getOperand(1).getReg();
1930a9b1c59SChen Zheng 
1940a9b1c59SChen Zheng   Register MoveReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);
1950a9b1c59SChen Zheng 
1960a9b1c59SChen Zheng   // For now, only handle the case for 64 bit integer.
1970a9b1c59SChen Zheng   BuildMI(MBB, I, DbgLoc, TII.get(PPC::MTVSRD), MoveReg).addReg(SrcReg);
1980a9b1c59SChen Zheng 
1990a9b1c59SChen Zheng   bool IsSingle = MRI.getType(DstReg).getSizeInBits() == 32;
2000a9b1c59SChen Zheng   bool IsSigned = I.getOpcode() == TargetOpcode::G_SITOFP;
2010a9b1c59SChen Zheng   unsigned ConvOp = IsSingle ? (IsSigned ? PPC::XSCVSXDSP : PPC::XSCVUXDSP)
2020a9b1c59SChen Zheng                              : (IsSigned ? PPC::XSCVSXDDP : PPC::XSCVUXDDP);
2030a9b1c59SChen Zheng 
2040a9b1c59SChen Zheng   MachineInstr *MI =
2050a9b1c59SChen Zheng       BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), DstReg).addReg(MoveReg);
2060a9b1c59SChen Zheng 
2070a9b1c59SChen Zheng   I.eraseFromParent();
2080a9b1c59SChen Zheng   return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
2090a9b1c59SChen Zheng }
2100a9b1c59SChen Zheng 
selectFPToInt(MachineInstr & I,MachineBasicBlock & MBB,MachineRegisterInfo & MRI) const2110a9b1c59SChen Zheng bool PPCInstructionSelector::selectFPToInt(MachineInstr &I,
2120a9b1c59SChen Zheng                                            MachineBasicBlock &MBB,
2130a9b1c59SChen Zheng                                            MachineRegisterInfo &MRI) const {
2140a9b1c59SChen Zheng   if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())
2150a9b1c59SChen Zheng     return false;
2160a9b1c59SChen Zheng 
2170a9b1c59SChen Zheng   const DebugLoc &DbgLoc = I.getDebugLoc();
2180a9b1c59SChen Zheng   const Register DstReg = I.getOperand(0).getReg();
2190a9b1c59SChen Zheng   const Register SrcReg = I.getOperand(1).getReg();
2200a9b1c59SChen Zheng 
2210a9b1c59SChen Zheng   Register CopyReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);
2220a9b1c59SChen Zheng   BuildMI(MBB, I, DbgLoc, TII.get(TargetOpcode::COPY), CopyReg).addReg(SrcReg);
2230a9b1c59SChen Zheng 
2240a9b1c59SChen Zheng   Register ConvReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);
2250a9b1c59SChen Zheng 
2260a9b1c59SChen Zheng   bool IsSigned = I.getOpcode() == TargetOpcode::G_FPTOSI;
2270a9b1c59SChen Zheng 
2280a9b1c59SChen Zheng   // single-precision is stored as double-precision on PPC in registers, so
2290a9b1c59SChen Zheng   // always use double-precision convertions.
2300a9b1c59SChen Zheng   unsigned ConvOp = IsSigned ? PPC::XSCVDPSXDS : PPC::XSCVDPUXDS;
2310a9b1c59SChen Zheng 
2320a9b1c59SChen Zheng   BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), ConvReg).addReg(CopyReg);
2330a9b1c59SChen Zheng 
2340a9b1c59SChen Zheng   MachineInstr *MI =
2350a9b1c59SChen Zheng       BuildMI(MBB, I, DbgLoc, TII.get(PPC::MFVSRD), DstReg).addReg(ConvReg);
2360a9b1c59SChen Zheng 
2370a9b1c59SChen Zheng   I.eraseFromParent();
2380a9b1c59SChen Zheng   return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
2390a9b1c59SChen Zheng }
2400a9b1c59SChen Zheng 
selectZExt(MachineInstr & I,MachineBasicBlock & MBB,MachineRegisterInfo & MRI) const241b41d22dbSChen Zheng bool PPCInstructionSelector::selectZExt(MachineInstr &I, MachineBasicBlock &MBB,
242b41d22dbSChen Zheng                                         MachineRegisterInfo &MRI) const {
243b41d22dbSChen Zheng   const Register DstReg = I.getOperand(0).getReg();
244b41d22dbSChen Zheng   const LLT DstTy = MRI.getType(DstReg);
245b41d22dbSChen Zheng   const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI);
246b41d22dbSChen Zheng 
247b41d22dbSChen Zheng   const Register SrcReg = I.getOperand(1).getReg();
248b41d22dbSChen Zheng 
249b41d22dbSChen Zheng   assert(DstTy.getSizeInBits() == 64 && "Unexpected dest size!");
250b41d22dbSChen Zheng   assert(MRI.getType(SrcReg).getSizeInBits() == 32 && "Unexpected src size!");
251b41d22dbSChen Zheng 
252b41d22dbSChen Zheng   Register ImpDefReg =
253b41d22dbSChen Zheng       MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank));
254b41d22dbSChen Zheng   BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::IMPLICIT_DEF),
255b41d22dbSChen Zheng           ImpDefReg);
256b41d22dbSChen Zheng 
257b41d22dbSChen Zheng   Register NewDefReg =
258b41d22dbSChen Zheng       MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank));
259b41d22dbSChen Zheng   BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::INSERT_SUBREG),
260b41d22dbSChen Zheng           NewDefReg)
261b41d22dbSChen Zheng       .addReg(ImpDefReg)
262b41d22dbSChen Zheng       .addReg(SrcReg)
263b41d22dbSChen Zheng       .addImm(PPC::sub_32);
264b41d22dbSChen Zheng 
265b41d22dbSChen Zheng   MachineInstr *MI =
266b41d22dbSChen Zheng       BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), DstReg)
267b41d22dbSChen Zheng           .addReg(NewDefReg)
268b41d22dbSChen Zheng           .addImm(0)
269b41d22dbSChen Zheng           .addImm(32);
270b41d22dbSChen Zheng 
271b41d22dbSChen Zheng   I.eraseFromParent();
272b41d22dbSChen Zheng   return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
273b41d22dbSChen Zheng }
274b41d22dbSChen Zheng 
275110340c6SKai Nacke // For any 32 < Num < 64, check if the Imm contains at least Num consecutive
276110340c6SKai Nacke // zeros and return the number of bits by the left of these consecutive zeros.
findContiguousZerosAtLeast(uint64_t Imm,unsigned Num)277110340c6SKai Nacke static uint32_t findContiguousZerosAtLeast(uint64_t Imm, unsigned Num) {
278e0782018SKazu Hirata   uint32_t HiTZ = llvm::countr_zero<uint32_t>(Hi_32(Imm));
279e0782018SKazu Hirata   uint32_t LoLZ = llvm::countl_zero<uint32_t>(Lo_32(Imm));
280110340c6SKai Nacke   if ((HiTZ + LoLZ) >= Num)
281110340c6SKai Nacke     return (32 + HiTZ);
282110340c6SKai Nacke   return 0;
283110340c6SKai Nacke }
284110340c6SKai Nacke 
285110340c6SKai Nacke // Direct materialization of 64-bit constants by enumerated patterns.
286110340c6SKai Nacke // Similar to PPCISelDAGToDAG::selectI64ImmDirect().
selectI64ImmDirect(MachineInstr & I,MachineBasicBlock & MBB,MachineRegisterInfo & MRI,Register Reg,uint64_t Imm) const287110340c6SKai Nacke std::optional<bool> PPCInstructionSelector::selectI64ImmDirect(MachineInstr &I,
288110340c6SKai Nacke                                                 MachineBasicBlock &MBB,
289110340c6SKai Nacke                                                 MachineRegisterInfo &MRI,
290110340c6SKai Nacke                                                 Register Reg,
291110340c6SKai Nacke                                                 uint64_t Imm) const {
292e0782018SKazu Hirata   unsigned TZ = llvm::countr_zero<uint64_t>(Imm);
293e0782018SKazu Hirata   unsigned LZ = llvm::countl_zero<uint64_t>(Imm);
294e0782018SKazu Hirata   unsigned TO = llvm::countr_one<uint64_t>(Imm);
295e0782018SKazu Hirata   unsigned LO = llvm::countl_one<uint64_t>(Imm);
296110340c6SKai Nacke   uint32_t Hi32 = Hi_32(Imm);
297110340c6SKai Nacke   uint32_t Lo32 = Lo_32(Imm);
298110340c6SKai Nacke   uint32_t Shift = 0;
299110340c6SKai Nacke 
300110340c6SKai Nacke   // Following patterns use 1 instructions to materialize the Imm.
301110340c6SKai Nacke 
302110340c6SKai Nacke   // 1-1) Patterns : {zeros}{15-bit valve}
303110340c6SKai Nacke   //                 {ones}{15-bit valve}
304110340c6SKai Nacke   if (isInt<16>(Imm))
305110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), Reg)
306110340c6SKai Nacke         .addImm(Imm)
307110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
308110340c6SKai Nacke   // 1-2) Patterns : {zeros}{15-bit valve}{16 zeros}
309110340c6SKai Nacke   //                 {ones}{15-bit valve}{16 zeros}
310110340c6SKai Nacke   if (TZ > 15 && (LZ > 32 || LO > 32))
311110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), Reg)
312110340c6SKai Nacke         .addImm((Imm >> 16) & 0xffff)
313110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
314110340c6SKai Nacke 
315110340c6SKai Nacke   // Following patterns use 2 instructions to materialize the Imm.
316110340c6SKai Nacke 
317110340c6SKai Nacke   assert(LZ < 64 && "Unexpected leading zeros here.");
318110340c6SKai Nacke   // Count of ones follwing the leading zeros.
319e0782018SKazu Hirata   unsigned FO = llvm::countl_one<uint64_t>(Imm << LZ);
320110340c6SKai Nacke   // 2-1) Patterns : {zeros}{31-bit value}
321110340c6SKai Nacke   //                 {ones}{31-bit value}
322110340c6SKai Nacke   if (isInt<32>(Imm)) {
323110340c6SKai Nacke     uint64_t ImmHi16 = (Imm >> 16) & 0xffff;
324110340c6SKai Nacke     unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
325110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
326110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
327110340c6SKai Nacke              .addImm((Imm >> 16) & 0xffff)
328110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
329110340c6SKai Nacke       return false;
330110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Reg)
331110340c6SKai Nacke         .addReg(TmpReg, RegState::Kill)
332110340c6SKai Nacke         .addImm(Imm & 0xffff)
333110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
334110340c6SKai Nacke   }
335110340c6SKai Nacke   // 2-2) Patterns : {zeros}{ones}{15-bit value}{zeros}
336110340c6SKai Nacke   //                 {zeros}{15-bit value}{zeros}
337110340c6SKai Nacke   //                 {zeros}{ones}{15-bit value}
338110340c6SKai Nacke   //                 {ones}{15-bit value}{zeros}
339110340c6SKai Nacke   // We can take advantage of LI's sign-extension semantics to generate leading
340110340c6SKai Nacke   // ones, and then use RLDIC to mask off the ones in both sides after rotation.
341110340c6SKai Nacke   if ((LZ + FO + TZ) > 48) {
342110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
343110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
344110340c6SKai Nacke              .addImm((Imm >> TZ) & 0xffff)
345110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
346110340c6SKai Nacke       return false;
347110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg)
348110340c6SKai Nacke         .addReg(TmpReg, RegState::Kill)
349110340c6SKai Nacke         .addImm(TZ)
350110340c6SKai Nacke         .addImm(LZ)
351110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
352110340c6SKai Nacke   }
353110340c6SKai Nacke   // 2-3) Pattern : {zeros}{15-bit value}{ones}
354110340c6SKai Nacke   // Shift right the Imm by (48 - LZ) bits to construct a negtive 16 bits value,
355110340c6SKai Nacke   // therefore we can take advantage of LI's sign-extension semantics, and then
356110340c6SKai Nacke   // mask them off after rotation.
357110340c6SKai Nacke   //
358110340c6SKai Nacke   // +--LZ--||-15-bit-||--TO--+     +-------------|--16-bit--+
359110340c6SKai Nacke   // |00000001bbbbbbbbb1111111| ->  |00000000000001bbbbbbbbb1|
360110340c6SKai Nacke   // +------------------------+     +------------------------+
361110340c6SKai Nacke   // 63                      0      63                      0
362110340c6SKai Nacke   //          Imm                   (Imm >> (48 - LZ) & 0xffff)
363110340c6SKai Nacke   // +----sext-----|--16-bit--+     +clear-|-----------------+
364110340c6SKai Nacke   // |11111111111111bbbbbbbbb1| ->  |00000001bbbbbbbbb1111111|
365110340c6SKai Nacke   // +------------------------+     +------------------------+
366110340c6SKai Nacke   // 63                      0      63                      0
367110340c6SKai Nacke   // LI8: sext many leading zeros   RLDICL: rotate left (48 - LZ), clear left LZ
368110340c6SKai Nacke   if ((LZ + TO) > 48) {
369110340c6SKai Nacke     // Since the immediates with (LZ > 32) have been handled by previous
370110340c6SKai Nacke     // patterns, here we have (LZ <= 32) to make sure we will not shift right
371110340c6SKai Nacke     // the Imm by a negative value.
372110340c6SKai Nacke     assert(LZ <= 32 && "Unexpected shift value.");
373110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
374110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
375110340c6SKai Nacke              .addImm(Imm >> (48 - LZ) & 0xffff)
376110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
377110340c6SKai Nacke       return false;
378110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
379110340c6SKai Nacke         .addReg(TmpReg, RegState::Kill)
380110340c6SKai Nacke         .addImm(48 - LZ)
381110340c6SKai Nacke         .addImm(LZ)
382110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
383110340c6SKai Nacke   }
384110340c6SKai Nacke   // 2-4) Patterns : {zeros}{ones}{15-bit value}{ones}
385110340c6SKai Nacke   //                 {ones}{15-bit value}{ones}
386110340c6SKai Nacke   // We can take advantage of LI's sign-extension semantics to generate leading
387110340c6SKai Nacke   // ones, and then use RLDICL to mask off the ones in left sides (if required)
388110340c6SKai Nacke   // after rotation.
389110340c6SKai Nacke   //
390110340c6SKai Nacke   // +-LZ-FO||-15-bit-||--TO--+     +-------------|--16-bit--+
391110340c6SKai Nacke   // |00011110bbbbbbbbb1111111| ->  |000000000011110bbbbbbbbb|
392110340c6SKai Nacke   // +------------------------+     +------------------------+
393110340c6SKai Nacke   // 63                      0      63                      0
394110340c6SKai Nacke   //            Imm                    (Imm >> TO) & 0xffff
395110340c6SKai Nacke   // +----sext-----|--16-bit--+     +LZ|---------------------+
396110340c6SKai Nacke   // |111111111111110bbbbbbbbb| ->  |00011110bbbbbbbbb1111111|
397110340c6SKai Nacke   // +------------------------+     +------------------------+
398110340c6SKai Nacke   // 63                      0      63                      0
399110340c6SKai Nacke   // LI8: sext many leading zeros   RLDICL: rotate left TO, clear left LZ
400110340c6SKai Nacke   if ((LZ + FO + TO) > 48) {
401110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
402110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
403110340c6SKai Nacke              .addImm((Imm >> TO) & 0xffff)
404110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
405110340c6SKai Nacke       return false;
406110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
407110340c6SKai Nacke         .addReg(TmpReg, RegState::Kill)
408110340c6SKai Nacke         .addImm(TO)
409110340c6SKai Nacke         .addImm(LZ)
410110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
411110340c6SKai Nacke   }
412110340c6SKai Nacke   // 2-5) Pattern : {32 zeros}{****}{0}{15-bit value}
413110340c6SKai Nacke   // If Hi32 is zero and the Lo16(in Lo32) can be presented as a positive 16 bit
414110340c6SKai Nacke   // value, we can use LI for Lo16 without generating leading ones then add the
415110340c6SKai Nacke   // Hi16(in Lo32).
416110340c6SKai Nacke   if (LZ == 32 && ((Lo32 & 0x8000) == 0)) {
417110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
418110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
419110340c6SKai Nacke              .addImm(Lo32 & 0xffff)
420110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
421110340c6SKai Nacke       return false;
422110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), Reg)
423110340c6SKai Nacke         .addReg(TmpReg, RegState::Kill)
424110340c6SKai Nacke         .addImm(Lo32 >> 16)
425110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
426110340c6SKai Nacke   }
427110340c6SKai Nacke   // 2-6) Patterns : {******}{49 zeros}{******}
428110340c6SKai Nacke   //                 {******}{49 ones}{******}
429110340c6SKai Nacke   // If the Imm contains 49 consecutive zeros/ones, it means that a total of 15
430110340c6SKai Nacke   // bits remain on both sides. Rotate right the Imm to construct an int<16>
431110340c6SKai Nacke   // value, use LI for int<16> value and then use RLDICL without mask to rotate
432110340c6SKai Nacke   // it back.
433110340c6SKai Nacke   //
434110340c6SKai Nacke   // 1) findContiguousZerosAtLeast(Imm, 49)
435110340c6SKai Nacke   // +------|--zeros-|------+     +---ones--||---15 bit--+
436110340c6SKai Nacke   // |bbbbbb0000000000aaaaaa| ->  |0000000000aaaaaabbbbbb|
437110340c6SKai Nacke   // +----------------------+     +----------------------+
438110340c6SKai Nacke   // 63                    0      63                    0
439110340c6SKai Nacke   //
440110340c6SKai Nacke   // 2) findContiguousZerosAtLeast(~Imm, 49)
441110340c6SKai Nacke   // +------|--ones--|------+     +---ones--||---15 bit--+
442110340c6SKai Nacke   // |bbbbbb1111111111aaaaaa| ->  |1111111111aaaaaabbbbbb|
443110340c6SKai Nacke   // +----------------------+     +----------------------+
444110340c6SKai Nacke   // 63                    0      63                    0
445110340c6SKai Nacke   if ((Shift = findContiguousZerosAtLeast(Imm, 49)) ||
446110340c6SKai Nacke       (Shift = findContiguousZerosAtLeast(~Imm, 49))) {
447110340c6SKai Nacke     uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
448110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
449110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
450110340c6SKai Nacke              .addImm(RotImm & 0xffff)
451110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
452110340c6SKai Nacke       return false;
453110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
454110340c6SKai Nacke         .addReg(TmpReg, RegState::Kill)
455110340c6SKai Nacke         .addImm(Shift)
456110340c6SKai Nacke         .addImm(0)
457110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
458110340c6SKai Nacke   }
459110340c6SKai Nacke 
460110340c6SKai Nacke   // Following patterns use 3 instructions to materialize the Imm.
461110340c6SKai Nacke 
462110340c6SKai Nacke   // 3-1) Patterns : {zeros}{ones}{31-bit value}{zeros}
463110340c6SKai Nacke   //                 {zeros}{31-bit value}{zeros}
464110340c6SKai Nacke   //                 {zeros}{ones}{31-bit value}
465110340c6SKai Nacke   //                 {ones}{31-bit value}{zeros}
466110340c6SKai Nacke   // We can take advantage of LIS's sign-extension semantics to generate leading
467110340c6SKai Nacke   // ones, add the remaining bits with ORI, and then use RLDIC to mask off the
468110340c6SKai Nacke   // ones in both sides after rotation.
469110340c6SKai Nacke   if ((LZ + FO + TZ) > 32) {
470110340c6SKai Nacke     uint64_t ImmHi16 = (Imm >> (TZ + 16)) & 0xffff;
471110340c6SKai Nacke     unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
472110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
473110340c6SKai Nacke     Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
474110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
475110340c6SKai Nacke              .addImm(ImmHi16)
476110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
477110340c6SKai Nacke       return false;
478110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
479110340c6SKai Nacke              .addReg(TmpReg, RegState::Kill)
480110340c6SKai Nacke              .addImm((Imm >> TZ) & 0xffff)
481110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
482110340c6SKai Nacke       return false;
483110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg)
484110340c6SKai Nacke         .addReg(Tmp2Reg, RegState::Kill)
485110340c6SKai Nacke         .addImm(TZ)
486110340c6SKai Nacke         .addImm(LZ)
487110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
488110340c6SKai Nacke   }
489110340c6SKai Nacke   // 3-2) Pattern : {zeros}{31-bit value}{ones}
490110340c6SKai Nacke   // Shift right the Imm by (32 - LZ) bits to construct a negative 32 bits
491110340c6SKai Nacke   // value, therefore we can take advantage of LIS's sign-extension semantics,
492110340c6SKai Nacke   // add the remaining bits with ORI, and then mask them off after rotation.
493110340c6SKai Nacke   // This is similar to Pattern 2-3, please refer to the diagram there.
494110340c6SKai Nacke   if ((LZ + TO) > 32) {
495110340c6SKai Nacke     // Since the immediates with (LZ > 32) have been handled by previous
496110340c6SKai Nacke     // patterns, here we have (LZ <= 32) to make sure we will not shift right
497110340c6SKai Nacke     // the Imm by a negative value.
498110340c6SKai Nacke     assert(LZ <= 32 && "Unexpected shift value.");
499110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
500110340c6SKai Nacke     Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
501110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg)
502110340c6SKai Nacke             .addImm((Imm >> (48 - LZ)) & 0xffff)
503110340c6SKai Nacke             .constrainAllUses(TII, TRI, RBI))
504110340c6SKai Nacke       return false;
505110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
506110340c6SKai Nacke              .addReg(TmpReg, RegState::Kill)
507110340c6SKai Nacke              .addImm((Imm >> (32 - LZ)) & 0xffff)
508110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
509110340c6SKai Nacke       return false;
510110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
511110340c6SKai Nacke         .addReg(Tmp2Reg, RegState::Kill)
512110340c6SKai Nacke         .addImm(32 - LZ)
513110340c6SKai Nacke         .addImm(LZ)
514110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
515110340c6SKai Nacke   }
516110340c6SKai Nacke   // 3-3) Patterns : {zeros}{ones}{31-bit value}{ones}
517110340c6SKai Nacke   //                 {ones}{31-bit value}{ones}
518110340c6SKai Nacke   // We can take advantage of LIS's sign-extension semantics to generate leading
519110340c6SKai Nacke   // ones, add the remaining bits with ORI, and then use RLDICL to mask off the
520110340c6SKai Nacke   // ones in left sides (if required) after rotation.
521110340c6SKai Nacke   // This is similar to Pattern 2-4, please refer to the diagram there.
522110340c6SKai Nacke   if ((LZ + FO + TO) > 32) {
523110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
524110340c6SKai Nacke     Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
525110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg)
526110340c6SKai Nacke              .addImm((Imm >> (TO + 16)) & 0xffff)
527110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
528110340c6SKai Nacke       return false;
529110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
530110340c6SKai Nacke              .addReg(TmpReg, RegState::Kill)
531110340c6SKai Nacke              .addImm((Imm >> TO) & 0xffff)
532110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
533110340c6SKai Nacke       return false;
534110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
535110340c6SKai Nacke         .addReg(Tmp2Reg, RegState::Kill)
536110340c6SKai Nacke         .addImm(TO)
537110340c6SKai Nacke         .addImm(LZ)
538110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
539110340c6SKai Nacke   }
540110340c6SKai Nacke   // 3-4) Patterns : High word == Low word
541110340c6SKai Nacke   if (Hi32 == Lo32) {
542110340c6SKai Nacke     // Handle the first 32 bits.
543110340c6SKai Nacke     uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff;
544110340c6SKai Nacke     unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
545110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
546110340c6SKai Nacke     Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
547110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
548110340c6SKai Nacke              .addImm(ImmHi16)
549110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
550110340c6SKai Nacke       return false;
551110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
552110340c6SKai Nacke              .addReg(TmpReg, RegState::Kill)
553110340c6SKai Nacke              .addImm(Lo32 & 0xffff)
554110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
555110340c6SKai Nacke       return false;
556110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIMI), Reg)
557110340c6SKai Nacke         .addReg(Tmp2Reg)
558110340c6SKai Nacke         .addReg(Tmp2Reg, RegState::Kill)
559110340c6SKai Nacke         .addImm(32)
560110340c6SKai Nacke         .addImm(0)
561110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
562110340c6SKai Nacke   }
563110340c6SKai Nacke   // 3-5) Patterns : {******}{33 zeros}{******}
564110340c6SKai Nacke   //                 {******}{33 ones}{******}
565110340c6SKai Nacke   // If the Imm contains 33 consecutive zeros/ones, it means that a total of 31
566110340c6SKai Nacke   // bits remain on both sides. Rotate right the Imm to construct an int<32>
567110340c6SKai Nacke   // value, use LIS + ORI for int<32> value and then use RLDICL without mask to
568110340c6SKai Nacke   // rotate it back.
569110340c6SKai Nacke   // This is similar to Pattern 2-6, please refer to the diagram there.
570110340c6SKai Nacke   if ((Shift = findContiguousZerosAtLeast(Imm, 33)) ||
571110340c6SKai Nacke       (Shift = findContiguousZerosAtLeast(~Imm, 33))) {
572110340c6SKai Nacke     uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
573110340c6SKai Nacke     uint64_t ImmHi16 = (RotImm >> 16) & 0xffff;
574110340c6SKai Nacke     unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
575110340c6SKai Nacke     Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
576110340c6SKai Nacke     Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
577110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
578110340c6SKai Nacke              .addImm(ImmHi16)
579110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
580110340c6SKai Nacke       return false;
581110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
582110340c6SKai Nacke              .addReg(TmpReg, RegState::Kill)
583110340c6SKai Nacke              .addImm(RotImm & 0xffff)
584110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
585110340c6SKai Nacke       return false;
586110340c6SKai Nacke     return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
587110340c6SKai Nacke         .addReg(Tmp2Reg, RegState::Kill)
588110340c6SKai Nacke         .addImm(Shift)
589110340c6SKai Nacke         .addImm(0)
590110340c6SKai Nacke         .constrainAllUses(TII, TRI, RBI);
591110340c6SKai Nacke   }
592110340c6SKai Nacke 
593110340c6SKai Nacke   // If we end up here then no instructions were inserted.
594110340c6SKai Nacke   return std::nullopt;
595110340c6SKai Nacke }
596110340c6SKai Nacke 
597110340c6SKai Nacke // Derived from PPCISelDAGToDAG::selectI64Imm().
598110340c6SKai Nacke // TODO: Add support for prefixed instructions.
selectI64Imm(MachineInstr & I,MachineBasicBlock & MBB,MachineRegisterInfo & MRI) const599110340c6SKai Nacke bool PPCInstructionSelector::selectI64Imm(MachineInstr &I,
600110340c6SKai Nacke                                           MachineBasicBlock &MBB,
601110340c6SKai Nacke                                           MachineRegisterInfo &MRI) const {
602110340c6SKai Nacke   assert(I.getOpcode() == TargetOpcode::G_CONSTANT && "Unexpected G code");
603110340c6SKai Nacke 
604110340c6SKai Nacke   Register DstReg = I.getOperand(0).getReg();
605110340c6SKai Nacke   int64_t Imm = I.getOperand(1).getCImm()->getValue().getZExtValue();
606110340c6SKai Nacke   // No more than 3 instructions are used if we can select the i64 immediate
607110340c6SKai Nacke   // directly.
608110340c6SKai Nacke   if (std::optional<bool> Res = selectI64ImmDirect(I, MBB, MRI, DstReg, Imm)) {
609110340c6SKai Nacke     I.eraseFromParent();
610110340c6SKai Nacke     return *Res;
611110340c6SKai Nacke   }
612110340c6SKai Nacke 
613110340c6SKai Nacke   // Calculate the last bits as required.
614110340c6SKai Nacke   uint32_t Hi16 = (Lo_32(Imm) >> 16) & 0xffff;
615110340c6SKai Nacke   uint32_t Lo16 = Lo_32(Imm) & 0xffff;
616110340c6SKai Nacke 
617110340c6SKai Nacke   Register Reg =
618110340c6SKai Nacke       (Hi16 || Lo16) ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;
619110340c6SKai Nacke 
620110340c6SKai Nacke   // Handle the upper 32 bit value.
621110340c6SKai Nacke   std::optional<bool> Res =
622110340c6SKai Nacke       selectI64ImmDirect(I, MBB, MRI, Reg, Imm & 0xffffffff00000000);
623110340c6SKai Nacke   if (!Res || !*Res)
624110340c6SKai Nacke     return false;
625110340c6SKai Nacke 
626110340c6SKai Nacke   // Add in the last bits as required.
627110340c6SKai Nacke   if (Hi16) {
628110340c6SKai Nacke     Register TmpReg =
629110340c6SKai Nacke         Lo16 ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;
630110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), TmpReg)
631110340c6SKai Nacke              .addReg(Reg, RegState::Kill)
632110340c6SKai Nacke              .addImm(Hi16)
633110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
634110340c6SKai Nacke       return false;
635110340c6SKai Nacke     Reg = TmpReg;
636110340c6SKai Nacke   }
637110340c6SKai Nacke   if (Lo16) {
638110340c6SKai Nacke     if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), DstReg)
639110340c6SKai Nacke              .addReg(Reg, RegState::Kill)
640110340c6SKai Nacke              .addImm(Lo16)
641110340c6SKai Nacke              .constrainAllUses(TII, TRI, RBI))
642110340c6SKai Nacke       return false;
643110340c6SKai Nacke   }
644110340c6SKai Nacke   I.eraseFromParent();
645110340c6SKai Nacke   return true;
646110340c6SKai Nacke }
647110340c6SKai Nacke 
selectConstantPool(MachineInstr & I,MachineBasicBlock & MBB,MachineRegisterInfo & MRI) const6486ee2f770SChen Zheng bool PPCInstructionSelector::selectConstantPool(
6496ee2f770SChen Zheng     MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const {
6506ee2f770SChen Zheng   const DebugLoc &DbgLoc = I.getDebugLoc();
6516ee2f770SChen Zheng   MachineFunction *MF = MBB.getParent();
6526ee2f770SChen Zheng 
6536ee2f770SChen Zheng   // TODO: handle 32-bit.
6546ee2f770SChen Zheng   // TODO: Enabling floating point constant pool selection on AIX requires
6556ee2f770SChen Zheng   // global isel on big endian target enabled first.
6566ee2f770SChen Zheng   // See CallLowering::enableBigEndian().
6576ee2f770SChen Zheng   if (!STI.isPPC64() || !STI.isLittleEndian())
6586ee2f770SChen Zheng     return false;
6596ee2f770SChen Zheng 
6606ee2f770SChen Zheng   MF->getInfo<PPCFunctionInfo>()->setUsesTOCBasePtr();
6616ee2f770SChen Zheng 
6626ee2f770SChen Zheng   const Register DstReg = I.getOperand(0).getReg();
6636ee2f770SChen Zheng   unsigned CPI = I.getOperand(1).getIndex();
6646ee2f770SChen Zheng 
6656ee2f770SChen Zheng   // Address stored in the TOC entry. This is related to code model and the ABI
6666ee2f770SChen Zheng   // we are currently using. For now we only handle 64-bit Linux LE. PowerPC
6676ee2f770SChen Zheng   // only supports small, medium and large code model.
6686ee2f770SChen Zheng   const CodeModel::Model CModel = TM.getCodeModel();
6696ee2f770SChen Zheng   assert(!(CModel == CodeModel::Tiny || CModel == CodeModel::Kernel) &&
6706ee2f770SChen Zheng          "PowerPC doesn't support tiny or kernel code models.");
6716ee2f770SChen Zheng 
6726ee2f770SChen Zheng   const MCRegister TOCReg = STI.getTOCPointerRegister();
6736ee2f770SChen Zheng   MachineMemOperand *MMO = MF->getMachineMemOperand(
6746ee2f770SChen Zheng       MachinePointerInfo::getGOT(*MF), MachineMemOperand::MOLoad,
6756ee2f770SChen Zheng       MRI.getType(DstReg), MF->getDataLayout().getPointerABIAlignment(0));
6766ee2f770SChen Zheng 
6776ee2f770SChen Zheng   MachineInstr *MI = nullptr;
6786ee2f770SChen Zheng   // For now we only handle 64-bit Linux.
6796ee2f770SChen Zheng   if (CModel == CodeModel::Small) {
6806ee2f770SChen Zheng     // For small code model, generate LDtocCPT(CPI, X2).
6816ee2f770SChen Zheng     MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::LDtocCPT), DstReg)
6826ee2f770SChen Zheng              .addConstantPoolIndex(CPI)
6836ee2f770SChen Zheng              .addReg(TOCReg)
6846ee2f770SChen Zheng              .addMemOperand(MMO);
6856ee2f770SChen Zheng   } else {
6866ee2f770SChen Zheng     Register HaAddrReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
6876ee2f770SChen Zheng     BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDIStocHA8), HaAddrReg)
6886ee2f770SChen Zheng         .addReg(TOCReg)
6896ee2f770SChen Zheng         .addConstantPoolIndex(CPI);
6906ee2f770SChen Zheng 
6916ee2f770SChen Zheng     if (CModel == CodeModel::Large)
6926ee2f770SChen Zheng       // For large code model, generate LDtocL(CPI, ADDIStocHA8(X2, CPI))
6936ee2f770SChen Zheng       MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::LDtocL), DstReg)
6946ee2f770SChen Zheng                .addConstantPoolIndex(CPI)
6956ee2f770SChen Zheng                .addReg(HaAddrReg)
6966ee2f770SChen Zheng                .addMemOperand(MMO);
6976ee2f770SChen Zheng     else
698cc761a7cSZaara Syeda       // For medium code model, generate ADDItocL8(CPI, ADDIStocHA8(X2, CPI))
699cc761a7cSZaara Syeda       MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDItocL8), DstReg)
7006ee2f770SChen Zheng                .addReg(HaAddrReg)
7016ee2f770SChen Zheng                .addConstantPoolIndex(CPI);
7026ee2f770SChen Zheng   }
7036ee2f770SChen Zheng 
7046ee2f770SChen Zheng   I.eraseFromParent();
7056ee2f770SChen Zheng   return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
7066ee2f770SChen Zheng }
7076ee2f770SChen Zheng 
select(MachineInstr & I)708009cd4e4SKit Barton bool PPCInstructionSelector::select(MachineInstr &I) {
709be4a1dfbSKai Nacke   auto &MBB = *I.getParent();
710be4a1dfbSKai Nacke   auto &MF = *MBB.getParent();
711be4a1dfbSKai Nacke   auto &MRI = MF.getRegInfo();
712be4a1dfbSKai Nacke 
713be4a1dfbSKai Nacke   if (!isPreISelGenericOpcode(I.getOpcode())) {
714be4a1dfbSKai Nacke     if (I.isCopy())
715be4a1dfbSKai Nacke       return selectCopy(I, TII, MRI, TRI, RBI);
716be4a1dfbSKai Nacke 
717be4a1dfbSKai Nacke     return true;
718be4a1dfbSKai Nacke   }
719be4a1dfbSKai Nacke 
720009cd4e4SKit Barton   if (selectImpl(I, *CoverageInfo))
721009cd4e4SKit Barton     return true;
7220a9b1c59SChen Zheng 
7230a9b1c59SChen Zheng   unsigned Opcode = I.getOpcode();
7240a9b1c59SChen Zheng 
7250a9b1c59SChen Zheng   switch (Opcode) {
7260a9b1c59SChen Zheng   default:
7270a9b1c59SChen Zheng     return false;
728503a935dSChen Zheng   case TargetOpcode::G_LOAD:
729503a935dSChen Zheng   case TargetOpcode::G_STORE: {
730503a935dSChen Zheng     GLoadStore &LdSt = cast<GLoadStore>(I);
731503a935dSChen Zheng     LLT PtrTy = MRI.getType(LdSt.getPointerReg());
732503a935dSChen Zheng 
733503a935dSChen Zheng     if (PtrTy != LLT::pointer(0, 64)) {
734503a935dSChen Zheng       LLVM_DEBUG(dbgs() << "Load/Store pointer has type: " << PtrTy
735503a935dSChen Zheng                         << ", expected: " << LLT::pointer(0, 64) << '\n');
736503a935dSChen Zheng       return false;
737503a935dSChen Zheng     }
738503a935dSChen Zheng 
739503a935dSChen Zheng     auto SelectLoadStoreAddressingMode = [&]() -> MachineInstr * {
740503a935dSChen Zheng       const unsigned NewOpc = selectLoadStoreOp(
741503a935dSChen Zheng           I.getOpcode(), RBI.getRegBank(LdSt.getReg(0), MRI, TRI)->getID(),
742*601e102bSDavid Green           LdSt.getMemSizeInBits().getValue());
743503a935dSChen Zheng 
744503a935dSChen Zheng       if (NewOpc == I.getOpcode())
745503a935dSChen Zheng         return nullptr;
746503a935dSChen Zheng 
747503a935dSChen Zheng       // For now, simply use DForm with load/store addr as base and 0 as imm.
748503a935dSChen Zheng       // FIXME: optimize load/store with some specific address patterns.
749503a935dSChen Zheng       I.setDesc(TII.get(NewOpc));
750503a935dSChen Zheng       Register AddrReg = I.getOperand(1).getReg();
751503a935dSChen Zheng       bool IsKill = I.getOperand(1).isKill();
752503a935dSChen Zheng       I.getOperand(1).ChangeToImmediate(0);
753503a935dSChen Zheng       I.addOperand(*I.getParent()->getParent(),
754503a935dSChen Zheng                    MachineOperand::CreateReg(AddrReg, /* isDef */ false,
755503a935dSChen Zheng                                              /* isImp */ false, IsKill));
756503a935dSChen Zheng       return &I;
757503a935dSChen Zheng     };
758503a935dSChen Zheng 
759503a935dSChen Zheng     MachineInstr *LoadStore = SelectLoadStoreAddressingMode();
760503a935dSChen Zheng     if (!LoadStore)
761503a935dSChen Zheng       return false;
762503a935dSChen Zheng 
763503a935dSChen Zheng     return constrainSelectedInstRegOperands(*LoadStore, TII, TRI, RBI);
764503a935dSChen Zheng   }
7650a9b1c59SChen Zheng   case TargetOpcode::G_SITOFP:
7660a9b1c59SChen Zheng   case TargetOpcode::G_UITOFP:
7670a9b1c59SChen Zheng     return selectIntToFP(I, MBB, MRI);
7680a9b1c59SChen Zheng   case TargetOpcode::G_FPTOSI:
7690a9b1c59SChen Zheng   case TargetOpcode::G_FPTOUI:
7700a9b1c59SChen Zheng     return selectFPToInt(I, MBB, MRI);
771b41d22dbSChen Zheng   // G_SEXT will be selected in tb-gen pattern.
772b41d22dbSChen Zheng   case TargetOpcode::G_ZEXT:
773b41d22dbSChen Zheng     return selectZExt(I, MBB, MRI);
774110340c6SKai Nacke   case TargetOpcode::G_CONSTANT:
775110340c6SKai Nacke     return selectI64Imm(I, MBB, MRI);
7766ee2f770SChen Zheng   case TargetOpcode::G_CONSTANT_POOL:
7776ee2f770SChen Zheng     return selectConstantPool(I, MBB, MRI);
7780a9b1c59SChen Zheng   }
779009cd4e4SKit Barton   return false;
780009cd4e4SKit Barton }
781009cd4e4SKit Barton 
782009cd4e4SKit Barton namespace llvm {
783009cd4e4SKit Barton InstructionSelector *
createPPCInstructionSelector(const PPCTargetMachine & TM,const PPCSubtarget & Subtarget,const PPCRegisterBankInfo & RBI)784009cd4e4SKit Barton createPPCInstructionSelector(const PPCTargetMachine &TM,
785009cd4e4SKit Barton                              const PPCSubtarget &Subtarget,
786009cd4e4SKit Barton                              const PPCRegisterBankInfo &RBI) {
787009cd4e4SKit Barton   return new PPCInstructionSelector(TM, Subtarget, RBI);
788009cd4e4SKit Barton }
789009cd4e4SKit Barton } // end namespace llvm
790