1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

Implement basic support for the 'f' register class constraint. This basically

works, but probably won't if you mix it with 't' or 'u' yet.

llvm-svn: 48243
This commit is contained in:
Chris Lattner 2008-03-11 19:50:13 +00:00
parent 4458eecb7a
commit fd2c24af72
2 changed files with 59 additions and 2 deletions

View File

@ -214,7 +214,12 @@ bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) {
for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) {
MachineInstr *MI = I;
unsigned Flags = MI->getDesc().TSFlags;
if ((Flags & X86II::FPTypeMask) == X86II::NotFP)
unsigned FPInstClass = Flags & X86II::FPTypeMask;
if (MI->getOpcode() == TargetInstrInfo::INLINEASM)
FPInstClass = X86II::SpecialFP;
if (FPInstClass == X86II::NotFP)
continue; // Efficiently ignore non-fp insts!
MachineInstr *PrevMI = 0;
@ -233,7 +238,7 @@ bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) {
DeadRegs.push_back(MO.getReg());
}
switch (Flags & X86II::FPTypeMask) {
switch (FPInstClass) {
case X86II::ZeroArgFP: handleZeroArgFP(I); break;
case X86II::OneArgFP: handleOneArgFP(I); break; // fstp ST(0)
case X86II::OneArgFPRW: handleOneArgFPRW(I); break; // ST(0) = fsqrt(ST(0))
@ -966,6 +971,44 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
}
}
break;
case TargetInstrInfo::INLINEASM: {
// The inline asm MachineInstr currently only *uses* FP registers for the
// 'f' constraint. These should be turned into the current ST(x) register
// in the machine instr. Also, any kills should be explicitly popped after
// the inline asm.
unsigned Kills[7];
unsigned NumKills = 0;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &Op = MI->getOperand(i);
if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6)
continue;
assert(Op.isUse() && "Only handle inline asm uses right now");
unsigned FPReg = getFPReg(Op);
Op.setReg(getSTReg(FPReg));
// If we kill this operand, make sure to pop it from the stack after the
// asm. We just remember it for now, and pop them all off at the end in
// a batch.
if (Op.isKill())
Kills[NumKills++] = FPReg;
}
// If this asm kills any FP registers (is the last use of them) we must
// explicitly emit pop instructions for them. Do this now after the asm has
// executed so that the ST(x) numbers are not off (which would happen if we
// did this inline with operand rewriting).
//
// Note: this might be a non-optimal pop sequence. We might be able to do
// better by trying to pop in stack order or something.
MachineBasicBlock::iterator InsertPt = MI;
while (NumKills)
freeStackSlotAfter(InsertPt, Kills[--NumKills]);
// Don't delete the inline asm!
return;
}
case X86::RET:
case X86::RETI:
// If RET has an FP register use operand, pass the first one in ST(0) and

View File

@ -26,4 +26,18 @@ define void @test5(double %X) {
ret void
}
define void @test6(double %A, double %B, double %C,
double %D, double %E) nounwind {
entry:
; Uses the same value twice, should have one fstp after the asm.
tail call void asm sideeffect "foo $0 $1", "f,f,~{dirflag},~{fpsr},~{flags}"( double %A, double %A ) nounwind
; Uses two different values, should be in st(0)/st(1) and both be popped.
tail call void asm sideeffect "bar $0 $1", "f,f,~{dirflag},~{fpsr},~{flags}"( double %B, double %C ) nounwind
; Uses two different values, one of which isn't killed in this asm, it
; should not be popped after the asm.
tail call void asm sideeffect "baz $0 $1", "f,f,~{dirflag},~{fpsr},~{flags}"( double %D, double %E ) nounwind
; This is the last use of %D, so it should be popped after.
tail call void asm sideeffect "baz $0", "f,~{dirflag},~{fpsr},~{flags}"( double %D ) nounwind
ret void
}