LLVM 17.0.0git
PPCInstructionSelector.cpp
Go to the documentation of this file.
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"
16#include "PPCRegisterBankInfo.h"
17#include "PPCSubtarget.h"
18#include "PPCTargetMachine.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,
53 bool selectIntToFP(MachineInstr &I, MachineBasicBlock &MBB,
55
56 bool selectZExt(MachineInstr &I, MachineBasicBlock &MBB,
58 bool selectConstantPool(MachineInstr &I, MachineBasicBlock &MBB,
60
61 std::optional<bool> selectI64ImmDirect(MachineInstr &I,
64 uint64_t Imm) 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),
95#include "PPCGenGlobalISel.inc"
98#include "PPCGenGlobalISel.inc"
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::CRRegBankID) {
117 if (Ty.getSizeInBits() == 1)
118 return &PPC::CRBITRCRegClass;
119 if (Ty.getSizeInBits() == 4)
120 return &PPC::CRRCRegClass;
121 }
122
123 llvm_unreachable("Unknown RegBank!");
124}
125
128 const RegisterBankInfo &RBI) {
129 Register DstReg = I.getOperand(0).getReg();
130
131 if (DstReg.isPhysical())
132 return true;
133
134 const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI);
135 const TargetRegisterClass *DstRC =
136 getRegClass(MRI.getType(DstReg), DstRegBank);
137
138 // No need to constrain SrcReg. It will get constrained when we hit another of
139 // its use or its defs.
140 // Copies do not have constraints.
141 if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
142 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
143 << " operand\n");
144 return false;
145 }
146
147 return true;
148}
149
150static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID,
151 unsigned OpSize) {
152 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
153 switch (RegBankID) {
154 case PPC::GPRRegBankID:
155 switch (OpSize) {
156 case 32:
157 return IsStore ? PPC::STW : PPC::LWZ;
158 case 64:
159 return IsStore ? PPC::STD : PPC::LD;
160 default:
161 llvm_unreachable("Unexpected size!");
162 }
163 break;
164 case PPC::FPRRegBankID:
165 switch (OpSize) {
166 case 32:
167 return IsStore ? PPC::STFS : PPC::LFS;
168 case 64:
169 return IsStore ? PPC::STFD : PPC::LFD;
170 default:
171 llvm_unreachable("Unexpected size!");
172 }
173 break;
174 default:
175 llvm_unreachable("Unexpected register bank!");
176 }
177 return GenericOpc;
178}
179
180bool PPCInstructionSelector::selectIntToFP(MachineInstr &I,
182 MachineRegisterInfo &MRI) const {
183 if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())
184 return false;
185
186 const DebugLoc &DbgLoc = I.getDebugLoc();
187 const Register DstReg = I.getOperand(0).getReg();
188 const Register SrcReg = I.getOperand(1).getReg();
189
190 Register MoveReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);
191
192 // For now, only handle the case for 64 bit integer.
193 BuildMI(MBB, I, DbgLoc, TII.get(PPC::MTVSRD), MoveReg).addReg(SrcReg);
194
195 bool IsSingle = MRI.getType(DstReg).getSizeInBits() == 32;
196 bool IsSigned = I.getOpcode() == TargetOpcode::G_SITOFP;
197 unsigned ConvOp = IsSingle ? (IsSigned ? PPC::XSCVSXDSP : PPC::XSCVUXDSP)
198 : (IsSigned ? PPC::XSCVSXDDP : PPC::XSCVUXDDP);
199
201 BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), DstReg).addReg(MoveReg);
202
203 I.eraseFromParent();
205}
206
207bool PPCInstructionSelector::selectFPToInt(MachineInstr &I,
209 MachineRegisterInfo &MRI) const {
210 if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())
211 return false;
212
213 const DebugLoc &DbgLoc = I.getDebugLoc();
214 const Register DstReg = I.getOperand(0).getReg();
215 const Register SrcReg = I.getOperand(1).getReg();
216
217 Register CopyReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);
218 BuildMI(MBB, I, DbgLoc, TII.get(TargetOpcode::COPY), CopyReg).addReg(SrcReg);
219
220 Register ConvReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);
221
222 bool IsSigned = I.getOpcode() == TargetOpcode::G_FPTOSI;
223
224 // single-precision is stored as double-precision on PPC in registers, so
225 // always use double-precision convertions.
226 unsigned ConvOp = IsSigned ? PPC::XSCVDPSXDS : PPC::XSCVDPUXDS;
227
228 BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), ConvReg).addReg(CopyReg);
229
231 BuildMI(MBB, I, DbgLoc, TII.get(PPC::MFVSRD), DstReg).addReg(ConvReg);
232
233 I.eraseFromParent();
235}
236
237bool PPCInstructionSelector::selectZExt(MachineInstr &I, MachineBasicBlock &MBB,
238 MachineRegisterInfo &MRI) const {
239 const Register DstReg = I.getOperand(0).getReg();
240 const LLT DstTy = MRI.getType(DstReg);
241 const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI);
242
243 const Register SrcReg = I.getOperand(1).getReg();
244
245 assert(DstTy.getSizeInBits() == 64 && "Unexpected dest size!");
246 assert(MRI.getType(SrcReg).getSizeInBits() == 32 && "Unexpected src size!");
247
248 Register ImpDefReg =
249 MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank));
250 BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::IMPLICIT_DEF),
251 ImpDefReg);
252
253 Register NewDefReg =
254 MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank));
255 BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::INSERT_SUBREG),
256 NewDefReg)
257 .addReg(ImpDefReg)
258 .addReg(SrcReg)
259 .addImm(PPC::sub_32);
260
262 BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), DstReg)
263 .addReg(NewDefReg)
264 .addImm(0)
265 .addImm(32);
266
267 I.eraseFromParent();
269}
270
271// For any 32 < Num < 64, check if the Imm contains at least Num consecutive
272// zeros and return the number of bits by the left of these consecutive zeros.
274 uint32_t HiTZ = llvm::countr_zero<uint32_t>(Hi_32(Imm));
275 uint32_t LoLZ = llvm::countl_zero<uint32_t>(Lo_32(Imm));
276 if ((HiTZ + LoLZ) >= Num)
277 return (32 + HiTZ);
278 return 0;
279}
280
281// Direct materialization of 64-bit constants by enumerated patterns.
282// Similar to PPCISelDAGToDAG::selectI64ImmDirect().
283std::optional<bool> PPCInstructionSelector::selectI64ImmDirect(MachineInstr &I,
286 Register Reg,
287 uint64_t Imm) const {
288 unsigned TZ = llvm::countr_zero<uint64_t>(Imm);
289 unsigned LZ = llvm::countl_zero<uint64_t>(Imm);
290 unsigned TO = llvm::countr_one<uint64_t>(Imm);
291 unsigned LO = llvm::countl_one<uint64_t>(Imm);
292 uint32_t Hi32 = Hi_32(Imm);
293 uint32_t Lo32 = Lo_32(Imm);
294 uint32_t Shift = 0;
295
296 // Following patterns use 1 instructions to materialize the Imm.
297
298 // 1-1) Patterns : {zeros}{15-bit valve}
299 // {ones}{15-bit valve}
300 if (isInt<16>(Imm))
301 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), Reg)
302 .addImm(Imm)
303 .constrainAllUses(TII, TRI, RBI);
304 // 1-2) Patterns : {zeros}{15-bit valve}{16 zeros}
305 // {ones}{15-bit valve}{16 zeros}
306 if (TZ > 15 && (LZ > 32 || LO > 32))
307 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), Reg)
308 .addImm((Imm >> 16) & 0xffff)
309 .constrainAllUses(TII, TRI, RBI);
310
311 // Following patterns use 2 instructions to materialize the Imm.
312
313 assert(LZ < 64 && "Unexpected leading zeros here.");
314 // Count of ones follwing the leading zeros.
315 unsigned FO = llvm::countl_one<uint64_t>(Imm << LZ);
316 // 2-1) Patterns : {zeros}{31-bit value}
317 // {ones}{31-bit value}
318 if (isInt<32>(Imm)) {
319 uint64_t ImmHi16 = (Imm >> 16) & 0xffff;
320 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
321 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
322 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
323 .addImm((Imm >> 16) & 0xffff)
324 .constrainAllUses(TII, TRI, RBI))
325 return false;
326 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Reg)
327 .addReg(TmpReg, RegState::Kill)
328 .addImm(Imm & 0xffff)
329 .constrainAllUses(TII, TRI, RBI);
330 }
331 // 2-2) Patterns : {zeros}{ones}{15-bit value}{zeros}
332 // {zeros}{15-bit value}{zeros}
333 // {zeros}{ones}{15-bit value}
334 // {ones}{15-bit value}{zeros}
335 // We can take advantage of LI's sign-extension semantics to generate leading
336 // ones, and then use RLDIC to mask off the ones in both sides after rotation.
337 if ((LZ + FO + TZ) > 48) {
338 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
339 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
340 .addImm((Imm >> TZ) & 0xffff)
341 .constrainAllUses(TII, TRI, RBI))
342 return false;
343 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg)
344 .addReg(TmpReg, RegState::Kill)
345 .addImm(TZ)
346 .addImm(LZ)
347 .constrainAllUses(TII, TRI, RBI);
348 }
349 // 2-3) Pattern : {zeros}{15-bit value}{ones}
350 // Shift right the Imm by (48 - LZ) bits to construct a negtive 16 bits value,
351 // therefore we can take advantage of LI's sign-extension semantics, and then
352 // mask them off after rotation.
353 //
354 // +--LZ--||-15-bit-||--TO--+ +-------------|--16-bit--+
355 // |00000001bbbbbbbbb1111111| -> |00000000000001bbbbbbbbb1|
356 // +------------------------+ +------------------------+
357 // 63 0 63 0
358 // Imm (Imm >> (48 - LZ) & 0xffff)
359 // +----sext-----|--16-bit--+ +clear-|-----------------+
360 // |11111111111111bbbbbbbbb1| -> |00000001bbbbbbbbb1111111|
361 // +------------------------+ +------------------------+
362 // 63 0 63 0
363 // LI8: sext many leading zeros RLDICL: rotate left (48 - LZ), clear left LZ
364 if ((LZ + TO) > 48) {
365 // Since the immediates with (LZ > 32) have been handled by previous
366 // patterns, here we have (LZ <= 32) to make sure we will not shift right
367 // the Imm by a negative value.
368 assert(LZ <= 32 && "Unexpected shift value.");
369 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
370 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
371 .addImm(Imm >> (48 - LZ) & 0xffff)
372 .constrainAllUses(TII, TRI, RBI))
373 return false;
374 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
375 .addReg(TmpReg, RegState::Kill)
376 .addImm(48 - LZ)
377 .addImm(LZ)
378 .constrainAllUses(TII, TRI, RBI);
379 }
380 // 2-4) Patterns : {zeros}{ones}{15-bit value}{ones}
381 // {ones}{15-bit value}{ones}
382 // We can take advantage of LI's sign-extension semantics to generate leading
383 // ones, and then use RLDICL to mask off the ones in left sides (if required)
384 // after rotation.
385 //
386 // +-LZ-FO||-15-bit-||--TO--+ +-------------|--16-bit--+
387 // |00011110bbbbbbbbb1111111| -> |000000000011110bbbbbbbbb|
388 // +------------------------+ +------------------------+
389 // 63 0 63 0
390 // Imm (Imm >> TO) & 0xffff
391 // +----sext-----|--16-bit--+ +LZ|---------------------+
392 // |111111111111110bbbbbbbbb| -> |00011110bbbbbbbbb1111111|
393 // +------------------------+ +------------------------+
394 // 63 0 63 0
395 // LI8: sext many leading zeros RLDICL: rotate left TO, clear left LZ
396 if ((LZ + FO + TO) > 48) {
397 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
398 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
399 .addImm((Imm >> TO) & 0xffff)
400 .constrainAllUses(TII, TRI, RBI))
401 return false;
402 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
403 .addReg(TmpReg, RegState::Kill)
404 .addImm(TO)
405 .addImm(LZ)
406 .constrainAllUses(TII, TRI, RBI);
407 }
408 // 2-5) Pattern : {32 zeros}{****}{0}{15-bit value}
409 // If Hi32 is zero and the Lo16(in Lo32) can be presented as a positive 16 bit
410 // value, we can use LI for Lo16 without generating leading ones then add the
411 // Hi16(in Lo32).
412 if (LZ == 32 && ((Lo32 & 0x8000) == 0)) {
413 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
414 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
415 .addImm(Lo32 & 0xffff)
416 .constrainAllUses(TII, TRI, RBI))
417 return false;
418 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), Reg)
419 .addReg(TmpReg, RegState::Kill)
420 .addImm(Lo32 >> 16)
421 .constrainAllUses(TII, TRI, RBI);
422 }
423 // 2-6) Patterns : {******}{49 zeros}{******}
424 // {******}{49 ones}{******}
425 // If the Imm contains 49 consecutive zeros/ones, it means that a total of 15
426 // bits remain on both sides. Rotate right the Imm to construct an int<16>
427 // value, use LI for int<16> value and then use RLDICL without mask to rotate
428 // it back.
429 //
430 // 1) findContiguousZerosAtLeast(Imm, 49)
431 // +------|--zeros-|------+ +---ones--||---15 bit--+
432 // |bbbbbb0000000000aaaaaa| -> |0000000000aaaaaabbbbbb|
433 // +----------------------+ +----------------------+
434 // 63 0 63 0
435 //
436 // 2) findContiguousZerosAtLeast(~Imm, 49)
437 // +------|--ones--|------+ +---ones--||---15 bit--+
438 // |bbbbbb1111111111aaaaaa| -> |1111111111aaaaaabbbbbb|
439 // +----------------------+ +----------------------+
440 // 63 0 63 0
441 if ((Shift = findContiguousZerosAtLeast(Imm, 49)) ||
442 (Shift = findContiguousZerosAtLeast(~Imm, 49))) {
443 uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
444 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
445 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
446 .addImm(RotImm & 0xffff)
447 .constrainAllUses(TII, TRI, RBI))
448 return false;
449 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
450 .addReg(TmpReg, RegState::Kill)
451 .addImm(Shift)
452 .addImm(0)
453 .constrainAllUses(TII, TRI, RBI);
454 }
455
456 // Following patterns use 3 instructions to materialize the Imm.
457
458 // 3-1) Patterns : {zeros}{ones}{31-bit value}{zeros}
459 // {zeros}{31-bit value}{zeros}
460 // {zeros}{ones}{31-bit value}
461 // {ones}{31-bit value}{zeros}
462 // We can take advantage of LIS's sign-extension semantics to generate leading
463 // ones, add the remaining bits with ORI, and then use RLDIC to mask off the
464 // ones in both sides after rotation.
465 if ((LZ + FO + TZ) > 32) {
466 uint64_t ImmHi16 = (Imm >> (TZ + 16)) & 0xffff;
467 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
468 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
469 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
470 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
471 .addImm(ImmHi16)
472 .constrainAllUses(TII, TRI, RBI))
473 return false;
474 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
475 .addReg(TmpReg, RegState::Kill)
476 .addImm((Imm >> TZ) & 0xffff)
477 .constrainAllUses(TII, TRI, RBI))
478 return false;
479 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg)
480 .addReg(Tmp2Reg, RegState::Kill)
481 .addImm(TZ)
482 .addImm(LZ)
483 .constrainAllUses(TII, TRI, RBI);
484 }
485 // 3-2) Pattern : {zeros}{31-bit value}{ones}
486 // Shift right the Imm by (32 - LZ) bits to construct a negative 32 bits
487 // value, therefore we can take advantage of LIS's sign-extension semantics,
488 // add the remaining bits with ORI, and then mask them off after rotation.
489 // This is similar to Pattern 2-3, please refer to the diagram there.
490 if ((LZ + TO) > 32) {
491 // Since the immediates with (LZ > 32) have been handled by previous
492 // patterns, here we have (LZ <= 32) to make sure we will not shift right
493 // the Imm by a negative value.
494 assert(LZ <= 32 && "Unexpected shift value.");
495 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
496 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
497 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg)
498 .addImm((Imm >> (48 - LZ)) & 0xffff)
499 .constrainAllUses(TII, TRI, RBI))
500 return false;
501 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
502 .addReg(TmpReg, RegState::Kill)
503 .addImm((Imm >> (32 - LZ)) & 0xffff)
504 .constrainAllUses(TII, TRI, RBI))
505 return false;
506 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
507 .addReg(Tmp2Reg, RegState::Kill)
508 .addImm(32 - LZ)
509 .addImm(LZ)
510 .constrainAllUses(TII, TRI, RBI);
511 }
512 // 3-3) Patterns : {zeros}{ones}{31-bit value}{ones}
513 // {ones}{31-bit value}{ones}
514 // We can take advantage of LIS's sign-extension semantics to generate leading
515 // ones, add the remaining bits with ORI, and then use RLDICL to mask off the
516 // ones in left sides (if required) after rotation.
517 // This is similar to Pattern 2-4, please refer to the diagram there.
518 if ((LZ + FO + TO) > 32) {
519 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
520 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
521 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg)
522 .addImm((Imm >> (TO + 16)) & 0xffff)
523 .constrainAllUses(TII, TRI, RBI))
524 return false;
525 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
526 .addReg(TmpReg, RegState::Kill)
527 .addImm((Imm >> TO) & 0xffff)
528 .constrainAllUses(TII, TRI, RBI))
529 return false;
530 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
531 .addReg(Tmp2Reg, RegState::Kill)
532 .addImm(TO)
533 .addImm(LZ)
534 .constrainAllUses(TII, TRI, RBI);
535 }
536 // 3-4) Patterns : High word == Low word
537 if (Hi32 == Lo32) {
538 // Handle the first 32 bits.
539 uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff;
540 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
541 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
542 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
543 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
544 .addImm(ImmHi16)
545 .constrainAllUses(TII, TRI, RBI))
546 return false;
547 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
548 .addReg(TmpReg, RegState::Kill)
549 .addImm(Lo32 & 0xffff)
550 .constrainAllUses(TII, TRI, RBI))
551 return false;
552 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIMI), Reg)
553 .addReg(Tmp2Reg)
554 .addReg(Tmp2Reg, RegState::Kill)
555 .addImm(32)
556 .addImm(0)
557 .constrainAllUses(TII, TRI, RBI);
558 }
559 // 3-5) Patterns : {******}{33 zeros}{******}
560 // {******}{33 ones}{******}
561 // If the Imm contains 33 consecutive zeros/ones, it means that a total of 31
562 // bits remain on both sides. Rotate right the Imm to construct an int<32>
563 // value, use LIS + ORI for int<32> value and then use RLDICL without mask to
564 // rotate it back.
565 // This is similar to Pattern 2-6, please refer to the diagram there.
566 if ((Shift = findContiguousZerosAtLeast(Imm, 33)) ||
567 (Shift = findContiguousZerosAtLeast(~Imm, 33))) {
568 uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
569 uint64_t ImmHi16 = (RotImm >> 16) & 0xffff;
570 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
571 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
572 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
573 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
574 .addImm(ImmHi16)
575 .constrainAllUses(TII, TRI, RBI))
576 return false;
577 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
578 .addReg(TmpReg, RegState::Kill)
579 .addImm(RotImm & 0xffff)
580 .constrainAllUses(TII, TRI, RBI))
581 return false;
582 return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
583 .addReg(Tmp2Reg, RegState::Kill)
584 .addImm(Shift)
585 .addImm(0)
586 .constrainAllUses(TII, TRI, RBI);
587 }
588
589 // If we end up here then no instructions were inserted.
590 return std::nullopt;
591}
592
593// Derived from PPCISelDAGToDAG::selectI64Imm().
594// TODO: Add support for prefixed instructions.
595bool PPCInstructionSelector::selectI64Imm(MachineInstr &I,
597 MachineRegisterInfo &MRI) const {
598 assert(I.getOpcode() == TargetOpcode::G_CONSTANT && "Unexpected G code");
599
600 Register DstReg = I.getOperand(0).getReg();
601 int64_t Imm = I.getOperand(1).getCImm()->getValue().getZExtValue();
602 // No more than 3 instructions are used if we can select the i64 immediate
603 // directly.
604 if (std::optional<bool> Res = selectI64ImmDirect(I, MBB, MRI, DstReg, Imm)) {
605 I.eraseFromParent();
606 return *Res;
607 }
608
609 // Calculate the last bits as required.
610 uint32_t Hi16 = (Lo_32(Imm) >> 16) & 0xffff;
611 uint32_t Lo16 = Lo_32(Imm) & 0xffff;
612
613 Register Reg =
614 (Hi16 || Lo16) ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;
615
616 // Handle the upper 32 bit value.
617 std::optional<bool> Res =
618 selectI64ImmDirect(I, MBB, MRI, Reg, Imm & 0xffffffff00000000);
619 if (!Res || !*Res)
620 return false;
621
622 // Add in the last bits as required.
623 if (Hi16) {
624 Register TmpReg =
625 Lo16 ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;
626 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), TmpReg)
628 .addImm(Hi16)
629 .constrainAllUses(TII, TRI, RBI))
630 return false;
631 Reg = TmpReg;
632 }
633 if (Lo16) {
634 if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), DstReg)
636 .addImm(Lo16)
637 .constrainAllUses(TII, TRI, RBI))
638 return false;
639 }
640 I.eraseFromParent();
641 return true;
642}
643
644bool PPCInstructionSelector::selectConstantPool(
646 const DebugLoc &DbgLoc = I.getDebugLoc();
648
649 // TODO: handle 32-bit.
650 // TODO: Enabling floating point constant pool selection on AIX requires
651 // global isel on big endian target enabled first.
652 // See CallLowering::enableBigEndian().
653 if (!STI.isPPC64() || !STI.isLittleEndian())
654 return false;
655
657
658 const Register DstReg = I.getOperand(0).getReg();
659 unsigned CPI = I.getOperand(1).getIndex();
660
661 // Address stored in the TOC entry. This is related to code model and the ABI
662 // we are currently using. For now we only handle 64-bit Linux LE. PowerPC
663 // only supports small, medium and large code model.
664 const CodeModel::Model CModel = TM.getCodeModel();
665 assert(!(CModel == CodeModel::Tiny || CModel == CodeModel::Kernel) &&
666 "PowerPC doesn't support tiny or kernel code models.");
667
668 const MCRegister TOCReg = STI.getTOCPointerRegister();
671 MRI.getType(DstReg), MF->getDataLayout().getPointerABIAlignment(0));
672
673 MachineInstr *MI = nullptr;
674 // For now we only handle 64-bit Linux.
675 if (CModel == CodeModel::Small) {
676 // For small code model, generate LDtocCPT(CPI, X2).
677 MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::LDtocCPT), DstReg)
679 .addReg(TOCReg)
680 .addMemOperand(MMO);
681 } else {
682 Register HaAddrReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
683 BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDIStocHA8), HaAddrReg)
684 .addReg(TOCReg)
686
687 if (CModel == CodeModel::Large)
688 // For large code model, generate LDtocL(CPI, ADDIStocHA8(X2, CPI))
689 MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::LDtocL), DstReg)
691 .addReg(HaAddrReg)
692 .addMemOperand(MMO);
693 else
694 // For medium code model, generate ADDItocL(CPI, ADDIStocHA8(X2, CPI))
695 MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDItocL), DstReg)
696 .addReg(HaAddrReg)
698 }
699
700 I.eraseFromParent();
702}
703
704bool PPCInstructionSelector::select(MachineInstr &I) {
705 auto &MBB = *I.getParent();
706 auto &MF = *MBB.getParent();
707 auto &MRI = MF.getRegInfo();
708
709 if (!isPreISelGenericOpcode(I.getOpcode())) {
710 if (I.isCopy())
711 return selectCopy(I, TII, MRI, TRI, RBI);
712
713 return true;
714 }
715
716 if (selectImpl(I, *CoverageInfo))
717 return true;
718
719 unsigned Opcode = I.getOpcode();
720
721 switch (Opcode) {
722 default:
723 return false;
724 case TargetOpcode::G_LOAD:
725 case TargetOpcode::G_STORE: {
726 GLoadStore &LdSt = cast<GLoadStore>(I);
727 LLT PtrTy = MRI.getType(LdSt.getPointerReg());
728
729 if (PtrTy != LLT::pointer(0, 64)) {
730 LLVM_DEBUG(dbgs() << "Load/Store pointer has type: " << PtrTy
731 << ", expected: " << LLT::pointer(0, 64) << '\n');
732 return false;
733 }
734
735 auto SelectLoadStoreAddressingMode = [&]() -> MachineInstr * {
736 const unsigned NewOpc = selectLoadStoreOp(
737 I.getOpcode(), RBI.getRegBank(LdSt.getReg(0), MRI, TRI)->getID(),
738 LdSt.getMemSizeInBits());
739
740 if (NewOpc == I.getOpcode())
741 return nullptr;
742
743 // For now, simply use DForm with load/store addr as base and 0 as imm.
744 // FIXME: optimize load/store with some specific address patterns.
745 I.setDesc(TII.get(NewOpc));
746 Register AddrReg = I.getOperand(1).getReg();
747 bool IsKill = I.getOperand(1).isKill();
748 I.getOperand(1).ChangeToImmediate(0);
749 I.addOperand(*I.getParent()->getParent(),
750 MachineOperand::CreateReg(AddrReg, /* isDef */ false,
751 /* isImp */ false, IsKill));
752 return &I;
753 };
754
755 MachineInstr *LoadStore = SelectLoadStoreAddressingMode();
756 if (!LoadStore)
757 return false;
758
759 return constrainSelectedInstRegOperands(*LoadStore, TII, TRI, RBI);
760 }
761 case TargetOpcode::G_SITOFP:
762 case TargetOpcode::G_UITOFP:
763 return selectIntToFP(I, MBB, MRI);
764 case TargetOpcode::G_FPTOSI:
765 case TargetOpcode::G_FPTOUI:
766 return selectFPToInt(I, MBB, MRI);
767 // G_SEXT will be selected in tb-gen pattern.
768 case TargetOpcode::G_ZEXT:
769 return selectZExt(I, MBB, MRI);
770 case TargetOpcode::G_CONSTANT:
771 return selectI64Imm(I, MBB, MRI);
772 case TargetOpcode::G_CONSTANT_POOL:
773 return selectConstantPool(I, MBB, MRI);
774 }
775 return false;
776}
777
778namespace llvm {
781 const PPCSubtarget &Subtarget,
782 const PPCRegisterBankInfo &RBI) {
783 return new PPCInstructionSelector(TM, Subtarget, RBI);
784}
785} // end namespace llvm
unsigned const MachineRegisterInfo * MRI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
MachineBasicBlock & MBB
#define LLVM_DEBUG(X)
Definition: Debug.h:101
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
unsigned const TargetRegisterInfo * TRI
static SDNode * selectI64ImmDirect(SelectionDAG *CurDAG, const SDLoc &dl, uint64_t Imm, unsigned &InstCnt)
static SDNode * selectI64Imm(SelectionDAG *CurDAG, const SDLoc &dl, uint64_t Imm, unsigned *InstCnt=nullptr)
static void setUsesTOCBasePtr(MachineFunction &MF)
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static uint32_t findContiguousZerosAtLeast(uint64_t Imm, unsigned Num)
static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
This file declares the targeting of the RegisterBankInfo class for PowerPC.
const char LLVMTargetMachineRef TM
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Class for arbitrary precision integers.
Definition: APInt.h:75
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1494
APInt rotr(unsigned rotateAmt) const
Rotate right by rotateAmt.
Definition: APInt.cpp:1116
Align getPointerABIAlignment(unsigned AS) const
Layout pointer alignment.
Definition: DataLayout.cpp:720
A debug info location.
Definition: DebugLoc.h:33
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
uint64_t getMemSizeInBits() const
Returns the size in bits of the memory access.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
Provides the logic to select generic machine instructions.
virtual bool select(MachineInstr &I)=0
Select the (possibly generic) instruction I to only use target-specific opcodes.
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:24
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
Definition: MachineInstr.h:68
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
PPCFunctionInfo - This class is derived from MachineFunction private PowerPC target-specific informat...
Common code between 32-bit and 64-bit PowerPC targets.
Holds all the information related to register banks.
static const TargetRegisterClass * constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
Definition: RegisterBank.h:28
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:47
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:97
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition: Utils.cpp:152
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
Definition: TargetOpcodes.h:30
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition: MathExtras.h:164
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition: MathExtras.h:169
InstructionSelector * createPPCInstructionSelector(const PPCTargetMachine &TM, const PPCSubtarget &Subtarget, const PPCRegisterBankInfo &RBI)
static MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.