Skip to content

Commit 85be554

Browse files
committed
[LoongArch] Avoid scheduling relaxable code sequence and attach relax relocs
If linker relaxation enabled, relaxable code sequence expanded from pseudos should avoid being separated by instruction scheduling. This commit tags scheduling boundary for them to avoid being scheduled. (Except for `tls_le` and `call36/tail36`. Because `tls_le` can be scheduled and have no influence to relax, `call36/tail36` are expanded later in `LoongArchExpandPseudo` pass.) A new mask target-flag is added to attach relax relocs to the relaxable code sequence. (No need to add it for `tls_le` and `call36/tail36` because of the reasons shown above.) Because of this, get "direct" flags is necessary when using their target-flags. In addition, code sequence after being optimized by `MergeBaseOffset` pass may not relaxable any more, so the relax "bitmask" flag should be removed.
1 parent 6ee3b7a commit 85be554

11 files changed

+370
-21
lines changed

llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -187,18 +187,23 @@ bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
187187
MachineInstr &MI = *MBBI;
188188
DebugLoc DL = MI.getDebugLoc();
189189

190+
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
191+
bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
192+
190193
Register DestReg = MI.getOperand(0).getReg();
191194
Register ScratchReg =
192195
MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
193196
MachineOperand &Symbol = MI.getOperand(1);
194197

195198
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
196-
.addDisp(Symbol, 0, FlagsHi);
199+
.addDisp(Symbol, 0,
200+
EnableRelax ? LoongArchII::addRelaxFlag(FlagsHi) : FlagsHi);
197201

198202
MachineInstr *SecondMI =
199203
BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
200204
.addReg(ScratchReg)
201-
.addDisp(Symbol, 0, FlagsLo);
205+
.addDisp(Symbol, 0,
206+
EnableRelax ? LoongArchII::addRelaxFlag(FlagsLo) : FlagsLo);
202207

203208
if (MI.hasOneMemOperand())
204209
SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
@@ -481,14 +486,18 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
481486
unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;
482487
unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
483488
unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
489+
bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
484490

485491
Register DestReg = MI.getOperand(0).getReg();
486492
Register Tmp1Reg =
487493
MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
488494
MachineOperand &Symbol = MI.getOperand(Large ? 2 : 1);
489495

490496
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), Tmp1Reg)
491-
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_HI);
497+
.addDisp(Symbol, 0,
498+
(EnableRelax && !Large)
499+
? LoongArchII::addRelaxFlag(LoongArchII::MO_DESC_PC_HI)
500+
: LoongArchII::MO_DESC_PC_HI);
492501

493502
if (Large) {
494503
// Code Sequence:
@@ -526,19 +535,28 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
526535
// pcalau12i $a0, %desc_pc_hi20(sym)
527536
// addi.w/d $a0, $a0, %desc_pc_lo12(sym)
528537
// ld.w/d $ra, $a0, %desc_ld(sym)
529-
// jirl $ra, $ra, %desc_ld(sym)
530-
// add.d $dst, $a0, $tp
538+
// jirl $ra, $ra, %desc_call(sym)
539+
// add.w/d $dst, $a0, $tp
531540
BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
532541
.addReg(Tmp1Reg)
533-
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO);
542+
.addDisp(Symbol, 0,
543+
EnableRelax
544+
? LoongArchII::addRelaxFlag(LoongArchII::MO_DESC_PC_LO)
545+
: LoongArchII::MO_DESC_PC_LO);
534546
}
535547

536548
BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1)
537549
.addReg(LoongArch::R4)
538-
.addDisp(Symbol, 0, LoongArchII::MO_DESC_LD);
550+
.addDisp(Symbol, 0,
551+
(EnableRelax && !Large)
552+
? LoongArchII::addRelaxFlag(LoongArchII::MO_DESC_LD)
553+
: LoongArchII::MO_DESC_LD);
539554
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)
540555
.addReg(LoongArch::R1)
541-
.addDisp(Symbol, 0, LoongArchII::MO_DESC_CALL);
556+
.addDisp(Symbol, 0,
557+
(EnableRelax && !Large)
558+
? LoongArchII::addRelaxFlag(LoongArchII::MO_DESC_CALL)
559+
: LoongArchII::MO_DESC_CALL);
542560
BuildMI(MBB, MBBI, DL, TII->get(ADD), DestReg)
543561
.addReg(LoongArch::R4)
544562
.addReg(LoongArch::R2);

llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,89 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
443443
break;
444444
}
445445

