Author: hev Date: 2026-01-22T08:27:35Z New Revision: cb16312a22177cd05809843b3c8d43875c75750a
URL: https://github.com/llvm/llvm-project/commit/cb16312a22177cd05809843b3c8d43875c75750a DIFF: https://github.com/llvm/llvm-project/commit/cb16312a22177cd05809843b3c8d43875c75750a.diff LOG: [llvm][LoongArch] Add call30 and tail30 macro instruction support (#175356) Link: https://sourceware.org/pipermail/binutils/2025-December/146091.html (cherry picked from commit c88cbaf2b204795c04596ee3071ce3484f0e610a) Added: Modified: llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp llvm/lib/Target/LoongArch/LoongArchInstrInfo.td llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp llvm/test/MC/LoongArch/Basic/Integer/invalid.s llvm/test/MC/LoongArch/Macros/macros-call.s Removed: ################################################################################ diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp index 9b11201d0312d..483be6b9a1a57 100644 --- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp +++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp @@ -171,9 +171,9 @@ class LoongArchAsmParser : public MCTargetAsmParser { // Helper to emit pseudo instruction "li.w/d $rd, $imm". void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); - // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym". - void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - bool IsTailCall); + // Helper to emit pseudo instruction "call{3x} sym" or "tail{3x} $rj, sym". + void emitFuncCall(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, bool IsTailCall, + bool IsCall36); public: enum LoongArchMatchResultTy { @@ -463,6 +463,22 @@ class LoongArchOperand : public MCParsedAsmOperand { IsValidKind; } + bool isSImm20pcaddu12i() const { + if (!isImm()) + return false; + + int64_t Imm; + LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None; + bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); + bool IsValidKind = + VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_CALL30; + + return IsConstantImm + ? isInt<20>(Imm) && IsValidKind + : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && + IsValidKind; + } + bool isSImm20pcaddu18i() const { if (!isImm()) return false; @@ -1465,8 +1481,19 @@ void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc, } } -void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, bool IsTailCall) { +void LoongArchAsmParser::emitFuncCall(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out, bool IsTailCall, + bool IsCall36) { + // call30 sym + // expands to: + // pcaddu12i $ra, %call30(sym) + // jirl $ra, $ra, 0 + // + // tail30 $rj, sym + // expands to: + // pcaddu12i $rj, %call30(sym) + // jirl $r0, $rj, 0 + // // call36 sym // expands to: // pcaddu18i $ra, %call36(sym) @@ -1478,14 +1505,15 @@ void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc, // jirl $r0, $rj, 0 MCRegister ScratchReg = IsTailCall ? Inst.getOperand(0).getReg() : MCRegister(LoongArch::R1); + unsigned PCAI = IsCall36 ? LoongArch::PCADDU18I : LoongArch::PCADDU12I; + unsigned Rel = IsCall36 ? ELF::R_LARCH_CALL36 : ELF::R_LARCH_CALL30; const MCExpr *Sym = IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr(); - const LoongArchMCExpr *LE = LoongArchMCExpr::create( - Sym, ELF::R_LARCH_CALL36, getContext(), /*RelaxHint=*/true); + const LoongArchMCExpr *LE = + LoongArchMCExpr::create(Sym, Rel, getContext(), /*RelaxHint=*/true); - Out.emitInstruction( - MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE), - getSTI()); + Out.emitInstruction(MCInstBuilder(PCAI).addReg(ScratchReg).addExpr(LE), + getSTI()); Out.emitInstruction( MCInstBuilder(LoongArch::JIRL) .addReg(IsTailCall ? MCRegister(LoongArch::R0) : ScratchReg) @@ -1548,11 +1576,17 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, case LoongArch::PseudoLI_D: emitLoadImm(Inst, IDLoc, Out); return false; + case LoongArch::PseudoCALL30: + emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/false, /*IsCall36=*/false); + return false; case LoongArch::PseudoCALL36: - emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false); + emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/false, /*IsCall36=*/true); + return false; + case LoongArch::PseudoTAIL30: + emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/true, /*IsCall36=*/false); return false; case LoongArch::PseudoTAIL36: - emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true); + emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/true, /*IsCall36=*/true); return false; } Out.emitInstruction(Inst, getSTI()); @@ -1849,6 +1883,12 @@ bool LoongArchAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, /*Upper=*/(1 << 19) - 1, "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer " "in the range"); + case Match_InvalidSImm20pcaddu12i: + return generateImmOutOfRangeError( + Operands, ErrorInfo, /*Lower=*/-(1 << 19), + /*Upper=*/(1 << 19) - 1, + "operand must be a symbol with modifier (e.g. %call30) or an integer " + "in the range"); case Match_InvalidSImm20pcaddu18i: return generateImmOutOfRangeError( Operands, ErrorInfo, /*Lower=*/-(1 << 19), diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp index 69ef349042d8a..44bb1f011dc6d 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp @@ -744,6 +744,7 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { {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_CALL30, "loongarch-call30"}, {MO_CALL36, "loongarch-call36"}, {MO_DESC_PC_HI, "loongarch-desc-pc-hi"}, {MO_DESC_PC_LO, "loongarch-desc-pc-lo"}, diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td index d971f8bc1986b..6f840dae3f0ae 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -474,6 +474,10 @@ def simm20_lu32id : SImm20Operand { let ParserMatchClass = SImmAsmOperand<20, "lu32id">; } +def simm20_pcaddu12i : SImm20Operand { + let ParserMatchClass = SImmAsmOperand<20, "pcaddu12i">; +} + def simm20_pcaddu18i : SImm20Operand { let ParserMatchClass = SImmAsmOperand<20, "pcaddu18i">; } @@ -855,7 +859,7 @@ def SLT : ALU_3R<0x00120000>; def SLTU : ALU_3R<0x00128000>; def SLTI : ALU_2RI12<0x02000000, simm12>; def SLTUI : ALU_2RI12<0x02400000, simm12>; -def PCADDU12I : ALU_1RI20<0x1c000000, simm20>; +def PCADDU12I : ALU_1RI20<0x1c000000, simm20_pcaddu12i>; def AND : ALU_3R<0x00148000>; def OR : ALU_3R<0x00150000>; def NOR : ALU_3R<0x00140000>; @@ -1718,6 +1722,16 @@ def PseudoJIRL_TAIL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>; +/// call30/tail30 macro instructions +let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, isAsmParserOnly = 1, + Defs = [R1], hasSideEffects = 0, mayStore = 0, mayLoad = 0 in +def PseudoCALL30 : Pseudo<(outs), (ins bare_symbol:$dst), [], "call30", "$dst">; +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3], + isCodeGenOnly = 0, isAsmParserOnly = 1, hasSideEffects = 0, + mayStore = 0, mayLoad = 0 in +def PseudoTAIL30 : Pseudo<(outs), (ins GPR:$tmp, bare_symbol:$dst), [], + "tail30", "$tmp, $dst">; + /// call36/taill36 macro instructions let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, isAsmParserOnly = 1, Defs = [R1], hasSideEffects = 0, mayStore = 0, mayLoad = 0 in diff --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp index 455e6ad7c3ac5..ae4090784a9f2 100644 --- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp @@ -92,6 +92,9 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, case LoongArchII::MO_GD_PC_HI: Kind = ELF::R_LARCH_TLS_GD_PC_HI20; break; + case LoongArchII::MO_CALL30: + Kind = ELF::R_LARCH_CALL30; + break; case LoongArchII::MO_CALL36: Kind = ELF::R_LARCH_CALL36; break; diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h index 833cd06261624..99d7df63fce04 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h @@ -48,6 +48,7 @@ enum { MO_IE_PC64_HI, MO_LD_PC_HI, MO_GD_PC_HI, + MO_CALL30, MO_CALL36, MO_DESC_PC_HI, MO_DESC_PC_LO, diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp index 8ecb62d0ea7bb..3f9bea5d69bf9 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp @@ -97,6 +97,8 @@ static StringRef getLoongArchSpecifierName(uint16_t S) { return "gd_pc_hi20"; case ELF::R_LARCH_TLS_GD_HI20: return "gd_hi20"; + case ELF::R_LARCH_CALL30: + return "call30"; case ELF::R_LARCH_CALL36: return "call36"; case ELF::R_LARCH_TLS_DESC_PC_HI20: @@ -174,6 +176,7 @@ LoongArchMCExpr::Specifier LoongArch::parseSpecifier(StringRef name) { .Case("ld_hi20", ELF::R_LARCH_TLS_LD_HI20) .Case("gd_pc_hi20", ELF::R_LARCH_TLS_GD_PC_HI20) .Case("gd_hi20", ELF::R_LARCH_TLS_GD_HI20) + .Case("call30", ELF::R_LARCH_CALL30) .Case("call36", ELF::R_LARCH_CALL36) .Case("desc_pc_hi20", ELF::R_LARCH_TLS_DESC_PC_HI20) .Case("desc_pc_lo12", ELF::R_LARCH_TLS_DESC_PC_LO12) diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp index 08fa51d333346..661cf8aae99e4 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp @@ -180,6 +180,7 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO, case ELF::R_LARCH_ABS64_HI12: FixupKind = LoongArch::fixup_loongarch_abs64_hi12; break; + case ELF::R_LARCH_CALL30: case ELF::R_LARCH_CALL36: case ELF::R_LARCH_TLS_LE_HI20_R: case ELF::R_LARCH_TLS_LE_LO12_R: diff --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s index 08a131d4d43f9..8488129bc253a 100644 --- a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s +++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s @@ -98,9 +98,9 @@ bgeu $a0, $a0, 0x1FFFF jirl $a0, $a0, 0x20000 # CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068] -## simm20 +## simm20_pcaddu12i pcaddu12i $a0, 0x80000 -# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287] +# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %call30) or an integer in the range [-524288, 524287] ## simm20_pcaddi pcaddi $a0, -0x80001 diff --git a/llvm/test/MC/LoongArch/Macros/macros-call.s b/llvm/test/MC/LoongArch/Macros/macros-call.s index df7715050a0f9..0fbc2160c14f5 100644 --- a/llvm/test/MC/LoongArch/Macros/macros-call.s +++ b/llvm/test/MC/LoongArch/Macros/macros-call.s @@ -7,6 +7,20 @@ # RELOC: Relocations [ # RELOC-NEXT: Section ({{.*}}) .rela.text { +call30 sym_call +# CHECK: pcaddu12i $ra, %call30(sym_call) +# CHECK-NEXT: jirl $ra, $ra, 0 + +# RELOC-NEXT: R_LARCH_CALL30 sym_call 0x0 +# RELAX-NEXT: R_LARCH_RELAX - 0x0 + +tail30 $t0, sym_tail +# CHECK: pcaddu12i $t0, %call30(sym_tail) +# CHECK-NEXT: jr $t0 + +# RELOC-NEXT: R_LARCH_CALL30 sym_tail 0x0 +# RELAX-NEXT: R_LARCH_RELAX - 0x0 + call36 sym_call # CHECK: pcaddu18i $ra, %call36(sym_call) # CHECK-NEXT: jirl $ra, $ra, 0 @@ -21,6 +35,5 @@ tail36 $t0, sym_tail # RELOC-NEXT: R_LARCH_CALL36 sym_tail 0x0 # RELAX-NEXT: R_LARCH_RELAX - 0x0 - # RELOC-NEXT: } # RELOC-NEXT: ] _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
