]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===- NVPTXInstrInfo.cpp - NVPTX Instruction Information -----------------===// |
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 contains the NVPTX implementation of the TargetInstrInfo class. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | #include "NVPTX.h" | |
15 | #include "NVPTXInstrInfo.h" | |
16 | #include "NVPTXTargetMachine.h" | |
223e47cc LB |
17 | #include "llvm/ADT/STLExtras.h" |
18 | #include "llvm/CodeGen/MachineFunction.h" | |
19 | #include "llvm/CodeGen/MachineInstrBuilder.h" | |
20 | #include "llvm/CodeGen/MachineRegisterInfo.h" | |
85aaf69f | 21 | #include "llvm/IR/Function.h" |
223e47cc LB |
22 | |
23 | using namespace llvm; | |
24 | ||
1a4d82fc JJ |
25 | #define GET_INSTRINFO_CTOR_DTOR |
26 | #include "NVPTXGenInstrInfo.inc" | |
27 | ||
28 | // Pin the vtable to this file. | |
29 | void NVPTXInstrInfo::anchor() {} | |
30 | ||
223e47cc | 31 | // FIXME: Add the subtarget support on this constructor. |
1a4d82fc JJ |
32 | NVPTXInstrInfo::NVPTXInstrInfo(NVPTXSubtarget &STI) |
33 | : NVPTXGenInstrInfo(), RegInfo(STI) {} | |
34 | ||
35 | void NVPTXInstrInfo::copyPhysReg( | |
36 | MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, | |
37 | unsigned DestReg, unsigned SrcReg, bool KillSrc) const { | |
38 | const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); | |
39 | const TargetRegisterClass *DestRC = MRI.getRegClass(DestReg); | |
40 | const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg); | |
41 | ||
42 | if (DestRC != SrcRC) | |
43 | report_fatal_error("Attempted to created cross-class register copy"); | |
44 | ||
45 | if (DestRC == &NVPTX::Int32RegsRegClass) | |
223e47cc | 46 | BuildMI(MBB, I, DL, get(NVPTX::IMOV32rr), DestReg) |
1a4d82fc JJ |
47 | .addReg(SrcReg, getKillRegState(KillSrc)); |
48 | else if (DestRC == &NVPTX::Int1RegsRegClass) | |
223e47cc | 49 | BuildMI(MBB, I, DL, get(NVPTX::IMOV1rr), DestReg) |
1a4d82fc JJ |
50 | .addReg(SrcReg, getKillRegState(KillSrc)); |
51 | else if (DestRC == &NVPTX::Float32RegsRegClass) | |
223e47cc | 52 | BuildMI(MBB, I, DL, get(NVPTX::FMOV32rr), DestReg) |
1a4d82fc JJ |
53 | .addReg(SrcReg, getKillRegState(KillSrc)); |
54 | else if (DestRC == &NVPTX::Int16RegsRegClass) | |
223e47cc | 55 | BuildMI(MBB, I, DL, get(NVPTX::IMOV16rr), DestReg) |
1a4d82fc JJ |
56 | .addReg(SrcReg, getKillRegState(KillSrc)); |
57 | else if (DestRC == &NVPTX::Int64RegsRegClass) | |
223e47cc | 58 | BuildMI(MBB, I, DL, get(NVPTX::IMOV64rr), DestReg) |
1a4d82fc JJ |
59 | .addReg(SrcReg, getKillRegState(KillSrc)); |
60 | else if (DestRC == &NVPTX::Float64RegsRegClass) | |
223e47cc | 61 | BuildMI(MBB, I, DL, get(NVPTX::FMOV64rr), DestReg) |
1a4d82fc | 62 | .addReg(SrcReg, getKillRegState(KillSrc)); |
223e47cc | 63 | else { |
1a4d82fc | 64 | llvm_unreachable("Bad register copy"); |
223e47cc LB |
65 | } |
66 | } | |
67 | ||
1a4d82fc | 68 | bool NVPTXInstrInfo::isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, |
223e47cc LB |
69 | unsigned &DestReg) const { |
70 | // Look for the appropriate part of TSFlags | |
71 | bool isMove = false; | |
72 | ||
1a4d82fc JJ |
73 | unsigned TSFlags = |
74 | (MI.getDesc().TSFlags & NVPTX::SimpleMoveMask) >> NVPTX::SimpleMoveShift; | |
223e47cc LB |
75 | isMove = (TSFlags == 1); |
76 | ||
77 | if (isMove) { | |
78 | MachineOperand dest = MI.getOperand(0); | |
79 | MachineOperand src = MI.getOperand(1); | |
80 | assert(dest.isReg() && "dest of a movrr is not a reg"); | |
81 | assert(src.isReg() && "src of a movrr is not a reg"); | |
82 | ||
83 | SrcReg = src.getReg(); | |
84 | DestReg = dest.getReg(); | |
85 | return true; | |
86 | } | |
87 | ||
88 | return false; | |
89 | } | |
90 | ||
1a4d82fc | 91 | bool NVPTXInstrInfo::isReadSpecialReg(MachineInstr &MI) const { |
223e47cc | 92 | switch (MI.getOpcode()) { |
1a4d82fc JJ |
93 | default: |
94 | return false; | |
223e47cc LB |
95 | case NVPTX::INT_PTX_SREG_NTID_X: |
96 | case NVPTX::INT_PTX_SREG_NTID_Y: | |
97 | case NVPTX::INT_PTX_SREG_NTID_Z: | |
98 | case NVPTX::INT_PTX_SREG_TID_X: | |
99 | case NVPTX::INT_PTX_SREG_TID_Y: | |
100 | case NVPTX::INT_PTX_SREG_TID_Z: | |
101 | case NVPTX::INT_PTX_SREG_CTAID_X: | |
102 | case NVPTX::INT_PTX_SREG_CTAID_Y: | |
103 | case NVPTX::INT_PTX_SREG_CTAID_Z: | |
104 | case NVPTX::INT_PTX_SREG_NCTAID_X: | |
105 | case NVPTX::INT_PTX_SREG_NCTAID_Y: | |
106 | case NVPTX::INT_PTX_SREG_NCTAID_Z: | |
107 | case NVPTX::INT_PTX_SREG_WARPSIZE: | |
108 | return true; | |
109 | } | |
110 | } | |
111 | ||
223e47cc LB |
112 | bool NVPTXInstrInfo::isLoadInstr(const MachineInstr &MI, |
113 | unsigned &AddrSpace) const { | |
114 | bool isLoad = false; | |
1a4d82fc JJ |
115 | unsigned TSFlags = |
116 | (MI.getDesc().TSFlags & NVPTX::isLoadMask) >> NVPTX::isLoadShift; | |
223e47cc LB |
117 | isLoad = (TSFlags == 1); |
118 | if (isLoad) | |
119 | AddrSpace = getLdStCodeAddrSpace(MI); | |
120 | return isLoad; | |
121 | } | |
122 | ||
123 | bool NVPTXInstrInfo::isStoreInstr(const MachineInstr &MI, | |
124 | unsigned &AddrSpace) const { | |
125 | bool isStore = false; | |
1a4d82fc JJ |
126 | unsigned TSFlags = |
127 | (MI.getDesc().TSFlags & NVPTX::isStoreMask) >> NVPTX::isStoreShift; | |
223e47cc LB |
128 | isStore = (TSFlags == 1); |
129 | if (isStore) | |
130 | AddrSpace = getLdStCodeAddrSpace(MI); | |
131 | return isStore; | |
132 | } | |
133 | ||
223e47cc LB |
134 | bool NVPTXInstrInfo::CanTailMerge(const MachineInstr *MI) const { |
135 | unsigned addrspace = 0; | |
136 | if (MI->getOpcode() == NVPTX::INT_CUDA_SYNCTHREADS) | |
137 | return false; | |
138 | if (isLoadInstr(*MI, addrspace)) | |
139 | if (addrspace == NVPTX::PTXLdStInstCode::SHARED) | |
140 | return false; | |
141 | if (isStoreInstr(*MI, addrspace)) | |
142 | if (addrspace == NVPTX::PTXLdStInstCode::SHARED) | |
143 | return false; | |
144 | return true; | |
145 | } | |
146 | ||
223e47cc LB |
147 | /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning |
148 | /// true if it cannot be understood (e.g. it's a switch dispatch or isn't | |
149 | /// implemented for a target). Upon success, this returns false and returns | |
150 | /// with the following information in various cases: | |
151 | /// | |
152 | /// 1. If this block ends with no branches (it just falls through to its succ) | |
153 | /// just return false, leaving TBB/FBB null. | |
154 | /// 2. If this block ends with only an unconditional branch, it sets TBB to be | |
155 | /// the destination block. | |
156 | /// 3. If this block ends with an conditional branch and it falls through to | |
157 | /// an successor block, it sets TBB to be the branch destination block and a | |
158 | /// list of operands that evaluate the condition. These | |
159 | /// operands can be passed to other TargetInstrInfo methods to create new | |
160 | /// branches. | |
161 | /// 4. If this block ends with an conditional branch and an unconditional | |
162 | /// block, it returns the 'true' destination in TBB, the 'false' destination | |
163 | /// in FBB, and a list of operands that evaluate the condition. These | |
164 | /// operands can be passed to other TargetInstrInfo methods to create new | |
165 | /// branches. | |
166 | /// | |
167 | /// Note that RemoveBranch and InsertBranch must be implemented to support | |
168 | /// cases where this method returns success. | |
169 | /// | |
1a4d82fc JJ |
170 | bool NVPTXInstrInfo::AnalyzeBranch( |
171 | MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, | |
172 | SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { | |
223e47cc LB |
173 | // If the block has no terminators, it just falls into the block after it. |
174 | MachineBasicBlock::iterator I = MBB.end(); | |
175 | if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) | |
176 | return false; | |
177 | ||
178 | // Get the last instruction in the block. | |
179 | MachineInstr *LastInst = I; | |
180 | ||
181 | // If there is only one terminator instruction, process it. | |
182 | if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { | |
183 | if (LastInst->getOpcode() == NVPTX::GOTO) { | |
184 | TBB = LastInst->getOperand(0).getMBB(); | |
185 | return false; | |
186 | } else if (LastInst->getOpcode() == NVPTX::CBranch) { | |
187 | // Block ends with fall-through condbranch. | |
188 | TBB = LastInst->getOperand(1).getMBB(); | |
189 | Cond.push_back(LastInst->getOperand(0)); | |
190 | return false; | |
191 | } | |
192 | // Otherwise, don't know what this is. | |
193 | return true; | |
194 | } | |
195 | ||
196 | // Get the instruction before it if it's a terminator. | |
197 | MachineInstr *SecondLastInst = I; | |
198 | ||
199 | // If there are three terminators, we don't know what sort of block this is. | |
1a4d82fc | 200 | if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I)) |
223e47cc LB |
201 | return true; |
202 | ||
203 | // If the block ends with NVPTX::GOTO and NVPTX:CBranch, handle it. | |
204 | if (SecondLastInst->getOpcode() == NVPTX::CBranch && | |
205 | LastInst->getOpcode() == NVPTX::GOTO) { | |
1a4d82fc | 206 | TBB = SecondLastInst->getOperand(1).getMBB(); |
223e47cc LB |
207 | Cond.push_back(SecondLastInst->getOperand(0)); |
208 | FBB = LastInst->getOperand(0).getMBB(); | |
209 | return false; | |
210 | } | |
211 | ||
212 | // If the block ends with two NVPTX:GOTOs, handle it. The second one is not | |
213 | // executed, so remove it. | |
214 | if (SecondLastInst->getOpcode() == NVPTX::GOTO && | |
215 | LastInst->getOpcode() == NVPTX::GOTO) { | |
216 | TBB = SecondLastInst->getOperand(0).getMBB(); | |
217 | I = LastInst; | |
218 | if (AllowModify) | |
219 | I->eraseFromParent(); | |
220 | return false; | |
221 | } | |
222 | ||
223 | // Otherwise, can't handle this. | |
224 | return true; | |
225 | } | |
226 | ||
227 | unsigned NVPTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { | |
228 | MachineBasicBlock::iterator I = MBB.end(); | |
1a4d82fc JJ |
229 | if (I == MBB.begin()) |
230 | return 0; | |
223e47cc LB |
231 | --I; |
232 | if (I->getOpcode() != NVPTX::GOTO && I->getOpcode() != NVPTX::CBranch) | |
233 | return 0; | |
234 | ||
235 | // Remove the branch. | |
236 | I->eraseFromParent(); | |
237 | ||
238 | I = MBB.end(); | |
239 | ||
1a4d82fc JJ |
240 | if (I == MBB.begin()) |
241 | return 1; | |
223e47cc LB |
242 | --I; |
243 | if (I->getOpcode() != NVPTX::CBranch) | |
244 | return 1; | |
245 | ||
246 | // Remove the branch. | |
247 | I->eraseFromParent(); | |
248 | return 2; | |
249 | } | |
250 | ||
1a4d82fc JJ |
251 | unsigned NVPTXInstrInfo::InsertBranch( |
252 | MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, | |
253 | const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const { | |
223e47cc LB |
254 | // Shouldn't be a fall through. |
255 | assert(TBB && "InsertBranch must not be told to insert a fallthrough"); | |
256 | assert((Cond.size() == 1 || Cond.size() == 0) && | |
257 | "NVPTX branch conditions have two components!"); | |
258 | ||
259 | // One-way branch. | |
1a4d82fc JJ |
260 | if (!FBB) { |
261 | if (Cond.empty()) // Unconditional branch | |
223e47cc | 262 | BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(TBB); |
1a4d82fc JJ |
263 | else // Conditional branch |
264 | BuildMI(&MBB, DL, get(NVPTX::CBranch)).addReg(Cond[0].getReg()) | |
265 | .addMBB(TBB); | |
223e47cc LB |
266 | return 1; |
267 | } | |
268 | ||
269 | // Two-way Conditional Branch. | |
1a4d82fc | 270 | BuildMI(&MBB, DL, get(NVPTX::CBranch)).addReg(Cond[0].getReg()).addMBB(TBB); |
223e47cc LB |
271 | BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(FBB); |
272 | return 2; | |
273 | } |