//==--- InstrEmitter.cpp - Emit MachineInstrs for the SelectionDAG class ---==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This implements the Emit routines for the SelectionDAG class, which creates
// MachineInstrs based on the decisions of the SelectionDAG instruction
// selection.
//
//===----------------------------------------------------------------------===//

#include "InstrEmitter.h"
#include "SDNodeDbgValue.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/PseudoProbe.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

#define DEBUG_TYPE "instr-emitter"

/// MinRCSize - Smallest register class we allow when constraining virtual
/// registers.  If satisfying all register class constraints would require
/// using a smaller register class, emit a COPY to a new virtual register
/// instead.
const unsigned MinRCSize = 4;

/// CountResults - The results of target nodes have register or immediate
/// operands first, then an optional chain, and optional glue operands (which do
/// not go into the resulting MachineInstr).
unsigned InstrEmitter::CountResults(SDNode *Node) {
  unsigned N = Node->getNumValues();
  while (N && Node->getValueType(N - 1) == MVT::Glue)
    --N;
  if (N && Node->getValueType(N - 1) == MVT::Other)
    --N;    // Skip over chain result.
  return N;
}

/// countOperands - The inputs to target nodes have any actual inputs first,
/// followed by an optional chain operand, then an optional glue operand.
/// Compute the number of actual operands that will go into the resulting
/// MachineInstr.
///
/// Also count physreg RegisterSDNode and RegisterMaskSDNode operands preceding
/// the chain and glue. These operands may be implicit on the machine instr.
static unsigned countOperands(SDNode *Node, unsigned NumExpUses,
                              unsigned &NumImpUses) {
  unsigned N = Node->getNumOperands();
  while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
    --N;
  if (N && Node->getOperand(N - 1).getOpcode() == ISD::DEACTIVATION_SYMBOL)
    --N; // Ignore deactivation symbol if it exists.
  if (N && Node->getOperand(N - 1).getValueType() == MVT::Other)
    --N; // Ignore chain if it exists.

  // Count RegisterSDNode and RegisterMaskSDNode operands for NumImpUses.
  NumImpUses = N - NumExpUses;
  for (unsigned I = N; I > NumExpUses; --I) {
    if (isa<RegisterMaskSDNode>(Node->getOperand(I - 1)))
      continue;
    if (RegisterSDNode *RN = dyn_cast<RegisterSDNode>(Node->getOperand(I - 1)))
      if (RN->getReg().isPhysical())
        continue;
    NumImpUses = N - I;
    break;
  }

  return N;
}

/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
/// implicit physical register output.
void InstrEmitter::EmitCopyFromReg(SDValue Op, bool IsClone, Register SrcReg,
                                   VRBaseMapType &VRBaseMap) {
  Register VRBase;
  if (SrcReg.isVirtual()) {
    // Just use the input register directly!
    if (IsClone)
      VRBaseMap.erase(Op);
    bool isNew = VRBaseMap.insert(std::make_pair(Op, SrcReg)).second;
    (void)isNew; // Silence compiler warning.
    assert(isNew && "Node emitted out of order - early");
    return;
  }

  // If the node is only used by a CopyToReg and the dest reg is a vreg, use
  // the CopyToReg'd destination register instead of creating a new vreg.
  bool MatchReg = true;

  MVT VT = Op.getSimpleValueType();

  // FIXME: The Untyped check is a workaround for SystemZ i128 inline assembly
  // using i128, when it should probably be using v2i64.
  const TargetRegisterClass *UseRC =
      VT == MVT::Untyped ? nullptr : TLI->getRegClassFor(VT, Op->isDivergent());

  for (SDNode *User : Op->users()) {
    bool Match = true;
    if (User->getOpcode() == ISD::CopyToReg && User->getOperand(2) == Op) {
      Register DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
      if (DestReg.isVirtual()) {
        VRBase = DestReg;
        Match = false;
      } else if (DestReg != SrcReg)
        Match = false;
    } else {
      for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
        if (User->getOperand(i) != Op)
          continue;
        if (VT == MVT::Other || VT == MVT::Glue)
          continue;
        Match = false;
        if (User->isMachineOpcode()) {
          const MCInstrDesc &II = TII->get(User->getMachineOpcode());
          const TargetRegisterClass *RC = nullptr;
          if (i + II.getNumDefs() < II.getNumOperands()) {
            RC = TRI->getAllocatableClass(
                TII->getRegClass(II, i + II.getNumDefs()));
          }
          if (!UseRC)
            UseRC = RC;
          else if (RC) {
            const TargetRegisterClass *ComRC =
                TRI->getCommonSubClass(UseRC, RC);
            // If multiple uses expect disjoint register classes, we emit
            // copies in AddRegisterOperand.
            if (ComRC)
              UseRC = ComRC;
          }
        }
      }
    }
    MatchReg &= Match;
    if (VRBase)
      break;
  }

  const TargetRegisterClass *SrcRC = nullptr, *DstRC = nullptr;
  SrcRC = TRI->getMinimalPhysRegClass(SrcReg);

  // Figure out the register class to create for the destreg.
  if (VRBase) {
    DstRC = MRI->getRegClass(VRBase);
  } else if (UseRC) {
    assert(TRI->isTypeLegalForClass(*UseRC, VT) &&
           "Incompatible phys register def and uses!");
    DstRC = UseRC;
  } else
    DstRC = SrcRC;

  // If all uses are reading from the src physical register and copying the
  // register is either impossible or very expensive, then don't create a copy.
  if (MatchReg && SrcRC->expensiveOrImpossibleToCopy()) {
    VRBase = SrcReg;
  } else {
    // Create the reg, emit the copy.
    VRBase = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, InsertPos, Op.getDebugLoc(), TII->get(TargetOpcode::COPY),
            VRBase)
        .addReg(SrcReg);
  }

  if (IsClone)
    VRBaseMap.erase(Op);
  bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second;
  (void)isNew; // Silence compiler warning.
  assert(isNew && "Node emitted out of order - early");
}

void InstrEmitter::CreateVirtualRegisters(SDNode *Node,
                                       MachineInstrBuilder &MIB,
                                       const MCInstrDesc &II,
                                       bool IsClone, bool IsCloned,
                                       VRBaseMapType &VRBaseMap) {
  assert(Node->getMachineOpcode() != TargetOpcode::IMPLICIT_DEF &&
         "IMPLICIT_DEF should have been handled as a special case elsewhere!");

  unsigned NumResults = CountResults(Node);
  bool HasVRegVariadicDefs = !MF->getTarget().usesPhysRegsForValues() &&
                             II.isVariadic() && II.variadicOpsAreDefs();
  unsigned NumVRegs = HasVRegVariadicDefs ? NumResults : II.getNumDefs();
  if (Node->getMachineOpcode() == TargetOpcode::STATEPOINT)
    NumVRegs = NumResults;
  for (unsigned i = 0; i < NumVRegs; ++i) {
    // If the specific node value is only used by a CopyToReg and the dest reg
    // is a vreg in the same register class, use the CopyToReg'd destination
    // register instead of creating a new vreg.
    Register VRBase;
    const TargetRegisterClass *RC =
        TRI->getAllocatableClass(TII->getRegClass(II, i));
    // Always let the value type influence the used register class. The
    // constraints on the instruction may be too lax to represent the value
    // type correctly. For example, a 64-bit float (X86::FR64) can't live in
    // the 32-bit float super-class (X86::FR32).
    if (i < NumResults && TLI->isTypeLegal(Node->getSimpleValueType(i))) {
      const TargetRegisterClass *VTRC = TLI->getRegClassFor(
          Node->getSimpleValueType(i),
          (Node->isDivergent() || (RC && TRI->isDivergentRegClass(RC))));
      if (RC)
        VTRC = TRI->getCommonSubClass(RC, VTRC);
      if (VTRC)
        RC = VTRC;
    }

    if (!II.operands().empty() && II.operands()[i].isOptionalDef()) {
      // Optional def must be a physical register.
      VRBase = cast<RegisterSDNode>(Node->getOperand(i-NumResults))->getReg();
      assert(VRBase.isPhysical());
      MIB.addReg(VRBase, RegState::Define);
    }

    if (!VRBase && !IsClone && !IsCloned)
      for (SDNode *User : Node->users()) {
        if (User->getOpcode() == ISD::CopyToReg &&
            User->getOperand(2).getNode() == Node &&
            User->getOperand(2).getResNo() == i) {
          Register Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
          if (Reg.isVirtual()) {
            const TargetRegisterClass *RegRC = MRI->getRegClass(Reg);
            if (RegRC == RC) {
              VRBase = Reg;
              MIB.addReg(VRBase, RegState::Define);
              break;
            }
          }
        }
      }

    // Create the result registers for this node and add the result regs to
    // the machine instruction.
    if (!VRBase) {
      assert(RC && "Isn't a register operand!");
      VRBase = MRI->createVirtualRegister(RC);
      MIB.addReg(VRBase, RegState::Define);
    }

    // If this def corresponds to a result of the SDNode insert the VRBase into
    // the lookup map.
    if (i < NumResults) {
      SDValue Op(Node, i);
      if (IsClone)
        VRBaseMap.erase(Op);
      bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second;
      (void)isNew; // Silence compiler warning.
      assert(isNew && "Node emitted out of order - early");
    }
  }
}

