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