LLVM: lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

25#include "llvm/IR/IntrinsicsPowerPC.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

39public:

42

45

46private:

47

48

50

55

60

67

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}

84

85#define GET_GLOBALISEL_IMPL

86#include "PPCGenGlobalISel.inc"

87#undef GET_GLOBALISEL_IMPL

88

89PPCInstructionSelector::PPCInstructionSelector(const PPCTargetMachine &TM,

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

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

128}

129

133 Register DstReg = I.getOperand(0).getReg();

134

136 return true;

137

141

142

143

144

146 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())

147 << " operand\n");

148 return false;

149 }

150

151 return true;

152}

153

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:

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:

176 }

177 break;

178 default:

180 }

181 return GenericOpc;

182}

183

184bool PPCInstructionSelector::selectIntToFP(MachineInstr &I,

187 if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())

188 return false;

189

190 const DebugLoc &DbgLoc = I.getDebugLoc();

191 const Register DstReg = I.getOperand(0).getReg();

192 const Register SrcReg = I.getOperand(1).getReg();

193

195

196

198

199 bool IsSingle = MRI.getType(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 =

206

207 I.eraseFromParent();

209}

210

211bool PPCInstructionSelector::selectFPToInt(MachineInstr &I,

212 MachineBasicBlock &MBB,

213 MachineRegisterInfo &MRI) const {

214 if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())

215 return false;

216

217 const DebugLoc &DbgLoc = I.getDebugLoc();

218 const Register DstReg = I.getOperand(0).getReg();

219 const Register SrcReg = I.getOperand(1).getReg();

220

221 Register CopyReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);

223

224 Register ConvReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);

225

226 bool IsSigned = I.getOpcode() == TargetOpcode::G_FPTOSI;

227

228

229

230 unsigned ConvOp = IsSigned ? PPC::XSCVDPSXDS : PPC::XSCVDPUXDS;

231

233

234 MachineInstr *MI =

236

237 I.eraseFromParent();

239}

240

241bool PPCInstructionSelector::selectZExt(MachineInstr &I, MachineBasicBlock &MBB,

242 MachineRegisterInfo &MRI) const {

243 const Register DstReg = I.getOperand(0).getReg();

244 const LLT DstTy = MRI.getType(DstReg);

245 const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI);

246

247 const Register SrcReg = I.getOperand(1).getReg();

248

250 assert(MRI.getType(SrcReg).getSizeInBits() == 32 && "Unexpected src size!");

251

253 MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank));

254 BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::IMPLICIT_DEF),

255 ImpDefReg);

256

258 MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank));

259 BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::INSERT_SUBREG),

260 NewDefReg)

263 .addImm(PPC::sub_32);

264

265 MachineInstr *MI =

270

271 I.eraseFromParent();

273}

274

275

276

280 if ((HiTZ + LoLZ) >= Num)

281 return (32 + HiTZ);

282 return 0;

283}

284

285

286

287std::optional PPCInstructionSelector::selectI64ImmDirect(MachineInstr &I,

288 MachineBasicBlock &MBB,

289 MachineRegisterInfo &MRI,

291 uint64_t Imm) const {

296 uint32_t Hi32 = Hi_32(Imm);

297 uint32_t Lo32 = Lo_32(Imm);

298 uint32_t Shift = 0;

299

300

301

302

303

308

309

310 if (TZ > 15 && (LZ > 32 || LO > 32))

312 .addImm((Imm >> 16) & 0xffff)

314

315

316

317 assert(LZ < 64 && "Unexpected leading zeros here.");

318

320

321

323 uint64_t ImmHi16 = (Imm >> 16) & 0xffff;

324 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;

325 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

327 .addImm((Imm >> 16) & 0xffff)

329 return false;

332 .addImm(Imm & 0xffff)

334 }

335

336

337

338

339

340

