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