forked from OSchip/llvm-project
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! llvm-svn: 108047
This commit is contained in:
parent
c4b3bcc051
commit
de457896b6
|
@ -1006,15 +1006,17 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
|
|||
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 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
|
|||
}
|
||||
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 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
|
|||
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
|
||||
|
|
|
@ -1898,6 +1898,42 @@ bool X86InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
|||
const TargetRegisterClass *SrcRC,
|
||||
DebugLoc DL) const {
|
||||
|
||||
// Moving from ST(0) turns into FpGET_ST0_32 etc.
|
||||
if (SrcReg == X86::ST0 || SrcReg == X86::ST1) {
|
||||
// Copying from ST(0)/ST(1).
|
||||
bool isST0 = SrcReg == X86::ST0;
|
||||
unsigned Opc;
|
||||
if (DestRC == &X86::RFP32RegClass)
|
||||
Opc = isST0 ? X86::FpGET_ST0_32 : X86::FpGET_ST1_32;
|
||||
else if (DestRC == &X86::RFP64RegClass)
|
||||
Opc = isST0 ? X86::FpGET_ST0_64 : X86::FpGET_ST1_64;
|
||||
else {
|
||||
if (DestRC != &X86::RFP80RegClass)
|
||||
return false;
|
||||
Opc = isST0 ? X86::FpGET_ST0_80 : X86::FpGET_ST1_80;
|
||||
}
|
||||
BuildMI(MBB, MI, DL, get(Opc), DestReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Moving to ST(0) turns into FpSET_ST0_32 etc.
|
||||
if (DestReg == X86::ST0 || DestReg == X86::ST1) {
|
||||
// Copying to ST(0) / ST(1).
|
||||
bool isST0 = DestReg == X86::ST0;
|
||||
unsigned Opc;
|
||||
if (SrcRC == &X86::RFP32RegClass)
|
||||
Opc = isST0 ? X86::FpSET_ST0_32 : X86::FpSET_ST1_32;
|
||||
else if (SrcRC == &X86::RFP64RegClass)
|
||||
Opc = isST0 ? X86::FpSET_ST0_64 : X86::FpSET_ST1_64;
|
||||
else {
|
||||
if (SrcRC != &X86::RFP80RegClass)
|
||||
return false;
|
||||
Opc = isST0 ? X86::FpSET_ST0_80 : X86::FpSET_ST1_80;
|
||||
}
|
||||
BuildMI(MBB, MI, DL, get(Opc)).addReg(SrcReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine if DstRC and SrcRC have a common superclass in common.
|
||||
const TargetRegisterClass *CommonRC = DestRC;
|
||||
if (DestRC == SrcRC)
|
||||
|
@ -1968,7 +2004,7 @@ bool X86InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
|||
Opc = X86::MOV32rr_TC;
|
||||
} else if (CommonRC == &X86::RFP32RegClass) {
|
||||
Opc = X86::MOV_Fp3232;
|
||||
} else if (CommonRC == &X86::RFP64RegClass || CommonRC == &X86::RSTRegClass) {
|
||||
} else if (CommonRC == &X86::RFP64RegClass) {
|
||||
Opc = X86::MOV_Fp6464;
|
||||
} else if (CommonRC == &X86::RFP80RegClass) {
|
||||
Opc = X86::MOV_Fp8080;
|
||||
|
@ -2016,48 +2052,6 @@ bool X86InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
|||
}
|
||||
}
|
||||
|
||||
// Moving from ST(0) turns into FpGET_ST0_32 etc.
|
||||
if (SrcRC == &X86::RSTRegClass) {
|
||||
// Copying from ST(0)/ST(1).
|
||||
if (SrcReg != X86::ST0 && SrcReg != X86::ST1)
|
||||
// Can only copy from ST(0)/ST(1) right now
|
||||
return false;
|
||||
bool isST0 = SrcReg == X86::ST0;
|
||||
unsigned Opc;
|
||||
if (DestRC == &X86::RFP32RegClass)
|
||||
Opc = isST0 ? X86::FpGET_ST0_32 : X86::FpGET_ST1_32;
|
||||
else if (DestRC == &X86::RFP64RegClass)
|
||||
Opc = isST0 ? X86::FpGET_ST0_64 : X86::FpGET_ST1_64;
|
||||
else {
|
||||
if (DestRC != &X86::RFP80RegClass)
|
||||
return false;
|
||||
Opc = isST0 ? X86::FpGET_ST0_80 : X86::FpGET_ST1_80;
|
||||
}
|
||||
BuildMI(MBB, MI, DL, get(Opc), DestReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Moving to ST(0) turns into FpSET_ST0_32 etc.
|
||||
if (DestRC == &X86::RSTRegClass) {
|
||||
// Copying to ST(0) / ST(1).
|
||||
if (DestReg != X86::ST0 && DestReg != X86::ST1)
|
||||
// Can only copy to TOS right now
|
||||
return false;
|
||||
bool isST0 = DestReg == X86::ST0;
|
||||
unsigned Opc;
|
||||
if (SrcRC == &X86::RFP32RegClass)
|
||||
Opc = isST0 ? X86::FpSET_ST0_32 : X86::FpSET_ST1_32;
|
||||
else if (SrcRC == &X86::RFP64RegClass)
|
||||
Opc = isST0 ? X86::FpSET_ST0_64 : X86::FpSET_ST1_64;
|
||||
else {
|
||||
if (SrcRC != &X86::RFP80RegClass)
|
||||
return false;
|
||||
Opc = isST0 ? X86::FpSET_ST0_80 : X86::FpSET_ST1_80;
|
||||
}
|
||||
BuildMI(MBB, MI, DL, get(Opc)).addReg(SrcReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not yet supported!
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue