diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 5d5a344243c..84e90b72a80 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -642,64 +642,6 @@ SDOperand X86DAGToDAGISel::Select(SDOperand N) { return CodeGenMap[N] = CurDAG->getTargetNode(Opc, VT, Result); break; } - - case X86ISD::FP_TO_INT16_IN_MEM: - case X86ISD::FP_TO_INT32_IN_MEM: - case X86ISD::FP_TO_INT64_IN_MEM: { - assert(N.getOperand(1).getValueType() == MVT::f64); - - // Change the floating point control register to use "round towards zero" - // mode when truncating to an integer value. - MachineFunction &MF = CurDAG->getMachineFunction(); - int CWFI = MF.getFrameInfo()->CreateStackObject(2, 2); - SDOperand CWSlot = CurDAG->getFrameIndex(CWFI, MVT::i32); - SDOperand Base, Scale, Index, Disp; - (void)SelectAddr(CWSlot, Base, Scale, Index, Disp); - SDOperand Chain = N.getOperand(0); - - // Save the control word. - Chain = CurDAG->getTargetNode(X86::FNSTCW16m, MVT::Other, - Base, Scale, Index, Disp, Chain); - - // Load the old value of the high byte of the control word. - SDOperand OldCW = - CurDAG->getTargetNode(X86::MOV16rm, MVT::i16, MVT::Other, - Base, Scale, Index, Disp, Chain); - Chain = OldCW.getValue(1); - - // Set the high part to be round to zero... - Chain = CurDAG->getTargetNode(X86::MOV16mi, MVT::Other, - Base, Scale, Index, Disp, - CurDAG->getConstant(0xC7F, MVT::i16), - Chain); - - // Reload the modified control word now... - Chain = CurDAG->getTargetNode(X86::FLDCW16m, MVT::Other, - Base, Scale, Index, Disp, Chain); - - // Restore the memory image of control word to original value - Chain = CurDAG->getTargetNode(X86::MOV16mr, MVT::Other, - Base, Scale, Index, Disp, OldCW, Chain); - - switch (Opcode) { - default: assert(0 && "Unknown FP_TO_INT*_IN_MEM"); - case X86ISD::FP_TO_INT16_IN_MEM: Opc = X86::FpIST16m; break; - case X86ISD::FP_TO_INT32_IN_MEM: Opc = X86::FpIST32m; break; - case X86ISD::FP_TO_INT64_IN_MEM: Opc = X86::FpIST64m; break; - } - - SDOperand N1 = Select(N.getOperand(1)); - SDOperand Base2, Scale2, Index2, Disp2; - (void)SelectAddr(N.getOperand(2), Base2, Scale2, Index2, Disp2); - Chain = CurDAG->getTargetNode(Opc, MVT::Other, - Base2, Scale2, Index2, Disp2, N1, Chain); - - // Reload the modified control word now... - CodeGenMap[N] = - Chain = CurDAG->getTargetNode(X86::FLDCW16m, MVT::Other, - Base, Scale, Index, Disp, Chain); - return Chain; - } } return SelectCode(N); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 22194aa1de9..bd53e61ab35 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "X86.h" +#include "X86InstrBuilder.h" #include "X86ISelLowering.h" #include "X86TargetMachine.h" #include "llvm/CallingConv.h" @@ -1261,54 +1262,117 @@ static bool hasFPCMov(unsigned X86CC) { MachineBasicBlock * X86TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI, MachineBasicBlock *BB) { - assert((MI->getOpcode() == X86::CMOV_FR32 || - MI->getOpcode() == X86::CMOV_FR64) && - "Unexpected instr type to insert"); + switch (MI->getOpcode()) { + default: assert(false && "Unexpected instr type to insert"); + case X86::CMOV_FR32: + case X86::CMOV_FR64: { + // To "insert" a SELECT_CC instruction, we actually have to insert the diamond + // control-flow pattern. The incoming instruction knows the destination vreg + // to set, the condition code register to branch on, the true/false values to + // select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + ilist::iterator It = BB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // cmpTY ccX, r1, r2 + // bCC copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); + unsigned Opc = getCondBrOpcodeForX86CC(MI->getOperand(3).getImmedValue()); + BuildMI(BB, Opc, 1).addMBB(sinkMBB); + MachineFunction *F = BB->getParent(); + F->getBasicBlockList().insert(It, copy0MBB); + F->getBasicBlockList().insert(It, sinkMBB); + // Update machine-CFG edges + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + BB = sinkMBB; + BuildMI(BB, X86::PHI, 4, MI->getOperand(0).getReg()) + .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB) + .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); - // To "insert" a SELECT_CC instruction, we actually have to insert the diamond - // control-flow pattern. The incoming instruction knows the destination vreg - // to set, the condition code register to branch on, the true/false values to - // select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - ilist::iterator It = BB; - ++It; - - // thisMBB: - // ... - // TrueVal = ... - // cmpTY ccX, r1, r2 - // bCC copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *thisMBB = BB; - MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); - unsigned Opc = getCondBrOpcodeForX86CC(MI->getOperand(3).getImmedValue()); - BuildMI(BB, Opc, 1).addMBB(sinkMBB); - MachineFunction *F = BB->getParent(); - F->getBasicBlockList().insert(It, copy0MBB); - F->getBasicBlockList().insert(It, sinkMBB); - // Update machine-CFG edges - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); - - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; - - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - - // sinkMBB: - // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] - // ... - BB = sinkMBB; - BuildMI(BB, X86::PHI, 4, MI->getOperand(0).getReg()) - .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB) - .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); + delete MI; // The pseudo instruction is gone now. + return BB; + } - delete MI; // The pseudo instruction is gone now. - return BB; + case X86::FP_TO_INT16_IN_MEM: + case X86::FP_TO_INT32_IN_MEM: + case X86::FP_TO_INT64_IN_MEM: { + // Change the floating point control register to use "round towards zero" + // mode when truncating to an integer value. + MachineFunction *F = BB->getParent(); + int CWFrameIdx = F->getFrameInfo()->CreateStackObject(2, 2); + addFrameReference(BuildMI(BB, X86::FNSTCW16m, 4), CWFrameIdx); + + // Load the old value of the high byte of the control word... + unsigned OldCW = + F->getSSARegMap()->createVirtualRegister(X86::R16RegisterClass); + addFrameReference(BuildMI(BB, X86::MOV16rm, 4, OldCW), CWFrameIdx); + + // Set the high part to be round to zero... + addFrameReference(BuildMI(BB, X86::MOV16mi, 5), CWFrameIdx).addImm(0xC7F); + + // Reload the modified control word now... + addFrameReference(BuildMI(BB, X86::FLDCW16m, 4), CWFrameIdx); + + // Restore the memory image of control word to original value + addFrameReference(BuildMI(BB, X86::MOV16mr, 5), CWFrameIdx).addReg(OldCW); + + // Get the X86 opcode to use. + unsigned Opc; + switch (MI->getOpcode()) { + case X86::FP_TO_INT16_IN_MEM: Opc = X86::FpIST16m; break; + case X86::FP_TO_INT32_IN_MEM: Opc = X86::FpIST32m; break; + case X86::FP_TO_INT64_IN_MEM: Opc = X86::FpIST64m; break; + } + + X86AddressMode AM; + MachineOperand &Op = MI->getOperand(0); + if (Op.isRegister()) { + AM.BaseType = X86AddressMode::RegBase; + AM.Base.Reg = Op.getReg(); + } else { + AM.BaseType = X86AddressMode::FrameIndexBase; + AM.Base.FrameIndex = Op.getFrameIndex(); + } + Op = MI->getOperand(1); + if (Op.isImmediate()) + AM.Scale = Op.getImmedValue(); + Op = MI->getOperand(2); + if (Op.isImmediate()) + AM.IndexReg = Op.getImmedValue(); + Op = MI->getOperand(3); + if (Op.isGlobalAddress()) { + AM.GV = Op.getGlobal(); + } else { + AM.Disp = Op.getImmedValue(); + } + addFullAddress(BuildMI(BB, Opc, 5), AM).addReg(MI->getOperand(4).getReg()); + + // Reload the original control word now. + addFrameReference(BuildMI(BB, X86::FLDCW16m, 4), CWFrameIdx); + + delete MI; // The pseudo instruction is gone now. + return BB; + } + } } diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 1a5e7380125..0340a1bec69 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -52,6 +52,7 @@ def SDTX86Fst : SDTypeProfile<0, 3, [SDTCisFP<0>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>; def SDTX86Fild : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>; +def SDTX86FpToIMem: SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>; def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; @@ -102,6 +103,12 @@ def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, [SDNPHasChain]>; def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, [SDNPHasChain]>; +def X86fp_to_i16mem : SDNode<"X86ISD::FP_TO_INT16_IN_MEM", SDTX86FpToIMem, + [SDNPHasChain]>; +def X86fp_to_i32mem : SDNode<"X86ISD::FP_TO_INT32_IN_MEM", SDTX86FpToIMem, + [SDNPHasChain]>; +def X86fp_to_i64mem : SDNode<"X86ISD::FP_TO_INT64_IN_MEM", SDTX86FpToIMem, + [SDNPHasChain]>; def X86rep_stos: SDNode<"X86ISD::REP_STOS", SDTX86RepStr, [SDNPHasChain, SDNPInFlag]>; @@ -401,16 +408,32 @@ def IMPLICIT_DEF_FR64 : I<0, Pseudo, (ops FR64:$dst), let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler. def CMOV_FR32 : I<0, Pseudo, (ops FR32:$dst, FR32:$t, FR32:$f, i8imm:$cond), - "#CMOV PSEUDO!", + "#CMOV_FR32 PSEUDO!", [(set FR32:$dst, (X86cmov FR32:$t, FR32:$f, imm:$cond, STATUS))]>; def CMOV_FR64 : I<0, Pseudo, (ops FR64:$dst, FR64:$t, FR64:$f, i8imm:$cond), - "#CMOV PSEUDO!", + "#CMOV_FR64 PSEUDO!", [(set FR64:$dst, (X86cmov FR64:$t, FR64:$f, imm:$cond, STATUS))]>; } +let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler. + def FP_TO_INT16_IN_MEM : I<0, Pseudo, + (ops i16mem:$dst, RFP:$src), + "#FP_TO_INT16_IN_MEM PSEUDO!", + [(X86fp_to_i16mem RFP:$src, addr:$dst)]>; + def FP_TO_INT32_IN_MEM : I<0, Pseudo, + (ops i32mem:$dst, RFP:$src), + "#FP_TO_INT32_IN_MEM PSEUDO!", + [(X86fp_to_i32mem RFP:$src, addr:$dst)]>; + def FP_TO_INT64_IN_MEM : I<0, Pseudo, + (ops i64mem:$dst, RFP:$src), + "#FP_TO_INT64_IN_MEM PSEUDO!", + [(X86fp_to_i64mem RFP:$src, addr:$dst)]>; +} + + let isTerminator = 1 in let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in def FP_REG_KILL : I<0, Pseudo, (ops), "#FP_REG_KILL", []>;