]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/lib/Target/PTX/PTXFPRoundingModePass.cpp
Partial MFC of r234508 (by adrian):
[FreeBSD/stable/9.git] / contrib / llvm / lib / Target / PTX / PTXFPRoundingModePass.cpp
1 //===-- PTXFPRoundingModePass.cpp - Assign rounding modes pass ------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a machine function pass that sets appropriate FP rounding
11 // modes for all relevant instructions.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "ptx-fp-rounding-mode"
16
17 #include "PTX.h"
18 #include "PTXTargetMachine.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/raw_ostream.h"
25
26 using namespace llvm;
27
28 // NOTE: PTXFPRoundingModePass should be executed just before emission.
29
30 namespace {
31   /// PTXFPRoundingModePass - Pass to assign appropriate FP rounding modes to
32   /// all FP instructions. Essentially, this pass just looks for all FP
33   /// instructions that have a rounding mode set to RndDefault, and sets an
34   /// appropriate rounding mode based on the target device.
35   ///
36   class PTXFPRoundingModePass : public MachineFunctionPass {
37     private:
38       static char ID;
39
40       typedef std::pair<unsigned, unsigned> RndModeDesc;
41
42       PTXTargetMachine& TargetMachine;
43       DenseMap<unsigned, RndModeDesc> Instrs;
44
45     public:
46       PTXFPRoundingModePass(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel)
47         : MachineFunctionPass(ID),
48           TargetMachine(TM) {
49         initializeMap();
50       }
51
52       virtual bool runOnMachineFunction(MachineFunction &MF);
53
54       virtual const char *getPassName() const {
55         return "PTX FP Rounding Mode Pass";
56       }
57
58     private:
59
60       void initializeMap();
61       void processInstruction(MachineInstr &MI);
62   }; // class PTXFPRoundingModePass
63 } // end anonymous namespace
64
65 using namespace llvm;
66
67 char PTXFPRoundingModePass::ID = 0;
68
69 bool PTXFPRoundingModePass::runOnMachineFunction(MachineFunction &MF) {
70   // Look at each basic block
71   for (MachineFunction::iterator bbi = MF.begin(), bbe = MF.end(); bbi != bbe;
72        ++bbi) {
73     MachineBasicBlock &MBB = *bbi;
74     // Look at each instruction
75     for (MachineBasicBlock::iterator ii = MBB.begin(), ie = MBB.end();
76          ii != ie; ++ii) {
77       MachineInstr &MI = *ii;
78       processInstruction(MI);
79     }
80   }
81   return false;
82 }
83
84 void PTXFPRoundingModePass::initializeMap() {
85   using namespace PTXRoundingMode;
86   const PTXSubtarget& ST = TargetMachine.getSubtarget<PTXSubtarget>();
87
88   // Build a map of default rounding mode for all instructions that need a
89   // rounding mode.
90   Instrs[PTX::FADDrr32] = std::make_pair(1U, (unsigned)RndNearestEven);
91   Instrs[PTX::FADDri32] = std::make_pair(1U, (unsigned)RndNearestEven);
92   Instrs[PTX::FADDrr64] = std::make_pair(1U, (unsigned)RndNearestEven);
93   Instrs[PTX::FADDri64] = std::make_pair(1U, (unsigned)RndNearestEven);
94   Instrs[PTX::FSUBrr32] = std::make_pair(1U, (unsigned)RndNearestEven);
95   Instrs[PTX::FSUBri32] = std::make_pair(1U, (unsigned)RndNearestEven);
96   Instrs[PTX::FSUBrr64] = std::make_pair(1U, (unsigned)RndNearestEven);
97   Instrs[PTX::FSUBri64] = std::make_pair(1U, (unsigned)RndNearestEven);
98   Instrs[PTX::FMULrr32] = std::make_pair(1U, (unsigned)RndNearestEven);
99   Instrs[PTX::FMULri32] = std::make_pair(1U, (unsigned)RndNearestEven);
100   Instrs[PTX::FMULrr64] = std::make_pair(1U, (unsigned)RndNearestEven);
101   Instrs[PTX::FMULri64] = std::make_pair(1U, (unsigned)RndNearestEven);
102
103   Instrs[PTX::FNEGrr32] = std::make_pair(1U, (unsigned)RndNone);
104   Instrs[PTX::FNEGri32] = std::make_pair(1U, (unsigned)RndNone);
105   Instrs[PTX::FNEGrr64] = std::make_pair(1U, (unsigned)RndNone);
106   Instrs[PTX::FNEGri64] = std::make_pair(1U, (unsigned)RndNone);
107
108   unsigned FDivRndMode = ST.fdivNeedsRoundingMode() ? RndNearestEven : RndNone;
109   Instrs[PTX::FDIVrr32] = std::make_pair(1U, FDivRndMode);
110   Instrs[PTX::FDIVri32] = std::make_pair(1U, FDivRndMode);
111   Instrs[PTX::FDIVrr64] = std::make_pair(1U, FDivRndMode);
112   Instrs[PTX::FDIVri64] = std::make_pair(1U, FDivRndMode);
113
114   unsigned FMADRndMode = ST.fmadNeedsRoundingMode() ? RndNearestEven : RndNone;
115   Instrs[PTX::FMADrrr32] = std::make_pair(1U, FMADRndMode);
116   Instrs[PTX::FMADrri32] = std::make_pair(1U, FMADRndMode);
117   Instrs[PTX::FMADrii32] = std::make_pair(1U, FMADRndMode);
118   Instrs[PTX::FMADrrr64] = std::make_pair(1U, FMADRndMode);
119   Instrs[PTX::FMADrri64] = std::make_pair(1U, FMADRndMode);
120   Instrs[PTX::FMADrii64] = std::make_pair(1U, FMADRndMode);
121
122   Instrs[PTX::FSQRTrr32] = std::make_pair(1U, (unsigned)RndNearestEven);
123   Instrs[PTX::FSQRTri32] = std::make_pair(1U, (unsigned)RndNearestEven);
124   Instrs[PTX::FSQRTrr64] = std::make_pair(1U, (unsigned)RndNearestEven);
125   Instrs[PTX::FSQRTri64] = std::make_pair(1U, (unsigned)RndNearestEven);
126
127   Instrs[PTX::FSINrr32] = std::make_pair(1U, (unsigned)RndApprox);
128   Instrs[PTX::FSINri32] = std::make_pair(1U, (unsigned)RndApprox);
129   Instrs[PTX::FSINrr64] = std::make_pair(1U, (unsigned)RndApprox);
130   Instrs[PTX::FSINri64] = std::make_pair(1U, (unsigned)RndApprox);
131   Instrs[PTX::FCOSrr32] = std::make_pair(1U, (unsigned)RndApprox);
132   Instrs[PTX::FCOSri32] = std::make_pair(1U, (unsigned)RndApprox);
133   Instrs[PTX::FCOSrr64] = std::make_pair(1U, (unsigned)RndApprox);
134   Instrs[PTX::FCOSri64] = std::make_pair(1U, (unsigned)RndApprox);
135
136   Instrs[PTX::CVTu16f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
137   Instrs[PTX::CVTs16f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
138   Instrs[PTX::CVTu16f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
139   Instrs[PTX::CVTs16f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
140   Instrs[PTX::CVTu32f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
141   Instrs[PTX::CVTs32f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
142   Instrs[PTX::CVTu32f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
143   Instrs[PTX::CVTs32f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
144   Instrs[PTX::CVTu64f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
145   Instrs[PTX::CVTs64f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
146   Instrs[PTX::CVTu64f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
147   Instrs[PTX::CVTs64f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
148
149   Instrs[PTX::CVTf32u16] = std::make_pair(1U, (unsigned)RndNearestEven);
150   Instrs[PTX::CVTf32s16] = std::make_pair(1U, (unsigned)RndNearestEven);
151   Instrs[PTX::CVTf32u32] = std::make_pair(1U, (unsigned)RndNearestEven);
152   Instrs[PTX::CVTf32s32] = std::make_pair(1U, (unsigned)RndNearestEven);
153   Instrs[PTX::CVTf32u64] = std::make_pair(1U, (unsigned)RndNearestEven);
154   Instrs[PTX::CVTf32s64] = std::make_pair(1U, (unsigned)RndNearestEven);
155   Instrs[PTX::CVTf32f64] = std::make_pair(1U, (unsigned)RndNearestEven);
156   Instrs[PTX::CVTf64u16] = std::make_pair(1U, (unsigned)RndNearestEven);
157   Instrs[PTX::CVTf64s16] = std::make_pair(1U, (unsigned)RndNearestEven);
158   Instrs[PTX::CVTf64u32] = std::make_pair(1U, (unsigned)RndNearestEven);
159   Instrs[PTX::CVTf64s32] = std::make_pair(1U, (unsigned)RndNearestEven);
160   Instrs[PTX::CVTf64u64] = std::make_pair(1U, (unsigned)RndNearestEven);
161   Instrs[PTX::CVTf64s64] = std::make_pair(1U, (unsigned)RndNearestEven);
162 }
163
164 void PTXFPRoundingModePass::processInstruction(MachineInstr &MI) {
165   // Is this an instruction that needs a rounding mode?
166   if (Instrs.count(MI.getOpcode())) {
167     const RndModeDesc &Desc = Instrs[MI.getOpcode()];
168     // Get the rounding mode operand
169     MachineOperand &Op = MI.getOperand(Desc.first);
170     // Update the rounding mode if needed
171     if (Op.getImm() == PTXRoundingMode::RndDefault) {
172       Op.setImm(Desc.second);
173     }
174   }
175 }
176
177 FunctionPass *llvm::createPTXFPRoundingModePass(PTXTargetMachine &TM,
178                                                 CodeGenOpt::Level OptLevel) {
179   return new PTXFPRoundingModePass(TM, OptLevel);
180 }
181