1 //===-- llvm/CodeGen/GlobalISel/MachineIRBuilder.cpp - MIBuilder--*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file implements the MachineIRBuidler class.
11 //===----------------------------------------------------------------------===//
12 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
13 
14 #include "llvm/CodeGen/MachineFunction.h"
15 #include "llvm/CodeGen/MachineInstr.h"
16 #include "llvm/CodeGen/MachineInstrBuilder.h"
17 #include "llvm/Target/TargetInstrInfo.h"
18 #include "llvm/Target/TargetOpcodes.h"
19 #include "llvm/Target/TargetSubtargetInfo.h"
20 
21 using namespace llvm;
22 
23 void MachineIRBuilder::setMF(MachineFunction &MF) {
24   this->MF = &MF;
25   this->MBB = nullptr;
26   this->TII = MF.getSubtarget().getInstrInfo();
27   this->DL = DebugLoc();
28   this->MI = nullptr;
29   this->InsertedInstr = nullptr;
30 }
31 
32 void MachineIRBuilder::setMBB(MachineBasicBlock &MBB, bool Beginning) {
33   this->MBB = &MBB;
34   Before = Beginning;
35   assert(&getMF() == MBB.getParent() &&
36          "Basic block is in a different function");
37 }
38 
39 void MachineIRBuilder::setInstr(MachineInstr &MI, bool Before) {
40   assert(MI.getParent() && "Instruction is not part of a basic block");
41   setMBB(*MI.getParent());
42   this->MI = &MI;
43   this->Before = Before;
44 }
45 
46 MachineBasicBlock::iterator MachineIRBuilder::getInsertPt() {
47   if (MI) {
48     if (Before)
49       return MI;
50     if (!MI->getNextNode())
51       return getMBB().end();
52     return MI->getNextNode();
53   }
54   return Before ? getMBB().begin() : getMBB().end();
55 }
56 
57 void MachineIRBuilder::recordInsertions(
58     std::function<void(MachineInstr *)> Inserted) {
59   InsertedInstr = Inserted;
60 }
61 
62 void MachineIRBuilder::stopRecordingInsertions() {
63   InsertedInstr = nullptr;
64 }
65 
66 //------------------------------------------------------------------------------
67 // Build instruction variants.
68 //------------------------------------------------------------------------------
69 
70 MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opcode,
71                                                   ArrayRef<LLT> Tys) {
72   MachineInstrBuilder MIB = BuildMI(getMF(), DL, getTII().get(Opcode));
73   if (Tys.size() > 0) {
74     assert(isPreISelGenericOpcode(Opcode) &&
75            "Only generic instruction can have a type");
76     for (unsigned i = 0; i < Tys.size(); ++i)
77       MIB->setType(Tys[i], i);
78   } else
79     assert(!isPreISelGenericOpcode(Opcode) &&
80            "Generic instruction must have a type");
81   getMBB().insert(getInsertPt(), MIB);
82   if (InsertedInstr)
83     InsertedInstr(MIB);
84   return MIB;
85 }
86 
87 MachineInstrBuilder MachineIRBuilder::buildFrameIndex(LLT Ty, unsigned Res,
88                                                        int Idx) {
89   return buildInstr(TargetOpcode::G_FRAME_INDEX, Ty)
90       .addDef(Res)
91       .addFrameIndex(Idx);
92 }
93 
94 MachineInstrBuilder MachineIRBuilder::buildAdd(LLT Ty, unsigned Res,
95                                                 unsigned Op0, unsigned Op1) {
96   return buildInstr(TargetOpcode::G_ADD, Ty)
97       .addDef(Res)
98       .addUse(Op0)
99       .addUse(Op1);
100 }
101 
102 MachineInstrBuilder MachineIRBuilder::buildSub(LLT Ty, unsigned Res,
103                                                 unsigned Op0, unsigned Op1) {
104   return buildInstr(TargetOpcode::G_SUB, Ty)
105       .addDef(Res)
106       .addUse(Op0)
107       .addUse(Op1);
108 }
109 
110 MachineInstrBuilder MachineIRBuilder::buildMul(LLT Ty, unsigned Res,
111                                                 unsigned Op0, unsigned Op1) {
112   return buildInstr(TargetOpcode::G_MUL, Ty)
113       .addDef(Res)
114       .addUse(Op0)
115       .addUse(Op1);
116 }
117 
118 MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
119   return buildInstr(TargetOpcode::G_BR, LLT::unsized()).addMBB(&Dest);
120 }
121 
122 MachineInstrBuilder MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) {
123   return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op);
124 }
125 
126 MachineInstrBuilder MachineIRBuilder::buildConstant(LLT Ty, unsigned Res,
127                                                     int64_t Val) {
128   return buildInstr(TargetOpcode::G_CONSTANT, Ty).addDef(Res).addImm(Val);
129 }
130 
131 MachineInstrBuilder MachineIRBuilder::buildFConstant(LLT Ty, unsigned Res,
132                                                     const ConstantFP &Val) {
133   return buildInstr(TargetOpcode::G_FCONSTANT, Ty).addDef(Res).addFPImm(&Val);
134 }
135 
136 MachineInstrBuilder MachineIRBuilder::buildBrCond(LLT Ty, unsigned Tst,
137                                                   MachineBasicBlock &Dest) {
138   return buildInstr(TargetOpcode::G_BRCOND, Ty).addUse(Tst).addMBB(&Dest);
139 }
140 
141 
142  MachineInstrBuilder MachineIRBuilder::buildLoad(LLT VTy, LLT PTy, unsigned Res,
143                                                  unsigned Addr,
144                                                  MachineMemOperand &MMO) {
145   return buildInstr(TargetOpcode::G_LOAD, {VTy, PTy})
146       .addDef(Res)
147       .addUse(Addr)
148       .addMemOperand(&MMO);
149 }
150 
151 MachineInstrBuilder MachineIRBuilder::buildStore(LLT VTy, LLT PTy,
152                                                   unsigned Val, unsigned Addr,
153                                                   MachineMemOperand &MMO) {
154   return buildInstr(TargetOpcode::G_STORE, {VTy, PTy})
155       .addUse(Val)
156       .addUse(Addr)
157       .addMemOperand(&MMO);
158 }
159 
160 MachineInstrBuilder
161 MachineIRBuilder::buildUAdde(ArrayRef<LLT> Tys, unsigned Res, unsigned CarryOut,
162                              unsigned Op0, unsigned Op1, unsigned CarryIn) {
163   return buildInstr(TargetOpcode::G_UADDE, Tys)
164       .addDef(Res)
165       .addDef(CarryOut)
166       .addUse(Op0)
167       .addUse(Op1)
168       .addUse(CarryIn);
169 }
170 
171 MachineInstrBuilder MachineIRBuilder::buildAnyExt(ArrayRef<LLT> Tys,
172                                                   unsigned Res, unsigned Op) {
173   validateTruncExt(Tys, true);
174   return buildInstr(TargetOpcode::G_ANYEXT, Tys).addDef(Res).addUse(Op);
175 }
176 
177 MachineInstrBuilder MachineIRBuilder::buildSExt(ArrayRef<LLT> Tys, unsigned Res,
178                                                 unsigned Op) {
179   validateTruncExt(Tys, true);
180   return buildInstr(TargetOpcode::G_SEXT, Tys).addDef(Res).addUse(Op);
181 }
182 
183 MachineInstrBuilder MachineIRBuilder::buildZExt(ArrayRef<LLT> Tys, unsigned Res,
184                                                 unsigned Op) {
185   validateTruncExt(Tys, true);
186   return buildInstr(TargetOpcode::G_ZEXT, Tys).addDef(Res).addUse(Op);
187 }
188 
189 MachineInstrBuilder MachineIRBuilder::buildExtract(ArrayRef<LLT> ResTys,
190                                                    ArrayRef<unsigned> Results,
191                                                    ArrayRef<uint64_t> Indices,
192                                                    LLT SrcTy, unsigned Src) {
193   assert(ResTys.size() == Results.size() && Results.size() == Indices.size() &&
194          "inconsistent number of regs");
195   assert(!Results.empty() && "invalid trivial extract");
196 
197   auto MIB = BuildMI(getMF(), DL, getTII().get(TargetOpcode::G_EXTRACT));
198   for (unsigned i = 0; i < ResTys.size(); ++i)
199     MIB->setType(LLT::scalar(ResTys[i].getSizeInBits()), i);
200   MIB->setType(LLT::scalar(SrcTy.getSizeInBits()), ResTys.size());
201 
202   for (auto Res : Results)
203     MIB.addDef(Res);
204 
205   MIB.addUse(Src);
206 
207   for (auto Idx : Indices)
208     MIB.addImm(Idx);
209 
210   getMBB().insert(getInsertPt(), MIB);
211   if (InsertedInstr)
212     InsertedInstr(MIB);
213 
214   return MIB;
215 }
216 
217 MachineInstrBuilder
218 MachineIRBuilder::buildSequence(LLT ResTy, unsigned Res,
219                                 ArrayRef<LLT> OpTys,
220                                 ArrayRef<unsigned> Ops,
221                                 ArrayRef<unsigned> Indices) {
222   assert(OpTys.size() == Ops.size() && Ops.size() == Indices.size() &&
223          "incompatible args");
224   assert(!Ops.empty() && "invalid trivial sequence");
225 
226   MachineInstrBuilder MIB =
227       buildInstr(TargetOpcode::G_SEQUENCE, LLT::scalar(ResTy.getSizeInBits()));
228   MIB.addDef(Res);
229   for (unsigned i = 0; i < Ops.size(); ++i) {
230     MIB.addUse(Ops[i]);
231     MIB.addImm(Indices[i]);
232     MIB->setType(LLT::scalar(OpTys[i].getSizeInBits()), MIB->getNumTypes());
233   }
234   return MIB;
235 }
236 
237 MachineInstrBuilder MachineIRBuilder::buildIntrinsic(ArrayRef<LLT> Tys,
238                                                      Intrinsic::ID ID,
239                                                      unsigned Res,
240                                                      bool HasSideEffects) {
241   auto MIB =
242       buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS
243                                 : TargetOpcode::G_INTRINSIC,
244                  Tys);
245   if (Res)
246     MIB.addDef(Res);
247   MIB.addIntrinsicID(ID);
248   return MIB;
249 }
250 
251 MachineInstrBuilder MachineIRBuilder::buildTrunc(ArrayRef<LLT> Tys,
252                                                  unsigned Res, unsigned Op) {
253   validateTruncExt(Tys, false);
254   return buildInstr(TargetOpcode::G_TRUNC, Tys).addDef(Res).addUse(Op);
255 }
256 
257 MachineInstrBuilder MachineIRBuilder::buildFPTrunc(ArrayRef<LLT> Tys,
258                                                    unsigned Res, unsigned Op) {
259   validateTruncExt(Tys, false);
260   return buildInstr(TargetOpcode::G_FPTRUNC, Tys).addDef(Res).addUse(Op);
261 }
262 
263 MachineInstrBuilder MachineIRBuilder::buildICmp(ArrayRef<LLT> Tys,
264                                                 CmpInst::Predicate Pred,
265                                                 unsigned Res, unsigned Op0,
266                                                 unsigned Op1) {
267   return buildInstr(TargetOpcode::G_ICMP, Tys)
268       .addDef(Res)
269       .addPredicate(Pred)
270       .addUse(Op0)
271       .addUse(Op1);
272 }
273 
274 MachineInstrBuilder MachineIRBuilder::buildFCmp(ArrayRef<LLT> Tys,
275                                                 CmpInst::Predicate Pred,
276                                                 unsigned Res, unsigned Op0,
277                                                 unsigned Op1) {
278   return buildInstr(TargetOpcode::G_FCMP, Tys)
279       .addDef(Res)
280       .addPredicate(Pred)
281       .addUse(Op0)
282       .addUse(Op1);
283 }
284 
285 MachineInstrBuilder MachineIRBuilder::buildSelect(LLT Ty, unsigned Res,
286                                                   unsigned Tst,
287                                                   unsigned Op0, unsigned Op1) {
288   return buildInstr(TargetOpcode::G_SELECT, {Ty, LLT::scalar(1)})
289       .addDef(Res)
290       .addUse(Tst)
291       .addUse(Op0)
292       .addUse(Op1);
293 }
294 
295 void MachineIRBuilder::validateTruncExt(ArrayRef<LLT> Tys, bool IsExtend) {
296 #ifndef NDEBUG
297   assert(Tys.size() == 2 && "cast should have a source and a dest type");
298   LLT DstTy{Tys[0]}, SrcTy{Tys[1]};
299 
300   if (DstTy.isVector()) {
301     assert(SrcTy.isVector() && "mismatched cast between vecot and non-vector");
302     assert(SrcTy.getNumElements() == DstTy.getNumElements() &&
303            "different number of elements in a trunc/ext");
304   } else
305     assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc");
306 
307   if (IsExtend)
308     assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&
309            "invalid narrowing extend");
310   else
311     assert(DstTy.getSizeInBits() < SrcTy.getSizeInBits() &&
312            "invalid widening trunc");
313 #endif
314 }
315