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