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" |
15 | #include "NVPTXTargetMachine.h" |
16 | #include "llvm/ADT/STLExtras.h" |
17 | #include "llvm/CodeGen/MachineFunction.h" |
18 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
19 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
20 | #include "llvm/IR/Function.h" |
21 | |
22 | using namespace llvm; |
23 | |
24 | #define GET_INSTRINFO_CTOR_DTOR |
25 | #include "NVPTXGenInstrInfo.inc" |
26 | |
27 | // Pin the vtable to this file. |
28 | void NVPTXInstrInfo::anchor() {} |
29 | |
30 | NVPTXInstrInfo::NVPTXInstrInfo() : RegInfo() {} |
31 | |
32 | void NVPTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB, |
33 | MachineBasicBlock::iterator I, |
34 | const DebugLoc &DL, MCRegister DestReg, |
35 | MCRegister SrcReg, bool KillSrc) const { |
36 | const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); |
37 | const TargetRegisterClass *DestRC = MRI.getRegClass(Reg: DestReg); |
38 | const TargetRegisterClass *SrcRC = MRI.getRegClass(Reg: SrcReg); |
39 | |
40 | if (RegInfo.getRegSizeInBits(*DestRC) != RegInfo.getRegSizeInBits(*SrcRC)) |
41 | report_fatal_error(reason: "Copy one register into another with a different width" ); |
42 | |
43 | unsigned Op; |
44 | if (DestRC == &NVPTX::Int1RegsRegClass) { |
45 | Op = NVPTX::IMOV1rr; |
46 | } else if (DestRC == &NVPTX::Int16RegsRegClass) { |
47 | Op = NVPTX::IMOV16rr; |
48 | } else if (DestRC == &NVPTX::Int32RegsRegClass) { |
49 | Op = (SrcRC == &NVPTX::Int32RegsRegClass ? NVPTX::IMOV32rr |
50 | : NVPTX::BITCONVERT_32_F2I); |
51 | } else if (DestRC == &NVPTX::Int64RegsRegClass) { |
52 | Op = (SrcRC == &NVPTX::Int64RegsRegClass ? NVPTX::IMOV64rr |
53 | : NVPTX::BITCONVERT_64_F2I); |
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(B: 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 | /// |
90 | bool NVPTXInstrInfo::analyzeBranch(MachineBasicBlock &MBB, |
91 | MachineBasicBlock *&TBB, |
92 | MachineBasicBlock *&FBB, |
93 | SmallVectorImpl<MachineOperand> &Cond, |
94 | bool AllowModify) const { |
95 | // If the block has no terminators, it just falls into the block after it. |
96 | MachineBasicBlock::iterator I = MBB.end(); |
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(i: 0).getMBB(); |
107 | return false; |
108 | } else if (LastInst.getOpcode() == NVPTX::CBranch) { |
109 | // Block ends with fall-through condbranch. |
110 | TBB = LastInst.getOperand(i: 1).getMBB(); |
111 | Cond.push_back(Elt: LastInst.getOperand(i: 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(i: 1).getMBB(); |
129 | Cond.push_back(Elt: SecondLastInst.getOperand(i: 0)); |
130 | FBB = LastInst.getOperand(i: 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(i: 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 | |
149 | unsigned NVPTXInstrInfo::removeBranch(MachineBasicBlock &MBB, |
150 | int *BytesRemoved) const { |
151 | assert(!BytesRemoved && "code size not handled" ); |
152 | MachineBasicBlock::iterator I = MBB.end(); |
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 | |
175 | unsigned NVPTXInstrInfo::insertBranch(MachineBasicBlock &MBB, |
176 | MachineBasicBlock *TBB, |
177 | MachineBasicBlock *FBB, |
178 | ArrayRef<MachineOperand> Cond, |
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 | |