341 if ((LZ + FO + TZ) > 48) {

342 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

344 .addImm((Imm >> TZ) & 0xffff)

346 return false;

352 }

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368 if ((LZ + TO) > 48) {

369

370

371

372 assert(LZ <= 32 && "Unexpected shift value.");

373 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

375 .addImm(Imm >> (48 - LZ) & 0xffff)

377 return false;

383 }

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400 if ((LZ + FO + TO) > 48) {

401 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

403 .addImm((Imm >> TO) & 0xffff)

405 return false;

411 }

412

413

414

415

416 if (LZ == 32 && ((Lo32 & 0x8000) == 0)) {

417 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

419 .addImm(Lo32 & 0xffff)

421 return false;

426 }

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

447 uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();

448 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

450 .addImm(RotImm & 0xffff)

452 return false;

458 }

459

460

461

462

463

464

465

466

467

468

469 if ((LZ + FO + TZ) > 32) {

470 uint64_t ImmHi16 = (Imm >> (TZ + 16)) & 0xffff;

471 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;

472 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

473 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

477 return false;

480 .addImm((Imm >> TZ) & 0xffff)

482 return false;

488 }

489

490

491

492

493

494 if ((LZ + TO) > 32) {

495

496

497

498 assert(LZ <= 32 && "Unexpected shift value.");

499 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

500 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

502 .addImm((Imm >> (48 - LZ)) & 0xffff)

504 return false;

507 .addImm((Imm >> (32 - LZ)) & 0xffff)

509 return false;

515 }

516

517

518

519

520

521

522 if ((LZ + FO + TO) > 32) {

523 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

524 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

526 .addImm((Imm >> (TO + 16)) & 0xffff)

528 return false;

531 .addImm((Imm >> TO) & 0xffff)

533 return false;

539 }

540

541 if (Hi32 == Lo32) {

542

543 uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff;

544 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;

545 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

546 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

550 return false;

553 .addImm(Lo32 & 0xffff)

555 return false;

562 }

563

564

565

566

567

568

569

572 uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();

573 uint64_t ImmHi16 = (RotImm >> 16) & 0xffff;

574 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;

575 Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

576 Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

580 return false;

583 .addImm(RotImm & 0xffff)

585 return false;

591 }

592

593

594 return std::nullopt;

595}

596

597

598

599bool PPCInstructionSelector::selectI64Imm(MachineInstr &I,

600 MachineBasicBlock &MBB,

601 MachineRegisterInfo &MRI) const {

602 assert(I.getOpcode() == TargetOpcode::G_CONSTANT && "Unexpected G code");

603

604 Register DstReg = I.getOperand(0).getReg();

605 int64_t Imm = I.getOperand(1).getCImm()->getValue().getZExtValue();

606

607

609 I.eraseFromParent();

610 return *Res;

611 }

612

613

614 uint32_t Hi16 = (Lo_32(Imm) >> 16) & 0xffff;

615 uint32_t Lo16 = Lo_32(Imm) & 0xffff;

616

618 (Hi16 || Lo16) ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;

619

620

621 std::optional Res =

623 if (!Res || !*Res)

624 return false;

625

626

627 if (Hi16) {

629 Lo16 ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;

634 return false;

635 Reg = TmpReg;

636 }

637 if (Lo16) {

642 return false;

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();

652

653

654

655

656

658 return false;

659

661

662 const Register DstReg = I.getOperand(0).getReg();

663 unsigned CPI = I.getOperand(1).getIndex();

664

665

666

667

670 "PowerPC doesn't support tiny or kernel code models.");

671

676

677 MachineInstr *MI = nullptr;

678

680

685 } else {

686 Register HaAddrReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);

690

692

697 else

698

702 }

703

704 I.eraseFromParent();

706}

707

708bool PPCInstructionSelector::select(MachineInstr &I) {

712

714 if (I.isCopy())

716

717 return true;

718 }

719

720 if (selectImpl(I, *CoverageInfo))

721 return true;

722

723 unsigned Opcode = I.getOpcode();

724