/// getVR - Return the virtual register corresponding to the specified result
/// of the specified node.
Register InstrEmitter::getVR(SDValue Op, VRBaseMapType &VRBaseMap) {
  if (Op.isMachineOpcode() &&
      Op.getMachineOpcode() == TargetOpcode::IMPLICIT_DEF) {
    // Add an IMPLICIT_DEF instruction before every use.
    // IMPLICIT_DEF can produce any type of result so its MCInstrDesc
    // does not include operand register class info.
    const TargetRegisterClass *RC = TLI->getRegClassFor(
        Op.getSimpleValueType(), Op.getNode()->isDivergent());
    Register VReg = MRI->createVirtualRegister(RC);
    BuildMI(*MBB, InsertPos, Op.getDebugLoc(),
            TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
    return VReg;
  }

  VRBaseMapType::iterator I = VRBaseMap.find(Op);
  assert(I != VRBaseMap.end() && "Node emitted out of order - late");
  return I->second;
}

static bool isConvergenceCtrlMachineOp(SDValue Op) {
  if (Op->isMachineOpcode()) {
    switch (Op->getMachineOpcode()) {
    case TargetOpcode::CONVERGENCECTRL_ANCHOR:
    case TargetOpcode::CONVERGENCECTRL_ENTRY:
    case TargetOpcode::CONVERGENCECTRL_LOOP:
    case TargetOpcode::CONVERGENCECTRL_GLUE:
      return true;
    }
    return false;
  }

  // We can reach here when CopyFromReg is encountered. But rather than making a
  // special case for that, we just make sure we don't reach here in some
  // surprising way.
  switch (Op->getOpcode()) {
  case ISD::CONVERGENCECTRL_ANCHOR:
  case ISD::CONVERGENCECTRL_ENTRY:
  case ISD::CONVERGENCECTRL_LOOP:
  case ISD::CONVERGENCECTRL_GLUE:
    llvm_unreachable("Convergence control should have been selected by now.");
  }
  return false;
}

/// AddRegisterOperand - Add the specified register as an operand to the
/// specified machine instr. Insert register copies if the register is
/// not in the required register class.
void
InstrEmitter::AddRegisterOperand(MachineInstrBuilder &MIB,
                                 SDValue Op,
                                 unsigned IIOpNum,
                                 const MCInstrDesc *II,
                                 VRBaseMapType &VRBaseMap,
                                 bool IsDebug, bool IsClone, bool IsCloned) {
  assert(Op.getValueType() != MVT::Other &&
         Op.getValueType() != MVT::Glue &&
         "Chain and glue operands should occur at end of operand list!");
  // Get/emit the operand.
  Register VReg = getVR(Op, VRBaseMap);

  const MCInstrDesc &MCID = MIB->getDesc();
  bool isOptDef = IIOpNum < MCID.getNumOperands() &&
                  MCID.operands()[IIOpNum].isOptionalDef();

  // If the instruction requires a register in a different class, create
  // a new virtual register and copy the value into it, but first attempt to
  // shrink VReg's register class within reason.  For example, if VReg == GR32
  // and II requires a GR32_NOSP, just constrain VReg to GR32_NOSP.
  if (II) {
    const TargetRegisterClass *OpRC = nullptr;
    if (IIOpNum < II->getNumOperands())
      OpRC = TII->getRegClass(*II, IIOpNum);

    if (OpRC) {
      unsigned MinNumRegs = MinRCSize;
      // Don't apply any RC size limit for IMPLICIT_DEF. Each use has a unique
      // virtual register.
      if (Op.isMachineOpcode() &&
          Op.getMachineOpcode() == TargetOpcode::IMPLICIT_DEF)
        MinNumRegs = 0;

      const TargetRegisterClass *ConstrainedRC
        = MRI->constrainRegClass(VReg, OpRC, MinNumRegs);
      if (!ConstrainedRC) {
        OpRC = TRI->getAllocatableClass(OpRC);
        assert(OpRC && "Constraints cannot be fulfilled for allocation");
        Register NewVReg = MRI->createVirtualRegister(OpRC);
        BuildMI(*MBB, InsertPos, MIB->getDebugLoc(),
                TII->get(TargetOpcode::COPY), NewVReg)
            .addReg(VReg);
        VReg = NewVReg;
      } else {
        assert(ConstrainedRC->isAllocatable() &&
           "Constraining an allocatable VReg produced an unallocatable class?");
      }
    }
  }

  // If this value has only one use, that use is a kill. This is a
  // conservative approximation. InstrEmitter does trivial coalescing
  // with CopyFromReg nodes, so don't emit kill flags for them.
  // Avoid kill flags on Schedule cloned nodes, since there will be
  // multiple uses.
  // Tied operands are never killed, so we need to check that. And that
  // means we need to determine the index of the operand.
  // Don't kill convergence control tokens. Initially they are only used in glue
  // nodes, and the InstrEmitter later adds implicit uses on the users of the
  // glue node. This can sometimes make it seem like there is only one use,
  // which is the glue node itself.
  bool isKill = Op.hasOneUse() && !isConvergenceCtrlMachineOp(Op) &&
                Op.getNode()->getOpcode() != ISD::CopyFromReg && !IsDebug &&
                !(IsClone || IsCloned);
  if (isKill) {
    unsigned Idx = MIB->getNumOperands();
    while (Idx > 0 &&
           MIB->getOperand(Idx-1).isReg() &&
           MIB->getOperand(Idx-1).isImplicit())
      --Idx;
    bool isTied = MCID.getOperandConstraint(Idx, MCOI::TIED_TO) != -1;
    if (isTied)
      isKill = false;
  }

  MIB.addReg(VReg, getDefRegState(isOptDef) | getKillRegState(isKill) |
             getDebugRegState(IsDebug));
}

/// AddOperand - Add the specified operand to the specified machine instr.  II
/// specifies the instruction information for the node, and IIOpNum is the
/// operand number (in the II) that we are adding.
void InstrEmitter::AddOperand(MachineInstrBuilder &MIB, SDValue Op,
                              unsigned IIOpNum, const MCInstrDesc *II,
                              VRBaseMapType &VRBaseMap, bool IsDebug,
                              bool IsClone, bool IsCloned) {
  if (Op.isMachineOpcode()) {
    AddRegisterOperand(MIB, Op, IIOpNum, II, VRBaseMap,
                       IsDebug, IsClone, IsCloned);
  } else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
    if (C->getAPIntValue().getSignificantBits() <= 64) {
      MIB.addImm(C->getSExtValue());
    } else {
      MIB.addCImm(
          ConstantInt::get(MF->getFunction().getContext(), C->getAPIntValue()));
    }
  } else if (ConstantFPSDNode *F = dyn_cast<ConstantFPSDNode>(Op)) {
    MIB.addFPImm(F->getConstantFPValue());
  } else if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op)) {
    Register VReg = R->getReg();
    MVT OpVT = Op.getSimpleValueType();
    const TargetRegisterClass *IIRC =
        II ? TRI->getAllocatableClass(TII->getRegClass(*II, IIOpNum)) : nullptr;
    const TargetRegisterClass *OpRC =
        TLI->isTypeLegal(OpVT)
            ? TLI->getRegClassFor(OpVT,
                                  Op.getNode()->isDivergent() ||
                                      (IIRC && TRI->isDivergentRegClass(IIRC)))
            : nullptr;

    if (OpRC && IIRC && OpRC != IIRC && VReg.isVirtual()) {
      Register NewVReg = MRI->createVirtualRegister(IIRC);
      BuildMI(*MBB, InsertPos, Op.getNode()->getDebugLoc(),
               TII->get(TargetOpcode::COPY), NewVReg).addReg(VReg);
      VReg = NewVReg;
    }
    // Turn additional physreg operands into implicit uses on non-variadic
    // instructions. This is used by call and return instructions passing
    // arguments in registers.
    bool Imp = II && (IIOpNum >= II->getNumOperands() && !II->isVariadic());
    MIB.addReg(VReg, getImplRegState(Imp));
  } else if (RegisterMaskSDNode *RM = dyn_cast<RegisterMaskSDNode>(Op)) {
    MIB.addRegMask(RM->getRegMask());
  } else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) {
    MIB.addGlobalAddress(TGA->getGlobal(), TGA->getOffset(),
                         TGA->getTargetFlags());
  } else if (BasicBlockSDNode *BBNode = dyn_cast<BasicBlockSDNode>(Op)) {
    MIB.addMBB(BBNode->getBasicBlock());
  } else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op)) {
    MIB.addFrameIndex(FI->getIndex());
  } else if (JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) {
    MIB.addJumpTableIndex(JT->getIndex(), JT->getTargetFlags());
  } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op)) {
    int Offset = CP->getOffset();
    Align Alignment = CP->getAlign();

    unsigned Idx;
    MachineConstantPool *MCP = MF->getConstantPool();
    if (CP->isMachineConstantPoolEntry())
      Idx = MCP->getConstantPoolIndex(CP->getMachineCPVal(), Alignment);
    else
      Idx = MCP->getConstantPoolIndex(CP->getConstVal(), Alignment);
    MIB.addConstantPoolIndex(Idx, Offset, CP->getTargetFlags());
  } else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) {
    MIB.addExternalSymbol(ES->getSymbol(), ES->getTargetFlags());
  } else if (auto *SymNode = dyn_cast<MCSymbolSDNode>(Op)) {
    MIB.addSym(SymNode->getMCSymbol());
  } else if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) {
    MIB.addBlockAddress(BA->getBlockAddress(),
                        BA->getOffset(),
                        BA->getTargetFlags());
  } else if (TargetIndexSDNode *TI = dyn_cast<TargetIndexSDNode>(Op)) {
    MIB.addTargetIndex(TI->getIndex(), TI->getOffset(), TI->getTargetFlags());
  } else {
    assert(Op.getValueType() != MVT::Other &&
           Op.getValueType() != MVT::Glue &&
           "Chain and glue operands should occur at end of operand list!");
    AddRegisterOperand(MIB, Op, IIOpNum, II, VRBaseMap,
                       IsDebug, IsClone, IsCloned);
  }
}

