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