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, 169 const ConstantInt &Val) { 170 LLT Ty = MRI->getType(Res); 171 172 assert(Ty.isScalar() || Ty.isPointer() && "invalid operand type"); 173 174 const ConstantInt *NewVal = &Val; 175 if (Ty.getSizeInBits() != Val.getBitWidth()) 176 NewVal = ConstantInt::get(MF->getFunction()->getContext(), 177 Val.getValue().sextOrTrunc(Ty.getSizeInBits())); 178 179 return buildInstr(TargetOpcode::G_CONSTANT).addDef(Res).addCImm(NewVal); 180 } 181 182 MachineInstrBuilder MachineIRBuilder::buildConstant(unsigned Res, 183 int64_t Val) { 184 auto IntN = IntegerType::get(MF->getFunction()->getContext(), 185 MRI->getType(Res).getSizeInBits()); 186 ConstantInt *CI = ConstantInt::get(IntN, Val, true); 187 return buildConstant(Res, *CI); 188 } 189 190 MachineInstrBuilder MachineIRBuilder::buildFConstant(unsigned Res, 191 const ConstantFP &Val) { 192 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 193 194 return buildInstr(TargetOpcode::G_FCONSTANT).addDef(Res).addFPImm(&Val); 195 } 196 197 MachineInstrBuilder MachineIRBuilder::buildBrCond(unsigned Tst, 198 MachineBasicBlock &Dest) { 199 assert(MRI->getType(Tst).isScalar() && "invalid operand type"); 200 201 return buildInstr(TargetOpcode::G_BRCOND).addUse(Tst).addMBB(&Dest); 202 } 203 204 MachineInstrBuilder MachineIRBuilder::buildLoad(unsigned Res, unsigned Addr, 205 MachineMemOperand &MMO) { 206 assert(MRI->getType(Res).isValid() && "invalid operand type"); 207 assert(MRI->getType(Addr).isPointer() && "invalid operand type"); 208 209 return buildInstr(TargetOpcode::G_LOAD) 210 .addDef(Res) 211 .addUse(Addr) 212 .addMemOperand(&MMO); 213 } 214 215 MachineInstrBuilder MachineIRBuilder::buildStore(unsigned Val, unsigned Addr, 216 MachineMemOperand &MMO) { 217 assert(MRI->getType(Val).isValid() && "invalid operand type"); 218 assert(MRI->getType(Addr).isPointer() && "invalid operand type"); 219 220 return buildInstr(TargetOpcode::G_STORE) 221 .addUse(Val) 222 .addUse(Addr) 223 .addMemOperand(&MMO); 224 } 225 226 MachineInstrBuilder MachineIRBuilder::buildUAdde(unsigned Res, 227 unsigned CarryOut, 228 unsigned Op0, unsigned Op1, 229 unsigned CarryIn) { 230 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 231 assert(MRI->getType(Res) == MRI->getType(Op0) && 232 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 233 assert(MRI->getType(CarryOut).isScalar() && "invalid operand type"); 234 assert(MRI->getType(CarryOut) == MRI->getType(CarryIn) && "type mismatch"); 235 236 return buildInstr(TargetOpcode::G_UADDE) 237 .addDef(Res) 238 .addDef(CarryOut) 239 .addUse(Op0) 240 .addUse(Op1) 241 .addUse(CarryIn); 242 } 243 244 MachineInstrBuilder MachineIRBuilder::buildAnyExt(unsigned Res, unsigned Op) { 245 validateTruncExt(Res, Op, true); 246 return buildInstr(TargetOpcode::G_ANYEXT).addDef(Res).addUse(Op); 247 } 248 249 MachineInstrBuilder MachineIRBuilder::buildSExt(unsigned Res, unsigned Op) { 250 validateTruncExt(Res, Op, true); 251 return buildInstr(TargetOpcode::G_SEXT).addDef(Res).addUse(Op); 252 } 253 254 MachineInstrBuilder MachineIRBuilder::buildZExt(unsigned Res, unsigned Op) { 255 validateTruncExt(Res, Op, true); 256 return buildInstr(TargetOpcode::G_ZEXT).addDef(Res).addUse(Op); 257 } 258 259 MachineInstrBuilder MachineIRBuilder::buildSExtOrTrunc(unsigned Res, 260 unsigned Op) { 261 unsigned Opcode = TargetOpcode::COPY; 262 if (MRI->getType(Res).getSizeInBits() > MRI->getType(Op).getSizeInBits()) 263 Opcode = TargetOpcode::G_SEXT; 264 else if (MRI->getType(Res).getSizeInBits() < MRI->getType(Op).getSizeInBits()) 265 Opcode = TargetOpcode::G_TRUNC; 266 267 return buildInstr(Opcode).addDef(Res).addUse(Op); 268 } 269 270 MachineInstrBuilder MachineIRBuilder::buildExtract(ArrayRef<unsigned> Results, 271 ArrayRef<uint64_t> Indices, 272 unsigned Src) { 273 #ifndef NDEBUG 274 assert(Results.size() == Indices.size() && "inconsistent number of regs"); 275 assert(!Results.empty() && "invalid trivial extract"); 276 assert(std::is_sorted(Indices.begin(), Indices.end()) && 277 "extract offsets must be in ascending order"); 278 279 assert(MRI->getType(Src).isValid() && "invalid operand type"); 280 for (auto Res : Results) 281 assert(MRI->getType(Res).isValid() && "invalid operand type"); 282 #endif 283 284 auto MIB = BuildMI(getMF(), DL, getTII().get(TargetOpcode::G_EXTRACT)); 285 for (auto Res : Results) 286 MIB.addDef(Res); 287 288 MIB.addUse(Src); 289 290 for (auto Idx : Indices) 291 MIB.addImm(Idx); 292 293 getMBB().insert(getInsertPt(), MIB); 294 if (InsertedInstr) 295 InsertedInstr(MIB); 296 297 return MIB; 298 } 299 300 MachineInstrBuilder 301 MachineIRBuilder::buildSequence(unsigned Res, 302 ArrayRef<unsigned> Ops, 303 ArrayRef<uint64_t> Indices) { 304 #ifndef NDEBUG 305 assert(Ops.size() == Indices.size() && "incompatible args"); 306 assert(!Ops.empty() && "invalid trivial sequence"); 307 assert(std::is_sorted(Indices.begin(), Indices.end()) && 308 "sequence offsets must be in ascending order"); 309 310 assert(MRI->getType(Res).isValid() && "invalid operand type"); 311 for (auto Op : Ops) 312 assert(MRI->getType(Op).isValid() && "invalid operand type"); 313 #endif 314 315 MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_SEQUENCE); 316 MIB.addDef(Res); 317 for (unsigned i = 0; i < Ops.size(); ++i) { 318 MIB.addUse(Ops[i]); 319 MIB.addImm(Indices[i]); 320 } 321 return MIB; 322 } 323 324 MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID, 325 unsigned Res, 326 bool HasSideEffects) { 327 auto MIB = 328 buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS 329 : TargetOpcode::G_INTRINSIC); 330 if (Res) 331 MIB.addDef(Res); 332 MIB.addIntrinsicID(ID); 333 return MIB; 334 } 335 336 MachineInstrBuilder MachineIRBuilder::buildTrunc(unsigned Res, unsigned Op) { 337 validateTruncExt(Res, Op, false); 338 return buildInstr(TargetOpcode::G_TRUNC).addDef(Res).addUse(Op); 339 } 340 341 MachineInstrBuilder MachineIRBuilder::buildFPTrunc(unsigned Res, unsigned Op) { 342 validateTruncExt(Res, Op, false); 343 return buildInstr(TargetOpcode::G_FPTRUNC).addDef(Res).addUse(Op); 344 } 345 346 MachineInstrBuilder MachineIRBuilder::buildICmp(CmpInst::Predicate Pred, 347 unsigned Res, unsigned Op0, 348 unsigned Op1) { 349 #ifndef NDEBUG 350 assert(MRI->getType(Op0) == MRI->getType(Op0) && "type mismatch"); 351 assert(CmpInst::isIntPredicate(Pred) && "invalid predicate"); 352 if (MRI->getType(Op0).isScalar() || MRI->getType(Op0).isPointer()) 353 assert(MRI->getType(Res).isScalar() && "type mismatch"); 354 else 355 assert(MRI->getType(Res).isVector() && 356 MRI->getType(Res).getNumElements() == 357 MRI->getType(Op0).getNumElements() && 358 "type mismatch"); 359 #endif 360 361 return buildInstr(TargetOpcode::G_ICMP) 362 .addDef(Res) 363 .addPredicate(Pred) 364 .addUse(Op0) 365 .addUse(Op1); 366 } 367 368 MachineInstrBuilder MachineIRBuilder::buildFCmp(CmpInst::Predicate Pred, 369 unsigned Res, unsigned Op0, 370 unsigned Op1) { 371 #ifndef NDEBUG 372 assert((MRI->getType(Op0).isScalar() || MRI->getType(Op0).isVector()) && 373 "invalid operand type"); 374 assert(MRI->getType(Op0) == MRI->getType(Op1) && "type mismatch"); 375 assert(CmpInst::isFPPredicate(Pred) && "invalid predicate"); 376 if (MRI->getType(Op0).isScalar()) 377 assert(MRI->getType(Res).isScalar() && "type mismatch"); 378 else 379 assert(MRI->getType(Res).isVector() && 380 MRI->getType(Res).getNumElements() == 381 MRI->getType(Op0).getNumElements() && 382 "type mismatch"); 383 #endif 384 385 return buildInstr(TargetOpcode::G_FCMP) 386 .addDef(Res) 387 .addPredicate(Pred) 388 .addUse(Op0) 389 .addUse(Op1); 390 } 391 392 MachineInstrBuilder MachineIRBuilder::buildSelect(unsigned Res, unsigned Tst, 393 unsigned Op0, unsigned Op1) { 394 #ifndef NDEBUG 395 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 396 "invalid operand type"); 397 assert(MRI->getType(Res) == MRI->getType(Op0) && 398 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 399 if (MRI->getType(Res).isScalar()) 400 assert(MRI->getType(Tst).isScalar() && "type mismatch"); 401 else 402 assert(MRI->getType(Tst).isVector() && 403 MRI->getType(Tst).getNumElements() == 404 MRI->getType(Op0).getNumElements() && 405 "type mismatch"); 406 #endif 407 408 return buildInstr(TargetOpcode::G_SELECT) 409 .addDef(Res) 410 .addUse(Tst) 411 .addUse(Op0) 412 .addUse(Op1); 413 } 414 415 void MachineIRBuilder::validateTruncExt(unsigned Dst, unsigned Src, 416 bool IsExtend) { 417 #ifndef NDEBUG 418 LLT SrcTy = MRI->getType(Src); 419 LLT DstTy = MRI->getType(Dst); 420 421 if (DstTy.isVector()) { 422 assert(SrcTy.isVector() && "mismatched cast between vecot and non-vector"); 423 assert(SrcTy.getNumElements() == DstTy.getNumElements() && 424 "different number of elements in a trunc/ext"); 425 } else 426 assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc"); 427 428 if (IsExtend) 429 assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() && 430 "invalid narrowing extend"); 431 else 432 assert(DstTy.getSizeInBits() < SrcTy.getSizeInBits() && 433 "invalid widening trunc"); 434 #endif 435 } 436