Register InstrEmitter::ConstrainForSubReg(Register VReg, unsigned SubIdx,
                                          MVT VT, bool isDivergent, const DebugLoc &DL) {
  const TargetRegisterClass *VRC = MRI->getRegClass(VReg);
  const TargetRegisterClass *RC = TRI->getSubClassWithSubReg(VRC, SubIdx);

  // RC is a sub-class of VRC that supports SubIdx.  Try to constrain VReg
  // within reason.
  if (RC && RC != VRC)
    RC = MRI->constrainRegClass(VReg, RC, MinRCSize);

  // VReg has been adjusted.  It can be used with SubIdx operands now.
  if (RC)
    return VReg;

  // VReg couldn't be reasonably constrained.  Emit a COPY to a new virtual
  // register instead.
  RC = TRI->getSubClassWithSubReg(TLI->getRegClassFor(VT, isDivergent), SubIdx);
  assert(RC && "No legal register class for VT supports that SubIdx");
  Register NewReg = MRI->createVirtualRegister(RC);
  BuildMI(*MBB, InsertPos, DL, TII->get(TargetOpcode::COPY), NewReg)
    .addReg(VReg);
  return NewReg;
}

/// EmitSubregNode - Generate machine code for subreg nodes.
///
void InstrEmitter::EmitSubregNode(SDNode *Node, VRBaseMapType &VRBaseMap,
                                  bool IsClone, bool IsCloned) {
  Register VRBase;
  unsigned Opc = Node->getMachineOpcode();

  // If the node is only used by a CopyToReg and the dest reg is a vreg, use
  // the CopyToReg'd destination register instead of creating a new vreg.
  for (SDNode *User : Node->users()) {
    if (User->getOpcode() == ISD::CopyToReg &&
        User->getOperand(2).getNode() == Node) {
      Register DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
      if (DestReg.isVirtual()) {
        VRBase = DestReg;
        break;
      }
    }
  }

  if (Opc == TargetOpcode::EXTRACT_SUBREG) {
    // EXTRACT_SUBREG is lowered as %dst = COPY %src:sub.  There are no
    // constraints on the %dst register, COPY can target all legal register
    // classes.
    unsigned SubIdx = Node->getConstantOperandVal(1);
    const TargetRegisterClass *TRC =
      TLI->getRegClassFor(Node->getSimpleValueType(0), Node->isDivergent());

    Register Reg;
    MachineInstr *DefMI;
    RegisterSDNode *R = dyn_cast<RegisterSDNode>(Node->getOperand(0));
    if (R && R->getReg().isPhysical()) {
      Reg = R->getReg();
      DefMI = nullptr;
    } else {
      Reg = R ? R->getReg() : getVR(Node->getOperand(0), VRBaseMap);
      DefMI = MRI->getVRegDef(Reg);
    }

    Register SrcReg, DstReg;
    unsigned DefSubIdx;
    if (DefMI &&
        TII->isCoalescableExtInstr(*DefMI, SrcReg, DstReg, DefSubIdx) &&
        SubIdx == DefSubIdx &&
        TRC == MRI->getRegClass(SrcReg)) {
      // Optimize these:
      // r1025 = s/zext r1024, 4
      // r1026 = extract_subreg r1025, 4
      // to a copy
      // r1026 = copy r1024
      VRBase = MRI->createVirtualRegister(TRC);
      BuildMI(*MBB, InsertPos, Node->getDebugLoc(),
              TII->get(TargetOpcode::COPY), VRBase).addReg(SrcReg);
      MRI->clearKillFlags(SrcReg);
    } else {
      // Reg may not support a SubIdx sub-register, and we may need to
      // constrain its register class or issue a COPY to a compatible register
      // class.
      if (Reg.isVirtual())
        Reg = ConstrainForSubReg(Reg, SubIdx,
                                 Node->getOperand(0).getSimpleValueType(),
                                 Node->isDivergent(), Node->getDebugLoc());
      // Create the destreg if it is missing.
      if (!VRBase)
        VRBase = MRI->createVirtualRegister(TRC);

      // Create the extract_subreg machine instruction.
      MachineInstrBuilder CopyMI =
          BuildMI(*MBB, InsertPos, Node->getDebugLoc(),
                  TII->get(TargetOpcode::COPY), VRBase);
      if (Reg.isVirtual())
        CopyMI.addReg(Reg, {}, SubIdx);
      else
        CopyMI.addReg(TRI->getSubReg(Reg, SubIdx));
    }
  } else if (Opc == TargetOpcode::INSERT_SUBREG ||
             Opc == TargetOpcode::SUBREG_TO_REG) {
    SDValue Reg;
    SDValue SubReg;
    unsigned SubIdx;
    if (Opc == TargetOpcode::INSERT_SUBREG) {
      Reg = Node->getOperand(0);
      SubReg = Node->getOperand(1);
      SubIdx = Node->getOperand(2)->getAsZExtVal();
    } else {
      SubReg = Node->getOperand(0);
      SubIdx = Node->getOperand(1)->getAsZExtVal();
    }

    // Figure out the register class to create for the destreg.  It should be
    // the largest legal register class supporting SubIdx sub-registers.
    // RegisterCoalescer will constrain it further if it decides to eliminate
    // the INSERT_SUBREG instruction.
    //
    //   %dst = INSERT_SUBREG %src, %sub, SubIdx
    //
    // is lowered by TwoAddressInstructionPass to:
    //
    //   %dst = COPY %src
    //   %dst:SubIdx = COPY %sub
    //
    // There is no constraint on the %src register class.
    //
    const TargetRegisterClass *SRC =
        TLI->getRegClassFor(Node->getSimpleValueType(0), Node->isDivergent());
    SRC = TRI->getSubClassWithSubReg(SRC, SubIdx);
    assert(SRC && "No register class supports VT and SubIdx for INSERT_SUBREG");

    if (VRBase == 0 || !SRC->hasSubClassEq(MRI->getRegClass(VRBase)))
      VRBase = MRI->createVirtualRegister(SRC);

    // Create the insert_subreg or subreg_to_reg machine instruction.
    MachineInstrBuilder MIB =
      BuildMI(*MF, Node->getDebugLoc(), TII->get(Opc), VRBase);

    // If creating an insert_subreg, then the first input operand
    // is a register
    if (Reg) {
      AddOperand(MIB, Reg, 0, nullptr, VRBaseMap, /*IsDebug=*/false, IsClone,
                 IsCloned);
    }
    // Add the subregister being inserted
    AddOperand(MIB, SubReg, 0, nullptr, VRBaseMap, /*IsDebug=*/false, IsClone,
               IsCloned);
    MIB.addImm(SubIdx);
    MBB->insert(InsertPos, MIB);
  } else
    llvm_unreachable("Node is not insert_subreg, extract_subreg, or subreg_to_reg");

  SDValue Op(Node, 0);
  bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second;
  (void)isNew; // Silence compiler warning.
  assert(isNew && "Node emitted out of order - early");
}