725 switch (Opcode) {

726 default:

727 return false;

728 case TargetOpcode::G_LOAD:

729 case TargetOpcode::G_STORE: {

732

734 LLVM_DEBUG(dbgs() << "Load/Store pointer has type: " << PtrTy

735 << ", expected: " << LLT::pointer(0, 64) << '\n');

736 return false;

737 }

738

739 auto SelectLoadStoreAddressingMode = [&]() -> MachineInstr * {

743

744 if (NewOpc == I.getOpcode())

745 return nullptr;

746

747

748

749 I.setDesc(TII.get(NewOpc));

750 Register AddrReg = I.getOperand(1).getReg();

751 bool IsKill = I.getOperand(1).isKill();

752 I.getOperand(1).ChangeToImmediate(0);

753 I.addOperand(*I.getParent()->getParent(),

755 false, IsKill));

756 return &I;

757 };

758

759 MachineInstr *LoadStore = SelectLoadStoreAddressingMode();

760 if (!LoadStore)

761 return false;

762

764 }

765 case TargetOpcode::G_SITOFP:

766 case TargetOpcode::G_UITOFP:

767 return selectIntToFP(I, MBB, MRI);

768 case TargetOpcode::G_FPTOSI:

769 case TargetOpcode::G_FPTOUI:

770 return selectFPToInt(I, MBB, MRI);

771

772 case TargetOpcode::G_ZEXT:

773 return selectZExt(I, MBB, MRI);

774 case TargetOpcode::G_CONSTANT:

776 case TargetOpcode::G_CONSTANT_POOL:

777 return selectConstantPool(I, MBB, MRI);

778 }

779 return false;

780}

781

782namespace llvm {

783InstructionSelector *

787 return new PPCInstructionSelector(TM, Subtarget, RBI);

788}

789}

unsigned const MachineRegisterInfo * MRI

static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)

#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)

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...

This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...

This file declares the MachineIRBuilder class.

Register const TargetRegisterInfo * TRI

Promote Memory to Register

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)

static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)

Definition PPCInstructionSelector.cpp:130

static uint32_t findContiguousZerosAtLeast(uint64_t Imm, unsigned Num)

Definition PPCInstructionSelector.cpp:277

static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)

Definition PPCInstructionSelector.cpp:154

This file declares the targeting of the RegisterBankInfo class for PowerPC.

static StringRef getName(Value *V)

LLVM_ABI Align getPointerABIAlignment(unsigned AS) const

Layout pointer alignment.

Register getPointerReg() const

Get the source register of the pointer value.

LocationSize 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.

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.

TypeSize getValue() const

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, 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.

@ 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,...

bool isLittleEndian() const

MCRegister getTOCPointerRegister() const

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.

const RegisterBank & getRegBank(unsigned ID)

Get the register bank identified by ID.

This class implements the register bank concept.

unsigned getID() const

Get the identifier of this register bank.

Wrapper class representing virtual and physical registers.

constexpr bool isPhysical() const

Return true if the specified register number is in the physical register namespace.

TargetInstrInfo - Interface to description of machine instruction set.

CodeModel::Model getCodeModel() const

Returns the code model.

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.

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

int countr_one(T Value)

Count the number of ones from the least significant bit to the first zero bit.

LLVM_ABI 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...

bool isPreISelGenericOpcode(unsigned Opcode)

Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.

int countr_zero(T Val)

Count number of 0's from the least significant bit to the most stopping at the first 1.

int countl_zero(T Val)

Count number of 0's from the most significant bit to the least stopping at the first 1.

constexpr uint32_t Hi_32(uint64_t Value)

Return the high 32 bits of a 64 bit value.

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

int countl_one(T Value)

Count the number of ones from the most significant bit to the first zero bit.

constexpr uint32_t Lo_32(uint64_t Value)

Return the low 32 bits of a 64 bit value.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

InstructionSelector * createPPCInstructionSelector(const PPCTargetMachine &TM, const PPCSubtarget &Subtarget, const PPCRegisterBankInfo &RBI)

Definition PPCInstructionSelector.cpp:784

static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)

Return a MachinePointerInfo record that refers to a GOT entry.