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/CodeGen/MachineRegisterInfo.h" 18 #include "llvm/Target/TargetInstrInfo.h" 19 #include "llvm/Target/TargetOpcodes.h" 20 #include "llvm/Target/TargetSubtargetInfo.h" 21 22 using namespace llvm; 23 24 void MachineIRBuilder::setMF(MachineFunction &MF) { 25 this->MF = &MF; 26 this->MBB = nullptr; 27 this->MRI = &MF.getRegInfo(); 28 this->TII = MF.getSubtarget().getInstrInfo(); 29 this->DL = DebugLoc(); 30 this->MI = nullptr; 31 this->InsertedInstr = nullptr; 32 } 33 34 void MachineIRBuilder::setMBB(MachineBasicBlock &MBB, bool Beginning) { 35 this->MBB = &MBB; 36 this->MI = nullptr; 37 Before = Beginning; 38 assert(&getMF() == MBB.getParent() && 39 "Basic block is in a different function"); 40 } 41 42 void MachineIRBuilder::setInstr(MachineInstr &MI, bool Before) { 43 assert(MI.getParent() && "Instruction is not part of a basic block"); 44 setMBB(*MI.getParent()); 45 this->MI = &MI; 46 this->Before = Before; 47 } 48 49 MachineBasicBlock::iterator MachineIRBuilder::getInsertPt() { 50 if (MI) { 51 if (Before) 52 return MI; 53 if (!MI->getNextNode()) 54 return getMBB().end(); 55 return MI->getNextNode(); 56 } 57 return Before ? getMBB().begin() : getMBB().end(); 58 } 59 60 void MachineIRBuilder::recordInsertions( 61 std::function<void(MachineInstr *)> Inserted) { 62 InsertedInstr = Inserted; 63 } 64 65 void MachineIRBuilder::stopRecordingInsertions() { 66 InsertedInstr = nullptr; 67 } 68 69 //------------------------------------------------------------------------------ 70 // Build instruction variants. 71 //------------------------------------------------------------------------------ 72 73 MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opcode) { 74 return insertInstr(buildInstrNoInsert(Opcode)); 75 } 76 77 MachineInstrBuilder MachineIRBuilder::buildInstrNoInsert(unsigned Opcode) { 78 MachineInstrBuilder MIB = BuildMI(getMF(), DL, getTII().get(Opcode)); 79 return MIB; 80 } 81 82 83 MachineInstrBuilder MachineIRBuilder::insertInstr(MachineInstrBuilder MIB) { 84 getMBB().insert(getInsertPt(), MIB); 85 if (InsertedInstr) 86 InsertedInstr(MIB); 87 return MIB; 88 } 89 90 MachineInstrBuilder MachineIRBuilder::buildFrameIndex(unsigned Res, int Idx) { 91 assert(MRI->getType(Res).isPointer() && "invalid operand type"); 92 return buildInstr(TargetOpcode::G_FRAME_INDEX) 93 .addDef(Res) 94 .addFrameIndex(Idx); 95 } 96 97 MachineInstrBuilder MachineIRBuilder::buildGlobalValue(unsigned Res, 98 const GlobalValue *GV) { 99 assert(MRI->getType(Res).isPointer() && "invalid operand type"); 100 assert(MRI->getType(Res).getAddressSpace() == 101 GV->getType()->getAddressSpace() && 102 "address space mismatch"); 103 104 return buildInstr(TargetOpcode::G_GLOBAL_VALUE) 105 .addDef(Res) 106 .addGlobalAddress(GV); 107 } 108 109 MachineInstrBuilder MachineIRBuilder::buildAdd(unsigned Res, unsigned Op0, 110 unsigned Op1) { 111 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 112 "invalid operand type"); 113 assert(MRI->getType(Res) == MRI->getType(Op0) && 114 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 115 116 return buildInstr(TargetOpcode::G_ADD) 117 .addDef(Res) 118 .addUse(Op0) 119 .addUse(Op1); 120 } 121 122 MachineInstrBuilder MachineIRBuilder::buildGEP(unsigned Res, unsigned Op0, 123 unsigned Op1) { 124 assert(MRI->getType(Res).isPointer() && 125 MRI->getType(Res) == MRI->getType(Op0) && "type mismatch"); 126 assert(MRI->getType(Op1).isScalar() && "invalid offset type"); 127 128 return buildInstr(TargetOpcode::G_GEP) 129 .addDef(Res) 130 .addUse(Op0) 131 .addUse(Op1); 132 } 133 134 MachineInstrBuilder MachineIRBuilder::buildSub(unsigned Res, unsigned Op0, 135 unsigned Op1) { 136 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 137 "invalid operand type"); 138 assert(MRI->getType(Res) == MRI->getType(Op0) && 139 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 140 141 return buildInstr(TargetOpcode::G_SUB) 142 .addDef(Res) 143 .addUse(Op0) 144 .addUse(Op1); 145 } 146 147 MachineInstrBuilder MachineIRBuilder::buildMul(unsigned Res, unsigned Op0, 148 unsigned Op1) { 149 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 150 "invalid operand type"); 151 assert(MRI->getType(Res) == MRI->getType(Op0) && 152 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 153 154 return buildInstr(TargetOpcode::G_MUL) 155 .addDef(Res) 156 .addUse(Op0) 157 .addUse(Op1); 158 } 159 160 MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) { 161 return buildInstr(TargetOpcode::G_BR).addMBB(&Dest); 162 } 163 164 MachineInstrBuilder MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) { 165 return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op); 166 } 167 168 MachineInstrBuilder MachineIRBuilder::buildConstant(unsigned Res, int64_t Val) { 169 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 170 171 return buildInstr(TargetOpcode::G_CONSTANT).addDef(Res).addImm(Val); 172 } 173 174 MachineInstrBuilder MachineIRBuilder::buildFConstant(unsigned Res, 175 const ConstantFP &Val) { 176 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 177 178 return buildInstr(TargetOpcode::G_FCONSTANT).addDef(Res).addFPImm(&Val); 179 } 180 181 MachineInstrBuilder MachineIRBuilder::buildBrCond(unsigned Tst, 182 MachineBasicBlock &Dest) { 183 assert(MRI->getType(Tst).isScalar() && "invalid operand type"); 184 185 return buildInstr(TargetOpcode::G_BRCOND).addUse(Tst).addMBB(&Dest); 186 } 187 188 MachineInstrBuilder MachineIRBuilder::buildLoad(unsigned Res, unsigned Addr, 189 MachineMemOperand &MMO) { 190 assert(MRI->getType(Res).isValid() && "invalid operand type"); 191 assert(MRI->getType(Addr).isPointer() && "invalid operand type"); 192 193 return buildInstr(TargetOpcode::G_LOAD) 194 .addDef(Res) 195 .addUse(Addr) 196 .addMemOperand(&MMO); 197 } 198 199 MachineInstrBuilder MachineIRBuilder::buildStore(unsigned Val, unsigned Addr, 200 MachineMemOperand &MMO) { 201 assert(MRI->getType(Val).isValid() && "invalid operand type"); 202 assert(MRI->getType(Addr).isPointer() && "invalid operand type"); 203 204 return buildInstr(TargetOpcode::G_STORE) 205 .addUse(Val) 206 .addUse(Addr) 207 .addMemOperand(&MMO); 208 } 209 210 MachineInstrBuilder MachineIRBuilder::buildUAdde(unsigned Res, 211 unsigned CarryOut, 212 unsigned Op0, unsigned Op1, 213 unsigned CarryIn) { 214 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 215 assert(MRI->getType(Res) == MRI->getType(Op0) && 216 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 217 assert(MRI->getType(CarryOut).isScalar() && "invalid operand type"); 218 assert(MRI->getType(CarryOut) == MRI->getType(CarryIn) && "type mismatch"); 219 220 return buildInstr(TargetOpcode::G_UADDE) 221 .addDef(Res) 222 .addDef(CarryOut) 223 .addUse(Op0) 224 .addUse(Op1) 225 .addUse(CarryIn); 226 } 227 228 MachineInstrBuilder MachineIRBuilder::buildAnyExt(unsigned Res, unsigned Op) { 229 validateTruncExt(Res, Op, true); 230 return buildInstr(TargetOpcode::G_ANYEXT).addDef(Res).addUse(Op); 231 } 232 233 MachineInstrBuilder MachineIRBuilder::buildSExt(unsigned Res, unsigned Op) { 234 validateTruncExt(Res, Op, true); 235 return buildInstr(TargetOpcode::G_SEXT).addDef(Res).addUse(Op); 236 } 237 238 MachineInstrBuilder MachineIRBuilder::buildZExt(unsigned Res, unsigned Op) { 239 validateTruncExt(Res, Op, true); 240 return buildInstr(TargetOpcode::G_ZEXT).addDef(Res).addUse(Op); 241 } 242 243 MachineInstrBuilder MachineIRBuilder::buildSExtOrTrunc(unsigned Res, 244 unsigned Op) { 245 unsigned Opcode = TargetOpcode::COPY; 246 if (MRI->getType(Res).getSizeInBits() > MRI->getType(Op).getSizeInBits()) 247 Opcode = TargetOpcode::G_SEXT; 248 else if (MRI->getType(Res).getSizeInBits() < MRI->getType(Op).getSizeInBits()) 249 Opcode = TargetOpcode::G_TRUNC; 250 251 return buildInstr(Opcode).addDef(Res).addUse(Op); 252 } 253 254 MachineInstrBuilder MachineIRBuilder::buildExtract(ArrayRef<unsigned> Results, 255 ArrayRef<uint64_t> Indices, 256 unsigned Src) { 257 #ifndef NDEBUG 258 assert(Results.size() == Indices.size() && "inconsistent number of regs"); 259 assert(!Results.empty() && "invalid trivial extract"); 260 assert(std::is_sorted(Indices.begin(), Indices.end()) && 261 "extract offsets must be in ascending order"); 262 263 assert(MRI->getType(Src).isValid() && "invalid operand type"); 264 for (auto Res : Results) 265 assert(MRI->getType(Res).isValid() && "invalid operand type"); 266 #endif 267 268 auto MIB = BuildMI(getMF(), DL, getTII().get(TargetOpcode::G_EXTRACT)); 269 for (auto Res : Results) 270 MIB.addDef(Res); 271 272 MIB.addUse(Src); 273 274 for (auto Idx : Indices) 275 MIB.addImm(Idx); 276 277 getMBB().insert(getInsertPt(), MIB); 278 if (InsertedInstr) 279 InsertedInstr(MIB); 280 281 return MIB; 282 } 283 284 MachineInstrBuilder 285 MachineIRBuilder::buildSequence(unsigned Res, 286 ArrayRef<unsigned> Ops, 287 ArrayRef<uint64_t> Indices) { 288 #ifndef NDEBUG 289 assert(Ops.size() == Indices.size() && "incompatible args"); 290 assert(!Ops.empty() && "invalid trivial sequence"); 291 assert(std::is_sorted(Indices.begin(), Indices.end()) && 292 "sequence offsets must be in ascending order"); 293 294 assert(MRI->getType(Res).isValid() && "invalid operand type"); 295 for (auto Op : Ops) 296 assert(MRI->getType(Op).isValid() && "invalid operand type"); 297 #endif 298 299 MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_SEQUENCE); 300 MIB.addDef(Res); 301 for (unsigned i = 0; i < Ops.size(); ++i) { 302 MIB.addUse(Ops[i]); 303 MIB.addImm(Indices[i]); 304 } 305 return MIB; 306 } 307 308 MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID, 309 unsigned Res, 310 bool HasSideEffects) { 311 auto MIB = 312 buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS 313 : TargetOpcode::G_INTRINSIC); 314 if (Res) 315 MIB.addDef(Res); 316 MIB.addIntrinsicID(ID); 317 return MIB; 318 } 319 320 MachineInstrBuilder MachineIRBuilder::buildTrunc(unsigned Res, unsigned Op) { 321 validateTruncExt(Res, Op, false); 322 return buildInstr(TargetOpcode::G_TRUNC).addDef(Res).addUse(Op); 323 } 324 325 MachineInstrBuilder MachineIRBuilder::buildFPTrunc(unsigned Res, unsigned Op) { 326 validateTruncExt(Res, Op, false); 327 return buildInstr(TargetOpcode::G_FPTRUNC).addDef(Res).addUse(Op); 328 } 329 330 MachineInstrBuilder MachineIRBuilder::buildICmp(CmpInst::Predicate Pred, 331 unsigned Res, unsigned Op0, 332 unsigned Op1) { 333 #ifndef NDEBUG 334 assert(MRI->getType(Op0) == MRI->getType(Op0) && "type mismatch"); 335 assert(CmpInst::isIntPredicate(Pred) && "invalid predicate"); 336 if (MRI->getType(Op0).isScalar() || MRI->getType(Op0).isPointer()) 337 assert(MRI->getType(Res).isScalar() && "type mismatch"); 338 else 339 assert(MRI->getType(Res).isVector() && 340 MRI->getType(Res).getNumElements() == 341 MRI->getType(Op0).getNumElements() && 342 "type mismatch"); 343 #endif 344 345 return buildInstr(TargetOpcode::G_ICMP) 346 .addDef(Res) 347 .addPredicate(Pred) 348 .addUse(Op0) 349 .addUse(Op1); 350 } 351 352 MachineInstrBuilder MachineIRBuilder::buildFCmp(CmpInst::Predicate Pred, 353 unsigned Res, unsigned Op0, 354 unsigned Op1) { 355 #ifndef NDEBUG 356 assert((MRI->getType(Op0).isScalar() || MRI->getType(Op0).isVector()) && 357 "invalid operand type"); 358 assert(MRI->getType(Op0) == MRI->getType(Op1) && "type mismatch"); 359 assert(CmpInst::isFPPredicate(Pred) && "invalid predicate"); 360 if (MRI->getType(Op0).isScalar()) 361 assert(MRI->getType(Res).isScalar() && "type mismatch"); 362 else 363 assert(MRI->getType(Res).isVector() && 364 MRI->getType(Res).getNumElements() == 365 MRI->getType(Op0).getNumElements() && 366 "type mismatch"); 367 #endif 368 369 return buildInstr(TargetOpcode::G_FCMP) 370 .addDef(Res) 371 .addPredicate(Pred) 372 .addUse(Op0) 373 .addUse(Op1); 374 } 375 376 MachineInstrBuilder MachineIRBuilder::buildSelect(unsigned Res, unsigned Tst, 377 unsigned Op0, unsigned Op1) { 378 #ifndef NDEBUG 379 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 380 "invalid operand type"); 381 assert(MRI->getType(Res) == MRI->getType(Op0) && 382 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 383 if (MRI->getType(Res).isScalar()) 384 assert(MRI->getType(Tst).isScalar() && "type mismatch"); 385 else 386 assert(MRI->getType(Tst).isVector() && 387 MRI->getType(Tst).getNumElements() == 388 MRI->getType(Op0).getNumElements() && 389 "type mismatch"); 390 #endif 391 392 return buildInstr(TargetOpcode::G_SELECT) 393 .addDef(Res) 394 .addUse(Tst) 395 .addUse(Op0) 396 .addUse(Op1); 397 } 398 399 void MachineIRBuilder::validateTruncExt(unsigned Dst, unsigned Src, 400 bool IsExtend) { 401 #ifndef NDEBUG 402 LLT SrcTy = MRI->getType(Src); 403 LLT DstTy = MRI->getType(Dst); 404 405 if (DstTy.isVector()) { 406 assert(SrcTy.isVector() && "mismatched cast between vecot and non-vector"); 407 assert(SrcTy.getNumElements() == DstTy.getNumElements() && 408 "different number of elements in a trunc/ext"); 409 } else 410 assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc"); 411 412 if (IsExtend) 413 assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() && 414 "invalid narrowing extend"); 415 else 416 assert(DstTy.getSizeInBits() < SrcTy.getSizeInBits() && 417 "invalid widening trunc"); 418 #endif 419 } 420