| //===-- PTXFPRoundingModePass.cpp - Assign rounding modes pass ------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines a machine function pass that sets appropriate FP rounding |
| // modes for all relevant instructions. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #define DEBUG_TYPE "ptx-fp-rounding-mode" |
| |
| #include "PTX.h" |
| #include "PTXTargetMachine.h" |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/CodeGen/MachineFunctionPass.h" |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| // NOTE: PTXFPRoundingModePass should be executed just before emission. |
| |
| namespace llvm { |
| /// PTXFPRoundingModePass - Pass to assign appropriate FP rounding modes to |
| /// all FP instructions. Essentially, this pass just looks for all FP |
| /// instructions that have a rounding mode set to RndDefault, and sets an |
| /// appropriate rounding mode based on the target device. |
| /// |
| class PTXFPRoundingModePass : public MachineFunctionPass { |
| private: |
| static char ID; |
| |
| typedef std::pair<unsigned, unsigned> RndModeDesc; |
| |
| PTXTargetMachine& TargetMachine; |
| DenseMap<unsigned, RndModeDesc> Instrs; |
| |
| public: |
| PTXFPRoundingModePass(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel) |
| : MachineFunctionPass(ID), |
| TargetMachine(TM) { |
| initializeMap(); |
| } |
| |
| virtual bool runOnMachineFunction(MachineFunction &MF); |
| |
| virtual const char *getPassName() const { |
| return "PTX FP Rounding Mode Pass"; |
| } |
| |
| private: |
| |
| void initializeMap(); |
| void processInstruction(MachineInstr &MI); |
| }; // class PTXFPRoundingModePass |
| } // namespace llvm |
| |
| using namespace llvm; |
| |
| char PTXFPRoundingModePass::ID = 0; |
| |
| bool PTXFPRoundingModePass::runOnMachineFunction(MachineFunction &MF) { |
| // Look at each basic block |
| for (MachineFunction::iterator bbi = MF.begin(), bbe = MF.end(); bbi != bbe; |
| ++bbi) { |
| MachineBasicBlock &MBB = *bbi; |
| // Look at each instruction |
| for (MachineBasicBlock::iterator ii = MBB.begin(), ie = MBB.end(); |
| ii != ie; ++ii) { |
| MachineInstr &MI = *ii; |
| processInstruction(MI); |
| } |
| } |
| return false; |
| } |
| |
| void PTXFPRoundingModePass::initializeMap() { |
| using namespace PTXRoundingMode; |
| const PTXSubtarget& ST = TargetMachine.getSubtarget<PTXSubtarget>(); |
| |
| // Build a map of default rounding mode for all instructions that need a |
| // rounding mode. |
| Instrs[PTX::FADDrr32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FADDri32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FADDrr64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FADDri64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FSUBrr32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FSUBri32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FSUBrr64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FSUBri64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FMULrr32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FMULri32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FMULrr64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FMULri64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| |
| Instrs[PTX::FNEGrr32] = std::make_pair(1U, (unsigned)RndNone); |
| Instrs[PTX::FNEGri32] = std::make_pair(1U, (unsigned)RndNone); |
| Instrs[PTX::FNEGrr64] = std::make_pair(1U, (unsigned)RndNone); |
| Instrs[PTX::FNEGri64] = std::make_pair(1U, (unsigned)RndNone); |
| |
| unsigned FDivRndMode = ST.fdivNeedsRoundingMode() ? RndNearestEven : RndNone; |
| Instrs[PTX::FDIVrr32] = std::make_pair(1U, FDivRndMode); |
| Instrs[PTX::FDIVri32] = std::make_pair(1U, FDivRndMode); |
| Instrs[PTX::FDIVrr64] = std::make_pair(1U, FDivRndMode); |
| Instrs[PTX::FDIVri64] = std::make_pair(1U, FDivRndMode); |
| |
| unsigned FMADRndMode = ST.fmadNeedsRoundingMode() ? RndNearestEven : RndNone; |
| Instrs[PTX::FMADrrr32] = std::make_pair(1U, FMADRndMode); |
| Instrs[PTX::FMADrri32] = std::make_pair(1U, FMADRndMode); |
| Instrs[PTX::FMADrii32] = std::make_pair(1U, FMADRndMode); |
| Instrs[PTX::FMADrrr64] = std::make_pair(1U, FMADRndMode); |
| Instrs[PTX::FMADrri64] = std::make_pair(1U, FMADRndMode); |
| Instrs[PTX::FMADrii64] = std::make_pair(1U, FMADRndMode); |
| |
| Instrs[PTX::FSQRTrr32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FSQRTri32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FSQRTrr64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::FSQRTri64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| |
| Instrs[PTX::FSINrr32] = std::make_pair(1U, (unsigned)RndApprox); |
| Instrs[PTX::FSINri32] = std::make_pair(1U, (unsigned)RndApprox); |
| Instrs[PTX::FSINrr64] = std::make_pair(1U, (unsigned)RndApprox); |
| Instrs[PTX::FSINri64] = std::make_pair(1U, (unsigned)RndApprox); |
| Instrs[PTX::FCOSrr32] = std::make_pair(1U, (unsigned)RndApprox); |
| Instrs[PTX::FCOSri32] = std::make_pair(1U, (unsigned)RndApprox); |
| Instrs[PTX::FCOSrr64] = std::make_pair(1U, (unsigned)RndApprox); |
| Instrs[PTX::FCOSri64] = std::make_pair(1U, (unsigned)RndApprox); |
| |
| Instrs[PTX::CVTu16f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTs16f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTu16f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTs16f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTu32f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTs32f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTu32f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTs32f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTu64f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTs64f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTu64f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| Instrs[PTX::CVTs64f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt); |
| |
| Instrs[PTX::CVTf32u16] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf32s16] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf32u32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf32s32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf32u64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf32s64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf32f64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf64u16] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf64s16] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf64u32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf64s32] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf64u64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| Instrs[PTX::CVTf64s64] = std::make_pair(1U, (unsigned)RndNearestEven); |
| } |
| |
| void PTXFPRoundingModePass::processInstruction(MachineInstr &MI) { |
| // Is this an instruction that needs a rounding mode? |
| if (Instrs.count(MI.getOpcode())) { |
| const RndModeDesc &Desc = Instrs[MI.getOpcode()]; |
| // Get the rounding mode operand |
| MachineOperand &Op = MI.getOperand(Desc.first); |
| // Update the rounding mode if needed |
| if (Op.getImm() == PTXRoundingMode::RndDefault) { |
| Op.setImm(Desc.second); |
| } |
| } |
| } |
| |
| FunctionPass *llvm::createPTXFPRoundingModePass(PTXTargetMachine &TM, |
| CodeGenOpt::Level OptLevel) { |
| return new PTXFPRoundingModePass(TM, OptLevel); |
| } |
| |