diff options
Diffstat (limited to 'contrib/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp')
| -rw-r--r-- | contrib/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 474 | 
1 files changed, 404 insertions, 70 deletions
diff --git a/contrib/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/contrib/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index eb25b6ca268f..1d0d3dffa4c5 100644 --- a/contrib/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/contrib/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -24,97 +24,132 @@  #include <sstream> -#define DEBUG_TYPE "legalize-mir" +#define DEBUG_TYPE "legalizer"  using namespace llvm;  LegalizerHelper::LegalizerHelper(MachineFunction &MF) -  : MRI(MF.getRegInfo()) { +    : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) {    MIRBuilder.setMF(MF);  }  LegalizerHelper::LegalizeResult -LegalizerHelper::legalizeInstrStep(MachineInstr &MI, -                                   const LegalizerInfo &LegalizerInfo) { -  auto Action = LegalizerInfo.getAction(MI, MRI); +LegalizerHelper::legalizeInstrStep(MachineInstr &MI) { +  DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs())); + +  auto Action = LI.getAction(MI, MRI);    switch (std::get<0>(Action)) {    case LegalizerInfo::Legal: +    DEBUG(dbgs() << ".. Already legal\n");      return AlreadyLegal;    case LegalizerInfo::Libcall: +    DEBUG(dbgs() << ".. Convert to libcall\n");      return libcall(MI);    case LegalizerInfo::NarrowScalar: +    DEBUG(dbgs() << ".. Narrow scalar\n");      return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));    case LegalizerInfo::WidenScalar: +    DEBUG(dbgs() << ".. Widen scalar\n");      return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));    case LegalizerInfo::Lower: +    DEBUG(dbgs() << ".. Lower\n");      return lower(MI, std::get<1>(Action), std::get<2>(Action));    case LegalizerInfo::FewerElements: +    DEBUG(dbgs() << ".. Reduce number of elements\n");      return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action)); +  case LegalizerInfo::Custom: +    DEBUG(dbgs() << ".. Custom legalization\n"); +    return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized +                                                  : UnableToLegalize;    default: +    DEBUG(dbgs() << ".. Unable to legalize\n");      return UnableToLegalize;    }  } -LegalizerHelper::LegalizeResult -LegalizerHelper::legalizeInstr(MachineInstr &MI, -                               const LegalizerInfo &LegalizerInfo) { -  SmallVector<MachineInstr *, 4> WorkList; -  MIRBuilder.recordInsertions( -      [&](MachineInstr *MI) { WorkList.push_back(MI); }); -  WorkList.push_back(&MI); - -  bool Changed = false; -  LegalizeResult Res; -  unsigned Idx = 0; -  do { -    Res = legalizeInstrStep(*WorkList[Idx], LegalizerInfo); -    if (Res == UnableToLegalize) { -      MIRBuilder.stopRecordingInsertions(); -      return UnableToLegalize; -    } -    Changed |= Res == Legalized; -    ++Idx; -  } while (Idx < WorkList.size()); - -  MIRBuilder.stopRecordingInsertions(); - -  return Changed ? Legalized : AlreadyLegal; -} -  void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,                                     SmallVectorImpl<unsigned> &VRegs) { -  unsigned Size = Ty.getSizeInBits(); -  SmallVector<uint64_t, 4> Indexes; -  for (int i = 0; i < NumParts; ++i) { +  for (int i = 0; i < NumParts; ++i)      VRegs.push_back(MRI.createGenericVirtualRegister(Ty)); -    Indexes.push_back(i * Size); +  MIRBuilder.buildUnmerge(VRegs, Reg); +} + +static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { +  switch (Opcode) { +  case TargetOpcode::G_SDIV: +    assert(Size == 32 && "Unsupported size"); +    return RTLIB::SDIV_I32; +  case TargetOpcode::G_UDIV: +    assert(Size == 32 && "Unsupported size"); +    return RTLIB::UDIV_I32; +  case TargetOpcode::G_SREM: +    assert(Size == 32 && "Unsupported size"); +    return RTLIB::SREM_I32; +  case TargetOpcode::G_UREM: +    assert(Size == 32 && "Unsupported size"); +    return RTLIB::UREM_I32; +  case TargetOpcode::G_FADD: +    assert((Size == 32 || Size == 64) && "Unsupported size"); +    return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32; +  case TargetOpcode::G_FREM: +    return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32; +  case TargetOpcode::G_FPOW: +    return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;    } -  MIRBuilder.buildExtract(VRegs, Indexes, Reg); +  llvm_unreachable("Unknown libcall function"); +} + +LegalizerHelper::LegalizeResult llvm::replaceWithLibcall( +    MachineInstr &MI, MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, +    const CallLowering::ArgInfo &Result, ArrayRef<CallLowering::ArgInfo> Args) { +  auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); +  auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); +  const char *Name = TLI.getLibcallName(Libcall); +  MIRBuilder.getMF().getFrameInfo().setHasCalls(true); +  MIRBuilder.setInstr(MI); +  if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall), +                     MachineOperand::CreateES(Name), Result, Args)) +    return LegalizerHelper::UnableToLegalize; + +  // We're about to remove MI, so move the insert point after it. +  MIRBuilder.setInsertPt(MIRBuilder.getMBB(), +                         std::next(MIRBuilder.getInsertPt())); + +  MI.eraseFromParent(); +  return LegalizerHelper::Legalized; +} + +static LegalizerHelper::LegalizeResult +simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, +              Type *OpType) { +  auto Libcall = getRTLibDesc(MI.getOpcode(), Size); +  return replaceWithLibcall(MI, MIRBuilder, Libcall, +                            {MI.getOperand(0).getReg(), OpType}, +                            {{MI.getOperand(1).getReg(), OpType}, +                             {MI.getOperand(2).getReg(), OpType}});  }  LegalizerHelper::LegalizeResult  LegalizerHelper::libcall(MachineInstr &MI) { -  LLT Ty = MRI.getType(MI.getOperand(0).getReg()); -  unsigned Size = Ty.getSizeInBits(); -  MIRBuilder.setInstr(MI); +  LLT LLTy = MRI.getType(MI.getOperand(0).getReg()); +  unsigned Size = LLTy.getSizeInBits(); +  auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();    switch (MI.getOpcode()) {    default:      return UnableToLegalize; +  case TargetOpcode::G_SDIV: +  case TargetOpcode::G_UDIV: +  case TargetOpcode::G_SREM: +  case TargetOpcode::G_UREM: { +    Type *HLTy = Type::getInt32Ty(Ctx); +    return simpleLibcall(MI, MIRBuilder, Size, HLTy); +  } +  case TargetOpcode::G_FADD: +  case TargetOpcode::G_FPOW:    case TargetOpcode::G_FREM: { -    auto &Ctx = MIRBuilder.getMF().getFunction()->getContext(); -    Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx); -    auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); -    auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); -    const char *Name = -        TLI.getLibcallName(Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32); - -    CLI.lowerCall( -        MIRBuilder, MachineOperand::CreateES(Name), -        {MI.getOperand(0).getReg(), Ty}, -        {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}}); -    MI.eraseFromParent(); -    return Legalized; +    Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx); +    return simpleLibcall(MI, MIRBuilder, Size, HLTy);    }    }  } @@ -125,19 +160,18 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,    // FIXME: Don't know how to handle secondary types yet.    if (TypeIdx != 0)      return UnableToLegalize; + +  MIRBuilder.setInstr(MI); +    switch (MI.getOpcode()) {    default:      return UnableToLegalize;    case TargetOpcode::G_ADD: {      // Expand in terms of carry-setting/consuming G_ADDE instructions. -    unsigned NarrowSize = NarrowTy.getSizeInBits();      int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /                     NarrowTy.getSizeInBits(); -    MIRBuilder.setInstr(MI); -      SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; -    SmallVector<uint64_t, 2> Indexes;      extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);      extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); @@ -152,11 +186,141 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,                              Src2Regs[i], CarryIn);        DstRegs.push_back(DstReg); -      Indexes.push_back(i * NarrowSize);        CarryIn = CarryOut;      }      unsigned DstReg = MI.getOperand(0).getReg(); -    MIRBuilder.buildSequence(DstReg, DstRegs, Indexes); +    MIRBuilder.buildMerge(DstReg, DstRegs); +    MI.eraseFromParent(); +    return Legalized; +  } +  case TargetOpcode::G_INSERT: { +    if (TypeIdx != 0) +      return UnableToLegalize; + +    int64_t NarrowSize = NarrowTy.getSizeInBits(); +    int NumParts = +        MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; + +    SmallVector<unsigned, 2> SrcRegs, DstRegs; +    SmallVector<uint64_t, 2> Indexes; +    extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); + +    unsigned OpReg = MI.getOperand(2).getReg(); +    int64_t OpStart = MI.getOperand(3).getImm(); +    int64_t OpSize = MRI.getType(OpReg).getSizeInBits(); +    for (int i = 0; i < NumParts; ++i) { +      unsigned DstStart = i * NarrowSize; + +      if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) { +        // No part of the insert affects this subregister, forward the original. +        DstRegs.push_back(SrcRegs[i]); +        continue; +      } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) { +        // The entire subregister is defined by this insert, forward the new +        // value. +        DstRegs.push_back(OpReg); +        continue; +      } + +      // OpSegStart is where this destination segment would start in OpReg if it +      // extended infinitely in both directions. +      int64_t ExtractOffset, InsertOffset, SegSize; +      if (OpStart < DstStart) { +        InsertOffset = 0; +        ExtractOffset = DstStart - OpStart; +        SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart); +      } else { +        InsertOffset = OpStart - DstStart; +        ExtractOffset = 0; +        SegSize = +            std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart); +      } + +      unsigned SegReg = OpReg; +      if (ExtractOffset != 0 || SegSize != OpSize) { +        // A genuine extract is needed. +        SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); +        MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset); +      } + +      unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); +      MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset); +      DstRegs.push_back(DstReg); +    } + +    assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered"); +    MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); +    MI.eraseFromParent(); +    return Legalized; +  } +  case TargetOpcode::G_LOAD: { +    unsigned NarrowSize = NarrowTy.getSizeInBits(); +    int NumParts = +        MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; +    LLT OffsetTy = LLT::scalar( +        MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits()); + +    SmallVector<unsigned, 2> DstRegs; +    for (int i = 0; i < NumParts; ++i) { +      unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); +      unsigned SrcReg = 0; +      unsigned Adjustment = i * NarrowSize / 8; + +      MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy, +                                Adjustment); + +      // TODO: This is conservatively correct, but we probably want to split the +      // memory operands in the future. +      MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin()); + +      DstRegs.push_back(DstReg); +    } +    unsigned DstReg = MI.getOperand(0).getReg(); +    MIRBuilder.buildMerge(DstReg, DstRegs); +    MI.eraseFromParent(); +    return Legalized; +  } +  case TargetOpcode::G_STORE: { +    unsigned NarrowSize = NarrowTy.getSizeInBits(); +    int NumParts = +        MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; +    LLT OffsetTy = LLT::scalar( +        MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits()); + +    SmallVector<unsigned, 2> SrcRegs; +    extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs); + +    for (int i = 0; i < NumParts; ++i) { +      unsigned DstReg = 0; +      unsigned Adjustment = i * NarrowSize / 8; + +      MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy, +                                Adjustment); + +      // TODO: This is conservatively correct, but we probably want to split the +      // memory operands in the future. +      MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin()); +    } +    MI.eraseFromParent(); +    return Legalized; +  } +  case TargetOpcode::G_CONSTANT: { +    unsigned NarrowSize = NarrowTy.getSizeInBits(); +    int NumParts = +        MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; +    const APInt &Cst = MI.getOperand(1).getCImm()->getValue(); +    LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext(); + +    SmallVector<unsigned, 2> DstRegs; +    for (int i = 0; i < NumParts; ++i) { +      unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); +      ConstantInt *CI = +          ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize)); +      MIRBuilder.buildConstant(DstReg, *CI); +      DstRegs.push_back(DstReg); +    } +    unsigned DstReg = MI.getOperand(0).getReg(); +    MIRBuilder.buildMerge(DstReg, DstRegs);      MI.eraseFromParent();      return Legalized;    } @@ -175,7 +339,8 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {    case TargetOpcode::G_MUL:    case TargetOpcode::G_OR:    case TargetOpcode::G_XOR: -  case TargetOpcode::G_SUB: { +  case TargetOpcode::G_SUB: +  case TargetOpcode::G_SHL: {      // Perform operation at larger width (any extension is fine here, high bits      // don't affect the result) and then truncate the result back to the      // original type. @@ -195,10 +360,13 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {      return Legalized;    }    case TargetOpcode::G_SDIV: -  case TargetOpcode::G_UDIV: { -    unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV -                          ? TargetOpcode::G_SEXT -                          : TargetOpcode::G_ZEXT; +  case TargetOpcode::G_UDIV: +  case TargetOpcode::G_ASHR: +  case TargetOpcode::G_LSHR: { +    unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV || +                             MI.getOpcode() == TargetOpcode::G_ASHR +                         ? TargetOpcode::G_SEXT +                         : TargetOpcode::G_ZEXT;      unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);      MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse( @@ -218,6 +386,85 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {      MI.eraseFromParent();      return Legalized;    } +  case TargetOpcode::G_SELECT: { +    if (TypeIdx != 0) +      return UnableToLegalize; + +    // Perform operation at larger width (any extension is fine here, high bits +    // don't affect the result) and then truncate the result back to the +    // original type. +    unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy); +    unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy); +    MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg()); +    MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg()); + +    unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); +    MIRBuilder.buildInstr(TargetOpcode::G_SELECT) +        .addDef(DstExt) +        .addReg(MI.getOperand(1).getReg()) +        .addUse(Src1Ext) +        .addUse(Src2Ext); + +    MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); +    MI.eraseFromParent(); +    return Legalized; +  } +  case TargetOpcode::G_FPTOSI: +  case TargetOpcode::G_FPTOUI: { +    if (TypeIdx != 0) +      return UnableToLegalize; + +    unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); +    MIRBuilder.buildInstr(MI.getOpcode()) +        .addDef(DstExt) +        .addUse(MI.getOperand(1).getReg()); + +    MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); +    MI.eraseFromParent(); +    return Legalized; +  } +  case TargetOpcode::G_SITOFP: +  case TargetOpcode::G_UITOFP: { +    if (TypeIdx != 1) +      return UnableToLegalize; + +    unsigned Src = MI.getOperand(1).getReg(); +    unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); + +    if (MI.getOpcode() == TargetOpcode::G_SITOFP) { +      MIRBuilder.buildSExt(SrcExt, Src); +    } else { +      assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op"); +      MIRBuilder.buildZExt(SrcExt, Src); +    } + +    MIRBuilder.buildInstr(MI.getOpcode()) +        .addDef(MI.getOperand(0).getReg()) +        .addUse(SrcExt); + +    MI.eraseFromParent(); +    return Legalized; +  } +  case TargetOpcode::G_INSERT: { +    if (TypeIdx != 0) +      return UnableToLegalize; + +    unsigned Src = MI.getOperand(1).getReg(); +    unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); +    MIRBuilder.buildAnyExt(SrcExt, Src); + +    unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); +    auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(), +                                      MI.getOperand(3).getImm()); +    for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) { +      MIB.addReg(MI.getOperand(OpNum).getReg()); +      MIB.addImm(MI.getOperand(OpNum + 1).getImm()); +    } + +    MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); +    MI.eraseFromParent(); +    return Legalized; +  }    case TargetOpcode::G_LOAD: {      assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==                 WideTy.getSizeInBits() && @@ -231,12 +478,24 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {      return Legalized;    }    case TargetOpcode::G_STORE: { -    assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) == -               WideTy.getSizeInBits() && -           "illegal to increase number of bytes modified by a store"); +    if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) || +        WideTy != LLT::scalar(8)) +      return UnableToLegalize; + +    auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); +    auto Content = TLI.getBooleanContents(false, false); + +    unsigned ExtOp = TargetOpcode::G_ANYEXT; +    if (Content == TargetLoweringBase::ZeroOrOneBooleanContent) +      ExtOp = TargetOpcode::G_ZEXT; +    else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent) +      ExtOp = TargetOpcode::G_SEXT; +    else +      ExtOp = TargetOpcode::G_ANYEXT;      unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); -    MIRBuilder.buildAnyExt(SrcExt, MI.getOperand(0).getReg()); +    MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse( +        MI.getOperand(0).getReg());      MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),                            **MI.memoperands_begin());      MI.eraseFromParent(); @@ -315,6 +574,83 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {      MI.eraseFromParent();      return Legalized;    } +  case TargetOpcode::G_SMULO: +  case TargetOpcode::G_UMULO: { +    // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the +    // result. +    unsigned Res = MI.getOperand(0).getReg(); +    unsigned Overflow = MI.getOperand(1).getReg(); +    unsigned LHS = MI.getOperand(2).getReg(); +    unsigned RHS = MI.getOperand(3).getReg(); + +    MIRBuilder.buildMul(Res, LHS, RHS); + +    unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO +                          ? TargetOpcode::G_SMULH +                          : TargetOpcode::G_UMULH; + +    unsigned HiPart = MRI.createGenericVirtualRegister(Ty); +    MIRBuilder.buildInstr(Opcode) +      .addDef(HiPart) +      .addUse(LHS) +      .addUse(RHS); + +    unsigned Zero = MRI.createGenericVirtualRegister(Ty); +    MIRBuilder.buildConstant(Zero, 0); +    MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero); +    MI.eraseFromParent(); +    return Legalized; +  } +  case TargetOpcode::G_FNEG: { +    // TODO: Handle vector types once we are able to +    // represent them. +    if (Ty.isVector()) +      return UnableToLegalize; +    unsigned Res = MI.getOperand(0).getReg(); +    Type *ZeroTy; +    LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext(); +    switch (Ty.getSizeInBits()) { +    case 16: +      ZeroTy = Type::getHalfTy(Ctx); +      break; +    case 32: +      ZeroTy = Type::getFloatTy(Ctx); +      break; +    case 64: +      ZeroTy = Type::getDoubleTy(Ctx); +      break; +    default: +      llvm_unreachable("unexpected floating-point type"); +    } +    ConstantFP &ZeroForNegation = +        *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy)); +    unsigned Zero = MRI.createGenericVirtualRegister(Ty); +    MIRBuilder.buildFConstant(Zero, ZeroForNegation); +    MIRBuilder.buildInstr(TargetOpcode::G_FSUB) +        .addDef(Res) +        .addUse(Zero) +        .addUse(MI.getOperand(1).getReg()); +    MI.eraseFromParent(); +    return Legalized; +  } +  case TargetOpcode::G_FSUB: { +    // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)). +    // First, check if G_FNEG is marked as Lower. If so, we may +    // end up with an infinite loop as G_FSUB is used to legalize G_FNEG. +    if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower) +      return UnableToLegalize; +    unsigned Res = MI.getOperand(0).getReg(); +    unsigned LHS = MI.getOperand(1).getReg(); +    unsigned RHS = MI.getOperand(2).getReg(); +    unsigned Neg = MRI.createGenericVirtualRegister(Ty); +    MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS); +    MIRBuilder.buildInstr(TargetOpcode::G_FADD) +        .addDef(Res) +        .addUse(LHS) +        .addUse(Neg); +    MI.eraseFromParent(); +    return Legalized; +  }    }  } @@ -335,7 +671,6 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,      MIRBuilder.setInstr(MI);      SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; -    SmallVector<uint64_t, 2> Indexes;      extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);      extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); @@ -343,10 +678,9 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,        unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);        MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);        DstRegs.push_back(DstReg); -      Indexes.push_back(i * NarrowSize);      } -    MIRBuilder.buildSequence(DstReg, DstRegs, Indexes); +    MIRBuilder.buildMerge(DstReg, DstRegs);      MI.eraseFromParent();      return Legalized;    }  | 
