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
setMF(MachineFunction & MF)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();
30bdd1243dSDimitry Andric State.PCSections = nullptr;
31*0fca6ea1SDimitry Andric State.MMRA = nullptr;
320b57cec5SDimitry Andric State.II = MachineBasicBlock::iterator();
330b57cec5SDimitry Andric State.Observer = nullptr;
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric //------------------------------------------------------------------------------
370b57cec5SDimitry Andric // Build instruction variants.
380b57cec5SDimitry Andric //------------------------------------------------------------------------------
390b57cec5SDimitry Andric
buildInstrNoInsert(unsigned Opcode)400b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildInstrNoInsert(unsigned Opcode) {
41*0fca6ea1SDimitry Andric return BuildMI(getMF(), {getDL(), getPCSections(), getMMRAMetadata()},
42*0fca6ea1SDimitry Andric getTII().get(Opcode));
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric
insertInstr(MachineInstrBuilder MIB)450b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::insertInstr(MachineInstrBuilder MIB) {
460b57cec5SDimitry Andric getMBB().insert(getInsertPt(), MIB);
470b57cec5SDimitry Andric recordInsertion(MIB);
480b57cec5SDimitry Andric return MIB;
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric MachineInstrBuilder
buildDirectDbgValue(Register Reg,const MDNode * Variable,const MDNode * Expr)520b57cec5SDimitry Andric MachineIRBuilder::buildDirectDbgValue(Register Reg, const MDNode *Variable,
530b57cec5SDimitry Andric const MDNode *Expr) {
540b57cec5SDimitry Andric assert(isa<DILocalVariable>(Variable) && "not a variable");
550b57cec5SDimitry Andric assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
560b57cec5SDimitry Andric assert(
570b57cec5SDimitry Andric cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
580b57cec5SDimitry Andric "Expected inlined-at fields to agree");
590b57cec5SDimitry Andric return insertInstr(BuildMI(getMF(), getDL(),
600b57cec5SDimitry Andric getTII().get(TargetOpcode::DBG_VALUE),
610b57cec5SDimitry Andric /*IsIndirect*/ false, Reg, Variable, Expr));
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric MachineInstrBuilder
buildIndirectDbgValue(Register Reg,const MDNode * Variable,const MDNode * Expr)650b57cec5SDimitry Andric MachineIRBuilder::buildIndirectDbgValue(Register Reg, const MDNode *Variable,
660b57cec5SDimitry Andric const MDNode *Expr) {
670b57cec5SDimitry Andric assert(isa<DILocalVariable>(Variable) && "not a variable");
680b57cec5SDimitry Andric assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
690b57cec5SDimitry Andric assert(
700b57cec5SDimitry Andric cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
710b57cec5SDimitry Andric "Expected inlined-at fields to agree");
720b57cec5SDimitry Andric return insertInstr(BuildMI(getMF(), getDL(),
730b57cec5SDimitry Andric getTII().get(TargetOpcode::DBG_VALUE),
7413138422SDimitry Andric /*IsIndirect*/ true, Reg, Variable, Expr));
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric
buildFIDbgValue(int FI,const MDNode * Variable,const MDNode * Expr)770b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFIDbgValue(int FI,
780b57cec5SDimitry Andric const MDNode *Variable,
790b57cec5SDimitry Andric const MDNode *Expr) {
800b57cec5SDimitry Andric assert(isa<DILocalVariable>(Variable) && "not a variable");
810b57cec5SDimitry Andric assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
820b57cec5SDimitry Andric assert(
830b57cec5SDimitry Andric cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
840b57cec5SDimitry Andric "Expected inlined-at fields to agree");
8506c3fb27SDimitry Andric return insertInstr(buildInstrNoInsert(TargetOpcode::DBG_VALUE)
860b57cec5SDimitry Andric .addFrameIndex(FI)
8713138422SDimitry Andric .addImm(0)
880b57cec5SDimitry Andric .addMetadata(Variable)
8906c3fb27SDimitry Andric .addMetadata(Expr));
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
buildConstDbgValue(const Constant & C,const MDNode * Variable,const MDNode * Expr)920b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstDbgValue(const Constant &C,
930b57cec5SDimitry Andric const MDNode *Variable,
940b57cec5SDimitry Andric const MDNode *Expr) {
950b57cec5SDimitry Andric assert(isa<DILocalVariable>(Variable) && "not a variable");
960b57cec5SDimitry Andric assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
970b57cec5SDimitry Andric assert(
980b57cec5SDimitry Andric cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
990b57cec5SDimitry Andric "Expected inlined-at fields to agree");
1005ffd83dbSDimitry Andric auto MIB = buildInstrNoInsert(TargetOpcode::DBG_VALUE);
101bdd1243dSDimitry Andric
102bdd1243dSDimitry Andric auto *NumericConstant = [&] () -> const Constant* {
103bdd1243dSDimitry Andric if (const auto *CE = dyn_cast<ConstantExpr>(&C))
104bdd1243dSDimitry Andric if (CE->getOpcode() == Instruction::IntToPtr)
105bdd1243dSDimitry Andric return CE->getOperand(0);
106bdd1243dSDimitry Andric return &C;
107bdd1243dSDimitry Andric }();
108bdd1243dSDimitry Andric
109bdd1243dSDimitry Andric if (auto *CI = dyn_cast<ConstantInt>(NumericConstant)) {
1100b57cec5SDimitry Andric if (CI->getBitWidth() > 64)
1110b57cec5SDimitry Andric MIB.addCImm(CI);
1120b57cec5SDimitry Andric else
1130b57cec5SDimitry Andric MIB.addImm(CI->getZExtValue());
114bdd1243dSDimitry Andric } else if (auto *CFP = dyn_cast<ConstantFP>(NumericConstant)) {
1150b57cec5SDimitry Andric MIB.addFPImm(CFP);
116bdd1243dSDimitry Andric } else if (isa<ConstantPointerNull>(NumericConstant)) {
117bdd1243dSDimitry Andric MIB.addImm(0);
1180b57cec5SDimitry Andric } else {
119e8d8bef9SDimitry Andric // Insert $noreg if we didn't find a usable constant and had to drop it.
120e8d8bef9SDimitry Andric MIB.addReg(Register());
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric
1235ffd83dbSDimitry Andric MIB.addImm(0).addMetadata(Variable).addMetadata(Expr);
1245ffd83dbSDimitry Andric return insertInstr(MIB);
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric
buildDbgLabel(const MDNode * Label)1270b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildDbgLabel(const MDNode *Label) {
1280b57cec5SDimitry Andric assert(isa<DILabel>(Label) && "not a label");
1290b57cec5SDimitry Andric assert(cast<DILabel>(Label)->isValidLocationForIntrinsic(State.DL) &&
1300b57cec5SDimitry Andric "Expected inlined-at fields to agree");
1310b57cec5SDimitry Andric auto MIB = buildInstr(TargetOpcode::DBG_LABEL);
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric return MIB.addMetadata(Label);
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric
buildDynStackAlloc(const DstOp & Res,const SrcOp & Size,Align Alignment)1368bcb0991SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildDynStackAlloc(const DstOp &Res,
1378bcb0991SDimitry Andric const SrcOp &Size,
1385ffd83dbSDimitry Andric Align Alignment) {
1398bcb0991SDimitry Andric assert(Res.getLLTTy(*getMRI()).isPointer() && "expected ptr dst type");
1408bcb0991SDimitry Andric auto MIB = buildInstr(TargetOpcode::G_DYN_STACKALLOC);
1418bcb0991SDimitry Andric Res.addDefToMIB(*getMRI(), MIB);
1428bcb0991SDimitry Andric Size.addSrcToMIB(MIB);
1435ffd83dbSDimitry Andric MIB.addImm(Alignment.value());
1448bcb0991SDimitry Andric return MIB;
1458bcb0991SDimitry Andric }
1468bcb0991SDimitry Andric
buildFrameIndex(const DstOp & Res,int Idx)1470b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFrameIndex(const DstOp &Res,
1480b57cec5SDimitry Andric int Idx) {
1490b57cec5SDimitry Andric assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
1500b57cec5SDimitry Andric auto MIB = buildInstr(TargetOpcode::G_FRAME_INDEX);
1510b57cec5SDimitry Andric Res.addDefToMIB(*getMRI(), MIB);
1520b57cec5SDimitry Andric MIB.addFrameIndex(Idx);
1530b57cec5SDimitry Andric return MIB;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric
buildGlobalValue(const DstOp & Res,const GlobalValue * GV)1560b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildGlobalValue(const DstOp &Res,
1570b57cec5SDimitry Andric const GlobalValue *GV) {
1580b57cec5SDimitry Andric assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
1590b57cec5SDimitry Andric assert(Res.getLLTTy(*getMRI()).getAddressSpace() ==
1600b57cec5SDimitry Andric GV->getType()->getAddressSpace() &&
1610b57cec5SDimitry Andric "address space mismatch");
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric auto MIB = buildInstr(TargetOpcode::G_GLOBAL_VALUE);
1640b57cec5SDimitry Andric Res.addDefToMIB(*getMRI(), MIB);
1650b57cec5SDimitry Andric MIB.addGlobalAddress(GV);
1660b57cec5SDimitry Andric return MIB;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric
buildConstantPool(const DstOp & Res,unsigned Idx)16906c3fb27SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstantPool(const DstOp &Res,
17006c3fb27SDimitry Andric unsigned Idx) {
17106c3fb27SDimitry Andric assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
17206c3fb27SDimitry Andric auto MIB = buildInstr(TargetOpcode::G_CONSTANT_POOL);
17306c3fb27SDimitry Andric Res.addDefToMIB(*getMRI(), MIB);
17406c3fb27SDimitry Andric MIB.addConstantPoolIndex(Idx);
17506c3fb27SDimitry Andric return MIB;
17606c3fb27SDimitry Andric }
17706c3fb27SDimitry Andric
buildJumpTable(const LLT PtrTy,unsigned JTI)1780b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildJumpTable(const LLT PtrTy,
1790b57cec5SDimitry Andric unsigned JTI) {
1800b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_JUMP_TABLE, {PtrTy}, {})
1810b57cec5SDimitry Andric .addJumpTableIndex(JTI);
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric
validateUnaryOp(const LLT Res,const LLT Op0)184e8d8bef9SDimitry Andric void MachineIRBuilder::validateUnaryOp(const LLT Res, const LLT Op0) {
185e8d8bef9SDimitry Andric assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
186e8d8bef9SDimitry Andric assert((Res == Op0) && "type mismatch");
187e8d8bef9SDimitry Andric }
188e8d8bef9SDimitry Andric
validateBinaryOp(const LLT Res,const LLT Op0,const LLT Op1)1895ffd83dbSDimitry Andric void MachineIRBuilder::validateBinaryOp(const LLT Res, const LLT Op0,
1905ffd83dbSDimitry Andric const LLT Op1) {
1910b57cec5SDimitry Andric assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
1920b57cec5SDimitry Andric assert((Res == Op0 && Res == Op1) && "type mismatch");
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric
validateShiftOp(const LLT Res,const LLT Op0,const LLT Op1)1955ffd83dbSDimitry Andric void MachineIRBuilder::validateShiftOp(const LLT Res, const LLT Op0,
1965ffd83dbSDimitry Andric const LLT Op1) {
1970b57cec5SDimitry Andric assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
1980b57cec5SDimitry Andric assert((Res == Op0) && "type mismatch");
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric
2015f757f3fSDimitry Andric MachineInstrBuilder
buildPtrAdd(const DstOp & Res,const SrcOp & Op0,const SrcOp & Op1,std::optional<unsigned> Flags)2025f757f3fSDimitry Andric MachineIRBuilder::buildPtrAdd(const DstOp &Res, const SrcOp &Op0,
2035f757f3fSDimitry Andric const SrcOp &Op1, std::optional<unsigned> Flags) {
204*0fca6ea1SDimitry Andric assert(Res.getLLTTy(*getMRI()).isPointerOrPointerVector() &&
2050b57cec5SDimitry Andric Res.getLLTTy(*getMRI()) == Op0.getLLTTy(*getMRI()) && "type mismatch");
2065ffd83dbSDimitry Andric assert(Op1.getLLTTy(*getMRI()).getScalarType().isScalar() && "invalid offset type");
2070b57cec5SDimitry Andric
2085f757f3fSDimitry Andric return buildInstr(TargetOpcode::G_PTR_ADD, {Res}, {Op0, Op1}, Flags);
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric
211bdd1243dSDimitry Andric std::optional<MachineInstrBuilder>
materializePtrAdd(Register & Res,Register Op0,const LLT ValueTy,uint64_t Value)212480093f4SDimitry Andric MachineIRBuilder::materializePtrAdd(Register &Res, Register Op0,
2135ffd83dbSDimitry Andric const LLT ValueTy, uint64_t Value) {
2140b57cec5SDimitry Andric assert(Res == 0 && "Res is a result argument");
2150b57cec5SDimitry Andric assert(ValueTy.isScalar() && "invalid offset type");
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric if (Value == 0) {
2180b57cec5SDimitry Andric Res = Op0;
219bdd1243dSDimitry Andric return std::nullopt;
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric
2220b57cec5SDimitry Andric Res = getMRI()->createGenericVirtualRegister(getMRI()->getType(Op0));
2230b57cec5SDimitry Andric auto Cst = buildConstant(ValueTy, Value);
224480093f4SDimitry Andric return buildPtrAdd(Res, Op0, Cst.getReg(0));
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric
buildMaskLowPtrBits(const DstOp & Res,const SrcOp & Op0,uint32_t NumBits)2275ffd83dbSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildMaskLowPtrBits(const DstOp &Res,
2280b57cec5SDimitry Andric const SrcOp &Op0,
2290b57cec5SDimitry Andric uint32_t NumBits) {
2305ffd83dbSDimitry Andric LLT PtrTy = Res.getLLTTy(*getMRI());
2315ffd83dbSDimitry Andric LLT MaskTy = LLT::scalar(PtrTy.getSizeInBits());
2325ffd83dbSDimitry Andric Register MaskReg = getMRI()->createGenericVirtualRegister(MaskTy);
2335ffd83dbSDimitry Andric buildConstant(MaskReg, maskTrailingZeros<uint64_t>(NumBits));
2345ffd83dbSDimitry Andric return buildPtrMask(Res, Op0, MaskReg);
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric
2370eae32dcSDimitry Andric MachineInstrBuilder
buildPadVectorWithUndefElements(const DstOp & Res,const SrcOp & Op0)2380eae32dcSDimitry Andric MachineIRBuilder::buildPadVectorWithUndefElements(const DstOp &Res,
2390eae32dcSDimitry Andric const SrcOp &Op0) {
2400eae32dcSDimitry Andric LLT ResTy = Res.getLLTTy(*getMRI());
2410eae32dcSDimitry Andric LLT Op0Ty = Op0.getLLTTy(*getMRI());
2420eae32dcSDimitry Andric
24306c3fb27SDimitry Andric assert(ResTy.isVector() && "Res non vector type");
24406c3fb27SDimitry Andric
24506c3fb27SDimitry Andric SmallVector<Register, 8> Regs;
24606c3fb27SDimitry Andric if (Op0Ty.isVector()) {
2470eae32dcSDimitry Andric assert((ResTy.getElementType() == Op0Ty.getElementType()) &&
2480eae32dcSDimitry Andric "Different vector element types");
2490eae32dcSDimitry Andric assert((ResTy.getNumElements() > Op0Ty.getNumElements()) &&
2500eae32dcSDimitry Andric "Op0 has more elements");
2510eae32dcSDimitry Andric auto Unmerge = buildUnmerge(Op0Ty.getElementType(), Op0);
25206c3fb27SDimitry Andric
2530eae32dcSDimitry Andric for (auto Op : Unmerge.getInstr()->defs())
2540eae32dcSDimitry Andric Regs.push_back(Op.getReg());
25506c3fb27SDimitry Andric } else {
25606c3fb27SDimitry Andric assert((ResTy.getSizeInBits() > Op0Ty.getSizeInBits()) &&
25706c3fb27SDimitry Andric "Op0 has more size");
25806c3fb27SDimitry Andric Regs.push_back(Op0.getReg());
25906c3fb27SDimitry Andric }
26006c3fb27SDimitry Andric Register Undef =
26106c3fb27SDimitry Andric buildUndef(Op0Ty.isVector() ? Op0Ty.getElementType() : Op0Ty).getReg(0);
2620eae32dcSDimitry Andric unsigned NumberOfPadElts = ResTy.getNumElements() - Regs.size();
2630eae32dcSDimitry Andric for (unsigned i = 0; i < NumberOfPadElts; ++i)
2640eae32dcSDimitry Andric Regs.push_back(Undef);
265bdd1243dSDimitry Andric return buildMergeLikeInstr(Res, Regs);
2660eae32dcSDimitry Andric }
2670eae32dcSDimitry Andric
2680eae32dcSDimitry Andric MachineInstrBuilder
buildDeleteTrailingVectorElements(const DstOp & Res,const SrcOp & Op0)2690eae32dcSDimitry Andric MachineIRBuilder::buildDeleteTrailingVectorElements(const DstOp &Res,
2700eae32dcSDimitry Andric const SrcOp &Op0) {
2710eae32dcSDimitry Andric LLT ResTy = Res.getLLTTy(*getMRI());
2720eae32dcSDimitry Andric LLT Op0Ty = Op0.getLLTTy(*getMRI());
2730eae32dcSDimitry Andric
274*0fca6ea1SDimitry Andric assert(Op0Ty.isVector() && "Non vector type");
275*0fca6ea1SDimitry Andric assert(((ResTy.isScalar() && (ResTy == Op0Ty.getElementType())) ||
276*0fca6ea1SDimitry Andric (ResTy.isVector() &&
277*0fca6ea1SDimitry Andric (ResTy.getElementType() == Op0Ty.getElementType()))) &&
2780eae32dcSDimitry Andric "Different vector element types");
279*0fca6ea1SDimitry Andric assert(
280*0fca6ea1SDimitry Andric (ResTy.isScalar() || (ResTy.getNumElements() < Op0Ty.getNumElements())) &&
2810eae32dcSDimitry Andric "Op0 has fewer elements");
2820eae32dcSDimitry Andric
2830eae32dcSDimitry Andric auto Unmerge = buildUnmerge(Op0Ty.getElementType(), Op0);
284*0fca6ea1SDimitry Andric if (ResTy.isScalar())
285*0fca6ea1SDimitry Andric return buildCopy(Res, Unmerge.getReg(0));
286*0fca6ea1SDimitry Andric SmallVector<Register, 8> Regs;
2870eae32dcSDimitry Andric for (unsigned i = 0; i < ResTy.getNumElements(); ++i)
2880eae32dcSDimitry Andric Regs.push_back(Unmerge.getReg(i));
289bdd1243dSDimitry Andric return buildMergeLikeInstr(Res, Regs);
2900eae32dcSDimitry Andric }
2910eae32dcSDimitry Andric
buildBr(MachineBasicBlock & Dest)2920b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
2930b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_BR).addMBB(&Dest);
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
buildBrIndirect(Register Tgt)2960b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBrIndirect(Register Tgt) {
2970b57cec5SDimitry Andric assert(getMRI()->getType(Tgt).isPointer() && "invalid branch destination");
2980b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_BRINDIRECT).addUse(Tgt);
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric
buildBrJT(Register TablePtr,unsigned JTI,Register IndexReg)3010b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBrJT(Register TablePtr,
3020b57cec5SDimitry Andric unsigned JTI,
3030b57cec5SDimitry Andric Register IndexReg) {
3040b57cec5SDimitry Andric assert(getMRI()->getType(TablePtr).isPointer() &&
3050b57cec5SDimitry Andric "Table reg must be a pointer");
3060b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_BRJT)
3070b57cec5SDimitry Andric .addUse(TablePtr)
3080b57cec5SDimitry Andric .addJumpTableIndex(JTI)
3090b57cec5SDimitry Andric .addUse(IndexReg);
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric
buildCopy(const DstOp & Res,const SrcOp & Op)3120b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildCopy(const DstOp &Res,
3130b57cec5SDimitry Andric const SrcOp &Op) {
3140b57cec5SDimitry Andric return buildInstr(TargetOpcode::COPY, Res, Op);
3150b57cec5SDimitry Andric }
3160b57cec5SDimitry Andric
buildConstant(const DstOp & Res,const ConstantInt & Val)3170b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
3180b57cec5SDimitry Andric const ConstantInt &Val) {
3190b57cec5SDimitry Andric LLT Ty = Res.getLLTTy(*getMRI());
3200b57cec5SDimitry Andric LLT EltTy = Ty.getScalarType();
3210b57cec5SDimitry Andric assert(EltTy.getScalarSizeInBits() == Val.getBitWidth() &&
3220b57cec5SDimitry Andric "creating constant with the wrong size");
3230b57cec5SDimitry Andric
3245f757f3fSDimitry Andric assert(!Ty.isScalableVector() &&
3255f757f3fSDimitry Andric "unexpected scalable vector in buildConstant");
3265f757f3fSDimitry Andric
3275f757f3fSDimitry Andric if (Ty.isFixedVector()) {
3280b57cec5SDimitry Andric auto Const = buildInstr(TargetOpcode::G_CONSTANT)
3290b57cec5SDimitry Andric .addDef(getMRI()->createGenericVirtualRegister(EltTy))
3300b57cec5SDimitry Andric .addCImm(&Val);
331*0fca6ea1SDimitry Andric return buildSplatBuildVector(Res, Const);
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andric auto Const = buildInstr(TargetOpcode::G_CONSTANT);
3355ffd83dbSDimitry Andric Const->setDebugLoc(DebugLoc());
3360b57cec5SDimitry Andric Res.addDefToMIB(*getMRI(), Const);
3370b57cec5SDimitry Andric Const.addCImm(&Val);
3380b57cec5SDimitry Andric return Const;
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric
buildConstant(const DstOp & Res,int64_t Val)3410b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
3420b57cec5SDimitry Andric int64_t Val) {
3430b57cec5SDimitry Andric auto IntN = IntegerType::get(getMF().getFunction().getContext(),
3440b57cec5SDimitry Andric Res.getLLTTy(*getMRI()).getScalarSizeInBits());
3450b57cec5SDimitry Andric ConstantInt *CI = ConstantInt::get(IntN, Val, true);
3460b57cec5SDimitry Andric return buildConstant(Res, *CI);
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric
buildFConstant(const DstOp & Res,const ConstantFP & Val)3490b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
3500b57cec5SDimitry Andric const ConstantFP &Val) {
3510b57cec5SDimitry Andric LLT Ty = Res.getLLTTy(*getMRI());
3520b57cec5SDimitry Andric LLT EltTy = Ty.getScalarType();
3530b57cec5SDimitry Andric
3540b57cec5SDimitry Andric assert(APFloat::getSizeInBits(Val.getValueAPF().getSemantics())
3550b57cec5SDimitry Andric == EltTy.getSizeInBits() &&
3560b57cec5SDimitry Andric "creating fconstant with the wrong size");
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andric assert(!Ty.isPointer() && "invalid operand type");
3590b57cec5SDimitry Andric
3605f757f3fSDimitry Andric assert(!Ty.isScalableVector() &&
3615f757f3fSDimitry Andric "unexpected scalable vector in buildFConstant");
3625f757f3fSDimitry Andric
3635f757f3fSDimitry Andric if (Ty.isFixedVector()) {
3640b57cec5SDimitry Andric auto Const = buildInstr(TargetOpcode::G_FCONSTANT)
3650b57cec5SDimitry Andric .addDef(getMRI()->createGenericVirtualRegister(EltTy))
3660b57cec5SDimitry Andric .addFPImm(&Val);
3670b57cec5SDimitry Andric
368*0fca6ea1SDimitry Andric return buildSplatBuildVector(Res, Const);
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric
3710b57cec5SDimitry Andric auto Const = buildInstr(TargetOpcode::G_FCONSTANT);
3725ffd83dbSDimitry Andric Const->setDebugLoc(DebugLoc());
3730b57cec5SDimitry Andric Res.addDefToMIB(*getMRI(), Const);
3740b57cec5SDimitry Andric Const.addFPImm(&Val);
3750b57cec5SDimitry Andric return Const;
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric
buildConstant(const DstOp & Res,const APInt & Val)3780b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
3790b57cec5SDimitry Andric const APInt &Val) {
3800b57cec5SDimitry Andric ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(), Val);
3810b57cec5SDimitry Andric return buildConstant(Res, *CI);
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric
buildFConstant(const DstOp & Res,double Val)3840b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
3850b57cec5SDimitry Andric double Val) {
3860b57cec5SDimitry Andric LLT DstTy = Res.getLLTTy(*getMRI());
3870b57cec5SDimitry Andric auto &Ctx = getMF().getFunction().getContext();
3880b57cec5SDimitry Andric auto *CFP =
3890b57cec5SDimitry Andric ConstantFP::get(Ctx, getAPFloatFromSize(Val, DstTy.getScalarSizeInBits()));
3900b57cec5SDimitry Andric return buildFConstant(Res, *CFP);
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric
buildFConstant(const DstOp & Res,const APFloat & Val)3930b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
3940b57cec5SDimitry Andric const APFloat &Val) {
3950b57cec5SDimitry Andric auto &Ctx = getMF().getFunction().getContext();
3960b57cec5SDimitry Andric auto *CFP = ConstantFP::get(Ctx, Val);
3970b57cec5SDimitry Andric return buildFConstant(Res, *CFP);
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric
400*0fca6ea1SDimitry Andric MachineInstrBuilder
buildConstantPtrAuth(const DstOp & Res,const ConstantPtrAuth * CPA,Register Addr,Register AddrDisc)401*0fca6ea1SDimitry Andric MachineIRBuilder::buildConstantPtrAuth(const DstOp &Res,
402*0fca6ea1SDimitry Andric const ConstantPtrAuth *CPA,
403*0fca6ea1SDimitry Andric Register Addr, Register AddrDisc) {
404*0fca6ea1SDimitry Andric auto MIB = buildInstr(TargetOpcode::G_PTRAUTH_GLOBAL_VALUE);
405*0fca6ea1SDimitry Andric Res.addDefToMIB(*getMRI(), MIB);
406*0fca6ea1SDimitry Andric MIB.addUse(Addr);
407*0fca6ea1SDimitry Andric MIB.addImm(CPA->getKey()->getZExtValue());
408*0fca6ea1SDimitry Andric MIB.addUse(AddrDisc);
409*0fca6ea1SDimitry Andric MIB.addImm(CPA->getDiscriminator()->getZExtValue());
410*0fca6ea1SDimitry Andric return MIB;
411*0fca6ea1SDimitry Andric }
412*0fca6ea1SDimitry Andric
buildBrCond(const SrcOp & Tst,MachineBasicBlock & Dest)413e8d8bef9SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBrCond(const SrcOp &Tst,
4140b57cec5SDimitry Andric MachineBasicBlock &Dest) {
415e8d8bef9SDimitry Andric assert(Tst.getLLTTy(*getMRI()).isScalar() && "invalid operand type");
4160b57cec5SDimitry Andric
417e8d8bef9SDimitry Andric auto MIB = buildInstr(TargetOpcode::G_BRCOND);
418e8d8bef9SDimitry Andric Tst.addSrcToMIB(MIB);
419e8d8bef9SDimitry Andric MIB.addMBB(&Dest);
420e8d8bef9SDimitry Andric return MIB;
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric
423e8d8bef9SDimitry Andric MachineInstrBuilder
buildLoad(const DstOp & Dst,const SrcOp & Addr,MachinePointerInfo PtrInfo,Align Alignment,MachineMemOperand::Flags MMOFlags,const AAMDNodes & AAInfo)424e8d8bef9SDimitry Andric MachineIRBuilder::buildLoad(const DstOp &Dst, const SrcOp &Addr,
425e8d8bef9SDimitry Andric MachinePointerInfo PtrInfo, Align Alignment,
426e8d8bef9SDimitry Andric MachineMemOperand::Flags MMOFlags,
427e8d8bef9SDimitry Andric const AAMDNodes &AAInfo) {
428e8d8bef9SDimitry Andric MMOFlags |= MachineMemOperand::MOLoad;
429e8d8bef9SDimitry Andric assert((MMOFlags & MachineMemOperand::MOStore) == 0);
430e8d8bef9SDimitry Andric
431fe6060f1SDimitry Andric LLT Ty = Dst.getLLTTy(*getMRI());
432e8d8bef9SDimitry Andric MachineMemOperand *MMO =
433fe6060f1SDimitry Andric getMF().getMachineMemOperand(PtrInfo, MMOFlags, Ty, Alignment, AAInfo);
434e8d8bef9SDimitry Andric return buildLoad(Dst, Addr, *MMO);
4350b57cec5SDimitry Andric }
4360b57cec5SDimitry Andric
buildLoadInstr(unsigned Opcode,const DstOp & Res,const SrcOp & Addr,MachineMemOperand & MMO)4370b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildLoadInstr(unsigned Opcode,
4380b57cec5SDimitry Andric const DstOp &Res,
4390b57cec5SDimitry Andric const SrcOp &Addr,
4400b57cec5SDimitry Andric MachineMemOperand &MMO) {
4410b57cec5SDimitry Andric assert(Res.getLLTTy(*getMRI()).isValid() && "invalid operand type");
4420b57cec5SDimitry Andric assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
4430b57cec5SDimitry Andric
4440b57cec5SDimitry Andric auto MIB = buildInstr(Opcode);
4450b57cec5SDimitry Andric Res.addDefToMIB(*getMRI(), MIB);
4460b57cec5SDimitry Andric Addr.addSrcToMIB(MIB);
4470b57cec5SDimitry Andric MIB.addMemOperand(&MMO);
4480b57cec5SDimitry Andric return MIB;
4490b57cec5SDimitry Andric }
4500b57cec5SDimitry Andric
buildLoadFromOffset(const DstOp & Dst,const SrcOp & BasePtr,MachineMemOperand & BaseMMO,int64_t Offset)4515ffd83dbSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildLoadFromOffset(
4525ffd83dbSDimitry Andric const DstOp &Dst, const SrcOp &BasePtr,
4535ffd83dbSDimitry Andric MachineMemOperand &BaseMMO, int64_t Offset) {
4545ffd83dbSDimitry Andric LLT LoadTy = Dst.getLLTTy(*getMRI());
4555ffd83dbSDimitry Andric MachineMemOperand *OffsetMMO =
456fe6060f1SDimitry Andric getMF().getMachineMemOperand(&BaseMMO, Offset, LoadTy);
4575ffd83dbSDimitry Andric
4585ffd83dbSDimitry Andric if (Offset == 0) // This may be a size or type changing load.
4595ffd83dbSDimitry Andric return buildLoad(Dst, BasePtr, *OffsetMMO);
4605ffd83dbSDimitry Andric
4615ffd83dbSDimitry Andric LLT PtrTy = BasePtr.getLLTTy(*getMRI());
4625ffd83dbSDimitry Andric LLT OffsetTy = LLT::scalar(PtrTy.getSizeInBits());
4635ffd83dbSDimitry Andric auto ConstOffset = buildConstant(OffsetTy, Offset);
4645ffd83dbSDimitry Andric auto Ptr = buildPtrAdd(PtrTy, BasePtr, ConstOffset);
4655ffd83dbSDimitry Andric return buildLoad(Dst, Ptr, *OffsetMMO);
4665ffd83dbSDimitry Andric }
4675ffd83dbSDimitry Andric
buildStore(const SrcOp & Val,const SrcOp & Addr,MachineMemOperand & MMO)4680b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildStore(const SrcOp &Val,
4690b57cec5SDimitry Andric const SrcOp &Addr,
4700b57cec5SDimitry Andric MachineMemOperand &MMO) {
4710b57cec5SDimitry Andric assert(Val.getLLTTy(*getMRI()).isValid() && "invalid operand type");
4720b57cec5SDimitry Andric assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
4730b57cec5SDimitry Andric
4740b57cec5SDimitry Andric auto MIB = buildInstr(TargetOpcode::G_STORE);
4750b57cec5SDimitry Andric Val.addSrcToMIB(MIB);
4760b57cec5SDimitry Andric Addr.addSrcToMIB(MIB);
4770b57cec5SDimitry Andric MIB.addMemOperand(&MMO);
4780b57cec5SDimitry Andric return MIB;
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric
481e8d8bef9SDimitry Andric MachineInstrBuilder
buildStore(const SrcOp & Val,const SrcOp & Addr,MachinePointerInfo PtrInfo,Align Alignment,MachineMemOperand::Flags MMOFlags,const AAMDNodes & AAInfo)482e8d8bef9SDimitry Andric MachineIRBuilder::buildStore(const SrcOp &Val, const SrcOp &Addr,
483e8d8bef9SDimitry Andric MachinePointerInfo PtrInfo, Align Alignment,
484e8d8bef9SDimitry Andric MachineMemOperand::Flags MMOFlags,
485e8d8bef9SDimitry Andric const AAMDNodes &AAInfo) {
486e8d8bef9SDimitry Andric MMOFlags |= MachineMemOperand::MOStore;
487e8d8bef9SDimitry Andric assert((MMOFlags & MachineMemOperand::MOLoad) == 0);
488e8d8bef9SDimitry Andric
489fe6060f1SDimitry Andric LLT Ty = Val.getLLTTy(*getMRI());
490e8d8bef9SDimitry Andric MachineMemOperand *MMO =
491fe6060f1SDimitry Andric getMF().getMachineMemOperand(PtrInfo, MMOFlags, Ty, Alignment, AAInfo);
492e8d8bef9SDimitry Andric return buildStore(Val, Addr, *MMO);
493e8d8bef9SDimitry Andric }
494e8d8bef9SDimitry Andric
buildAnyExt(const DstOp & Res,const SrcOp & Op)4950b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAnyExt(const DstOp &Res,
4960b57cec5SDimitry Andric const SrcOp &Op) {
4970b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_ANYEXT, Res, Op);
4980b57cec5SDimitry Andric }
4990b57cec5SDimitry Andric
buildSExt(const DstOp & Res,const SrcOp & Op)5000b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSExt(const DstOp &Res,
5010b57cec5SDimitry Andric const SrcOp &Op) {
5020b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_SEXT, Res, Op);
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric
buildZExt(const DstOp & Res,const SrcOp & Op,std::optional<unsigned> Flags)5050b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildZExt(const DstOp &Res,
506*0fca6ea1SDimitry Andric const SrcOp &Op,
507*0fca6ea1SDimitry Andric std::optional<unsigned> Flags) {
508*0fca6ea1SDimitry Andric return buildInstr(TargetOpcode::G_ZEXT, Res, Op, Flags);
5090b57cec5SDimitry Andric }
5100b57cec5SDimitry Andric
getBoolExtOp(bool IsVec,bool IsFP) const5110b57cec5SDimitry Andric unsigned MachineIRBuilder::getBoolExtOp(bool IsVec, bool IsFP) const {
5120b57cec5SDimitry Andric const auto *TLI = getMF().getSubtarget().getTargetLowering();
5130b57cec5SDimitry Andric switch (TLI->getBooleanContents(IsVec, IsFP)) {
5140b57cec5SDimitry Andric case TargetLoweringBase::ZeroOrNegativeOneBooleanContent:
5150b57cec5SDimitry Andric return TargetOpcode::G_SEXT;
5160b57cec5SDimitry Andric case TargetLoweringBase::ZeroOrOneBooleanContent:
5170b57cec5SDimitry Andric return TargetOpcode::G_ZEXT;
5180b57cec5SDimitry Andric default:
5190b57cec5SDimitry Andric return TargetOpcode::G_ANYEXT;
5200b57cec5SDimitry Andric }
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric
buildBoolExt(const DstOp & Res,const SrcOp & Op,bool IsFP)5230b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBoolExt(const DstOp &Res,
5240b57cec5SDimitry Andric const SrcOp &Op,
5250b57cec5SDimitry Andric bool IsFP) {
5260b57cec5SDimitry Andric unsigned ExtOp = getBoolExtOp(getMRI()->getType(Op.getReg()).isVector(), IsFP);
5270b57cec5SDimitry Andric return buildInstr(ExtOp, Res, Op);
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric
buildBoolExtInReg(const DstOp & Res,const SrcOp & Op,bool IsVector,bool IsFP)530753f127fSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBoolExtInReg(const DstOp &Res,
531753f127fSDimitry Andric const SrcOp &Op,
532753f127fSDimitry Andric bool IsVector,
533753f127fSDimitry Andric bool IsFP) {
534753f127fSDimitry Andric const auto *TLI = getMF().getSubtarget().getTargetLowering();
535753f127fSDimitry Andric switch (TLI->getBooleanContents(IsVector, IsFP)) {
536753f127fSDimitry Andric case TargetLoweringBase::ZeroOrNegativeOneBooleanContent:
537753f127fSDimitry Andric return buildSExtInReg(Res, Op, 1);
538753f127fSDimitry Andric case TargetLoweringBase::ZeroOrOneBooleanContent:
539753f127fSDimitry Andric return buildZExtInReg(Res, Op, 1);
540753f127fSDimitry Andric case TargetLoweringBase::UndefinedBooleanContent:
541753f127fSDimitry Andric return buildCopy(Res, Op);
542753f127fSDimitry Andric }
543753f127fSDimitry Andric
544753f127fSDimitry Andric llvm_unreachable("unexpected BooleanContent");
545753f127fSDimitry Andric }
546753f127fSDimitry Andric
buildExtOrTrunc(unsigned ExtOpc,const DstOp & Res,const SrcOp & Op)5470b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildExtOrTrunc(unsigned ExtOpc,
5480b57cec5SDimitry Andric const DstOp &Res,
5490b57cec5SDimitry Andric const SrcOp &Op) {
5500b57cec5SDimitry Andric assert((TargetOpcode::G_ANYEXT == ExtOpc || TargetOpcode::G_ZEXT == ExtOpc ||
5510b57cec5SDimitry Andric TargetOpcode::G_SEXT == ExtOpc) &&
5520b57cec5SDimitry Andric "Expecting Extending Opc");
5530b57cec5SDimitry Andric assert(Res.getLLTTy(*getMRI()).isScalar() ||
5540b57cec5SDimitry Andric Res.getLLTTy(*getMRI()).isVector());
5550b57cec5SDimitry Andric assert(Res.getLLTTy(*getMRI()).isScalar() ==
5560b57cec5SDimitry Andric Op.getLLTTy(*getMRI()).isScalar());
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric unsigned Opcode = TargetOpcode::COPY;
5590b57cec5SDimitry Andric if (Res.getLLTTy(*getMRI()).getSizeInBits() >
5600b57cec5SDimitry Andric Op.getLLTTy(*getMRI()).getSizeInBits())
5610b57cec5SDimitry Andric Opcode = ExtOpc;
5620b57cec5SDimitry Andric else if (Res.getLLTTy(*getMRI()).getSizeInBits() <
5630b57cec5SDimitry Andric Op.getLLTTy(*getMRI()).getSizeInBits())
5640b57cec5SDimitry Andric Opcode = TargetOpcode::G_TRUNC;
5650b57cec5SDimitry Andric else
5660b57cec5SDimitry Andric assert(Res.getLLTTy(*getMRI()) == Op.getLLTTy(*getMRI()));
5670b57cec5SDimitry Andric
5680b57cec5SDimitry Andric return buildInstr(Opcode, Res, Op);
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric
buildSExtOrTrunc(const DstOp & Res,const SrcOp & Op)5710b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSExtOrTrunc(const DstOp &Res,
5720b57cec5SDimitry Andric const SrcOp &Op) {
5730b57cec5SDimitry Andric return buildExtOrTrunc(TargetOpcode::G_SEXT, Res, Op);
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric
buildZExtOrTrunc(const DstOp & Res,const SrcOp & Op)5760b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildZExtOrTrunc(const DstOp &Res,
5770b57cec5SDimitry Andric const SrcOp &Op) {
5780b57cec5SDimitry Andric return buildExtOrTrunc(TargetOpcode::G_ZEXT, Res, Op);
5790b57cec5SDimitry Andric }
5800b57cec5SDimitry Andric
buildAnyExtOrTrunc(const DstOp & Res,const SrcOp & Op)5810b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAnyExtOrTrunc(const DstOp &Res,
5820b57cec5SDimitry Andric const SrcOp &Op) {
5830b57cec5SDimitry Andric return buildExtOrTrunc(TargetOpcode::G_ANYEXT, Res, Op);
5840b57cec5SDimitry Andric }
5850b57cec5SDimitry Andric
buildZExtInReg(const DstOp & Res,const SrcOp & Op,int64_t ImmOp)586fe6060f1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildZExtInReg(const DstOp &Res,
587fe6060f1SDimitry Andric const SrcOp &Op,
588fe6060f1SDimitry Andric int64_t ImmOp) {
589fe6060f1SDimitry Andric LLT ResTy = Res.getLLTTy(*getMRI());
590fe6060f1SDimitry Andric auto Mask = buildConstant(
591fe6060f1SDimitry Andric ResTy, APInt::getLowBitsSet(ResTy.getScalarSizeInBits(), ImmOp));
592fe6060f1SDimitry Andric return buildAnd(Res, Op, Mask);
593fe6060f1SDimitry Andric }
594fe6060f1SDimitry Andric
buildCast(const DstOp & Dst,const SrcOp & Src)5950b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildCast(const DstOp &Dst,
5960b57cec5SDimitry Andric const SrcOp &Src) {
5970b57cec5SDimitry Andric LLT SrcTy = Src.getLLTTy(*getMRI());
5980b57cec5SDimitry Andric LLT DstTy = Dst.getLLTTy(*getMRI());
5990b57cec5SDimitry Andric if (SrcTy == DstTy)
6000b57cec5SDimitry Andric return buildCopy(Dst, Src);
6010b57cec5SDimitry Andric
6020b57cec5SDimitry Andric unsigned Opcode;
6030b57cec5SDimitry Andric if (SrcTy.isPointer() && DstTy.isScalar())
6040b57cec5SDimitry Andric Opcode = TargetOpcode::G_PTRTOINT;
6050b57cec5SDimitry Andric else if (DstTy.isPointer() && SrcTy.isScalar())
6060b57cec5SDimitry Andric Opcode = TargetOpcode::G_INTTOPTR;
6070b57cec5SDimitry Andric else {
6080b57cec5SDimitry Andric assert(!SrcTy.isPointer() && !DstTy.isPointer() && "n G_ADDRCAST yet");
6090b57cec5SDimitry Andric Opcode = TargetOpcode::G_BITCAST;
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric
6120b57cec5SDimitry Andric return buildInstr(Opcode, Dst, Src);
6130b57cec5SDimitry Andric }
6140b57cec5SDimitry Andric
buildExtract(const DstOp & Dst,const SrcOp & Src,uint64_t Index)6150b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildExtract(const DstOp &Dst,
6160b57cec5SDimitry Andric const SrcOp &Src,
6170b57cec5SDimitry Andric uint64_t Index) {
6180b57cec5SDimitry Andric LLT SrcTy = Src.getLLTTy(*getMRI());
6190b57cec5SDimitry Andric LLT DstTy = Dst.getLLTTy(*getMRI());
6200b57cec5SDimitry Andric
6210b57cec5SDimitry Andric #ifndef NDEBUG
6220b57cec5SDimitry Andric assert(SrcTy.isValid() && "invalid operand type");
6230b57cec5SDimitry Andric assert(DstTy.isValid() && "invalid operand type");
6240b57cec5SDimitry Andric assert(Index + DstTy.getSizeInBits() <= SrcTy.getSizeInBits() &&
6250b57cec5SDimitry Andric "extracting off end of register");
6260b57cec5SDimitry Andric #endif
6270b57cec5SDimitry Andric
6280b57cec5SDimitry Andric if (DstTy.getSizeInBits() == SrcTy.getSizeInBits()) {
6290b57cec5SDimitry Andric assert(Index == 0 && "insertion past the end of a register");
6300b57cec5SDimitry Andric return buildCast(Dst, Src);
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric
6330b57cec5SDimitry Andric auto Extract = buildInstr(TargetOpcode::G_EXTRACT);
6340b57cec5SDimitry Andric Dst.addDefToMIB(*getMRI(), Extract);
6350b57cec5SDimitry Andric Src.addSrcToMIB(Extract);
6360b57cec5SDimitry Andric Extract.addImm(Index);
6370b57cec5SDimitry Andric return Extract;
6380b57cec5SDimitry Andric }
6390b57cec5SDimitry Andric
buildUndef(const DstOp & Res)6400b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUndef(const DstOp &Res) {
6410b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_IMPLICIT_DEF, {Res}, {});
6420b57cec5SDimitry Andric }
6430b57cec5SDimitry Andric
buildMergeValues(const DstOp & Res,ArrayRef<Register> Ops)644bdd1243dSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildMergeValues(const DstOp &Res,
6450b57cec5SDimitry Andric ArrayRef<Register> Ops) {
6460b57cec5SDimitry Andric // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
6470b57cec5SDimitry Andric // we need some temporary storage for the DstOp objects. Here we use a
6480b57cec5SDimitry Andric // sufficiently large SmallVector to not go through the heap.
6490b57cec5SDimitry Andric SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
6500b57cec5SDimitry Andric assert(TmpVec.size() > 1);
6510b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_MERGE_VALUES, Res, TmpVec);
6520b57cec5SDimitry Andric }
6530b57cec5SDimitry Andric
6545ffd83dbSDimitry Andric MachineInstrBuilder
buildMergeLikeInstr(const DstOp & Res,ArrayRef<Register> Ops)655bdd1243dSDimitry Andric MachineIRBuilder::buildMergeLikeInstr(const DstOp &Res,
656bdd1243dSDimitry Andric ArrayRef<Register> Ops) {
657bdd1243dSDimitry Andric // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
658bdd1243dSDimitry Andric // we need some temporary storage for the DstOp objects. Here we use a
659bdd1243dSDimitry Andric // sufficiently large SmallVector to not go through the heap.
660bdd1243dSDimitry Andric SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
661bdd1243dSDimitry Andric assert(TmpVec.size() > 1);
662bdd1243dSDimitry Andric return buildInstr(getOpcodeForMerge(Res, TmpVec), Res, TmpVec);
663bdd1243dSDimitry Andric }
664bdd1243dSDimitry Andric
665bdd1243dSDimitry Andric MachineInstrBuilder
buildMergeLikeInstr(const DstOp & Res,std::initializer_list<SrcOp> Ops)666bdd1243dSDimitry Andric MachineIRBuilder::buildMergeLikeInstr(const DstOp &Res,
6675ffd83dbSDimitry Andric std::initializer_list<SrcOp> Ops) {
6685ffd83dbSDimitry Andric assert(Ops.size() > 1);
669bdd1243dSDimitry Andric return buildInstr(getOpcodeForMerge(Res, Ops), Res, Ops);
670bdd1243dSDimitry Andric }
671bdd1243dSDimitry Andric
getOpcodeForMerge(const DstOp & DstOp,ArrayRef<SrcOp> SrcOps) const672bdd1243dSDimitry Andric unsigned MachineIRBuilder::getOpcodeForMerge(const DstOp &DstOp,
673bdd1243dSDimitry Andric ArrayRef<SrcOp> SrcOps) const {
674bdd1243dSDimitry Andric if (DstOp.getLLTTy(*getMRI()).isVector()) {
675bdd1243dSDimitry Andric if (SrcOps[0].getLLTTy(*getMRI()).isVector())
676bdd1243dSDimitry Andric return TargetOpcode::G_CONCAT_VECTORS;
677bdd1243dSDimitry Andric return TargetOpcode::G_BUILD_VECTOR;
678bdd1243dSDimitry Andric }
679bdd1243dSDimitry Andric
680bdd1243dSDimitry Andric return TargetOpcode::G_MERGE_VALUES;
6815ffd83dbSDimitry Andric }
6825ffd83dbSDimitry Andric
buildUnmerge(ArrayRef<LLT> Res,const SrcOp & Op)6830b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUnmerge(ArrayRef<LLT> Res,
6840b57cec5SDimitry Andric const SrcOp &Op) {
6850b57cec5SDimitry Andric // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<DstOp>,
6860b57cec5SDimitry Andric // we need some temporary storage for the DstOp objects. Here we use a
6870b57cec5SDimitry Andric // sufficiently large SmallVector to not go through the heap.
6880b57cec5SDimitry Andric SmallVector<DstOp, 8> TmpVec(Res.begin(), Res.end());
6890b57cec5SDimitry Andric assert(TmpVec.size() > 1);
6900b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
6910b57cec5SDimitry Andric }
6920b57cec5SDimitry Andric
buildUnmerge(LLT Res,const SrcOp & Op)6930b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUnmerge(LLT Res,
6940b57cec5SDimitry Andric const SrcOp &Op) {
6950b57cec5SDimitry Andric unsigned NumReg = Op.getLLTTy(*getMRI()).getSizeInBits() / Res.getSizeInBits();
6960eae32dcSDimitry Andric SmallVector<DstOp, 8> TmpVec(NumReg, Res);
6970eae32dcSDimitry Andric return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
6980b57cec5SDimitry Andric }
6990b57cec5SDimitry Andric
buildUnmerge(ArrayRef<Register> Res,const SrcOp & Op)7000b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUnmerge(ArrayRef<Register> Res,
7010b57cec5SDimitry Andric const SrcOp &Op) {
7020b57cec5SDimitry Andric // Unfortunately to convert from ArrayRef<Register> to ArrayRef<DstOp>,
7030b57cec5SDimitry Andric // we need some temporary storage for the DstOp objects. Here we use a
7040b57cec5SDimitry Andric // sufficiently large SmallVector to not go through the heap.
7050b57cec5SDimitry Andric SmallVector<DstOp, 8> TmpVec(Res.begin(), Res.end());
7060b57cec5SDimitry Andric assert(TmpVec.size() > 1);
7070b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
7080b57cec5SDimitry Andric }
7090b57cec5SDimitry Andric
buildBuildVector(const DstOp & Res,ArrayRef<Register> Ops)7100b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBuildVector(const DstOp &Res,
7110b57cec5SDimitry Andric ArrayRef<Register> Ops) {
7120b57cec5SDimitry Andric // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
7130b57cec5SDimitry Andric // we need some temporary storage for the DstOp objects. Here we use a
7140b57cec5SDimitry Andric // sufficiently large SmallVector to not go through the heap.
7150b57cec5SDimitry Andric SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
7160b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric
71981ad6265SDimitry Andric MachineInstrBuilder
buildBuildVectorConstant(const DstOp & Res,ArrayRef<APInt> Ops)72081ad6265SDimitry Andric MachineIRBuilder::buildBuildVectorConstant(const DstOp &Res,
72181ad6265SDimitry Andric ArrayRef<APInt> Ops) {
72281ad6265SDimitry Andric SmallVector<SrcOp> TmpVec;
72381ad6265SDimitry Andric TmpVec.reserve(Ops.size());
72481ad6265SDimitry Andric LLT EltTy = Res.getLLTTy(*getMRI()).getElementType();
725fcaf7f86SDimitry Andric for (const auto &Op : Ops)
72681ad6265SDimitry Andric TmpVec.push_back(buildConstant(EltTy, Op));
72781ad6265SDimitry Andric return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
72881ad6265SDimitry Andric }
72981ad6265SDimitry Andric
buildSplatBuildVector(const DstOp & Res,const SrcOp & Src)730*0fca6ea1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSplatBuildVector(const DstOp &Res,
7310b57cec5SDimitry Andric const SrcOp &Src) {
7320b57cec5SDimitry Andric SmallVector<SrcOp, 8> TmpVec(Res.getLLTTy(*getMRI()).getNumElements(), Src);
7330b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
7340b57cec5SDimitry Andric }
7350b57cec5SDimitry Andric
7360b57cec5SDimitry Andric MachineInstrBuilder
buildBuildVectorTrunc(const DstOp & Res,ArrayRef<Register> Ops)7370b57cec5SDimitry Andric MachineIRBuilder::buildBuildVectorTrunc(const DstOp &Res,
7380b57cec5SDimitry Andric ArrayRef<Register> Ops) {
7390b57cec5SDimitry Andric // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
7400b57cec5SDimitry Andric // we need some temporary storage for the DstOp objects. Here we use a
7410b57cec5SDimitry Andric // sufficiently large SmallVector to not go through the heap.
7420b57cec5SDimitry Andric SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
743bdd1243dSDimitry Andric if (TmpVec[0].getLLTTy(*getMRI()).getSizeInBits() ==
744bdd1243dSDimitry Andric Res.getLLTTy(*getMRI()).getElementType().getSizeInBits())
745bdd1243dSDimitry Andric return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
7460b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_BUILD_VECTOR_TRUNC, Res, TmpVec);
7470b57cec5SDimitry Andric }
7480b57cec5SDimitry Andric
buildShuffleSplat(const DstOp & Res,const SrcOp & Src)749e8d8bef9SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildShuffleSplat(const DstOp &Res,
750e8d8bef9SDimitry Andric const SrcOp &Src) {
751e8d8bef9SDimitry Andric LLT DstTy = Res.getLLTTy(*getMRI());
752e8d8bef9SDimitry Andric assert(Src.getLLTTy(*getMRI()) == DstTy.getElementType() &&
753e8d8bef9SDimitry Andric "Expected Src to match Dst elt ty");
754e8d8bef9SDimitry Andric auto UndefVec = buildUndef(DstTy);
755e8d8bef9SDimitry Andric auto Zero = buildConstant(LLT::scalar(64), 0);
756e8d8bef9SDimitry Andric auto InsElt = buildInsertVectorElement(DstTy, UndefVec, Src, Zero);
757e8d8bef9SDimitry Andric SmallVector<int, 16> ZeroMask(DstTy.getNumElements());
758e8d8bef9SDimitry Andric return buildShuffleVector(DstTy, InsElt, UndefVec, ZeroMask);
759e8d8bef9SDimitry Andric }
760e8d8bef9SDimitry Andric
buildSplatVector(const DstOp & Res,const SrcOp & Src)761*0fca6ea1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSplatVector(const DstOp &Res,
762*0fca6ea1SDimitry Andric const SrcOp &Src) {
763*0fca6ea1SDimitry Andric assert(Src.getLLTTy(*getMRI()) == Res.getLLTTy(*getMRI()).getElementType() &&
764*0fca6ea1SDimitry Andric "Expected Src to match Dst elt ty");
765*0fca6ea1SDimitry Andric return buildInstr(TargetOpcode::G_SPLAT_VECTOR, Res, Src);
766*0fca6ea1SDimitry Andric }
767*0fca6ea1SDimitry Andric
buildShuffleVector(const DstOp & Res,const SrcOp & Src1,const SrcOp & Src2,ArrayRef<int> Mask)768e8d8bef9SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildShuffleVector(const DstOp &Res,
769e8d8bef9SDimitry Andric const SrcOp &Src1,
770e8d8bef9SDimitry Andric const SrcOp &Src2,
771e8d8bef9SDimitry Andric ArrayRef<int> Mask) {
772e8d8bef9SDimitry Andric LLT DstTy = Res.getLLTTy(*getMRI());
773e8d8bef9SDimitry Andric LLT Src1Ty = Src1.getLLTTy(*getMRI());
774e8d8bef9SDimitry Andric LLT Src2Ty = Src2.getLLTTy(*getMRI());
775349cc55cSDimitry Andric assert((size_t)(Src1Ty.getNumElements() + Src2Ty.getNumElements()) >=
776349cc55cSDimitry Andric Mask.size());
777e8d8bef9SDimitry Andric assert(DstTy.getElementType() == Src1Ty.getElementType() &&
778e8d8bef9SDimitry Andric DstTy.getElementType() == Src2Ty.getElementType());
779fe6060f1SDimitry Andric (void)DstTy;
780e8d8bef9SDimitry Andric (void)Src1Ty;
781e8d8bef9SDimitry Andric (void)Src2Ty;
782e8d8bef9SDimitry Andric ArrayRef<int> MaskAlloc = getMF().allocateShuffleMask(Mask);
783fe6060f1SDimitry Andric return buildInstr(TargetOpcode::G_SHUFFLE_VECTOR, {Res}, {Src1, Src2})
784e8d8bef9SDimitry Andric .addShuffleMask(MaskAlloc);
785e8d8bef9SDimitry Andric }
786e8d8bef9SDimitry Andric
7870b57cec5SDimitry Andric MachineInstrBuilder
buildConcatVectors(const DstOp & Res,ArrayRef<Register> Ops)7880b57cec5SDimitry Andric MachineIRBuilder::buildConcatVectors(const DstOp &Res, ArrayRef<Register> Ops) {
7890b57cec5SDimitry Andric // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
7900b57cec5SDimitry Andric // we need some temporary storage for the DstOp objects. Here we use a
7910b57cec5SDimitry Andric // sufficiently large SmallVector to not go through the heap.
7920b57cec5SDimitry Andric SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
7930b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_CONCAT_VECTORS, Res, TmpVec);
7940b57cec5SDimitry Andric }
7950b57cec5SDimitry Andric
buildInsert(const DstOp & Res,const SrcOp & Src,const SrcOp & Op,unsigned Index)7965ffd83dbSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildInsert(const DstOp &Res,
7975ffd83dbSDimitry Andric const SrcOp &Src,
7985ffd83dbSDimitry Andric const SrcOp &Op,
7995ffd83dbSDimitry Andric unsigned Index) {
8005ffd83dbSDimitry Andric assert(Index + Op.getLLTTy(*getMRI()).getSizeInBits() <=
8015ffd83dbSDimitry Andric Res.getLLTTy(*getMRI()).getSizeInBits() &&
8020b57cec5SDimitry Andric "insertion past the end of a register");
8030b57cec5SDimitry Andric
8045ffd83dbSDimitry Andric if (Res.getLLTTy(*getMRI()).getSizeInBits() ==
8055ffd83dbSDimitry Andric Op.getLLTTy(*getMRI()).getSizeInBits()) {
8060b57cec5SDimitry Andric return buildCast(Res, Op);
8070b57cec5SDimitry Andric }
8080b57cec5SDimitry Andric
8095ffd83dbSDimitry Andric return buildInstr(TargetOpcode::G_INSERT, Res, {Src, Op, uint64_t(Index)});
8100b57cec5SDimitry Andric }
8110b57cec5SDimitry Andric
buildVScale(const DstOp & Res,unsigned MinElts)812*0fca6ea1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res,
813*0fca6ea1SDimitry Andric unsigned MinElts) {
814*0fca6ea1SDimitry Andric
815*0fca6ea1SDimitry Andric auto IntN = IntegerType::get(getMF().getFunction().getContext(),
816*0fca6ea1SDimitry Andric Res.getLLTTy(*getMRI()).getScalarSizeInBits());
817*0fca6ea1SDimitry Andric ConstantInt *CI = ConstantInt::get(IntN, MinElts);
818*0fca6ea1SDimitry Andric return buildVScale(Res, *CI);
819*0fca6ea1SDimitry Andric }
820*0fca6ea1SDimitry Andric
buildVScale(const DstOp & Res,const ConstantInt & MinElts)821*0fca6ea1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res,
822*0fca6ea1SDimitry Andric const ConstantInt &MinElts) {
823*0fca6ea1SDimitry Andric auto VScale = buildInstr(TargetOpcode::G_VSCALE);
824*0fca6ea1SDimitry Andric VScale->setDebugLoc(DebugLoc());
825*0fca6ea1SDimitry Andric Res.addDefToMIB(*getMRI(), VScale);
826*0fca6ea1SDimitry Andric VScale.addCImm(&MinElts);
827*0fca6ea1SDimitry Andric return VScale;
828*0fca6ea1SDimitry Andric }
829*0fca6ea1SDimitry Andric
buildVScale(const DstOp & Res,const APInt & MinElts)830*0fca6ea1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res,
831*0fca6ea1SDimitry Andric const APInt &MinElts) {
832*0fca6ea1SDimitry Andric ConstantInt *CI =
833*0fca6ea1SDimitry Andric ConstantInt::get(getMF().getFunction().getContext(), MinElts);
834*0fca6ea1SDimitry Andric return buildVScale(Res, *CI);
835*0fca6ea1SDimitry Andric }
836*0fca6ea1SDimitry Andric
getIntrinsicOpcode(bool HasSideEffects,bool IsConvergent)8375f757f3fSDimitry Andric static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) {
8385f757f3fSDimitry Andric if (HasSideEffects && IsConvergent)
8395f757f3fSDimitry Andric return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS;
8405f757f3fSDimitry Andric if (HasSideEffects)
8415f757f3fSDimitry Andric return TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS;
8425f757f3fSDimitry Andric if (IsConvergent)
8435f757f3fSDimitry Andric return TargetOpcode::G_INTRINSIC_CONVERGENT;
8445f757f3fSDimitry Andric return TargetOpcode::G_INTRINSIC;
8455f757f3fSDimitry Andric }
8465f757f3fSDimitry Andric
8475f757f3fSDimitry Andric MachineInstrBuilder
buildIntrinsic(Intrinsic::ID ID,ArrayRef<Register> ResultRegs,bool HasSideEffects,bool isConvergent)8485f757f3fSDimitry Andric MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID,
8490b57cec5SDimitry Andric ArrayRef<Register> ResultRegs,
8505f757f3fSDimitry Andric bool HasSideEffects, bool isConvergent) {
8515f757f3fSDimitry Andric auto MIB = buildInstr(getIntrinsicOpcode(HasSideEffects, isConvergent));
8520b57cec5SDimitry Andric for (unsigned ResultReg : ResultRegs)
8530b57cec5SDimitry Andric MIB.addDef(ResultReg);
8540b57cec5SDimitry Andric MIB.addIntrinsicID(ID);
8550b57cec5SDimitry Andric return MIB;
8560b57cec5SDimitry Andric }
8570b57cec5SDimitry Andric
8585f757f3fSDimitry Andric MachineInstrBuilder
buildIntrinsic(Intrinsic::ID ID,ArrayRef<Register> ResultRegs)8595f757f3fSDimitry Andric MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID,
8605f757f3fSDimitry Andric ArrayRef<Register> ResultRegs) {
8615f757f3fSDimitry Andric auto Attrs = Intrinsic::getAttributes(getContext(), ID);
8625f757f3fSDimitry Andric bool HasSideEffects = !Attrs.getMemoryEffects().doesNotAccessMemory();
8635f757f3fSDimitry Andric bool isConvergent = Attrs.hasFnAttr(Attribute::Convergent);
8645f757f3fSDimitry Andric return buildIntrinsic(ID, ResultRegs, HasSideEffects, isConvergent);
8655f757f3fSDimitry Andric }
8665f757f3fSDimitry Andric
buildIntrinsic(Intrinsic::ID ID,ArrayRef<DstOp> Results,bool HasSideEffects,bool isConvergent)8670b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID,
8680b57cec5SDimitry Andric ArrayRef<DstOp> Results,
8695f757f3fSDimitry Andric bool HasSideEffects,
8705f757f3fSDimitry Andric bool isConvergent) {
8715f757f3fSDimitry Andric auto MIB = buildInstr(getIntrinsicOpcode(HasSideEffects, isConvergent));
8720b57cec5SDimitry Andric for (DstOp Result : Results)
8730b57cec5SDimitry Andric Result.addDefToMIB(*getMRI(), MIB);
8740b57cec5SDimitry Andric MIB.addIntrinsicID(ID);
8750b57cec5SDimitry Andric return MIB;
8760b57cec5SDimitry Andric }
8770b57cec5SDimitry Andric
buildIntrinsic(Intrinsic::ID ID,ArrayRef<DstOp> Results)8785f757f3fSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID,
8795f757f3fSDimitry Andric ArrayRef<DstOp> Results) {
8805f757f3fSDimitry Andric auto Attrs = Intrinsic::getAttributes(getContext(), ID);
8815f757f3fSDimitry Andric bool HasSideEffects = !Attrs.getMemoryEffects().doesNotAccessMemory();
8825f757f3fSDimitry Andric bool isConvergent = Attrs.hasFnAttr(Attribute::Convergent);
8835f757f3fSDimitry Andric return buildIntrinsic(ID, Results, HasSideEffects, isConvergent);
8845f757f3fSDimitry Andric }
8855f757f3fSDimitry Andric
886*0fca6ea1SDimitry Andric MachineInstrBuilder
buildTrunc(const DstOp & Res,const SrcOp & Op,std::optional<unsigned> Flags)887*0fca6ea1SDimitry Andric MachineIRBuilder::buildTrunc(const DstOp &Res, const SrcOp &Op,
888*0fca6ea1SDimitry Andric std::optional<unsigned> Flags) {
889*0fca6ea1SDimitry Andric return buildInstr(TargetOpcode::G_TRUNC, Res, Op, Flags);
8900b57cec5SDimitry Andric }
8910b57cec5SDimitry Andric
892bdd1243dSDimitry Andric MachineInstrBuilder
buildFPTrunc(const DstOp & Res,const SrcOp & Op,std::optional<unsigned> Flags)893bdd1243dSDimitry Andric MachineIRBuilder::buildFPTrunc(const DstOp &Res, const SrcOp &Op,
894bdd1243dSDimitry Andric std::optional<unsigned> Flags) {
895480093f4SDimitry Andric return buildInstr(TargetOpcode::G_FPTRUNC, Res, Op, Flags);
8960b57cec5SDimitry Andric }
8970b57cec5SDimitry Andric
buildICmp(CmpInst::Predicate Pred,const DstOp & Res,const SrcOp & Op0,const SrcOp & Op1)8980b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildICmp(CmpInst::Predicate Pred,
8990b57cec5SDimitry Andric const DstOp &Res,
9000b57cec5SDimitry Andric const SrcOp &Op0,
9010b57cec5SDimitry Andric const SrcOp &Op1) {
9020b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_ICMP, Res, {Pred, Op0, Op1});
9030b57cec5SDimitry Andric }
9040b57cec5SDimitry Andric
buildFCmp(CmpInst::Predicate Pred,const DstOp & Res,const SrcOp & Op0,const SrcOp & Op1,std::optional<unsigned> Flags)9050b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFCmp(CmpInst::Predicate Pred,
9060b57cec5SDimitry Andric const DstOp &Res,
9070b57cec5SDimitry Andric const SrcOp &Op0,
9088bcb0991SDimitry Andric const SrcOp &Op1,
909bdd1243dSDimitry Andric std::optional<unsigned> Flags) {
9100b57cec5SDimitry Andric
9118bcb0991SDimitry Andric return buildInstr(TargetOpcode::G_FCMP, Res, {Pred, Op0, Op1}, Flags);
9120b57cec5SDimitry Andric }
9130b57cec5SDimitry Andric
buildSCmp(const DstOp & Res,const SrcOp & Op0,const SrcOp & Op1)914*0fca6ea1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSCmp(const DstOp &Res,
915*0fca6ea1SDimitry Andric const SrcOp &Op0,
916*0fca6ea1SDimitry Andric const SrcOp &Op1) {
917*0fca6ea1SDimitry Andric return buildInstr(TargetOpcode::G_SCMP, Res, {Op0, Op1});
918*0fca6ea1SDimitry Andric }
919*0fca6ea1SDimitry Andric
buildUCmp(const DstOp & Res,const SrcOp & Op0,const SrcOp & Op1)920*0fca6ea1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUCmp(const DstOp &Res,
921*0fca6ea1SDimitry Andric const SrcOp &Op0,
922*0fca6ea1SDimitry Andric const SrcOp &Op1) {
923*0fca6ea1SDimitry Andric return buildInstr(TargetOpcode::G_UCMP, Res, {Op0, Op1});
924*0fca6ea1SDimitry Andric }
925*0fca6ea1SDimitry Andric
926bdd1243dSDimitry Andric MachineInstrBuilder
buildSelect(const DstOp & Res,const SrcOp & Tst,const SrcOp & Op0,const SrcOp & Op1,std::optional<unsigned> Flags)927bdd1243dSDimitry Andric MachineIRBuilder::buildSelect(const DstOp &Res, const SrcOp &Tst,
928bdd1243dSDimitry Andric const SrcOp &Op0, const SrcOp &Op1,
929bdd1243dSDimitry Andric std::optional<unsigned> Flags) {
9300b57cec5SDimitry Andric
9318bcb0991SDimitry Andric return buildInstr(TargetOpcode::G_SELECT, {Res}, {Tst, Op0, Op1}, Flags);
9320b57cec5SDimitry Andric }
9330b57cec5SDimitry Andric
buildInsertSubvector(const DstOp & Res,const SrcOp & Src0,const SrcOp & Src1,unsigned Idx)934*0fca6ea1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildInsertSubvector(const DstOp &Res,
935*0fca6ea1SDimitry Andric const SrcOp &Src0,
936*0fca6ea1SDimitry Andric const SrcOp &Src1,
937*0fca6ea1SDimitry Andric unsigned Idx) {
938*0fca6ea1SDimitry Andric return buildInstr(TargetOpcode::G_INSERT_SUBVECTOR, Res,
939*0fca6ea1SDimitry Andric {Src0, Src1, uint64_t(Idx)});
940*0fca6ea1SDimitry Andric }
941*0fca6ea1SDimitry Andric
buildExtractSubvector(const DstOp & Res,const SrcOp & Src,unsigned Idx)942*0fca6ea1SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildExtractSubvector(const DstOp &Res,
943*0fca6ea1SDimitry Andric const SrcOp &Src,
944*0fca6ea1SDimitry Andric unsigned Idx) {
945*0fca6ea1SDimitry Andric return buildInstr(TargetOpcode::G_INSERT_SUBVECTOR, Res,
946*0fca6ea1SDimitry Andric {Src, uint64_t(Idx)});
947*0fca6ea1SDimitry Andric }
948*0fca6ea1SDimitry Andric
9490b57cec5SDimitry Andric MachineInstrBuilder
buildInsertVectorElement(const DstOp & Res,const SrcOp & Val,const SrcOp & Elt,const SrcOp & Idx)9500b57cec5SDimitry Andric MachineIRBuilder::buildInsertVectorElement(const DstOp &Res, const SrcOp &Val,
9510b57cec5SDimitry Andric const SrcOp &Elt, const SrcOp &Idx) {
9520b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_INSERT_VECTOR_ELT, Res, {Val, Elt, Idx});
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric
9550b57cec5SDimitry Andric MachineInstrBuilder
buildExtractVectorElement(const DstOp & Res,const SrcOp & Val,const SrcOp & Idx)9560b57cec5SDimitry Andric MachineIRBuilder::buildExtractVectorElement(const DstOp &Res, const SrcOp &Val,
9570b57cec5SDimitry Andric const SrcOp &Idx) {
9580b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_EXTRACT_VECTOR_ELT, Res, {Val, Idx});
9590b57cec5SDimitry Andric }
9600b57cec5SDimitry Andric
buildAtomicCmpXchgWithSuccess(const DstOp & OldValRes,const DstOp & SuccessRes,const SrcOp & Addr,const SrcOp & CmpVal,const SrcOp & NewVal,MachineMemOperand & MMO)9610b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAtomicCmpXchgWithSuccess(
962*0fca6ea1SDimitry Andric const DstOp &OldValRes, const DstOp &SuccessRes, const SrcOp &Addr,
963*0fca6ea1SDimitry Andric const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO) {
9640b57cec5SDimitry Andric #ifndef NDEBUG
965*0fca6ea1SDimitry Andric LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
966*0fca6ea1SDimitry Andric LLT SuccessResTy = SuccessRes.getLLTTy(*getMRI());
967*0fca6ea1SDimitry Andric LLT AddrTy = Addr.getLLTTy(*getMRI());
968*0fca6ea1SDimitry Andric LLT CmpValTy = CmpVal.getLLTTy(*getMRI());
969*0fca6ea1SDimitry Andric LLT NewValTy = NewVal.getLLTTy(*getMRI());
9700b57cec5SDimitry Andric assert(OldValResTy.isScalar() && "invalid operand type");
9710b57cec5SDimitry Andric assert(SuccessResTy.isScalar() && "invalid operand type");
9720b57cec5SDimitry Andric assert(AddrTy.isPointer() && "invalid operand type");
9730b57cec5SDimitry Andric assert(CmpValTy.isValid() && "invalid operand type");
9740b57cec5SDimitry Andric assert(NewValTy.isValid() && "invalid operand type");
9750b57cec5SDimitry Andric assert(OldValResTy == CmpValTy && "type mismatch");
9760b57cec5SDimitry Andric assert(OldValResTy == NewValTy && "type mismatch");
9770b57cec5SDimitry Andric #endif
9780b57cec5SDimitry Andric
979*0fca6ea1SDimitry Andric auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS);
980*0fca6ea1SDimitry Andric OldValRes.addDefToMIB(*getMRI(), MIB);
981*0fca6ea1SDimitry Andric SuccessRes.addDefToMIB(*getMRI(), MIB);
982*0fca6ea1SDimitry Andric Addr.addSrcToMIB(MIB);
983*0fca6ea1SDimitry Andric CmpVal.addSrcToMIB(MIB);
984*0fca6ea1SDimitry Andric NewVal.addSrcToMIB(MIB);
985*0fca6ea1SDimitry Andric MIB.addMemOperand(&MMO);
986*0fca6ea1SDimitry Andric return MIB;
9870b57cec5SDimitry Andric }
9880b57cec5SDimitry Andric
9890b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicCmpXchg(const DstOp & OldValRes,const SrcOp & Addr,const SrcOp & CmpVal,const SrcOp & NewVal,MachineMemOperand & MMO)990*0fca6ea1SDimitry Andric MachineIRBuilder::buildAtomicCmpXchg(const DstOp &OldValRes, const SrcOp &Addr,
991*0fca6ea1SDimitry Andric const SrcOp &CmpVal, const SrcOp &NewVal,
9920b57cec5SDimitry Andric MachineMemOperand &MMO) {
9930b57cec5SDimitry Andric #ifndef NDEBUG
994*0fca6ea1SDimitry Andric LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
995*0fca6ea1SDimitry Andric LLT AddrTy = Addr.getLLTTy(*getMRI());
996*0fca6ea1SDimitry Andric LLT CmpValTy = CmpVal.getLLTTy(*getMRI());
997*0fca6ea1SDimitry Andric LLT NewValTy = NewVal.getLLTTy(*getMRI());
9980b57cec5SDimitry Andric assert(OldValResTy.isScalar() && "invalid operand type");
9990b57cec5SDimitry Andric assert(AddrTy.isPointer() && "invalid operand type");
10000b57cec5SDimitry Andric assert(CmpValTy.isValid() && "invalid operand type");
10010b57cec5SDimitry Andric assert(NewValTy.isValid() && "invalid operand type");
10020b57cec5SDimitry Andric assert(OldValResTy == CmpValTy && "type mismatch");
10030b57cec5SDimitry Andric assert(OldValResTy == NewValTy && "type mismatch");
10040b57cec5SDimitry Andric #endif
10050b57cec5SDimitry Andric
1006*0fca6ea1SDimitry Andric auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG);
1007*0fca6ea1SDimitry Andric OldValRes.addDefToMIB(*getMRI(), MIB);
1008*0fca6ea1SDimitry Andric Addr.addSrcToMIB(MIB);
1009*0fca6ea1SDimitry Andric CmpVal.addSrcToMIB(MIB);
1010*0fca6ea1SDimitry Andric NewVal.addSrcToMIB(MIB);
1011*0fca6ea1SDimitry Andric MIB.addMemOperand(&MMO);
1012*0fca6ea1SDimitry Andric return MIB;
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric
buildAtomicRMW(unsigned Opcode,const DstOp & OldValRes,const SrcOp & Addr,const SrcOp & Val,MachineMemOperand & MMO)10158bcb0991SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAtomicRMW(
10168bcb0991SDimitry Andric unsigned Opcode, const DstOp &OldValRes,
10178bcb0991SDimitry Andric const SrcOp &Addr, const SrcOp &Val,
10180b57cec5SDimitry Andric MachineMemOperand &MMO) {
10198bcb0991SDimitry Andric
10200b57cec5SDimitry Andric #ifndef NDEBUG
10218bcb0991SDimitry Andric LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
10228bcb0991SDimitry Andric LLT AddrTy = Addr.getLLTTy(*getMRI());
10238bcb0991SDimitry Andric LLT ValTy = Val.getLLTTy(*getMRI());
10240b57cec5SDimitry Andric assert(AddrTy.isPointer() && "invalid operand type");
10250b57cec5SDimitry Andric assert(ValTy.isValid() && "invalid operand type");
10260b57cec5SDimitry Andric assert(OldValResTy == ValTy && "type mismatch");
10278bcb0991SDimitry Andric assert(MMO.isAtomic() && "not atomic mem operand");
10280b57cec5SDimitry Andric #endif
10290b57cec5SDimitry Andric
10308bcb0991SDimitry Andric auto MIB = buildInstr(Opcode);
10318bcb0991SDimitry Andric OldValRes.addDefToMIB(*getMRI(), MIB);
10328bcb0991SDimitry Andric Addr.addSrcToMIB(MIB);
10338bcb0991SDimitry Andric Val.addSrcToMIB(MIB);
10348bcb0991SDimitry Andric MIB.addMemOperand(&MMO);
10358bcb0991SDimitry Andric return MIB;
10360b57cec5SDimitry Andric }
10370b57cec5SDimitry Andric
10380b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWXchg(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)10390b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWXchg(Register OldValRes, Register Addr,
10400b57cec5SDimitry Andric Register Val, MachineMemOperand &MMO) {
10410b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XCHG, OldValRes, Addr, Val,
10420b57cec5SDimitry Andric MMO);
10430b57cec5SDimitry Andric }
10440b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWAdd(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)10450b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWAdd(Register OldValRes, Register Addr,
10460b57cec5SDimitry Andric Register Val, MachineMemOperand &MMO) {
10470b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_ADD, OldValRes, Addr, Val,
10480b57cec5SDimitry Andric MMO);
10490b57cec5SDimitry Andric }
10500b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWSub(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)10510b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWSub(Register OldValRes, Register Addr,
10520b57cec5SDimitry Andric Register Val, MachineMemOperand &MMO) {
10530b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_SUB, OldValRes, Addr, Val,
10540b57cec5SDimitry Andric MMO);
10550b57cec5SDimitry Andric }
10560b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWAnd(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)10570b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWAnd(Register OldValRes, Register Addr,
10580b57cec5SDimitry Andric Register Val, MachineMemOperand &MMO) {
10590b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_AND, OldValRes, Addr, Val,
10600b57cec5SDimitry Andric MMO);
10610b57cec5SDimitry Andric }
10620b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWNand(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)10630b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWNand(Register OldValRes, Register Addr,
10640b57cec5SDimitry Andric Register Val, MachineMemOperand &MMO) {
10650b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_NAND, OldValRes, Addr, Val,
10660b57cec5SDimitry Andric MMO);
10670b57cec5SDimitry Andric }
buildAtomicRMWOr(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)10680b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAtomicRMWOr(Register OldValRes,
10690b57cec5SDimitry Andric Register Addr,
10700b57cec5SDimitry Andric Register Val,
10710b57cec5SDimitry Andric MachineMemOperand &MMO) {
10720b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_OR, OldValRes, Addr, Val,
10730b57cec5SDimitry Andric MMO);
10740b57cec5SDimitry Andric }
10750b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWXor(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)10760b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWXor(Register OldValRes, Register Addr,
10770b57cec5SDimitry Andric Register Val, MachineMemOperand &MMO) {
10780b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XOR, OldValRes, Addr, Val,
10790b57cec5SDimitry Andric MMO);
10800b57cec5SDimitry Andric }
10810b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWMax(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)10820b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWMax(Register OldValRes, Register Addr,
10830b57cec5SDimitry Andric Register Val, MachineMemOperand &MMO) {
10840b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MAX, OldValRes, Addr, Val,
10850b57cec5SDimitry Andric MMO);
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWMin(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)10880b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWMin(Register OldValRes, Register Addr,
10890b57cec5SDimitry Andric Register Val, MachineMemOperand &MMO) {
10900b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MIN, OldValRes, Addr, Val,
10910b57cec5SDimitry Andric MMO);
10920b57cec5SDimitry Andric }
10930b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWUmax(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)10940b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWUmax(Register OldValRes, Register Addr,
10950b57cec5SDimitry Andric Register Val, MachineMemOperand &MMO) {
10960b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMAX, OldValRes, Addr, Val,
10970b57cec5SDimitry Andric MMO);
10980b57cec5SDimitry Andric }
10990b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWUmin(Register OldValRes,Register Addr,Register Val,MachineMemOperand & MMO)11000b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWUmin(Register OldValRes, Register Addr,
11010b57cec5SDimitry Andric Register Val, MachineMemOperand &MMO) {
11020b57cec5SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMIN, OldValRes, Addr, Val,
11030b57cec5SDimitry Andric MMO);
11040b57cec5SDimitry Andric }
11050b57cec5SDimitry Andric
11060b57cec5SDimitry Andric MachineInstrBuilder
buildAtomicRMWFAdd(const DstOp & OldValRes,const SrcOp & Addr,const SrcOp & Val,MachineMemOperand & MMO)11078bcb0991SDimitry Andric MachineIRBuilder::buildAtomicRMWFAdd(
11088bcb0991SDimitry Andric const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
11098bcb0991SDimitry Andric MachineMemOperand &MMO) {
11108bcb0991SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FADD, OldValRes, Addr, Val,
11118bcb0991SDimitry Andric MMO);
11128bcb0991SDimitry Andric }
11138bcb0991SDimitry Andric
11148bcb0991SDimitry Andric MachineInstrBuilder
buildAtomicRMWFSub(const DstOp & OldValRes,const SrcOp & Addr,const SrcOp & Val,MachineMemOperand & MMO)11158bcb0991SDimitry Andric MachineIRBuilder::buildAtomicRMWFSub(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
11168bcb0991SDimitry Andric MachineMemOperand &MMO) {
11178bcb0991SDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FSUB, OldValRes, Addr, Val,
11188bcb0991SDimitry Andric MMO);
11198bcb0991SDimitry Andric }
11208bcb0991SDimitry Andric
11218bcb0991SDimitry Andric MachineInstrBuilder
buildAtomicRMWFMax(const DstOp & OldValRes,const SrcOp & Addr,const SrcOp & Val,MachineMemOperand & MMO)1122753f127fSDimitry Andric MachineIRBuilder::buildAtomicRMWFMax(const DstOp &OldValRes, const SrcOp &Addr,
1123753f127fSDimitry Andric const SrcOp &Val, MachineMemOperand &MMO) {
1124753f127fSDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMAX, OldValRes, Addr, Val,
1125753f127fSDimitry Andric MMO);
1126753f127fSDimitry Andric }
1127753f127fSDimitry Andric
1128753f127fSDimitry Andric MachineInstrBuilder
buildAtomicRMWFMin(const DstOp & OldValRes,const SrcOp & Addr,const SrcOp & Val,MachineMemOperand & MMO)1129753f127fSDimitry Andric MachineIRBuilder::buildAtomicRMWFMin(const DstOp &OldValRes, const SrcOp &Addr,
1130753f127fSDimitry Andric const SrcOp &Val, MachineMemOperand &MMO) {
1131753f127fSDimitry Andric return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMIN, OldValRes, Addr, Val,
1132753f127fSDimitry Andric MMO);
1133753f127fSDimitry Andric }
1134753f127fSDimitry Andric
1135753f127fSDimitry Andric MachineInstrBuilder
buildFence(unsigned Ordering,unsigned Scope)11360b57cec5SDimitry Andric MachineIRBuilder::buildFence(unsigned Ordering, unsigned Scope) {
11370b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_FENCE)
11380b57cec5SDimitry Andric .addImm(Ordering)
11390b57cec5SDimitry Andric .addImm(Scope);
11400b57cec5SDimitry Andric }
11410b57cec5SDimitry Andric
buildPrefetch(const SrcOp & Addr,unsigned RW,unsigned Locality,unsigned CacheType,MachineMemOperand & MMO)11425f757f3fSDimitry Andric MachineInstrBuilder MachineIRBuilder::buildPrefetch(const SrcOp &Addr,
11435f757f3fSDimitry Andric unsigned RW,
11445f757f3fSDimitry Andric unsigned Locality,
11455f757f3fSDimitry Andric unsigned CacheType,
11465f757f3fSDimitry Andric MachineMemOperand &MMO) {
11475f757f3fSDimitry Andric auto MIB = buildInstr(TargetOpcode::G_PREFETCH);
11485f757f3fSDimitry Andric Addr.addSrcToMIB(MIB);
11495f757f3fSDimitry Andric MIB.addImm(RW).addImm(Locality).addImm(CacheType);
11505f757f3fSDimitry Andric MIB.addMemOperand(&MMO);
11515f757f3fSDimitry Andric return MIB;
11525f757f3fSDimitry Andric }
11535f757f3fSDimitry Andric
11540b57cec5SDimitry Andric MachineInstrBuilder
buildBlockAddress(Register Res,const BlockAddress * BA)11550b57cec5SDimitry Andric MachineIRBuilder::buildBlockAddress(Register Res, const BlockAddress *BA) {
11560b57cec5SDimitry Andric #ifndef NDEBUG
11570b57cec5SDimitry Andric assert(getMRI()->getType(Res).isPointer() && "invalid res type");
11580b57cec5SDimitry Andric #endif
11590b57cec5SDimitry Andric
11600b57cec5SDimitry Andric return buildInstr(TargetOpcode::G_BLOCK_ADDR).addDef(Res).addBlockAddress(BA);
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric
validateTruncExt(const LLT DstTy,const LLT SrcTy,bool IsExtend)11635ffd83dbSDimitry Andric void MachineIRBuilder::validateTruncExt(const LLT DstTy, const LLT SrcTy,
11640b57cec5SDimitry Andric bool IsExtend) {
11650b57cec5SDimitry Andric #ifndef NDEBUG
11660b57cec5SDimitry Andric if (DstTy.isVector()) {
11670b57cec5SDimitry Andric assert(SrcTy.isVector() && "mismatched cast between vector and non-vector");
11685f757f3fSDimitry Andric assert(SrcTy.getElementCount() == DstTy.getElementCount() &&
11690b57cec5SDimitry Andric "different number of elements in a trunc/ext");
11700b57cec5SDimitry Andric } else
11710b57cec5SDimitry Andric assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc");
11720b57cec5SDimitry Andric
11730b57cec5SDimitry Andric if (IsExtend)
11745f757f3fSDimitry Andric assert(TypeSize::isKnownGT(DstTy.getSizeInBits(), SrcTy.getSizeInBits()) &&
11750b57cec5SDimitry Andric "invalid narrowing extend");
11760b57cec5SDimitry Andric else
11775f757f3fSDimitry Andric assert(TypeSize::isKnownLT(DstTy.getSizeInBits(), SrcTy.getSizeInBits()) &&
11780b57cec5SDimitry Andric "invalid widening trunc");
11790b57cec5SDimitry Andric #endif
11800b57cec5SDimitry Andric }
11810b57cec5SDimitry Andric
validateSelectOp(const LLT ResTy,const LLT TstTy,const LLT Op0Ty,const LLT Op1Ty)11825ffd83dbSDimitry Andric void MachineIRBuilder::validateSelectOp(const LLT ResTy, const LLT TstTy,
11835ffd83dbSDimitry Andric const LLT Op0Ty, const LLT Op1Ty) {
11840b57cec5SDimitry Andric #ifndef NDEBUG
11850b57cec5SDimitry Andric assert((ResTy.isScalar() || ResTy.isVector() || ResTy.isPointer()) &&
11860b57cec5SDimitry Andric "invalid operand type");
11870b57cec5SDimitry Andric assert((ResTy == Op0Ty && ResTy == Op1Ty) && "type mismatch");
11880b57cec5SDimitry Andric if (ResTy.isScalar() || ResTy.isPointer())
11890b57cec5SDimitry Andric assert(TstTy.isScalar() && "type mismatch");
11900b57cec5SDimitry Andric else
11910b57cec5SDimitry Andric assert((TstTy.isScalar() ||
11920b57cec5SDimitry Andric (TstTy.isVector() &&
1193*0fca6ea1SDimitry Andric TstTy.getElementCount() == Op0Ty.getElementCount())) &&
11940b57cec5SDimitry Andric "type mismatch");
11950b57cec5SDimitry Andric #endif
11960b57cec5SDimitry Andric }
11970b57cec5SDimitry Andric
1198bdd1243dSDimitry Andric MachineInstrBuilder
buildInstr(unsigned Opc,ArrayRef<DstOp> DstOps,ArrayRef<SrcOp> SrcOps,std::optional<unsigned> Flags)1199bdd1243dSDimitry Andric MachineIRBuilder::buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps,
12000b57cec5SDimitry Andric ArrayRef<SrcOp> SrcOps,
1201bdd1243dSDimitry Andric std::optional<unsigned> Flags) {
12020b57cec5SDimitry Andric switch (Opc) {
12030b57cec5SDimitry Andric default:
12040b57cec5SDimitry Andric break;
12050b57cec5SDimitry Andric case TargetOpcode::G_SELECT: {
12060b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid select");
12070b57cec5SDimitry Andric assert(SrcOps.size() == 3 && "Invalid select");
12080b57cec5SDimitry Andric validateSelectOp(
12090b57cec5SDimitry Andric DstOps[0].getLLTTy(*getMRI()), SrcOps[0].getLLTTy(*getMRI()),
12100b57cec5SDimitry Andric SrcOps[1].getLLTTy(*getMRI()), SrcOps[2].getLLTTy(*getMRI()));
12110b57cec5SDimitry Andric break;
12120b57cec5SDimitry Andric }
1213e8d8bef9SDimitry Andric case TargetOpcode::G_FNEG:
1214e8d8bef9SDimitry Andric case TargetOpcode::G_ABS:
1215e8d8bef9SDimitry Andric // All these are unary ops.
1216e8d8bef9SDimitry Andric assert(DstOps.size() == 1 && "Invalid Dst");
1217e8d8bef9SDimitry Andric assert(SrcOps.size() == 1 && "Invalid Srcs");
1218e8d8bef9SDimitry Andric validateUnaryOp(DstOps[0].getLLTTy(*getMRI()),
1219e8d8bef9SDimitry Andric SrcOps[0].getLLTTy(*getMRI()));
1220e8d8bef9SDimitry Andric break;
12210b57cec5SDimitry Andric case TargetOpcode::G_ADD:
12220b57cec5SDimitry Andric case TargetOpcode::G_AND:
12230b57cec5SDimitry Andric case TargetOpcode::G_MUL:
12240b57cec5SDimitry Andric case TargetOpcode::G_OR:
12250b57cec5SDimitry Andric case TargetOpcode::G_SUB:
12260b57cec5SDimitry Andric case TargetOpcode::G_XOR:
12270b57cec5SDimitry Andric case TargetOpcode::G_UDIV:
12280b57cec5SDimitry Andric case TargetOpcode::G_SDIV:
12290b57cec5SDimitry Andric case TargetOpcode::G_UREM:
12300b57cec5SDimitry Andric case TargetOpcode::G_SREM:
12310b57cec5SDimitry Andric case TargetOpcode::G_SMIN:
12320b57cec5SDimitry Andric case TargetOpcode::G_SMAX:
12330b57cec5SDimitry Andric case TargetOpcode::G_UMIN:
12345ffd83dbSDimitry Andric case TargetOpcode::G_UMAX:
12355ffd83dbSDimitry Andric case TargetOpcode::G_UADDSAT:
12365ffd83dbSDimitry Andric case TargetOpcode::G_SADDSAT:
12375ffd83dbSDimitry Andric case TargetOpcode::G_USUBSAT:
12385ffd83dbSDimitry Andric case TargetOpcode::G_SSUBSAT: {
12390b57cec5SDimitry Andric // All these are binary ops.
12400b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid Dst");
12410b57cec5SDimitry Andric assert(SrcOps.size() == 2 && "Invalid Srcs");
12420b57cec5SDimitry Andric validateBinaryOp(DstOps[0].getLLTTy(*getMRI()),
12430b57cec5SDimitry Andric SrcOps[0].getLLTTy(*getMRI()),
12440b57cec5SDimitry Andric SrcOps[1].getLLTTy(*getMRI()));
12450b57cec5SDimitry Andric break;
12460b57cec5SDimitry Andric }
12470b57cec5SDimitry Andric case TargetOpcode::G_SHL:
12480b57cec5SDimitry Andric case TargetOpcode::G_ASHR:
1249e8d8bef9SDimitry Andric case TargetOpcode::G_LSHR:
1250e8d8bef9SDimitry Andric case TargetOpcode::G_USHLSAT:
1251e8d8bef9SDimitry Andric case TargetOpcode::G_SSHLSAT: {
12520b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid Dst");
12530b57cec5SDimitry Andric assert(SrcOps.size() == 2 && "Invalid Srcs");
12540b57cec5SDimitry Andric validateShiftOp(DstOps[0].getLLTTy(*getMRI()),
12550b57cec5SDimitry Andric SrcOps[0].getLLTTy(*getMRI()),
12560b57cec5SDimitry Andric SrcOps[1].getLLTTy(*getMRI()));
12570b57cec5SDimitry Andric break;
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric case TargetOpcode::G_SEXT:
12600b57cec5SDimitry Andric case TargetOpcode::G_ZEXT:
12610b57cec5SDimitry Andric case TargetOpcode::G_ANYEXT:
12620b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid Dst");
12630b57cec5SDimitry Andric assert(SrcOps.size() == 1 && "Invalid Srcs");
12640b57cec5SDimitry Andric validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
12650b57cec5SDimitry Andric SrcOps[0].getLLTTy(*getMRI()), true);
12660b57cec5SDimitry Andric break;
12670b57cec5SDimitry Andric case TargetOpcode::G_TRUNC:
12680b57cec5SDimitry Andric case TargetOpcode::G_FPTRUNC: {
12690b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid Dst");
12700b57cec5SDimitry Andric assert(SrcOps.size() == 1 && "Invalid Srcs");
12710b57cec5SDimitry Andric validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
12720b57cec5SDimitry Andric SrcOps[0].getLLTTy(*getMRI()), false);
12730b57cec5SDimitry Andric break;
12740b57cec5SDimitry Andric }
12755ffd83dbSDimitry Andric case TargetOpcode::G_BITCAST: {
12765ffd83dbSDimitry Andric assert(DstOps.size() == 1 && "Invalid Dst");
12775ffd83dbSDimitry Andric assert(SrcOps.size() == 1 && "Invalid Srcs");
12785ffd83dbSDimitry Andric assert(DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
12795ffd83dbSDimitry Andric SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() && "invalid bitcast");
12805ffd83dbSDimitry Andric break;
12815ffd83dbSDimitry Andric }
12820b57cec5SDimitry Andric case TargetOpcode::COPY:
12830b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid Dst");
12840b57cec5SDimitry Andric // If the caller wants to add a subreg source it has to be done separately
12850b57cec5SDimitry Andric // so we may not have any SrcOps at this point yet.
12860b57cec5SDimitry Andric break;
12870b57cec5SDimitry Andric case TargetOpcode::G_FCMP:
12880b57cec5SDimitry Andric case TargetOpcode::G_ICMP: {
12890b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid Dst Operands");
12900b57cec5SDimitry Andric assert(SrcOps.size() == 3 && "Invalid Src Operands");
12910b57cec5SDimitry Andric // For F/ICMP, the first src operand is the predicate, followed by
12920b57cec5SDimitry Andric // the two comparands.
12930b57cec5SDimitry Andric assert(SrcOps[0].getSrcOpKind() == SrcOp::SrcType::Ty_Predicate &&
12940b57cec5SDimitry Andric "Expecting predicate");
12950b57cec5SDimitry Andric assert([&]() -> bool {
12960b57cec5SDimitry Andric CmpInst::Predicate Pred = SrcOps[0].getPredicate();
12970b57cec5SDimitry Andric return Opc == TargetOpcode::G_ICMP ? CmpInst::isIntPredicate(Pred)
12980b57cec5SDimitry Andric : CmpInst::isFPPredicate(Pred);
12990b57cec5SDimitry Andric }() && "Invalid predicate");
13000b57cec5SDimitry Andric assert(SrcOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
13010b57cec5SDimitry Andric "Type mismatch");
13020b57cec5SDimitry Andric assert([&]() -> bool {
13030b57cec5SDimitry Andric LLT Op0Ty = SrcOps[1].getLLTTy(*getMRI());
13040b57cec5SDimitry Andric LLT DstTy = DstOps[0].getLLTTy(*getMRI());
13050b57cec5SDimitry Andric if (Op0Ty.isScalar() || Op0Ty.isPointer())
13060b57cec5SDimitry Andric return DstTy.isScalar();
13070b57cec5SDimitry Andric else
13080b57cec5SDimitry Andric return DstTy.isVector() &&
1309*0fca6ea1SDimitry Andric DstTy.getElementCount() == Op0Ty.getElementCount();
13100b57cec5SDimitry Andric }() && "Type Mismatch");
13110b57cec5SDimitry Andric break;
13120b57cec5SDimitry Andric }
13130b57cec5SDimitry Andric case TargetOpcode::G_UNMERGE_VALUES: {
13140b57cec5SDimitry Andric assert(!DstOps.empty() && "Invalid trivial sequence");
13150b57cec5SDimitry Andric assert(SrcOps.size() == 1 && "Invalid src for Unmerge");
1316e8d8bef9SDimitry Andric assert(llvm::all_of(DstOps,
13170b57cec5SDimitry Andric [&, this](const DstOp &Op) {
13180b57cec5SDimitry Andric return Op.getLLTTy(*getMRI()) ==
13190b57cec5SDimitry Andric DstOps[0].getLLTTy(*getMRI());
13200b57cec5SDimitry Andric }) &&
13210b57cec5SDimitry Andric "type mismatch in output list");
1322fe6060f1SDimitry Andric assert((TypeSize::ScalarTy)DstOps.size() *
1323fe6060f1SDimitry Andric DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
13240b57cec5SDimitry Andric SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
13250b57cec5SDimitry Andric "input operands do not cover output register");
13260b57cec5SDimitry Andric break;
13270b57cec5SDimitry Andric }
13280b57cec5SDimitry Andric case TargetOpcode::G_MERGE_VALUES: {
1329bdd1243dSDimitry Andric assert(SrcOps.size() >= 2 && "invalid trivial sequence");
13300b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid Dst");
1331e8d8bef9SDimitry Andric assert(llvm::all_of(SrcOps,
13320b57cec5SDimitry Andric [&, this](const SrcOp &Op) {
13330b57cec5SDimitry Andric return Op.getLLTTy(*getMRI()) ==
13340b57cec5SDimitry Andric SrcOps[0].getLLTTy(*getMRI());
13350b57cec5SDimitry Andric }) &&
13360b57cec5SDimitry Andric "type mismatch in input list");
1337fe6060f1SDimitry Andric assert((TypeSize::ScalarTy)SrcOps.size() *
1338fe6060f1SDimitry Andric SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
13390b57cec5SDimitry Andric DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
13400b57cec5SDimitry Andric "input operands do not cover output register");
1341bdd1243dSDimitry Andric assert(!DstOps[0].getLLTTy(*getMRI()).isVector() &&
1342bdd1243dSDimitry Andric "vectors should be built with G_CONCAT_VECTOR or G_BUILD_VECTOR");
13430b57cec5SDimitry Andric break;
13440b57cec5SDimitry Andric }
13450b57cec5SDimitry Andric case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
13460b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid Dst size");
13470b57cec5SDimitry Andric assert(SrcOps.size() == 2 && "Invalid Src size");
13480b57cec5SDimitry Andric assert(SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
13490b57cec5SDimitry Andric assert((DstOps[0].getLLTTy(*getMRI()).isScalar() ||
13500b57cec5SDimitry Andric DstOps[0].getLLTTy(*getMRI()).isPointer()) &&
13510b57cec5SDimitry Andric "Invalid operand type");
13520b57cec5SDimitry Andric assert(SrcOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand type");
13530b57cec5SDimitry Andric assert(SrcOps[0].getLLTTy(*getMRI()).getElementType() ==
13540b57cec5SDimitry Andric DstOps[0].getLLTTy(*getMRI()) &&
13550b57cec5SDimitry Andric "Type mismatch");
13560b57cec5SDimitry Andric break;
13570b57cec5SDimitry Andric }
13580b57cec5SDimitry Andric case TargetOpcode::G_INSERT_VECTOR_ELT: {
13590b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid dst size");
13600b57cec5SDimitry Andric assert(SrcOps.size() == 3 && "Invalid src size");
13610b57cec5SDimitry Andric assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
13620b57cec5SDimitry Andric SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
13630b57cec5SDimitry Andric assert(DstOps[0].getLLTTy(*getMRI()).getElementType() ==
13640b57cec5SDimitry Andric SrcOps[1].getLLTTy(*getMRI()) &&
13650b57cec5SDimitry Andric "Type mismatch");
13660b57cec5SDimitry Andric assert(SrcOps[2].getLLTTy(*getMRI()).isScalar() && "Invalid index");
1367*0fca6ea1SDimitry Andric assert(DstOps[0].getLLTTy(*getMRI()).getElementCount() ==
1368*0fca6ea1SDimitry Andric SrcOps[0].getLLTTy(*getMRI()).getElementCount() &&
13690b57cec5SDimitry Andric "Type mismatch");
13700b57cec5SDimitry Andric break;
13710b57cec5SDimitry Andric }
13720b57cec5SDimitry Andric case TargetOpcode::G_BUILD_VECTOR: {
13730b57cec5SDimitry Andric assert((!SrcOps.empty() || SrcOps.size() < 2) &&
13740b57cec5SDimitry Andric "Must have at least 2 operands");
13750b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid DstOps");
13760b57cec5SDimitry Andric assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
13770b57cec5SDimitry Andric "Res type must be a vector");
1378e8d8bef9SDimitry Andric assert(llvm::all_of(SrcOps,
13790b57cec5SDimitry Andric [&, this](const SrcOp &Op) {
13800b57cec5SDimitry Andric return Op.getLLTTy(*getMRI()) ==
13810b57cec5SDimitry Andric SrcOps[0].getLLTTy(*getMRI());
13820b57cec5SDimitry Andric }) &&
13830b57cec5SDimitry Andric "type mismatch in input list");
1384fe6060f1SDimitry Andric assert((TypeSize::ScalarTy)SrcOps.size() *
1385fe6060f1SDimitry Andric SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
13860b57cec5SDimitry Andric DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
13870b57cec5SDimitry Andric "input scalars do not exactly cover the output vector register");
13880b57cec5SDimitry Andric break;
13890b57cec5SDimitry Andric }
13900b57cec5SDimitry Andric case TargetOpcode::G_BUILD_VECTOR_TRUNC: {
13910b57cec5SDimitry Andric assert((!SrcOps.empty() || SrcOps.size() < 2) &&
13920b57cec5SDimitry Andric "Must have at least 2 operands");
13930b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid DstOps");
13940b57cec5SDimitry Andric assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
13950b57cec5SDimitry Andric "Res type must be a vector");
1396e8d8bef9SDimitry Andric assert(llvm::all_of(SrcOps,
13970b57cec5SDimitry Andric [&, this](const SrcOp &Op) {
13980b57cec5SDimitry Andric return Op.getLLTTy(*getMRI()) ==
13990b57cec5SDimitry Andric SrcOps[0].getLLTTy(*getMRI());
14000b57cec5SDimitry Andric }) &&
14010b57cec5SDimitry Andric "type mismatch in input list");
14020b57cec5SDimitry Andric break;
14030b57cec5SDimitry Andric }
14040b57cec5SDimitry Andric case TargetOpcode::G_CONCAT_VECTORS: {
14050b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid DstOps");
14060b57cec5SDimitry Andric assert((!SrcOps.empty() || SrcOps.size() < 2) &&
14070b57cec5SDimitry Andric "Must have at least 2 operands");
1408e8d8bef9SDimitry Andric assert(llvm::all_of(SrcOps,
14090b57cec5SDimitry Andric [&, this](const SrcOp &Op) {
14100b57cec5SDimitry Andric return (Op.getLLTTy(*getMRI()).isVector() &&
14110b57cec5SDimitry Andric Op.getLLTTy(*getMRI()) ==
14120b57cec5SDimitry Andric SrcOps[0].getLLTTy(*getMRI()));
14130b57cec5SDimitry Andric }) &&
14140b57cec5SDimitry Andric "type mismatch in input list");
1415fe6060f1SDimitry Andric assert((TypeSize::ScalarTy)SrcOps.size() *
1416fe6060f1SDimitry Andric SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
14170b57cec5SDimitry Andric DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
14180b57cec5SDimitry Andric "input vectors do not exactly cover the output vector register");
14190b57cec5SDimitry Andric break;
14200b57cec5SDimitry Andric }
14210b57cec5SDimitry Andric case TargetOpcode::G_UADDE: {
14220b57cec5SDimitry Andric assert(DstOps.size() == 2 && "Invalid no of dst operands");
14230b57cec5SDimitry Andric assert(SrcOps.size() == 3 && "Invalid no of src operands");
14240b57cec5SDimitry Andric assert(DstOps[0].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
14250b57cec5SDimitry Andric assert((DstOps[0].getLLTTy(*getMRI()) == SrcOps[0].getLLTTy(*getMRI())) &&
14260b57cec5SDimitry Andric (DstOps[0].getLLTTy(*getMRI()) == SrcOps[1].getLLTTy(*getMRI())) &&
14270b57cec5SDimitry Andric "Invalid operand");
14280b57cec5SDimitry Andric assert(DstOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
14290b57cec5SDimitry Andric assert(DstOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
14300b57cec5SDimitry Andric "type mismatch");
14310b57cec5SDimitry Andric break;
14320b57cec5SDimitry Andric }
14330b57cec5SDimitry Andric }
14340b57cec5SDimitry Andric
14350b57cec5SDimitry Andric auto MIB = buildInstr(Opc);
14360b57cec5SDimitry Andric for (const DstOp &Op : DstOps)
14370b57cec5SDimitry Andric Op.addDefToMIB(*getMRI(), MIB);
14380b57cec5SDimitry Andric for (const SrcOp &Op : SrcOps)
14390b57cec5SDimitry Andric Op.addSrcToMIB(MIB);
14400b57cec5SDimitry Andric if (Flags)
14410b57cec5SDimitry Andric MIB->setFlags(*Flags);
14420b57cec5SDimitry Andric return MIB;
14430b57cec5SDimitry Andric }
1444