diff options
author | Chris Lattner <sabre@nondot.org> | 2004-04-11 23:21:26 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-04-11 23:21:26 +0000 |
commit | feac3e18aa861a4dd1ba0e0d6222805821b6bc1b (patch) | |
tree | e99f8686746486d1f2270c92cac321c0ee4955d1 /lib | |
parent | bb4d6c59c3bf3d0a5a8b8ac3f67f40e32e5d8b95 (diff) | |
download | external_llvm-feac3e18aa861a4dd1ba0e0d6222805821b6bc1b.zip external_llvm-feac3e18aa861a4dd1ba0e0d6222805821b6bc1b.tar.gz external_llvm-feac3e18aa861a4dd1ba0e0d6222805821b6bc1b.tar.bz2 |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/X86/InstSelectSimple.cpp | 38 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelSimple.cpp | 38 |
2 files changed, 66 insertions, 10 deletions
diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp index 4d06f0b..6584981 100644 --- a/lib/Target/X86/InstSelectSimple.cpp +++ b/lib/Target/X86/InstSelectSimple.cpp @@ -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) { diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp index 4d06f0b..6584981 100644 --- a/lib/Target/X86/X86ISelSimple.cpp +++ b/lib/Target/X86/X86ISelSimple.cpp @@ -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) { |