10b57cec5SDimitry Andric //===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.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 CSEMIRBuilder class which CSEs as it builds 100b57cec5SDimitry Andric /// instructions. 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" 150b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" 16*349cc55cSDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h" 17*349cc55cSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 18e8d8bef9SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric using namespace llvm; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric bool CSEMIRBuilder::dominates(MachineBasicBlock::const_iterator A, 230b57cec5SDimitry Andric MachineBasicBlock::const_iterator B) const { 240b57cec5SDimitry Andric auto MBBEnd = getMBB().end(); 250b57cec5SDimitry Andric if (B == MBBEnd) 260b57cec5SDimitry Andric return true; 270b57cec5SDimitry Andric assert(A->getParent() == B->getParent() && 280b57cec5SDimitry Andric "Iterators should be in same block"); 290b57cec5SDimitry Andric const MachineBasicBlock *BBA = A->getParent(); 300b57cec5SDimitry Andric MachineBasicBlock::const_iterator I = BBA->begin(); 310b57cec5SDimitry Andric for (; &*I != A && &*I != B; ++I) 320b57cec5SDimitry Andric ; 330b57cec5SDimitry Andric return &*I == A; 340b57cec5SDimitry Andric } 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric MachineInstrBuilder 370b57cec5SDimitry Andric CSEMIRBuilder::getDominatingInstrForID(FoldingSetNodeID &ID, 380b57cec5SDimitry Andric void *&NodeInsertPos) { 390b57cec5SDimitry Andric GISelCSEInfo *CSEInfo = getCSEInfo(); 400b57cec5SDimitry Andric assert(CSEInfo && "Can't get here without setting CSEInfo"); 410b57cec5SDimitry Andric MachineBasicBlock *CurMBB = &getMBB(); 420b57cec5SDimitry Andric MachineInstr *MI = 430b57cec5SDimitry Andric CSEInfo->getMachineInstrIfExists(ID, CurMBB, NodeInsertPos); 440b57cec5SDimitry Andric if (MI) { 450b57cec5SDimitry Andric CSEInfo->countOpcodeHit(MI->getOpcode()); 460b57cec5SDimitry Andric auto CurrPos = getInsertPt(); 47e8d8bef9SDimitry Andric auto MII = MachineBasicBlock::iterator(MI); 48e8d8bef9SDimitry Andric if (MII == CurrPos) { 49e8d8bef9SDimitry Andric // Move the insert point ahead of the instruction so any future uses of 50e8d8bef9SDimitry Andric // this builder will have the def ready. 51e8d8bef9SDimitry Andric setInsertPt(*CurMBB, std::next(MII)); 52e8d8bef9SDimitry Andric } else if (!dominates(MI, CurrPos)) { 530b57cec5SDimitry Andric CurMBB->splice(CurrPos, CurMBB, MI); 54e8d8bef9SDimitry Andric } 550b57cec5SDimitry Andric return MachineInstrBuilder(getMF(), MI); 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric return MachineInstrBuilder(); 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric bool CSEMIRBuilder::canPerformCSEForOpc(unsigned Opc) const { 610b57cec5SDimitry Andric const GISelCSEInfo *CSEInfo = getCSEInfo(); 620b57cec5SDimitry Andric if (!CSEInfo || !CSEInfo->shouldCSE(Opc)) 630b57cec5SDimitry Andric return false; 640b57cec5SDimitry Andric return true; 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric void CSEMIRBuilder::profileDstOp(const DstOp &Op, 680b57cec5SDimitry Andric GISelInstProfileBuilder &B) const { 690b57cec5SDimitry Andric switch (Op.getDstOpKind()) { 700b57cec5SDimitry Andric case DstOp::DstType::Ty_RC: 710b57cec5SDimitry Andric B.addNodeIDRegType(Op.getRegClass()); 720b57cec5SDimitry Andric break; 73e8d8bef9SDimitry Andric case DstOp::DstType::Ty_Reg: { 74e8d8bef9SDimitry Andric // Regs can have LLT&(RB|RC). If those exist, profile them as well. 75e8d8bef9SDimitry Andric B.addNodeIDReg(Op.getReg()); 76e8d8bef9SDimitry Andric break; 77e8d8bef9SDimitry Andric } 780b57cec5SDimitry Andric default: 790b57cec5SDimitry Andric B.addNodeIDRegType(Op.getLLTTy(*getMRI())); 800b57cec5SDimitry Andric break; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric void CSEMIRBuilder::profileSrcOp(const SrcOp &Op, 850b57cec5SDimitry Andric GISelInstProfileBuilder &B) const { 860b57cec5SDimitry Andric switch (Op.getSrcOpKind()) { 87e8d8bef9SDimitry Andric case SrcOp::SrcType::Ty_Imm: 88e8d8bef9SDimitry Andric B.addNodeIDImmediate(static_cast<int64_t>(Op.getImm())); 89e8d8bef9SDimitry Andric break; 900b57cec5SDimitry Andric case SrcOp::SrcType::Ty_Predicate: 910b57cec5SDimitry Andric B.addNodeIDImmediate(static_cast<int64_t>(Op.getPredicate())); 920b57cec5SDimitry Andric break; 930b57cec5SDimitry Andric default: 940b57cec5SDimitry Andric B.addNodeIDRegType(Op.getReg()); 950b57cec5SDimitry Andric break; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric void CSEMIRBuilder::profileMBBOpcode(GISelInstProfileBuilder &B, 1000b57cec5SDimitry Andric unsigned Opc) const { 1010b57cec5SDimitry Andric // First add the MBB (Local CSE). 1020b57cec5SDimitry Andric B.addNodeIDMBB(&getMBB()); 1030b57cec5SDimitry Andric // Then add the opcode. 1040b57cec5SDimitry Andric B.addNodeIDOpcode(Opc); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric void CSEMIRBuilder::profileEverything(unsigned Opc, ArrayRef<DstOp> DstOps, 1080b57cec5SDimitry Andric ArrayRef<SrcOp> SrcOps, 1090b57cec5SDimitry Andric Optional<unsigned> Flags, 1100b57cec5SDimitry Andric GISelInstProfileBuilder &B) const { 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric profileMBBOpcode(B, Opc); 1130b57cec5SDimitry Andric // Then add the DstOps. 1140b57cec5SDimitry Andric profileDstOps(DstOps, B); 1150b57cec5SDimitry Andric // Then add the SrcOps. 1160b57cec5SDimitry Andric profileSrcOps(SrcOps, B); 1170b57cec5SDimitry Andric // Add Flags if passed in. 1180b57cec5SDimitry Andric if (Flags) 1190b57cec5SDimitry Andric B.addNodeIDFlag(*Flags); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric MachineInstrBuilder CSEMIRBuilder::memoizeMI(MachineInstrBuilder MIB, 1230b57cec5SDimitry Andric void *NodeInsertPos) { 1240b57cec5SDimitry Andric assert(canPerformCSEForOpc(MIB->getOpcode()) && 1250b57cec5SDimitry Andric "Attempting to CSE illegal op"); 1260b57cec5SDimitry Andric MachineInstr *MIBInstr = MIB; 1270b57cec5SDimitry Andric getCSEInfo()->insertInstr(MIBInstr, NodeInsertPos); 1280b57cec5SDimitry Andric return MIB; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric bool CSEMIRBuilder::checkCopyToDefsPossible(ArrayRef<DstOp> DstOps) { 1320b57cec5SDimitry Andric if (DstOps.size() == 1) 1330b57cec5SDimitry Andric return true; // always possible to emit copy to just 1 vreg. 1340b57cec5SDimitry Andric 135e8d8bef9SDimitry Andric return llvm::all_of(DstOps, [](const DstOp &Op) { 1360b57cec5SDimitry Andric DstOp::DstType DT = Op.getDstOpKind(); 1370b57cec5SDimitry Andric return DT == DstOp::DstType::Ty_LLT || DT == DstOp::DstType::Ty_RC; 1380b57cec5SDimitry Andric }); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric MachineInstrBuilder 1420b57cec5SDimitry Andric CSEMIRBuilder::generateCopiesIfRequired(ArrayRef<DstOp> DstOps, 1430b57cec5SDimitry Andric MachineInstrBuilder &MIB) { 1440b57cec5SDimitry Andric assert(checkCopyToDefsPossible(DstOps) && 1450b57cec5SDimitry Andric "Impossible return a single MIB with copies to multiple defs"); 1460b57cec5SDimitry Andric if (DstOps.size() == 1) { 1470b57cec5SDimitry Andric const DstOp &Op = DstOps[0]; 1480b57cec5SDimitry Andric if (Op.getDstOpKind() == DstOp::DstType::Ty_Reg) 1495ffd83dbSDimitry Andric return buildCopy(Op.getReg(), MIB.getReg(0)); 1500b57cec5SDimitry Andric } 151e8d8bef9SDimitry Andric 152e8d8bef9SDimitry Andric // If we didn't generate a copy then we're re-using an existing node directly 153e8d8bef9SDimitry Andric // instead of emitting any code. Merge the debug location we wanted to emit 154e8d8bef9SDimitry Andric // into the instruction we're CSE'ing with. Debug locations arent part of the 155e8d8bef9SDimitry Andric // profile so we don't need to recompute it. 156e8d8bef9SDimitry Andric if (getDebugLoc()) { 157e8d8bef9SDimitry Andric GISelChangeObserver *Observer = getState().Observer; 158e8d8bef9SDimitry Andric if (Observer) 159e8d8bef9SDimitry Andric Observer->changingInstr(*MIB); 160e8d8bef9SDimitry Andric MIB->setDebugLoc( 161e8d8bef9SDimitry Andric DILocation::getMergedLocation(MIB->getDebugLoc(), getDebugLoc())); 162e8d8bef9SDimitry Andric if (Observer) 163e8d8bef9SDimitry Andric Observer->changedInstr(*MIB); 164e8d8bef9SDimitry Andric } 165e8d8bef9SDimitry Andric 1660b57cec5SDimitry Andric return MIB; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric MachineInstrBuilder CSEMIRBuilder::buildInstr(unsigned Opc, 1700b57cec5SDimitry Andric ArrayRef<DstOp> DstOps, 1710b57cec5SDimitry Andric ArrayRef<SrcOp> SrcOps, 1720b57cec5SDimitry Andric Optional<unsigned> Flag) { 1730b57cec5SDimitry Andric switch (Opc) { 1740b57cec5SDimitry Andric default: 1750b57cec5SDimitry Andric break; 1760b57cec5SDimitry Andric case TargetOpcode::G_ADD: 1770b57cec5SDimitry Andric case TargetOpcode::G_AND: 1780b57cec5SDimitry Andric case TargetOpcode::G_ASHR: 1790b57cec5SDimitry Andric case TargetOpcode::G_LSHR: 1800b57cec5SDimitry Andric case TargetOpcode::G_MUL: 1810b57cec5SDimitry Andric case TargetOpcode::G_OR: 1820b57cec5SDimitry Andric case TargetOpcode::G_SHL: 1830b57cec5SDimitry Andric case TargetOpcode::G_SUB: 1840b57cec5SDimitry Andric case TargetOpcode::G_XOR: 1850b57cec5SDimitry Andric case TargetOpcode::G_UDIV: 1860b57cec5SDimitry Andric case TargetOpcode::G_SDIV: 1870b57cec5SDimitry Andric case TargetOpcode::G_UREM: 1880b57cec5SDimitry Andric case TargetOpcode::G_SREM: { 1890b57cec5SDimitry Andric // Try to constant fold these. 1900b57cec5SDimitry Andric assert(SrcOps.size() == 2 && "Invalid sources"); 1910b57cec5SDimitry Andric assert(DstOps.size() == 1 && "Invalid dsts"); 192*349cc55cSDimitry Andric if (SrcOps[0].getLLTTy(*getMRI()).isVector()) { 193*349cc55cSDimitry Andric // Try to constant fold vector constants. 194*349cc55cSDimitry Andric auto VecCst = ConstantFoldVectorBinop( 195*349cc55cSDimitry Andric Opc, SrcOps[0].getReg(), SrcOps[1].getReg(), *getMRI(), *this); 196*349cc55cSDimitry Andric if (VecCst) 197*349cc55cSDimitry Andric return MachineInstrBuilder(getMF(), *VecCst); 198*349cc55cSDimitry Andric break; 199*349cc55cSDimitry Andric } 2000b57cec5SDimitry Andric if (Optional<APInt> Cst = ConstantFoldBinOp(Opc, SrcOps[0].getReg(), 2010b57cec5SDimitry Andric SrcOps[1].getReg(), *getMRI())) 202fe6060f1SDimitry Andric return buildConstant(DstOps[0], *Cst); 2030b57cec5SDimitry Andric break; 2040b57cec5SDimitry Andric } 2058bcb0991SDimitry Andric case TargetOpcode::G_SEXT_INREG: { 2068bcb0991SDimitry Andric assert(DstOps.size() == 1 && "Invalid dst ops"); 2078bcb0991SDimitry Andric assert(SrcOps.size() == 2 && "Invalid src ops"); 2088bcb0991SDimitry Andric const DstOp &Dst = DstOps[0]; 2098bcb0991SDimitry Andric const SrcOp &Src0 = SrcOps[0]; 2108bcb0991SDimitry Andric const SrcOp &Src1 = SrcOps[1]; 2118bcb0991SDimitry Andric if (auto MaybeCst = 2128bcb0991SDimitry Andric ConstantFoldExtOp(Opc, Src0.getReg(), Src1.getImm(), *getMRI())) 213fe6060f1SDimitry Andric return buildConstant(Dst, *MaybeCst); 214fe6060f1SDimitry Andric break; 215fe6060f1SDimitry Andric } 216fe6060f1SDimitry Andric case TargetOpcode::G_SITOFP: 217fe6060f1SDimitry Andric case TargetOpcode::G_UITOFP: { 218fe6060f1SDimitry Andric // Try to constant fold these. 219fe6060f1SDimitry Andric assert(SrcOps.size() == 1 && "Invalid sources"); 220fe6060f1SDimitry Andric assert(DstOps.size() == 1 && "Invalid dsts"); 221fe6060f1SDimitry Andric if (Optional<APFloat> Cst = ConstantFoldIntToFloat( 222fe6060f1SDimitry Andric Opc, DstOps[0].getLLTTy(*getMRI()), SrcOps[0].getReg(), *getMRI())) 223fe6060f1SDimitry Andric return buildFConstant(DstOps[0], *Cst); 2248bcb0991SDimitry Andric break; 2258bcb0991SDimitry Andric } 226*349cc55cSDimitry Andric case TargetOpcode::G_CTLZ: { 227*349cc55cSDimitry Andric assert(SrcOps.size() == 1 && "Expected one source"); 228*349cc55cSDimitry Andric assert(DstOps.size() == 1 && "Expected one dest"); 229*349cc55cSDimitry Andric auto MaybeCsts = ConstantFoldCTLZ(SrcOps[0].getReg(), *getMRI()); 230*349cc55cSDimitry Andric if (!MaybeCsts) 231*349cc55cSDimitry Andric break; 232*349cc55cSDimitry Andric if (MaybeCsts->size() == 1) 233*349cc55cSDimitry Andric return buildConstant(DstOps[0], (*MaybeCsts)[0]); 234*349cc55cSDimitry Andric // This was a vector constant. Build a G_BUILD_VECTOR for them. 235*349cc55cSDimitry Andric SmallVector<Register> ConstantRegs; 236*349cc55cSDimitry Andric LLT VecTy = DstOps[0].getLLTTy(*getMRI()); 237*349cc55cSDimitry Andric for (unsigned Cst : *MaybeCsts) 238*349cc55cSDimitry Andric ConstantRegs.emplace_back( 239*349cc55cSDimitry Andric buildConstant(VecTy.getScalarType(), Cst).getReg(0)); 240*349cc55cSDimitry Andric return buildBuildVector(DstOps[0], ConstantRegs); 241*349cc55cSDimitry Andric } 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric bool CanCopy = checkCopyToDefsPossible(DstOps); 2440b57cec5SDimitry Andric if (!canPerformCSEForOpc(Opc)) 2450b57cec5SDimitry Andric return MachineIRBuilder::buildInstr(Opc, DstOps, SrcOps, Flag); 2460b57cec5SDimitry Andric // If we can CSE this instruction, but involves generating copies to multiple 2470b57cec5SDimitry Andric // regs, give up. This frequently happens to UNMERGEs. 2480b57cec5SDimitry Andric if (!CanCopy) { 2490b57cec5SDimitry Andric auto MIB = MachineIRBuilder::buildInstr(Opc, DstOps, SrcOps, Flag); 2500b57cec5SDimitry Andric // CSEInfo would have tracked this instruction. Remove it from the temporary 2510b57cec5SDimitry Andric // insts. 2520b57cec5SDimitry Andric getCSEInfo()->handleRemoveInst(&*MIB); 2530b57cec5SDimitry Andric return MIB; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric FoldingSetNodeID ID; 2560b57cec5SDimitry Andric GISelInstProfileBuilder ProfBuilder(ID, *getMRI()); 2570b57cec5SDimitry Andric void *InsertPos = nullptr; 2580b57cec5SDimitry Andric profileEverything(Opc, DstOps, SrcOps, Flag, ProfBuilder); 2590b57cec5SDimitry Andric MachineInstrBuilder MIB = getDominatingInstrForID(ID, InsertPos); 2600b57cec5SDimitry Andric if (MIB) { 2610b57cec5SDimitry Andric // Handle generating copies here. 2620b57cec5SDimitry Andric return generateCopiesIfRequired(DstOps, MIB); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric // This instruction does not exist in the CSEInfo. Build it and CSE it. 2650b57cec5SDimitry Andric MachineInstrBuilder NewMIB = 2660b57cec5SDimitry Andric MachineIRBuilder::buildInstr(Opc, DstOps, SrcOps, Flag); 2670b57cec5SDimitry Andric return memoizeMI(NewMIB, InsertPos); 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric MachineInstrBuilder CSEMIRBuilder::buildConstant(const DstOp &Res, 2710b57cec5SDimitry Andric const ConstantInt &Val) { 2720b57cec5SDimitry Andric constexpr unsigned Opc = TargetOpcode::G_CONSTANT; 2730b57cec5SDimitry Andric if (!canPerformCSEForOpc(Opc)) 2740b57cec5SDimitry Andric return MachineIRBuilder::buildConstant(Res, Val); 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric // For vectors, CSE the element only for now. 2770b57cec5SDimitry Andric LLT Ty = Res.getLLTTy(*getMRI()); 2780b57cec5SDimitry Andric if (Ty.isVector()) 2790b57cec5SDimitry Andric return buildSplatVector(Res, buildConstant(Ty.getElementType(), Val)); 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric FoldingSetNodeID ID; 2820b57cec5SDimitry Andric GISelInstProfileBuilder ProfBuilder(ID, *getMRI()); 2830b57cec5SDimitry Andric void *InsertPos = nullptr; 2840b57cec5SDimitry Andric profileMBBOpcode(ProfBuilder, Opc); 2850b57cec5SDimitry Andric profileDstOp(Res, ProfBuilder); 2860b57cec5SDimitry Andric ProfBuilder.addNodeIDMachineOperand(MachineOperand::CreateCImm(&Val)); 2870b57cec5SDimitry Andric MachineInstrBuilder MIB = getDominatingInstrForID(ID, InsertPos); 2880b57cec5SDimitry Andric if (MIB) { 2890b57cec5SDimitry Andric // Handle generating copies here. 2900b57cec5SDimitry Andric return generateCopiesIfRequired({Res}, MIB); 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric MachineInstrBuilder NewMIB = MachineIRBuilder::buildConstant(Res, Val); 2940b57cec5SDimitry Andric return memoizeMI(NewMIB, InsertPos); 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric MachineInstrBuilder CSEMIRBuilder::buildFConstant(const DstOp &Res, 2980b57cec5SDimitry Andric const ConstantFP &Val) { 2990b57cec5SDimitry Andric constexpr unsigned Opc = TargetOpcode::G_FCONSTANT; 3000b57cec5SDimitry Andric if (!canPerformCSEForOpc(Opc)) 3010b57cec5SDimitry Andric return MachineIRBuilder::buildFConstant(Res, Val); 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric // For vectors, CSE the element only for now. 3040b57cec5SDimitry Andric LLT Ty = Res.getLLTTy(*getMRI()); 3050b57cec5SDimitry Andric if (Ty.isVector()) 3060b57cec5SDimitry Andric return buildSplatVector(Res, buildFConstant(Ty.getElementType(), Val)); 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric FoldingSetNodeID ID; 3090b57cec5SDimitry Andric GISelInstProfileBuilder ProfBuilder(ID, *getMRI()); 3100b57cec5SDimitry Andric void *InsertPos = nullptr; 3110b57cec5SDimitry Andric profileMBBOpcode(ProfBuilder, Opc); 3120b57cec5SDimitry Andric profileDstOp(Res, ProfBuilder); 3130b57cec5SDimitry Andric ProfBuilder.addNodeIDMachineOperand(MachineOperand::CreateFPImm(&Val)); 3140b57cec5SDimitry Andric MachineInstrBuilder MIB = getDominatingInstrForID(ID, InsertPos); 3150b57cec5SDimitry Andric if (MIB) { 3160b57cec5SDimitry Andric // Handle generating copies here. 3170b57cec5SDimitry Andric return generateCopiesIfRequired({Res}, MIB); 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric MachineInstrBuilder NewMIB = MachineIRBuilder::buildFConstant(Res, Val); 3200b57cec5SDimitry Andric return memoizeMI(NewMIB, InsertPos); 3210b57cec5SDimitry Andric } 322