[llvm-branch-commits] [llvm] release/18.x: [SPARC] Implement L and H inline asm argument modifiers (#87259) (PR #87714)
Tom Stellard via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Apr 10 15:21:04 PDT 2024
https://github.com/tstellar updated https://github.com/llvm/llvm-project/pull/87714
>From b6ebea7972cd05a8e4dcf0d5a54f2c793999995a Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Fri, 5 Apr 2024 04:34:07 +0700
Subject: [PATCH] [SPARC] Implement L and H inline asm argument modifiers
(#87259)
This adds support for using the L and H argument modifiers for twinword
operands in inline asm code, such as in:
```
%1 = tail call i64 asm sideeffect "rd %pc, ${0:L} ; srlx ${0:L}, 32, ${0:H}", "={o4}"()
```
This is needed by the Linux kernel.
(cherry picked from commit 697dd93ae30f489e5bcdac74c2ef2d876e3ca064)
---
llvm/docs/LangRef.rst | 2 ++
llvm/lib/Target/Sparc/SparcAsmPrinter.cpp | 44 +++++++++++++++++++++++
llvm/test/CodeGen/SPARC/inlineasm-bad.ll | 9 +++++
llvm/test/CodeGen/SPARC/inlineasm.ll | 9 +++++
4 files changed, 64 insertions(+)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 7a7ddc59ba985d..74b0439da7fc58 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -5499,6 +5499,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..6855471840e9db 100644
--- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
+++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
@@ -434,6 +434,50 @@ 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
+ {
+ const SparcSubtarget &Subtarget = MF->getSubtarget<SparcSubtarget>();
+ const MachineOperand &MO = MI->getOperand(OpNo);
+ const SparcRegisterInfo *RegisterInfo = Subtarget.getRegisterInfo();
+ Register MOReg = MO.getReg();
+
+ Register HiReg, LoReg;
+ 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.
+ MOReg = RegisterInfo->getMatchingSuperReg(MOReg, SP::sub_even,
+ &SP::IntPairRegClass);
+ if (!MOReg) {
+ SMLoc Loc;
+ 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;
+ }
+ }
+
+ HiReg = RegisterInfo->getSubReg(MOReg, SP::sub_even);
+ LoReg = RegisterInfo->getSubReg(MOReg, SP::sub_odd);
+
+ 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-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 8bf34bf1609c18..efb7f7c15220c2 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}", "={i0}"()
+ ret i64 %1
+}
More information about the llvm-branch-commits
mailing list