LLVM: lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

27

28using namespace llvm;

29

31

32#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \

33 "LoongArch Pre-RA pseudo instruction expansion pass"

34#define LOONGARCH_EXPAND_PSEUDO_NAME \

35 "LoongArch pseudo instruction expansion pass"

36

37namespace {

38

40public:

42 static char ID;

43

45

47

48 void getAnalysisUsage(AnalysisUsage &AU) const override {

51 }

52 StringRef getPassName() const override {

54 }

55

56private:

63 unsigned FlagsHi, unsigned SecondOpcode,

64 unsigned FlagsLo);

68 unsigned LastOpcode, unsigned IdentifyingMO);

72 unsigned LastOpcode, unsigned IdentifyingMO,

74 bool EraseFromParent);

78 bool Large = false);

82 bool Large = false);

89 bool Large = false);

93 bool Large = false);

97 bool Large = false);

101 bool Large = false);

105 bool IsTailCall);

108};

109

110char LoongArchPreRAExpandPseudo::ID = 0;

111

112bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {

116 for (auto &MBB : MF)

119}

120

123

125 while (MBBI != E) {

128 MBBI = NMBBI;

129 }

130

132}

133

134bool LoongArchPreRAExpandPseudo::expandMI(

137 switch (MBBI->getOpcode()) {

138 case LoongArch::PseudoLA_PCREL:

139 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);

140 case LoongArch::PseudoLA_PCREL_LARGE:

141 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI, true);

142 case LoongArch::PseudoLA_GOT:

143 return expandLoadAddressGot(MBB, MBBI, NextMBBI);

144 case LoongArch::PseudoLA_GOT_LARGE:

145 return expandLoadAddressGot(MBB, MBBI, NextMBBI, true);

146 case LoongArch::PseudoLA_TLS_LE:

147 return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);

148 case LoongArch::PseudoLA_TLS_IE:

149 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);

150 case LoongArch::PseudoLA_TLS_IE_LARGE:

151 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI, true);

152 case LoongArch::PseudoLA_TLS_LD:

153 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);

154 case LoongArch::PseudoLA_TLS_LD_LARGE:

155 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI, true);

156 case LoongArch::PseudoLA_TLS_GD:

157 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);

158 case LoongArch::PseudoLA_TLS_GD_LARGE:

159 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI, true);

160 case LoongArch::PseudoLA_TLS_DESC:

161 return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI);

162 case LoongArch::PseudoLA_TLS_DESC_LARGE:

163 return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI, true);

164 case LoongArch::PseudoCALL:

165 case LoongArch::PseudoCALL_LARGE:

166 return expandFunctionCALL(MBB, MBBI, NextMBBI, false);

167 case LoongArch::PseudoTAIL:

168 case LoongArch::PseudoTAIL_LARGE:

169 return expandFunctionCALL(MBB, MBBI, NextMBBI, true);

170 case LoongArch::PseudoBRIND:

171

172

174 annotateTableJump(MBB, MBBI);

175 break;

176 }

177 return false;

178}

179

180bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(

183 unsigned SecondOpcode, unsigned FlagsLo) {

187

189 bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);

190

191 Register DestReg = MI.getOperand(0).getReg();

195

198

203

204 if (MI.hasOneMemOperand())

206

207 MI.eraseFromParent();

208 return true;

209}

210

211bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(

214 unsigned IdentifyingMO) {

216 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,

217 MI.getOperand(2), MI.getOperand(0).getReg(),

218 true);

219}

220

221bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(

225 bool EraseFromParent) {

226

227

228

229

230

231

232

233

234 unsigned MO0, MO1, MO2, MO3;

235 switch (IdentifyingMO) {

236 default:

239 MO0 = IdentifyingMO;

243 break;

247

249 MO1 = IdentifyingMO;

252 break;

254 MO0 = IdentifyingMO;

258 break;

259 }

260

264

266 "Large code model requires LA64");

267

273 : DestReg;

277 : DestReg;

281 : DestReg;

282

283 auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), TmpPart1);

284 auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), TmpPart0)

285 .addReg(LoongArch::R0);

286 auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), TmpParts02)

287

289 auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), TmpParts023)

294

296 const char *SymName = Symbol.getSymbolName();

297 Part0.addExternalSymbol(SymName, MO0);

298 Part1.addExternalSymbol(SymName, MO1);

