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