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