LLVM 20.0.0git
NVPTXInstrInfo.cpp
Go to the documentation of this file.
1//===- NVPTXInstrInfo.cpp - NVPTX Instruction Information -----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the NVPTX implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "NVPTXInstrInfo.h"
14#include "NVPTX.h"
18
19using namespace llvm;
20
21#define GET_INSTRINFO_CTOR_DTOR
22#include "NVPTXGenInstrInfo.inc"
23
24// Pin the vtable to this file.
25void NVPTXInstrInfo::anchor() {}
26
28
31 const DebugLoc &DL, MCRegister DestReg,
32 MCRegister SrcReg, bool KillSrc,
33 bool RenamableDest, bool RenamableSrc) const {
35 const TargetRegisterClass *DestRC = MRI.getRegClass(DestReg);
36 const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
37
38 if (RegInfo.getRegSizeInBits(*DestRC) != RegInfo.getRegSizeInBits(*SrcRC))
39 report_fatal_error("Copy one register into another with a different width");
40
41 unsigned Op;
42 if (DestRC == &NVPTX::Int1RegsRegClass) {
43 Op = NVPTX::IMOV1rr;
44 } else if (DestRC == &NVPTX::Int16RegsRegClass) {
45 Op = NVPTX::IMOV16rr;
46 } else if (DestRC == &NVPTX::Int32RegsRegClass) {
47 Op = (SrcRC == &NVPTX::Int32RegsRegClass ? NVPTX::IMOV32rr
48 : NVPTX::BITCONVERT_32_F2I);
49 } else if (DestRC == &NVPTX::Int64RegsRegClass) {
50 Op = (SrcRC == &NVPTX::Int64RegsRegClass ? NVPTX::IMOV64rr
51 : NVPTX::BITCONVERT_64_F2I);
52 } else if (DestRC == &NVPTX::Int128RegsRegClass) {
53 Op = NVPTX::IMOV128rr;
54 } else if (DestRC == &NVPTX::Float32RegsRegClass) {
55 Op = (SrcRC == &NVPTX::Float32RegsRegClass ? NVPTX::FMOV32rr
56 : NVPTX::BITCONVERT_32_I2F);
57 } else if (DestRC == &NVPTX::Float64RegsRegClass) {
58 Op = (SrcRC == &NVPTX::Float64RegsRegClass ? NVPTX::FMOV64rr
59 : NVPTX::BITCONVERT_64_I2F);
60 } else {
61 llvm_unreachable("Bad register copy");
62 }
63 BuildMI(MBB, I, DL, get(Op), DestReg)
64 .addReg(SrcReg, getKillRegState(KillSrc));
65}
66
67/// analyzeBranch - Analyze the branching code at the end of MBB, returning
68/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
69/// implemented for a target). Upon success, this returns false and returns
70/// with the following information in various cases:
71///
72/// 1. If this block ends with no branches (it just falls through to its succ)
73/// just return false, leaving TBB/FBB null.
74/// 2. If this block ends with only an unconditional branch, it sets TBB to be
75/// the destination block.
76/// 3. If this block ends with an conditional branch and it falls through to
77/// an successor block, it sets TBB to be the branch destination block and a
78/// list of operands that evaluate the condition. These
79/// operands can be passed to other TargetInstrInfo methods to create new
80/// branches.
81/// 4. If this block ends with an conditional branch and an unconditional
82/// block, it returns the 'true' destination in TBB, the 'false' destination
83/// in FBB, and a list of operands that evaluate the condition. These
84/// operands can be passed to other TargetInstrInfo methods to create new
85/// branches.
86///
87/// Note that removeBranch and insertBranch must be implemented to support
88/// cases where this method returns success.
89///
94 bool AllowModify) const {
95 // If the block has no terminators, it just falls into the block after it.
97 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I))
98 return false;
99
100 // Get the last instruction in the block.
101 MachineInstr &LastInst = *I;
102
103 // If there is only one terminator instruction, process it.
104 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
105 if (LastInst.getOpcode() == NVPTX::GOTO) {
106 TBB = LastInst.getOperand(0).getMBB();
107 return false;
108 } else if (LastInst.getOpcode() == NVPTX::CBranch) {
109 // Block ends with fall-through condbranch.
110 TBB = LastInst.getOperand(1).getMBB();
111 Cond.push_back(LastInst.getOperand(0));
112 return false;
113 }
114 // Otherwise, don't know what this is.
115 return true;
116 }
117
118 // Get the instruction before it if it's a terminator.
119 MachineInstr &SecondLastInst = *I;
120
121 // If there are three terminators, we don't know what sort of block this is.
122 if (I != MBB.begin() && isUnpredicatedTerminator(*--I))
123 return true;
124
125 // If the block ends with NVPTX::GOTO and NVPTX:CBranch, handle it.
126 if (SecondLastInst.getOpcode() == NVPTX::CBranch &&
127 LastInst.getOpcode() == NVPTX::GOTO) {
128 TBB = SecondLastInst.getOperand(1).getMBB();
129 Cond.push_back(SecondLastInst.getOperand(0));
130 FBB = LastInst.getOperand(0).getMBB();
131 return false;
132 }
133
134 // If the block ends with two NVPTX:GOTOs, handle it. The second one is not
135 // executed, so remove it.
136 if (SecondLastInst.getOpcode() == NVPTX::GOTO &&
137 LastInst.getOpcode() == NVPTX::GOTO) {
138 TBB = SecondLastInst.getOperand(0).getMBB();
139 I = LastInst;
140 if (AllowModify)
141 I->eraseFromParent();
142 return false;
143 }
144
145 // Otherwise, can't handle this.
146 return true;
147}
148
150 int *BytesRemoved) const {
151 assert(!BytesRemoved && "code size not handled");
153 if (I == MBB.begin())
154 return 0;
155 --I;
156 if (I->getOpcode() != NVPTX::GOTO && I->getOpcode() != NVPTX::CBranch)
157 return 0;
158
159 // Remove the branch.
160 I->eraseFromParent();
161
162 I = MBB.end();
163
164 if (I == MBB.begin())
165 return 1;
166 --I;
167 if (I->getOpcode() != NVPTX::CBranch)
168 return 1;
169
170 // Remove the branch.
171 I->eraseFromParent();
172 return 2;
173}
174
179 const DebugLoc &DL,
180 int *BytesAdded) const {
181 assert(!BytesAdded && "code size not handled");
182
183 // Shouldn't be a fall through.
184 assert(TBB && "insertBranch must not be told to insert a fallthrough");
185 assert((Cond.size() == 1 || Cond.size() == 0) &&
186 "NVPTX branch conditions have two components!");
187
188 // One-way branch.
189 if (!FBB) {
190 if (Cond.empty()) // Unconditional branch
191 BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(TBB);
192 else // Conditional branch
193 BuildMI(&MBB, DL, get(NVPTX::CBranch)).add(Cond[0]).addMBB(TBB);
194 return 1;
195 }
196
197 // Two-way Conditional Branch.
198 BuildMI(&MBB, DL, get(NVPTX::CBranch)).add(Cond[0]).addMBB(TBB);
199 BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(FBB);
200 return 2;
201}
202
204 const MachineBasicBlock *MBB,
205 const MachineFunction &MF) const {
206 // Prevent the scheduler from reordering & splitting up MachineInstrs
207 // which must stick together (in initially set order) to
208 // comprise a valid PTX function call sequence.
209 switch (MI.getOpcode()) {
210 case NVPTX::CallUniPrintCallRetInst1:
211 case NVPTX::CallArgBeginInst:
212 case NVPTX::CallArgI32imm:
213 case NVPTX::CallArgParam:
214 case NVPTX::LastCallArgI32imm:
215 case NVPTX::LastCallArgParam:
216 case NVPTX::CallArgEndInst1:
217 return true;
218 }
219
221}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
This class represents an Operation in the Expression.
A debug info location.
Definition: DebugLoc.h:33
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:585
MachineBasicBlock * getMBB() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
analyzeBranch - Analyze the branching code at the end of MBB, returning true if it cannot be understo...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
virtual bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Test if the given instruction should be considered a scheduling boundary.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
unsigned getKillRegState(bool B)
DWARFExpression::Operation Op