[llvm] f873c50 - [LoongArch] AsmParser support for the li.[wd] pseudo instructions
via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 21 00:35:19 PST 2022
Author: wanglei
Date: 2022-11-21T16:33:47+08:00
New Revision: f873c50caa597051e7cbff50116da83b8a9171c9
URL: https://github.com/llvm/llvm-project/commit/f873c50caa597051e7cbff50116da83b8a9171c9
DIFF: https://github.com/llvm/llvm-project/commit/f873c50caa597051e7cbff50116da83b8a9171c9.diff
LOG: [LoongArch] AsmParser support for the li.[wd] pseudo instructions
The `li.[wd]` pseudo instructions are used to load an immediate value
into a GPR. These expand directly during asm parsing. As the result,
only real MC instructions are emitted to the MCStreamer. The actual
expansion to real instructions is similar to the expansion performed by
the GAS.
Note: The `li.w` always treats the imm operand as a 32-bit signed value.
Reviewed By: SixWeining
Differential Revision: https://reviews.llvm.org/D138086
Added:
llvm/test/MC/LoongArch/Macros/macros-li-bad.s
llvm/test/MC/LoongArch/Macros/macros-li.s
Modified:
llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index b33be3ee32acc..43941fbf49401 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -9,6 +9,7 @@
#include "MCTargetDesc/LoongArchInstPrinter.h"
#include "MCTargetDesc/LoongArchMCExpr.h"
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
+#include "MCTargetDesc/LoongArchMatInt.h"
#include "TargetInfo/LoongArchTargetInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstBuilder.h"
@@ -117,6 +118,9 @@ class LoongArchAsmParser : public MCTargetAsmParser {
// Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".
void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+ // Helper to emit pseudo instruction "li.w/d $rd, $imm".
+ void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+
public:
enum LoongArchMatchResultTy {
Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
@@ -409,6 +413,8 @@ class LoongArchOperand : public MCParsedAsmOperand {
IsValidKind;
}
+ bool isImm32() const { return isSImm<32>() || isUImm<32>(); }
+
/// Gets location of the first token of this operand.
SMLoc getStartLoc() const override { return StartLoc; }
/// Gets location of the last token of this operand.
@@ -1059,6 +1065,28 @@ void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
}
+void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out) {
+ MCRegister DestReg = Inst.getOperand(0).getReg();
+ int64_t Imm = Inst.getOperand(1).getImm();
+ MCRegister SrcReg = LoongArch::R0;
+
+ if (Inst.getOpcode() == LoongArch::PseudoLI_W)
+ Imm = SignExtend64<32>(Imm);
+
+ for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) {
+ unsigned Opc = Inst.Opc;
+ if (Opc == LoongArch::LU12I_W)
+ Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addImm(Inst.Imm),
+ getSTI());
+ else
+ Out.emitInstruction(
+ MCInstBuilder(Opc).addReg(DestReg).addReg(SrcReg).addImm(Inst.Imm),
+ getSTI());
+ SrcReg = DestReg;
+ }
+}
+
bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
OperandVector &Operands,
MCStreamer &Out) {
@@ -1103,6 +1131,10 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case LoongArch::PseudoLA_TLS_GD_LARGE:
emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
return false;
+ case LoongArch::PseudoLI_W:
+ case LoongArch::PseudoLI_D:
+ emitLoadImm(Inst, IDLoc, Out);
+ return false;
}
Out.emitInstruction(Inst, getSTI());
return false;
@@ -1342,6 +1374,10 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
"operand must be a bare symbol name or an immediate must be a multiple "
"of 4 in the range");
+ case Match_InvalidImm32: {
+ SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
+ return Error(ErrorLoc, "operand must be a 32 bit immediate");
+ }
case Match_InvalidBareSymbol: {
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "operand must be a bare symbol name");
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 71bf6b53e42e8..e2bb260ed435c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -101,6 +101,9 @@ class UImmAsmOperand<int width, string suffix = "">
// A parameterized register class alternative to i32imm/i64imm from Target.td.
def grlenimm : Operand<GRLenVT>;
+def imm32 : Operand<GRLenVT> {
+ let ParserMatchClass = ImmAsmOperand<"", 32, "">;
+}
def uimm2 : Operand<GRLenVT> {
let ParserMatchClass = UImmAsmOperand<2>;
@@ -1492,6 +1495,15 @@ def : InstAlias<"blez $rj, $imm16",
def : InstAlias<"bgez $rd, $imm16",
(BGE GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>;
+// Load immediate.
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
+ isAsmParserOnly = 1 in {
+def PseudoLI_W : Pseudo<(outs GPR:$rd), (ins imm32:$imm), [],
+ "li.w", "$rd, $imm">;
+def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins grlenimm:$imm), [],
+ "li.d", "$rd, $imm">, Requires<[IsLA64]>;
+}
+
//===----------------------------------------------------------------------===//
// Basic Floating-Point Instructions
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/MC/LoongArch/Macros/macros-li-bad.s b/llvm/test/MC/LoongArch/Macros/macros-li-bad.s
new file mode 100644
index 0000000000000..194b86bfed273
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Macros/macros-li-bad.s
@@ -0,0 +1,7 @@
+# RUN: not llvm-mc --triple=loongarch64 %s 2>&1 | FileCheck %s
+
+li.w $a0, 0x100000000
+# CHECK: :[[#@LINE-1]]:11: error: operand must be a 32 bit immediate
+
+li.d $a0, 0x10000000000000000
+# CHECK: :[[#@LINE-1]]:11: error: unknown operand
diff --git a/llvm/test/MC/LoongArch/Macros/macros-li.s b/llvm/test/MC/LoongArch/Macros/macros-li.s
new file mode 100644
index 0000000000000..994aa439effa1
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Macros/macros-li.s
@@ -0,0 +1,90 @@
+# RUN: llvm-mc --triple=loongarch64 %s | FileCheck %s
+
+li.w $a0, 0x0
+# CHECK: ori $a0, $zero, 0
+li.d $a0, 0x0
+# CHECK-NEXT: ori $a0, $zero, 0
+
+li.w $a0, 0xfff
+# CHECK: ori $a0, $zero, 4095
+li.d $a0, 0xfff
+# CHECK-NEXT: ori $a0, $zero, 4095
+
+li.w $a0, 0x7ffff000
+# CHECK: lu12i.w $a0, 524287
+li.d $a0, 0x7ffff000
+# CHECK-NEXT: lu12i.w $a0, 524287
+
+li.w $a0, 0x80000000
+# CHECK: lu12i.w $a0, -524288
+li.d $a0, 0x80000000
+# CHECK-NEXT: lu12i.w $a0, -524288
+# CHECK-NEXT: lu32i.d $a0, 0
+
+li.w $a0, 0xfffff800
+# CHECK: addi.w $a0, $zero, -2048
+li.d $a0, 0xfffff800
+# CHECK-NEXT: addi.w $a0, $zero, -2048
+# CHECK-NEXT: lu32i.d $a0, 0
+
+li.w $a0, 0xfffffffffffff800
+# CHECK: addi.w $a0, $zero, -2048
+li.d $a0, 0xfffffffffffff800
+# CHECK-NEXT: addi.w $a0, $zero, -2048
+
+li.w $a0, 0xffffffff80000800
+# CHECK: lu12i.w $a0, -524288
+# CHECK-NEXT: ori $a0, $a0, 2048
+li.d $a0, 0xffffffff80000800
+# CHECK-NEXT: lu12i.w $a0, -524288
+# CHECK-NEXT: ori $a0, $a0, 2048
+
+li.d $a0, 0x7ffff00000800
+# CHECK: ori $a0, $zero, 2048
+# CHECK-NEXT: lu32i.d $a0, 524287
+
+li.d $a0, 0x8000000000fff
+# CHECK: ori $a0, $zero, 4095
+# CHECK-NEXT: lu32i.d $a0, -524288
+# CHECK-NEXT: lu52i.d $a0, $a0, 0
+
+li.d $a0, 0x8000080000800
+# CHECK: lu12i.w $a0, -524288
+# CHECK-NEXT: ori $a0, $a0, 2048
+# CHECK-NEXT: lu32i.d $a0, -524288
+# CHECK-NEXT: lu52i.d $a0, $a0, 0
+
+li.d $a0, 0x80000fffff800
+# CHECK: addi.w $a0, $zero, -2048
+# CHECK-NEXT: lu32i.d $a0, -524288
+# CHECK-NEXT: lu52i.d $a0, $a0, 0
+
+li.d $a0, 0xffffffffff000
+# CHECK: lu12i.w $a0, -1
+# CHECK-NEXT: lu52i.d $a0, $a0, 0
+
+li.d $a0, 0xffffffffff800
+# CHECK: addi.w $a0, $zero, -2048
+# CHECK-NEXT: lu52i.d $a0, $a0, 0
+
+li.d $a0, 0x7ff0000000000000
+# CHECK: lu52i.d $a0, $zero, 2047
+
+li.d $a0, 0x7ff0000080000000
+# CHECK: lu12i.w $a0, -524288
+# CHECK-NEXT: lu32i.d $a0, 0
+# CHECK-NEXT: lu52i.d $a0, $a0, 2047
+
+li.d $a0, 0x7fffffff800007ff
+# CHECK: lu12i.w $a0, -524288
+# CHECK-NEXT: ori $a0, $a0, 2047
+# CHECK-NEXT: lu52i.d $a0, $a0, 2047
+
+li.d $a0, 0xfff0000000000fff
+# CHECK: ori $a0, $zero, 4095
+# CHECK-NEXT: lu52i.d $a0, $a0, -1
+
+li.d $a0, 0xffffffff7ffff800
+# CHECK: lu12i.w $a0, 524287
+# CHECK-NEXT: ori $a0, $a0, 2048
+# CHECK-NEXT: lu32i.d $a0, -1
More information about the llvm-commits
mailing list