Use a custom expander to compile this:

long %test4(double %X) {
        %tmp.1 = cast double %X to long         ; <long> [#uses=1]
        ret long %tmp.1
}

to this:

_test4:
        sub %ESP, 12
        fld QWORD PTR [%ESP + 16]
        fistp QWORD PTR [%ESP]
        mov %EDX, DWORD PTR [%ESP + 4]
        mov %EAX, DWORD PTR [%ESP]
        add %ESP, 12
        ret

instead of this:

_test4:
        sub %ESP, 28
        fld QWORD PTR [%ESP + 32]
        fstp QWORD PTR [%ESP]
        call ___fixdfdi
        add %ESP, 28
        ret

llvm-svn: 22549
This commit is contained in:
Chris Lattner 2005-07-29 00:40:01 +00:00
parent fe68d75aad
commit 67756e2e22
1 changed files with 57 additions and 13 deletions

View File

@ -54,6 +54,12 @@ namespace {
/// address) and two outputs (FP value and token chain). /// address) and two outputs (FP value and token chain).
FILD64m, FILD64m,
/// FISTP64m - This instruction implements FP_TO_SINT with a
/// 64-bit destination in memory and a FP reg source. This corresponds to
/// the X86::FISTP64m instruction. It has two inputs (token chain and
/// address) and two outputs (FP value and token chain).
FISTP64m,
/// CALL/TAILCALL - These operations represent an abstract X86 call /// CALL/TAILCALL - These operations represent an abstract X86 call
/// instruction, which includes a bunch of information. In particular the /// instruction, which includes a bunch of information. In particular the
/// operands of these node are: /// operands of these node are:
@ -118,8 +124,12 @@ namespace {
setOperationAction(ISD::SINT_TO_FP , MVT::i1 , Promote); setOperationAction(ISD::SINT_TO_FP , MVT::i1 , Promote);
setOperationAction(ISD::SINT_TO_FP , MVT::i8 , Promote); setOperationAction(ISD::SINT_TO_FP , MVT::i8 , Promote);
// We can handle SINT_TO_FP from i64 even though i64 isn't legal. if (!X86ScalarSSE) {
// We can handle SINT_TO_FP and FP_TO_SINT from/TO i64 even though i64
// isn't legal.
setOperationAction(ISD::SINT_TO_FP , MVT::i64 , Custom); setOperationAction(ISD::SINT_TO_FP , MVT::i64 , Custom);
setOperationAction(ISD::FP_TO_SINT , MVT::i64 , Custom);
}
setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand); setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand);
setOperationAction(ISD::MEMMOVE , MVT::Other, Expand); setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);
@ -944,7 +954,7 @@ LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
switch (Op.getOpcode()) { switch (Op.getOpcode()) {
default: assert(0 && "Should not custom lower this!"); default: assert(0 && "Should not custom lower this!");
case ISD::SINT_TO_FP: case ISD::SINT_TO_FP: {
assert(Op.getValueType() == MVT::f64 && assert(Op.getValueType() == MVT::f64 &&
Op.getOperand(0).getValueType() == MVT::i64 && Op.getOperand(0).getValueType() == MVT::i64 &&
"Unknown SINT_TO_FP to lower!"); "Unknown SINT_TO_FP to lower!");
@ -963,6 +973,27 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
Ops.push_back(StackSlot); Ops.push_back(StackSlot);
return DAG.getNode(X86ISD::FILD64m, RTs, Ops); return DAG.getNode(X86ISD::FILD64m, RTs, Ops);
} }
case ISD::FP_TO_SINT: {
assert(Op.getValueType() == MVT::i64 &&
Op.getOperand(0).getValueType() == MVT::f64 &&
"Unknown FP_TO_SINT to lower!");
// We lower FP->sint64 into FISTP64, followed by a load, all to a temporary
// stack slot.
MachineFunction &MF = DAG.getMachineFunction();
int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
// Build the FISTP64
std::vector<SDOperand> Ops;
Ops.push_back(DAG.getEntryNode());
Ops.push_back(Op.getOperand(0));
Ops.push_back(StackSlot);
SDOperand FISTP = DAG.getNode(X86ISD::FISTP64m, MVT::Other, Ops);
// Load the result.
return DAG.getLoad(MVT::i64, FISTP, StackSlot, DAG.getSrcValue(NULL));
}
}
} }
@ -2475,7 +2506,8 @@ unsigned ISel::SelectExpr(SDOperand N) {
break; break;
case MVT::i64: case MVT::i64:
addFrameReference(BuildMI(BB, X86::FISTP64m, 5), FrameIdx).addReg(Tmp1); addFrameReference(BuildMI(BB, X86::FISTP64m, 5), FrameIdx).addReg(Tmp1);
break; } break;
}
switch (Node->getValueType(0)) { switch (Node->getValueType(0)) {
default: default:
@ -3320,14 +3352,9 @@ unsigned ISel::SelectExpr(SDOperand N) {
SelectAddress(Address, AM); SelectAddress(Address, AM);
Select(Chain); Select(Chain);
} }
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); addFullAddress(BuildMI(BB, X86::FILD64m, 4, Result), AM);
} }
}
return Result; return Result;
case ISD::EXTLOAD: // Arbitrarily codegen extloads as MOVZX* case ISD::EXTLOAD: // Arbitrarily codegen extloads as MOVZX*
@ -4329,6 +4356,23 @@ void ISel::Select(SDOperand N) {
SelectExpr(N.getValue(0)); SelectExpr(N.getValue(0));
return; return;
case X86ISD::FISTP64m: {
assert(N.getOperand(1).getValueType() == MVT::f64);
X86AddressMode AM;
Select(N.getOperand(0)); // Select the token chain
unsigned ValReg;
if (getRegPressure(N.getOperand(1)) > getRegPressure(N.getOperand(2))) {
ValReg = SelectExpr(N.getOperand(1));
SelectAddress(N.getOperand(2), AM);
} else {
SelectAddress(N.getOperand(2), AM);
ValReg = SelectExpr(N.getOperand(1));
}
addFullAddress(BuildMI(BB, X86::FISTP64m, 5), AM).addReg(ValReg);
return;
}
case ISD::TRUNCSTORE: { // truncstore chain, val, ptr, SRCVALUE, storety case ISD::TRUNCSTORE: { // truncstore chain, val, ptr, SRCVALUE, storety
X86AddressMode AM; X86AddressMode AM;
MVT::ValueType StoredTy = cast<VTSDNode>(N.getOperand(4))->getVT(); MVT::ValueType StoredTy = cast<VTSDNode>(N.getOperand(4))->getVT();