xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===-- llvm/CodeGen/GlobalISel/MachineIRBuilder.cpp - MIBuilder--*- C++ -*-==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric /// This file implements the MachineIRBuidler class.
100b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
110b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
120b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
140b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
2081ad6265SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric void MachineIRBuilder::setMF(MachineFunction &MF) {
250b57cec5SDimitry Andric   State.MF = &MF;
260b57cec5SDimitry Andric   State.MBB = nullptr;
270b57cec5SDimitry Andric   State.MRI = &MF.getRegInfo();
280b57cec5SDimitry Andric   State.TII = MF.getSubtarget().getInstrInfo();
290b57cec5SDimitry Andric   State.DL = DebugLoc();
30*bdd1243dSDimitry Andric   State.PCSections = nullptr;
310b57cec5SDimitry Andric   State.II = MachineBasicBlock::iterator();
320b57cec5SDimitry Andric   State.Observer = nullptr;
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric //------------------------------------------------------------------------------
360b57cec5SDimitry Andric // Build instruction variants.
370b57cec5SDimitry Andric //------------------------------------------------------------------------------
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildInstrNoInsert(unsigned Opcode) {
40*bdd1243dSDimitry Andric   return BuildMI(getMF(), {getDL(), getPCSections()}, getTII().get(Opcode));
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::insertInstr(MachineInstrBuilder MIB) {
440b57cec5SDimitry Andric   getMBB().insert(getInsertPt(), MIB);
450b57cec5SDimitry Andric   recordInsertion(MIB);
460b57cec5SDimitry Andric   return MIB;
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric MachineInstrBuilder
500b57cec5SDimitry Andric MachineIRBuilder::buildDirectDbgValue(Register Reg, const MDNode *Variable,
510b57cec5SDimitry Andric                                       const MDNode *Expr) {
520b57cec5SDimitry Andric   assert(isa<DILocalVariable>(Variable) && "not a variable");
530b57cec5SDimitry Andric   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
540b57cec5SDimitry Andric   assert(
550b57cec5SDimitry Andric       cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
560b57cec5SDimitry Andric       "Expected inlined-at fields to agree");
570b57cec5SDimitry Andric   return insertInstr(BuildMI(getMF(), getDL(),
580b57cec5SDimitry Andric                              getTII().get(TargetOpcode::DBG_VALUE),
590b57cec5SDimitry Andric                              /*IsIndirect*/ false, Reg, Variable, Expr));
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric MachineInstrBuilder
630b57cec5SDimitry Andric MachineIRBuilder::buildIndirectDbgValue(Register Reg, const MDNode *Variable,
640b57cec5SDimitry Andric                                         const MDNode *Expr) {
650b57cec5SDimitry Andric   assert(isa<DILocalVariable>(Variable) && "not a variable");
660b57cec5SDimitry Andric   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
670b57cec5SDimitry Andric   assert(
680b57cec5SDimitry Andric       cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
690b57cec5SDimitry Andric       "Expected inlined-at fields to agree");
700b57cec5SDimitry Andric   return insertInstr(BuildMI(getMF(), getDL(),
710b57cec5SDimitry Andric                              getTII().get(TargetOpcode::DBG_VALUE),
7213138422SDimitry Andric                              /*IsIndirect*/ true, Reg, Variable, Expr));
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFIDbgValue(int FI,
760b57cec5SDimitry Andric                                                       const MDNode *Variable,
770b57cec5SDimitry Andric                                                       const MDNode *Expr) {
780b57cec5SDimitry Andric   assert(isa<DILocalVariable>(Variable) && "not a variable");
790b57cec5SDimitry Andric   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
800b57cec5SDimitry Andric   assert(
810b57cec5SDimitry Andric       cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
820b57cec5SDimitry Andric       "Expected inlined-at fields to agree");
830b57cec5SDimitry Andric   return buildInstr(TargetOpcode::DBG_VALUE)
840b57cec5SDimitry Andric       .addFrameIndex(FI)
8513138422SDimitry Andric       .addImm(0)
860b57cec5SDimitry Andric       .addMetadata(Variable)
8713138422SDimitry Andric       .addMetadata(Expr);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstDbgValue(const Constant &C,
910b57cec5SDimitry Andric                                                          const MDNode *Variable,
920b57cec5SDimitry Andric                                                          const MDNode *Expr) {
930b57cec5SDimitry Andric   assert(isa<DILocalVariable>(Variable) && "not a variable");
940b57cec5SDimitry Andric   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
950b57cec5SDimitry Andric   assert(
960b57cec5SDimitry Andric       cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
970b57cec5SDimitry Andric       "Expected inlined-at fields to agree");
985ffd83dbSDimitry Andric   auto MIB = buildInstrNoInsert(TargetOpcode::DBG_VALUE);
99*bdd1243dSDimitry Andric 
100*bdd1243dSDimitry Andric   auto *NumericConstant = [&] () -> const Constant* {
101*bdd1243dSDimitry Andric     if (const auto *CE = dyn_cast<ConstantExpr>(&C))
102*bdd1243dSDimitry Andric       if (CE->getOpcode() == Instruction::IntToPtr)
103*bdd1243dSDimitry Andric         return CE->getOperand(0);
104*bdd1243dSDimitry Andric     return &C;
105*bdd1243dSDimitry Andric   }();
106*bdd1243dSDimitry Andric 
107*bdd1243dSDimitry Andric   if (auto *CI = dyn_cast<ConstantInt>(NumericConstant)) {
1080b57cec5SDimitry Andric     if (CI->getBitWidth() > 64)
1090b57cec5SDimitry Andric       MIB.addCImm(CI);
1100b57cec5SDimitry Andric     else
1110b57cec5SDimitry Andric       MIB.addImm(CI->getZExtValue());
112*bdd1243dSDimitry Andric   } else if (auto *CFP = dyn_cast<ConstantFP>(NumericConstant)) {
1130b57cec5SDimitry Andric     MIB.addFPImm(CFP);
114*bdd1243dSDimitry Andric   } else if (isa<ConstantPointerNull>(NumericConstant)) {
115*bdd1243dSDimitry Andric     MIB.addImm(0);
1160b57cec5SDimitry Andric   } else {
117e8d8bef9SDimitry Andric     // Insert $noreg if we didn't find a usable constant and had to drop it.
118e8d8bef9SDimitry Andric     MIB.addReg(Register());
1190b57cec5SDimitry Andric   }
1200b57cec5SDimitry Andric 
1215ffd83dbSDimitry Andric   MIB.addImm(0).addMetadata(Variable).addMetadata(Expr);
1225ffd83dbSDimitry Andric   return insertInstr(MIB);
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildDbgLabel(const MDNode *Label) {
1260b57cec5SDimitry Andric   assert(isa<DILabel>(Label) && "not a label");
1270b57cec5SDimitry Andric   assert(cast<DILabel>(Label)->isValidLocationForIntrinsic(State.DL) &&
1280b57cec5SDimitry Andric          "Expected inlined-at fields to agree");
1290b57cec5SDimitry Andric   auto MIB = buildInstr(TargetOpcode::DBG_LABEL);
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   return MIB.addMetadata(Label);
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1348bcb0991SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildDynStackAlloc(const DstOp &Res,
1358bcb0991SDimitry Andric                                                          const SrcOp &Size,
1365ffd83dbSDimitry Andric                                                          Align Alignment) {
1378bcb0991SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isPointer() && "expected ptr dst type");
1388bcb0991SDimitry Andric   auto MIB = buildInstr(TargetOpcode::G_DYN_STACKALLOC);
1398bcb0991SDimitry Andric   Res.addDefToMIB(*getMRI(), MIB);
1408bcb0991SDimitry Andric   Size.addSrcToMIB(MIB);
1415ffd83dbSDimitry Andric   MIB.addImm(Alignment.value());
1428bcb0991SDimitry Andric   return MIB;
1438bcb0991SDimitry Andric }
1448bcb0991SDimitry Andric 
1450b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFrameIndex(const DstOp &Res,
1460b57cec5SDimitry Andric                                                       int Idx) {
1470b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
1480b57cec5SDimitry Andric   auto MIB = buildInstr(TargetOpcode::G_FRAME_INDEX);
1490b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), MIB);
1500b57cec5SDimitry Andric   MIB.addFrameIndex(Idx);
1510b57cec5SDimitry Andric   return MIB;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildGlobalValue(const DstOp &Res,
1550b57cec5SDimitry Andric                                                        const GlobalValue *GV) {
1560b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
1570b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).getAddressSpace() ==
1580b57cec5SDimitry Andric              GV->getType()->getAddressSpace() &&
1590b57cec5SDimitry Andric          "address space mismatch");
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   auto MIB = buildInstr(TargetOpcode::G_GLOBAL_VALUE);
1620b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), MIB);
1630b57cec5SDimitry Andric   MIB.addGlobalAddress(GV);
1640b57cec5SDimitry Andric   return MIB;
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildJumpTable(const LLT PtrTy,
1680b57cec5SDimitry Andric                                                      unsigned JTI) {
1690b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_JUMP_TABLE, {PtrTy}, {})
1700b57cec5SDimitry Andric       .addJumpTableIndex(JTI);
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
173e8d8bef9SDimitry Andric void MachineIRBuilder::validateUnaryOp(const LLT Res, const LLT Op0) {
174e8d8bef9SDimitry Andric   assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
175e8d8bef9SDimitry Andric   assert((Res == Op0) && "type mismatch");
176e8d8bef9SDimitry Andric }
177e8d8bef9SDimitry Andric 
1785ffd83dbSDimitry Andric void MachineIRBuilder::validateBinaryOp(const LLT Res, const LLT Op0,
1795ffd83dbSDimitry Andric                                         const LLT Op1) {
1800b57cec5SDimitry Andric   assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
1810b57cec5SDimitry Andric   assert((Res == Op0 && Res == Op1) && "type mismatch");
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
1845ffd83dbSDimitry Andric void MachineIRBuilder::validateShiftOp(const LLT Res, const LLT Op0,
1855ffd83dbSDimitry Andric                                        const LLT Op1) {
1860b57cec5SDimitry Andric   assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
1870b57cec5SDimitry Andric   assert((Res == Op0) && "type mismatch");
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
190480093f4SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildPtrAdd(const DstOp &Res,
1910b57cec5SDimitry Andric                                                   const SrcOp &Op0,
1920b57cec5SDimitry Andric                                                   const SrcOp &Op1) {
1935ffd83dbSDimitry Andric   assert(Res.getLLTTy(*getMRI()).getScalarType().isPointer() &&
1940b57cec5SDimitry Andric          Res.getLLTTy(*getMRI()) == Op0.getLLTTy(*getMRI()) && "type mismatch");
1955ffd83dbSDimitry Andric   assert(Op1.getLLTTy(*getMRI()).getScalarType().isScalar() && "invalid offset type");
1960b57cec5SDimitry Andric 
197480093f4SDimitry Andric   return buildInstr(TargetOpcode::G_PTR_ADD, {Res}, {Op0, Op1});
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric 
200*bdd1243dSDimitry Andric std::optional<MachineInstrBuilder>
201480093f4SDimitry Andric MachineIRBuilder::materializePtrAdd(Register &Res, Register Op0,
2025ffd83dbSDimitry Andric                                     const LLT ValueTy, uint64_t Value) {
2030b57cec5SDimitry Andric   assert(Res == 0 && "Res is a result argument");
2040b57cec5SDimitry Andric   assert(ValueTy.isScalar()  && "invalid offset type");
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   if (Value == 0) {
2070b57cec5SDimitry Andric     Res = Op0;
208*bdd1243dSDimitry Andric     return std::nullopt;
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   Res = getMRI()->createGenericVirtualRegister(getMRI()->getType(Op0));
2120b57cec5SDimitry Andric   auto Cst = buildConstant(ValueTy, Value);
213480093f4SDimitry Andric   return buildPtrAdd(Res, Op0, Cst.getReg(0));
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2165ffd83dbSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildMaskLowPtrBits(const DstOp &Res,
2170b57cec5SDimitry Andric                                                           const SrcOp &Op0,
2180b57cec5SDimitry Andric                                                           uint32_t NumBits) {
2195ffd83dbSDimitry Andric   LLT PtrTy = Res.getLLTTy(*getMRI());
2205ffd83dbSDimitry Andric   LLT MaskTy = LLT::scalar(PtrTy.getSizeInBits());
2215ffd83dbSDimitry Andric   Register MaskReg = getMRI()->createGenericVirtualRegister(MaskTy);
2225ffd83dbSDimitry Andric   buildConstant(MaskReg, maskTrailingZeros<uint64_t>(NumBits));
2235ffd83dbSDimitry Andric   return buildPtrMask(Res, Op0, MaskReg);
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric 
2260eae32dcSDimitry Andric MachineInstrBuilder
2270eae32dcSDimitry Andric MachineIRBuilder::buildPadVectorWithUndefElements(const DstOp &Res,
2280eae32dcSDimitry Andric                                                   const SrcOp &Op0) {
2290eae32dcSDimitry Andric   LLT ResTy = Res.getLLTTy(*getMRI());
2300eae32dcSDimitry Andric   LLT Op0Ty = Op0.getLLTTy(*getMRI());
2310eae32dcSDimitry Andric 
2320eae32dcSDimitry Andric   assert((ResTy.isVector() && Op0Ty.isVector()) && "Non vector type");
2330eae32dcSDimitry Andric   assert((ResTy.getElementType() == Op0Ty.getElementType()) &&
2340eae32dcSDimitry Andric          "Different vector element types");
2350eae32dcSDimitry Andric   assert((ResTy.getNumElements() > Op0Ty.getNumElements()) &&
2360eae32dcSDimitry Andric          "Op0 has more elements");
2370eae32dcSDimitry Andric 
2380eae32dcSDimitry Andric   auto Unmerge = buildUnmerge(Op0Ty.getElementType(), Op0);
2390eae32dcSDimitry Andric   SmallVector<Register, 8> Regs;
2400eae32dcSDimitry Andric   for (auto Op : Unmerge.getInstr()->defs())
2410eae32dcSDimitry Andric     Regs.push_back(Op.getReg());
2420eae32dcSDimitry Andric   Register Undef = buildUndef(Op0Ty.getElementType()).getReg(0);
2430eae32dcSDimitry Andric   unsigned NumberOfPadElts = ResTy.getNumElements() - Regs.size();
2440eae32dcSDimitry Andric   for (unsigned i = 0; i < NumberOfPadElts; ++i)
2450eae32dcSDimitry Andric     Regs.push_back(Undef);
246*bdd1243dSDimitry Andric   return buildMergeLikeInstr(Res, Regs);
2470eae32dcSDimitry Andric }
2480eae32dcSDimitry Andric 
2490eae32dcSDimitry Andric MachineInstrBuilder
2500eae32dcSDimitry Andric MachineIRBuilder::buildDeleteTrailingVectorElements(const DstOp &Res,
2510eae32dcSDimitry Andric                                                     const SrcOp &Op0) {
2520eae32dcSDimitry Andric   LLT ResTy = Res.getLLTTy(*getMRI());
2530eae32dcSDimitry Andric   LLT Op0Ty = Op0.getLLTTy(*getMRI());
2540eae32dcSDimitry Andric 
2550eae32dcSDimitry Andric   assert((ResTy.isVector() && Op0Ty.isVector()) && "Non vector type");
2560eae32dcSDimitry Andric   assert((ResTy.getElementType() == Op0Ty.getElementType()) &&
2570eae32dcSDimitry Andric          "Different vector element types");
2580eae32dcSDimitry Andric   assert((ResTy.getNumElements() < Op0Ty.getNumElements()) &&
2590eae32dcSDimitry Andric          "Op0 has fewer elements");
2600eae32dcSDimitry Andric 
2610eae32dcSDimitry Andric   SmallVector<Register, 8> Regs;
2620eae32dcSDimitry Andric   auto Unmerge = buildUnmerge(Op0Ty.getElementType(), Op0);
2630eae32dcSDimitry Andric   for (unsigned i = 0; i < ResTy.getNumElements(); ++i)
2640eae32dcSDimitry Andric     Regs.push_back(Unmerge.getReg(i));
265*bdd1243dSDimitry Andric   return buildMergeLikeInstr(Res, Regs);
2660eae32dcSDimitry Andric }
2670eae32dcSDimitry Andric 
2680b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
2690b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BR).addMBB(&Dest);
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBrIndirect(Register Tgt) {
2730b57cec5SDimitry Andric   assert(getMRI()->getType(Tgt).isPointer() && "invalid branch destination");
2740b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BRINDIRECT).addUse(Tgt);
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBrJT(Register TablePtr,
2780b57cec5SDimitry Andric                                                 unsigned JTI,
2790b57cec5SDimitry Andric                                                 Register IndexReg) {
2800b57cec5SDimitry Andric   assert(getMRI()->getType(TablePtr).isPointer() &&
2810b57cec5SDimitry Andric          "Table reg must be a pointer");
2820b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BRJT)
2830b57cec5SDimitry Andric       .addUse(TablePtr)
2840b57cec5SDimitry Andric       .addJumpTableIndex(JTI)
2850b57cec5SDimitry Andric       .addUse(IndexReg);
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildCopy(const DstOp &Res,
2890b57cec5SDimitry Andric                                                 const SrcOp &Op) {
2900b57cec5SDimitry Andric   return buildInstr(TargetOpcode::COPY, Res, Op);
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
2940b57cec5SDimitry Andric                                                     const ConstantInt &Val) {
2950b57cec5SDimitry Andric   LLT Ty = Res.getLLTTy(*getMRI());
2960b57cec5SDimitry Andric   LLT EltTy = Ty.getScalarType();
2970b57cec5SDimitry Andric   assert(EltTy.getScalarSizeInBits() == Val.getBitWidth() &&
2980b57cec5SDimitry Andric          "creating constant with the wrong size");
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   if (Ty.isVector()) {
3010b57cec5SDimitry Andric     auto Const = buildInstr(TargetOpcode::G_CONSTANT)
3020b57cec5SDimitry Andric     .addDef(getMRI()->createGenericVirtualRegister(EltTy))
3030b57cec5SDimitry Andric     .addCImm(&Val);
3040b57cec5SDimitry Andric     return buildSplatVector(Res, Const);
3050b57cec5SDimitry Andric   }
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   auto Const = buildInstr(TargetOpcode::G_CONSTANT);
3085ffd83dbSDimitry Andric   Const->setDebugLoc(DebugLoc());
3090b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), Const);
3100b57cec5SDimitry Andric   Const.addCImm(&Val);
3110b57cec5SDimitry Andric   return Const;
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
3150b57cec5SDimitry Andric                                                     int64_t Val) {
3160b57cec5SDimitry Andric   auto IntN = IntegerType::get(getMF().getFunction().getContext(),
3170b57cec5SDimitry Andric                                Res.getLLTTy(*getMRI()).getScalarSizeInBits());
3180b57cec5SDimitry Andric   ConstantInt *CI = ConstantInt::get(IntN, Val, true);
3190b57cec5SDimitry Andric   return buildConstant(Res, *CI);
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
3230b57cec5SDimitry Andric                                                      const ConstantFP &Val) {
3240b57cec5SDimitry Andric   LLT Ty = Res.getLLTTy(*getMRI());
3250b57cec5SDimitry Andric   LLT EltTy = Ty.getScalarType();
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   assert(APFloat::getSizeInBits(Val.getValueAPF().getSemantics())
3280b57cec5SDimitry Andric          == EltTy.getSizeInBits() &&
3290b57cec5SDimitry Andric          "creating fconstant with the wrong size");
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   assert(!Ty.isPointer() && "invalid operand type");
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   if (Ty.isVector()) {
3340b57cec5SDimitry Andric     auto Const = buildInstr(TargetOpcode::G_FCONSTANT)
3350b57cec5SDimitry Andric     .addDef(getMRI()->createGenericVirtualRegister(EltTy))
3360b57cec5SDimitry Andric     .addFPImm(&Val);
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric     return buildSplatVector(Res, Const);
3390b57cec5SDimitry Andric   }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric   auto Const = buildInstr(TargetOpcode::G_FCONSTANT);
3425ffd83dbSDimitry Andric   Const->setDebugLoc(DebugLoc());
3430b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), Const);
3440b57cec5SDimitry Andric   Const.addFPImm(&Val);
3450b57cec5SDimitry Andric   return Const;
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
3490b57cec5SDimitry Andric                                                     const APInt &Val) {
3500b57cec5SDimitry Andric   ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(), Val);
3510b57cec5SDimitry Andric   return buildConstant(Res, *CI);
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
3550b57cec5SDimitry Andric                                                      double Val) {
3560b57cec5SDimitry Andric   LLT DstTy = Res.getLLTTy(*getMRI());
3570b57cec5SDimitry Andric   auto &Ctx = getMF().getFunction().getContext();
3580b57cec5SDimitry Andric   auto *CFP =
3590b57cec5SDimitry Andric       ConstantFP::get(Ctx, getAPFloatFromSize(Val, DstTy.getScalarSizeInBits()));
3600b57cec5SDimitry Andric   return buildFConstant(Res, *CFP);
3610b57cec5SDimitry Andric }
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
3640b57cec5SDimitry Andric                                                      const APFloat &Val) {
3650b57cec5SDimitry Andric   auto &Ctx = getMF().getFunction().getContext();
3660b57cec5SDimitry Andric   auto *CFP = ConstantFP::get(Ctx, Val);
3670b57cec5SDimitry Andric   return buildFConstant(Res, *CFP);
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric 
370e8d8bef9SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBrCond(const SrcOp &Tst,
3710b57cec5SDimitry Andric                                                   MachineBasicBlock &Dest) {
372e8d8bef9SDimitry Andric   assert(Tst.getLLTTy(*getMRI()).isScalar() && "invalid operand type");
3730b57cec5SDimitry Andric 
374e8d8bef9SDimitry Andric   auto MIB = buildInstr(TargetOpcode::G_BRCOND);
375e8d8bef9SDimitry Andric   Tst.addSrcToMIB(MIB);
376e8d8bef9SDimitry Andric   MIB.addMBB(&Dest);
377e8d8bef9SDimitry Andric   return MIB;
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
380e8d8bef9SDimitry Andric MachineInstrBuilder
381e8d8bef9SDimitry Andric MachineIRBuilder::buildLoad(const DstOp &Dst, const SrcOp &Addr,
382e8d8bef9SDimitry Andric                             MachinePointerInfo PtrInfo, Align Alignment,
383e8d8bef9SDimitry Andric                             MachineMemOperand::Flags MMOFlags,
384e8d8bef9SDimitry Andric                             const AAMDNodes &AAInfo) {
385e8d8bef9SDimitry Andric   MMOFlags |= MachineMemOperand::MOLoad;
386e8d8bef9SDimitry Andric   assert((MMOFlags & MachineMemOperand::MOStore) == 0);
387e8d8bef9SDimitry Andric 
388fe6060f1SDimitry Andric   LLT Ty = Dst.getLLTTy(*getMRI());
389e8d8bef9SDimitry Andric   MachineMemOperand *MMO =
390fe6060f1SDimitry Andric       getMF().getMachineMemOperand(PtrInfo, MMOFlags, Ty, Alignment, AAInfo);
391e8d8bef9SDimitry Andric   return buildLoad(Dst, Addr, *MMO);
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildLoadInstr(unsigned Opcode,
3950b57cec5SDimitry Andric                                                      const DstOp &Res,
3960b57cec5SDimitry Andric                                                      const SrcOp &Addr,
3970b57cec5SDimitry Andric                                                      MachineMemOperand &MMO) {
3980b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isValid() && "invalid operand type");
3990b57cec5SDimitry Andric   assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   auto MIB = buildInstr(Opcode);
4020b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), MIB);
4030b57cec5SDimitry Andric   Addr.addSrcToMIB(MIB);
4040b57cec5SDimitry Andric   MIB.addMemOperand(&MMO);
4050b57cec5SDimitry Andric   return MIB;
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric 
4085ffd83dbSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildLoadFromOffset(
4095ffd83dbSDimitry Andric   const DstOp &Dst, const SrcOp &BasePtr,
4105ffd83dbSDimitry Andric   MachineMemOperand &BaseMMO, int64_t Offset) {
4115ffd83dbSDimitry Andric   LLT LoadTy = Dst.getLLTTy(*getMRI());
4125ffd83dbSDimitry Andric   MachineMemOperand *OffsetMMO =
413fe6060f1SDimitry Andric       getMF().getMachineMemOperand(&BaseMMO, Offset, LoadTy);
4145ffd83dbSDimitry Andric 
4155ffd83dbSDimitry Andric   if (Offset == 0) // This may be a size or type changing load.
4165ffd83dbSDimitry Andric     return buildLoad(Dst, BasePtr, *OffsetMMO);
4175ffd83dbSDimitry Andric 
4185ffd83dbSDimitry Andric   LLT PtrTy = BasePtr.getLLTTy(*getMRI());
4195ffd83dbSDimitry Andric   LLT OffsetTy = LLT::scalar(PtrTy.getSizeInBits());
4205ffd83dbSDimitry Andric   auto ConstOffset = buildConstant(OffsetTy, Offset);
4215ffd83dbSDimitry Andric   auto Ptr = buildPtrAdd(PtrTy, BasePtr, ConstOffset);
4225ffd83dbSDimitry Andric   return buildLoad(Dst, Ptr, *OffsetMMO);
4235ffd83dbSDimitry Andric }
4245ffd83dbSDimitry Andric 
4250b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildStore(const SrcOp &Val,
4260b57cec5SDimitry Andric                                                  const SrcOp &Addr,
4270b57cec5SDimitry Andric                                                  MachineMemOperand &MMO) {
4280b57cec5SDimitry Andric   assert(Val.getLLTTy(*getMRI()).isValid() && "invalid operand type");
4290b57cec5SDimitry Andric   assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   auto MIB = buildInstr(TargetOpcode::G_STORE);
4320b57cec5SDimitry Andric   Val.addSrcToMIB(MIB);
4330b57cec5SDimitry Andric   Addr.addSrcToMIB(MIB);
4340b57cec5SDimitry Andric   MIB.addMemOperand(&MMO);
4350b57cec5SDimitry Andric   return MIB;
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric 
438e8d8bef9SDimitry Andric MachineInstrBuilder
439e8d8bef9SDimitry Andric MachineIRBuilder::buildStore(const SrcOp &Val, const SrcOp &Addr,
440e8d8bef9SDimitry Andric                              MachinePointerInfo PtrInfo, Align Alignment,
441e8d8bef9SDimitry Andric                              MachineMemOperand::Flags MMOFlags,
442e8d8bef9SDimitry Andric                              const AAMDNodes &AAInfo) {
443e8d8bef9SDimitry Andric   MMOFlags |= MachineMemOperand::MOStore;
444e8d8bef9SDimitry Andric   assert((MMOFlags & MachineMemOperand::MOLoad) == 0);
445e8d8bef9SDimitry Andric 
446fe6060f1SDimitry Andric   LLT Ty = Val.getLLTTy(*getMRI());
447e8d8bef9SDimitry Andric   MachineMemOperand *MMO =
448fe6060f1SDimitry Andric       getMF().getMachineMemOperand(PtrInfo, MMOFlags, Ty, Alignment, AAInfo);
449e8d8bef9SDimitry Andric   return buildStore(Val, Addr, *MMO);
450e8d8bef9SDimitry Andric }
451e8d8bef9SDimitry Andric 
4520b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAnyExt(const DstOp &Res,
4530b57cec5SDimitry Andric                                                   const SrcOp &Op) {
4540b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_ANYEXT, Res, Op);
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSExt(const DstOp &Res,
4580b57cec5SDimitry Andric                                                 const SrcOp &Op) {
4590b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_SEXT, Res, Op);
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildZExt(const DstOp &Res,
4630b57cec5SDimitry Andric                                                 const SrcOp &Op) {
4640b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_ZEXT, Res, Op);
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric unsigned MachineIRBuilder::getBoolExtOp(bool IsVec, bool IsFP) const {
4680b57cec5SDimitry Andric   const auto *TLI = getMF().getSubtarget().getTargetLowering();
4690b57cec5SDimitry Andric   switch (TLI->getBooleanContents(IsVec, IsFP)) {
4700b57cec5SDimitry Andric   case TargetLoweringBase::ZeroOrNegativeOneBooleanContent:
4710b57cec5SDimitry Andric     return TargetOpcode::G_SEXT;
4720b57cec5SDimitry Andric   case TargetLoweringBase::ZeroOrOneBooleanContent:
4730b57cec5SDimitry Andric     return TargetOpcode::G_ZEXT;
4740b57cec5SDimitry Andric   default:
4750b57cec5SDimitry Andric     return TargetOpcode::G_ANYEXT;
4760b57cec5SDimitry Andric   }
4770b57cec5SDimitry Andric }
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBoolExt(const DstOp &Res,
4800b57cec5SDimitry Andric                                                    const SrcOp &Op,
4810b57cec5SDimitry Andric                                                    bool IsFP) {
4820b57cec5SDimitry Andric   unsigned ExtOp = getBoolExtOp(getMRI()->getType(Op.getReg()).isVector(), IsFP);
4830b57cec5SDimitry Andric   return buildInstr(ExtOp, Res, Op);
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric 
486753f127fSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBoolExtInReg(const DstOp &Res,
487753f127fSDimitry Andric                                                         const SrcOp &Op,
488753f127fSDimitry Andric                                                         bool IsVector,
489753f127fSDimitry Andric                                                         bool IsFP) {
490753f127fSDimitry Andric   const auto *TLI = getMF().getSubtarget().getTargetLowering();
491753f127fSDimitry Andric   switch (TLI->getBooleanContents(IsVector, IsFP)) {
492753f127fSDimitry Andric   case TargetLoweringBase::ZeroOrNegativeOneBooleanContent:
493753f127fSDimitry Andric     return buildSExtInReg(Res, Op, 1);
494753f127fSDimitry Andric   case TargetLoweringBase::ZeroOrOneBooleanContent:
495753f127fSDimitry Andric     return buildZExtInReg(Res, Op, 1);
496753f127fSDimitry Andric   case TargetLoweringBase::UndefinedBooleanContent:
497753f127fSDimitry Andric     return buildCopy(Res, Op);
498753f127fSDimitry Andric   }
499753f127fSDimitry Andric 
500753f127fSDimitry Andric   llvm_unreachable("unexpected BooleanContent");
501753f127fSDimitry Andric }
502753f127fSDimitry Andric 
5030b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildExtOrTrunc(unsigned ExtOpc,
5040b57cec5SDimitry Andric                                                       const DstOp &Res,
5050b57cec5SDimitry Andric                                                       const SrcOp &Op) {
5060b57cec5SDimitry Andric   assert((TargetOpcode::G_ANYEXT == ExtOpc || TargetOpcode::G_ZEXT == ExtOpc ||
5070b57cec5SDimitry Andric           TargetOpcode::G_SEXT == ExtOpc) &&
5080b57cec5SDimitry Andric          "Expecting Extending Opc");
5090b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isScalar() ||
5100b57cec5SDimitry Andric          Res.getLLTTy(*getMRI()).isVector());
5110b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isScalar() ==
5120b57cec5SDimitry Andric          Op.getLLTTy(*getMRI()).isScalar());
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric   unsigned Opcode = TargetOpcode::COPY;
5150b57cec5SDimitry Andric   if (Res.getLLTTy(*getMRI()).getSizeInBits() >
5160b57cec5SDimitry Andric       Op.getLLTTy(*getMRI()).getSizeInBits())
5170b57cec5SDimitry Andric     Opcode = ExtOpc;
5180b57cec5SDimitry Andric   else if (Res.getLLTTy(*getMRI()).getSizeInBits() <
5190b57cec5SDimitry Andric            Op.getLLTTy(*getMRI()).getSizeInBits())
5200b57cec5SDimitry Andric     Opcode = TargetOpcode::G_TRUNC;
5210b57cec5SDimitry Andric   else
5220b57cec5SDimitry Andric     assert(Res.getLLTTy(*getMRI()) == Op.getLLTTy(*getMRI()));
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric   return buildInstr(Opcode, Res, Op);
5250b57cec5SDimitry Andric }
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSExtOrTrunc(const DstOp &Res,
5280b57cec5SDimitry Andric                                                        const SrcOp &Op) {
5290b57cec5SDimitry Andric   return buildExtOrTrunc(TargetOpcode::G_SEXT, Res, Op);
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildZExtOrTrunc(const DstOp &Res,
5330b57cec5SDimitry Andric                                                        const SrcOp &Op) {
5340b57cec5SDimitry Andric   return buildExtOrTrunc(TargetOpcode::G_ZEXT, Res, Op);
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAnyExtOrTrunc(const DstOp &Res,
5380b57cec5SDimitry Andric                                                          const SrcOp &Op) {
5390b57cec5SDimitry Andric   return buildExtOrTrunc(TargetOpcode::G_ANYEXT, Res, Op);
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric 
542fe6060f1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildZExtInReg(const DstOp &Res,
543fe6060f1SDimitry Andric                                                      const SrcOp &Op,
544fe6060f1SDimitry Andric                                                      int64_t ImmOp) {
545fe6060f1SDimitry Andric   LLT ResTy = Res.getLLTTy(*getMRI());
546fe6060f1SDimitry Andric   auto Mask = buildConstant(
547fe6060f1SDimitry Andric       ResTy, APInt::getLowBitsSet(ResTy.getScalarSizeInBits(), ImmOp));
548fe6060f1SDimitry Andric   return buildAnd(Res, Op, Mask);
549fe6060f1SDimitry Andric }
550fe6060f1SDimitry Andric 
5510b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildCast(const DstOp &Dst,
5520b57cec5SDimitry Andric                                                 const SrcOp &Src) {
5530b57cec5SDimitry Andric   LLT SrcTy = Src.getLLTTy(*getMRI());
5540b57cec5SDimitry Andric   LLT DstTy = Dst.getLLTTy(*getMRI());
5550b57cec5SDimitry Andric   if (SrcTy == DstTy)
5560b57cec5SDimitry Andric     return buildCopy(Dst, Src);
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   unsigned Opcode;
5590b57cec5SDimitry Andric   if (SrcTy.isPointer() && DstTy.isScalar())
5600b57cec5SDimitry Andric     Opcode = TargetOpcode::G_PTRTOINT;
5610b57cec5SDimitry Andric   else if (DstTy.isPointer() && SrcTy.isScalar())
5620b57cec5SDimitry Andric     Opcode = TargetOpcode::G_INTTOPTR;
5630b57cec5SDimitry Andric   else {
5640b57cec5SDimitry Andric     assert(!SrcTy.isPointer() && !DstTy.isPointer() && "n G_ADDRCAST yet");
5650b57cec5SDimitry Andric     Opcode = TargetOpcode::G_BITCAST;
5660b57cec5SDimitry Andric   }
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   return buildInstr(Opcode, Dst, Src);
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildExtract(const DstOp &Dst,
5720b57cec5SDimitry Andric                                                    const SrcOp &Src,
5730b57cec5SDimitry Andric                                                    uint64_t Index) {
5740b57cec5SDimitry Andric   LLT SrcTy = Src.getLLTTy(*getMRI());
5750b57cec5SDimitry Andric   LLT DstTy = Dst.getLLTTy(*getMRI());
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric #ifndef NDEBUG
5780b57cec5SDimitry Andric   assert(SrcTy.isValid() && "invalid operand type");
5790b57cec5SDimitry Andric   assert(DstTy.isValid() && "invalid operand type");
5800b57cec5SDimitry Andric   assert(Index + DstTy.getSizeInBits() <= SrcTy.getSizeInBits() &&
5810b57cec5SDimitry Andric          "extracting off end of register");
5820b57cec5SDimitry Andric #endif
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric   if (DstTy.getSizeInBits() == SrcTy.getSizeInBits()) {
5850b57cec5SDimitry Andric     assert(Index == 0 && "insertion past the end of a register");
5860b57cec5SDimitry Andric     return buildCast(Dst, Src);
5870b57cec5SDimitry Andric   }
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric   auto Extract = buildInstr(TargetOpcode::G_EXTRACT);
5900b57cec5SDimitry Andric   Dst.addDefToMIB(*getMRI(), Extract);
5910b57cec5SDimitry Andric   Src.addSrcToMIB(Extract);
5920b57cec5SDimitry Andric   Extract.addImm(Index);
5930b57cec5SDimitry Andric   return Extract;
5940b57cec5SDimitry Andric }
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUndef(const DstOp &Res) {
5970b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_IMPLICIT_DEF, {Res}, {});
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric 
600*bdd1243dSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildMergeValues(const DstOp &Res,
6010b57cec5SDimitry Andric                                                        ArrayRef<Register> Ops) {
6020b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
6030b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
6040b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
6050b57cec5SDimitry Andric   SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
6060b57cec5SDimitry Andric   assert(TmpVec.size() > 1);
6070b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_MERGE_VALUES, Res, TmpVec);
6080b57cec5SDimitry Andric }
6090b57cec5SDimitry Andric 
6105ffd83dbSDimitry Andric MachineInstrBuilder
611*bdd1243dSDimitry Andric MachineIRBuilder::buildMergeLikeInstr(const DstOp &Res,
612*bdd1243dSDimitry Andric                                       ArrayRef<Register> Ops) {
613*bdd1243dSDimitry Andric   // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
614*bdd1243dSDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
615*bdd1243dSDimitry Andric   // sufficiently large SmallVector to not go through the heap.
616*bdd1243dSDimitry Andric   SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
617*bdd1243dSDimitry Andric   assert(TmpVec.size() > 1);
618*bdd1243dSDimitry Andric   return buildInstr(getOpcodeForMerge(Res, TmpVec), Res, TmpVec);
619*bdd1243dSDimitry Andric }
620*bdd1243dSDimitry Andric 
621*bdd1243dSDimitry Andric MachineInstrBuilder
622*bdd1243dSDimitry Andric MachineIRBuilder::buildMergeLikeInstr(const DstOp &Res,
6235ffd83dbSDimitry Andric                                       std::initializer_list<SrcOp> Ops) {
6245ffd83dbSDimitry Andric   assert(Ops.size() > 1);
625*bdd1243dSDimitry Andric   return buildInstr(getOpcodeForMerge(Res, Ops), Res, Ops);
626*bdd1243dSDimitry Andric }
627*bdd1243dSDimitry Andric 
628*bdd1243dSDimitry Andric unsigned MachineIRBuilder::getOpcodeForMerge(const DstOp &DstOp,
629*bdd1243dSDimitry Andric                                              ArrayRef<SrcOp> SrcOps) const {
630*bdd1243dSDimitry Andric   if (DstOp.getLLTTy(*getMRI()).isVector()) {
631*bdd1243dSDimitry Andric     if (SrcOps[0].getLLTTy(*getMRI()).isVector())
632*bdd1243dSDimitry Andric       return TargetOpcode::G_CONCAT_VECTORS;
633*bdd1243dSDimitry Andric     return TargetOpcode::G_BUILD_VECTOR;
634*bdd1243dSDimitry Andric   }
635*bdd1243dSDimitry Andric 
636*bdd1243dSDimitry Andric   return TargetOpcode::G_MERGE_VALUES;
6375ffd83dbSDimitry Andric }
6385ffd83dbSDimitry Andric 
6390b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUnmerge(ArrayRef<LLT> Res,
6400b57cec5SDimitry Andric                                                    const SrcOp &Op) {
6410b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<DstOp>,
6420b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
6430b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
6440b57cec5SDimitry Andric   SmallVector<DstOp, 8> TmpVec(Res.begin(), Res.end());
6450b57cec5SDimitry Andric   assert(TmpVec.size() > 1);
6460b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUnmerge(LLT Res,
6500b57cec5SDimitry Andric                                                    const SrcOp &Op) {
6510b57cec5SDimitry Andric   unsigned NumReg = Op.getLLTTy(*getMRI()).getSizeInBits() / Res.getSizeInBits();
6520eae32dcSDimitry Andric   SmallVector<DstOp, 8> TmpVec(NumReg, Res);
6530eae32dcSDimitry Andric   return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
6540b57cec5SDimitry Andric }
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUnmerge(ArrayRef<Register> Res,
6570b57cec5SDimitry Andric                                                    const SrcOp &Op) {
6580b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<Register> to ArrayRef<DstOp>,
6590b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
6600b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
6610b57cec5SDimitry Andric   SmallVector<DstOp, 8> TmpVec(Res.begin(), Res.end());
6620b57cec5SDimitry Andric   assert(TmpVec.size() > 1);
6630b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
6640b57cec5SDimitry Andric }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBuildVector(const DstOp &Res,
6670b57cec5SDimitry Andric                                                        ArrayRef<Register> Ops) {
6680b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
6690b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
6700b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
6710b57cec5SDimitry Andric   SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
6720b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
6730b57cec5SDimitry Andric }
6740b57cec5SDimitry Andric 
67581ad6265SDimitry Andric MachineInstrBuilder
67681ad6265SDimitry Andric MachineIRBuilder::buildBuildVectorConstant(const DstOp &Res,
67781ad6265SDimitry Andric                                            ArrayRef<APInt> Ops) {
67881ad6265SDimitry Andric   SmallVector<SrcOp> TmpVec;
67981ad6265SDimitry Andric   TmpVec.reserve(Ops.size());
68081ad6265SDimitry Andric   LLT EltTy = Res.getLLTTy(*getMRI()).getElementType();
681fcaf7f86SDimitry Andric   for (const auto &Op : Ops)
68281ad6265SDimitry Andric     TmpVec.push_back(buildConstant(EltTy, Op));
68381ad6265SDimitry Andric   return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
68481ad6265SDimitry Andric }
68581ad6265SDimitry Andric 
6860b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSplatVector(const DstOp &Res,
6870b57cec5SDimitry Andric                                                        const SrcOp &Src) {
6880b57cec5SDimitry Andric   SmallVector<SrcOp, 8> TmpVec(Res.getLLTTy(*getMRI()).getNumElements(), Src);
6890b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
6900b57cec5SDimitry Andric }
6910b57cec5SDimitry Andric 
6920b57cec5SDimitry Andric MachineInstrBuilder
6930b57cec5SDimitry Andric MachineIRBuilder::buildBuildVectorTrunc(const DstOp &Res,
6940b57cec5SDimitry Andric                                         ArrayRef<Register> Ops) {
6950b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
6960b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
6970b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
6980b57cec5SDimitry Andric   SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
699*bdd1243dSDimitry Andric   if (TmpVec[0].getLLTTy(*getMRI()).getSizeInBits() ==
700*bdd1243dSDimitry Andric       Res.getLLTTy(*getMRI()).getElementType().getSizeInBits())
701*bdd1243dSDimitry Andric     return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
7020b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BUILD_VECTOR_TRUNC, Res, TmpVec);
7030b57cec5SDimitry Andric }
7040b57cec5SDimitry Andric 
705e8d8bef9SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildShuffleSplat(const DstOp &Res,
706e8d8bef9SDimitry Andric                                                         const SrcOp &Src) {
707e8d8bef9SDimitry Andric   LLT DstTy = Res.getLLTTy(*getMRI());
708e8d8bef9SDimitry Andric   assert(Src.getLLTTy(*getMRI()) == DstTy.getElementType() &&
709e8d8bef9SDimitry Andric          "Expected Src to match Dst elt ty");
710e8d8bef9SDimitry Andric   auto UndefVec = buildUndef(DstTy);
711e8d8bef9SDimitry Andric   auto Zero = buildConstant(LLT::scalar(64), 0);
712e8d8bef9SDimitry Andric   auto InsElt = buildInsertVectorElement(DstTy, UndefVec, Src, Zero);
713e8d8bef9SDimitry Andric   SmallVector<int, 16> ZeroMask(DstTy.getNumElements());
714e8d8bef9SDimitry Andric   return buildShuffleVector(DstTy, InsElt, UndefVec, ZeroMask);
715e8d8bef9SDimitry Andric }
716e8d8bef9SDimitry Andric 
717e8d8bef9SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildShuffleVector(const DstOp &Res,
718e8d8bef9SDimitry Andric                                                          const SrcOp &Src1,
719e8d8bef9SDimitry Andric                                                          const SrcOp &Src2,
720e8d8bef9SDimitry Andric                                                          ArrayRef<int> Mask) {
721e8d8bef9SDimitry Andric   LLT DstTy = Res.getLLTTy(*getMRI());
722e8d8bef9SDimitry Andric   LLT Src1Ty = Src1.getLLTTy(*getMRI());
723e8d8bef9SDimitry Andric   LLT Src2Ty = Src2.getLLTTy(*getMRI());
724349cc55cSDimitry Andric   assert((size_t)(Src1Ty.getNumElements() + Src2Ty.getNumElements()) >=
725349cc55cSDimitry Andric          Mask.size());
726e8d8bef9SDimitry Andric   assert(DstTy.getElementType() == Src1Ty.getElementType() &&
727e8d8bef9SDimitry Andric          DstTy.getElementType() == Src2Ty.getElementType());
728fe6060f1SDimitry Andric   (void)DstTy;
729e8d8bef9SDimitry Andric   (void)Src1Ty;
730e8d8bef9SDimitry Andric   (void)Src2Ty;
731e8d8bef9SDimitry Andric   ArrayRef<int> MaskAlloc = getMF().allocateShuffleMask(Mask);
732fe6060f1SDimitry Andric   return buildInstr(TargetOpcode::G_SHUFFLE_VECTOR, {Res}, {Src1, Src2})
733e8d8bef9SDimitry Andric       .addShuffleMask(MaskAlloc);
734e8d8bef9SDimitry Andric }
735e8d8bef9SDimitry Andric 
7360b57cec5SDimitry Andric MachineInstrBuilder
7370b57cec5SDimitry Andric MachineIRBuilder::buildConcatVectors(const DstOp &Res, ArrayRef<Register> Ops) {
7380b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
7390b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
7400b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
7410b57cec5SDimitry Andric   SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
7420b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_CONCAT_VECTORS, Res, TmpVec);
7430b57cec5SDimitry Andric }
7440b57cec5SDimitry Andric 
7455ffd83dbSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildInsert(const DstOp &Res,
7465ffd83dbSDimitry Andric                                                   const SrcOp &Src,
7475ffd83dbSDimitry Andric                                                   const SrcOp &Op,
7485ffd83dbSDimitry Andric                                                   unsigned Index) {
7495ffd83dbSDimitry Andric   assert(Index + Op.getLLTTy(*getMRI()).getSizeInBits() <=
7505ffd83dbSDimitry Andric              Res.getLLTTy(*getMRI()).getSizeInBits() &&
7510b57cec5SDimitry Andric          "insertion past the end of a register");
7520b57cec5SDimitry Andric 
7535ffd83dbSDimitry Andric   if (Res.getLLTTy(*getMRI()).getSizeInBits() ==
7545ffd83dbSDimitry Andric       Op.getLLTTy(*getMRI()).getSizeInBits()) {
7550b57cec5SDimitry Andric     return buildCast(Res, Op);
7560b57cec5SDimitry Andric   }
7570b57cec5SDimitry Andric 
7585ffd83dbSDimitry Andric   return buildInstr(TargetOpcode::G_INSERT, Res, {Src, Op, uint64_t(Index)});
7590b57cec5SDimitry Andric }
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID,
7620b57cec5SDimitry Andric                                                      ArrayRef<Register> ResultRegs,
7630b57cec5SDimitry Andric                                                      bool HasSideEffects) {
7640b57cec5SDimitry Andric   auto MIB =
7650b57cec5SDimitry Andric       buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS
7660b57cec5SDimitry Andric                                 : TargetOpcode::G_INTRINSIC);
7670b57cec5SDimitry Andric   for (unsigned ResultReg : ResultRegs)
7680b57cec5SDimitry Andric     MIB.addDef(ResultReg);
7690b57cec5SDimitry Andric   MIB.addIntrinsicID(ID);
7700b57cec5SDimitry Andric   return MIB;
7710b57cec5SDimitry Andric }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID,
7740b57cec5SDimitry Andric                                                      ArrayRef<DstOp> Results,
7750b57cec5SDimitry Andric                                                      bool HasSideEffects) {
7760b57cec5SDimitry Andric   auto MIB =
7770b57cec5SDimitry Andric       buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS
7780b57cec5SDimitry Andric                                 : TargetOpcode::G_INTRINSIC);
7790b57cec5SDimitry Andric   for (DstOp Result : Results)
7800b57cec5SDimitry Andric     Result.addDefToMIB(*getMRI(), MIB);
7810b57cec5SDimitry Andric   MIB.addIntrinsicID(ID);
7820b57cec5SDimitry Andric   return MIB;
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildTrunc(const DstOp &Res,
7860b57cec5SDimitry Andric                                                  const SrcOp &Op) {
7870b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_TRUNC, Res, Op);
7880b57cec5SDimitry Andric }
7890b57cec5SDimitry Andric 
790*bdd1243dSDimitry Andric MachineInstrBuilder
791*bdd1243dSDimitry Andric MachineIRBuilder::buildFPTrunc(const DstOp &Res, const SrcOp &Op,
792*bdd1243dSDimitry Andric                                std::optional<unsigned> Flags) {
793480093f4SDimitry Andric   return buildInstr(TargetOpcode::G_FPTRUNC, Res, Op, Flags);
7940b57cec5SDimitry Andric }
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildICmp(CmpInst::Predicate Pred,
7970b57cec5SDimitry Andric                                                 const DstOp &Res,
7980b57cec5SDimitry Andric                                                 const SrcOp &Op0,
7990b57cec5SDimitry Andric                                                 const SrcOp &Op1) {
8000b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_ICMP, Res, {Pred, Op0, Op1});
8010b57cec5SDimitry Andric }
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFCmp(CmpInst::Predicate Pred,
8040b57cec5SDimitry Andric                                                 const DstOp &Res,
8050b57cec5SDimitry Andric                                                 const SrcOp &Op0,
8068bcb0991SDimitry Andric                                                 const SrcOp &Op1,
807*bdd1243dSDimitry Andric                                                 std::optional<unsigned> Flags) {
8080b57cec5SDimitry Andric 
8098bcb0991SDimitry Andric   return buildInstr(TargetOpcode::G_FCMP, Res, {Pred, Op0, Op1}, Flags);
8100b57cec5SDimitry Andric }
8110b57cec5SDimitry Andric 
812*bdd1243dSDimitry Andric MachineInstrBuilder
813*bdd1243dSDimitry Andric MachineIRBuilder::buildSelect(const DstOp &Res, const SrcOp &Tst,
814*bdd1243dSDimitry Andric                               const SrcOp &Op0, const SrcOp &Op1,
815*bdd1243dSDimitry Andric                               std::optional<unsigned> Flags) {
8160b57cec5SDimitry Andric 
8178bcb0991SDimitry Andric   return buildInstr(TargetOpcode::G_SELECT, {Res}, {Tst, Op0, Op1}, Flags);
8180b57cec5SDimitry Andric }
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric MachineInstrBuilder
8210b57cec5SDimitry Andric MachineIRBuilder::buildInsertVectorElement(const DstOp &Res, const SrcOp &Val,
8220b57cec5SDimitry Andric                                            const SrcOp &Elt, const SrcOp &Idx) {
8230b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_INSERT_VECTOR_ELT, Res, {Val, Elt, Idx});
8240b57cec5SDimitry Andric }
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric MachineInstrBuilder
8270b57cec5SDimitry Andric MachineIRBuilder::buildExtractVectorElement(const DstOp &Res, const SrcOp &Val,
8280b57cec5SDimitry Andric                                             const SrcOp &Idx) {
8290b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_EXTRACT_VECTOR_ELT, Res, {Val, Idx});
8300b57cec5SDimitry Andric }
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAtomicCmpXchgWithSuccess(
8330b57cec5SDimitry Andric     Register OldValRes, Register SuccessRes, Register Addr, Register CmpVal,
8340b57cec5SDimitry Andric     Register NewVal, MachineMemOperand &MMO) {
8350b57cec5SDimitry Andric #ifndef NDEBUG
8360b57cec5SDimitry Andric   LLT OldValResTy = getMRI()->getType(OldValRes);
8370b57cec5SDimitry Andric   LLT SuccessResTy = getMRI()->getType(SuccessRes);
8380b57cec5SDimitry Andric   LLT AddrTy = getMRI()->getType(Addr);
8390b57cec5SDimitry Andric   LLT CmpValTy = getMRI()->getType(CmpVal);
8400b57cec5SDimitry Andric   LLT NewValTy = getMRI()->getType(NewVal);
8410b57cec5SDimitry Andric   assert(OldValResTy.isScalar() && "invalid operand type");
8420b57cec5SDimitry Andric   assert(SuccessResTy.isScalar() && "invalid operand type");
8430b57cec5SDimitry Andric   assert(AddrTy.isPointer() && "invalid operand type");
8440b57cec5SDimitry Andric   assert(CmpValTy.isValid() && "invalid operand type");
8450b57cec5SDimitry Andric   assert(NewValTy.isValid() && "invalid operand type");
8460b57cec5SDimitry Andric   assert(OldValResTy == CmpValTy && "type mismatch");
8470b57cec5SDimitry Andric   assert(OldValResTy == NewValTy && "type mismatch");
8480b57cec5SDimitry Andric #endif
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS)
8510b57cec5SDimitry Andric       .addDef(OldValRes)
8520b57cec5SDimitry Andric       .addDef(SuccessRes)
8530b57cec5SDimitry Andric       .addUse(Addr)
8540b57cec5SDimitry Andric       .addUse(CmpVal)
8550b57cec5SDimitry Andric       .addUse(NewVal)
8560b57cec5SDimitry Andric       .addMemOperand(&MMO);
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric MachineInstrBuilder
8600b57cec5SDimitry Andric MachineIRBuilder::buildAtomicCmpXchg(Register OldValRes, Register Addr,
8610b57cec5SDimitry Andric                                      Register CmpVal, Register NewVal,
8620b57cec5SDimitry Andric                                      MachineMemOperand &MMO) {
8630b57cec5SDimitry Andric #ifndef NDEBUG
8640b57cec5SDimitry Andric   LLT OldValResTy = getMRI()->getType(OldValRes);
8650b57cec5SDimitry Andric   LLT AddrTy = getMRI()->getType(Addr);
8660b57cec5SDimitry Andric   LLT CmpValTy = getMRI()->getType(CmpVal);
8670b57cec5SDimitry Andric   LLT NewValTy = getMRI()->getType(NewVal);
8680b57cec5SDimitry Andric   assert(OldValResTy.isScalar() && "invalid operand type");
8690b57cec5SDimitry Andric   assert(AddrTy.isPointer() && "invalid operand type");
8700b57cec5SDimitry Andric   assert(CmpValTy.isValid() && "invalid operand type");
8710b57cec5SDimitry Andric   assert(NewValTy.isValid() && "invalid operand type");
8720b57cec5SDimitry Andric   assert(OldValResTy == CmpValTy && "type mismatch");
8730b57cec5SDimitry Andric   assert(OldValResTy == NewValTy && "type mismatch");
8740b57cec5SDimitry Andric #endif
8750b57cec5SDimitry Andric 
8760b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG)
8770b57cec5SDimitry Andric       .addDef(OldValRes)
8780b57cec5SDimitry Andric       .addUse(Addr)
8790b57cec5SDimitry Andric       .addUse(CmpVal)
8800b57cec5SDimitry Andric       .addUse(NewVal)
8810b57cec5SDimitry Andric       .addMemOperand(&MMO);
8820b57cec5SDimitry Andric }
8830b57cec5SDimitry Andric 
8848bcb0991SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAtomicRMW(
8858bcb0991SDimitry Andric   unsigned Opcode, const DstOp &OldValRes,
8868bcb0991SDimitry Andric   const SrcOp &Addr, const SrcOp &Val,
8870b57cec5SDimitry Andric   MachineMemOperand &MMO) {
8888bcb0991SDimitry Andric 
8890b57cec5SDimitry Andric #ifndef NDEBUG
8908bcb0991SDimitry Andric   LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
8918bcb0991SDimitry Andric   LLT AddrTy = Addr.getLLTTy(*getMRI());
8928bcb0991SDimitry Andric   LLT ValTy = Val.getLLTTy(*getMRI());
8930b57cec5SDimitry Andric   assert(OldValResTy.isScalar() && "invalid operand type");
8940b57cec5SDimitry Andric   assert(AddrTy.isPointer() && "invalid operand type");
8950b57cec5SDimitry Andric   assert(ValTy.isValid() && "invalid operand type");
8960b57cec5SDimitry Andric   assert(OldValResTy == ValTy && "type mismatch");
8978bcb0991SDimitry Andric   assert(MMO.isAtomic() && "not atomic mem operand");
8980b57cec5SDimitry Andric #endif
8990b57cec5SDimitry Andric 
9008bcb0991SDimitry Andric   auto MIB = buildInstr(Opcode);
9018bcb0991SDimitry Andric   OldValRes.addDefToMIB(*getMRI(), MIB);
9028bcb0991SDimitry Andric   Addr.addSrcToMIB(MIB);
9038bcb0991SDimitry Andric   Val.addSrcToMIB(MIB);
9048bcb0991SDimitry Andric   MIB.addMemOperand(&MMO);
9058bcb0991SDimitry Andric   return MIB;
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric MachineInstrBuilder
9090b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWXchg(Register OldValRes, Register Addr,
9100b57cec5SDimitry Andric                                      Register Val, MachineMemOperand &MMO) {
9110b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XCHG, OldValRes, Addr, Val,
9120b57cec5SDimitry Andric                         MMO);
9130b57cec5SDimitry Andric }
9140b57cec5SDimitry Andric MachineInstrBuilder
9150b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWAdd(Register OldValRes, Register Addr,
9160b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
9170b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_ADD, OldValRes, Addr, Val,
9180b57cec5SDimitry Andric                         MMO);
9190b57cec5SDimitry Andric }
9200b57cec5SDimitry Andric MachineInstrBuilder
9210b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWSub(Register OldValRes, Register Addr,
9220b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
9230b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_SUB, OldValRes, Addr, Val,
9240b57cec5SDimitry Andric                         MMO);
9250b57cec5SDimitry Andric }
9260b57cec5SDimitry Andric MachineInstrBuilder
9270b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWAnd(Register OldValRes, Register Addr,
9280b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
9290b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_AND, OldValRes, Addr, Val,
9300b57cec5SDimitry Andric                         MMO);
9310b57cec5SDimitry Andric }
9320b57cec5SDimitry Andric MachineInstrBuilder
9330b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWNand(Register OldValRes, Register Addr,
9340b57cec5SDimitry Andric                                      Register Val, MachineMemOperand &MMO) {
9350b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_NAND, OldValRes, Addr, Val,
9360b57cec5SDimitry Andric                         MMO);
9370b57cec5SDimitry Andric }
9380b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAtomicRMWOr(Register OldValRes,
9390b57cec5SDimitry Andric                                                        Register Addr,
9400b57cec5SDimitry Andric                                                        Register Val,
9410b57cec5SDimitry Andric                                                        MachineMemOperand &MMO) {
9420b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_OR, OldValRes, Addr, Val,
9430b57cec5SDimitry Andric                         MMO);
9440b57cec5SDimitry Andric }
9450b57cec5SDimitry Andric MachineInstrBuilder
9460b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWXor(Register OldValRes, Register Addr,
9470b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
9480b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XOR, OldValRes, Addr, Val,
9490b57cec5SDimitry Andric                         MMO);
9500b57cec5SDimitry Andric }
9510b57cec5SDimitry Andric MachineInstrBuilder
9520b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWMax(Register OldValRes, Register Addr,
9530b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
9540b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MAX, OldValRes, Addr, Val,
9550b57cec5SDimitry Andric                         MMO);
9560b57cec5SDimitry Andric }
9570b57cec5SDimitry Andric MachineInstrBuilder
9580b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWMin(Register OldValRes, Register Addr,
9590b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
9600b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MIN, OldValRes, Addr, Val,
9610b57cec5SDimitry Andric                         MMO);
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric MachineInstrBuilder
9640b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWUmax(Register OldValRes, Register Addr,
9650b57cec5SDimitry Andric                                      Register Val, MachineMemOperand &MMO) {
9660b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMAX, OldValRes, Addr, Val,
9670b57cec5SDimitry Andric                         MMO);
9680b57cec5SDimitry Andric }
9690b57cec5SDimitry Andric MachineInstrBuilder
9700b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWUmin(Register OldValRes, Register Addr,
9710b57cec5SDimitry Andric                                      Register Val, MachineMemOperand &MMO) {
9720b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMIN, OldValRes, Addr, Val,
9730b57cec5SDimitry Andric                         MMO);
9740b57cec5SDimitry Andric }
9750b57cec5SDimitry Andric 
9760b57cec5SDimitry Andric MachineInstrBuilder
9778bcb0991SDimitry Andric MachineIRBuilder::buildAtomicRMWFAdd(
9788bcb0991SDimitry Andric   const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
9798bcb0991SDimitry Andric   MachineMemOperand &MMO) {
9808bcb0991SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FADD, OldValRes, Addr, Val,
9818bcb0991SDimitry Andric                         MMO);
9828bcb0991SDimitry Andric }
9838bcb0991SDimitry Andric 
9848bcb0991SDimitry Andric MachineInstrBuilder
9858bcb0991SDimitry Andric MachineIRBuilder::buildAtomicRMWFSub(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
9868bcb0991SDimitry Andric                                      MachineMemOperand &MMO) {
9878bcb0991SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FSUB, OldValRes, Addr, Val,
9888bcb0991SDimitry Andric                         MMO);
9898bcb0991SDimitry Andric }
9908bcb0991SDimitry Andric 
9918bcb0991SDimitry Andric MachineInstrBuilder
992753f127fSDimitry Andric MachineIRBuilder::buildAtomicRMWFMax(const DstOp &OldValRes, const SrcOp &Addr,
993753f127fSDimitry Andric                                      const SrcOp &Val, MachineMemOperand &MMO) {
994753f127fSDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMAX, OldValRes, Addr, Val,
995753f127fSDimitry Andric                         MMO);
996753f127fSDimitry Andric }
997753f127fSDimitry Andric 
998753f127fSDimitry Andric MachineInstrBuilder
999753f127fSDimitry Andric MachineIRBuilder::buildAtomicRMWFMin(const DstOp &OldValRes, const SrcOp &Addr,
1000753f127fSDimitry Andric                                      const SrcOp &Val, MachineMemOperand &MMO) {
1001753f127fSDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMIN, OldValRes, Addr, Val,
1002753f127fSDimitry Andric                         MMO);
1003753f127fSDimitry Andric }
1004753f127fSDimitry Andric 
1005753f127fSDimitry Andric MachineInstrBuilder
10060b57cec5SDimitry Andric MachineIRBuilder::buildFence(unsigned Ordering, unsigned Scope) {
10070b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_FENCE)
10080b57cec5SDimitry Andric     .addImm(Ordering)
10090b57cec5SDimitry Andric     .addImm(Scope);
10100b57cec5SDimitry Andric }
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric MachineInstrBuilder
10130b57cec5SDimitry Andric MachineIRBuilder::buildBlockAddress(Register Res, const BlockAddress *BA) {
10140b57cec5SDimitry Andric #ifndef NDEBUG
10150b57cec5SDimitry Andric   assert(getMRI()->getType(Res).isPointer() && "invalid res type");
10160b57cec5SDimitry Andric #endif
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BLOCK_ADDR).addDef(Res).addBlockAddress(BA);
10190b57cec5SDimitry Andric }
10200b57cec5SDimitry Andric 
10215ffd83dbSDimitry Andric void MachineIRBuilder::validateTruncExt(const LLT DstTy, const LLT SrcTy,
10220b57cec5SDimitry Andric                                         bool IsExtend) {
10230b57cec5SDimitry Andric #ifndef NDEBUG
10240b57cec5SDimitry Andric   if (DstTy.isVector()) {
10250b57cec5SDimitry Andric     assert(SrcTy.isVector() && "mismatched cast between vector and non-vector");
10260b57cec5SDimitry Andric     assert(SrcTy.getNumElements() == DstTy.getNumElements() &&
10270b57cec5SDimitry Andric            "different number of elements in a trunc/ext");
10280b57cec5SDimitry Andric   } else
10290b57cec5SDimitry Andric     assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc");
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric   if (IsExtend)
10320b57cec5SDimitry Andric     assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&
10330b57cec5SDimitry Andric            "invalid narrowing extend");
10340b57cec5SDimitry Andric   else
10350b57cec5SDimitry Andric     assert(DstTy.getSizeInBits() < SrcTy.getSizeInBits() &&
10360b57cec5SDimitry Andric            "invalid widening trunc");
10370b57cec5SDimitry Andric #endif
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric 
10405ffd83dbSDimitry Andric void MachineIRBuilder::validateSelectOp(const LLT ResTy, const LLT TstTy,
10415ffd83dbSDimitry Andric                                         const LLT Op0Ty, const LLT Op1Ty) {
10420b57cec5SDimitry Andric #ifndef NDEBUG
10430b57cec5SDimitry Andric   assert((ResTy.isScalar() || ResTy.isVector() || ResTy.isPointer()) &&
10440b57cec5SDimitry Andric          "invalid operand type");
10450b57cec5SDimitry Andric   assert((ResTy == Op0Ty && ResTy == Op1Ty) && "type mismatch");
10460b57cec5SDimitry Andric   if (ResTy.isScalar() || ResTy.isPointer())
10470b57cec5SDimitry Andric     assert(TstTy.isScalar() && "type mismatch");
10480b57cec5SDimitry Andric   else
10490b57cec5SDimitry Andric     assert((TstTy.isScalar() ||
10500b57cec5SDimitry Andric             (TstTy.isVector() &&
10510b57cec5SDimitry Andric              TstTy.getNumElements() == Op0Ty.getNumElements())) &&
10520b57cec5SDimitry Andric            "type mismatch");
10530b57cec5SDimitry Andric #endif
10540b57cec5SDimitry Andric }
10550b57cec5SDimitry Andric 
1056*bdd1243dSDimitry Andric MachineInstrBuilder
1057*bdd1243dSDimitry Andric MachineIRBuilder::buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps,
10580b57cec5SDimitry Andric                              ArrayRef<SrcOp> SrcOps,
1059*bdd1243dSDimitry Andric                              std::optional<unsigned> Flags) {
10600b57cec5SDimitry Andric   switch (Opc) {
10610b57cec5SDimitry Andric   default:
10620b57cec5SDimitry Andric     break;
10630b57cec5SDimitry Andric   case TargetOpcode::G_SELECT: {
10640b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid select");
10650b57cec5SDimitry Andric     assert(SrcOps.size() == 3 && "Invalid select");
10660b57cec5SDimitry Andric     validateSelectOp(
10670b57cec5SDimitry Andric         DstOps[0].getLLTTy(*getMRI()), SrcOps[0].getLLTTy(*getMRI()),
10680b57cec5SDimitry Andric         SrcOps[1].getLLTTy(*getMRI()), SrcOps[2].getLLTTy(*getMRI()));
10690b57cec5SDimitry Andric     break;
10700b57cec5SDimitry Andric   }
1071e8d8bef9SDimitry Andric   case TargetOpcode::G_FNEG:
1072e8d8bef9SDimitry Andric   case TargetOpcode::G_ABS:
1073e8d8bef9SDimitry Andric     // All these are unary ops.
1074e8d8bef9SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
1075e8d8bef9SDimitry Andric     assert(SrcOps.size() == 1 && "Invalid Srcs");
1076e8d8bef9SDimitry Andric     validateUnaryOp(DstOps[0].getLLTTy(*getMRI()),
1077e8d8bef9SDimitry Andric                     SrcOps[0].getLLTTy(*getMRI()));
1078e8d8bef9SDimitry Andric     break;
10790b57cec5SDimitry Andric   case TargetOpcode::G_ADD:
10800b57cec5SDimitry Andric   case TargetOpcode::G_AND:
10810b57cec5SDimitry Andric   case TargetOpcode::G_MUL:
10820b57cec5SDimitry Andric   case TargetOpcode::G_OR:
10830b57cec5SDimitry Andric   case TargetOpcode::G_SUB:
10840b57cec5SDimitry Andric   case TargetOpcode::G_XOR:
10850b57cec5SDimitry Andric   case TargetOpcode::G_UDIV:
10860b57cec5SDimitry Andric   case TargetOpcode::G_SDIV:
10870b57cec5SDimitry Andric   case TargetOpcode::G_UREM:
10880b57cec5SDimitry Andric   case TargetOpcode::G_SREM:
10890b57cec5SDimitry Andric   case TargetOpcode::G_SMIN:
10900b57cec5SDimitry Andric   case TargetOpcode::G_SMAX:
10910b57cec5SDimitry Andric   case TargetOpcode::G_UMIN:
10925ffd83dbSDimitry Andric   case TargetOpcode::G_UMAX:
10935ffd83dbSDimitry Andric   case TargetOpcode::G_UADDSAT:
10945ffd83dbSDimitry Andric   case TargetOpcode::G_SADDSAT:
10955ffd83dbSDimitry Andric   case TargetOpcode::G_USUBSAT:
10965ffd83dbSDimitry Andric   case TargetOpcode::G_SSUBSAT: {
10970b57cec5SDimitry Andric     // All these are binary ops.
10980b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
10990b57cec5SDimitry Andric     assert(SrcOps.size() == 2 && "Invalid Srcs");
11000b57cec5SDimitry Andric     validateBinaryOp(DstOps[0].getLLTTy(*getMRI()),
11010b57cec5SDimitry Andric                      SrcOps[0].getLLTTy(*getMRI()),
11020b57cec5SDimitry Andric                      SrcOps[1].getLLTTy(*getMRI()));
11030b57cec5SDimitry Andric     break;
11040b57cec5SDimitry Andric   }
11050b57cec5SDimitry Andric   case TargetOpcode::G_SHL:
11060b57cec5SDimitry Andric   case TargetOpcode::G_ASHR:
1107e8d8bef9SDimitry Andric   case TargetOpcode::G_LSHR:
1108e8d8bef9SDimitry Andric   case TargetOpcode::G_USHLSAT:
1109e8d8bef9SDimitry Andric   case TargetOpcode::G_SSHLSAT: {
11100b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
11110b57cec5SDimitry Andric     assert(SrcOps.size() == 2 && "Invalid Srcs");
11120b57cec5SDimitry Andric     validateShiftOp(DstOps[0].getLLTTy(*getMRI()),
11130b57cec5SDimitry Andric                     SrcOps[0].getLLTTy(*getMRI()),
11140b57cec5SDimitry Andric                     SrcOps[1].getLLTTy(*getMRI()));
11150b57cec5SDimitry Andric     break;
11160b57cec5SDimitry Andric   }
11170b57cec5SDimitry Andric   case TargetOpcode::G_SEXT:
11180b57cec5SDimitry Andric   case TargetOpcode::G_ZEXT:
11190b57cec5SDimitry Andric   case TargetOpcode::G_ANYEXT:
11200b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
11210b57cec5SDimitry Andric     assert(SrcOps.size() == 1 && "Invalid Srcs");
11220b57cec5SDimitry Andric     validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
11230b57cec5SDimitry Andric                      SrcOps[0].getLLTTy(*getMRI()), true);
11240b57cec5SDimitry Andric     break;
11250b57cec5SDimitry Andric   case TargetOpcode::G_TRUNC:
11260b57cec5SDimitry Andric   case TargetOpcode::G_FPTRUNC: {
11270b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
11280b57cec5SDimitry Andric     assert(SrcOps.size() == 1 && "Invalid Srcs");
11290b57cec5SDimitry Andric     validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
11300b57cec5SDimitry Andric                      SrcOps[0].getLLTTy(*getMRI()), false);
11310b57cec5SDimitry Andric     break;
11320b57cec5SDimitry Andric   }
11335ffd83dbSDimitry Andric   case TargetOpcode::G_BITCAST: {
11345ffd83dbSDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
11355ffd83dbSDimitry Andric     assert(SrcOps.size() == 1 && "Invalid Srcs");
11365ffd83dbSDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
11375ffd83dbSDimitry Andric            SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() && "invalid bitcast");
11385ffd83dbSDimitry Andric     break;
11395ffd83dbSDimitry Andric   }
11400b57cec5SDimitry Andric   case TargetOpcode::COPY:
11410b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
11420b57cec5SDimitry Andric     // If the caller wants to add a subreg source it has to be done separately
11430b57cec5SDimitry Andric     // so we may not have any SrcOps at this point yet.
11440b57cec5SDimitry Andric     break;
11450b57cec5SDimitry Andric   case TargetOpcode::G_FCMP:
11460b57cec5SDimitry Andric   case TargetOpcode::G_ICMP: {
11470b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst Operands");
11480b57cec5SDimitry Andric     assert(SrcOps.size() == 3 && "Invalid Src Operands");
11490b57cec5SDimitry Andric     // For F/ICMP, the first src operand is the predicate, followed by
11500b57cec5SDimitry Andric     // the two comparands.
11510b57cec5SDimitry Andric     assert(SrcOps[0].getSrcOpKind() == SrcOp::SrcType::Ty_Predicate &&
11520b57cec5SDimitry Andric            "Expecting predicate");
11530b57cec5SDimitry Andric     assert([&]() -> bool {
11540b57cec5SDimitry Andric       CmpInst::Predicate Pred = SrcOps[0].getPredicate();
11550b57cec5SDimitry Andric       return Opc == TargetOpcode::G_ICMP ? CmpInst::isIntPredicate(Pred)
11560b57cec5SDimitry Andric                                          : CmpInst::isFPPredicate(Pred);
11570b57cec5SDimitry Andric     }() && "Invalid predicate");
11580b57cec5SDimitry Andric     assert(SrcOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
11590b57cec5SDimitry Andric            "Type mismatch");
11600b57cec5SDimitry Andric     assert([&]() -> bool {
11610b57cec5SDimitry Andric       LLT Op0Ty = SrcOps[1].getLLTTy(*getMRI());
11620b57cec5SDimitry Andric       LLT DstTy = DstOps[0].getLLTTy(*getMRI());
11630b57cec5SDimitry Andric       if (Op0Ty.isScalar() || Op0Ty.isPointer())
11640b57cec5SDimitry Andric         return DstTy.isScalar();
11650b57cec5SDimitry Andric       else
11660b57cec5SDimitry Andric         return DstTy.isVector() &&
11670b57cec5SDimitry Andric                DstTy.getNumElements() == Op0Ty.getNumElements();
11680b57cec5SDimitry Andric     }() && "Type Mismatch");
11690b57cec5SDimitry Andric     break;
11700b57cec5SDimitry Andric   }
11710b57cec5SDimitry Andric   case TargetOpcode::G_UNMERGE_VALUES: {
11720b57cec5SDimitry Andric     assert(!DstOps.empty() && "Invalid trivial sequence");
11730b57cec5SDimitry Andric     assert(SrcOps.size() == 1 && "Invalid src for Unmerge");
1174e8d8bef9SDimitry Andric     assert(llvm::all_of(DstOps,
11750b57cec5SDimitry Andric                         [&, this](const DstOp &Op) {
11760b57cec5SDimitry Andric                           return Op.getLLTTy(*getMRI()) ==
11770b57cec5SDimitry Andric                                  DstOps[0].getLLTTy(*getMRI());
11780b57cec5SDimitry Andric                         }) &&
11790b57cec5SDimitry Andric            "type mismatch in output list");
1180fe6060f1SDimitry Andric     assert((TypeSize::ScalarTy)DstOps.size() *
1181fe6060f1SDimitry Andric                    DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
11820b57cec5SDimitry Andric                SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
11830b57cec5SDimitry Andric            "input operands do not cover output register");
11840b57cec5SDimitry Andric     break;
11850b57cec5SDimitry Andric   }
11860b57cec5SDimitry Andric   case TargetOpcode::G_MERGE_VALUES: {
1187*bdd1243dSDimitry Andric     assert(SrcOps.size() >= 2 && "invalid trivial sequence");
11880b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
1189e8d8bef9SDimitry Andric     assert(llvm::all_of(SrcOps,
11900b57cec5SDimitry Andric                         [&, this](const SrcOp &Op) {
11910b57cec5SDimitry Andric                           return Op.getLLTTy(*getMRI()) ==
11920b57cec5SDimitry Andric                                  SrcOps[0].getLLTTy(*getMRI());
11930b57cec5SDimitry Andric                         }) &&
11940b57cec5SDimitry Andric            "type mismatch in input list");
1195fe6060f1SDimitry Andric     assert((TypeSize::ScalarTy)SrcOps.size() *
1196fe6060f1SDimitry Andric                    SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
11970b57cec5SDimitry Andric                DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
11980b57cec5SDimitry Andric            "input operands do not cover output register");
1199*bdd1243dSDimitry Andric     assert(!DstOps[0].getLLTTy(*getMRI()).isVector() &&
1200*bdd1243dSDimitry Andric            "vectors should be built with G_CONCAT_VECTOR or G_BUILD_VECTOR");
12010b57cec5SDimitry Andric     break;
12020b57cec5SDimitry Andric   }
12030b57cec5SDimitry Andric   case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
12040b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst size");
12050b57cec5SDimitry Andric     assert(SrcOps.size() == 2 && "Invalid Src size");
12060b57cec5SDimitry Andric     assert(SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
12070b57cec5SDimitry Andric     assert((DstOps[0].getLLTTy(*getMRI()).isScalar() ||
12080b57cec5SDimitry Andric             DstOps[0].getLLTTy(*getMRI()).isPointer()) &&
12090b57cec5SDimitry Andric            "Invalid operand type");
12100b57cec5SDimitry Andric     assert(SrcOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand type");
12110b57cec5SDimitry Andric     assert(SrcOps[0].getLLTTy(*getMRI()).getElementType() ==
12120b57cec5SDimitry Andric                DstOps[0].getLLTTy(*getMRI()) &&
12130b57cec5SDimitry Andric            "Type mismatch");
12140b57cec5SDimitry Andric     break;
12150b57cec5SDimitry Andric   }
12160b57cec5SDimitry Andric   case TargetOpcode::G_INSERT_VECTOR_ELT: {
12170b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid dst size");
12180b57cec5SDimitry Andric     assert(SrcOps.size() == 3 && "Invalid src size");
12190b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
12200b57cec5SDimitry Andric            SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
12210b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).getElementType() ==
12220b57cec5SDimitry Andric                SrcOps[1].getLLTTy(*getMRI()) &&
12230b57cec5SDimitry Andric            "Type mismatch");
12240b57cec5SDimitry Andric     assert(SrcOps[2].getLLTTy(*getMRI()).isScalar() && "Invalid index");
12250b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).getNumElements() ==
12260b57cec5SDimitry Andric                SrcOps[0].getLLTTy(*getMRI()).getNumElements() &&
12270b57cec5SDimitry Andric            "Type mismatch");
12280b57cec5SDimitry Andric     break;
12290b57cec5SDimitry Andric   }
12300b57cec5SDimitry Andric   case TargetOpcode::G_BUILD_VECTOR: {
12310b57cec5SDimitry Andric     assert((!SrcOps.empty() || SrcOps.size() < 2) &&
12320b57cec5SDimitry Andric            "Must have at least 2 operands");
12330b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid DstOps");
12340b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
12350b57cec5SDimitry Andric            "Res type must be a vector");
1236e8d8bef9SDimitry Andric     assert(llvm::all_of(SrcOps,
12370b57cec5SDimitry Andric                         [&, this](const SrcOp &Op) {
12380b57cec5SDimitry Andric                           return Op.getLLTTy(*getMRI()) ==
12390b57cec5SDimitry Andric                                  SrcOps[0].getLLTTy(*getMRI());
12400b57cec5SDimitry Andric                         }) &&
12410b57cec5SDimitry Andric            "type mismatch in input list");
1242fe6060f1SDimitry Andric     assert((TypeSize::ScalarTy)SrcOps.size() *
1243fe6060f1SDimitry Andric                    SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
12440b57cec5SDimitry Andric                DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
12450b57cec5SDimitry Andric            "input scalars do not exactly cover the output vector register");
12460b57cec5SDimitry Andric     break;
12470b57cec5SDimitry Andric   }
12480b57cec5SDimitry Andric   case TargetOpcode::G_BUILD_VECTOR_TRUNC: {
12490b57cec5SDimitry Andric     assert((!SrcOps.empty() || SrcOps.size() < 2) &&
12500b57cec5SDimitry Andric            "Must have at least 2 operands");
12510b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid DstOps");
12520b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
12530b57cec5SDimitry Andric            "Res type must be a vector");
1254e8d8bef9SDimitry Andric     assert(llvm::all_of(SrcOps,
12550b57cec5SDimitry Andric                         [&, this](const SrcOp &Op) {
12560b57cec5SDimitry Andric                           return Op.getLLTTy(*getMRI()) ==
12570b57cec5SDimitry Andric                                  SrcOps[0].getLLTTy(*getMRI());
12580b57cec5SDimitry Andric                         }) &&
12590b57cec5SDimitry Andric            "type mismatch in input list");
12600b57cec5SDimitry Andric     break;
12610b57cec5SDimitry Andric   }
12620b57cec5SDimitry Andric   case TargetOpcode::G_CONCAT_VECTORS: {
12630b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid DstOps");
12640b57cec5SDimitry Andric     assert((!SrcOps.empty() || SrcOps.size() < 2) &&
12650b57cec5SDimitry Andric            "Must have at least 2 operands");
1266e8d8bef9SDimitry Andric     assert(llvm::all_of(SrcOps,
12670b57cec5SDimitry Andric                         [&, this](const SrcOp &Op) {
12680b57cec5SDimitry Andric                           return (Op.getLLTTy(*getMRI()).isVector() &&
12690b57cec5SDimitry Andric                                   Op.getLLTTy(*getMRI()) ==
12700b57cec5SDimitry Andric                                       SrcOps[0].getLLTTy(*getMRI()));
12710b57cec5SDimitry Andric                         }) &&
12720b57cec5SDimitry Andric            "type mismatch in input list");
1273fe6060f1SDimitry Andric     assert((TypeSize::ScalarTy)SrcOps.size() *
1274fe6060f1SDimitry Andric                    SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
12750b57cec5SDimitry Andric                DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
12760b57cec5SDimitry Andric            "input vectors do not exactly cover the output vector register");
12770b57cec5SDimitry Andric     break;
12780b57cec5SDimitry Andric   }
12790b57cec5SDimitry Andric   case TargetOpcode::G_UADDE: {
12800b57cec5SDimitry Andric     assert(DstOps.size() == 2 && "Invalid no of dst operands");
12810b57cec5SDimitry Andric     assert(SrcOps.size() == 3 && "Invalid no of src operands");
12820b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
12830b57cec5SDimitry Andric     assert((DstOps[0].getLLTTy(*getMRI()) == SrcOps[0].getLLTTy(*getMRI())) &&
12840b57cec5SDimitry Andric            (DstOps[0].getLLTTy(*getMRI()) == SrcOps[1].getLLTTy(*getMRI())) &&
12850b57cec5SDimitry Andric            "Invalid operand");
12860b57cec5SDimitry Andric     assert(DstOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
12870b57cec5SDimitry Andric     assert(DstOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
12880b57cec5SDimitry Andric            "type mismatch");
12890b57cec5SDimitry Andric     break;
12900b57cec5SDimitry Andric   }
12910b57cec5SDimitry Andric   }
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric   auto MIB = buildInstr(Opc);
12940b57cec5SDimitry Andric   for (const DstOp &Op : DstOps)
12950b57cec5SDimitry Andric     Op.addDefToMIB(*getMRI(), MIB);
12960b57cec5SDimitry Andric   for (const SrcOp &Op : SrcOps)
12970b57cec5SDimitry Andric     Op.addSrcToMIB(MIB);
12980b57cec5SDimitry Andric   if (Flags)
12990b57cec5SDimitry Andric     MIB->setFlags(*Flags);
13000b57cec5SDimitry Andric   return MIB;
13010b57cec5SDimitry Andric }
1302