299 Part2.addExternalSymbol(SymName, MO2);

300 Part3.addExternalSymbol(SymName, MO3);

301 } else {

302 Part0.addDisp(Symbol, 0, MO0);

303 Part1.addDisp(Symbol, 0, MO1);

304 Part2.addDisp(Symbol, 0, MO2);

305 Part3.addDisp(Symbol, 0, MO3);

306 }

307

308 if (EraseFromParent)

309 MI.eraseFromParent();

310

311 return true;

312}

313

314bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(

317 if (Large)

318

319

320 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,

322

323

324

325

328 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

331}

332

333bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(

336 if (Large)

337

338

339 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,

341

342

343

344

347 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;

350}

351

352bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(

355

356

357

358

359

360

361

362

363

364

368

370 Register DestReg = MI.getOperand(0).getReg();

376

377 if (!Large) {

380

382 unsigned AddOp = STI.is64Bit() ? LoongArch::PseudoAddTPRel_D

383 : LoongArch::PseudoAddTPRel_W;

386 .addReg(LoongArch::R2)

388

389 unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

393 } else {

396

400

403

405

411 }

412

413 MI.eraseFromParent();

414 return true;

415}

416

417bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(

420 if (Large)

421

422

423 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,

425

426

427

428

431 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;

434}

435

436bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(

439 if (Large)

440

441

442 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,

444

445

446

447

450 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

453}

454

455bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(

458 if (Large)

459

460

461 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,

463

464

465

466

469 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

472}

473

474bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(

480

482 unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;

483 unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

484 unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;

485 bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);

486

487 Register DestReg = MI.getOperand(0).getReg();

491

495 EnableRelax && !Large));

496

497 if (Large) {

498

499

500

501

502

503

504

505

506

507

509 "Large code model requires LA64");

517 .addReg(LoongArch::R0)

528 } else {

529

530

531

532

533

534

538 Symbol, 0,

540 }

541

543 .addReg(LoongArch::R4)

546 EnableRelax && !Large));

547 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)

548 .addReg(LoongArch::R1)

551 EnableRelax && !Large));

553 .addReg(LoongArch::R4)

554 .addReg(LoongArch::R2);

555

556 MI.eraseFromParent();

557 return true;

558}

559

560bool LoongArchPreRAExpandPseudo::expandFunctionCALL(

568 unsigned Opcode;

569

571 default:

573 break;

575

576

577

578

579 Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;

581 break;

582 }

584

585

586

587 Opcode =

588 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;

590 IsTailCall

592 : LoongArch::R1;

593

596 unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;

597 expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg,

598 false);

600 break;

601 }

602 }

603

604

605 CALL.copyImplicitOps(MI);

606

607

608 CALL.setMIFlags(MI.getFlags());

609

610 MI.eraseFromParent();

611 return true;

612}

613

614void LoongArchPreRAExpandPseudo::annotateTableJump(

618

619 bool IsFound = false;

620

622 int FindDepth) {

623 if (FindDepth < 0)

624 return;

625 for (auto &MO : MInst->all_uses()) {

626 if (IsFound)

627 return;

629 if (Reg.isVirtual())

630 continue;

633 continue;

634 for (unsigned Idx = 0; Idx < DefMI->getNumOperands(); ++Idx) {

636 if (MO.isJTI()) {

637 MBBI->setPreInstrSymbol(

641 IsFound = true;

642 return;

643 }

644 }

645 FindJTIMI(DefMI, --FindDepth);

646 }

647 };

648

649

650 FindJTIMI(&*MBBI, 3);

651}

652

654public:

656 static char ID;

657

659

661

662 StringRef getPassName() const override {

664 }

665

666private:

675 bool IsTailCall);

676};

677

678char LoongArchExpandPseudo::ID = 0;

679

680bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) {

683

685 for (auto &MBB : MF)

687

689}

690

693

695 while (MBBI != E) {

698 MBBI = NMBBI;

699 }

700

702}

703

707 switch (MBBI->getOpcode()) {

708 case LoongArch::PseudoCopyCFR:

709 return expandCopyCFR(MBB, MBBI, NextMBBI);

710 case LoongArch::PseudoCALL_MEDIUM:

711 return expandFunctionCALL(MBB, MBBI, NextMBBI, false);

712 case LoongArch::PseudoTAIL_MEDIUM:

713 return expandFunctionCALL(MBB, MBBI, NextMBBI, true);

714 }

