From feac3e18aa861a4dd1ba0e0d6222805821b6bc1b Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 11 Apr 2004 23:21:26 +0000 Subject: [PATCH] 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 --- lib/Target/X86/InstSelectSimple.cpp | 38 +++++++++++++++++++++++++---- 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 4d06f0bba2d..6584981947a 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(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(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 4d06f0bba2d..6584981947a 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(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(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) {