/// EmitCopyToRegClassNode - Generate machine code for COPY_TO_REGCLASS nodes.
/// COPY_TO_REGCLASS is just a normal copy, except that the destination
/// register is constrained to be in a particular register class.
///
void
InstrEmitter::EmitCopyToRegClassNode(SDNode *Node,
                                     VRBaseMapType &VRBaseMap) {
  // Create the new VReg in the destination class and emit a copy.
  unsigned DstRCIdx = Node->getConstantOperandVal(1);
  const TargetRegisterClass *DstRC =
    TRI->getAllocatableClass(TRI->getRegClass(DstRCIdx));
  Register NewVReg = MRI->createVirtualRegister(DstRC);
  const MCInstrDesc &II = TII->get(TargetOpcode::COPY);
  MachineInstrBuilder MIB = BuildMI(*MF, Node->getDebugLoc(), II, NewVReg);
  AddOperand(MIB, Node->getOperand(0), 1, &II, VRBaseMap, /*IsDebug=*/false,
             /*IsClone=*/false, /*IsCloned*/ false);

  MBB->insert(InsertPos, MIB);
  SDValue Op(Node, 0);
  bool isNew = VRBaseMap.insert(std::make_pair(Op, NewVReg)).second;
  (void)isNew; // Silence compiler warning.
  assert(isNew && "Node emitted out of order - early");
}

/// EmitRegSequence - Generate machine code for REG_SEQUENCE nodes.
///
void InstrEmitter::EmitRegSequence(SDNode *Node, VRBaseMapType &VRBaseMap,
                                   bool IsClone, bool IsCloned) {
  unsigned DstRCIdx = Node->getConstantOperandVal(0);
  const TargetRegisterClass *RC = TRI->getRegClass(DstRCIdx);
  Register NewVReg = MRI->createVirtualRegister(TRI->getAllocatableClass(RC));
  const MCInstrDesc &II = TII->get(TargetOpcode::REG_SEQUENCE);
  MachineInstrBuilder MIB = BuildMI(*MF, Node->getDebugLoc(), II, NewVReg);
  unsigned NumOps = Node->getNumOperands();
  // If the input pattern has a chain, then the root of the corresponding
  // output pattern will get a chain as well. This can happen to be a
  // REG_SEQUENCE (which is not "guarded" by countOperands/CountResults).
  if (NumOps && Node->getOperand(NumOps-1).getValueType() == MVT::Other)
    --NumOps; // Ignore chain if it exists.

  assert((NumOps & 1) == 1 &&
         "REG_SEQUENCE must have an odd number of operands!");
  for (unsigned i = 1; i != NumOps; ++i) {
    SDValue Op = Node->getOperand(i);
    if ((i & 1) == 0) {
      RegisterSDNode *R = dyn_cast<RegisterSDNode>(Node->getOperand(i-1));
      // Skip physical registers as they don't have a vreg to get and we'll
      // insert copies for them in TwoAddressInstructionPass anyway.
      if (!R || !R->getReg().isPhysical()) {
        unsigned SubIdx = Op->getAsZExtVal();
        Register SubReg = getVR(Node->getOperand(i - 1), VRBaseMap);
        const TargetRegisterClass *TRC = MRI->getRegClass(SubReg);
        const TargetRegisterClass *SRC =
        TRI->getMatchingSuperRegClass(RC, TRC, SubIdx);
        if (SRC && SRC != RC) {
          MRI->setRegClass(NewVReg, SRC);
          RC = SRC;
        }
      }
    }
    AddOperand(MIB, Op, i+1, &II, VRBaseMap, /*IsDebug=*/false,
               IsClone, IsCloned);
  }

  MBB->insert(InsertPos, MIB);
  SDValue Op(Node, 0);
  bool isNew = VRBaseMap.insert(std::make_pair(Op, NewVReg)).second;
  (void)isNew; // Silence compiler warning.
  assert(isNew && "Node emitted out of order - early");
}

/// EmitDbgValue - Generate machine instruction for a dbg_value node.
///
MachineInstr *InstrEmitter::EmitDbgValue(SDDbgValue *SD,
                                         VRBaseMapType &VRBaseMap) {
  assert(cast<DILocalVariable>(SD->getVariable())
             ->isValidLocationForIntrinsic(SD->getDebugLoc()) &&
         "Expected inlined-at fields to agree");

  SD->setIsEmitted();

  assert(!SD->getLocationOps().empty() &&
         "dbg_value with no location operands?");

  if (SD->isInvalidated())
    return EmitDbgNoLocation(SD);

  // Attempt to produce a DBG_INSTR_REF if we've been asked to.
  if (EmitDebugInstrRefs)
    if (auto *InstrRef = EmitDbgInstrRef(SD, VRBaseMap))
      return InstrRef;

  // Emit variadic dbg_value nodes as DBG_VALUE_LIST if they have not been
  // emitted as instruction references.
  if (SD->isVariadic())
    return EmitDbgValueList(SD, VRBaseMap);

  // Emit single-location dbg_value nodes as DBG_VALUE if they have not been
  // emitted as instruction references.
  return EmitDbgValueFromSingleOp(SD, VRBaseMap);
}

