From: Chris Lattner Date: Wed, 31 Mar 2004 22:02:36 +0000 (+0000) Subject: Add support for floating point conditional move instructions X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=c1bab32bc56e6d27d1223431716523bbe35e4d2e;p=oota-llvm.git Add support for floating point conditional move instructions git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12576 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/FloatingPoint.cpp b/lib/Target/X86/FloatingPoint.cpp index 663b0b24b91..f2ff6c59d8a 100644 --- a/lib/Target/X86/FloatingPoint.cpp +++ b/lib/Target/X86/FloatingPoint.cpp @@ -143,6 +143,7 @@ namespace { void handleOneArgFP(MachineBasicBlock::iterator &I); void handleOneArgFPRW(MachineBasicBlock::iterator &I); void handleTwoArgFP(MachineBasicBlock::iterator &I); + void handleCondMovFP(MachineBasicBlock::iterator &I); void handleSpecialFP(MachineBasicBlock::iterator &I); }; } @@ -224,9 +225,10 @@ bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) { switch (Flags & X86II::FPTypeMask) { case X86II::ZeroArgFP: handleZeroArgFP(I); break; - case X86II::OneArgFP: handleOneArgFP(I); break; // fstp ST(0) + case X86II::OneArgFP: handleOneArgFP(I); break; // fstp ST(0) case X86II::OneArgFPRW: handleOneArgFPRW(I); break; // ST(0) = fsqrt(ST(0)) case X86II::TwoArgFP: handleTwoArgFP(I); break; + case X86II::CondMovFP: handleCondMovFP(I); break; case X86II::SpecialFP: handleSpecialFP(I); break; default: assert(0 && "Unknown FP Type!"); } @@ -554,7 +556,7 @@ void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) { Op0 = TOS = Dest; KillsOp0 = true; } - } else if (!KillsOp0 && !KillsOp1 && MI->getOpcode() != X86::FpUCOM) { + } else if (!KillsOp0 && !KillsOp1 && MI->getOpcode() != X86::FpUCOM) { // If we DO have one of our operands at the top of the stack, but we don't // have a dead operand, we must duplicate one of the operands to a new slot // on the stack. @@ -566,7 +568,7 @@ void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) { // Now we know that one of our operands is on the top of the stack, and at // least one of our operands is killed by this instruction. assert((TOS == Op0 || TOS == Op1) && - (KillsOp0 || KillsOp1 || MI->getOpcode() == X86::FpUCOM) && + (KillsOp0 || KillsOp1 || MI->getOpcode() == X86::FpUCOM) && "Stack conditions not set up right!"); // We decide which form to use based on what is on the top of the stack, and @@ -593,8 +595,9 @@ void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) { unsigned NotTOS = (TOS == Op0) ? Op1 : Op0; // Replace the old instruction with a new instruction - MBB->remove(I); - I = MBB->insert(I, BuildMI(Opcode, 1).addReg(getSTReg(NotTOS))); + MBB->remove(I++); + BuildMI(*MBB, I, Opcode, 1).addReg(getSTReg(NotTOS)); + --I; // If both operands are killed, pop one off of the stack in addition to // overwriting the other one. @@ -639,6 +642,35 @@ void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) { delete MI; // Remove the old instruction } +/// handleCondMovFP - Handle two address conditional move instructions. These +/// instructions move a st(i) register to st(0) iff a condition is true. These +/// instructions require that the first operand is at the top of the stack, but +/// otherwise don't modify the stack at all. +void FPS::handleCondMovFP(MachineBasicBlock::iterator &I) { + MachineInstr *MI = I; + + unsigned Op0 = getFPReg(MI->getOperand(0)); + unsigned Op1 = getFPReg(MI->getOperand(1)); + + // The first operand *must* be on the top of the stack. + moveToTop(Op0, I); + + // Change the second operand to the stack register that the operand is in. + MI->RemoveOperand(0); + MI->getOperand(0).setReg(getSTReg(Op1)); + + // If we kill the second operand, make sure to pop it from the stack. + for (LiveVariables::killed_iterator KI = LV->killed_begin(MI), + E = LV->killed_end(MI); KI != E; ++KI) + if (KI->second == X86::FP0+Op1) { + ++I; + moveToTop(Op1, I); // Insert fxch if necessary + --I; + popStackAfter(I); // Pop the top of the stack, killing value + break; + } +} + /// handleSpecialFP - Handle special instructions which behave unlike other /// floating point instructions. This is primarily intended for use by pseudo diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp index 663b0b24b91..f2ff6c59d8a 100644 --- a/lib/Target/X86/X86FloatingPoint.cpp +++ b/lib/Target/X86/X86FloatingPoint.cpp @@ -143,6 +143,7 @@ namespace { void handleOneArgFP(MachineBasicBlock::iterator &I); void handleOneArgFPRW(MachineBasicBlock::iterator &I); void handleTwoArgFP(MachineBasicBlock::iterator &I); + void handleCondMovFP(MachineBasicBlock::iterator &I); void handleSpecialFP(MachineBasicBlock::iterator &I); }; } @@ -224,9 +225,10 @@ bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) { switch (Flags & X86II::FPTypeMask) { case X86II::ZeroArgFP: handleZeroArgFP(I); break; - case X86II::OneArgFP: handleOneArgFP(I); break; // fstp ST(0) + case X86II::OneArgFP: handleOneArgFP(I); break; // fstp ST(0) case X86II::OneArgFPRW: handleOneArgFPRW(I); break; // ST(0) = fsqrt(ST(0)) case X86II::TwoArgFP: handleTwoArgFP(I); break; + case X86II::CondMovFP: handleCondMovFP(I); break; case X86II::SpecialFP: handleSpecialFP(I); break; default: assert(0 && "Unknown FP Type!"); } @@ -554,7 +556,7 @@ void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) { Op0 = TOS = Dest; KillsOp0 = true; } - } else if (!KillsOp0 && !KillsOp1 && MI->getOpcode() != X86::FpUCOM) { + } else if (!KillsOp0 && !KillsOp1 && MI->getOpcode() != X86::FpUCOM) { // If we DO have one of our operands at the top of the stack, but we don't // have a dead operand, we must duplicate one of the operands to a new slot // on the stack. @@ -566,7 +568,7 @@ void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) { // Now we know that one of our operands is on the top of the stack, and at // least one of our operands is killed by this instruction. assert((TOS == Op0 || TOS == Op1) && - (KillsOp0 || KillsOp1 || MI->getOpcode() == X86::FpUCOM) && + (KillsOp0 || KillsOp1 || MI->getOpcode() == X86::FpUCOM) && "Stack conditions not set up right!"); // We decide which form to use based on what is on the top of the stack, and @@ -593,8 +595,9 @@ void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) { unsigned NotTOS = (TOS == Op0) ? Op1 : Op0; // Replace the old instruction with a new instruction - MBB->remove(I); - I = MBB->insert(I, BuildMI(Opcode, 1).addReg(getSTReg(NotTOS))); + MBB->remove(I++); + BuildMI(*MBB, I, Opcode, 1).addReg(getSTReg(NotTOS)); + --I; // If both operands are killed, pop one off of the stack in addition to // overwriting the other one. @@ -639,6 +642,35 @@ void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) { delete MI; // Remove the old instruction } +/// handleCondMovFP - Handle two address conditional move instructions. These +/// instructions move a st(i) register to st(0) iff a condition is true. These +/// instructions require that the first operand is at the top of the stack, but +/// otherwise don't modify the stack at all. +void FPS::handleCondMovFP(MachineBasicBlock::iterator &I) { + MachineInstr *MI = I; + + unsigned Op0 = getFPReg(MI->getOperand(0)); + unsigned Op1 = getFPReg(MI->getOperand(1)); + + // The first operand *must* be on the top of the stack. + moveToTop(Op0, I); + + // Change the second operand to the stack register that the operand is in. + MI->RemoveOperand(0); + MI->getOperand(0).setReg(getSTReg(Op1)); + + // If we kill the second operand, make sure to pop it from the stack. + for (LiveVariables::killed_iterator KI = LV->killed_begin(MI), + E = LV->killed_end(MI); KI != E; ++KI) + if (KI->second == X86::FP0+Op1) { + ++I; + moveToTop(Op1, I); // Insert fxch if necessary + --I; + popStackAfter(I); // Pop the top of the stack, killing value + break; + } +} + /// handleSpecialFP - Handle special instructions which behave unlike other /// floating point instructions. This is primarily intended for use by pseudo