446+
const auto &STI = MF.getSubtarget<LoongArchSubtarget>();
447+
if (STI.hasFeature(LoongArch::FeatureRelax)) {
448+
// When linker relaxation enabled, the following instruction patterns are
449+
// prohibited from being reordered:
450+
//
451+
// * pcalau12i $a0, %pc_hi20(s)
452+
// addi.w/d $a0, $a0, %pc_lo12(s)
453+
//
454+
// * pcalau12i $a0, %got_pc_hi20(s)
455+
// ld.w/d $a0, $a0, %got_pc_lo12(s)
456+
//
457+
// * pcalau12i $a0, %ie_pc_hi20(s)
458+
// ld.w/d $a0, $a0, %ie_pc_lo12(s)
459+
//
460+
// * pcalau12i $a0, %ld_pc_hi20(s) | %gd_pc_hi20(s)
461+
// addi.w/d $a0, $a0, %got_pc_lo12(s)
462+
//
463+
// * pcalau12i $a0, %desc_pc_hi20(s)
464+
// addi.w/d $a0, $a0, %desc_pc_lo12(s)
465+
// ld.w/d $ra, $a0, %desc_ld(s)
466+
// jirl $ra, $ra, %desc_call(s)
467+
unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
468+
unsigned LdOp = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
469+
switch (MI.getOpcode()) {
470+
case LoongArch::PCALAU12I: {
471+
auto MO0 = LoongArchII::getDirectFlags(MI.getOperand(1));
472+
auto SecondOp = std::next(MII);
473+
if (MO0 == LoongArchII::MO_DESC_PC_HI) {
474+
if (SecondOp == MIE || SecondOp->getOpcode() != AddiOp)
475+
break;
476+
auto Ld = std::next(SecondOp);
477+
if (Ld == MIE || Ld->getOpcode() != LdOp)
478+
break;
479+
auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2));
480+
auto MO2 = LoongArchII::getDirectFlags(Ld->getOperand(2));
481+
if (MO1 == LoongArchII::MO_DESC_PC_LO && MO2 == LoongArchII::MO_DESC_LD)
482+
return true;
483+
break;
484+
}
485+
if (SecondOp == MIE ||
486+
(SecondOp->getOpcode() != AddiOp && SecondOp->getOpcode() != LdOp))
487+
break;
488+
auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2));
489+
if (MO0 == LoongArchII::MO_PCREL_HI && SecondOp->getOpcode() == AddiOp &&
490+
MO1 == LoongArchII::MO_PCREL_LO)
491+
return true;
492+
if (MO0 == LoongArchII::MO_GOT_PC_HI && SecondOp->getOpcode() == LdOp &&
493+
MO1 == LoongArchII::MO_GOT_PC_LO)
494+
return true;
495+
if (MO0 == LoongArchII::MO_IE_PC_HI && SecondOp->getOpcode() == LdOp &&
496+
MO1 == LoongArchII::MO_IE_PC_LO)
497+
return true;
498+
if ((MO0 == LoongArchII::MO_LD_PC_HI ||
499+
MO0 == LoongArchII::MO_GD_PC_HI) &&
500+
SecondOp->getOpcode() == AddiOp && MO1 == LoongArchII::MO_GOT_PC_LO)
501+
return true;
502+
break;
503+
}
504+
case LoongArch::ADDI_W:
505+
case LoongArch::ADDI_D: {
506+
auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
507+
if (MO == LoongArchII::MO_PCREL_LO || MO == LoongArchII::MO_GOT_PC_LO)
508+
return true;
509+
break;
510+
}
511+
case LoongArch::LD_W:
512+
case LoongArch::LD_D: {
513+
auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
514+
if (MO == LoongArchII::MO_GOT_PC_LO || MO == LoongArchII::MO_IE_PC_LO)
515+
return true;
516+
break;
517+
}
518+
case LoongArch::PseudoDESC_CALL: {
519+
auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
520+
if (MO == LoongArchII::MO_DESC_CALL)
521+
return true;
522+
break;
523+
}
524+
default:
525+
break;
526+
}
527+
}
528+
446529
return false;
447530
}
448531

@@ -618,7 +701,8 @@ bool LoongArchInstrInfo::reverseBranchCondition(
618701

619702
std::pair<unsigned, unsigned>
620703
LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
621-
return std::make_pair(TF, 0u);
704+
const unsigned Mask = LoongArchII::MO_DIRECT_FLAG_MASK;
705+
return std::make_pair(TF & Mask, TF & ~Mask);
622706
}
623707

