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