[llvm] [SPARC] Implement L and H inline asm argument modifiers (PR #87259)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 2 09:01:37 PDT 2024
https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/87259
>From 65ed4a79d9bd810b19ba86423e3ea656fffa6610 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Sat, 30 Mar 2024 13:01:19 +0700
Subject: [PATCH 1/2] [SPARC] Implement L and H inline asm argument modifiers
This adds support for using the L and H argument modifiers for twinword
operands in inline asm code, which is used by the Linux kernel.
---
llvm/docs/LangRef.rst | 2 ++
llvm/lib/Target/Sparc/SparcAsmPrinter.cpp | 42 +++++++++++++++++++++++
llvm/test/CodeGen/SPARC/inlineasm.ll | 9 +++++
3 files changed, 53 insertions(+)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 8bc1cab01bf0a6..3f8f4c01201a6c 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -5557,6 +5557,8 @@ RISC-V:
Sparc:
+- ``L``: Print the low-order register of a two-register operand.
+- ``H``: Print the high-order register of a two-register operand.
- ``r``: No effect.
SystemZ:
diff --git a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
index 215a8ea8319046..35daf84a351239 100644
--- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
+++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
@@ -434,6 +434,48 @@ bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
default:
// See if this is a generic print operand
return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
+ case 'L': // Low order register of a twin word register operand
+ case 'H': // High order register of a twin word register operand
+ {
+ if (OpNo == 0)
+ return true;
+
+ const SparcSubtarget &Subtarget = MF->getSubtarget<SparcSubtarget>();
+ const MachineOperand &MO = MI->getOperand(OpNo);
+ const Register MOReg = MO.getReg();
+
+ Register HiReg, LoReg;
+ if (SP::IntPairRegClass.contains(MOReg)) {
+ // If we're given a register pair, decompose it
+ // to its constituents and use them as-is.
+ const SparcRegisterInfo *RegisterInfo = Subtarget.getRegisterInfo();
+ HiReg = RegisterInfo->getSubReg(MOReg, SP::sub_even);
+ LoReg = RegisterInfo->getSubReg(MOReg, SP::sub_odd);
+ } else {
+ // Otherwise we should be given an even-numbered register,
+ // which will become the Hi part of the pair.
+ HiReg = MOReg;
+ LoReg = MOReg + 1;
+
+ // FIXME this really should not be an assert check, but
+ // I have no good idea on how to raise an error with explainations.
+ assert(((HiReg - SP::G0) % 2 == 0) &&
+ "Hi part of pair should point to an even-numbered register!");
+ }
+
+ Register Reg;
+ switch (ExtraCode[0]) {
+ case 'L':
+ Reg = LoReg;
+ break;
+ case 'H':
+ Reg = HiReg;
+ break;
+ }
+
+ O << '%' << SparcInstPrinter::getRegisterName(Reg);
+ return false;
+ }
case 'f':
case 'r':
break;
diff --git a/llvm/test/CodeGen/SPARC/inlineasm.ll b/llvm/test/CodeGen/SPARC/inlineasm.ll
index ec27598e5e83b7..cfb44817fb54a8 100644
--- a/llvm/test/CodeGen/SPARC/inlineasm.ll
+++ b/llvm/test/CodeGen/SPARC/inlineasm.ll
@@ -143,3 +143,12 @@ entry:
%1 = call double asm sideeffect "faddd $1, $2, $0", "=f,f,e"(i64 0, i64 0)
ret void
}
+
+; CHECK-label:test_twinword
+; CHECK: rd %asr5, %i1
+; CHECK: srlx %i1, 32, %i0
+
+define i64 @test_twinword(){
+ %1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "=r"()
+ ret i64 %1
+}
>From 619665f05f61e6d3be91951a1589feb2254e4b5c Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Tue, 2 Apr 2024 23:00:39 +0700
Subject: [PATCH 2/2] Add tests and apply suggested changes.
---
llvm/lib/Target/Sparc/SparcAsmPrinter.cpp | 40 +++++++++++++----------
llvm/test/CodeGen/SPARC/inlineasm-bad.ll | 9 +++++
llvm/test/CodeGen/SPARC/inlineasm.ll | 2 +-
3 files changed, 33 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
index 35daf84a351239..5beed8b342c072 100644
--- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
+++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
@@ -442,27 +442,33 @@ bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
const SparcSubtarget &Subtarget = MF->getSubtarget<SparcSubtarget>();
const MachineOperand &MO = MI->getOperand(OpNo);
- const Register MOReg = MO.getReg();
+ const SparcRegisterInfo *RegisterInfo = Subtarget.getRegisterInfo();
+ Register MOReg = MO.getReg();
Register HiReg, LoReg;
- if (SP::IntPairRegClass.contains(MOReg)) {
- // If we're given a register pair, decompose it
- // to its constituents and use them as-is.
- const SparcRegisterInfo *RegisterInfo = Subtarget.getRegisterInfo();
- HiReg = RegisterInfo->getSubReg(MOReg, SP::sub_even);
- LoReg = RegisterInfo->getSubReg(MOReg, SP::sub_odd);
- } else {
- // Otherwise we should be given an even-numbered register,
- // which will become the Hi part of the pair.
- HiReg = MOReg;
- LoReg = MOReg + 1;
-
- // FIXME this really should not be an assert check, but
- // I have no good idea on how to raise an error with explainations.
- assert(((HiReg - SP::G0) % 2 == 0) &&
- "Hi part of pair should point to an even-numbered register!");
+ if (!SP::IntPairRegClass.contains(MOReg)) {
+ // If we aren't given a register pair already, find out which pair it
+ // belongs to. Note that here, the specified register operand, which
+ // refers to the high part of the twinword, needs to be an even-numbered
+ // register.
+ if ((MOReg - SP::G0) % 2 != 0) {
+ SMLoc Loc = SMLoc();
+ OutContext.reportError(
+ Loc, "Hi part of pair should point to an even-numbered register");
+ OutContext.reportError(
+ Loc, "(note that in some cases it might be necessary to manually "
+ "bind the input/output registers instead of relying on "
+ "automatic allocation)");
+ return true;
+ }
+
+ MOReg = RegisterInfo->getMatchingSuperReg(MOReg, SP::sub_even,
+ &SP::IntPairRegClass);
}
+ HiReg = RegisterInfo->getSubReg(MOReg, SP::sub_even);
+ LoReg = RegisterInfo->getSubReg(MOReg, SP::sub_odd);
+
Register Reg;
switch (ExtraCode[0]) {
case 'L':
diff --git a/llvm/test/CodeGen/SPARC/inlineasm-bad.ll b/llvm/test/CodeGen/SPARC/inlineasm-bad.ll
index 5bf2adbeb75c95..07eb67df6e5f7e 100644
--- a/llvm/test/CodeGen/SPARC/inlineasm-bad.ll
+++ b/llvm/test/CodeGen/SPARC/inlineasm-bad.ll
@@ -11,3 +11,12 @@ entry:
tail call void asm sideeffect "faddq $0,$1,$2", "{f38},{f0},{f0}"(fp128 0xL0, fp128 0xL0, fp128 0xL0)
ret void
}
+
+; CHECK-label:test_twinword_error
+; CHECK: error: Hi part of pair should point to an even-numbered register
+; CHECK: error: (note that in some cases it might be necessary to manually bind the input/output registers instead of relying on automatic allocation)
+
+define i64 @test_twinword_error(){
+ %1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "={i1}"()
+ ret i64 %1
+}
diff --git a/llvm/test/CodeGen/SPARC/inlineasm.ll b/llvm/test/CodeGen/SPARC/inlineasm.ll
index cfb44817fb54a8..9817d7c6971f5c 100644
--- a/llvm/test/CodeGen/SPARC/inlineasm.ll
+++ b/llvm/test/CodeGen/SPARC/inlineasm.ll
@@ -149,6 +149,6 @@ entry:
; CHECK: srlx %i1, 32, %i0
define i64 @test_twinword(){
- %1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "=r"()
+ %1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "={i0}"()
ret i64 %1
}
More information about the llvm-commits
mailing list