mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-23 12:40:17 +00:00
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
This commit is contained in:
parent
11cefd926a
commit
5a8441ea3f
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user