Skip to content

[LoongArch][MC] Handle more PseudoLA* instructions with la-global-with-abs feature #112858

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
241 changes: 167 additions & 74 deletions llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,9 @@ class LoongArchAsmParser : public MCTargetAsmParser {
void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

// Helper to emit pseudo instruction "la.tls.desc $rd, sym".
void emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
void emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
void emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
// Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".
void emitLoadAddressTLSDescPcrelLarge(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out);
void emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

// Helper to emit pseudo instruction "li.w/d $rd, $imm".
void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
Expand Down Expand Up @@ -1023,14 +1021,42 @@ void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
// la.got $rd, sym
// expands to:
// pcalau12i $rd, %got_pc_hi20(sym)
// ld.w/d $rd, $rd, %got_pc_lo12(sym)
MCRegister DestReg = Inst.getOperand(0).getReg();
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
InstSeq Insts;
unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;

if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
// with feature: +la-glabal-with-abs
// for 32bit:
// lu12i.w $rd, %got_hi20(sym)
// ori $rd, $rd, %got_lo12(sym)
// ld.w $rd, $rd, 0
//
// for 64bit:
// lu12i.w $rd, %got_hi20(sym)
// ori $rd, $rd, %got_lo12(sym)
// lu32i.d $rd, %got64_lo20(sym)
// lu52i.d $rd, $rd, %got64_hi12(sym)
// ld.d $rd, $rd, 0
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_GOT_HI20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_GOT_LO12));

if (is64Bit()) {
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
}
Insts.push_back(LoongArchAsmParser::Inst(LD));
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
return;
}
// expands to:
// pcalau12i $rd, %got_pc_hi20(sym)
// ld.w/d $rd, $rd, %got_pc_lo12(sym)
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
Insts.push_back(
Expand Down Expand Up @@ -1087,14 +1113,43 @@ void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,
void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
// la.tls.ie $rd, sym
// expands to:
// pcalau12i $rd, %ie_pc_hi20(sym)
// ld.w/d $rd, $rd, %ie_pc_lo12(sym)
MCRegister DestReg = Inst.getOperand(0).getReg();
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
InstSeq Insts;
unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;

if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
// with feature: +la-glabal-with-abs
// for 32bit:
// lu12i.w $rd, %ie_hi20(sym)
// ori $rd, $rd, %ie_lo12(sym)
// ld.w $rd, $rd, 0
//
// for 64bit:
// lu12i.w $rd, %ie_hi20(sym)
// ori $rd, $rd, %ie_lo12(sym)
// lu32i.d $rd, %ie64_lo20(sym)
// lu52i.d $rd, $rd, %ie64_hi12(sym)
// ld.d $rd, $rd, 0
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12));

if (is64Bit()) {
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12));
}
Insts.push_back(LoongArchAsmParser::Inst(LD));
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
return;
}

// expands to:
// pcalau12i $rd, %ie_pc_hi20(sym)
// ld.w/d $rd, $rd, %ie_pc_lo12(sym)
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
Insts.push_back(LoongArchAsmParser::Inst(
Expand Down Expand Up @@ -1133,14 +1188,40 @@ void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,
void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
// la.tls.ld $rd, sym
// expands to:
// pcalau12i $rd, %ld_pc_hi20(sym)
// addi.w/d $rd, $rd, %got_pc_lo12(sym)
MCRegister DestReg = Inst.getOperand(0).getReg();
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
InstSeq Insts;
unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
// with feature: +la-glabal-with-abs
// for 32bit:
// lu12i.w $rd, %ld_hi20(sym)
// ori $rd, $rd, %got_lo12(sym)
//
// for 64bit:
// lu12i.w $rd, %ld_hi20(sym)
// ori $rd, $rd, %got_lo12(sym)
// lu32i.d $rd, %got64_lo20(sym)
// lu52i.d $rd, $rd, %got64_hi12(sym)
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_GOT_LO12));

if (is64Bit()) {
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
}
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
return;
}

