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