MachineOperand GetMOForConstDbgOp(const SDDbgOperand &Op) {
  const Value *V = Op.getConst();
  if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
    if (CI->getBitWidth() > 64)
      return MachineOperand::CreateCImm(CI);
    if (CI->getBitWidth() == 1)
      return MachineOperand::CreateImm(CI->getZExtValue());
    return MachineOperand::CreateImm(CI->getSExtValue());
  }
  if (const ConstantFP *CF = dyn_cast<ConstantFP>(V))
    return MachineOperand::CreateFPImm(CF);
  // Note: This assumes that all nullptr constants are zero-valued.
  if (isa<ConstantPointerNull>(V))
    return MachineOperand::CreateImm(0);
  // Undef or unhandled value type, so return an undef operand.
  return MachineOperand::CreateReg(
      /* Reg */ 0U, /* isDef */ false, /* isImp */ false,
      /* isKill */ false, /* isDead */ false,
      /* isUndef */ false, /* isEarlyClobber */ false,
      /* SubReg */ 0, /* isDebug */ true);
}

void InstrEmitter::AddDbgValueLocationOps(
    MachineInstrBuilder &MIB, const MCInstrDesc &DbgValDesc,
    ArrayRef<SDDbgOperand> LocationOps,
    VRBaseMapType &VRBaseMap) {
  for (const SDDbgOperand &Op : LocationOps) {
    switch (Op.getKind()) {
    case SDDbgOperand::FRAMEIX:
      MIB.addFrameIndex(Op.getFrameIx());
      break;
    case SDDbgOperand::VREG:
      MIB.addReg(Op.getVReg());
      break;
    case SDDbgOperand::SDNODE: {
      SDValue V = SDValue(Op.getSDNode(), Op.getResNo());
      // It's possible we replaced this SDNode with other(s) and therefore
      // didn't generate code for it. It's better to catch these cases where
      // they happen and transfer the debug info, but trying to guarantee that
      // in all cases would be very fragile; this is a safeguard for any
      // that were missed.
      if (VRBaseMap.count(V) == 0)
        MIB.addReg(0U); // undef
      else
        AddOperand(MIB, V, (*MIB).getNumOperands(), &DbgValDesc, VRBaseMap,
                   /*IsDebug=*/true, /*IsClone=*/false, /*IsCloned=*/false);
    } break;
    case SDDbgOperand::CONST:
      MIB.add(GetMOForConstDbgOp(Op));
      break;
    }
  }
}

MachineInstr *
InstrEmitter::EmitDbgInstrRef(SDDbgValue *SD,
                              VRBaseMapType &VRBaseMap) {
  MDNode *Var = SD->getVariable();
  const DIExpression *Expr = SD->getExpression();
  DebugLoc DL = SD->getDebugLoc();
  const MCInstrDesc &RefII = TII->get(TargetOpcode::DBG_INSTR_REF);

  // Returns true if the given operand is not a legal debug operand for a
  // DBG_INSTR_REF.
  auto IsInvalidOp = [](SDDbgOperand DbgOp) {
    return DbgOp.getKind() == SDDbgOperand::FRAMEIX;
  };
  // Returns true if the given operand is not itself an instruction reference
  // but is a legal debug operand for a DBG_INSTR_REF.
  auto IsNonInstrRefOp = [](SDDbgOperand DbgOp) {
    return DbgOp.getKind() == SDDbgOperand::CONST;
  };

  // If this variable location does not depend on any instructions or contains
  // any stack locations, produce it as a standard debug value instead.
  if (any_of(SD->getLocationOps(), IsInvalidOp) ||
      all_of(SD->getLocationOps(), IsNonInstrRefOp)) {
    if (SD->isVariadic())
      return EmitDbgValueList(SD, VRBaseMap);
    return EmitDbgValueFromSingleOp(SD, VRBaseMap);
  }

  // Immediately fold any indirectness from the LLVM-IR intrinsic into the
  // expression:
  if (SD->isIndirect())
    Expr = DIExpression::append(Expr, dwarf::DW_OP_deref);
  // If this is not already a variadic expression, it must be modified to become
  // one.
  if (!SD->isVariadic())
    Expr = DIExpression::convertToVariadicExpression(Expr);

  SmallVector<MachineOperand> MOs;

  // It may not be immediately possible to identify the MachineInstr that
  // defines a VReg, it can depend for example on the order blocks are
  // emitted in. When this happens, or when further analysis is needed later,
  // produce an instruction like this:
  //
  //    DBG_INSTR_REF !123, !456, %0:gr64
  //
  // i.e., point the instruction at the vreg, and patch it up later in
  // MachineFunction::finalizeDebugInstrRefs.
  auto AddVRegOp = [&](Register VReg) {
    MOs.push_back(MachineOperand::CreateReg(
        /* Reg */ VReg, /* isDef */ false, /* isImp */ false,
        /* isKill */ false, /* isDead */ false,
        /* isUndef */ false, /* isEarlyClobber */ false,
        /* SubReg */ 0, /* isDebug */ true));
  };
  unsigned OpCount = SD->getLocationOps().size();
  for (unsigned OpIdx = 0; OpIdx < OpCount; ++OpIdx) {
    SDDbgOperand DbgOperand = SD->getLocationOps()[OpIdx];

    // Try to find both the defined register and the instruction defining it.
    MachineInstr *DefMI = nullptr;
    Register VReg;

    if (DbgOperand.getKind() == SDDbgOperand::VREG) {
      VReg = DbgOperand.getVReg();

      // No definition means that block hasn't been emitted yet. Leave a vreg
      // reference to be fixed later.
      if (!MRI->hasOneDef(VReg)) {
        AddVRegOp(VReg);
        continue;
      }

      DefMI = &*MRI->def_instr_begin(VReg);
    } else if (DbgOperand.getKind() == SDDbgOperand::SDNODE) {
      // Look up the corresponding VReg for the given SDNode, if any.
      SDNode *Node = DbgOperand.getSDNode();
      SDValue Op = SDValue(Node, DbgOperand.getResNo());
      VRBaseMapType::iterator I = VRBaseMap.find(Op);
      // No VReg -> produce a DBG_VALUE $noreg instead.
      if (I == VRBaseMap.end())
        break;

      // Try to pick out a defining instruction at this point.
      VReg = getVR(Op, VRBaseMap);

      // Again, if there's no instruction defining the VReg right now, fix it up
      // later.
      if (!MRI->hasOneDef(VReg)) {
        AddVRegOp(VReg);
        continue;
      }

      DefMI = &*MRI->def_instr_begin(VReg);
    } else {
      assert(DbgOperand.getKind() == SDDbgOperand::CONST);
      MOs.push_back(GetMOForConstDbgOp(DbgOperand));
      continue;
    }

    // Avoid copy like instructions: they don't define values, only move them.
    // Leave a virtual-register reference until it can be fixed up later, to
    // find the underlying value definition.
    if (DefMI->isCopyLike() || TII->isCopyInstr(*DefMI)) {
      AddVRegOp(VReg);
      continue;
    }

    // Find the operand number which defines the specified VReg.
    unsigned OperandIdx = 0;
    for (const auto &MO : DefMI->operands()) {
      if (MO.isReg() && MO.isDef() && MO.getReg() == VReg)
        break;
      ++OperandIdx;
    }
    assert(OperandIdx < DefMI->getNumOperands());

    // Make the DBG_INSTR_REF refer to that instruction, and that operand.
    unsigned InstrNum = DefMI->getDebugInstrNum();
    MOs.push_back(MachineOperand::CreateDbgInstrRef(InstrNum, OperandIdx));
  }

  // If we haven't created a valid MachineOperand for every DbgOp, abort and
  // produce an undef DBG_VALUE.
  if (MOs.size() != OpCount)
    return EmitDbgNoLocation(SD);

  return BuildMI(*MF, DL, RefII, false, MOs, Var, Expr);
}

MachineInstr *InstrEmitter::EmitDbgNoLocation(SDDbgValue *SD) {
  // An invalidated SDNode must generate an undef DBG_VALUE: although the
  // original value is no longer computed, earlier DBG_VALUEs live ranges
  // must not leak into later code.
  DIVariable *Var = SD->getVariable();
  const DIExpression *Expr =
      DIExpression::convertToUndefExpression(SD->getExpression());
  DebugLoc DL = SD->getDebugLoc();
  const MCInstrDesc &Desc = TII->get(TargetOpcode::DBG_VALUE);
  return BuildMI(*MF, DL, Desc, false, 0U, Var, Expr);
}

