On X86, casting an integer to floating point requires going through memory.

If the source of the cast is a load, we can just use the source memory location,
without having to create a temporary stack slot entry.

Before we code generated this:

double %int(int* %P) {
        %V = load int* %P
        %V2 = cast int %V to double
        ret double %V2
}

into:

int:
        sub %ESP, 4
        mov %EAX, DWORD PTR [%ESP + 8]
        mov %EAX, DWORD PTR [%EAX]
        mov DWORD PTR [%ESP], %EAX
        fild DWORD PTR [%ESP]
        add %ESP, 4
        ret

Now we produce this:

int:
        mov %EAX, DWORD PTR [%ESP + 4]
        fild DWORD PTR [%EAX]
        ret

... which is nicer.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12846 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2004-04-11 23:21:26 +00:00
parent bb4d6c59c3
commit feac3e18aa
2 changed files with 66 additions and 10 deletions

View File

@ -2621,20 +2621,40 @@ void ISel::visitLoadInst(LoadInst &I) {
// instruction, like add. If so, we don't want to emit it. Wouldn't a real
// pattern matching instruction selector be nice?
unsigned Class = getClassB(I.getType());
if (I.hasOneUse() && Class != cLong) {
if (I.hasOneUse()) {
Instruction *User = cast<Instruction>(I.use_back());
switch (User->getOpcode()) {
case Instruction::Cast:
// If this is a cast from a signed-integer type to a floating point type,
// fold the cast here.
if (getClass(User->getType()) == cFP &&
(I.getType() == Type::ShortTy || I.getType() == Type::IntTy ||
I.getType() == Type::LongTy)) {
unsigned DestReg = getReg(User);
static const unsigned Opcode[] = {
0/*BYTE*/, X86::FILD16m, X86::FILD32m, 0/*FP*/, X86::FILD64m
};
unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0;
getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp);
addFullAddress(BuildMI(BB, Opcode[Class], 5, DestReg),
BaseReg, Scale, IndexReg, Disp);
return;
} else {
User = 0;
}
break;
case Instruction::Add:
case Instruction::Sub:
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
if (Class == cLong) User = 0;
break;
case Instruction::Mul:
case Instruction::Div:
if (Class == cFP)
break; // Folding only implemented for floating point.
// fall through.
if (Class == cFP) User = 0;
break; // Folding only implemented for floating point.
default: User = 0; break;
}
@ -2771,11 +2791,19 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
MachineBasicBlock::iterator IP,
Value *Src, const Type *DestTy,
unsigned DestReg) {
unsigned SrcReg = getReg(Src, BB, IP);
const Type *SrcTy = Src->getType();
unsigned SrcClass = getClassB(SrcTy);
unsigned DestClass = getClassB(DestTy);
// If this cast converts a load from a short,int, or long integer to a FP
// value, we will have folded this cast away.
if (DestClass == cFP && isa<LoadInst>(Src) &&
(Src->getType() == Type::ShortTy || Src->getType() == Type::IntTy ||
Src->getType() == Type::LongTy))
return;
unsigned SrcReg = getReg(Src, BB, IP);
// Implement casts to bool by using compare on the operand followed by set if
// not zero on the result.
if (DestTy == Type::BoolTy) {

View File

@ -2621,20 +2621,40 @@ void ISel::visitLoadInst(LoadInst &I) {
// instruction, like add. If so, we don't want to emit it. Wouldn't a real
// pattern matching instruction selector be nice?
unsigned Class = getClassB(I.getType());
if (I.hasOneUse() && Class != cLong) {
if (I.hasOneUse()) {
Instruction *User = cast<Instruction>(I.use_back());
switch (User->getOpcode()) {
case Instruction::Cast:
// If this is a cast from a signed-integer type to a floating point type,
// fold the cast here.
if (getClass(User->getType()) == cFP &&
(I.getType() == Type::ShortTy || I.getType() == Type::IntTy ||
I.getType() == Type::LongTy)) {
unsigned DestReg = getReg(User);
static const unsigned Opcode[] = {
0/*BYTE*/, X86::FILD16m, X86::FILD32m, 0/*FP*/, X86::FILD64m
};
unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0;
getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp);
addFullAddress(BuildMI(BB, Opcode[Class], 5, DestReg),
BaseReg, Scale, IndexReg, Disp);
return;
} else {
User = 0;
}
break;
case Instruction::Add:
case Instruction::Sub:
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
if (Class == cLong) User = 0;
break;
case Instruction::Mul:
case Instruction::Div:
if (Class == cFP)
break; // Folding only implemented for floating point.
// fall through.
if (Class == cFP) User = 0;
break; // Folding only implemented for floating point.
default: User = 0; break;
}
@ -2771,11 +2791,19 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
MachineBasicBlock::iterator IP,
Value *Src, const Type *DestTy,
unsigned DestReg) {
unsigned SrcReg = getReg(Src, BB, IP);
const Type *SrcTy = Src->getType();
unsigned SrcClass = getClassB(SrcTy);
unsigned DestClass = getClassB(DestTy);
// If this cast converts a load from a short,int, or long integer to a FP
// value, we will have folded this cast away.
if (DestClass == cFP && isa<LoadInst>(Src) &&
(Src->getType() == Type::ShortTy || Src->getType() == Type::IntTy ||
Src->getType() == Type::LongTy))
return;
unsigned SrcReg = getReg(Src, BB, IP);
// Implement casts to bool by using compare on the operand followed by set if
// not zero on the result.
if (DestTy == Type::BoolTy) {