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/CodeGen/TargetInstrInfo.h" 19 #include "llvm/CodeGen/TargetOpcodes.h" 20 #include "llvm/CodeGen/TargetSubtargetInfo.h" 21 #include "llvm/IR/DebugInfo.h" 22 23 using namespace llvm; 24 25 void MachineIRBuilderBase::setMF(MachineFunction &MF) { 26 State.MF = &MF; 27 State.MBB = nullptr; 28 State.MRI = &MF.getRegInfo(); 29 State.TII = MF.getSubtarget().getInstrInfo(); 30 State.DL = DebugLoc(); 31 State.II = MachineBasicBlock::iterator(); 32 State.InsertedInstr = nullptr; 33 } 34 35 void MachineIRBuilderBase::setMBB(MachineBasicBlock &MBB) { 36 State.MBB = &MBB; 37 State.II = MBB.end(); 38 assert(&getMF() == MBB.getParent() && 39 "Basic block is in a different function"); 40 } 41 42 void MachineIRBuilderBase::setInstr(MachineInstr &MI) { 43 assert(MI.getParent() && "Instruction is not part of a basic block"); 44 setMBB(*MI.getParent()); 45 State.II = MI.getIterator(); 46 } 47 48 void MachineIRBuilderBase::setInsertPt(MachineBasicBlock &MBB, 49 MachineBasicBlock::iterator II) { 50 assert(MBB.getParent() == &getMF() && 51 "Basic block is in a different function"); 52 State.MBB = &MBB; 53 State.II = II; 54 } 55 56 void MachineIRBuilderBase::recordInsertions( 57 std::function<void(MachineInstr *)> Inserted) { 58 State.InsertedInstr = std::move(Inserted); 59 } 60 61 void MachineIRBuilderBase::stopRecordingInsertions() { 62 State.InsertedInstr = nullptr; 63 } 64 65 //------------------------------------------------------------------------------ 66 // Build instruction variants. 67 //------------------------------------------------------------------------------ 68 69 MachineInstrBuilder MachineIRBuilderBase::buildInstr(unsigned Opcode) { 70 return insertInstr(buildInstrNoInsert(Opcode)); 71 } 72 73 MachineInstrBuilder MachineIRBuilderBase::buildInstrNoInsert(unsigned Opcode) { 74 MachineInstrBuilder MIB = BuildMI(getMF(), getDL(), getTII().get(Opcode)); 75 return MIB; 76 } 77 78 MachineInstrBuilder MachineIRBuilderBase::insertInstr(MachineInstrBuilder MIB) { 79 getMBB().insert(getInsertPt(), MIB); 80 if (State.InsertedInstr) 81 State.InsertedInstr(MIB); 82 return MIB; 83 } 84 85 MachineInstrBuilder 86 MachineIRBuilderBase::buildDirectDbgValue(unsigned Reg, const MDNode *Variable, 87 const MDNode *Expr) { 88 assert(isa<DILocalVariable>(Variable) && "not a variable"); 89 assert(cast<DIExpression>(Expr)->isValid() && "not an expression"); 90 assert( 91 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) && 92 "Expected inlined-at fields to agree"); 93 return insertInstr(BuildMI(getMF(), getDL(), 94 getTII().get(TargetOpcode::DBG_VALUE), 95 /*IsIndirect*/ false, Reg, Variable, Expr)); 96 } 97 98 MachineInstrBuilder MachineIRBuilderBase::buildIndirectDbgValue( 99 unsigned Reg, const MDNode *Variable, const MDNode *Expr) { 100 assert(isa<DILocalVariable>(Variable) && "not a variable"); 101 assert(cast<DIExpression>(Expr)->isValid() && "not an expression"); 102 assert( 103 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) && 104 "Expected inlined-at fields to agree"); 105 return insertInstr(BuildMI(getMF(), getDL(), 106 getTII().get(TargetOpcode::DBG_VALUE), 107 /*IsIndirect*/ true, Reg, Variable, Expr)); 108 } 109 110 MachineInstrBuilder 111 MachineIRBuilderBase::buildFIDbgValue(int FI, const MDNode *Variable, 112 const MDNode *Expr) { 113 assert(isa<DILocalVariable>(Variable) && "not a variable"); 114 assert(cast<DIExpression>(Expr)->isValid() && "not an expression"); 115 assert( 116 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) && 117 "Expected inlined-at fields to agree"); 118 return buildInstr(TargetOpcode::DBG_VALUE) 119 .addFrameIndex(FI) 120 .addImm(0) 121 .addMetadata(Variable) 122 .addMetadata(Expr); 123 } 124 125 MachineInstrBuilder MachineIRBuilderBase::buildConstDbgValue( 126 const Constant &C, const MDNode *Variable, const MDNode *Expr) { 127 assert(isa<DILocalVariable>(Variable) && "not a variable"); 128 assert(cast<DIExpression>(Expr)->isValid() && "not an expression"); 129 assert( 130 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) && 131 "Expected inlined-at fields to agree"); 132 auto MIB = buildInstr(TargetOpcode::DBG_VALUE); 133 if (auto *CI = dyn_cast<ConstantInt>(&C)) { 134 if (CI->getBitWidth() > 64) 135 MIB.addCImm(CI); 136 else 137 MIB.addImm(CI->getZExtValue()); 138 } else if (auto *CFP = dyn_cast<ConstantFP>(&C)) { 139 MIB.addFPImm(CFP); 140 } else { 141 // Insert %noreg if we didn't find a usable constant and had to drop it. 142 MIB.addReg(0U); 143 } 144 145 return MIB.addImm(0).addMetadata(Variable).addMetadata(Expr); 146 } 147 148 MachineInstrBuilder MachineIRBuilderBase::buildFrameIndex(unsigned Res, 149 int Idx) { 150 assert(getMRI()->getType(Res).isPointer() && "invalid operand type"); 151 return buildInstr(TargetOpcode::G_FRAME_INDEX) 152 .addDef(Res) 153 .addFrameIndex(Idx); 154 } 155 156 MachineInstrBuilder 157 MachineIRBuilderBase::buildGlobalValue(unsigned Res, const GlobalValue *GV) { 158 assert(getMRI()->getType(Res).isPointer() && "invalid operand type"); 159 assert(getMRI()->getType(Res).getAddressSpace() == 160 GV->getType()->getAddressSpace() && 161 "address space mismatch"); 162 163 return buildInstr(TargetOpcode::G_GLOBAL_VALUE) 164 .addDef(Res) 165 .addGlobalAddress(GV); 166 } 167 168 void MachineIRBuilderBase::validateBinaryOp(unsigned Res, unsigned Op0, 169 unsigned Op1) { 170 assert((getMRI()->getType(Res).isScalar() || 171 getMRI()->getType(Res).isVector()) && 172 "invalid operand type"); 173 assert(getMRI()->getType(Res) == getMRI()->getType(Op0) && 174 getMRI()->getType(Res) == getMRI()->getType(Op1) && "type mismatch"); 175 } 176 177 MachineInstrBuilder MachineIRBuilderBase::buildGEP(unsigned Res, unsigned Op0, 178 unsigned Op1) { 179 assert(getMRI()->getType(Res).isPointer() && 180 getMRI()->getType(Res) == getMRI()->getType(Op0) && "type mismatch"); 181 assert(getMRI()->getType(Op1).isScalar() && "invalid offset type"); 182 183 return buildInstr(TargetOpcode::G_GEP) 184 .addDef(Res) 185 .addUse(Op0) 186 .addUse(Op1); 187 } 188 189 Optional<MachineInstrBuilder> 190 MachineIRBuilderBase::materializeGEP(unsigned &Res, unsigned Op0, 191 const LLT &ValueTy, uint64_t Value) { 192 assert(Res == 0 && "Res is a result argument"); 193 assert(ValueTy.isScalar() && "invalid offset type"); 194 195 if (Value == 0) { 196 Res = Op0; 197 return None; 198 } 199 200 Res = getMRI()->createGenericVirtualRegister(getMRI()->getType(Op0)); 201 unsigned TmpReg = getMRI()->createGenericVirtualRegister(ValueTy); 202 203 buildConstant(TmpReg, Value); 204 return buildGEP(Res, Op0, TmpReg); 205 } 206 207 MachineInstrBuilder MachineIRBuilderBase::buildPtrMask(unsigned Res, 208 unsigned Op0, 209 uint32_t NumBits) { 210 assert(getMRI()->getType(Res).isPointer() && 211 getMRI()->getType(Res) == getMRI()->getType(Op0) && "type mismatch"); 212 213 return buildInstr(TargetOpcode::G_PTR_MASK) 214 .addDef(Res) 215 .addUse(Op0) 216 .addImm(NumBits); 217 } 218 219 MachineInstrBuilder MachineIRBuilderBase::buildBr(MachineBasicBlock &Dest) { 220 return buildInstr(TargetOpcode::G_BR).addMBB(&Dest); 221 } 222 223 MachineInstrBuilder MachineIRBuilderBase::buildBrIndirect(unsigned Tgt) { 224 assert(getMRI()->getType(Tgt).isPointer() && "invalid branch destination"); 225 return buildInstr(TargetOpcode::G_BRINDIRECT).addUse(Tgt); 226 } 227 228 MachineInstrBuilder MachineIRBuilderBase::buildCopy(unsigned Res, unsigned Op) { 229 assert(getMRI()->getType(Res) == LLT() || getMRI()->getType(Op) == LLT() || 230 getMRI()->getType(Res) == getMRI()->getType(Op)); 231 return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op); 232 } 233 234 MachineInstrBuilder 235 MachineIRBuilderBase::buildConstant(unsigned Res, const ConstantInt &Val) { 236 LLT Ty = getMRI()->getType(Res); 237 238 assert((Ty.isScalar() || Ty.isPointer()) && "invalid operand type"); 239 240 const ConstantInt *NewVal = &Val; 241 if (Ty.getSizeInBits() != Val.getBitWidth()) 242 NewVal = ConstantInt::get(getMF().getFunction().getContext(), 243 Val.getValue().sextOrTrunc(Ty.getSizeInBits())); 244 245 return buildInstr(TargetOpcode::G_CONSTANT).addDef(Res).addCImm(NewVal); 246 } 247 248 MachineInstrBuilder MachineIRBuilderBase::buildConstant(unsigned Res, 249 int64_t Val) { 250 auto IntN = IntegerType::get(getMF().getFunction().getContext(), 251 getMRI()->getType(Res).getSizeInBits()); 252 ConstantInt *CI = ConstantInt::get(IntN, Val, true); 253 return buildConstant(Res, *CI); 254 } 255 256 MachineInstrBuilder 257 MachineIRBuilderBase::buildFConstant(unsigned Res, const ConstantFP &Val) { 258 assert(getMRI()->getType(Res).isScalar() && "invalid operand type"); 259 260 return buildInstr(TargetOpcode::G_FCONSTANT).addDef(Res).addFPImm(&Val); 261 } 262 263 MachineInstrBuilder MachineIRBuilderBase::buildFConstant(unsigned Res, 264 double Val) { 265 LLT DstTy = getMRI()->getType(Res); 266 auto &Ctx = getMF().getFunction().getContext(); 267 auto *CFP = 268 ConstantFP::get(Ctx, getAPFloatFromSize(Val, DstTy.getSizeInBits())); 269 return buildFConstant(Res, *CFP); 270 } 271 272 MachineInstrBuilder MachineIRBuilderBase::buildBrCond(unsigned Tst, 273 MachineBasicBlock &Dest) { 274 assert(getMRI()->getType(Tst).isScalar() && "invalid operand type"); 275 276 return buildInstr(TargetOpcode::G_BRCOND).addUse(Tst).addMBB(&Dest); 277 } 278 279 MachineInstrBuilder MachineIRBuilderBase::buildLoad(unsigned Res, unsigned Addr, 280 MachineMemOperand &MMO) { 281 return buildLoadInstr(TargetOpcode::G_LOAD, Res, Addr, MMO); 282 } 283 284 MachineInstrBuilder 285 MachineIRBuilderBase::buildLoadInstr(unsigned Opcode, unsigned Res, 286 unsigned Addr, MachineMemOperand &MMO) { 287 assert(getMRI()->getType(Res).isValid() && "invalid operand type"); 288 assert(getMRI()->getType(Addr).isPointer() && "invalid operand type"); 289 290 return buildInstr(Opcode) 291 .addDef(Res) 292 .addUse(Addr) 293 .addMemOperand(&MMO); 294 } 295 296 MachineInstrBuilder MachineIRBuilderBase::buildStore(unsigned Val, 297 unsigned Addr, 298 MachineMemOperand &MMO) { 299 assert(getMRI()->getType(Val).isValid() && "invalid operand type"); 300 assert(getMRI()->getType(Addr).isPointer() && "invalid operand type"); 301 302 return buildInstr(TargetOpcode::G_STORE) 303 .addUse(Val) 304 .addUse(Addr) 305 .addMemOperand(&MMO); 306 } 307 308 MachineInstrBuilder MachineIRBuilderBase::buildUAdde(unsigned Res, 309 unsigned CarryOut, 310 unsigned Op0, unsigned Op1, 311 unsigned CarryIn) { 312 assert(getMRI()->getType(Res).isScalar() && "invalid operand type"); 313 assert(getMRI()->getType(Res) == getMRI()->getType(Op0) && 314 getMRI()->getType(Res) == getMRI()->getType(Op1) && "type mismatch"); 315 assert(getMRI()->getType(CarryOut).isScalar() && "invalid operand type"); 316 assert(getMRI()->getType(CarryOut) == getMRI()->getType(CarryIn) && 317 "type mismatch"); 318 319 return buildInstr(TargetOpcode::G_UADDE) 320 .addDef(Res) 321 .addDef(CarryOut) 322 .addUse(Op0) 323 .addUse(Op1) 324 .addUse(CarryIn); 325 } 326 327 MachineInstrBuilder MachineIRBuilderBase::buildAnyExt(unsigned Res, 328 unsigned Op) { 329 validateTruncExt(Res, Op, true); 330 return buildInstr(TargetOpcode::G_ANYEXT).addDef(Res).addUse(Op); 331 } 332 333 MachineInstrBuilder MachineIRBuilderBase::buildSExt(unsigned Res, unsigned Op) { 334 validateTruncExt(Res, Op, true); 335 return buildInstr(TargetOpcode::G_SEXT).addDef(Res).addUse(Op); 336 } 337 338 MachineInstrBuilder MachineIRBuilderBase::buildZExt(unsigned Res, unsigned Op) { 339 validateTruncExt(Res, Op, true); 340 return buildInstr(TargetOpcode::G_ZEXT).addDef(Res).addUse(Op); 341 } 342 343 MachineInstrBuilder MachineIRBuilderBase::buildExtOrTrunc(unsigned ExtOpc, 344 unsigned Res, 345 unsigned Op) { 346 assert((TargetOpcode::G_ANYEXT == ExtOpc || TargetOpcode::G_ZEXT == ExtOpc || 347 TargetOpcode::G_SEXT == ExtOpc) && 348 "Expecting Extending Opc"); 349 assert(getMRI()->getType(Res).isScalar() || 350 getMRI()->getType(Res).isVector()); 351 assert(getMRI()->getType(Res).isScalar() == getMRI()->getType(Op).isScalar()); 352 353 unsigned Opcode = TargetOpcode::COPY; 354 if (getMRI()->getType(Res).getSizeInBits() > 355 getMRI()->getType(Op).getSizeInBits()) 356 Opcode = ExtOpc; 357 else if (getMRI()->getType(Res).getSizeInBits() < 358 getMRI()->getType(Op).getSizeInBits()) 359 Opcode = TargetOpcode::G_TRUNC; 360 else 361 assert(getMRI()->getType(Res) == getMRI()->getType(Op)); 362 363 return buildInstr(Opcode).addDef(Res).addUse(Op); 364 } 365 366 MachineInstrBuilder MachineIRBuilderBase::buildSExtOrTrunc(unsigned Res, 367 unsigned Op) { 368 return buildExtOrTrunc(TargetOpcode::G_SEXT, Res, Op); 369 } 370 371 MachineInstrBuilder MachineIRBuilderBase::buildZExtOrTrunc(unsigned Res, 372 unsigned Op) { 373 return buildExtOrTrunc(TargetOpcode::G_ZEXT, Res, Op); 374 } 375 376 MachineInstrBuilder MachineIRBuilderBase::buildAnyExtOrTrunc(unsigned Res, 377 unsigned Op) { 378 return buildExtOrTrunc(TargetOpcode::G_ANYEXT, Res, Op); 379 } 380 381 MachineInstrBuilder MachineIRBuilderBase::buildCast(unsigned Dst, 382 unsigned Src) { 383 LLT SrcTy = getMRI()->getType(Src); 384 LLT DstTy = getMRI()->getType(Dst); 385 if (SrcTy == DstTy) 386 return buildCopy(Dst, Src); 387 388 unsigned Opcode; 389 if (SrcTy.isPointer() && DstTy.isScalar()) 390 Opcode = TargetOpcode::G_PTRTOINT; 391 else if (DstTy.isPointer() && SrcTy.isScalar()) 392 Opcode = TargetOpcode::G_INTTOPTR; 393 else { 394 assert(!SrcTy.isPointer() && !DstTy.isPointer() && "n G_ADDRCAST yet"); 395 Opcode = TargetOpcode::G_BITCAST; 396 } 397 398 return buildInstr(Opcode).addDef(Dst).addUse(Src); 399 } 400 401 MachineInstrBuilder 402 MachineIRBuilderBase::buildExtract(unsigned Res, unsigned Src, uint64_t Index) { 403 #ifndef NDEBUG 404 assert(getMRI()->getType(Src).isValid() && "invalid operand type"); 405 assert(getMRI()->getType(Res).isValid() && "invalid operand type"); 406 assert(Index + getMRI()->getType(Res).getSizeInBits() <= 407 getMRI()->getType(Src).getSizeInBits() && 408 "extracting off end of register"); 409 #endif 410 411 if (getMRI()->getType(Res).getSizeInBits() == 412 getMRI()->getType(Src).getSizeInBits()) { 413 assert(Index == 0 && "insertion past the end of a register"); 414 return buildCast(Res, Src); 415 } 416 417 return buildInstr(TargetOpcode::G_EXTRACT) 418 .addDef(Res) 419 .addUse(Src) 420 .addImm(Index); 421 } 422 423 void MachineIRBuilderBase::buildSequence(unsigned Res, ArrayRef<unsigned> Ops, 424 ArrayRef<uint64_t> Indices) { 425 #ifndef NDEBUG 426 assert(Ops.size() == Indices.size() && "incompatible args"); 427 assert(!Ops.empty() && "invalid trivial sequence"); 428 assert(std::is_sorted(Indices.begin(), Indices.end()) && 429 "sequence offsets must be in ascending order"); 430 431 assert(getMRI()->getType(Res).isValid() && "invalid operand type"); 432 for (auto Op : Ops) 433 assert(getMRI()->getType(Op).isValid() && "invalid operand type"); 434 #endif 435 436 LLT ResTy = getMRI()->getType(Res); 437 LLT OpTy = getMRI()->getType(Ops[0]); 438 unsigned OpSize = OpTy.getSizeInBits(); 439 bool MaybeMerge = true; 440 for (unsigned i = 0; i < Ops.size(); ++i) { 441 if (getMRI()->getType(Ops[i]) != OpTy || Indices[i] != i * OpSize) { 442 MaybeMerge = false; 443 break; 444 } 445 } 446 447 if (MaybeMerge && Ops.size() * OpSize == ResTy.getSizeInBits()) { 448 buildMerge(Res, Ops); 449 return; 450 } 451 452 unsigned ResIn = getMRI()->createGenericVirtualRegister(ResTy); 453 buildUndef(ResIn); 454 455 for (unsigned i = 0; i < Ops.size(); ++i) { 456 unsigned ResOut = i + 1 == Ops.size() 457 ? Res 458 : getMRI()->createGenericVirtualRegister(ResTy); 459 buildInsert(ResOut, ResIn, Ops[i], Indices[i]); 460 ResIn = ResOut; 461 } 462 } 463 464 MachineInstrBuilder MachineIRBuilderBase::buildUndef(unsigned Res) { 465 return buildInstr(TargetOpcode::G_IMPLICIT_DEF).addDef(Res); 466 } 467 468 MachineInstrBuilder MachineIRBuilderBase::buildMerge(unsigned Res, 469 ArrayRef<unsigned> Ops) { 470 471 #ifndef NDEBUG 472 assert(!Ops.empty() && "invalid trivial sequence"); 473 LLT Ty = getMRI()->getType(Ops[0]); 474 for (auto Reg : Ops) 475 assert(getMRI()->getType(Reg) == Ty && "type mismatch in input list"); 476 assert(Ops.size() * getMRI()->getType(Ops[0]).getSizeInBits() == 477 getMRI()->getType(Res).getSizeInBits() && 478 "input operands do not cover output register"); 479 #endif 480 481 if (Ops.size() == 1) 482 return buildCast(Res, Ops[0]); 483 484 MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_MERGE_VALUES); 485 MIB.addDef(Res); 486 for (unsigned i = 0; i < Ops.size(); ++i) 487 MIB.addUse(Ops[i]); 488 return MIB; 489 } 490 491 MachineInstrBuilder MachineIRBuilderBase::buildUnmerge(ArrayRef<unsigned> Res, 492 unsigned Op) { 493 494 #ifndef NDEBUG 495 assert(!Res.empty() && "invalid trivial sequence"); 496 LLT Ty = getMRI()->getType(Res[0]); 497 for (auto Reg : Res) 498 assert(getMRI()->getType(Reg) == Ty && "type mismatch in input list"); 499 assert(Res.size() * getMRI()->getType(Res[0]).getSizeInBits() == 500 getMRI()->getType(Op).getSizeInBits() && 501 "input operands do not cover output register"); 502 #endif 503 504 MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_UNMERGE_VALUES); 505 for (unsigned i = 0; i < Res.size(); ++i) 506 MIB.addDef(Res[i]); 507 MIB.addUse(Op); 508 return MIB; 509 } 510 511 MachineInstrBuilder MachineIRBuilderBase::buildInsert(unsigned Res, 512 unsigned Src, unsigned Op, 513 unsigned Index) { 514 assert(Index + getMRI()->getType(Op).getSizeInBits() <= 515 getMRI()->getType(Res).getSizeInBits() && 516 "insertion past the end of a register"); 517 518 if (getMRI()->getType(Res).getSizeInBits() == 519 getMRI()->getType(Op).getSizeInBits()) { 520 return buildCast(Res, Op); 521 } 522 523 return buildInstr(TargetOpcode::G_INSERT) 524 .addDef(Res) 525 .addUse(Src) 526 .addUse(Op) 527 .addImm(Index); 528 } 529 530 MachineInstrBuilder MachineIRBuilderBase::buildIntrinsic(Intrinsic::ID ID, 531 unsigned Res, 532 bool HasSideEffects) { 533 auto MIB = 534 buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS 535 : TargetOpcode::G_INTRINSIC); 536 if (Res) 537 MIB.addDef(Res); 538 MIB.addIntrinsicID(ID); 539 return MIB; 540 } 541 542 MachineInstrBuilder MachineIRBuilderBase::buildTrunc(unsigned Res, 543 unsigned Op) { 544 validateTruncExt(Res, Op, false); 545 return buildInstr(TargetOpcode::G_TRUNC).addDef(Res).addUse(Op); 546 } 547 548 MachineInstrBuilder MachineIRBuilderBase::buildFPTrunc(unsigned Res, 549 unsigned Op) { 550 validateTruncExt(Res, Op, false); 551 return buildInstr(TargetOpcode::G_FPTRUNC).addDef(Res).addUse(Op); 552 } 553 554 MachineInstrBuilder MachineIRBuilderBase::buildICmp(CmpInst::Predicate Pred, 555 unsigned Res, unsigned Op0, 556 unsigned Op1) { 557 #ifndef NDEBUG 558 assert(getMRI()->getType(Op0) == getMRI()->getType(Op0) && "type mismatch"); 559 assert(CmpInst::isIntPredicate(Pred) && "invalid predicate"); 560 if (getMRI()->getType(Op0).isScalar() || getMRI()->getType(Op0).isPointer()) 561 assert(getMRI()->getType(Res).isScalar() && "type mismatch"); 562 else 563 assert(getMRI()->getType(Res).isVector() && 564 getMRI()->getType(Res).getNumElements() == 565 getMRI()->getType(Op0).getNumElements() && 566 "type mismatch"); 567 #endif 568 569 return buildInstr(TargetOpcode::G_ICMP) 570 .addDef(Res) 571 .addPredicate(Pred) 572 .addUse(Op0) 573 .addUse(Op1); 574 } 575 576 MachineInstrBuilder MachineIRBuilderBase::buildFCmp(CmpInst::Predicate Pred, 577 unsigned Res, unsigned Op0, 578 unsigned Op1) { 579 #ifndef NDEBUG 580 assert((getMRI()->getType(Op0).isScalar() || 581 getMRI()->getType(Op0).isVector()) && 582 "invalid operand type"); 583 assert(getMRI()->getType(Op0) == getMRI()->getType(Op1) && "type mismatch"); 584 assert(CmpInst::isFPPredicate(Pred) && "invalid predicate"); 585 if (getMRI()->getType(Op0).isScalar()) 586 assert(getMRI()->getType(Res).isScalar() && "type mismatch"); 587 else 588 assert(getMRI()->getType(Res).isVector() && 589 getMRI()->getType(Res).getNumElements() == 590 getMRI()->getType(Op0).getNumElements() && 591 "type mismatch"); 592 #endif 593 594 return buildInstr(TargetOpcode::G_FCMP) 595 .addDef(Res) 596 .addPredicate(Pred) 597 .addUse(Op0) 598 .addUse(Op1); 599 } 600 601 MachineInstrBuilder MachineIRBuilderBase::buildSelect(unsigned Res, 602 unsigned Tst, 603 unsigned Op0, 604 unsigned Op1) { 605 #ifndef NDEBUG 606 LLT ResTy = getMRI()->getType(Res); 607 assert((ResTy.isScalar() || ResTy.isVector() || ResTy.isPointer()) && 608 "invalid operand type"); 609 assert(ResTy == getMRI()->getType(Op0) && ResTy == getMRI()->getType(Op1) && 610 "type mismatch"); 611 if (ResTy.isScalar() || ResTy.isPointer()) 612 assert(getMRI()->getType(Tst).isScalar() && "type mismatch"); 613 else 614 assert((getMRI()->getType(Tst).isScalar() || 615 (getMRI()->getType(Tst).isVector() && 616 getMRI()->getType(Tst).getNumElements() == 617 getMRI()->getType(Op0).getNumElements())) && 618 "type mismatch"); 619 #endif 620 621 return buildInstr(TargetOpcode::G_SELECT) 622 .addDef(Res) 623 .addUse(Tst) 624 .addUse(Op0) 625 .addUse(Op1); 626 } 627 628 MachineInstrBuilder 629 MachineIRBuilderBase::buildInsertVectorElement(unsigned Res, unsigned Val, 630 unsigned Elt, unsigned Idx) { 631 #ifndef NDEBUG 632 LLT ResTy = getMRI()->getType(Res); 633 LLT ValTy = getMRI()->getType(Val); 634 LLT EltTy = getMRI()->getType(Elt); 635 LLT IdxTy = getMRI()->getType(Idx); 636 assert(ResTy.isVector() && ValTy.isVector() && "invalid operand type"); 637 assert(IdxTy.isScalar() && "invalid operand type"); 638 assert(ResTy.getNumElements() == ValTy.getNumElements() && "type mismatch"); 639 assert(ResTy.getElementType() == EltTy && "type mismatch"); 640 #endif 641 642 return buildInstr(TargetOpcode::G_INSERT_VECTOR_ELT) 643 .addDef(Res) 644 .addUse(Val) 645 .addUse(Elt) 646 .addUse(Idx); 647 } 648 649 MachineInstrBuilder 650 MachineIRBuilderBase::buildExtractVectorElement(unsigned Res, unsigned Val, 651 unsigned Idx) { 652 #ifndef NDEBUG 653 LLT ResTy = getMRI()->getType(Res); 654 LLT ValTy = getMRI()->getType(Val); 655 LLT IdxTy = getMRI()->getType(Idx); 656 assert(ValTy.isVector() && "invalid operand type"); 657 assert((ResTy.isScalar() || ResTy.isPointer()) && "invalid operand type"); 658 assert(IdxTy.isScalar() && "invalid operand type"); 659 assert(ValTy.getElementType() == ResTy && "type mismatch"); 660 #endif 661 662 return buildInstr(TargetOpcode::G_EXTRACT_VECTOR_ELT) 663 .addDef(Res) 664 .addUse(Val) 665 .addUse(Idx); 666 } 667 668 MachineInstrBuilder 669 MachineIRBuilderBase::buildAtomicCmpXchg(unsigned OldValRes, unsigned Addr, 670 unsigned CmpVal, unsigned NewVal, 671 MachineMemOperand &MMO) { 672 #ifndef NDEBUG 673 LLT OldValResTy = getMRI()->getType(OldValRes); 674 LLT AddrTy = getMRI()->getType(Addr); 675 LLT CmpValTy = getMRI()->getType(CmpVal); 676 LLT NewValTy = getMRI()->getType(NewVal); 677 assert(OldValResTy.isScalar() && "invalid operand type"); 678 assert(AddrTy.isPointer() && "invalid operand type"); 679 assert(CmpValTy.isValid() && "invalid operand type"); 680 assert(NewValTy.isValid() && "invalid operand type"); 681 assert(OldValResTy == CmpValTy && "type mismatch"); 682 assert(OldValResTy == NewValTy && "type mismatch"); 683 #endif 684 685 return buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG) 686 .addDef(OldValRes) 687 .addUse(Addr) 688 .addUse(CmpVal) 689 .addUse(NewVal) 690 .addMemOperand(&MMO); 691 } 692 693 void MachineIRBuilderBase::validateTruncExt(unsigned Dst, unsigned Src, 694 bool IsExtend) { 695 #ifndef NDEBUG 696 LLT SrcTy = getMRI()->getType(Src); 697 LLT DstTy = getMRI()->getType(Dst); 698 699 if (DstTy.isVector()) { 700 assert(SrcTy.isVector() && "mismatched cast between vecot and non-vector"); 701 assert(SrcTy.getNumElements() == DstTy.getNumElements() && 702 "different number of elements in a trunc/ext"); 703 } else 704 assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc"); 705 706 if (IsExtend) 707 assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() && 708 "invalid narrowing extend"); 709 else 710 assert(DstTy.getSizeInBits() < SrcTy.getSizeInBits() && 711 "invalid widening trunc"); 712 #endif 713 } 714