MachineInstr *
InstrEmitter::EmitDbgValueList(SDDbgValue *SD,
                               VRBaseMapType &VRBaseMap) {
  MDNode *Var = SD->getVariable();
  DIExpression *Expr = SD->getExpression();
  DebugLoc DL = SD->getDebugLoc();
  // DBG_VALUE_LIST := "DBG_VALUE_LIST" var, expression, loc (, loc)*
  const MCInstrDesc &DbgValDesc = TII->get(TargetOpcode::DBG_VALUE_LIST);
  // Build the DBG_VALUE_LIST instruction base.
  auto MIB = BuildMI(*MF, DL, DbgValDesc);
  MIB.addMetadata(Var);
  MIB.addMetadata(Expr);
  AddDbgValueLocationOps(MIB, DbgValDesc, SD->getLocationOps(), VRBaseMap);
  return &*MIB;
}

MachineInstr *
InstrEmitter::EmitDbgValueFromSingleOp(SDDbgValue *SD,
                                       VRBaseMapType &VRBaseMap) {
  MDNode *Var = SD->getVariable();
  DIExpression *Expr = SD->getExpression();
  DebugLoc DL = SD->getDebugLoc();
  const MCInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE);

  assert(SD->getLocationOps().size() == 1 &&
         "Non variadic dbg_value should have only one location op");

  // See about constant-folding the expression.
  // Copy the location operand in case we replace it.
  SmallVector<SDDbgOperand, 1> LocationOps(1, SD->getLocationOps()[0]);
  if (Expr && LocationOps[0].getKind() == SDDbgOperand::CONST) {
    const Value *V = LocationOps[0].getConst();
    if (auto *C = dyn_cast<ConstantInt>(V)) {
      std::tie(Expr, C) = Expr->constantFold(C);
      LocationOps[0] = SDDbgOperand::fromConst(C);
    }
  }

  // Emit non-variadic dbg_value nodes as DBG_VALUE.
  // DBG_VALUE := "DBG_VALUE" loc, isIndirect, var, expr
  auto MIB = BuildMI(*MF, DL, II);
  AddDbgValueLocationOps(MIB, II, LocationOps, VRBaseMap);

  if (SD->isIndirect())
    MIB.addImm(0U);
  else
    MIB.addReg(0U);

  return MIB.addMetadata(Var).addMetadata(Expr);
}

MachineInstr *
InstrEmitter::EmitDbgLabel(SDDbgLabel *SD) {
  MDNode *Label = SD->getLabel();
  DebugLoc DL = SD->getDebugLoc();
  assert(cast<DILabel>(Label)->isValidLocationForIntrinsic(DL) &&
         "Expected inlined-at fields to agree");

  const MCInstrDesc &II = TII->get(TargetOpcode::DBG_LABEL);
  MachineInstrBuilder MIB = BuildMI(*MF, DL, II);
  MIB.addMetadata(Label);

  return &*MIB;
}