624708
ArrayRef<std::pair<unsigned, const char *>>
@@ -644,20 +728,29 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
644728
{MO_IE_PC_LO, "loongarch-ie-pc-lo"},
645729
{MO_IE_PC64_LO, "loongarch-ie-pc64-lo"},
646730
{MO_IE_PC64_HI, "loongarch-ie-pc64-hi"},
731+
{MO_LD_PC_HI, "loongarch-ld-pc-hi"},
732+
{MO_GD_PC_HI, "loongarch-gd-pc-hi"},
733+
{MO_CALL36, "loongarch-call36"},
647734
{MO_DESC_PC_HI, "loongarch-desc-pc-hi"},
648735
{MO_DESC_PC_LO, "loongarch-desc-pc-lo"},
649736
{MO_DESC64_PC_LO, "loongarch-desc64-pc-lo"},
650737
{MO_DESC64_PC_HI, "loongarch-desc64-pc-hi"},
651738
{MO_DESC_LD, "loongarch-desc-ld"},
652739
{MO_DESC_CALL, "loongarch-desc-call"},
653-
{MO_LD_PC_HI, "loongarch-ld-pc-hi"},
654-
{MO_GD_PC_HI, "loongarch-gd-pc-hi"},
655740
{MO_LE_HI_R, "loongarch-le-hi-r"},
656741
{MO_LE_ADD_R, "loongarch-le-add-r"},
657742
{MO_LE_LO_R, "loongarch-le-lo-r"}};
658743
return ArrayRef(TargetFlags);
659744
}
660745

