From b160d1f9f7c39e00f103096afb69aca144ef5b6e Mon Sep 17 00:00:00 2001 From: Misha Brukman Date: Fri, 23 Jul 2004 20:32:59 +0000 Subject: [PATCH] Implement casting a floating point to 32-bit unsigned value git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15143 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPC32ISelSimple.cpp | 63 +++++++++++++++++++++++- lib/Target/PowerPC/PowerPCISelSimple.cpp | 63 +++++++++++++++++++++++- 2 files changed, 122 insertions(+), 4 deletions(-) diff --git a/lib/Target/PowerPC/PPC32ISelSimple.cpp b/lib/Target/PowerPC/PPC32ISelSimple.cpp index a28efc42b8e..83a6cc30e50 100644 --- a/lib/Target/PowerPC/PPC32ISelSimple.cpp +++ b/lib/Target/PowerPC/PPC32ISelSimple.cpp @@ -2672,8 +2672,67 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB, ValueFrameIdx, 4); } } else { - std::cerr << "ERROR: Cast fp-to-unsigned not implemented!\n"; - abort(); + unsigned Zero = getReg(ConstantFP::get(Type::DoubleTy, 0.0f)); + double maxInt = (1LL << 32) - 1; + unsigned MaxInt = getReg(ConstantFP::get(Type::DoubleTy, maxInt)); + double border = 1LL << 31; + unsigned Border = getReg(ConstantFP::get(Type::DoubleTy, border)); + unsigned UseZero = makeAnotherReg(Type::DoubleTy); + unsigned UseMaxInt = makeAnotherReg(Type::DoubleTy); + unsigned UseChoice = makeAnotherReg(Type::DoubleTy); + unsigned TmpReg = makeAnotherReg(Type::DoubleTy); + unsigned TmpReg2 = makeAnotherReg(Type::DoubleTy); + unsigned ConvReg = makeAnotherReg(Type::DoubleTy); + unsigned IntTmp = makeAnotherReg(Type::IntTy); + unsigned XorReg = makeAnotherReg(Type::IntTy); + int FrameIdx = + F->getFrameInfo()->CreateStackObject(SrcTy, TM.getTargetData()); + // Update machine-CFG edges + MachineBasicBlock *XorMBB = new MachineBasicBlock(BB->getBasicBlock()); + MachineBasicBlock *PhiMBB = new MachineBasicBlock(BB->getBasicBlock()); + MachineBasicBlock *OldMBB = BB; + ilist::iterator It = BB; ++It; + F->getBasicBlockList().insert(It, XorMBB); + F->getBasicBlockList().insert(It, PhiMBB); + BB->addSuccessor(XorMBB); + BB->addSuccessor(PhiMBB); + + // Convert from floating point to unsigned 32-bit value + // Use 0 if incoming value is < 0.0 + BuildMI(*BB, IP, PPC32::FSEL, 3, UseZero).addReg(SrcReg).addReg(SrcReg) + .addReg(Zero); + // Use 2**32 - 1 if incoming value is >= 2**32 + BuildMI(*BB, IP, PPC32::FSUB, 2, UseMaxInt).addReg(MaxInt).addReg(SrcReg); + BuildMI(*BB, IP, PPC32::FSEL, 3, UseChoice).addReg(UseMaxInt) + .addReg(UseZero).addReg(MaxInt); + // Subtract 2**31 + BuildMI(*BB, IP, PPC32::FSUB, 2, TmpReg).addReg(UseChoice).addReg(Border); + // Use difference if >= 2**31 + BuildMI(*BB, IP, PPC32::FCMPU, 2, PPC32::CR0).addReg(UseChoice) + .addReg(Border); + BuildMI(*BB, IP, PPC32::FSEL, 3, TmpReg2).addReg(TmpReg).addReg(TmpReg) + .addReg(UseChoice); + // Convert to integer + BuildMI(*BB, IP, PPC32::FCTIWZ, 1, ConvReg).addReg(TmpReg2); + addFrameReference(BuildMI(*BB, IP, PPC32::STFD, 3).addReg(ConvReg), + FrameIdx); + addFrameReference(BuildMI(*BB, IP, PPC32::LWZ, 2, IntTmp), + FrameIdx, 4); + BuildMI(*BB, IP, PPC32::BLT, 2).addReg(PPC32::CR0).addMBB(PhiMBB); + BuildMI(*BB, IP, PPC32::B, 1).addMBB(XorMBB); + + // XorMBB: + // add 2**31 if input was >= 2**31 + BB = XorMBB; + BuildMI(BB, PPC32::XORIS, 2, XorReg).addReg(IntTmp).addImm(0x8000); + BuildMI(BB, PPC32::B, 1).addMBB(PhiMBB); + XorMBB->addSuccessor(PhiMBB); + + // PhiMBB: + // DestReg = phi [ IntTmp, OldMBB ], [ XorReg, XorMBB ] + BB = PhiMBB; + BuildMI(BB, PPC32::PHI, 2, DestReg).addReg(IntTmp).addMBB(OldMBB) + .addReg(XorReg).addMBB(XorMBB); } return; } diff --git a/lib/Target/PowerPC/PowerPCISelSimple.cpp b/lib/Target/PowerPC/PowerPCISelSimple.cpp index a28efc42b8e..83a6cc30e50 100644 --- a/lib/Target/PowerPC/PowerPCISelSimple.cpp +++ b/lib/Target/PowerPC/PowerPCISelSimple.cpp @@ -2672,8 +2672,67 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB, ValueFrameIdx, 4); } } else { - std::cerr << "ERROR: Cast fp-to-unsigned not implemented!\n"; - abort(); + unsigned Zero = getReg(ConstantFP::get(Type::DoubleTy, 0.0f)); + double maxInt = (1LL << 32) - 1; + unsigned MaxInt = getReg(ConstantFP::get(Type::DoubleTy, maxInt)); + double border = 1LL << 31; + unsigned Border = getReg(ConstantFP::get(Type::DoubleTy, border)); + unsigned UseZero = makeAnotherReg(Type::DoubleTy); + unsigned UseMaxInt = makeAnotherReg(Type::DoubleTy); + unsigned UseChoice = makeAnotherReg(Type::DoubleTy); + unsigned TmpReg = makeAnotherReg(Type::DoubleTy); + unsigned TmpReg2 = makeAnotherReg(Type::DoubleTy); + unsigned ConvReg = makeAnotherReg(Type::DoubleTy); + unsigned IntTmp = makeAnotherReg(Type::IntTy); + unsigned XorReg = makeAnotherReg(Type::IntTy); + int FrameIdx = + F->getFrameInfo()->CreateStackObject(SrcTy, TM.getTargetData()); + // Update machine-CFG edges + MachineBasicBlock *XorMBB = new MachineBasicBlock(BB->getBasicBlock()); + MachineBasicBlock *PhiMBB = new MachineBasicBlock(BB->getBasicBlock()); + MachineBasicBlock *OldMBB = BB; + ilist::iterator It = BB; ++It; + F->getBasicBlockList().insert(It, XorMBB); + F->getBasicBlockList().insert(It, PhiMBB); + BB->addSuccessor(XorMBB); + BB->addSuccessor(PhiMBB); + + // Convert from floating point to unsigned 32-bit value + // Use 0 if incoming value is < 0.0 + BuildMI(*BB, IP, PPC32::FSEL, 3, UseZero).addReg(SrcReg).addReg(SrcReg) + .addReg(Zero); + // Use 2**32 - 1 if incoming value is >= 2**32 + BuildMI(*BB, IP, PPC32::FSUB, 2, UseMaxInt).addReg(MaxInt).addReg(SrcReg); + BuildMI(*BB, IP, PPC32::FSEL, 3, UseChoice).addReg(UseMaxInt) + .addReg(UseZero).addReg(MaxInt); + // Subtract 2**31 + BuildMI(*BB, IP, PPC32::FSUB, 2, TmpReg).addReg(UseChoice).addReg(Border); + // Use difference if >= 2**31 + BuildMI(*BB, IP, PPC32::FCMPU, 2, PPC32::CR0).addReg(UseChoice) + .addReg(Border); + BuildMI(*BB, IP, PPC32::FSEL, 3, TmpReg2).addReg(TmpReg).addReg(TmpReg) + .addReg(UseChoice); + // Convert to integer + BuildMI(*BB, IP, PPC32::FCTIWZ, 1, ConvReg).addReg(TmpReg2); + addFrameReference(BuildMI(*BB, IP, PPC32::STFD, 3).addReg(ConvReg), + FrameIdx); + addFrameReference(BuildMI(*BB, IP, PPC32::LWZ, 2, IntTmp), + FrameIdx, 4); + BuildMI(*BB, IP, PPC32::BLT, 2).addReg(PPC32::CR0).addMBB(PhiMBB); + BuildMI(*BB, IP, PPC32::B, 1).addMBB(XorMBB); + + // XorMBB: + // add 2**31 if input was >= 2**31 + BB = XorMBB; + BuildMI(BB, PPC32::XORIS, 2, XorReg).addReg(IntTmp).addImm(0x8000); + BuildMI(BB, PPC32::B, 1).addMBB(PhiMBB); + XorMBB->addSuccessor(PhiMBB); + + // PhiMBB: + // DestReg = phi [ IntTmp, OldMBB ], [ XorReg, XorMBB ] + BB = PhiMBB; + BuildMI(BB, PPC32::PHI, 2, DestReg).addReg(IntTmp).addMBB(OldMBB) + .addReg(XorReg).addMBB(XorMBB); } return; } -- 2.34.1