[llvm] 4e127bc - [PowerPC] Handle FP physical register in inline asm constraint.

Sean Fertile via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 17 06:29:00 PST 2021


Author: Sean Fertile
Date: 2021-02-17T09:27:03-05:00
New Revision: 4e127bce2d1133ba95a551d69bd0e8fc3b4f9e71

URL: https://github.com/llvm/llvm-project/commit/4e127bce2d1133ba95a551d69bd0e8fc3b4f9e71
DIFF: https://github.com/llvm/llvm-project/commit/4e127bce2d1133ba95a551d69bd0e8fc3b4f9e71.diff

LOG: [PowerPC] Handle FP physical register in inline asm constraint.

Do not defer to the base class when the register constraint is a
physical fpr. The base class will select SPILLTOVSRRC as the register
class and register allocation will fail on subtargets without VSX
registers.

Differential Revision: https://reviews.llvm.org/D91629

Added: 
    llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr-spe.ll
    llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr.ll

Modified: 
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index e679ffd29327..e9cdb50492e0 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -15092,17 +15092,38 @@ PPCTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
       return std::make_pair(0U, &PPC::VSFRCRegClass);
   }
 
-  // If we name a VSX register, we can't defer to the base class because it
-  // will not recognize the correct register (their names will be VSL{0-31}
-  // and V{0-31} so they won't match). So we match them here.
-  if (Constraint.size() > 3 && Constraint[1] == 'v' && Constraint[2] == 's') {
-    int VSNum = atoi(Constraint.data() + 3);
-    assert(VSNum >= 0 && VSNum <= 63 &&
-           "Attempted to access a vsr out of range");
-    if (VSNum < 32)
-      return std::make_pair(PPC::VSL0 + VSNum, &PPC::VSRCRegClass);
-    return std::make_pair(PPC::V0 + VSNum - 32, &PPC::VSRCRegClass);
+  // Handle special cases of physical registers that are not properly handled
+  // by the base class.
+  if (Constraint[0] == '{' && Constraint[Constraint.size() - 1] == '}') {
+    // If we name a VSX register, we can't defer to the base class because it
+    // will not recognize the correct register (their names will be VSL{0-31}
+    // and V{0-31} so they won't match). So we match them here.
+    if (Constraint.size() > 3 && Constraint[1] == 'v' && Constraint[2] == 's') {
+      int VSNum = atoi(Constraint.data() + 3);
+      assert(VSNum >= 0 && VSNum <= 63 &&
+             "Attempted to access a vsr out of range");
+      if (VSNum < 32)
+        return std::make_pair(PPC::VSL0 + VSNum, &PPC::VSRCRegClass);
+      return std::make_pair(PPC::V0 + VSNum - 32, &PPC::VSRCRegClass);
+    }
+
+    // For float registers, we can't defer to the base class as it will match
+    // the SPILLTOVSRRC class.
+    if (Constraint.size() > 3 && Constraint[1] == 'f') {
+      int RegNum = atoi(Constraint.data() + 2);
+      if (RegNum > 31 || RegNum < 0)
+        report_fatal_error("Invalid floating point register number");
+      if (VT == MVT::f32 || VT == MVT::i32)
+        return Subtarget.hasSPE()
+                   ? std::make_pair(PPC::R0 + RegNum, &PPC::GPRCRegClass)
+                   : std::make_pair(PPC::F0 + RegNum, &PPC::F4RCRegClass);
+      if (VT == MVT::f64 || VT == MVT::i64)
+        return Subtarget.hasSPE()
+                   ? std::make_pair(PPC::S0 + RegNum, &PPC::SPERCRegClass)
+                   : std::make_pair(PPC::F0 + RegNum, &PPC::F8RCRegClass);
+    }
   }
+
   std::pair<unsigned, const TargetRegisterClass *> R =
       TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
 

diff  --git a/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr-spe.ll b/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr-spe.ll
new file mode 100644
index 000000000000..94147501878f
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr-spe.ll
@@ -0,0 +1,23 @@
+; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu \
+; RUN:          -mattr=+spe |  FileCheck %s
+
+define i32 @test_f32(float %x) {
+; CHECK-LABEL: test_f32:
+; CHECK:         #APP
+; CHECK-NEXT:    efsctsi 31, 3
+; CHECK-NEXT:    #NO_APP
+entry:
+  %0 = call i32 asm sideeffect "efsctsi $0, $1", "={f31},f"(float %x)
+  ret i32 %0
+}
+
+define i32 @test_f64(double %x) {
+; CHECK-LABEL: test_f64:
+; CHECK:         #APP
+; CHECK-NEXT:    efdctsi 0, 3
+; CHECK-NEXT:    #NO_APP
+entry:
+  %0 = call i32 asm sideeffect "efdctsi $0, $1", "={f0},d"(double %x)
+  ret i32 %0
+}
+

diff  --git a/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr.ll b/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr.ll
new file mode 100644
index 000000000000..132b5d150054
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr.ll
@@ -0,0 +1,26 @@
+; RUN: llc -mcpu=pwr7 -mattr=-altivec -verify-machineinstrs \
+; RUN:     -mtriple=powerpc-unknown-aix < %s  | FileCheck %s
+
+; RUN: llc -mcpu=pwr7 -mattr=-altivec -verify-machineinstrs \
+; RUN:     -mtriple=powerpc64-unknown-aix < %s | FileCheck %s
+
+
+define dso_local double @test_double(double %a, double %b) {
+entry:
+  %0 = tail call double asm "fadd. $0,$1,$2\0A", "={f31},d,d,0"(double %a, double %b, double 0.000000e+00)
+  ret double %0
+}
+
+; CHECK-LABEL: test_double
+; CHECK:         #APP
+; CHECK-NEXT:    fadd. 31,1,2
+
+define dso_local signext i32 @test_int(double %a, double %b) {
+entry:
+  %0 = tail call i32 asm "fadd. $0,$1,$2\0A", "={f0},d,d,0"(double %a, double %b, i32 0)
+  ret i32 %0
+}
+
+; CHECK-LABEL: test_int
+; CHECK:         #APP
+; CHECK-NEXT:    fadd. 0,1,2


        


More information about the llvm-commits mailing list