// expands to:
// pcalau12i $rd, %ld_pc_hi20(sym)
// addi.w/d $rd, $rd, %got_pc_lo12(sym)
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
Insts.push_back(LoongArchAsmParser::Inst(
Expand Down Expand Up @@ -1179,14 +1260,40 @@ void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,
void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
// la.tls.gd $rd, sym
// expands to:
// pcalau12i $rd, %gd_pc_hi20(sym)
// addi.w/d $rd, $rd, %got_pc_lo12(sym)
MCRegister DestReg = Inst.getOperand(0).getReg();
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
InstSeq Insts;
unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
// with feature: +la-glabal-with-abs
// for 32bit:
// lu12i.w $rd, %gd_hi20(sym)
// ori $rd, $rd, %got_lo12(sym)
//
// for 64bit:
// lu12i.w $rd, %gd_hi20(sym)
// ori $rd, $rd, %got_lo12(sym)
// lu32i.d $rd, %got64_lo20(sym)
// lu52i.d $rd, $rd, %got64_hi12(sym)
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_GOT_LO12));

if (is64Bit()) {
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
}
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
return;
}

// expands to:
// pcalau12i $rd, %gd_pc_hi20(sym)
// addi.w/d $rd, $rd, %got_pc_lo12(sym)
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
Insts.push_back(LoongArchAsmParser::Inst(
Expand Down Expand Up @@ -1222,63 +1329,56 @@ void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
}

void LoongArchAsmParser::emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
// `la.tls.desc $rd, sym` with `la-global-with-abs` feature
// for la32 expands to:
// lu12i.w $rd, %desc_hi20(sym)
// ori $rd, $rd, %desc_lo12(sym)
// ld.w $ra, $rd, %desc_ld(sym)
// jirl $ra, $ra, %desc_call(sym)
//
// for la64 expands to:
// lu12i.w $rd, %desc_hi20(sym)
// ori $rd, $rd, %desc_lo12(sym)
// lu32i.d $rd, %desc64_lo20(sym)
// lu52i.d $rd, $rd, %desc64_hi12(sym)
// ld.d $ra, $rd, %desc_ld(sym)
// jirl $ra, $ra, %desc_call(sym)
void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
// la.tls.desc $rd, sym
MCRegister DestReg = Inst.getOperand(0).getReg();
const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_TLS_DESC_ABS
? Inst.getOperand(1).getExpr()
: Inst.getOperand(2).getExpr();
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
InstSeq Insts;

Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12));

if (is64Bit()) {
if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
// with feature: +la-glabal-with-abs
// for la32 expands to:
// lu12i.w $rd, %desc_hi20(sym)
// ori $rd, $rd, %desc_lo12(sym)
// ld.w $ra, $rd, %desc_ld(sym)
// jirl $ra, $ra, %desc_call(sym)
//
// for la64 expands to:
// lu12i.w $rd, %desc_hi20(sym)
// ori $rd, $rd, %desc_lo12(sym)
// lu32i.d $rd, %desc64_lo20(sym)
// lu52i.d $rd, $rd, %desc64_hi12(sym)
// ld.d $ra, $rd, %desc_ld(sym)
// jirl $ra, $ra, %desc_call(sym)
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20));
LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12));
}
LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12));

Insts.push_back(
LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));
if (is64Bit()) {
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12));
}

emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
}
Insts.push_back(LoongArchAsmParser::Inst(
LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));

emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
return;
}

void LoongArchAsmParser::emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
// la.tls.desc $rd, sym
// expands to:
// pcalau12i $rd, %desc_pc_hi20(sym)
// addi.w/d $rd, $rd, %desc_pc_lo12(sym)
// ld.w/d $ra, $rd, %desc_ld(sym)
// jirl $ra, $ra, %desc_call(sym)
MCRegister DestReg = Inst.getOperand(0).getReg();
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
InstSeq Insts;