715

716 return false;

717}

718

719bool LoongArchExpandPseudo::expandCopyCFR(

725

726

727

728

729

730

731

732

733

734

738

739 MF->insert(++MBB.getIterator(), FalseBB);

740 MF->insert(++FalseBB->getIterator(), SinkBB);

741

742 Register DestReg = MI.getOperand(0).getReg();

743 Register SrcReg = MI.getOperand(1).getReg();

744

746

750

751 BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg);

752

753 FalseBB->addSuccessor(SinkBB);

754

755 SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end());

756 SinkBB->transferSuccessors(&MBB);

757

758 MBB.addSuccessor(FalseBB);

759 MBB.addSuccessor(SinkBB);

760

761 NextMBBI = MBB.end();

762 MI.eraseFromParent();

763

764

768

769 return true;

770}

771

772bool LoongArchExpandPseudo::expandFunctionCALL(

780 unsigned Opcode;

781

783 default:

785 break;

787

788

789

790

791

792

793 Opcode =

794 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;

795 Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1;

798

799 CALL =

801

802 if (Func.isSymbol())

804 else

806 break;

807 }

808 }

809

810

811 CALL.copyImplicitOps(MI);

812

813

814 CALL.setMIFlags(MI.getFlags());

815

816 MI.eraseFromParent();

817 return true;

818}

819

820}

821

822INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",

824

827

828namespace llvm {

829

831 return new LoongArchPreRAExpandPseudo();

832}

834 return new LoongArchExpandPseudo();

835}

836

837}

unsigned const MachineRegisterInfo * MRI

MachineInstrBuilder MachineInstrBuilder & DefMI

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

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

MachineBasicBlock MachineBasicBlock::iterator MBBI

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

const HexagonInstrInfo * TII

This file implements the LivePhysRegs utility for tracking liveness of physical registers.

cl::opt< bool > LArchAnnotateTableJump("loongarch-annotate-tablejump", cl::Hidden, cl::desc("Annotate table jump instruction to correlate it with the jump table."), cl::init(false))

#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME

Definition LoongArchExpandPseudoInsts.cpp:32

#define LOONGARCH_EXPAND_PSEUDO_NAME

Definition LoongArchExpandPseudoInsts.cpp:34

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

Represent the analysis usage information of a pass.

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

LLVM Basic Block Representation.

FunctionPass class - This class is used to implement most global optimizations.

A set of physical registers with utility functions to track liveness when walking backward/forward th...

LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...

LLVM_ABI MCSymbol * createNamedTempSymbol()

Create a temporary symbol with a unique name whose name cannot be omitted in the symbol table.

MachineInstrBundleIterator< MachineInstr > iterator

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

MCContext & getContext() const

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)

CreateMachineInstr - Allocate a new MachineInstr.

void insert(iterator MBBI, MachineBasicBlock *MBB)

const TargetMachine & getTarget() const

getTarget - Return the target machine this machine code is compiled with

const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

const MachineInstrBuilder & addDisp(const MachineOperand &Disp, int64_t off, unsigned char TargetFlags=0) const

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const

Representation of each machine instruction.

filtered_mop_range all_uses()

Returns an iterator range over all operands that are (explicit or implicit) register uses.

LLVM_ABI void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)

Add a MachineMemOperand to the machine instruction.

MachineOperand class - Representation of each machine instruction operand.

bool isJTI() const

isJTI - Tests if this is a MO_JumpTableIndex operand.

@ MO_ExternalSymbol

Name of external global symbol.

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")

createVirtualRegister - Create and return a new virtual register in the function with the specified r...

Wrapper class representing virtual and physical registers.

constexpr bool isVirtual() const

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

StringRef - Represent a constant reference to a string, i.e.

CodeModel::Model getCodeModel() const

Returns the code model.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

static unsigned encodeFlags(unsigned Flags, bool Relax)

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

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

FunctionPass * createLoongArchPreRAExpandPseudoPass()

Definition LoongArchExpandPseudoInsts.cpp:830

FunctionPass * createLoongArchExpandPseudoPass()

Definition LoongArchExpandPseudoInsts.cpp:833

void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)

Convenience function combining computeLiveIns() and addLiveIns().