Don't emit st(0)/st(1) copies as FpMOV instructions. Use FpSET_ST? instead.
Based on a patch by Rafael EspĂndola.
Attempt to make the FpSET_ST1 hack more robust, but we are still relying on
FpSET_ST0 preceeding it. This is only for supporting really weird x87 inline
asm.
We support:
FpSET_ST0
INLINEASM
FpSET_ST0
FpSET_ST1
INLINEASM
with and without kills on the arguments. We don't support:
FpSET_ST1
FpSET_ST0
INLINEASM
nor
FpSET_ST1
INLINEASM
Just Don't Do It!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108047 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp
index bf60c88..cee4ad7 100644
--- a/lib/Target/X86/X86FloatingPoint.cpp
+++ b/lib/Target/X86/X86FloatingPoint.cpp
@@ -1006,15 +1006,17 @@
case X86::FpSET_ST0_32:
case X86::FpSET_ST0_64:
case X86::FpSET_ST0_80: {
+ // FpSET_ST0_80 is generated by copyRegToReg for setting up inline asm
+ // arguments that use an st constraint. We expect a sequence of
+ // instructions: Fp_SET_ST0 Fp_SET_ST1? INLINEASM
unsigned Op0 = getFPReg(MI->getOperand(0));
- // FpSET_ST0_80 is generated by copyRegToReg for both function return
- // and inline assembly with the "st" constrain. In the latter case,
- // it is possible for ST(0) to be alive after this instruction.
if (!MI->killsRegister(X86::FP0 + Op0)) {
- // Duplicate Op0
- duplicateToTop(0, 7 /*temp register*/, I);
+ // Duplicate Op0 into a temporary on the stack top.
+ // This actually assumes that FP7 is dead.
+ duplicateToTop(Op0, 7, I);
} else {
+ // Op0 is killed, so just swap it into position.
moveToTop(Op0, I);
}
--StackTop; // "Forget" we have something on the top of stack!
@@ -1022,17 +1024,29 @@
}
case X86::FpSET_ST1_32:
case X86::FpSET_ST1_64:
- case X86::FpSET_ST1_80:
- // StackTop can be 1 if a FpSET_ST0_* was before this. Exchange them.
- if (StackTop == 1) {
- BuildMI(*MBB, I, dl, TII->get(X86::XCH_F)).addReg(X86::ST1);
- ++NumFXCH;
- StackTop = 0;
- break;
+ case X86::FpSET_ST1_80: {
+ // Set up st(1) for inline asm. We are assuming that st(0) has already been
+ // set up by FpSET_ST0, and our StackTop is off by one because of it.
+ unsigned Op0 = getFPReg(MI->getOperand(0));
+ // Restore the actual StackTop from before Fp_SET_ST0.
+ // Note we can't handle Fp_SET_ST1 without a preceeding Fp_SET_ST0, and we
+ // are not enforcing the constraint.
+ ++StackTop;
+ unsigned RegOnTop = getStackEntry(0); // This reg must remain in st(0).
+ if (!MI->killsRegister(X86::FP0 + Op0)) {
+ // Assume FP6 is not live, use it as a scratch register.
+ duplicateToTop(Op0, 6, I);
+ moveToTop(RegOnTop, I);
+ } else if (getSTReg(Op0) != X86::ST1) {
+ // We have the wrong value at st(1). Shuffle! Untested!
+ moveToTop(getStackEntry(1), I);
+ moveToTop(Op0, I);
+ moveToTop(RegOnTop, I);
}
- assert(StackTop == 2 && "Stack should have two element on it to return!");
- --StackTop; // "Forget" we have something on the top of stack!
+ assert(StackTop >= 2 && "Too few live registers");
+ StackTop -= 2; // "Forget" both st(0) and st(1).
break;
+ }
case X86::MOV_Fp3232:
case X86::MOV_Fp3264:
case X86::MOV_Fp6432:
@@ -1046,32 +1060,6 @@
unsigned SrcReg = getFPReg(MO1);
const MachineOperand &MO0 = MI->getOperand(0);
- // These can be created due to inline asm. Two address pass can introduce
- // copies from RFP registers to virtual registers.
- if (MO0.getReg() == X86::ST0 && SrcReg == 0) {
- assert(MO1.isKill());
- // Treat %ST0<def> = MOV_Fp8080 %FP0<kill>
- // like FpSET_ST0_80 %FP0<kill>, %ST0<imp-def>
- assert((StackTop == 1 || StackTop == 2)
- && "Stack should have one or two element on it to return!");
- --StackTop; // "Forget" we have something on the top of stack!
- break;
- } else if (MO0.getReg() == X86::ST1 && SrcReg == 1) {
- assert(MO1.isKill());
- // Treat %ST1<def> = MOV_Fp8080 %FP1<kill>
- // like FpSET_ST1_80 %FP0<kill>, %ST1<imp-def>
- // StackTop can be 1 if a FpSET_ST0_* was before this. Exchange them.
- if (StackTop == 1) {
- BuildMI(*MBB, I, dl, TII->get(X86::XCH_F)).addReg(X86::ST1);
- ++NumFXCH;
- StackTop = 0;
- break;
- }
- assert(StackTop == 2 && "Stack should have two element on it to return!");
- --StackTop; // "Forget" we have something on the top of stack!
- break;
- }
-
unsigned DestReg = getFPReg(MO0);
if (MI->killsRegister(X86::FP0+SrcReg)) {
// If the input operand is killed, we can just change the owner of the