summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-03-21 06:38:26 +0000
committerChris Lattner <sabre@nondot.org>2008-03-21 06:38:26 +0000
commit24e0a546b40d67dd3662273eb4aef30c230a15ef (patch)
treea13ccd51a3a64ca1fc6a6703e714c91cfa9778f1 /lib
parentae60ddc22ad243ea9ae2f4353e143190063f2322 (diff)
downloadllvm-24e0a546b40d67dd3662273eb4aef30c230a15ef.tar.gz
llvm-24e0a546b40d67dd3662273eb4aef30c230a15ef.tar.bz2
llvm-24e0a546b40d67dd3662273eb4aef30c230a15ef.tar.xz
Add support for calls that return two FP values in
ST(0)/ST(1). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48634 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/X86/X86FloatingPoint.cpp36
-rw-r--r--lib/Target/X86/X86InstrFPStack.td9
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp12
3 files changed, 52 insertions, 5 deletions
diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp
index 2070cc5d13..897edcbadd 100644
--- a/lib/Target/X86/X86FloatingPoint.cpp
+++ b/lib/Target/X86/X86FloatingPoint.cpp
@@ -933,6 +933,42 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
assert(StackTop == 0 && "Stack should be empty after a call!");
pushReg(getFPReg(MI->getOperand(0)));
break;
+ case X86::FpGET_ST1_32:// Appears immediately after a call returning FP type!
+ case X86::FpGET_ST1_64:// Appears immediately after a call returning FP type!
+ case X86::FpGET_ST1_80:{// Appears immediately after a call returning FP type!
+ // FpGET_ST1 should occur right after a FpGET_ST0 for a call or inline asm.
+ // The pattern we expect is:
+ // CALL
+ // FP1 = FpGET_ST0
+ // FP4 = FpGET_ST1
+ //
+ // At this point, we've pushed FP1 on the top of stack, so it should be
+ // present if it isn't dead. If it was dead, we already emitted a pop to
+ // remove it from the stack and StackTop = 0.
+
+ // Push FP4 as top of stack next.
+ pushReg(getFPReg(MI->getOperand(0)));
+
+ // If StackTop was 0 before we pushed our operand, then ST(0) must have been
+ // dead. In this case, the ST(1) value is the only thing that is live, so
+ // it should be on the TOS (after the pop that was emitted) and is. Just
+ // continue in this case.
+ if (StackTop == 1)
+ break;
+
+ // Because pushReg just pushed ST(1) as TOS, we now have to swap the two top
+ // elements so that our accounting is correct.
+ unsigned RegOnTop = getStackEntry(0);
+ unsigned RegNo = getStackEntry(1);
+
+ // Swap the slots the regs are in.
+ std::swap(RegMap[RegNo], RegMap[RegOnTop]);
+
+ // Swap stack slot contents.
+ assert(RegMap[RegOnTop] < StackTop);
+ std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]);
+ break;
+ }
case X86::FpGET_ST0_ST1:
assert(StackTop == 0 && "Stack should be empty after a call!");
pushReg(getFPReg(MI->getOperand(0)));
diff --git a/lib/Target/X86/X86InstrFPStack.td b/lib/Target/X86/X86InstrFPStack.td
index d37ecf8089..be9129471c 100644
--- a/lib/Target/X86/X86InstrFPStack.td
+++ b/lib/Target/X86/X86InstrFPStack.td
@@ -136,6 +136,15 @@ def FpGET_ST0_32 : FpI_<(outs RFP32:$dst), (ins), SpecialFP, []>; // FPR = ST(0)
def FpGET_ST0_64 : FpI_<(outs RFP64:$dst), (ins), SpecialFP, []>; // FPR = ST(0)
def FpGET_ST0_80 : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FPR = ST(0)
+// FpGET_ST1* should only be issued *after* an FpGET_ST0* has been issued when
+// there are two values live out on the stack from a call or inlineasm. This
+// magic is handled by the stackifier. It is not valid to emit FpGET_ST1* and
+// then FpGET_ST0*. In addition, it is invalid for any FP-using operations to
+// occur between them.
+def FpGET_ST1_32 : FpI_<(outs RFP32:$dst), (ins), SpecialFP, []>; // FPR = ST(1)
+def FpGET_ST1_64 : FpI_<(outs RFP64:$dst), (ins), SpecialFP, []>; // FPR = ST(1)
+def FpGET_ST1_80 : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FPR = ST(1)
+
def FpGET_ST0_ST1 : FpI_<(outs RFP80:$dst1, RFP80:$dst2), (ins), SpecialFP,
[]>; // FPR = ST(0), FPR = ST(1)
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 650ab415ee..dc267942e1 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -1487,16 +1487,18 @@ void X86InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
// Moving from ST(0) turns into FpGET_ST0_32 etc.
if (SrcRC == &X86::RSTRegClass) {
- // Copying from ST(0). FIXME: handle ST(1) also
- assert(SrcReg == X86::ST0 && "Can only copy from TOS right now");
+ // Copying from ST(0)/ST(1).
+ assert((SrcReg == X86::ST0 || SrcReg == X86::ST1) &&
+ "Can only copy from ST(0)/ST(1) right now");
+ bool isST0 = SrcReg == X86::ST0;
unsigned Opc;
if (DestRC == &X86::RFP32RegClass)
- Opc = X86::FpGET_ST0_32;
+ Opc = isST0 ? X86::FpGET_ST0_32 : X86::FpGET_ST1_32;
else if (DestRC == &X86::RFP64RegClass)
- Opc = X86::FpGET_ST0_64;
+ Opc = isST0 ? X86::FpGET_ST0_64 : X86::FpGET_ST1_64;
else {
assert(DestRC == &X86::RFP80RegClass);
- Opc = X86::FpGET_ST0_80;
+ Opc = isST0 ? X86::FpGET_ST0_80 : X86::FpGET_ST1_80;
}
BuildMI(MBB, MI, get(Opc), DestReg);
return;