Skip to content
Merged
28 changes: 20 additions & 8 deletions llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,18 +187,21 @@ bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
MachineInstr &MI = *MBBI;
DebugLoc DL = MI.getDebugLoc();

const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);

Register DestReg = MI.getOperand(0).getReg();
Register ScratchReg =
MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
MachineOperand &Symbol = MI.getOperand(1);

BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
.addDisp(Symbol, 0, FlagsHi);
.addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsHi, EnableRelax));

MachineInstr *SecondMI =
BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
.addReg(ScratchReg)
.addDisp(Symbol, 0, FlagsLo);
.addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsLo, EnableRelax));

if (MI.hasOneMemOperand())
SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
Expand Down Expand Up @@ -481,14 +484,17 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;
unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);

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

BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), Tmp1Reg)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_HI);
.addDisp(Symbol, 0,
LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_HI,
EnableRelax && !Large));

if (Large) {
// Code Sequence:
Expand Down Expand Up @@ -526,19 +532,25 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
// pcalau12i $a0, %desc_pc_hi20(sym)
// addi.w/d $a0, $a0, %desc_pc_lo12(sym)
// ld.w/d $ra, $a0, %desc_ld(sym)
// jirl $ra, $ra, %desc_ld(sym)
// add.d $dst, $a0, $tp
// jirl $ra, $ra, %desc_call(sym)
// add.w/d $dst, $a0, $tp
BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
.addReg(Tmp1Reg)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO);
.addDisp(
Symbol, 0,
LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_LO, EnableRelax));
}

BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1)
.addReg(LoongArch::R4)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_LD);
.addDisp(Symbol, 0,
LoongArchII::encodeFlags(LoongArchII::MO_DESC_LD,
EnableRelax && !Large));
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)
.addReg(LoongArch::R1)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_CALL);
.addDisp(Symbol, 0,
LoongArchII::encodeFlags(LoongArchII::MO_DESC_CALL,
EnableRelax && !Large));
BuildMI(MBB, MBBI, DL, TII->get(ADD), DestReg)
.addReg(LoongArch::R4)
.addReg(LoongArch::R2);
Expand Down
93 changes: 90 additions & 3 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,83 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
break;
}

const auto &STI = MF.getSubtarget<LoongArchSubtarget>();
if (STI.hasFeature(LoongArch::FeatureRelax)) {
// When linker relaxation enabled, the following instruction patterns are
// prohibited from being reordered:
//
// * pcalau12i $a0, %pc_hi20(s)
// addi.w/d $a0, $a0, %pc_lo12(s)
//
// * pcalau12i $a0, %got_pc_hi20(s)
// ld.w/d $a0, $a0, %got_pc_lo12(s)
//
// * pcalau12i $a0, %ld_pc_hi20(s) | %gd_pc_hi20(s)
// addi.w/d $a0, $a0, %got_pc_lo12(s)
//
// * pcalau12i $a0, %desc_pc_hi20(s)
// addi.w/d $a0, $a0, %desc_pc_lo12(s)
// ld.w/d $ra, $a0, %desc_ld(s)
// jirl $ra, $ra, %desc_call(s)
unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
unsigned LdOp = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
switch (MI.getOpcode()) {
case LoongArch::PCALAU12I: {
auto MO0 = LoongArchII::getDirectFlags(MI.getOperand(1));
auto SecondOp = std::next(MII);
if (MO0 == LoongArchII::MO_DESC_PC_HI) {
if (SecondOp == MIE || SecondOp->getOpcode() != AddiOp)
break;
auto Ld = std::next(SecondOp);
if (Ld == MIE || Ld->getOpcode() != LdOp)
break;
auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2));
auto MO2 = LoongArchII::getDirectFlags(Ld->getOperand(2));
if (MO1 == LoongArchII::MO_DESC_PC_LO && MO2 == LoongArchII::MO_DESC_LD)
return true;
break;
}
if (SecondOp == MIE ||
(SecondOp->getOpcode() != AddiOp && SecondOp->getOpcode() != LdOp))
break;
auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2));
if (MO0 == LoongArchII::MO_PCREL_HI && SecondOp->getOpcode() == AddiOp &&
MO1 == LoongArchII::MO_PCREL_LO)
return true;
if (MO0 == LoongArchII::MO_GOT_PC_HI && SecondOp->getOpcode() == LdOp &&
MO1 == LoongArchII::MO_GOT_PC_LO)
return true;
if ((MO0 == LoongArchII::MO_LD_PC_HI ||
MO0 == LoongArchII::MO_GD_PC_HI) &&
SecondOp->getOpcode() == AddiOp && MO1 == LoongArchII::MO_GOT_PC_LO)
return true;
break;
}
case LoongArch::ADDI_W:
case LoongArch::ADDI_D: {
auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
if (MO == LoongArchII::MO_PCREL_LO || MO == LoongArchII::MO_GOT_PC_LO)
return true;
break;
}
case LoongArch::LD_W:
case LoongArch::LD_D: {
auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
if (MO == LoongArchII::MO_GOT_PC_LO)
return true;
break;
}
case LoongArch::PseudoDESC_CALL: {
auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
if (MO == LoongArchII::MO_DESC_CALL)
return true;
break;
}
default:
break;
}
}

