OSDN Git Service

If an xmm register is referenced explicitly in an inline asm, make sure to
authorChris Lattner <sabre@nondot.org>
Tue, 26 Aug 2008 06:19:02 +0000 (06:19 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 26 Aug 2008 06:19:02 +0000 (06:19 +0000)
assign it to a version of the xmm register with the regclass that matches its
type.  This fixes PR2715, a bug handling some crazy xpcom case in mozilla.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55358 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/2008-08-25-AsmRegTypeMismatch.ll [new file with mode: 0644]

index 8601683..0477c27 100644 (file)
@@ -7221,56 +7221,68 @@ X86TargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
   // 16-bit register pieces "ax","dx","cx","bx","si","di","bp","sp".  If we
   // really want an 8-bit or 32-bit register, map to the appropriate register
   // class and return the appropriate register.
-  if (Res.second != X86::GR16RegisterClass)
-    return Res;
-
-  if (VT == MVT::i8) {
-    unsigned DestReg = 0;
-    switch (Res.first) {
-    default: break;
-    case X86::AX: DestReg = X86::AL; break;
-    case X86::DX: DestReg = X86::DL; break;
-    case X86::CX: DestReg = X86::CL; break;
-    case X86::BX: DestReg = X86::BL; break;
-    }
-    if (DestReg) {
-      Res.first = DestReg;
-      Res.second = Res.second = X86::GR8RegisterClass;
-    }
-  } else if (VT == MVT::i32) {
-    unsigned DestReg = 0;
-    switch (Res.first) {
-    default: break;
-    case X86::AX: DestReg = X86::EAX; break;
-    case X86::DX: DestReg = X86::EDX; break;
-    case X86::CX: DestReg = X86::ECX; break;
-    case X86::BX: DestReg = X86::EBX; break;
-    case X86::SI: DestReg = X86::ESI; break;
-    case X86::DI: DestReg = X86::EDI; break;
-    case X86::BP: DestReg = X86::EBP; break;
-    case X86::SP: DestReg = X86::ESP; break;
-    }
-    if (DestReg) {
-      Res.first = DestReg;
-      Res.second = Res.second = X86::GR32RegisterClass;
-    }
-  } else if (VT == MVT::i64) {
-    unsigned DestReg = 0;
-    switch (Res.first) {
-    default: break;
-    case X86::AX: DestReg = X86::RAX; break;
-    case X86::DX: DestReg = X86::RDX; break;
-    case X86::CX: DestReg = X86::RCX; break;
-    case X86::BX: DestReg = X86::RBX; break;
-    case X86::SI: DestReg = X86::RSI; break;
-    case X86::DI: DestReg = X86::RDI; break;
-    case X86::BP: DestReg = X86::RBP; break;
-    case X86::SP: DestReg = X86::RSP; break;
-    }
-    if (DestReg) {
-      Res.first = DestReg;
-      Res.second = Res.second = X86::GR64RegisterClass;
+  if (Res.second == X86::GR16RegisterClass) {
+    if (VT == MVT::i8) {
+      unsigned DestReg = 0;
+      switch (Res.first) {
+      default: break;
+      case X86::AX: DestReg = X86::AL; break;
+      case X86::DX: DestReg = X86::DL; break;
+      case X86::CX: DestReg = X86::CL; break;
+      case X86::BX: DestReg = X86::BL; break;
+      }
+      if (DestReg) {
+        Res.first = DestReg;
+        Res.second = Res.second = X86::GR8RegisterClass;
+      }
+    } else if (VT == MVT::i32) {
+      unsigned DestReg = 0;
+      switch (Res.first) {
+      default: break;
+      case X86::AX: DestReg = X86::EAX; break;
+      case X86::DX: DestReg = X86::EDX; break;
+      case X86::CX: DestReg = X86::ECX; break;
+      case X86::BX: DestReg = X86::EBX; break;
+      case X86::SI: DestReg = X86::ESI; break;
+      case X86::DI: DestReg = X86::EDI; break;
+      case X86::BP: DestReg = X86::EBP; break;
+      case X86::SP: DestReg = X86::ESP; break;
+      }
+      if (DestReg) {
+        Res.first = DestReg;
+        Res.second = Res.second = X86::GR32RegisterClass;
+      }
+    } else if (VT == MVT::i64) {
+      unsigned DestReg = 0;
+      switch (Res.first) {
+      default: break;
+      case X86::AX: DestReg = X86::RAX; break;
+      case X86::DX: DestReg = X86::RDX; break;
+      case X86::CX: DestReg = X86::RCX; break;
+      case X86::BX: DestReg = X86::RBX; break;
+      case X86::SI: DestReg = X86::RSI; break;
+      case X86::DI: DestReg = X86::RDI; break;
+      case X86::BP: DestReg = X86::RBP; break;
+      case X86::SP: DestReg = X86::RSP; break;
+      }
+      if (DestReg) {
+        Res.first = DestReg;
+        Res.second = Res.second = X86::GR64RegisterClass;
+      }
     }
+  } else if (Res.second == X86::FR32RegisterClass ||
+             Res.second == X86::FR64RegisterClass ||
+             Res.second == X86::VR128RegisterClass) {
+    // Handle references to XMM physical registers that got mapped into the
+    // wrong class.  This can happen with constraints like {xmm0} where the
+    // target independent register mapper will just pick the first match it can
+    // find, ignoring the required type.
+    if (VT == MVT::f32)
+      Res.second = X86::FR32RegisterClass;
+    else if (VT == MVT::f64)
+      Res.second = X86::FR64RegisterClass;
+    else if (X86::VR128RegisterClass->hasType(VT))
+      Res.second = X86::VR128RegisterClass;
   }
 
   return Res;
diff --git a/test/CodeGen/X86/2008-08-25-AsmRegTypeMismatch.ll b/test/CodeGen/X86/2008-08-25-AsmRegTypeMismatch.ll
new file mode 100644 (file)
index 0000000..8d987b5
--- /dev/null
@@ -0,0 +1,16 @@
+; RUN: llvm-as < %s | llc -mcpu=yonah
+; PR2715
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+       %struct.XPTTypeDescriptorPrefix = type { i8 }
+       %struct.nsISupports = type { i32 (...)** }
+       %struct.nsXPTCMiniVariant = type { %"struct.nsXPTCMiniVariant::._39" }
+       %"struct.nsXPTCMiniVariant::._39" = type { i64 }
+       %struct.nsXPTCVariant = type { %struct.nsXPTCMiniVariant, i8*, %struct.nsXPTType, i8 }
+       %struct.nsXPTType = type { %struct.XPTTypeDescriptorPrefix }
+
+define i32 @XPTC_InvokeByIndex(%struct.nsISupports* %that, i32 %methodIndex, i32 %paramCount, %struct.nsXPTCVariant* %params) nounwind {
+entry:
+       call void asm sideeffect "", "{xmm0},{xmm1},{xmm2},{xmm3},{xmm4},{xmm5},{xmm6},{xmm7},~{dirflag},~{fpsr},~{flags}"( double undef, double undef, double undef, double 1.0, double undef, double 0.0, double undef, double 0.0 ) nounwind
+       ret i32 0
+}