/// EmitMachineNode - Generate machine code for a target-specific node and
/// needed dependencies.
///
void InstrEmitter::
EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned,
                VRBaseMapType &VRBaseMap) {
  unsigned Opc = Node->getMachineOpcode();

  // Handle subreg insert/extract specially
  if (Opc == TargetOpcode::EXTRACT_SUBREG ||
      Opc == TargetOpcode::INSERT_SUBREG ||
      Opc == TargetOpcode::SUBREG_TO_REG) {
    EmitSubregNode(Node, VRBaseMap, IsClone, IsCloned);
    return;
  }

  // Handle COPY_TO_REGCLASS specially.
  if (Opc == TargetOpcode::COPY_TO_REGCLASS) {
    EmitCopyToRegClassNode(Node, VRBaseMap);
    return;
  }

  // Handle REG_SEQUENCE specially.
  if (Opc == TargetOpcode::REG_SEQUENCE) {
    EmitRegSequence(Node, VRBaseMap, IsClone, IsCloned);
    return;
  }

  if (Opc == TargetOpcode::IMPLICIT_DEF)
    // We want a unique VR for each IMPLICIT_DEF use.
    return;

  const MCInstrDesc &II = TII->get(Opc);
  unsigned NumResults = CountResults(Node);
  unsigned NumDefs = II.getNumDefs();
  const MCPhysReg *ScratchRegs = nullptr;

  // Handle STACKMAP and PATCHPOINT specially and then use the generic code.
  if (Opc == TargetOpcode::STACKMAP || Opc == TargetOpcode::PATCHPOINT) {
    // Stackmaps do not have arguments and do not preserve their calling
    // convention. However, to simplify runtime support, they clobber the same
    // scratch registers as AnyRegCC.
    unsigned CC = CallingConv::AnyReg;
    if (Opc == TargetOpcode::PATCHPOINT) {
      CC = Node->getConstantOperandVal(PatchPointOpers::CCPos);
      NumDefs = NumResults;
    }
    ScratchRegs = TLI->getScratchRegisters((CallingConv::ID) CC);
  } else if (Opc == TargetOpcode::STATEPOINT) {
    NumDefs = NumResults;
  }

  unsigned NumImpUses = 0;
  unsigned NodeOperands =
    countOperands(Node, II.getNumOperands() - NumDefs, NumImpUses);
  bool HasVRegVariadicDefs = !MF->getTarget().usesPhysRegsForValues() &&
                             II.isVariadic() && II.variadicOpsAreDefs();
  bool HasPhysRegOuts = NumResults > NumDefs && !II.implicit_defs().empty() &&
                        !HasVRegVariadicDefs;
#ifndef NDEBUG
  unsigned NumMIOperands = NodeOperands + NumResults;
  if (II.isVariadic())
    assert(NumMIOperands >= II.getNumOperands() &&
           "Too few operands for a variadic node!");
  else
    assert(NumMIOperands >= II.getNumOperands() &&
           NumMIOperands <=
               II.getNumOperands() + II.implicit_defs().size() + NumImpUses &&
           "#operands for dag node doesn't match .td file!");
#endif

  // Create the new machine instruction.
  MachineInstrBuilder MIB = BuildMI(*MF, Node->getDebugLoc(), II);

  // Transfer IR flags from the SDNode to the MachineInstr
  MachineInstr *MI = MIB.getInstr();
  const SDNodeFlags Flags = Node->getFlags();
  if (Flags.hasUnpredictable())
    MI->setFlag(MachineInstr::MIFlag::Unpredictable);

  // Add result register values for things that are defined by this
  // instruction.
  if (NumResults) {
    CreateVirtualRegisters(Node, MIB, II, IsClone, IsCloned, VRBaseMap);

    if (Flags.hasNoSignedZeros())
      MI->setFlag(MachineInstr::MIFlag::FmNsz);

    if (Flags.hasAllowReciprocal())
      MI->setFlag(MachineInstr::MIFlag::FmArcp);

    if (Flags.hasNoNaNs())
      MI->setFlag(MachineInstr::MIFlag::FmNoNans);

    if (Flags.hasNoInfs())
      MI->setFlag(MachineInstr::MIFlag::FmNoInfs);

    if (Flags.hasAllowContract())
      MI->setFlag(MachineInstr::MIFlag::FmContract);

    if (Flags.hasApproximateFuncs())
      MI->setFlag(MachineInstr::MIFlag::FmAfn);

    if (Flags.hasAllowReassociation())
      MI->setFlag(MachineInstr::MIFlag::FmReassoc);

    if (Flags.hasNoUnsignedWrap())
      MI->setFlag(MachineInstr::MIFlag::NoUWrap);

    if (Flags.hasNoSignedWrap())
      MI->setFlag(MachineInstr::MIFlag::NoSWrap);

    if (Flags.hasExact())
      MI->setFlag(MachineInstr::MIFlag::IsExact);

    if (Flags.hasNoFPExcept())
      MI->setFlag(MachineInstr::MIFlag::NoFPExcept);

    if (Flags.hasDisjoint())
      MI->setFlag(MachineInstr::MIFlag::Disjoint);

    if (Flags.hasSameSign())
      MI->setFlag(MachineInstr::MIFlag::SameSign);

    if (Flags.hasNoConvergent())
      MI->setFlag(MachineInstr::MIFlag::NoConvergent);
  }

  // Emit all of the actual operands of this instruction, adding them to the
  // instruction as appropriate.
  bool HasOptPRefs = NumDefs > NumResults;
  assert((!HasOptPRefs || !HasPhysRegOuts) &&
         "Unable to cope with optional defs and phys regs defs!");
  unsigned NumSkip = HasOptPRefs ? NumDefs - NumResults : 0;
  for (unsigned i = NumSkip; i != NodeOperands; ++i)
    AddOperand(MIB, Node->getOperand(i), i-NumSkip+NumDefs, &II,
               VRBaseMap, /*IsDebug=*/false, IsClone, IsCloned);

  // Add scratch registers as implicit def and early clobber
  if (ScratchRegs)
    for (unsigned i = 0; ScratchRegs[i]; ++i)
      MIB.addReg(ScratchRegs[i], RegState::ImplicitDefine |
                                 RegState::EarlyClobber);

  // Set the memory reference descriptions of this instruction now that it is
  // part of the function.
  MIB.setMemRefs(cast<MachineSDNode>(Node)->memoperands());

  // Set the CFI type.
  MIB->setCFIType(*MF, Node->getCFIType());

  // Insert the instruction into position in the block. This needs to
  // happen before any custom inserter hook is called so that the
  // hook knows where in the block to insert the replacement code.
  MBB->insert(InsertPos, MIB);

  // The MachineInstr may also define physregs instead of virtregs.  These
  // physreg values can reach other instructions in different ways:
  //
  // 1. When there is a use of a Node value beyond the explicitly defined
  //    virtual registers, we emit a CopyFromReg for one of the implicitly
  //    defined physregs.  This only happens when HasPhysRegOuts is true.
  //
  // 2. A CopyFromReg reading a physreg may be glued to this instruction.
  //
  // 3. A glued instruction may implicitly use a physreg.
  //
  // 4. A glued instruction may use a RegisterSDNode operand.
  //
  // Collect all the used physreg defs, and make sure that any unused physreg
  // defs are marked as dead.
  SmallVector<Register, 8> UsedRegs;

  // Additional results must be physical register defs.
  if (HasPhysRegOuts) {
    for (unsigned i = NumDefs; i < NumResults; ++i) {
      Register Reg = II.implicit_defs()[i - NumDefs];
      if (!Node->hasAnyUseOfValue(i))
        continue;
      // This implicitly defined physreg has a use.
      UsedRegs.push_back(Reg);
      EmitCopyFromReg(SDValue(Node, i), IsClone, Reg, VRBaseMap);
    }
  }

  // Scan the glue chain for any used physregs.
  if (Node->getValueType(Node->getNumValues()-1) == MVT::Glue) {
    for (SDNode *F = Node->getGluedUser(); F; F = F->getGluedUser()) {
      if (F->getOpcode() == ISD::CopyFromReg) {
        Register Reg = cast<RegisterSDNode>(F->getOperand(1))->getReg();
        if (Reg.isPhysical())
          UsedRegs.push_back(Reg);
        continue;
      } else if (F->getOpcode() == ISD::CopyToReg) {
        // Skip CopyToReg nodes that are internal to the glue chain.
        continue;
      }
      // Collect declared implicit uses.
      const MCInstrDesc &MCID = TII->get(F->getMachineOpcode());
      append_range(UsedRegs, MCID.implicit_uses());
      // In addition to declared implicit uses, we must also check for
      // direct RegisterSDNode operands.
      for (const SDValue &Op : F->op_values())
        if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op)) {
          Register Reg = R->getReg();
          if (Reg.isPhysical())
            UsedRegs.push_back(Reg);
        }
    }
  }

  // Add rounding control registers as implicit def for function call.
  if (II.isCall() && MF->getFunction().hasFnAttribute(Attribute::StrictFP)) {
    ArrayRef<MCPhysReg> RCRegs = TLI->getRoundingControlRegisters();
    llvm::append_range(UsedRegs, RCRegs);
  }

  // Finally mark unused registers as dead.
  if (!UsedRegs.empty() || !II.implicit_defs().empty() || II.hasOptionalDef())
    MIB->setPhysRegsDeadExcept(UsedRegs, *TRI);

  // STATEPOINT is too 'dynamic' to have meaningful machine description.
  // We have to manually tie operands.
  if (Opc == TargetOpcode::STATEPOINT && NumDefs > 0) {
    assert(!HasPhysRegOuts && "STATEPOINT mishandled");
    MachineInstr *MI = MIB;
    unsigned Def = 0;
    int First = StatepointOpers(MI).getFirstGCPtrIdx();
    assert(First > 0 && "Statepoint has Defs but no GC ptr list");
    unsigned Use = (unsigned)First;
    while (Def < NumDefs) {
      if (MI->getOperand(Use).isReg())
        MI->tieOperands(Def++, Use);
      Use = StackMaps::getNextMetaArgIdx(MI, Use);
    }
  }

  unsigned Op = Node->getNumOperands();
  if (Op != 0 && Node->getOperand(Op - 1)->getOpcode() ==
                     ~(unsigned)TargetOpcode::CONVERGENCECTRL_GLUE) {
    Register VReg = getVR(Node->getOperand(Op - 1)->getOperand(0), VRBaseMap);
    MachineOperand MO = MachineOperand::CreateReg(VReg, /*isDef=*/false,
                                                  /*isImp=*/true);
    MIB->addOperand(MO);
    Op--;
  }

  if (Op != 0 &&
      Node->getOperand(Op - 1)->getOpcode() == ISD::DEACTIVATION_SYMBOL) {
    MI->setDeactivationSymbol(
        *MF, const_cast<GlobalValue *>(
                 cast<DeactivationSymbolSDNode>(Node->getOperand(Op - 1))
                     ->getGlobal()));
    Op--;
  }

  // Run post-isel target hook to adjust this instruction if needed.
  if (II.hasPostISelHook())
    TLI->AdjustInstrPostInstrSelection(*MIB, Node);
}

