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(RC: *DestRC) != RegInfo.getRegSizeInBits(RC: *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::Int128RegsRegClass) { |
55 | Op = NVPTX::IMOV128rr; |
56 | } else if (DestRC == &NVPTX::Float32RegsRegClass) { |
57 | Op = (SrcRC == &NVPTX::Float32RegsRegClass ? NVPTX::FMOV32rr |
58 | : NVPTX::BITCONVERT_32_I2F); |
59 | } else if (DestRC == &NVPTX::Float64RegsRegClass) { |
60 | Op = (SrcRC == &NVPTX::Float64RegsRegClass ? NVPTX::FMOV64rr |
61 | : NVPTX::BITCONVERT_64_I2F); |
62 | } else { |
63 | llvm_unreachable("Bad register copy" ); |
64 | } |
65 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode: Op), DestReg) |
66 | .addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc)); |
67 | } |
68 | |
69 | /// analyzeBranch - Analyze the branching code at the end of MBB, returning |
70 | /// true if it cannot be understood (e.g. it's a switch dispatch or isn't |
71 | /// implemented for a target). Upon success, this returns false and returns |
72 | /// with the following information in various cases: |
73 | /// |
74 | /// 1. If this block ends with no branches (it just falls through to its succ) |
75 | /// just return false, leaving TBB/FBB null. |
76 | /// 2. If this block ends with only an unconditional branch, it sets TBB to be |
77 | /// the destination block. |
78 | /// 3. If this block ends with an conditional branch and it falls through to |
79 | /// an successor block, it sets TBB to be the branch destination block and a |
80 | /// list of operands that evaluate the condition. These |
81 | /// operands can be passed to other TargetInstrInfo methods to create new |
82 | /// branches. |
83 | /// 4. If this block ends with an conditional branch and an unconditional |
84 | /// block, it returns the 'true' destination in TBB, the 'false' destination |
85 | /// in FBB, and a list of operands that evaluate the condition. These |
86 | /// operands can be passed to other TargetInstrInfo methods to create new |
87 | /// branches. |
88 | /// |
89 | /// Note that removeBranch and insertBranch must be implemented to support |
90 | /// cases where this method returns success. |
91 | /// |
92 | bool NVPTXInstrInfo::analyzeBranch(MachineBasicBlock &MBB, |
93 | MachineBasicBlock *&TBB, |
94 | MachineBasicBlock *&FBB, |
95 | SmallVectorImpl<MachineOperand> &Cond, |
96 | bool AllowModify) const { |
97 | // If the block has no terminators, it just falls into the block after it. |
98 | MachineBasicBlock::iterator I = MBB.end(); |
99 | if (I == MBB.begin() || !isUnpredicatedTerminator(MI: *--I)) |
100 | return false; |
101 | |
102 | // Get the last instruction in the block. |
103 | MachineInstr &LastInst = *I; |
104 | |
105 | // If there is only one terminator instruction, process it. |
106 | if (I == MBB.begin() || !isUnpredicatedTerminator(MI: *--I)) { |
107 | if (LastInst.getOpcode() == NVPTX::GOTO) { |
108 | TBB = LastInst.getOperand(i: 0).getMBB(); |
109 | return false; |
110 | } else if (LastInst.getOpcode() == NVPTX::CBranch) { |
111 | // Block ends with fall-through condbranch. |
112 | TBB = LastInst.getOperand(i: 1).getMBB(); |
113 | Cond.push_back(Elt: LastInst.getOperand(i: 0)); |
114 | return false; |
115 | } |
116 | // Otherwise, don't know what this is. |
117 | return true; |
118 | } |
119 | |
120 | // Get the instruction before it if it's a terminator. |
121 | MachineInstr &SecondLastInst = *I; |
122 | |
123 | // If there are three terminators, we don't know what sort of block this is. |
124 | if (I != MBB.begin() && isUnpredicatedTerminator(MI: *--I)) |
125 | return true; |
126 | |
127 | // If the block ends with NVPTX::GOTO and NVPTX:CBranch, handle it. |
128 | if (SecondLastInst.getOpcode() == NVPTX::CBranch && |
129 | LastInst.getOpcode() == NVPTX::GOTO) { |
130 | TBB = SecondLastInst.getOperand(i: 1).getMBB(); |
131 | Cond.push_back(Elt: SecondLastInst.getOperand(i: 0)); |
132 | FBB = LastInst.getOperand(i: 0).getMBB(); |
133 | return false; |
134 | } |
135 | |
136 | // If the block ends with two NVPTX:GOTOs, handle it. The second one is not |
137 | // executed, so remove it. |
138 | if (SecondLastInst.getOpcode() == NVPTX::GOTO && |
139 | LastInst.getOpcode() == NVPTX::GOTO) { |
140 | TBB = SecondLastInst.getOperand(i: 0).getMBB(); |
141 | I = LastInst; |
142 | if (AllowModify) |
143 | I->eraseFromParent(); |
144 | return false; |
145 | } |
146 | |
147 | // Otherwise, can't handle this. |
148 | return true; |
149 | } |
150 | |
151 | unsigned NVPTXInstrInfo::removeBranch(MachineBasicBlock &MBB, |
152 | int *BytesRemoved) const { |
153 | assert(!BytesRemoved && "code size not handled" ); |
154 | MachineBasicBlock::iterator I = MBB.end(); |
155 | if (I == MBB.begin()) |
156 | return 0; |
157 | --I; |
158 | if (I->getOpcode() != NVPTX::GOTO && I->getOpcode() != NVPTX::CBranch) |
159 | return 0; |
160 | |
161 | // Remove the branch. |
162 | I->eraseFromParent(); |
163 | |
164 | I = MBB.end(); |
165 | |
166 | if (I == MBB.begin()) |
167 | return 1; |
168 | --I; |
169 | if (I->getOpcode() != NVPTX::CBranch) |
170 | return 1; |
171 | |
172 | // Remove the branch. |
173 | I->eraseFromParent(); |
174 | return 2; |
175 | } |
176 | |
177 | unsigned NVPTXInstrInfo::insertBranch(MachineBasicBlock &MBB, |
178 | MachineBasicBlock *TBB, |
179 | MachineBasicBlock *FBB, |
180 | ArrayRef<MachineOperand> Cond, |
181 | const DebugLoc &DL, |
182 | int *BytesAdded) const { |
183 | assert(!BytesAdded && "code size not handled" ); |
184 | |
185 | // Shouldn't be a fall through. |
186 | assert(TBB && "insertBranch must not be told to insert a fallthrough" ); |
187 | assert((Cond.size() == 1 || Cond.size() == 0) && |
188 | "NVPTX branch conditions have two components!" ); |
189 | |
190 | // One-way branch. |
191 | if (!FBB) { |
192 | if (Cond.empty()) // Unconditional branch |
193 | BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: NVPTX::GOTO)).addMBB(MBB: TBB); |
194 | else // Conditional branch |
195 | BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: NVPTX::CBranch)).add(MO: Cond[0]).addMBB(MBB: TBB); |
196 | return 1; |
197 | } |
198 | |
199 | // Two-way Conditional Branch. |
200 | BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: NVPTX::CBranch)).add(MO: Cond[0]).addMBB(MBB: TBB); |
201 | BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: NVPTX::GOTO)).addMBB(MBB: FBB); |
202 | return 2; |
203 | } |
204 | |