746+
ArrayRef<std::pair<unsigned, const char *>>
747+
LoongArchInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
748+
using namespace LoongArchII;
749+
static const std::pair<unsigned, const char *> TargetFlags[] = {
750+
{MO_RELAX, "loongarch-relax"}};
751+
return ArrayRef(TargetFlags);
752+
}
753+
661754
// Returns true if this is the sext.w pattern, addi.w rd, rs, 0.
662755
bool LoongArch::isSEXT_W(const MachineInstr &MI) {
663756
return MI.getOpcode() == LoongArch::ADDI_W && MI.getOperand(1).isReg() &&

llvm/lib/Target/LoongArch/LoongArchInstrInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class LoongArchInstrInfo : public LoongArchGenInstrInfo {
9191
ArrayRef<std::pair<unsigned, const char *>>
9292
getSerializableDirectMachineOperandTargetFlags() const override;
9393

94+
ArrayRef<std::pair<unsigned, const char *>>
95+
getSerializableBitmaskMachineOperandTargetFlags() const override;
96+
9497
protected:
9598
const LoongArchSubtarget &STI;
9699
};

llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
2727
MCContext &Ctx = AP.OutContext;
2828
LoongArchMCExpr::VariantKind Kind;
2929

30-
switch (MO.getTargetFlags()) {
30+
switch (LoongArchII::getDirectFlags(MO)) {
3131
default:
3232
llvm_unreachable("Unknown target flag on GV operand");
3333
case LoongArchII::MO_None:
@@ -134,7 +134,7 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
134134
ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
135135

136136
if (Kind != LoongArchMCExpr::VK_LoongArch_None)
137-
ME = LoongArchMCExpr::create(ME, Kind, Ctx);
137+
ME = LoongArchMCExpr::create(ME, Kind, Ctx, LoongArchII::hasRelaxFlag(MO));
138138
return MCOperand::createExpr(ME);
139139
}
140140

llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ bool LoongArchMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi20,
105105
return false;
106106

107107
const MachineOperand &Hi20Op1 = Hi20.getOperand(1);
108-
if (Hi20Op1.getTargetFlags() != LoongArchII::MO_PCREL_HI)
108+
if (LoongArchII::getDirectFlags(Hi20Op1) != LoongArchII::MO_PCREL_HI)
109109
return false;
110110

111111
auto isGlobalOrCPIOrBlockAddress = [](const MachineOperand &Op) {
@@ -157,7 +157,7 @@ bool LoongArchMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi20,
157157

158158
const MachineOperand &Lo12Op2 = Lo12->getOperand(2);
159159
assert(Hi20.getOpcode() == LoongArch::PCALAU12I);
160-
if (Lo12Op2.getTargetFlags() != LoongArchII::MO_PCREL_LO ||
160+
if (LoongArchII::getDirectFlags(Lo12Op2) != LoongArchII::MO_PCREL_LO ||
161161
!(isGlobalOrCPIOrBlockAddress(Lo12Op2) || Lo12Op2.isMCSymbol()) ||
162162
Lo12Op2.getOffset() != 0)
163163
return false;
@@ -597,9 +597,28 @@ bool LoongArchMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi20,
597597
if (!isInt<32>(NewOffset))
598598
return false;
599599

600+
// If optimized by this pass successfully, MO_RELAX bitmask target-flag should
601+
// be removed from the code sequence.
602+
//
603+
// For example:
604+
// pcalau12i $a0, %pc_hi20(symbol)
605+
// addi.d $a0, $a0, %pc_lo12(symbol)
606+
// ld.w $a0, $a0, 0
607+
//
608+
// =>
609+
//
610+
// pcalau12i $a0, %pc_hi20(symbol)
611+
// ld.w $a0, $a0, %pc_lo12(symbol)
612+
//
613+
// Code sequence optimized before can be relax by linker. But after being
614+
// optimized, it cannot be relaxed any more. So MO_RELAX flag should not be
615+
// carried by them.
600616
Hi20.getOperand(1).setOffset(NewOffset);
617+
Hi20.getOperand(1).setTargetFlags(
618+
LoongArchII::getDirectFlags(Hi20.getOperand(1)));
601619
MachineOperand &ImmOp = Lo12.getOperand(2);
602620
ImmOp.setOffset(NewOffset);
621+
ImmOp.setTargetFlags(LoongArchII::getDirectFlags(ImmOp));
603622
if (Lo20 && Hi12) {
604623
Lo20->getOperand(2).setOffset(NewOffset);
605624
Hi12->getOperand(2).setOffset(NewOffset);
@@ -617,15 +636,16 @@ bool LoongArchMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi20,
617636
switch (ImmOp.getType()) {
618637
case MachineOperand::MO_GlobalAddress:
619638
MO.ChangeToGA(ImmOp.getGlobal(), ImmOp.getOffset(),
620-
ImmOp.getTargetFlags());
639+
LoongArchII::getDirectFlags(ImmOp));
621640
break;
622641
case MachineOperand::MO_MCSymbol:
623-
MO.ChangeToMCSymbol(ImmOp.getMCSymbol(), ImmOp.getTargetFlags());
642+
MO.ChangeToMCSymbol(ImmOp.getMCSymbol(),
643+
LoongArchII::getDirectFlags(ImmOp));
624644
MO.setOffset(ImmOp.getOffset());
625645
break;
626646
case MachineOperand::MO_BlockAddress:
627647
MO.ChangeToBA(ImmOp.getBlockAddress(), ImmOp.getOffset(),
628-
ImmOp.getTargetFlags());
648+
LoongArchII::getDirectFlags(ImmOp));
629649
break;
630650
default:
631651
report_fatal_error("unsupported machine operand type");

llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() {
3838
initializeLoongArchMergeBaseOffsetOptPass(*PR);
3939
initializeLoongArchOptWInstrsPass(*PR);
4040
initializeLoongArchPreRAExpandPseudoPass(*PR);
41+
initializeLoongArchExpandPseudoPass(*PR);
4142
initializeLoongArchDAGToDAGISelLegacyPass(*PR);
4243
}
4344

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
1818
#include "llvm/ADT/StringRef.h"
1919
#include "llvm/ADT/StringSwitch.h"
20+
#include "llvm/CodeGen/MachineOperand.h"
2021
#include "llvm/MC/MCInstrDesc.h"
2122
#include "llvm/TargetParser/SubtargetFeature.h"
2223

@@ -58,8 +59,29 @@ enum {
5859
MO_LE_ADD_R,
5960
MO_LE_LO_R,
6061
// TODO: Add more flags.
62+
63+
// Used to differentiate between target-specific "direct" flags and "bitmask"
64+
// flags. A machine operand can only have one "direct" flag, but can have
65+
// multiple "bitmask" flags.
66+
MO_DIRECT_FLAG_MASK = 0x3f,
67+
68+
MO_RELAX = 0x40
6169
};
6270

71+
// Given a MachineOperand that may carry out "bitmask" flags, such as MO_RELAX,
72+
// return LoongArch target-specific "direct" flags.
73+
static inline unsigned getDirectFlags(const MachineOperand &MO) {
74+
return MO.getTargetFlags() & MO_DIRECT_FLAG_MASK;
75+
}
76+
77+
// Add MO_RELAX "bitmask" flag when FeatureRelax is enabled.
78+
static inline unsigned addRelaxFlag(unsigned Flags) { return Flags | MO_RELAX; }
79+
80+
// \returns true if the given MachineOperand has MO_RELAX "bitmask" flag.
81+
static inline bool hasRelaxFlag(const MachineOperand &MO) {
82+
return MO.getTargetFlags() & MO_RELAX;
83+
}
84+
6385
// Target-specific flags of LAInst.
6486
// All definitions must match LoongArchInstrFormats.td.
6587
enum {

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
249249
break;
250250
case LoongArchMCExpr::VK_LoongArch_CALL36:
251251
FixupKind = LoongArch::fixup_loongarch_call36;
252+
RelaxCandidate = true;
252253
break;
253254
case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20:
254255
FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_hi20;

0 commit comments

Comments
 (0)