return false;
}

Expand Down Expand Up @@ -618,7 +695,8 @@ bool LoongArchInstrInfo::reverseBranchCondition(

std::pair<unsigned, unsigned>
LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
return std::make_pair(TF, 0u);
const unsigned Mask = LoongArchII::MO_DIRECT_FLAG_MASK;
return std::make_pair(TF & Mask, TF & ~Mask);
}

ArrayRef<std::pair<unsigned, const char *>>
Expand All @@ -644,20 +722,29 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
{MO_IE_PC_LO, "loongarch-ie-pc-lo"},
{MO_IE_PC64_LO, "loongarch-ie-pc64-lo"},
{MO_IE_PC64_HI, "loongarch-ie-pc64-hi"},
{MO_LD_PC_HI, "loongarch-ld-pc-hi"},
{MO_GD_PC_HI, "loongarch-gd-pc-hi"},
{MO_CALL36, "loongarch-call36"},
{MO_DESC_PC_HI, "loongarch-desc-pc-hi"},
{MO_DESC_PC_LO, "loongarch-desc-pc-lo"},
{MO_DESC64_PC_LO, "loongarch-desc64-pc-lo"},
{MO_DESC64_PC_HI, "loongarch-desc64-pc-hi"},
{MO_DESC_LD, "loongarch-desc-ld"},
{MO_DESC_CALL, "loongarch-desc-call"},
{MO_LD_PC_HI, "loongarch-ld-pc-hi"},
{MO_GD_PC_HI, "loongarch-gd-pc-hi"},
{MO_LE_HI_R, "loongarch-le-hi-r"},
{MO_LE_ADD_R, "loongarch-le-add-r"},
{MO_LE_LO_R, "loongarch-le-lo-r"}};
return ArrayRef(TargetFlags);
}

ArrayRef<std::pair<unsigned, const char *>>
LoongArchInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
using namespace LoongArchII;
static const std::pair<unsigned, const char *> TargetFlags[] = {
{MO_RELAX, "loongarch-relax"}};
return ArrayRef(TargetFlags);
}

// Returns true if this is the sext.w pattern, addi.w rd, rs, 0.
bool LoongArch::isSEXT_W(const MachineInstr &MI) {
return MI.getOpcode() == LoongArch::ADDI_W && MI.getOperand(1).isReg() &&
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ class LoongArchInstrInfo : public LoongArchGenInstrInfo {
ArrayRef<std::pair<unsigned, const char *>>
getSerializableDirectMachineOperandTargetFlags() const override;

ArrayRef<std::pair<unsigned, const char *>>
getSerializableBitmaskMachineOperandTargetFlags() const override;

protected:
const LoongArchSubtarget &STI;
};
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
MCContext &Ctx = AP.OutContext;
LoongArchMCExpr::VariantKind Kind;

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

if (Kind != LoongArchMCExpr::VK_LoongArch_None)
ME = LoongArchMCExpr::create(ME, Kind, Ctx);
ME = LoongArchMCExpr::create(ME, Kind, Ctx, LoongArchII::hasRelaxFlag(MO));
return MCOperand::createExpr(ME);
}

Expand Down
Loading
Loading