diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-05-23 09:59:16 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-05-23 09:59:16 +0000 |
commit | 8c3cb58b10adafd833b035fca6ffdb1c5041665f (patch) | |
tree | 5a2da25ea02beb3971514295e559333e6a6180bb /lib/Target | |
parent | 9574c3047b618eb888b3718e3d596ded4dfdcc68 (diff) | |
download | external_llvm-8c3cb58b10adafd833b035fca6ffdb1c5041665f.zip external_llvm-8c3cb58b10adafd833b035fca6ffdb1c5041665f.tar.gz external_llvm-8c3cb58b10adafd833b035fca6ffdb1c5041665f.tar.bz2 |
Make the x86 backend custom-lower UINT_TO_FP and FP_TO_UINT on 32-bit
systems instead of attempting to promote them to a 64-bit SINT_TO_FP or
FP_TO_SINT. This is in preparation for removing the type legalization
code from LegalizeDAG: once type legalization is gone from LegalizeDAG,
it won't be able to handle the i64 operand/result correctly.
This isn't quite ideal, but I don't think any other operation for any
target ends up in this situation, so treating this case specially seems
reasonable.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72324 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 82 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelLowering.h | 7 |
2 files changed, 64 insertions, 25 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index debfac4..fda8cba 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -116,16 +116,14 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) if (Subtarget->is64Bit()) { setOperationAction(ISD::UINT_TO_FP , MVT::i32 , Promote); setOperationAction(ISD::UINT_TO_FP , MVT::i64 , Expand); - } else { - if (!UseSoftFloat && !NoImplicitFloat && X86ScalarSSEf64) { + } else if (!UseSoftFloat) { + if (X86ScalarSSEf64) { // We have an impenetrably clever algorithm for ui64->double only. setOperationAction(ISD::UINT_TO_FP , MVT::i64 , Custom); - - // We have faster algorithm for ui32->single only. - setOperationAction(ISD::UINT_TO_FP , MVT::i32 , Custom); - } else { - setOperationAction(ISD::UINT_TO_FP , MVT::i32 , Promote); } + // We have an algorithm for SSE2, and we turn this into a 64-bit + // FILD for other targets. + setOperationAction(ISD::UINT_TO_FP , MVT::i32 , Custom); } // Promote i1/i8 SINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have @@ -176,15 +174,16 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) if (Subtarget->is64Bit()) { setOperationAction(ISD::FP_TO_UINT , MVT::i64 , Expand); setOperationAction(ISD::FP_TO_UINT , MVT::i32 , Promote); - } else { + } else if (!UseSoftFloat) { if (X86ScalarSSEf32 && !Subtarget->hasSSE3()) // Expand FP_TO_UINT into a select. // FIXME: We would like to use a Custom expander here eventually to do // the optimal thing for SSE vs. the default expansion in the legalizer. setOperationAction(ISD::FP_TO_UINT , MVT::i32 , Expand); else - // With SSE3 we can use fisttpll to convert to a signed i64. - setOperationAction(ISD::FP_TO_UINT , MVT::i32 , Promote); + // With SSE3 we can use fisttpll to convert to a signed i64; without + // SSE, we're stuck with a fistpll. + setOperationAction(ISD::FP_TO_UINT , MVT::i32 , Custom); } // TODO: when we have SSE, these could be more efficient, by using movd/movq. @@ -4608,8 +4607,14 @@ SDValue X86TargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) { SDValue Chain = DAG.getStore(DAG.getEntryNode(), dl, Op.getOperand(0), StackSlot, PseudoSourceValue::getFixedStack(SSFI), 0); + return BuildFILD(Op, SrcVT, Chain, StackSlot, DAG); +} +SDValue X86TargetLowering::BuildFILD(SDValue Op, MVT SrcVT, SDValue Chain, + SDValue StackSlot, + SelectionDAG &DAG) { // Build the FILD + DebugLoc dl = Op.getDebugLoc(); SDVTList Tys; bool useSSE = isScalarFPTypeInSSEReg(Op.getValueType()); if (useSSE) @@ -4792,38 +4797,57 @@ SDValue X86TargetLowering::LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) { return SDValue(); return LowerUINT_TO_FP_i64(Op, DAG); - } else if (SrcVT == MVT::i32) { + } else if (SrcVT == MVT::i32 && X86ScalarSSEf64) { return LowerUINT_TO_FP_i32(Op, DAG); } - assert(0 && "Unknown UINT_TO_FP to lower!"); - return SDValue(); + assert(SrcVT == MVT::i32 && "Unknown UINT_TO_FP to lower!"); + + // Make a 64-bit buffer, and use it to build an FILD. + SDValue StackSlot = DAG.CreateStackTemporary(MVT::i64); + SDValue WordOff = DAG.getConstant(4, getPointerTy()); + SDValue OffsetSlot = DAG.getNode(ISD::ADD, dl, + getPointerTy(), StackSlot, WordOff); + SDValue Store1 = DAG.getStore(DAG.getEntryNode(), dl, Op.getOperand(0), + StackSlot, NULL, 0); + SDValue Store2 = DAG.getStore(Store1, dl, DAG.getConstant(0, MVT::i32), + OffsetSlot, NULL, 0); + return BuildFILD(Op, MVT::i64, Store2, StackSlot, DAG); } std::pair<SDValue,SDValue> X86TargetLowering:: -FP_TO_SINTHelper(SDValue Op, SelectionDAG &DAG) { +FP_TO_INTHelper(SDValue Op, SelectionDAG &DAG, bool IsSigned) { DebugLoc dl = Op.getDebugLoc(); - assert(Op.getValueType().getSimpleVT() <= MVT::i64 && - Op.getValueType().getSimpleVT() >= MVT::i16 && + + MVT DstTy = Op.getValueType(); + + if (!IsSigned) { + assert(DstTy == MVT::i32 && "Unexpected FP_TO_UINT"); + DstTy = MVT::i64; + } + + assert(DstTy.getSimpleVT() <= MVT::i64 && + DstTy.getSimpleVT() >= MVT::i16 && "Unknown FP_TO_SINT to lower!"); // These are really Legal. - if (Op.getValueType() == MVT::i32 && + if (DstTy == MVT::i32 && isScalarFPTypeInSSEReg(Op.getOperand(0).getValueType())) return std::make_pair(SDValue(), SDValue()); if (Subtarget->is64Bit() && - Op.getValueType() == MVT::i64 && + DstTy == MVT::i64 && Op.getOperand(0).getValueType() != MVT::f80) return std::make_pair(SDValue(), SDValue()); // We lower FP->sint64 into FISTP64, followed by a load, all to a temporary // stack slot. MachineFunction &MF = DAG.getMachineFunction(); - unsigned MemSize = Op.getValueType().getSizeInBits()/8; + unsigned MemSize = DstTy.getSizeInBits()/8; int SSFI = MF.getFrameInfo()->CreateStackObject(MemSize, MemSize); SDValue StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); + unsigned Opc; - switch (Op.getValueType().getSimpleVT()) { + switch (DstTy.getSimpleVT()) { default: assert(0 && "Invalid FP_TO_SINT to lower!"); case MVT::i16: Opc = X86ISD::FP_TO_INT16_IN_MEM; break; case MVT::i32: Opc = X86ISD::FP_TO_INT32_IN_MEM; break; @@ -4833,7 +4857,7 @@ FP_TO_SINTHelper(SDValue Op, SelectionDAG &DAG) { SDValue Chain = DAG.getEntryNode(); SDValue Value = Op.getOperand(0); if (isScalarFPTypeInSSEReg(Op.getOperand(0).getValueType())) { - assert(Op.getValueType() == MVT::i64 && "Invalid FP_TO_SINT to lower!"); + assert(DstTy == MVT::i64 && "Invalid FP_TO_SINT to lower!"); Chain = DAG.getStore(Chain, dl, Value, StackSlot, PseudoSourceValue::getFixedStack(SSFI), 0); SDVTList Tys = DAG.getVTList(Op.getOperand(0).getValueType(), MVT::Other); @@ -4854,7 +4878,7 @@ FP_TO_SINTHelper(SDValue Op, SelectionDAG &DAG) { } SDValue X86TargetLowering::LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) { - std::pair<SDValue,SDValue> Vals = FP_TO_SINTHelper(Op, DAG); + std::pair<SDValue,SDValue> Vals = FP_TO_INTHelper(Op, DAG, true); SDValue FIST = Vals.first, StackSlot = Vals.second; if (FIST.getNode() == 0) return SDValue(); @@ -4863,6 +4887,16 @@ SDValue X86TargetLowering::LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) { FIST, StackSlot, NULL, 0); } +SDValue X86TargetLowering::LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG) { + std::pair<SDValue,SDValue> Vals = FP_TO_INTHelper(Op, DAG, false); + SDValue FIST = Vals.first, StackSlot = Vals.second; + assert(FIST.getNode() && "Unexpected failure"); + + // Load the result. + return DAG.getLoad(Op.getValueType(), Op.getDebugLoc(), + FIST, StackSlot, NULL, 0); +} + SDValue X86TargetLowering::LowerFABS(SDValue Op, SelectionDAG &DAG) { DebugLoc dl = Op.getDebugLoc(); MVT VT = Op.getValueType(); @@ -6555,6 +6589,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG); case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG); case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG); + case ISD::FP_TO_UINT: return LowerFP_TO_UINT(Op, DAG); case ISD::FABS: return LowerFABS(Op, DAG); case ISD::FNEG: return LowerFNEG(Op, DAG); case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG); @@ -6626,7 +6661,8 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N, assert(false && "Do not know how to custom type legalize this operation!"); return; case ISD::FP_TO_SINT: { - std::pair<SDValue,SDValue> Vals = FP_TO_SINTHelper(SDValue(N, 0), DAG); + std::pair<SDValue,SDValue> Vals = + FP_TO_INTHelper(SDValue(N, 0), DAG, true); SDValue FIST = Vals.first, StackSlot = Vals.second; if (FIST.getNode() != 0) { MVT VT = N->getValueType(0); diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index a68a6fa..badbd24 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -569,8 +569,8 @@ namespace llvm { NameDecorationStyle NameDecorationForFORMAL_ARGUMENTS(SDValue Op); unsigned GetAlignedArgumentStackSize(unsigned StackSize, SelectionDAG &DAG); - std::pair<SDValue,SDValue> FP_TO_SINTHelper(SDValue Op, - SelectionDAG &DAG); + std::pair<SDValue,SDValue> FP_TO_INTHelper(SDValue Op, SelectionDAG &DAG, + bool isSigned); SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG); SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG); @@ -586,11 +586,14 @@ namespace llvm { SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG); SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG); SDValue LowerShift(SDValue Op, SelectionDAG &DAG); + SDValue BuildFILD(SDValue Op, MVT SrcVT, SDValue Chain, SDValue StackSlot, + SelectionDAG &DAG); SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG); SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG); SDValue LowerUINT_TO_FP_i64(SDValue Op, SelectionDAG &DAG); SDValue LowerUINT_TO_FP_i32(SDValue Op, SelectionDAG &DAG); SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG); + SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG); SDValue LowerFABS(SDValue Op, SelectionDAG &DAG); SDValue LowerFNEG(SDValue Op, SelectionDAG &DAG); SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG); |