diff options
author | Nate Begeman <natebegeman@mac.com> | 2005-07-16 02:02:34 +0000 |
---|---|---|
committer | Nate Begeman <natebegeman@mac.com> | 2005-07-16 02:02:34 +0000 |
commit | 5a8441ea3fc145393d6274156bd05c4a006099ea (patch) | |
tree | cc5a8d6efc77c3e61d52510456c108fd2b4c9f27 | |
parent | 11cefd926a1be9e6cd52b4e189a99081a385d57f (diff) | |
download | external_llvm-5a8441ea3fc145393d6274156bd05c4a006099ea.zip external_llvm-5a8441ea3fc145393d6274156bd05c4a006099ea.tar.gz external_llvm-5a8441ea3fc145393d6274156bd05c4a006099ea.tar.bz2 |
Teach the legalizer how to promote SINT_TO_FP to a wider SINT_TO_FP that
the target natively supports. This eliminates some special-case code from
the x86 backend and generates better code as well.
For an i8 to f64 conversion, before & after:
_x87 before:
subl $2, %esp
movb 6(%esp), %al
movsbw %al, %ax
movw %ax, (%esp)
filds (%esp)
addl $2, %esp
ret
_x87 after:
subl $2, %esp
movsbw 6(%esp), %ax
movw %ax, (%esp)
filds (%esp)
addl $2, %esp
ret
_sse before:
subl $12, %esp
movb 16(%esp), %al
movsbl %al, %eax
cvtsi2sd %eax, %xmm0
addl $12, %esp
ret
_sse after:
subl $12, %esp
movsbl 16(%esp), %eax
cvtsi2sd %eax, %xmm0
addl $12, %esp
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22452 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 28 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelPattern.cpp | 65 |
2 files changed, 39 insertions, 54 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index ee515fd3..701e528 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -126,7 +126,8 @@ private: SDOperand Source); SDOperand ExpandLegalUINT_TO_FP(SDOperand LegalOp, MVT::ValueType DestVT); - SDOperand PromoteLegalUINT_TO_FP(SDOperand LegalOp, MVT::ValueType DestVT); + SDOperand PromoteLegalINT_TO_FP(SDOperand LegalOp, MVT::ValueType DestVT, + bool isSigned); bool ExpandShift(unsigned Opc, SDOperand Op, SDOperand Amt, SDOperand &Lo, SDOperand &Hi); @@ -197,8 +198,9 @@ SDOperand SelectionDAGLegalize::ExpandLegalUINT_TO_FP(SDOperand Op0, /// we promote it. At this point, we know that the result and operand types are /// legal for the target, and that there is a legal UINT_TO_FP or SINT_TO_FP /// operation that takes a larger input. -SDOperand SelectionDAGLegalize::PromoteLegalUINT_TO_FP(SDOperand LegalOp, - MVT::ValueType DestVT) { +SDOperand SelectionDAGLegalize::PromoteLegalINT_TO_FP(SDOperand LegalOp, + MVT::ValueType DestVT, + bool isSigned) { // First step, figure out the appropriate *INT_TO_FP operation to use. MVT::ValueType NewInTy = LegalOp.getValueType(); @@ -221,6 +223,7 @@ SDOperand SelectionDAGLegalize::PromoteLegalUINT_TO_FP(SDOperand LegalOp, break; } if (OpToUse) break; + if (isSigned) continue; // If the target supports UINT_TO_FP of this type, use it. switch (TLI.getOperationAction(ISD::UINT_TO_FP, NewInTy)) { @@ -244,7 +247,8 @@ SDOperand SelectionDAGLegalize::PromoteLegalUINT_TO_FP(SDOperand LegalOp, // Okay, we found the operation and type to use. Zero extend our input to the // desired type then run the operation on it. return DAG.getNode(OpToUse, DestVT, - DAG.getNode(ISD::ZERO_EXTEND, NewInTy, LegalOp)); + DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, + NewInTy, LegalOp)); } void SelectionDAGLegalize::LegalizeDAG() { @@ -1438,18 +1442,24 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { switch (getTypeAction(Node->getOperand(0).getValueType())) { case Legal: //still made need to expand if the op is illegal, but the types are legal - if (Node->getOpcode() == ISD::UINT_TO_FP) { + if (Node->getOpcode() == ISD::UINT_TO_FP || + Node->getOpcode() == ISD::SINT_TO_FP) { + bool isSigned = Node->getOpcode() == ISD::SINT_TO_FP; switch (TLI.getOperationAction(Node->getOpcode(), Node->getOperand(0).getValueType())) { default: assert(0 && "Unknown operation action!"); case TargetLowering::Expand: - Result = ExpandLegalUINT_TO_FP(LegalizeOp(Node->getOperand(0)), - Node->getValueType(0)); + if (!isSigned) + Result = ExpandLegalUINT_TO_FP(LegalizeOp(Node->getOperand(0)), + Node->getValueType(0)); + else + assert(0 && "Legalize cannot Expand SINT_TO_FP yet"); AddLegalizedOperand(Op, Result); return Result; case TargetLowering::Promote: - Result = PromoteLegalUINT_TO_FP(LegalizeOp(Node->getOperand(0)), - Node->getValueType(0)); + Result = PromoteLegalINT_TO_FP(LegalizeOp(Node->getOperand(0)), + Node->getValueType(0), + isSigned); AddLegalizedOperand(Op, Result); return Result; case TargetLowering::Legal: diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp index 6378663..999f089 100644 --- a/lib/Target/X86/X86ISelPattern.cpp +++ b/lib/Target/X86/X86ISelPattern.cpp @@ -112,6 +112,11 @@ namespace { setOperationAction(ISD::UINT_TO_FP , MVT::i8 , Promote); setOperationAction(ISD::UINT_TO_FP , MVT::i16 , Promote); setOperationAction(ISD::UINT_TO_FP , MVT::i32 , Promote); + + // Promote i1/i8 SINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have + // this operation. + setOperationAction(ISD::SINT_TO_FP , MVT::i1 , Promote); + setOperationAction(ISD::SINT_TO_FP , MVT::i8 , Promote); // We can handle SINT_TO_FP from i64 even though i64 isn't legal. setOperationAction(ISD::SINT_TO_FP , MVT::i64 , Custom); @@ -151,9 +156,13 @@ namespace { addRegisterClass(MVT::f32, X86::RXMMRegisterClass); addRegisterClass(MVT::f64, X86::RXMMRegisterClass); + // SSE has no load+extend ops setOperationAction(ISD::EXTLOAD, MVT::f32, Expand); setOperationAction(ISD::ZEXTLOAD, MVT::f32, Expand); - + + // SSE has no i16 to fp conversion, only i32 + setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote); + // We don't support sin/cos/sqrt/fmod setOperationAction(ISD::FSIN , MVT::f64, Expand); setOperationAction(ISD::FCOS , MVT::f64, Expand); @@ -2363,56 +2372,17 @@ unsigned ISel::SelectExpr(SDOperand N) { Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register unsigned PromoteOpcode = 0; - // We can handle any sint to fp, and 8 and 16 uint to fp with the direct - // sse conversion instructions. + // We can handle any sint to fp with the direct sse conversion instructions. if (X86ScalarSSE) { - MVT::ValueType SrcTy = N.getOperand(0).getValueType(); - MVT::ValueType DstTy = N.getValueType(); - switch (SrcTy) { - case MVT::i1: // FIXME: Should teach legalize about SINT_TO_FP i1/i8/i16 - case MVT::i8: // promotion, just like UINT_TO_FP promotion. - PromoteOpcode = X86::MOVSX32rr8; - break; - case MVT::i16: - PromoteOpcode = X86::MOVSX32rr16; - break; - default: - break; - } - if (PromoteOpcode) { - BuildMI(BB, PromoteOpcode, 1, Tmp2).addReg(Tmp1); - Tmp1 = Tmp2; - } - Opc = (DstTy == MVT::f64) ? X86::CVTSI2SDrr : X86::CVTSI2SSrr; + Opc = (N.getValueType() == MVT::f64) ? X86::CVTSI2SDrr : X86::CVTSI2SSrr; BuildMI(BB, Opc, 1, Result).addReg(Tmp1); return Result; } - // FIXME: Most of this grunt work should be done by legalize! ContainsFPCode = true; - // Promote the integer to a type supported by FLD. We do this because there - // are no unsigned FLD instructions, so we must promote an unsigned value to - // a larger signed value, then use FLD on the larger value. - // - MVT::ValueType SrcTy = N.getOperand(0).getValueType(); - switch (SrcTy) { - case MVT::i1: - case MVT::i8: - // We don't have the facilities for directly loading byte sized data from - // memory (even signed). Promote it to 16 bits. - - // FIXME: move to legalize. - Tmp2 = MakeReg(MVT::i16); - BuildMI(BB, X86::MOVSX16rr8, 1, Tmp2).addReg(Tmp1); - SrcTy = MVT::i16; - Tmp1 = Tmp2; - break; - default: - break; - } - // Spill the integer to memory and reload it from there. + MVT::ValueType SrcTy = N.getOperand(0).getValueType(); unsigned Size = MVT::getSizeInBits(SrcTy)/8; MachineFunction *F = BB->getParent(); int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size); @@ -3345,8 +3315,13 @@ unsigned ISel::SelectExpr(SDOperand N) { SelectAddress(Address, AM); Select(Chain); } - - addFullAddress(BuildMI(BB, X86::FILD64m, 4, Result), AM); + if (X86ScalarSSE) { + addFullAddress(BuildMI(BB, X86::FILD64m, 4, X86::FP0), AM); + addFullAddress(BuildMI(BB, X86::FST64m, 5), AM).addReg(X86::FP0); + addFullAddress(BuildMI(BB, X86::MOVSDrm, 4, Result), AM); + } else { + addFullAddress(BuildMI(BB, X86::FILD64m, 4, Result), AM); + } } return Result; |