xref: /aosp_15_r20/external/llvm/lib/Target/NVPTX/NVPTXInstrInfo.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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