/// EmitSpecialNode - Generate machine code for a target-independent node and
/// needed dependencies.
void InstrEmitter::
EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned,
                VRBaseMapType &VRBaseMap) {
  switch (Node->getOpcode()) {
  default:
#ifndef NDEBUG
    Node->dump();
#endif
    llvm_unreachable("This target-independent node should have been selected!");
  case ISD::EntryToken:
  case ISD::MERGE_VALUES:
  case ISD::TokenFactor:
  case ISD::DEACTIVATION_SYMBOL:
    break;
  case ISD::CopyToReg: {
    Register DestReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
    SDValue SrcVal = Node->getOperand(2);
    if (DestReg.isVirtual() && SrcVal.isMachineOpcode() &&
        SrcVal.getMachineOpcode() == TargetOpcode::IMPLICIT_DEF) {
      // Instead building a COPY to that vreg destination, build an
      // IMPLICIT_DEF instruction instead.
      BuildMI(*MBB, InsertPos, Node->getDebugLoc(),
              TII->get(TargetOpcode::IMPLICIT_DEF), DestReg);
      break;
    }
    Register SrcReg;
    if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(SrcVal))
      SrcReg = R->getReg();
    else
      SrcReg = getVR(SrcVal, VRBaseMap);

    if (SrcReg == DestReg) // Coalesced away the copy? Ignore.
      break;

    BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TargetOpcode::COPY),
            DestReg).addReg(SrcReg);
    break;
  }
  case ISD::CopyFromReg: {
    Register SrcReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
    EmitCopyFromReg(SDValue(Node, 0), IsClone, SrcReg, VRBaseMap);
    break;
  }
  case ISD::EH_LABEL:
  case ISD::ANNOTATION_LABEL: {
    unsigned Opc = (Node->getOpcode() == ISD::EH_LABEL)
                       ? TargetOpcode::EH_LABEL
                       : TargetOpcode::ANNOTATION_LABEL;
    MCSymbol *S = cast<LabelSDNode>(Node)->getLabel();
    BuildMI(*MBB, InsertPos, Node->getDebugLoc(),
            TII->get(Opc)).addSym(S);
    break;
  }

  case ISD::LIFETIME_START:
  case ISD::LIFETIME_END: {
    unsigned TarOp = (Node->getOpcode() == ISD::LIFETIME_START)
                         ? TargetOpcode::LIFETIME_START
                         : TargetOpcode::LIFETIME_END;
    auto *FI = cast<FrameIndexSDNode>(Node->getOperand(1));
    BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TarOp))
    .addFrameIndex(FI->getIndex());
    break;
  }

  case ISD::PSEUDO_PROBE: {
    unsigned TarOp = TargetOpcode::PSEUDO_PROBE;
    auto Guid = cast<PseudoProbeSDNode>(Node)->getGuid();
    auto Index = cast<PseudoProbeSDNode>(Node)->getIndex();
    auto Attr = cast<PseudoProbeSDNode>(Node)->getAttributes();

    BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TarOp))
        .addImm(Guid)
        .addImm(Index)
        .addImm((uint8_t)PseudoProbeType::Block)
        .addImm(Attr);
    break;
  }

  case ISD::INLINEASM:
  case ISD::INLINEASM_BR: {
    unsigned NumOps = Node->getNumOperands();
    if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue)
      --NumOps;  // Ignore the glue operand.

    // Create the inline asm machine instruction.
    unsigned TgtOpc = Node->getOpcode() == ISD::INLINEASM_BR
                          ? TargetOpcode::INLINEASM_BR
                          : TargetOpcode::INLINEASM;
    MachineInstrBuilder MIB =
        BuildMI(*MF, Node->getDebugLoc(), TII->get(TgtOpc));

    // Add the asm string as an external symbol operand.
    SDValue AsmStrV = Node->getOperand(InlineAsm::Op_AsmString);
    const char *AsmStr = cast<ExternalSymbolSDNode>(AsmStrV)->getSymbol();
    MIB.addExternalSymbol(AsmStr);

    // Add the HasSideEffect, isAlignStack, AsmDialect, MayLoad and MayStore
    // bits.
    int64_t ExtraInfo =
      cast<ConstantSDNode>(Node->getOperand(InlineAsm::Op_ExtraInfo))->
                          getZExtValue();
    MIB.addImm(ExtraInfo);

    // Remember to operand index of the group flags.
    SmallVector<unsigned, 8> GroupIdx;

    // Remember registers that are part of early-clobber defs.
    SmallVector<Register, 8> ECRegs;

    // Add all of the operand registers to the instruction.
    for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
      unsigned Flags = Node->getConstantOperandVal(i);
      const InlineAsm::Flag F(Flags);
      const unsigned NumVals = F.getNumOperandRegisters();

      GroupIdx.push_back(MIB->getNumOperands());
      MIB.addImm(Flags);
      ++i;  // Skip the ID value.

      switch (F.getKind()) {
      case InlineAsm::Kind::RegDef:
        for (unsigned j = 0; j != NumVals; ++j, ++i) {
          Register Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
          // FIXME: Add dead flags for physical and virtual registers defined.
          // For now, mark physical register defs as implicit to help fast
          // regalloc. This makes inline asm look a lot like calls.
          MIB.addReg(Reg, RegState::Define | getImplRegState(Reg.isPhysical()));
        }
        break;
      case InlineAsm::Kind::RegDefEarlyClobber:
      case InlineAsm::Kind::Clobber:
        for (unsigned j = 0; j != NumVals; ++j, ++i) {
          Register Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
          MIB.addReg(Reg, RegState::Define | RegState::EarlyClobber |
                              getImplRegState(Reg.isPhysical()));
          ECRegs.push_back(Reg);
        }
        break;
      case InlineAsm::Kind::RegUse: // Use of register.
      case InlineAsm::Kind::Imm:    // Immediate.
      case InlineAsm::Kind::Mem:    // Non-function addressing mode.
        // The addressing mode has been selected, just add all of the
        // operands to the machine instruction.
        for (unsigned j = 0; j != NumVals; ++j, ++i)
          AddOperand(MIB, Node->getOperand(i), 0, nullptr, VRBaseMap,
                     /*IsDebug=*/false, IsClone, IsCloned);

        // Manually set isTied bits.
        if (F.isRegUseKind()) {
          unsigned DefGroup;
          if (F.isUseOperandTiedToDef(DefGroup)) {
            unsigned DefIdx = GroupIdx[DefGroup] + 1;
            unsigned UseIdx = GroupIdx.back() + 1;
            for (unsigned j = 0; j != NumVals; ++j)
              MIB->tieOperands(DefIdx + j, UseIdx + j);
          }
        }
        break;
      case InlineAsm::Kind::Func: // Function addressing mode.
        for (unsigned j = 0; j != NumVals; ++j, ++i) {
          SDValue Op = Node->getOperand(i);
          AddOperand(MIB, Op, 0, nullptr, VRBaseMap,
                     /*IsDebug=*/false, IsClone, IsCloned);

          // Adjust Target Flags for function reference.
          if (auto *TGA = dyn_cast<GlobalAddressSDNode>(Op)) {
            unsigned NewFlags =
                MF->getSubtarget().classifyGlobalFunctionReference(
                    TGA->getGlobal());
            unsigned LastIdx = MIB.getInstr()->getNumOperands() - 1;
            MIB.getInstr()->getOperand(LastIdx).setTargetFlags(NewFlags);
          }
        }
      }
    }

    // GCC inline assembly allows input operands to also be early-clobber
    // output operands (so long as the operand is written only after it's
    // used), but this does not match the semantics of our early-clobber flag.
    // If an early-clobber operand register is also an input operand register,
    // then remove the early-clobber flag.
    for (Register Reg : ECRegs) {
      if (MIB->readsRegister(Reg, TRI)) {
        MachineOperand *MO =
            MIB->findRegisterDefOperand(Reg, TRI, false, false);
        assert(MO && "No def operand for clobbered register?");
        MO->setIsEarlyClobber(false);
      }
    }

    // Get the mdnode from the asm if it exists and add it to the instruction.
    SDValue MDV = Node->getOperand(InlineAsm::Op_MDNode);
    const MDNode *MD = cast<MDNodeSDNode>(MDV)->getMD();
    if (MD)
      MIB.addMetadata(MD);

    // Add rounding control registers as implicit def for inline asm.
    if (MF->getFunction().hasFnAttribute(Attribute::StrictFP)) {
      ArrayRef<MCPhysReg> RCRegs = TLI->getRoundingControlRegisters();
      for (MCPhysReg Reg : RCRegs)
        MIB.addReg(Reg, RegState::ImplicitDefine);
    }

    MBB->insert(InsertPos, MIB);
    break;
  }
  }
}

/// InstrEmitter - Construct an InstrEmitter and set it to start inserting
/// at the given position in the given block.
InstrEmitter::InstrEmitter(const TargetMachine &TM, MachineBasicBlock *mbb,
                           MachineBasicBlock::iterator insertpos)
    : MF(mbb->getParent()), MRI(&MF->getRegInfo()),
      TII(MF->getSubtarget().getInstrInfo()),
      TRI(MF->getSubtarget().getRegisterInfo()),
      TLI(MF->getSubtarget().getTargetLowering()), MBB(mbb),
      InsertPos(insertpos) {
  EmitDebugInstrRefs = mbb->getParent()->useDebugInstrRef();
}
