[llvm] [SPARC] Implement L and H inline asm argument modifiers (PR #87259)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 1 09:48:03 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-sparc

Author: Koakuma (koachan)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/87259.diff


3 Files Affected:

- (modified) llvm/docs/LangRef.rst (+2) 
- (modified) llvm/lib/Target/Sparc/SparcAsmPrinter.cpp (+42) 
- (modified) llvm/test/CodeGen/SPARC/inlineasm.ll (+9) 


``````````diff
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
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/87259


More information about the llvm-commits mailing list