xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (revision 8bcb0991864975618c09697b1aca10683346d9f0)
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/GlobalISel/GISelChangeObserver.h"
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
220b57cec5SDimitry Andric #include "llvm/IR/DebugInfo.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric void MachineIRBuilder::setMF(MachineFunction &MF) {
270b57cec5SDimitry Andric   State.MF = &MF;
280b57cec5SDimitry Andric   State.MBB = nullptr;
290b57cec5SDimitry Andric   State.MRI = &MF.getRegInfo();
300b57cec5SDimitry Andric   State.TII = MF.getSubtarget().getInstrInfo();
310b57cec5SDimitry Andric   State.DL = DebugLoc();
320b57cec5SDimitry Andric   State.II = MachineBasicBlock::iterator();
330b57cec5SDimitry Andric   State.Observer = nullptr;
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric void MachineIRBuilder::setMBB(MachineBasicBlock &MBB) {
370b57cec5SDimitry Andric   State.MBB = &MBB;
380b57cec5SDimitry Andric   State.II = MBB.end();
390b57cec5SDimitry Andric   assert(&getMF() == MBB.getParent() &&
400b57cec5SDimitry Andric          "Basic block is in a different function");
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric void MachineIRBuilder::setInstr(MachineInstr &MI) {
440b57cec5SDimitry Andric   assert(MI.getParent() && "Instruction is not part of a basic block");
450b57cec5SDimitry Andric   setMBB(*MI.getParent());
460b57cec5SDimitry Andric   State.II = MI.getIterator();
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric void MachineIRBuilder::setCSEInfo(GISelCSEInfo *Info) { State.CSEInfo = Info; }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric void MachineIRBuilder::setInsertPt(MachineBasicBlock &MBB,
520b57cec5SDimitry Andric                                    MachineBasicBlock::iterator II) {
530b57cec5SDimitry Andric   assert(MBB.getParent() == &getMF() &&
540b57cec5SDimitry Andric          "Basic block is in a different function");
550b57cec5SDimitry Andric   State.MBB = &MBB;
560b57cec5SDimitry Andric   State.II = II;
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric void MachineIRBuilder::recordInsertion(MachineInstr *InsertedInstr) const {
600b57cec5SDimitry Andric   if (State.Observer)
610b57cec5SDimitry Andric     State.Observer->createdInstr(*InsertedInstr);
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric void MachineIRBuilder::setChangeObserver(GISelChangeObserver &Observer) {
650b57cec5SDimitry Andric   State.Observer = &Observer;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric void MachineIRBuilder::stopObservingChanges() { State.Observer = nullptr; }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric //------------------------------------------------------------------------------
710b57cec5SDimitry Andric // Build instruction variants.
720b57cec5SDimitry Andric //------------------------------------------------------------------------------
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opcode) {
750b57cec5SDimitry Andric   return insertInstr(buildInstrNoInsert(Opcode));
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildInstrNoInsert(unsigned Opcode) {
790b57cec5SDimitry Andric   MachineInstrBuilder MIB = BuildMI(getMF(), getDL(), getTII().get(Opcode));
800b57cec5SDimitry Andric   return MIB;
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::insertInstr(MachineInstrBuilder MIB) {
840b57cec5SDimitry Andric   getMBB().insert(getInsertPt(), MIB);
850b57cec5SDimitry Andric   recordInsertion(MIB);
860b57cec5SDimitry Andric   return MIB;
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric MachineInstrBuilder
900b57cec5SDimitry Andric MachineIRBuilder::buildDirectDbgValue(Register Reg, const MDNode *Variable,
910b57cec5SDimitry Andric                                       const MDNode *Expr) {
920b57cec5SDimitry Andric   assert(isa<DILocalVariable>(Variable) && "not a variable");
930b57cec5SDimitry Andric   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
940b57cec5SDimitry Andric   assert(
950b57cec5SDimitry Andric       cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
960b57cec5SDimitry Andric       "Expected inlined-at fields to agree");
970b57cec5SDimitry Andric   return insertInstr(BuildMI(getMF(), getDL(),
980b57cec5SDimitry Andric                              getTII().get(TargetOpcode::DBG_VALUE),
990b57cec5SDimitry Andric                              /*IsIndirect*/ false, Reg, Variable, Expr));
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric MachineInstrBuilder
1030b57cec5SDimitry Andric MachineIRBuilder::buildIndirectDbgValue(Register Reg, const MDNode *Variable,
1040b57cec5SDimitry Andric                                         const MDNode *Expr) {
1050b57cec5SDimitry Andric   assert(isa<DILocalVariable>(Variable) && "not a variable");
1060b57cec5SDimitry Andric   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
1070b57cec5SDimitry Andric   assert(
1080b57cec5SDimitry Andric       cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
1090b57cec5SDimitry Andric       "Expected inlined-at fields to agree");
110*8bcb0991SDimitry Andric   // DBG_VALUE insts now carry IR-level indirection in their DIExpression
111*8bcb0991SDimitry Andric   // rather than encoding it in the instruction itself.
112*8bcb0991SDimitry Andric   const DIExpression *DIExpr = cast<DIExpression>(Expr);
113*8bcb0991SDimitry Andric   DIExpr = DIExpression::append(DIExpr, {dwarf::DW_OP_deref});
1140b57cec5SDimitry Andric   return insertInstr(BuildMI(getMF(), getDL(),
1150b57cec5SDimitry Andric                              getTII().get(TargetOpcode::DBG_VALUE),
116*8bcb0991SDimitry Andric                              /*IsIndirect*/ false, Reg, Variable, DIExpr));
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFIDbgValue(int FI,
1200b57cec5SDimitry Andric                                                       const MDNode *Variable,
1210b57cec5SDimitry Andric                                                       const MDNode *Expr) {
1220b57cec5SDimitry Andric   assert(isa<DILocalVariable>(Variable) && "not a variable");
1230b57cec5SDimitry Andric   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
1240b57cec5SDimitry Andric   assert(
1250b57cec5SDimitry Andric       cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
1260b57cec5SDimitry Andric       "Expected inlined-at fields to agree");
127*8bcb0991SDimitry Andric   // DBG_VALUE insts now carry IR-level indirection in their DIExpression
128*8bcb0991SDimitry Andric   // rather than encoding it in the instruction itself.
129*8bcb0991SDimitry Andric   const DIExpression *DIExpr = cast<DIExpression>(Expr);
130*8bcb0991SDimitry Andric   DIExpr = DIExpression::append(DIExpr, {dwarf::DW_OP_deref});
1310b57cec5SDimitry Andric   return buildInstr(TargetOpcode::DBG_VALUE)
1320b57cec5SDimitry Andric       .addFrameIndex(FI)
133*8bcb0991SDimitry Andric       .addReg(0)
1340b57cec5SDimitry Andric       .addMetadata(Variable)
135*8bcb0991SDimitry Andric       .addMetadata(DIExpr);
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstDbgValue(const Constant &C,
1390b57cec5SDimitry Andric                                                          const MDNode *Variable,
1400b57cec5SDimitry Andric                                                          const MDNode *Expr) {
1410b57cec5SDimitry Andric   assert(isa<DILocalVariable>(Variable) && "not a variable");
1420b57cec5SDimitry Andric   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
1430b57cec5SDimitry Andric   assert(
1440b57cec5SDimitry Andric       cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
1450b57cec5SDimitry Andric       "Expected inlined-at fields to agree");
1460b57cec5SDimitry Andric   auto MIB = buildInstr(TargetOpcode::DBG_VALUE);
1470b57cec5SDimitry Andric   if (auto *CI = dyn_cast<ConstantInt>(&C)) {
1480b57cec5SDimitry Andric     if (CI->getBitWidth() > 64)
1490b57cec5SDimitry Andric       MIB.addCImm(CI);
1500b57cec5SDimitry Andric     else
1510b57cec5SDimitry Andric       MIB.addImm(CI->getZExtValue());
1520b57cec5SDimitry Andric   } else if (auto *CFP = dyn_cast<ConstantFP>(&C)) {
1530b57cec5SDimitry Andric     MIB.addFPImm(CFP);
1540b57cec5SDimitry Andric   } else {
1550b57cec5SDimitry Andric     // Insert %noreg if we didn't find a usable constant and had to drop it.
1560b57cec5SDimitry Andric     MIB.addReg(0U);
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric 
159*8bcb0991SDimitry Andric   return MIB.addReg(0).addMetadata(Variable).addMetadata(Expr);
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildDbgLabel(const MDNode *Label) {
1630b57cec5SDimitry Andric   assert(isa<DILabel>(Label) && "not a label");
1640b57cec5SDimitry Andric   assert(cast<DILabel>(Label)->isValidLocationForIntrinsic(State.DL) &&
1650b57cec5SDimitry Andric          "Expected inlined-at fields to agree");
1660b57cec5SDimitry Andric   auto MIB = buildInstr(TargetOpcode::DBG_LABEL);
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   return MIB.addMetadata(Label);
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
171*8bcb0991SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildDynStackAlloc(const DstOp &Res,
172*8bcb0991SDimitry Andric                                                          const SrcOp &Size,
173*8bcb0991SDimitry Andric                                                          unsigned Align) {
174*8bcb0991SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isPointer() && "expected ptr dst type");
175*8bcb0991SDimitry Andric   auto MIB = buildInstr(TargetOpcode::G_DYN_STACKALLOC);
176*8bcb0991SDimitry Andric   Res.addDefToMIB(*getMRI(), MIB);
177*8bcb0991SDimitry Andric   Size.addSrcToMIB(MIB);
178*8bcb0991SDimitry Andric   MIB.addImm(Align);
179*8bcb0991SDimitry Andric   return MIB;
180*8bcb0991SDimitry Andric }
181*8bcb0991SDimitry Andric 
1820b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFrameIndex(const DstOp &Res,
1830b57cec5SDimitry Andric                                                       int Idx) {
1840b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
1850b57cec5SDimitry Andric   auto MIB = buildInstr(TargetOpcode::G_FRAME_INDEX);
1860b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), MIB);
1870b57cec5SDimitry Andric   MIB.addFrameIndex(Idx);
1880b57cec5SDimitry Andric   return MIB;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildGlobalValue(const DstOp &Res,
1920b57cec5SDimitry Andric                                                        const GlobalValue *GV) {
1930b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
1940b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).getAddressSpace() ==
1950b57cec5SDimitry Andric              GV->getType()->getAddressSpace() &&
1960b57cec5SDimitry Andric          "address space mismatch");
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   auto MIB = buildInstr(TargetOpcode::G_GLOBAL_VALUE);
1990b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), MIB);
2000b57cec5SDimitry Andric   MIB.addGlobalAddress(GV);
2010b57cec5SDimitry Andric   return MIB;
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildJumpTable(const LLT PtrTy,
2050b57cec5SDimitry Andric                                                      unsigned JTI) {
2060b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_JUMP_TABLE, {PtrTy}, {})
2070b57cec5SDimitry Andric       .addJumpTableIndex(JTI);
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric void MachineIRBuilder::validateBinaryOp(const LLT &Res, const LLT &Op0,
2110b57cec5SDimitry Andric                                         const LLT &Op1) {
2120b57cec5SDimitry Andric   assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
2130b57cec5SDimitry Andric   assert((Res == Op0 && Res == Op1) && "type mismatch");
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric void MachineIRBuilder::validateShiftOp(const LLT &Res, const LLT &Op0,
2170b57cec5SDimitry Andric                                        const LLT &Op1) {
2180b57cec5SDimitry Andric   assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
2190b57cec5SDimitry Andric   assert((Res == Op0) && "type mismatch");
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildGEP(const DstOp &Res,
2230b57cec5SDimitry Andric                                                const SrcOp &Op0,
2240b57cec5SDimitry Andric                                                const SrcOp &Op1) {
2250b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isPointer() &&
2260b57cec5SDimitry Andric          Res.getLLTTy(*getMRI()) == Op0.getLLTTy(*getMRI()) && "type mismatch");
2270b57cec5SDimitry Andric   assert(Op1.getLLTTy(*getMRI()).isScalar() && "invalid offset type");
2280b57cec5SDimitry Andric 
229*8bcb0991SDimitry Andric   return buildInstr(TargetOpcode::G_GEP, {Res}, {Op0, Op1});
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric Optional<MachineInstrBuilder>
2330b57cec5SDimitry Andric MachineIRBuilder::materializeGEP(Register &Res, Register Op0,
2340b57cec5SDimitry Andric                                  const LLT &ValueTy, uint64_t Value) {
2350b57cec5SDimitry Andric   assert(Res == 0 && "Res is a result argument");
2360b57cec5SDimitry Andric   assert(ValueTy.isScalar()  && "invalid offset type");
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   if (Value == 0) {
2390b57cec5SDimitry Andric     Res = Op0;
2400b57cec5SDimitry Andric     return None;
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   Res = getMRI()->createGenericVirtualRegister(getMRI()->getType(Op0));
2440b57cec5SDimitry Andric   auto Cst = buildConstant(ValueTy, Value);
2450b57cec5SDimitry Andric   return buildGEP(Res, Op0, Cst.getReg(0));
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildPtrMask(const DstOp &Res,
2490b57cec5SDimitry Andric                                                    const SrcOp &Op0,
2500b57cec5SDimitry Andric                                                    uint32_t NumBits) {
2510b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isPointer() &&
2520b57cec5SDimitry Andric          Res.getLLTTy(*getMRI()) == Op0.getLLTTy(*getMRI()) && "type mismatch");
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   auto MIB = buildInstr(TargetOpcode::G_PTR_MASK);
2550b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), MIB);
2560b57cec5SDimitry Andric   Op0.addSrcToMIB(MIB);
2570b57cec5SDimitry Andric   MIB.addImm(NumBits);
2580b57cec5SDimitry Andric   return MIB;
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
2620b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BR).addMBB(&Dest);
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBrIndirect(Register Tgt) {
2660b57cec5SDimitry Andric   assert(getMRI()->getType(Tgt).isPointer() && "invalid branch destination");
2670b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BRINDIRECT).addUse(Tgt);
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBrJT(Register TablePtr,
2710b57cec5SDimitry Andric                                                 unsigned JTI,
2720b57cec5SDimitry Andric                                                 Register IndexReg) {
2730b57cec5SDimitry Andric   assert(getMRI()->getType(TablePtr).isPointer() &&
2740b57cec5SDimitry Andric          "Table reg must be a pointer");
2750b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BRJT)
2760b57cec5SDimitry Andric       .addUse(TablePtr)
2770b57cec5SDimitry Andric       .addJumpTableIndex(JTI)
2780b57cec5SDimitry Andric       .addUse(IndexReg);
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildCopy(const DstOp &Res,
2820b57cec5SDimitry Andric                                                 const SrcOp &Op) {
2830b57cec5SDimitry Andric   return buildInstr(TargetOpcode::COPY, Res, Op);
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
2870b57cec5SDimitry Andric                                                     const ConstantInt &Val) {
2880b57cec5SDimitry Andric   LLT Ty = Res.getLLTTy(*getMRI());
2890b57cec5SDimitry Andric   LLT EltTy = Ty.getScalarType();
2900b57cec5SDimitry Andric   assert(EltTy.getScalarSizeInBits() == Val.getBitWidth() &&
2910b57cec5SDimitry Andric          "creating constant with the wrong size");
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   if (Ty.isVector()) {
2940b57cec5SDimitry Andric     auto Const = buildInstr(TargetOpcode::G_CONSTANT)
2950b57cec5SDimitry Andric     .addDef(getMRI()->createGenericVirtualRegister(EltTy))
2960b57cec5SDimitry Andric     .addCImm(&Val);
2970b57cec5SDimitry Andric     return buildSplatVector(Res, Const);
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   auto Const = buildInstr(TargetOpcode::G_CONSTANT);
3010b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), Const);
3020b57cec5SDimitry Andric   Const.addCImm(&Val);
3030b57cec5SDimitry Andric   return Const;
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
3070b57cec5SDimitry Andric                                                     int64_t Val) {
3080b57cec5SDimitry Andric   auto IntN = IntegerType::get(getMF().getFunction().getContext(),
3090b57cec5SDimitry Andric                                Res.getLLTTy(*getMRI()).getScalarSizeInBits());
3100b57cec5SDimitry Andric   ConstantInt *CI = ConstantInt::get(IntN, Val, true);
3110b57cec5SDimitry Andric   return buildConstant(Res, *CI);
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
3150b57cec5SDimitry Andric                                                      const ConstantFP &Val) {
3160b57cec5SDimitry Andric   LLT Ty = Res.getLLTTy(*getMRI());
3170b57cec5SDimitry Andric   LLT EltTy = Ty.getScalarType();
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   assert(APFloat::getSizeInBits(Val.getValueAPF().getSemantics())
3200b57cec5SDimitry Andric          == EltTy.getSizeInBits() &&
3210b57cec5SDimitry Andric          "creating fconstant with the wrong size");
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   assert(!Ty.isPointer() && "invalid operand type");
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   if (Ty.isVector()) {
3260b57cec5SDimitry Andric     auto Const = buildInstr(TargetOpcode::G_FCONSTANT)
3270b57cec5SDimitry Andric     .addDef(getMRI()->createGenericVirtualRegister(EltTy))
3280b57cec5SDimitry Andric     .addFPImm(&Val);
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric     return buildSplatVector(Res, Const);
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   auto Const = buildInstr(TargetOpcode::G_FCONSTANT);
3340b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), Const);
3350b57cec5SDimitry Andric   Const.addFPImm(&Val);
3360b57cec5SDimitry Andric   return Const;
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
3400b57cec5SDimitry Andric                                                     const APInt &Val) {
3410b57cec5SDimitry Andric   ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(), Val);
3420b57cec5SDimitry Andric   return buildConstant(Res, *CI);
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
3460b57cec5SDimitry Andric                                                      double Val) {
3470b57cec5SDimitry Andric   LLT DstTy = Res.getLLTTy(*getMRI());
3480b57cec5SDimitry Andric   auto &Ctx = getMF().getFunction().getContext();
3490b57cec5SDimitry Andric   auto *CFP =
3500b57cec5SDimitry Andric       ConstantFP::get(Ctx, getAPFloatFromSize(Val, DstTy.getScalarSizeInBits()));
3510b57cec5SDimitry Andric   return buildFConstant(Res, *CFP);
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
3550b57cec5SDimitry Andric                                                      const APFloat &Val) {
3560b57cec5SDimitry Andric   auto &Ctx = getMF().getFunction().getContext();
3570b57cec5SDimitry Andric   auto *CFP = ConstantFP::get(Ctx, Val);
3580b57cec5SDimitry Andric   return buildFConstant(Res, *CFP);
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBrCond(Register Tst,
3620b57cec5SDimitry Andric                                                   MachineBasicBlock &Dest) {
3630b57cec5SDimitry Andric   assert(getMRI()->getType(Tst).isScalar() && "invalid operand type");
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BRCOND).addUse(Tst).addMBB(&Dest);
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildLoad(const DstOp &Res,
3690b57cec5SDimitry Andric                                                 const SrcOp &Addr,
3700b57cec5SDimitry Andric                                                 MachineMemOperand &MMO) {
3710b57cec5SDimitry Andric   return buildLoadInstr(TargetOpcode::G_LOAD, Res, Addr, MMO);
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildLoadInstr(unsigned Opcode,
3750b57cec5SDimitry Andric                                                      const DstOp &Res,
3760b57cec5SDimitry Andric                                                      const SrcOp &Addr,
3770b57cec5SDimitry Andric                                                      MachineMemOperand &MMO) {
3780b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isValid() && "invalid operand type");
3790b57cec5SDimitry Andric   assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   auto MIB = buildInstr(Opcode);
3820b57cec5SDimitry Andric   Res.addDefToMIB(*getMRI(), MIB);
3830b57cec5SDimitry Andric   Addr.addSrcToMIB(MIB);
3840b57cec5SDimitry Andric   MIB.addMemOperand(&MMO);
3850b57cec5SDimitry Andric   return MIB;
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildStore(const SrcOp &Val,
3890b57cec5SDimitry Andric                                                  const SrcOp &Addr,
3900b57cec5SDimitry Andric                                                  MachineMemOperand &MMO) {
3910b57cec5SDimitry Andric   assert(Val.getLLTTy(*getMRI()).isValid() && "invalid operand type");
3920b57cec5SDimitry Andric   assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   auto MIB = buildInstr(TargetOpcode::G_STORE);
3950b57cec5SDimitry Andric   Val.addSrcToMIB(MIB);
3960b57cec5SDimitry Andric   Addr.addSrcToMIB(MIB);
3970b57cec5SDimitry Andric   MIB.addMemOperand(&MMO);
3980b57cec5SDimitry Andric   return MIB;
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUAddo(const DstOp &Res,
4020b57cec5SDimitry Andric                                                  const DstOp &CarryOut,
4030b57cec5SDimitry Andric                                                  const SrcOp &Op0,
4040b57cec5SDimitry Andric                                                  const SrcOp &Op1) {
4050b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_UADDO, {Res, CarryOut}, {Op0, Op1});
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUAdde(const DstOp &Res,
4090b57cec5SDimitry Andric                                                  const DstOp &CarryOut,
4100b57cec5SDimitry Andric                                                  const SrcOp &Op0,
4110b57cec5SDimitry Andric                                                  const SrcOp &Op1,
4120b57cec5SDimitry Andric                                                  const SrcOp &CarryIn) {
4130b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_UADDE, {Res, CarryOut},
4140b57cec5SDimitry Andric                     {Op0, Op1, CarryIn});
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAnyExt(const DstOp &Res,
4180b57cec5SDimitry Andric                                                   const SrcOp &Op) {
4190b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_ANYEXT, Res, Op);
4200b57cec5SDimitry Andric }
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSExt(const DstOp &Res,
4230b57cec5SDimitry Andric                                                 const SrcOp &Op) {
4240b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_SEXT, Res, Op);
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildZExt(const DstOp &Res,
4280b57cec5SDimitry Andric                                                 const SrcOp &Op) {
4290b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_ZEXT, Res, Op);
4300b57cec5SDimitry Andric }
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric unsigned MachineIRBuilder::getBoolExtOp(bool IsVec, bool IsFP) const {
4330b57cec5SDimitry Andric   const auto *TLI = getMF().getSubtarget().getTargetLowering();
4340b57cec5SDimitry Andric   switch (TLI->getBooleanContents(IsVec, IsFP)) {
4350b57cec5SDimitry Andric   case TargetLoweringBase::ZeroOrNegativeOneBooleanContent:
4360b57cec5SDimitry Andric     return TargetOpcode::G_SEXT;
4370b57cec5SDimitry Andric   case TargetLoweringBase::ZeroOrOneBooleanContent:
4380b57cec5SDimitry Andric     return TargetOpcode::G_ZEXT;
4390b57cec5SDimitry Andric   default:
4400b57cec5SDimitry Andric     return TargetOpcode::G_ANYEXT;
4410b57cec5SDimitry Andric   }
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBoolExt(const DstOp &Res,
4450b57cec5SDimitry Andric                                                    const SrcOp &Op,
4460b57cec5SDimitry Andric                                                    bool IsFP) {
4470b57cec5SDimitry Andric   unsigned ExtOp = getBoolExtOp(getMRI()->getType(Op.getReg()).isVector(), IsFP);
4480b57cec5SDimitry Andric   return buildInstr(ExtOp, Res, Op);
4490b57cec5SDimitry Andric }
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildExtOrTrunc(unsigned ExtOpc,
4520b57cec5SDimitry Andric                                                       const DstOp &Res,
4530b57cec5SDimitry Andric                                                       const SrcOp &Op) {
4540b57cec5SDimitry Andric   assert((TargetOpcode::G_ANYEXT == ExtOpc || TargetOpcode::G_ZEXT == ExtOpc ||
4550b57cec5SDimitry Andric           TargetOpcode::G_SEXT == ExtOpc) &&
4560b57cec5SDimitry Andric          "Expecting Extending Opc");
4570b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isScalar() ||
4580b57cec5SDimitry Andric          Res.getLLTTy(*getMRI()).isVector());
4590b57cec5SDimitry Andric   assert(Res.getLLTTy(*getMRI()).isScalar() ==
4600b57cec5SDimitry Andric          Op.getLLTTy(*getMRI()).isScalar());
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric   unsigned Opcode = TargetOpcode::COPY;
4630b57cec5SDimitry Andric   if (Res.getLLTTy(*getMRI()).getSizeInBits() >
4640b57cec5SDimitry Andric       Op.getLLTTy(*getMRI()).getSizeInBits())
4650b57cec5SDimitry Andric     Opcode = ExtOpc;
4660b57cec5SDimitry Andric   else if (Res.getLLTTy(*getMRI()).getSizeInBits() <
4670b57cec5SDimitry Andric            Op.getLLTTy(*getMRI()).getSizeInBits())
4680b57cec5SDimitry Andric     Opcode = TargetOpcode::G_TRUNC;
4690b57cec5SDimitry Andric   else
4700b57cec5SDimitry Andric     assert(Res.getLLTTy(*getMRI()) == Op.getLLTTy(*getMRI()));
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   return buildInstr(Opcode, Res, Op);
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSExtOrTrunc(const DstOp &Res,
4760b57cec5SDimitry Andric                                                        const SrcOp &Op) {
4770b57cec5SDimitry Andric   return buildExtOrTrunc(TargetOpcode::G_SEXT, Res, Op);
4780b57cec5SDimitry Andric }
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildZExtOrTrunc(const DstOp &Res,
4810b57cec5SDimitry Andric                                                        const SrcOp &Op) {
4820b57cec5SDimitry Andric   return buildExtOrTrunc(TargetOpcode::G_ZEXT, Res, Op);
4830b57cec5SDimitry Andric }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAnyExtOrTrunc(const DstOp &Res,
4860b57cec5SDimitry Andric                                                          const SrcOp &Op) {
4870b57cec5SDimitry Andric   return buildExtOrTrunc(TargetOpcode::G_ANYEXT, Res, Op);
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildCast(const DstOp &Dst,
4910b57cec5SDimitry Andric                                                 const SrcOp &Src) {
4920b57cec5SDimitry Andric   LLT SrcTy = Src.getLLTTy(*getMRI());
4930b57cec5SDimitry Andric   LLT DstTy = Dst.getLLTTy(*getMRI());
4940b57cec5SDimitry Andric   if (SrcTy == DstTy)
4950b57cec5SDimitry Andric     return buildCopy(Dst, Src);
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   unsigned Opcode;
4980b57cec5SDimitry Andric   if (SrcTy.isPointer() && DstTy.isScalar())
4990b57cec5SDimitry Andric     Opcode = TargetOpcode::G_PTRTOINT;
5000b57cec5SDimitry Andric   else if (DstTy.isPointer() && SrcTy.isScalar())
5010b57cec5SDimitry Andric     Opcode = TargetOpcode::G_INTTOPTR;
5020b57cec5SDimitry Andric   else {
5030b57cec5SDimitry Andric     assert(!SrcTy.isPointer() && !DstTy.isPointer() && "n G_ADDRCAST yet");
5040b57cec5SDimitry Andric     Opcode = TargetOpcode::G_BITCAST;
5050b57cec5SDimitry Andric   }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   return buildInstr(Opcode, Dst, Src);
5080b57cec5SDimitry Andric }
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildExtract(const DstOp &Dst,
5110b57cec5SDimitry Andric                                                    const SrcOp &Src,
5120b57cec5SDimitry Andric                                                    uint64_t Index) {
5130b57cec5SDimitry Andric   LLT SrcTy = Src.getLLTTy(*getMRI());
5140b57cec5SDimitry Andric   LLT DstTy = Dst.getLLTTy(*getMRI());
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric #ifndef NDEBUG
5170b57cec5SDimitry Andric   assert(SrcTy.isValid() && "invalid operand type");
5180b57cec5SDimitry Andric   assert(DstTy.isValid() && "invalid operand type");
5190b57cec5SDimitry Andric   assert(Index + DstTy.getSizeInBits() <= SrcTy.getSizeInBits() &&
5200b57cec5SDimitry Andric          "extracting off end of register");
5210b57cec5SDimitry Andric #endif
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   if (DstTy.getSizeInBits() == SrcTy.getSizeInBits()) {
5240b57cec5SDimitry Andric     assert(Index == 0 && "insertion past the end of a register");
5250b57cec5SDimitry Andric     return buildCast(Dst, Src);
5260b57cec5SDimitry Andric   }
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   auto Extract = buildInstr(TargetOpcode::G_EXTRACT);
5290b57cec5SDimitry Andric   Dst.addDefToMIB(*getMRI(), Extract);
5300b57cec5SDimitry Andric   Src.addSrcToMIB(Extract);
5310b57cec5SDimitry Andric   Extract.addImm(Index);
5320b57cec5SDimitry Andric   return Extract;
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric void MachineIRBuilder::buildSequence(Register Res, ArrayRef<Register> Ops,
5360b57cec5SDimitry Andric                                      ArrayRef<uint64_t> Indices) {
5370b57cec5SDimitry Andric #ifndef NDEBUG
5380b57cec5SDimitry Andric   assert(Ops.size() == Indices.size() && "incompatible args");
5390b57cec5SDimitry Andric   assert(!Ops.empty() && "invalid trivial sequence");
5400b57cec5SDimitry Andric   assert(std::is_sorted(Indices.begin(), Indices.end()) &&
5410b57cec5SDimitry Andric          "sequence offsets must be in ascending order");
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   assert(getMRI()->getType(Res).isValid() && "invalid operand type");
5440b57cec5SDimitry Andric   for (auto Op : Ops)
5450b57cec5SDimitry Andric     assert(getMRI()->getType(Op).isValid() && "invalid operand type");
5460b57cec5SDimitry Andric #endif
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric   LLT ResTy = getMRI()->getType(Res);
5490b57cec5SDimitry Andric   LLT OpTy = getMRI()->getType(Ops[0]);
5500b57cec5SDimitry Andric   unsigned OpSize = OpTy.getSizeInBits();
5510b57cec5SDimitry Andric   bool MaybeMerge = true;
5520b57cec5SDimitry Andric   for (unsigned i = 0; i < Ops.size(); ++i) {
5530b57cec5SDimitry Andric     if (getMRI()->getType(Ops[i]) != OpTy || Indices[i] != i * OpSize) {
5540b57cec5SDimitry Andric       MaybeMerge = false;
5550b57cec5SDimitry Andric       break;
5560b57cec5SDimitry Andric     }
5570b57cec5SDimitry Andric   }
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric   if (MaybeMerge && Ops.size() * OpSize == ResTy.getSizeInBits()) {
5600b57cec5SDimitry Andric     buildMerge(Res, Ops);
5610b57cec5SDimitry Andric     return;
5620b57cec5SDimitry Andric   }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric   Register ResIn = getMRI()->createGenericVirtualRegister(ResTy);
5650b57cec5SDimitry Andric   buildUndef(ResIn);
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric   for (unsigned i = 0; i < Ops.size(); ++i) {
5680b57cec5SDimitry Andric     Register ResOut = i + 1 == Ops.size()
5690b57cec5SDimitry Andric                           ? Res
5700b57cec5SDimitry Andric                           : getMRI()->createGenericVirtualRegister(ResTy);
5710b57cec5SDimitry Andric     buildInsert(ResOut, ResIn, Ops[i], Indices[i]);
5720b57cec5SDimitry Andric     ResIn = ResOut;
5730b57cec5SDimitry Andric   }
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUndef(const DstOp &Res) {
5770b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_IMPLICIT_DEF, {Res}, {});
5780b57cec5SDimitry Andric }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildMerge(const DstOp &Res,
5810b57cec5SDimitry Andric                                                  ArrayRef<Register> Ops) {
5820b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
5830b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
5840b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
5850b57cec5SDimitry Andric   SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
5860b57cec5SDimitry Andric   assert(TmpVec.size() > 1);
5870b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_MERGE_VALUES, Res, TmpVec);
5880b57cec5SDimitry Andric }
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUnmerge(ArrayRef<LLT> Res,
5910b57cec5SDimitry Andric                                                    const SrcOp &Op) {
5920b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<DstOp>,
5930b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
5940b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
5950b57cec5SDimitry Andric   SmallVector<DstOp, 8> TmpVec(Res.begin(), Res.end());
5960b57cec5SDimitry Andric   assert(TmpVec.size() > 1);
5970b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUnmerge(LLT Res,
6010b57cec5SDimitry Andric                                                    const SrcOp &Op) {
6020b57cec5SDimitry Andric   unsigned NumReg = Op.getLLTTy(*getMRI()).getSizeInBits() / Res.getSizeInBits();
6030b57cec5SDimitry Andric   SmallVector<Register, 8> TmpVec;
6040b57cec5SDimitry Andric   for (unsigned I = 0; I != NumReg; ++I)
6050b57cec5SDimitry Andric     TmpVec.push_back(getMRI()->createGenericVirtualRegister(Res));
6060b57cec5SDimitry Andric   return buildUnmerge(TmpVec, Op);
6070b57cec5SDimitry Andric }
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildUnmerge(ArrayRef<Register> Res,
6100b57cec5SDimitry Andric                                                    const SrcOp &Op) {
6110b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<Register> to ArrayRef<DstOp>,
6120b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
6130b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
6140b57cec5SDimitry Andric   SmallVector<DstOp, 8> TmpVec(Res.begin(), Res.end());
6150b57cec5SDimitry Andric   assert(TmpVec.size() > 1);
6160b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
6170b57cec5SDimitry Andric }
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildBuildVector(const DstOp &Res,
6200b57cec5SDimitry Andric                                                        ArrayRef<Register> Ops) {
6210b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
6220b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
6230b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
6240b57cec5SDimitry Andric   SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
6250b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSplatVector(const DstOp &Res,
6290b57cec5SDimitry Andric                                                        const SrcOp &Src) {
6300b57cec5SDimitry Andric   SmallVector<SrcOp, 8> TmpVec(Res.getLLTTy(*getMRI()).getNumElements(), Src);
6310b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
6320b57cec5SDimitry Andric }
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric MachineInstrBuilder
6350b57cec5SDimitry Andric MachineIRBuilder::buildBuildVectorTrunc(const DstOp &Res,
6360b57cec5SDimitry Andric                                         ArrayRef<Register> Ops) {
6370b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
6380b57cec5SDimitry Andric   // we need some temporary storage for the DstOp objects. Here we use a
6390b57cec5SDimitry Andric   // sufficiently large SmallVector to not go through the heap.
6400b57cec5SDimitry Andric   SmallVector<SrcOp, 8> TmpVec(Ops.begin(), Ops.end());
6410b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BUILD_VECTOR_TRUNC, Res, TmpVec);
6420b57cec5SDimitry Andric }
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric MachineInstrBuilder
6450b57cec5SDimitry Andric MachineIRBuilder::buildConcatVectors(const DstOp &Res, ArrayRef<Register> Ops) {
6460b57cec5SDimitry Andric   // Unfortunately to convert from ArrayRef<Register> 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   return buildInstr(TargetOpcode::G_CONCAT_VECTORS, Res, TmpVec);
6510b57cec5SDimitry Andric }
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildInsert(Register Res, Register Src,
6540b57cec5SDimitry Andric                                                   Register Op, unsigned Index) {
6550b57cec5SDimitry Andric   assert(Index + getMRI()->getType(Op).getSizeInBits() <=
6560b57cec5SDimitry Andric              getMRI()->getType(Res).getSizeInBits() &&
6570b57cec5SDimitry Andric          "insertion past the end of a register");
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric   if (getMRI()->getType(Res).getSizeInBits() ==
6600b57cec5SDimitry Andric       getMRI()->getType(Op).getSizeInBits()) {
6610b57cec5SDimitry Andric     return buildCast(Res, Op);
6620b57cec5SDimitry Andric   }
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_INSERT)
6650b57cec5SDimitry Andric       .addDef(Res)
6660b57cec5SDimitry Andric       .addUse(Src)
6670b57cec5SDimitry Andric       .addUse(Op)
6680b57cec5SDimitry Andric       .addImm(Index);
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID,
6720b57cec5SDimitry Andric                                                      ArrayRef<Register> ResultRegs,
6730b57cec5SDimitry Andric                                                      bool HasSideEffects) {
6740b57cec5SDimitry Andric   auto MIB =
6750b57cec5SDimitry Andric       buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS
6760b57cec5SDimitry Andric                                 : TargetOpcode::G_INTRINSIC);
6770b57cec5SDimitry Andric   for (unsigned ResultReg : ResultRegs)
6780b57cec5SDimitry Andric     MIB.addDef(ResultReg);
6790b57cec5SDimitry Andric   MIB.addIntrinsicID(ID);
6800b57cec5SDimitry Andric   return MIB;
6810b57cec5SDimitry Andric }
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID,
6840b57cec5SDimitry Andric                                                      ArrayRef<DstOp> Results,
6850b57cec5SDimitry Andric                                                      bool HasSideEffects) {
6860b57cec5SDimitry Andric   auto MIB =
6870b57cec5SDimitry Andric       buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS
6880b57cec5SDimitry Andric                                 : TargetOpcode::G_INTRINSIC);
6890b57cec5SDimitry Andric   for (DstOp Result : Results)
6900b57cec5SDimitry Andric     Result.addDefToMIB(*getMRI(), MIB);
6910b57cec5SDimitry Andric   MIB.addIntrinsicID(ID);
6920b57cec5SDimitry Andric   return MIB;
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildTrunc(const DstOp &Res,
6960b57cec5SDimitry Andric                                                  const SrcOp &Op) {
6970b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_TRUNC, Res, Op);
6980b57cec5SDimitry Andric }
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFPTrunc(const DstOp &Res,
7010b57cec5SDimitry Andric                                                    const SrcOp &Op) {
7020b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_FPTRUNC, Res, Op);
7030b57cec5SDimitry Andric }
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildICmp(CmpInst::Predicate Pred,
7060b57cec5SDimitry Andric                                                 const DstOp &Res,
7070b57cec5SDimitry Andric                                                 const SrcOp &Op0,
7080b57cec5SDimitry Andric                                                 const SrcOp &Op1) {
7090b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_ICMP, Res, {Pred, Op0, Op1});
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildFCmp(CmpInst::Predicate Pred,
7130b57cec5SDimitry Andric                                                 const DstOp &Res,
7140b57cec5SDimitry Andric                                                 const SrcOp &Op0,
715*8bcb0991SDimitry Andric                                                 const SrcOp &Op1,
716*8bcb0991SDimitry Andric                                                 Optional<unsigned> Flags) {
7170b57cec5SDimitry Andric 
718*8bcb0991SDimitry Andric   return buildInstr(TargetOpcode::G_FCMP, Res, {Pred, Op0, Op1}, Flags);
7190b57cec5SDimitry Andric }
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildSelect(const DstOp &Res,
7220b57cec5SDimitry Andric                                                   const SrcOp &Tst,
7230b57cec5SDimitry Andric                                                   const SrcOp &Op0,
724*8bcb0991SDimitry Andric                                                   const SrcOp &Op1,
725*8bcb0991SDimitry Andric                                                   Optional<unsigned> Flags) {
7260b57cec5SDimitry Andric 
727*8bcb0991SDimitry Andric   return buildInstr(TargetOpcode::G_SELECT, {Res}, {Tst, Op0, Op1}, Flags);
7280b57cec5SDimitry Andric }
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric MachineInstrBuilder
7310b57cec5SDimitry Andric MachineIRBuilder::buildInsertVectorElement(const DstOp &Res, const SrcOp &Val,
7320b57cec5SDimitry Andric                                            const SrcOp &Elt, const SrcOp &Idx) {
7330b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_INSERT_VECTOR_ELT, Res, {Val, Elt, Idx});
7340b57cec5SDimitry Andric }
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric MachineInstrBuilder
7370b57cec5SDimitry Andric MachineIRBuilder::buildExtractVectorElement(const DstOp &Res, const SrcOp &Val,
7380b57cec5SDimitry Andric                                             const SrcOp &Idx) {
7390b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_EXTRACT_VECTOR_ELT, Res, {Val, Idx});
7400b57cec5SDimitry Andric }
7410b57cec5SDimitry Andric 
7420b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAtomicCmpXchgWithSuccess(
7430b57cec5SDimitry Andric     Register OldValRes, Register SuccessRes, Register Addr, Register CmpVal,
7440b57cec5SDimitry Andric     Register NewVal, MachineMemOperand &MMO) {
7450b57cec5SDimitry Andric #ifndef NDEBUG
7460b57cec5SDimitry Andric   LLT OldValResTy = getMRI()->getType(OldValRes);
7470b57cec5SDimitry Andric   LLT SuccessResTy = getMRI()->getType(SuccessRes);
7480b57cec5SDimitry Andric   LLT AddrTy = getMRI()->getType(Addr);
7490b57cec5SDimitry Andric   LLT CmpValTy = getMRI()->getType(CmpVal);
7500b57cec5SDimitry Andric   LLT NewValTy = getMRI()->getType(NewVal);
7510b57cec5SDimitry Andric   assert(OldValResTy.isScalar() && "invalid operand type");
7520b57cec5SDimitry Andric   assert(SuccessResTy.isScalar() && "invalid operand type");
7530b57cec5SDimitry Andric   assert(AddrTy.isPointer() && "invalid operand type");
7540b57cec5SDimitry Andric   assert(CmpValTy.isValid() && "invalid operand type");
7550b57cec5SDimitry Andric   assert(NewValTy.isValid() && "invalid operand type");
7560b57cec5SDimitry Andric   assert(OldValResTy == CmpValTy && "type mismatch");
7570b57cec5SDimitry Andric   assert(OldValResTy == NewValTy && "type mismatch");
7580b57cec5SDimitry Andric #endif
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS)
7610b57cec5SDimitry Andric       .addDef(OldValRes)
7620b57cec5SDimitry Andric       .addDef(SuccessRes)
7630b57cec5SDimitry Andric       .addUse(Addr)
7640b57cec5SDimitry Andric       .addUse(CmpVal)
7650b57cec5SDimitry Andric       .addUse(NewVal)
7660b57cec5SDimitry Andric       .addMemOperand(&MMO);
7670b57cec5SDimitry Andric }
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric MachineInstrBuilder
7700b57cec5SDimitry Andric MachineIRBuilder::buildAtomicCmpXchg(Register OldValRes, Register Addr,
7710b57cec5SDimitry Andric                                      Register CmpVal, Register NewVal,
7720b57cec5SDimitry Andric                                      MachineMemOperand &MMO) {
7730b57cec5SDimitry Andric #ifndef NDEBUG
7740b57cec5SDimitry Andric   LLT OldValResTy = getMRI()->getType(OldValRes);
7750b57cec5SDimitry Andric   LLT AddrTy = getMRI()->getType(Addr);
7760b57cec5SDimitry Andric   LLT CmpValTy = getMRI()->getType(CmpVal);
7770b57cec5SDimitry Andric   LLT NewValTy = getMRI()->getType(NewVal);
7780b57cec5SDimitry Andric   assert(OldValResTy.isScalar() && "invalid operand type");
7790b57cec5SDimitry Andric   assert(AddrTy.isPointer() && "invalid operand type");
7800b57cec5SDimitry Andric   assert(CmpValTy.isValid() && "invalid operand type");
7810b57cec5SDimitry Andric   assert(NewValTy.isValid() && "invalid operand type");
7820b57cec5SDimitry Andric   assert(OldValResTy == CmpValTy && "type mismatch");
7830b57cec5SDimitry Andric   assert(OldValResTy == NewValTy && "type mismatch");
7840b57cec5SDimitry Andric #endif
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG)
7870b57cec5SDimitry Andric       .addDef(OldValRes)
7880b57cec5SDimitry Andric       .addUse(Addr)
7890b57cec5SDimitry Andric       .addUse(CmpVal)
7900b57cec5SDimitry Andric       .addUse(NewVal)
7910b57cec5SDimitry Andric       .addMemOperand(&MMO);
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric 
794*8bcb0991SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAtomicRMW(
795*8bcb0991SDimitry Andric   unsigned Opcode, const DstOp &OldValRes,
796*8bcb0991SDimitry Andric   const SrcOp &Addr, const SrcOp &Val,
7970b57cec5SDimitry Andric   MachineMemOperand &MMO) {
798*8bcb0991SDimitry Andric 
7990b57cec5SDimitry Andric #ifndef NDEBUG
800*8bcb0991SDimitry Andric   LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
801*8bcb0991SDimitry Andric   LLT AddrTy = Addr.getLLTTy(*getMRI());
802*8bcb0991SDimitry Andric   LLT ValTy = Val.getLLTTy(*getMRI());
8030b57cec5SDimitry Andric   assert(OldValResTy.isScalar() && "invalid operand type");
8040b57cec5SDimitry Andric   assert(AddrTy.isPointer() && "invalid operand type");
8050b57cec5SDimitry Andric   assert(ValTy.isValid() && "invalid operand type");
8060b57cec5SDimitry Andric   assert(OldValResTy == ValTy && "type mismatch");
807*8bcb0991SDimitry Andric   assert(MMO.isAtomic() && "not atomic mem operand");
8080b57cec5SDimitry Andric #endif
8090b57cec5SDimitry Andric 
810*8bcb0991SDimitry Andric   auto MIB = buildInstr(Opcode);
811*8bcb0991SDimitry Andric   OldValRes.addDefToMIB(*getMRI(), MIB);
812*8bcb0991SDimitry Andric   Addr.addSrcToMIB(MIB);
813*8bcb0991SDimitry Andric   Val.addSrcToMIB(MIB);
814*8bcb0991SDimitry Andric   MIB.addMemOperand(&MMO);
815*8bcb0991SDimitry Andric   return MIB;
8160b57cec5SDimitry Andric }
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric MachineInstrBuilder
8190b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWXchg(Register OldValRes, Register Addr,
8200b57cec5SDimitry Andric                                      Register Val, MachineMemOperand &MMO) {
8210b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XCHG, OldValRes, Addr, Val,
8220b57cec5SDimitry Andric                         MMO);
8230b57cec5SDimitry Andric }
8240b57cec5SDimitry Andric MachineInstrBuilder
8250b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWAdd(Register OldValRes, Register Addr,
8260b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
8270b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_ADD, OldValRes, Addr, Val,
8280b57cec5SDimitry Andric                         MMO);
8290b57cec5SDimitry Andric }
8300b57cec5SDimitry Andric MachineInstrBuilder
8310b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWSub(Register OldValRes, Register Addr,
8320b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
8330b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_SUB, OldValRes, Addr, Val,
8340b57cec5SDimitry Andric                         MMO);
8350b57cec5SDimitry Andric }
8360b57cec5SDimitry Andric MachineInstrBuilder
8370b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWAnd(Register OldValRes, Register Addr,
8380b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
8390b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_AND, OldValRes, Addr, Val,
8400b57cec5SDimitry Andric                         MMO);
8410b57cec5SDimitry Andric }
8420b57cec5SDimitry Andric MachineInstrBuilder
8430b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWNand(Register OldValRes, Register Addr,
8440b57cec5SDimitry Andric                                      Register Val, MachineMemOperand &MMO) {
8450b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_NAND, OldValRes, Addr, Val,
8460b57cec5SDimitry Andric                         MMO);
8470b57cec5SDimitry Andric }
8480b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildAtomicRMWOr(Register OldValRes,
8490b57cec5SDimitry Andric                                                        Register Addr,
8500b57cec5SDimitry Andric                                                        Register Val,
8510b57cec5SDimitry Andric                                                        MachineMemOperand &MMO) {
8520b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_OR, OldValRes, Addr, Val,
8530b57cec5SDimitry Andric                         MMO);
8540b57cec5SDimitry Andric }
8550b57cec5SDimitry Andric MachineInstrBuilder
8560b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWXor(Register OldValRes, Register Addr,
8570b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
8580b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XOR, OldValRes, Addr, Val,
8590b57cec5SDimitry Andric                         MMO);
8600b57cec5SDimitry Andric }
8610b57cec5SDimitry Andric MachineInstrBuilder
8620b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWMax(Register OldValRes, Register Addr,
8630b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
8640b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MAX, OldValRes, Addr, Val,
8650b57cec5SDimitry Andric                         MMO);
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric MachineInstrBuilder
8680b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWMin(Register OldValRes, Register Addr,
8690b57cec5SDimitry Andric                                     Register Val, MachineMemOperand &MMO) {
8700b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MIN, OldValRes, Addr, Val,
8710b57cec5SDimitry Andric                         MMO);
8720b57cec5SDimitry Andric }
8730b57cec5SDimitry Andric MachineInstrBuilder
8740b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWUmax(Register OldValRes, Register Addr,
8750b57cec5SDimitry Andric                                      Register Val, MachineMemOperand &MMO) {
8760b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMAX, OldValRes, Addr, Val,
8770b57cec5SDimitry Andric                         MMO);
8780b57cec5SDimitry Andric }
8790b57cec5SDimitry Andric MachineInstrBuilder
8800b57cec5SDimitry Andric MachineIRBuilder::buildAtomicRMWUmin(Register OldValRes, Register Addr,
8810b57cec5SDimitry Andric                                      Register Val, MachineMemOperand &MMO) {
8820b57cec5SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMIN, OldValRes, Addr, Val,
8830b57cec5SDimitry Andric                         MMO);
8840b57cec5SDimitry Andric }
8850b57cec5SDimitry Andric 
8860b57cec5SDimitry Andric MachineInstrBuilder
887*8bcb0991SDimitry Andric MachineIRBuilder::buildAtomicRMWFAdd(
888*8bcb0991SDimitry Andric   const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
889*8bcb0991SDimitry Andric   MachineMemOperand &MMO) {
890*8bcb0991SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FADD, OldValRes, Addr, Val,
891*8bcb0991SDimitry Andric                         MMO);
892*8bcb0991SDimitry Andric }
893*8bcb0991SDimitry Andric 
894*8bcb0991SDimitry Andric MachineInstrBuilder
895*8bcb0991SDimitry Andric MachineIRBuilder::buildAtomicRMWFSub(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
896*8bcb0991SDimitry Andric                                      MachineMemOperand &MMO) {
897*8bcb0991SDimitry Andric   return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FSUB, OldValRes, Addr, Val,
898*8bcb0991SDimitry Andric                         MMO);
899*8bcb0991SDimitry Andric }
900*8bcb0991SDimitry Andric 
901*8bcb0991SDimitry Andric MachineInstrBuilder
9020b57cec5SDimitry Andric MachineIRBuilder::buildFence(unsigned Ordering, unsigned Scope) {
9030b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_FENCE)
9040b57cec5SDimitry Andric     .addImm(Ordering)
9050b57cec5SDimitry Andric     .addImm(Scope);
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric MachineInstrBuilder
9090b57cec5SDimitry Andric MachineIRBuilder::buildBlockAddress(Register Res, const BlockAddress *BA) {
9100b57cec5SDimitry Andric #ifndef NDEBUG
9110b57cec5SDimitry Andric   assert(getMRI()->getType(Res).isPointer() && "invalid res type");
9120b57cec5SDimitry Andric #endif
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric   return buildInstr(TargetOpcode::G_BLOCK_ADDR).addDef(Res).addBlockAddress(BA);
9150b57cec5SDimitry Andric }
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric void MachineIRBuilder::validateTruncExt(const LLT &DstTy, const LLT &SrcTy,
9180b57cec5SDimitry Andric                                         bool IsExtend) {
9190b57cec5SDimitry Andric #ifndef NDEBUG
9200b57cec5SDimitry Andric   if (DstTy.isVector()) {
9210b57cec5SDimitry Andric     assert(SrcTy.isVector() && "mismatched cast between vector and non-vector");
9220b57cec5SDimitry Andric     assert(SrcTy.getNumElements() == DstTy.getNumElements() &&
9230b57cec5SDimitry Andric            "different number of elements in a trunc/ext");
9240b57cec5SDimitry Andric   } else
9250b57cec5SDimitry Andric     assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc");
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric   if (IsExtend)
9280b57cec5SDimitry Andric     assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&
9290b57cec5SDimitry Andric            "invalid narrowing extend");
9300b57cec5SDimitry Andric   else
9310b57cec5SDimitry Andric     assert(DstTy.getSizeInBits() < SrcTy.getSizeInBits() &&
9320b57cec5SDimitry Andric            "invalid widening trunc");
9330b57cec5SDimitry Andric #endif
9340b57cec5SDimitry Andric }
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric void MachineIRBuilder::validateSelectOp(const LLT &ResTy, const LLT &TstTy,
9370b57cec5SDimitry Andric                                         const LLT &Op0Ty, const LLT &Op1Ty) {
9380b57cec5SDimitry Andric #ifndef NDEBUG
9390b57cec5SDimitry Andric   assert((ResTy.isScalar() || ResTy.isVector() || ResTy.isPointer()) &&
9400b57cec5SDimitry Andric          "invalid operand type");
9410b57cec5SDimitry Andric   assert((ResTy == Op0Ty && ResTy == Op1Ty) && "type mismatch");
9420b57cec5SDimitry Andric   if (ResTy.isScalar() || ResTy.isPointer())
9430b57cec5SDimitry Andric     assert(TstTy.isScalar() && "type mismatch");
9440b57cec5SDimitry Andric   else
9450b57cec5SDimitry Andric     assert((TstTy.isScalar() ||
9460b57cec5SDimitry Andric             (TstTy.isVector() &&
9470b57cec5SDimitry Andric              TstTy.getNumElements() == Op0Ty.getNumElements())) &&
9480b57cec5SDimitry Andric            "type mismatch");
9490b57cec5SDimitry Andric #endif
9500b57cec5SDimitry Andric }
9510b57cec5SDimitry Andric 
9520b57cec5SDimitry Andric MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opc,
9530b57cec5SDimitry Andric                                                  ArrayRef<DstOp> DstOps,
9540b57cec5SDimitry Andric                                                  ArrayRef<SrcOp> SrcOps,
9550b57cec5SDimitry Andric                                                  Optional<unsigned> Flags) {
9560b57cec5SDimitry Andric   switch (Opc) {
9570b57cec5SDimitry Andric   default:
9580b57cec5SDimitry Andric     break;
9590b57cec5SDimitry Andric   case TargetOpcode::G_SELECT: {
9600b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid select");
9610b57cec5SDimitry Andric     assert(SrcOps.size() == 3 && "Invalid select");
9620b57cec5SDimitry Andric     validateSelectOp(
9630b57cec5SDimitry Andric         DstOps[0].getLLTTy(*getMRI()), SrcOps[0].getLLTTy(*getMRI()),
9640b57cec5SDimitry Andric         SrcOps[1].getLLTTy(*getMRI()), SrcOps[2].getLLTTy(*getMRI()));
9650b57cec5SDimitry Andric     break;
9660b57cec5SDimitry Andric   }
9670b57cec5SDimitry Andric   case TargetOpcode::G_ADD:
9680b57cec5SDimitry Andric   case TargetOpcode::G_AND:
9690b57cec5SDimitry Andric   case TargetOpcode::G_MUL:
9700b57cec5SDimitry Andric   case TargetOpcode::G_OR:
9710b57cec5SDimitry Andric   case TargetOpcode::G_SUB:
9720b57cec5SDimitry Andric   case TargetOpcode::G_XOR:
9730b57cec5SDimitry Andric   case TargetOpcode::G_UDIV:
9740b57cec5SDimitry Andric   case TargetOpcode::G_SDIV:
9750b57cec5SDimitry Andric   case TargetOpcode::G_UREM:
9760b57cec5SDimitry Andric   case TargetOpcode::G_SREM:
9770b57cec5SDimitry Andric   case TargetOpcode::G_SMIN:
9780b57cec5SDimitry Andric   case TargetOpcode::G_SMAX:
9790b57cec5SDimitry Andric   case TargetOpcode::G_UMIN:
9800b57cec5SDimitry Andric   case TargetOpcode::G_UMAX: {
9810b57cec5SDimitry Andric     // All these are binary ops.
9820b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
9830b57cec5SDimitry Andric     assert(SrcOps.size() == 2 && "Invalid Srcs");
9840b57cec5SDimitry Andric     validateBinaryOp(DstOps[0].getLLTTy(*getMRI()),
9850b57cec5SDimitry Andric                      SrcOps[0].getLLTTy(*getMRI()),
9860b57cec5SDimitry Andric                      SrcOps[1].getLLTTy(*getMRI()));
9870b57cec5SDimitry Andric     break;
9880b57cec5SDimitry Andric   }
9890b57cec5SDimitry Andric   case TargetOpcode::G_SHL:
9900b57cec5SDimitry Andric   case TargetOpcode::G_ASHR:
9910b57cec5SDimitry Andric   case TargetOpcode::G_LSHR: {
9920b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
9930b57cec5SDimitry Andric     assert(SrcOps.size() == 2 && "Invalid Srcs");
9940b57cec5SDimitry Andric     validateShiftOp(DstOps[0].getLLTTy(*getMRI()),
9950b57cec5SDimitry Andric                     SrcOps[0].getLLTTy(*getMRI()),
9960b57cec5SDimitry Andric                     SrcOps[1].getLLTTy(*getMRI()));
9970b57cec5SDimitry Andric     break;
9980b57cec5SDimitry Andric   }
9990b57cec5SDimitry Andric   case TargetOpcode::G_SEXT:
10000b57cec5SDimitry Andric   case TargetOpcode::G_ZEXT:
10010b57cec5SDimitry Andric   case TargetOpcode::G_ANYEXT:
10020b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
10030b57cec5SDimitry Andric     assert(SrcOps.size() == 1 && "Invalid Srcs");
10040b57cec5SDimitry Andric     validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
10050b57cec5SDimitry Andric                      SrcOps[0].getLLTTy(*getMRI()), true);
10060b57cec5SDimitry Andric     break;
10070b57cec5SDimitry Andric   case TargetOpcode::G_TRUNC:
10080b57cec5SDimitry Andric   case TargetOpcode::G_FPTRUNC: {
10090b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
10100b57cec5SDimitry Andric     assert(SrcOps.size() == 1 && "Invalid Srcs");
10110b57cec5SDimitry Andric     validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
10120b57cec5SDimitry Andric                      SrcOps[0].getLLTTy(*getMRI()), false);
10130b57cec5SDimitry Andric     break;
10140b57cec5SDimitry Andric   }
10150b57cec5SDimitry Andric   case TargetOpcode::COPY:
10160b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
10170b57cec5SDimitry Andric     // If the caller wants to add a subreg source it has to be done separately
10180b57cec5SDimitry Andric     // so we may not have any SrcOps at this point yet.
10190b57cec5SDimitry Andric     break;
10200b57cec5SDimitry Andric   case TargetOpcode::G_FCMP:
10210b57cec5SDimitry Andric   case TargetOpcode::G_ICMP: {
10220b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst Operands");
10230b57cec5SDimitry Andric     assert(SrcOps.size() == 3 && "Invalid Src Operands");
10240b57cec5SDimitry Andric     // For F/ICMP, the first src operand is the predicate, followed by
10250b57cec5SDimitry Andric     // the two comparands.
10260b57cec5SDimitry Andric     assert(SrcOps[0].getSrcOpKind() == SrcOp::SrcType::Ty_Predicate &&
10270b57cec5SDimitry Andric            "Expecting predicate");
10280b57cec5SDimitry Andric     assert([&]() -> bool {
10290b57cec5SDimitry Andric       CmpInst::Predicate Pred = SrcOps[0].getPredicate();
10300b57cec5SDimitry Andric       return Opc == TargetOpcode::G_ICMP ? CmpInst::isIntPredicate(Pred)
10310b57cec5SDimitry Andric                                          : CmpInst::isFPPredicate(Pred);
10320b57cec5SDimitry Andric     }() && "Invalid predicate");
10330b57cec5SDimitry Andric     assert(SrcOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
10340b57cec5SDimitry Andric            "Type mismatch");
10350b57cec5SDimitry Andric     assert([&]() -> bool {
10360b57cec5SDimitry Andric       LLT Op0Ty = SrcOps[1].getLLTTy(*getMRI());
10370b57cec5SDimitry Andric       LLT DstTy = DstOps[0].getLLTTy(*getMRI());
10380b57cec5SDimitry Andric       if (Op0Ty.isScalar() || Op0Ty.isPointer())
10390b57cec5SDimitry Andric         return DstTy.isScalar();
10400b57cec5SDimitry Andric       else
10410b57cec5SDimitry Andric         return DstTy.isVector() &&
10420b57cec5SDimitry Andric                DstTy.getNumElements() == Op0Ty.getNumElements();
10430b57cec5SDimitry Andric     }() && "Type Mismatch");
10440b57cec5SDimitry Andric     break;
10450b57cec5SDimitry Andric   }
10460b57cec5SDimitry Andric   case TargetOpcode::G_UNMERGE_VALUES: {
10470b57cec5SDimitry Andric     assert(!DstOps.empty() && "Invalid trivial sequence");
10480b57cec5SDimitry Andric     assert(SrcOps.size() == 1 && "Invalid src for Unmerge");
10490b57cec5SDimitry Andric     assert(std::all_of(DstOps.begin(), DstOps.end(),
10500b57cec5SDimitry Andric                        [&, this](const DstOp &Op) {
10510b57cec5SDimitry Andric                          return Op.getLLTTy(*getMRI()) ==
10520b57cec5SDimitry Andric                                 DstOps[0].getLLTTy(*getMRI());
10530b57cec5SDimitry Andric                        }) &&
10540b57cec5SDimitry Andric            "type mismatch in output list");
10550b57cec5SDimitry Andric     assert(DstOps.size() * DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
10560b57cec5SDimitry Andric                SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
10570b57cec5SDimitry Andric            "input operands do not cover output register");
10580b57cec5SDimitry Andric     break;
10590b57cec5SDimitry Andric   }
10600b57cec5SDimitry Andric   case TargetOpcode::G_MERGE_VALUES: {
10610b57cec5SDimitry Andric     assert(!SrcOps.empty() && "invalid trivial sequence");
10620b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst");
10630b57cec5SDimitry Andric     assert(std::all_of(SrcOps.begin(), SrcOps.end(),
10640b57cec5SDimitry Andric                        [&, this](const SrcOp &Op) {
10650b57cec5SDimitry Andric                          return Op.getLLTTy(*getMRI()) ==
10660b57cec5SDimitry Andric                                 SrcOps[0].getLLTTy(*getMRI());
10670b57cec5SDimitry Andric                        }) &&
10680b57cec5SDimitry Andric            "type mismatch in input list");
10690b57cec5SDimitry Andric     assert(SrcOps.size() * SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
10700b57cec5SDimitry Andric                DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
10710b57cec5SDimitry Andric            "input operands do not cover output register");
10720b57cec5SDimitry Andric     if (SrcOps.size() == 1)
10730b57cec5SDimitry Andric       return buildCast(DstOps[0], SrcOps[0]);
1074*8bcb0991SDimitry Andric     if (DstOps[0].getLLTTy(*getMRI()).isVector()) {
1075*8bcb0991SDimitry Andric       if (SrcOps[0].getLLTTy(*getMRI()).isVector())
10760b57cec5SDimitry Andric         return buildInstr(TargetOpcode::G_CONCAT_VECTORS, DstOps, SrcOps);
1077*8bcb0991SDimitry Andric       return buildInstr(TargetOpcode::G_BUILD_VECTOR, DstOps, SrcOps);
1078*8bcb0991SDimitry Andric     }
10790b57cec5SDimitry Andric     break;
10800b57cec5SDimitry Andric   }
10810b57cec5SDimitry Andric   case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
10820b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid Dst size");
10830b57cec5SDimitry Andric     assert(SrcOps.size() == 2 && "Invalid Src size");
10840b57cec5SDimitry Andric     assert(SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
10850b57cec5SDimitry Andric     assert((DstOps[0].getLLTTy(*getMRI()).isScalar() ||
10860b57cec5SDimitry Andric             DstOps[0].getLLTTy(*getMRI()).isPointer()) &&
10870b57cec5SDimitry Andric            "Invalid operand type");
10880b57cec5SDimitry Andric     assert(SrcOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand type");
10890b57cec5SDimitry Andric     assert(SrcOps[0].getLLTTy(*getMRI()).getElementType() ==
10900b57cec5SDimitry Andric                DstOps[0].getLLTTy(*getMRI()) &&
10910b57cec5SDimitry Andric            "Type mismatch");
10920b57cec5SDimitry Andric     break;
10930b57cec5SDimitry Andric   }
10940b57cec5SDimitry Andric   case TargetOpcode::G_INSERT_VECTOR_ELT: {
10950b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid dst size");
10960b57cec5SDimitry Andric     assert(SrcOps.size() == 3 && "Invalid src size");
10970b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
10980b57cec5SDimitry Andric            SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
10990b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).getElementType() ==
11000b57cec5SDimitry Andric                SrcOps[1].getLLTTy(*getMRI()) &&
11010b57cec5SDimitry Andric            "Type mismatch");
11020b57cec5SDimitry Andric     assert(SrcOps[2].getLLTTy(*getMRI()).isScalar() && "Invalid index");
11030b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).getNumElements() ==
11040b57cec5SDimitry Andric                SrcOps[0].getLLTTy(*getMRI()).getNumElements() &&
11050b57cec5SDimitry Andric            "Type mismatch");
11060b57cec5SDimitry Andric     break;
11070b57cec5SDimitry Andric   }
11080b57cec5SDimitry Andric   case TargetOpcode::G_BUILD_VECTOR: {
11090b57cec5SDimitry Andric     assert((!SrcOps.empty() || SrcOps.size() < 2) &&
11100b57cec5SDimitry Andric            "Must have at least 2 operands");
11110b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid DstOps");
11120b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
11130b57cec5SDimitry Andric            "Res type must be a vector");
11140b57cec5SDimitry Andric     assert(std::all_of(SrcOps.begin(), SrcOps.end(),
11150b57cec5SDimitry Andric                        [&, this](const SrcOp &Op) {
11160b57cec5SDimitry Andric                          return Op.getLLTTy(*getMRI()) ==
11170b57cec5SDimitry Andric                                 SrcOps[0].getLLTTy(*getMRI());
11180b57cec5SDimitry Andric                        }) &&
11190b57cec5SDimitry Andric            "type mismatch in input list");
11200b57cec5SDimitry Andric     assert(SrcOps.size() * SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
11210b57cec5SDimitry Andric                DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
11220b57cec5SDimitry Andric            "input scalars do not exactly cover the output vector register");
11230b57cec5SDimitry Andric     break;
11240b57cec5SDimitry Andric   }
11250b57cec5SDimitry Andric   case TargetOpcode::G_BUILD_VECTOR_TRUNC: {
11260b57cec5SDimitry Andric     assert((!SrcOps.empty() || SrcOps.size() < 2) &&
11270b57cec5SDimitry Andric            "Must have at least 2 operands");
11280b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid DstOps");
11290b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
11300b57cec5SDimitry Andric            "Res type must be a vector");
11310b57cec5SDimitry Andric     assert(std::all_of(SrcOps.begin(), SrcOps.end(),
11320b57cec5SDimitry Andric                        [&, this](const SrcOp &Op) {
11330b57cec5SDimitry Andric                          return Op.getLLTTy(*getMRI()) ==
11340b57cec5SDimitry Andric                                 SrcOps[0].getLLTTy(*getMRI());
11350b57cec5SDimitry Andric                        }) &&
11360b57cec5SDimitry Andric            "type mismatch in input list");
11370b57cec5SDimitry Andric     if (SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
11380b57cec5SDimitry Andric         DstOps[0].getLLTTy(*getMRI()).getElementType().getSizeInBits())
11390b57cec5SDimitry Andric       return buildInstr(TargetOpcode::G_BUILD_VECTOR, DstOps, SrcOps);
11400b57cec5SDimitry Andric     break;
11410b57cec5SDimitry Andric   }
11420b57cec5SDimitry Andric   case TargetOpcode::G_CONCAT_VECTORS: {
11430b57cec5SDimitry Andric     assert(DstOps.size() == 1 && "Invalid DstOps");
11440b57cec5SDimitry Andric     assert((!SrcOps.empty() || SrcOps.size() < 2) &&
11450b57cec5SDimitry Andric            "Must have at least 2 operands");
11460b57cec5SDimitry Andric     assert(std::all_of(SrcOps.begin(), SrcOps.end(),
11470b57cec5SDimitry Andric                        [&, this](const SrcOp &Op) {
11480b57cec5SDimitry Andric                          return (Op.getLLTTy(*getMRI()).isVector() &&
11490b57cec5SDimitry Andric                                  Op.getLLTTy(*getMRI()) ==
11500b57cec5SDimitry Andric                                      SrcOps[0].getLLTTy(*getMRI()));
11510b57cec5SDimitry Andric                        }) &&
11520b57cec5SDimitry Andric            "type mismatch in input list");
11530b57cec5SDimitry Andric     assert(SrcOps.size() * SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
11540b57cec5SDimitry Andric                DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
11550b57cec5SDimitry Andric            "input vectors do not exactly cover the output vector register");
11560b57cec5SDimitry Andric     break;
11570b57cec5SDimitry Andric   }
11580b57cec5SDimitry Andric   case TargetOpcode::G_UADDE: {
11590b57cec5SDimitry Andric     assert(DstOps.size() == 2 && "Invalid no of dst operands");
11600b57cec5SDimitry Andric     assert(SrcOps.size() == 3 && "Invalid no of src operands");
11610b57cec5SDimitry Andric     assert(DstOps[0].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
11620b57cec5SDimitry Andric     assert((DstOps[0].getLLTTy(*getMRI()) == SrcOps[0].getLLTTy(*getMRI())) &&
11630b57cec5SDimitry Andric            (DstOps[0].getLLTTy(*getMRI()) == SrcOps[1].getLLTTy(*getMRI())) &&
11640b57cec5SDimitry Andric            "Invalid operand");
11650b57cec5SDimitry Andric     assert(DstOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
11660b57cec5SDimitry Andric     assert(DstOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
11670b57cec5SDimitry Andric            "type mismatch");
11680b57cec5SDimitry Andric     break;
11690b57cec5SDimitry Andric   }
11700b57cec5SDimitry Andric   }
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric   auto MIB = buildInstr(Opc);
11730b57cec5SDimitry Andric   for (const DstOp &Op : DstOps)
11740b57cec5SDimitry Andric     Op.addDefToMIB(*getMRI(), MIB);
11750b57cec5SDimitry Andric   for (const SrcOp &Op : SrcOps)
11760b57cec5SDimitry Andric     Op.addSrcToMIB(MIB);
11770b57cec5SDimitry Andric   if (Flags)
11780b57cec5SDimitry Andric     MIB->setFlags(*Flags);
11790b57cec5SDimitry Andric   return MIB;
11800b57cec5SDimitry Andric }
1181