forked from OSchip/llvm-project
If an xmm register is referenced explicitly in an inline asm, make sure to
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. llvm-svn: 55358
This commit is contained in:
parent
e36c39f3bf
commit
09f8cef571
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue