[llvm] MIPS: Support '%w' token in inline asm template for MSA (PR #91920)

YunQiang Su via llvm-commits llvm-commits at lists.llvm.org
Sun May 12 23:54:56 PDT 2024


https://github.com/wzssyqa created https://github.com/llvm/llvm-project/pull/91920

MSA registers share the FPRs as its bottom half. So that we can use MSA instructions to work with normal float/double:
   double a, b, c;
   asm volatile ("fmadd.d %w0, %w1, %w2" : "+f"(a) : "f"(b), "f"(c));

GCC has support it for quite long time.

>From c78819dc5a080b64e8ab8aa146093b729f6ac5e7 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Mon, 13 May 2024 14:40:57 +0800
Subject: [PATCH] MIPS: Support '%w' token in inline asm template for MSA

MSA registers share the FPRs as its bottom half. So that we can use
MSA instructions to work with normal float/double:
   double a, b, c;
   asm volatile ("fmadd.d %w0, %w1, %w2" : "+f"(a) : "f"(b), "f"(c));

GCC has support it for quite long time.
---
 llvm/lib/Target/Mips/MipsAsmPrinter.cpp   | 23 +++++++++++++++++++----
 llvm/lib/Target/Mips/MipsISelLowering.cpp |  4 ++++
 llvm/test/CodeGen/Mips/msa/inline-asm.ll  |  8 ++++++++
 3 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
index 66b2b0de8d52a..6112fe0b2c12f 100644
--- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -565,12 +565,27 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
       }
       break;
     }
-    case 'w':
-      // Print MSA registers for the 'f' constraint
-      // In LLVM, the 'w' modifier doesn't need to do anything.
-      // We can just call printOperand as normal.
+    case 'w': {
+      // Support to use MSA instructions on FPR.
+      // double a, b, c;
+      // asm volatile ("fmadd.d %w0, %w1, %w2" : "+w"(a) : "w"(b), "w"(c))
+      const char *RegNameF =
+          MipsInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg());
+      if (RegNameF[0] != 'f')
+        break;
+      // Now we have 'fXX', let's find 'wXX'.
+      for (const char *RegNameW = RegNameF; RegNameW < RegNameF + 32;
+           RegNameW++) {
+        if (RegNameW[0] != 'w')
+          continue;
+        if (StringRef(RegNameF + 1) == StringRef(RegNameW + 1)) {
+          O << '$' << RegNameW;
+          return false;
+        }
+      }
       break;
     }
+    }
   }
 
   printOperand(MI, OpNum, O);
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 8f7c47370ee51..f2516500e2b90 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -3958,12 +3958,14 @@ MipsTargetLowering::getConstraintType(StringRef Constraint) const {
   //       jump. This will always be $25 for -mabicalls.
   // 'l' : The lo register. 1 word storage.
   // 'x' : The hilo register pair. Double word storage.
+  // 'w' : The MSA Registers.
   if (Constraint.size() == 1) {
     switch (Constraint[0]) {
       default : break;
       case 'd':
       case 'y':
       case 'f':
+      case 'w':
       case 'c':
       case 'l':
       case 'x':
@@ -4003,6 +4005,7 @@ MipsTargetLowering::getSingleConstraintMatchWeight(
       weight = CW_Register;
     break;
   case 'f': // FPU or MSA register
+  case 'w':
     if (Subtarget.hasMSA() && type->isVectorTy() &&
         type->getPrimitiveSizeInBits().getFixedValue() == 128)
       weight = CW_Register;
@@ -4165,6 +4168,7 @@ MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
       // This will generate an error message
       return std::make_pair(0U, nullptr);
     case 'f': // FPU or MSA register
+    case 'w':
       if (VT == MVT::v16i8)
         return std::make_pair(0U, &Mips::MSA128BRegClass);
       else if (VT == MVT::v8i16 || VT == MVT::v8f16)
diff --git a/llvm/test/CodeGen/Mips/msa/inline-asm.ll b/llvm/test/CodeGen/Mips/msa/inline-asm.ll
index 57cd78a25647c..b1e7a047dbc6a 100644
--- a/llvm/test/CodeGen/Mips/msa/inline-asm.ll
+++ b/llvm/test/CodeGen/Mips/msa/inline-asm.ll
@@ -32,3 +32,11 @@ entry:
   store <4 x i32> %1, ptr @v4i32_r
   ret void
 }
+
+define dso_local double @test4(double noundef %a, double noundef %b, double noundef %c) {
+entry:
+  ; CHECK-LABEL: test4:
+  %0 = tail call double asm sideeffect "fmadd.d ${0:w}, ${1:w}, ${2:w}", "=f,f,f,0,~{$1}"(double %b, double %c, double %a)
+  ; CHECK: fmadd.d $w{{([0-9]|[1-3][0-9])}}, $w{{([0-9]|[1-3][0-9])}}, $w{{([0-9]|[1-3][0-9])}}
+  ret double %0
+}



More information about the llvm-commits mailing list