Insts.push_back(LoongArchAsmParser::Inst(
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
Insts.push_back(LoongArchAsmParser::Inst(
Expand All @@ -1291,9 +1391,8 @@ void LoongArchAsmParser::emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc,
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
}

void LoongArchAsmParser::emitLoadAddressTLSDescPcrelLarge(MCInst &Inst,
SMLoc IDLoc,
MCStreamer &Out) {
void LoongArchAsmParser::emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
// la.tls.desc $rd, $rj, sym
// expands to:
// pcalau12i $rd, %desc_pc_hi20(sym)
Expand Down Expand Up @@ -1438,15 +1537,11 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case LoongArch::PseudoLA_TLS_GD_LARGE:
emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
return false;
case LoongArch::PseudoLA_TLS_DESC_ABS:
case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE:
emitLoadAddressTLSDescAbs(Inst, IDLoc, Out);
return false;
case LoongArch::PseudoLA_TLS_DESC_PC:
emitLoadAddressTLSDescPcrel(Inst, IDLoc, Out);
case LoongArch::PseudoLA_TLS_DESC:
emitLoadAddressTLSDesc(Inst, IDLoc, Out);
return false;
case LoongArch::PseudoLA_TLS_DESC_PC_LARGE:
emitLoadAddressTLSDescPcrelLarge(Inst, IDLoc, Out);
case LoongArch::PseudoLA_TLS_DESC_LARGE:
emitLoadAddressTLSDescLarge(Inst, IDLoc, Out);
return false;
case LoongArch::PseudoLI_W:
case LoongArch::PseudoLI_D:
Expand Down Expand Up @@ -1475,10 +1570,8 @@ unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
return Match_RequiresAMORdDifferRkRj;
}
break;
case LoongArch::PseudoLA_TLS_DESC_ABS:
case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE:
case LoongArch::PseudoLA_TLS_DESC_PC:
case LoongArch::PseudoLA_TLS_DESC_PC_LARGE: {
case LoongArch::PseudoLA_TLS_DESC:
case LoongArch::PseudoLA_TLS_DESC_LARGE: {
MCRegister Rd = Inst.getOperand(0).getReg();
if (Rd != LoongArch::R4)
return Match_RequiresLAORdR4;
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ bool LoongArchPreRAExpandPseudo::expandMI(
return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);
case LoongArch::PseudoLA_TLS_GD_LARGE:
return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI, /*Large=*/true);
case LoongArch::PseudoLA_TLS_DESC_PC:
case LoongArch::PseudoLA_TLS_DESC:
return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI);
case LoongArch::PseudoLA_TLS_DESC_PC_LARGE:
case LoongArch::PseudoLA_TLS_DESC_LARGE:
return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI, /*Large=*/true);
case LoongArch::PseudoCALL:
case LoongArch::PseudoCALL_MEDIUM:
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1927,8 +1927,8 @@ LoongArchTargetLowering::lowerGlobalTLSAddress(SDValue Op,
}

return getTLSDescAddr(N, DAG,
Large ? LoongArch::PseudoLA_TLS_DESC_PC_LARGE
: LoongArch::PseudoLA_TLS_DESC_PC,
Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
: LoongArch::PseudoLA_TLS_DESC,
Large);
}

Expand Down
24 changes: 7 additions & 17 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1655,27 +1655,17 @@ let isCall = 1, isBarrier = 1, hasSideEffects = 0, mayStore = 0, mayLoad = 0,
def PseudoDESC_CALL : Pseudo<(outs GPR:$rd), (ins GPR:$rj, simm16_lsl2:$imm16)>,
PseudoInstExpansion<(JIRL GPR:$rd, GPR:$rj,
simm16_lsl2:$imm16)>;

// TLSDESC
let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
isAsmParserOnly = 1, Defs = [R1] in {
def PseudoLA_TLS_DESC_ABS : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src),
[], "la.tls.desc", "$dst, $src">,
Requires<[IsLA32, HasLaGlobalWithAbs]>;
def PseudoLA_TLS_DESC_ABS_LARGE : Pseudo<(outs GPR:$dst),
(ins GPR:$tmp, bare_symbol:$src), [],
"la.tls.desc", "$dst, $src">,
Requires<[IsLA64, HasLaGlobalWithAbs]>;
def PseudoLA_TLS_DESC_PC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
"la.tls.desc", "$dst, $src">;
}

isAsmParserOnly = 1, Defs = [R1] in
def PseudoLA_TLS_DESC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
"la.tls.desc", "$dst, $src">;
let isCall = 1, isBarrier = 1, hasSideEffects = 0, mayStore = 0, mayLoad = 0,
isCodeGenOnly = 0, isAsmParserOnly = 1, Defs = [R1, R4] in
def PseudoLA_TLS_DESC_PC_LARGE : Pseudo<(outs GPR:$dst),
(ins GPR:$tmp, bare_symbol:$src), [],
"la.tls.desc", "$dst, $tmp, $src">,
Requires<[IsLA64]>;
def PseudoLA_TLS_DESC_LARGE : Pseudo<(outs GPR:$dst),
(ins GPR:$tmp, bare_symbol:$src), [],
"la.tls.desc", "$dst, $tmp, $src">,
Requires<[IsLA64]>;

// Load address inst alias: "la", "la.global" and "la.local".
// Default:
Expand Down
Loading
Loading