diff options
Diffstat (limited to 'llvm/lib/Target/Mips')
62 files changed, 1364 insertions, 710 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 21d0df74d458..e467ed36938b 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -126,13 +126,16 @@ const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = { Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6, Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3, Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips, - Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008 + Mips::FeatureCnMipsP, Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, + Mips::FeatureNaN2008 }; namespace { class MipsAsmParser : public MCTargetAsmParser { MipsTargetStreamer &getTargetStreamer() { + assert(getParser().getStreamer().getTargetStreamer() && + "do not have a target streamer"); MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); return static_cast<MipsTargetStreamer &>(TS); } @@ -251,8 +254,10 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); - void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, bool IsLoad); + void expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, bool IsLoad); + void expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, bool IsLoad); bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); @@ -330,12 +335,14 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); + bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool reportParseError(Twine ErrorMsg); bool reportParseError(SMLoc Loc, Twine ErrorMsg); bool parseMemOffset(const MCExpr *&Res, bool isParenExpr); - bool isEvaluated(const MCExpr *Expr); bool parseSetMips0Directive(); bool parseSetArchDirective(); bool parseSetFeature(uint64_t Feature); @@ -558,6 +565,19 @@ public: return getSTI().getFeatureBits()[Mips::FeatureFP64Bit]; } + bool isJalrRelocAvailable(const MCExpr *JalExpr) { + if (!EmitJalrReloc) + return false; + MCValue Res; + if (!JalExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) + return false; + if (Res.getSymB() != nullptr) + return false; + if (Res.getConstant() != 0) + return ABI.IsN32() || ABI.IsN64(); + return true; + } + const MipsABIInfo &getABI() const { return ABI; } bool isABI_N32() const { return ABI.IsN32(); } bool isABI_N64() const { return ABI.IsN64(); } @@ -654,6 +674,10 @@ public: return (getSTI().getFeatureBits()[Mips::FeatureCnMips]); } + bool hasCnMipsP() const { + return (getSTI().getFeatureBits()[Mips::FeatureCnMipsP]); + } + bool inPicMode() { return IsPicEnabled; } @@ -1295,8 +1319,6 @@ public: } // Allow relocation operators. - // FIXME: This predicate and others need to look through binary expressions - // and determine whether a Value is a constant or not. template <unsigned Bits, unsigned ShiftAmount = 0> bool isMemWithSimmOffset() const { if (!isMem()) @@ -1777,17 +1799,71 @@ static unsigned countMCSymbolRefExpr(const MCExpr *Expr) { return 0; } +static bool isEvaluated(const MCExpr *Expr) { + switch (Expr->getKind()) { + case MCExpr::Constant: + return true; + case MCExpr::SymbolRef: + return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None); + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); + if (!isEvaluated(BE->getLHS())) + return false; + return isEvaluated(BE->getRHS()); + } + case MCExpr::Unary: + return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr()); + case MCExpr::Target: + return true; + } + return false; +} + +static bool needsExpandMemInst(MCInst &Inst) { + const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); + + unsigned NumOp = MCID.getNumOperands(); + if (NumOp != 3 && NumOp != 4) + return false; + + const MCOperandInfo &OpInfo = MCID.OpInfo[NumOp - 1]; + if (OpInfo.OperandType != MCOI::OPERAND_MEMORY && + OpInfo.OperandType != MCOI::OPERAND_UNKNOWN && + OpInfo.OperandType != MipsII::OPERAND_MEM_SIMM9) + return false; + + MCOperand &Op = Inst.getOperand(NumOp - 1); + if (Op.isImm()) { + if (OpInfo.OperandType == MipsII::OPERAND_MEM_SIMM9) + return !isInt<9>(Op.getImm()); + // Offset can't exceed 16bit value. + return !isInt<16>(Op.getImm()); + } + + if (Op.isExpr()) { + const MCExpr *Expr = Op.getExpr(); + if (Expr->getKind() != MCExpr::SymbolRef) + return !isEvaluated(Expr); + + // Expand symbol. + const MCSymbolRefExpr *SR = static_cast<const MCSymbolRefExpr *>(Expr); + return SR->getKind() == MCSymbolRefExpr::VK_None; + } + + return false; +} + bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { MipsTargetStreamer &TOut = getTargetStreamer(); - const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); + const unsigned Opcode = Inst.getOpcode(); + const MCInstrDesc &MCID = getInstDesc(Opcode); bool ExpandedJalSym = false; Inst.setLoc(IDLoc); if (MCID.isBranch() || MCID.isCall()) { - const unsigned Opcode = Inst.getOpcode(); MCOperand Offset; switch (Opcode) { @@ -1901,14 +1977,13 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, // SSNOP is deprecated on MIPS32r6/MIPS64r6 // We still accept it but it is a normal nop. - if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) { + if (hasMips32r6() && Opcode == Mips::SSNOP) { std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6"; Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a " "nop instruction"); } if (hasCnMips()) { - const unsigned Opcode = Inst.getOpcode(); MCOperand Opnd; int Imm; @@ -1958,7 +2033,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, // not in the operands. unsigned FirstOp = 1; unsigned SecondOp = 2; - switch (Inst.getOpcode()) { + switch (Opcode) { default: break; case Mips::SDivIMacro: @@ -2004,8 +2079,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } // For PIC code convert unconditional jump to unconditional branch. - if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) && - inPicMode()) { + if ((Opcode == Mips::J || Opcode == Mips::J_MM) && inPicMode()) { MCInst BInst; BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ); BInst.addOperand(MCOperand::createReg(Mips::ZERO)); @@ -2016,8 +2090,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, // This expansion is not in a function called by tryExpandInstruction() // because the pseudo-instruction doesn't have a distinct opcode. - if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) && - inPicMode()) { + if ((Opcode == Mips::JAL || Opcode == Mips::JAL_MM) && inPicMode()) { warnIfNoMacro(IDLoc); const MCExpr *JalExpr = Inst.getOperand(0).getExpr(); @@ -2031,62 +2104,19 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, // of the assembler. We ought to leave it to those later stages. const MCSymbol *JalSym = getSingleMCSymbol(JalExpr); - // FIXME: Add support for label+offset operands (currently causes an error). - // FIXME: Add support for forward-declared local symbols. - // FIXME: Add expansion for when the LargeGOT option is enabled. - if (JalSym->isInSection() || JalSym->isTemporary() || - (JalSym->isELF() && - cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) { - if (isABI_O32()) { - // If it's a local symbol and the O32 ABI is being used, we expand to: - // lw $25, 0($gp) - // R_(MICRO)MIPS_GOT16 label - // addiu $25, $25, 0 - // R_(MICRO)MIPS_LO16 label - // jalr $25 - const MCExpr *Got16RelocExpr = - MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext()); - const MCExpr *Lo16RelocExpr = - MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext()); - - TOut.emitRRX(Mips::LW, Mips::T9, GPReg, - MCOperand::createExpr(Got16RelocExpr), IDLoc, STI); - TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9, - MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI); - } else if (isABI_N32() || isABI_N64()) { - // If it's a local symbol and the N32/N64 ABIs are being used, - // we expand to: - // lw/ld $25, 0($gp) - // R_(MICRO)MIPS_GOT_DISP label - // jalr $25 - const MCExpr *GotDispRelocExpr = - MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext()); - - TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, - GPReg, MCOperand::createExpr(GotDispRelocExpr), IDLoc, - STI); - } - } else { - // If it's an external/weak symbol, we expand to: - // lw/ld $25, 0($gp) - // R_(MICRO)MIPS_CALL16 label - // jalr $25 - const MCExpr *Call16RelocExpr = - MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext()); - - TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, GPReg, - MCOperand::createExpr(Call16RelocExpr), IDLoc, STI); - } + if (expandLoadAddress(Mips::T9, Mips::NoRegister, Inst.getOperand(0), + !isGP64bit(), IDLoc, Out, STI)) + return true; MCInst JalrInst; - if (IsCpRestoreSet && inMicroMipsMode()) - JalrInst.setOpcode(Mips::JALRS_MM); + if (inMicroMipsMode()) + JalrInst.setOpcode(IsCpRestoreSet ? Mips::JALRS_MM : Mips::JALR_MM); else - JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); + JalrInst.setOpcode(Mips::JALR); JalrInst.addOperand(MCOperand::createReg(Mips::RA)); JalrInst.addOperand(MCOperand::createReg(Mips::T9)); - if (EmitJalrReloc) { + if (isJalrRelocAvailable(JalExpr)) { // As an optimization hint for the linker, before the JALR we add: // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol // tmplabel: @@ -2106,43 +2136,25 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, ExpandedJalSym = true; } - bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0; - if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) { + if (MCID.mayLoad() || MCID.mayStore()) { // Check the offset of memory operand, if it is a symbol // reference or immediate we may have to expand instructions. - for (unsigned i = 0; i < MCID.getNumOperands(); i++) { - const MCOperandInfo &OpInfo = MCID.OpInfo[i]; - if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || - (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { - MCOperand &Op = Inst.getOperand(i); - if (Op.isImm()) { - int64_t MemOffset = Op.getImm(); - if (MemOffset < -32768 || MemOffset > 32767) { - // Offset can't exceed 16bit value. - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); - return getParser().hasPendingError(); - } - } else if (Op.isExpr()) { - const MCExpr *Expr = Op.getExpr(); - if (Expr->getKind() == MCExpr::SymbolRef) { - const MCSymbolRefExpr *SR = - static_cast<const MCSymbolRefExpr *>(Expr); - if (SR->getKind() == MCSymbolRefExpr::VK_None) { - // Expand symbol. - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); - return getParser().hasPendingError(); - } - } else if (!isEvaluated(Expr)) { - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); - return getParser().hasPendingError(); - } - } + if (needsExpandMemInst(Inst)) { + const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); + switch (MCID.OpInfo[MCID.getNumOperands() - 1].OperandType) { + case MipsII::OPERAND_MEM_SIMM9: + expandMem9Inst(Inst, IDLoc, Out, STI, MCID.mayLoad()); + break; + default: + expandMem16Inst(Inst, IDLoc, Out, STI, MCID.mayLoad()); + break; } - } // for - } // if load/store + return getParser().hasPendingError(); + } + } if (inMicroMipsMode()) { - if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) { + if (MCID.mayLoad() && Opcode != Mips::LWP_MM) { // Try to create 16-bit GP relative load instruction. for (unsigned i = 0; i < MCID.getNumOperands(); i++) { const MCOperandInfo &OpInfo = MCID.OpInfo[i]; @@ -2173,7 +2185,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, MCOperand Opnd; int Imm; - switch (Inst.getOpcode()) { + switch (Opcode) { default: break; case Mips::ADDIUSP_MM: @@ -2321,8 +2333,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, TOut.emitDirectiveSetReorder(); } - if ((Inst.getOpcode() == Mips::JalOneReg || - Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) && + if ((Opcode == Mips::JalOneReg || Opcode == Mips::JalTwoReg || + ExpandedJalSym) && isPicAndNotNxxAbi()) { if (IsCpRestoreSet) { // We need a NOP between the JALR and the LW: @@ -2586,6 +2598,9 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::MFTHC1: case Mips::MTTHC1: case Mips::CFTC1: case Mips::CTTC1: return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SaaAddr: + case Mips::SaadAddr: + return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; } } @@ -2837,13 +2852,9 @@ bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg, const MCSubtargetInfo *STI) { // la can't produce a usable address when addresses are 64-bit. if (Is32BitAddress && ABI.ArePtrs64bit()) { - // FIXME: Demote this to a warning and continue as if we had 'dla' instead. - // We currently can't do this because we depend on the equality - // operator and N64 can end up with a GPR32/GPR64 mismatch. - Error(IDLoc, "la used to load 64-bit address"); + Warning(IDLoc, "la used to load 64-bit address"); // Continue as if we had 'dla' instead. Is32BitAddress = false; - return true; } // dla requires 64-bit addresses. @@ -2933,6 +2944,9 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, TmpReg = ATReg; } + // FIXME: In case of N32 / N64 ABI and emabled XGOT, local addresses + // loaded using R_MIPS_GOT_PAGE / R_MIPS_GOT_OFST pair of relocations. + // FIXME: Implement XGOT for microMIPS. if (UseXGOT) { // Loading address from XGOT // External GOT: lui $tmp, %got_hi(symbol)($gp) @@ -2969,7 +2983,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, const MipsMCExpr *GotExpr = nullptr; const MCExpr *LoExpr = nullptr; - if (IsPtr64) { + if (ABI.IsN32() || ABI.IsN64()) { // The remaining cases are: // Small offset: ld $tmp, %got_disp(symbol)($gp) // >daddiu $tmp, $tmp, offset @@ -3079,7 +3093,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI); return false; - } else if (canUseATReg() && !RdRegIsRsReg) { + } else if (canUseATReg() && !RdRegIsRsReg && DstReg != getATReg(IDLoc)) { unsigned ATReg = getATReg(IDLoc); // If the $rs is different from $rd or if $rs isn't specified and we @@ -3106,7 +3120,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI); return false; - } else if (!canUseATReg() && !RdRegIsRsReg) { + } else if ((!canUseATReg() && !RdRegIsRsReg) || + (canUseATReg() && DstReg == getATReg(IDLoc))) { // Otherwise, synthesize the address in the destination register // serially: // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym) @@ -3631,20 +3646,26 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return false; } -void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, bool IsLoad) { - const MCOperand &DstRegOp = Inst.getOperand(0); +void MipsAsmParser::expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, bool IsLoad) { + unsigned NumOp = Inst.getNumOperands(); + assert((NumOp == 3 || NumOp == 4) && "unexpected operands number"); + unsigned StartOp = NumOp == 3 ? 0 : 1; + + const MCOperand &DstRegOp = Inst.getOperand(StartOp); assert(DstRegOp.isReg() && "expected register operand kind"); - const MCOperand &BaseRegOp = Inst.getOperand(1); + const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1); assert(BaseRegOp.isReg() && "expected register operand kind"); + const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2); MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned OpCode = Inst.getOpcode(); unsigned DstReg = DstRegOp.getReg(); unsigned BaseReg = BaseRegOp.getReg(); unsigned TmpReg = DstReg; - const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode()); - int16_t DstRegClass = Desc.OpInfo[0].RegClass; + const MCInstrDesc &Desc = getInstDesc(OpCode); + int16_t DstRegClass = Desc.OpInfo[StartOp].RegClass; unsigned DstRegClassID = getContext().getRegisterInfo()->getRegClass(DstRegClass).getID(); bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) || @@ -3658,25 +3679,12 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return; } - if (Inst.getNumOperands() > 3) { - const MCOperand &BaseRegOp = Inst.getOperand(2); - assert(BaseRegOp.isReg() && "expected register operand kind"); - const MCOperand &ExprOp = Inst.getOperand(3); - assert(ExprOp.isExpr() && "expected expression oprand kind"); - - unsigned BaseReg = BaseRegOp.getReg(); - const MCExpr *ExprOffset = ExprOp.getExpr(); - - MCOperand LoOperand = MCOperand::createExpr( - MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); - MCOperand HiOperand = MCOperand::createExpr( - MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext())); - TOut.emitSCWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, - LoOperand, TmpReg, IDLoc, STI); - return; - } - - const MCOperand &OffsetOp = Inst.getOperand(2); + auto emitInstWithOffset = [&](const MCOperand &Off) { + if (NumOp == 3) + TOut.emitRRX(OpCode, DstReg, TmpReg, Off, IDLoc, STI); + else + TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, Off, IDLoc, STI); + }; if (OffsetOp.isImm()) { int64_t LoOffset = OffsetOp.getImm() & 0xffff; @@ -3690,16 +3698,16 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, bool IsLargeOffset = HiOffset != 0; if (IsLargeOffset) { - bool Is32BitImm = (HiOffset >> 32) == 0; + bool Is32BitImm = isInt<32>(OffsetOp.getImm()); if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true, IDLoc, Out, STI)) return; } if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64) - TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, - BaseReg, IDLoc, STI); - TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI); + TOut.emitRRR(ABI.ArePtrs64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, + TmpReg, BaseReg, IDLoc, STI); + emitInstWithOffset(MCOperand::createImm(int16_t(LoOffset))); return; } @@ -3723,26 +3731,41 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, loadAndAddSymbolAddress(Res.getSymA(), TmpReg, BaseReg, !ABI.ArePtrs64bit(), IDLoc, Out, STI); - TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, Res.getConstant(), IDLoc, - STI); + emitInstWithOffset(MCOperand::createImm(int16_t(Res.getConstant()))); } else { // FIXME: Implement 64-bit case. // 1) lw $8, sym => lui $8, %hi(sym) // lw $8, %lo(sym)($8) // 2) sw $8, sym => lui $at, %hi(sym) // sw $8, %lo(sym)($at) - const MCExpr *ExprOffset = OffsetOp.getExpr(); + const MCExpr *OffExpr = OffsetOp.getExpr(); MCOperand LoOperand = MCOperand::createExpr( - MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); + MipsMCExpr::create(MipsMCExpr::MEK_LO, OffExpr, getContext())); MCOperand HiOperand = MCOperand::createExpr( - MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext())); + MipsMCExpr::create(MipsMCExpr::MEK_HI, OffExpr, getContext())); + + if (ABI.IsN64()) { + MCOperand HighestOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, OffExpr, getContext())); + MCOperand HigherOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, OffExpr, getContext())); - // Generate the base address in TmpReg. - TOut.emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI); - if (BaseReg != Mips::ZERO) - TOut.emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI); - // Emit the load or store with the adjusted base and offset. - TOut.emitRRX(Inst.getOpcode(), DstReg, TmpReg, LoOperand, IDLoc, STI); + TOut.emitRX(Mips::LUi, TmpReg, HighestOperand, IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HigherOperand, IDLoc, STI); + TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HiOperand, IDLoc, STI); + TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI); + if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64) + TOut.emitRRR(Mips::DADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI); + emitInstWithOffset(LoOperand); + } else { + // Generate the base address in TmpReg. + TOut.emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI); + if (BaseReg != Mips::ZERO) + TOut.emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI); + // Emit the load or store with the adjusted base and offset. + emitInstWithOffset(LoOperand); + } } return; } @@ -3750,6 +3773,64 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, llvm_unreachable("unexpected operand type"); } +void MipsAsmParser::expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, bool IsLoad) { + unsigned NumOp = Inst.getNumOperands(); + assert((NumOp == 3 || NumOp == 4) && "unexpected operands number"); + unsigned StartOp = NumOp == 3 ? 0 : 1; + + const MCOperand &DstRegOp = Inst.getOperand(StartOp); + assert(DstRegOp.isReg() && "expected register operand kind"); + const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1); + assert(BaseRegOp.isReg() && "expected register operand kind"); + const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2); + + MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned OpCode = Inst.getOpcode(); + unsigned DstReg = DstRegOp.getReg(); + unsigned BaseReg = BaseRegOp.getReg(); + unsigned TmpReg = DstReg; + + const MCInstrDesc &Desc = getInstDesc(OpCode); + int16_t DstRegClass = Desc.OpInfo[StartOp].RegClass; + unsigned DstRegClassID = + getContext().getRegisterInfo()->getRegClass(DstRegClass).getID(); + bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) || + (DstRegClassID == Mips::GPR64RegClassID); + + if (!IsLoad || !IsGPR || (BaseReg == DstReg)) { + // At this point we need AT to perform the expansions + // and we exit if it is not available. + TmpReg = getATReg(IDLoc); + if (!TmpReg) + return; + } + + auto emitInst = [&]() { + if (NumOp == 3) + TOut.emitRRX(OpCode, DstReg, TmpReg, MCOperand::createImm(0), IDLoc, STI); + else + TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, MCOperand::createImm(0), + IDLoc, STI); + }; + + if (OffsetOp.isImm()) { + loadImmediate(OffsetOp.getImm(), TmpReg, BaseReg, !ABI.ArePtrs64bit(), true, + IDLoc, Out, STI); + emitInst(); + return; + } + + if (OffsetOp.isExpr()) { + loadAndAddSymbolAddress(OffsetOp.getExpr(), TmpReg, BaseReg, + !ABI.ArePtrs64bit(), IDLoc, Out, STI); + emitInst(); + return; + } + + llvm_unreachable("unexpected operand type"); +} + bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { @@ -4051,8 +4132,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // D(S)DivMacro. bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, const bool IsMips64, - const bool Signed) { + const MCSubtargetInfo *STI, + const bool IsMips64, const bool Signed) { MipsTargetStreamer &TOut = getTargetStreamer(); warnIfNoMacro(IDLoc); @@ -5450,6 +5531,39 @@ bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return false; } +bool MipsAsmParser::expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + assert(Inst.getNumOperands() == 3 && "expected three operands"); + assert(Inst.getOperand(0).isReg() && "expected register operand kind"); + assert(Inst.getOperand(1).isReg() && "expected register operand kind"); + + warnIfNoMacro(IDLoc); + + MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned Opcode = Inst.getOpcode() == Mips::SaaAddr ? Mips::SAA : Mips::SAAD; + unsigned RtReg = Inst.getOperand(0).getReg(); + unsigned BaseReg = Inst.getOperand(1).getReg(); + const MCOperand &BaseOp = Inst.getOperand(2); + + if (BaseOp.isImm()) { + int64_t ImmValue = BaseOp.getImm(); + if (ImmValue == 0) { + TOut.emitRR(Opcode, RtReg, BaseReg, IDLoc, STI); + return false; + } + } + + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + + if (expandLoadAddress(ATReg, BaseReg, BaseOp, !isGP64bit(), IDLoc, Out, STI)) + return true; + + TOut.emitRR(Opcode, RtReg, ATReg, IDLoc, STI); + return false; +} + unsigned MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst, const OperandVector &Operands) { @@ -6086,26 +6200,6 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { return true; } -bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { - switch (Expr->getKind()) { - case MCExpr::Constant: - return true; - case MCExpr::SymbolRef: - return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None); - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); - if (!isEvaluated(BE->getLHS())) - return false; - return isEvaluated(BE->getRHS()); - } - case MCExpr::Unary: - return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr()); - case MCExpr::Target: - return true; - } - return false; -} - bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands; @@ -7168,8 +7262,8 @@ bool MipsAsmParser::parseSetArchDirective() { return reportParseError("unexpected token, expected equals sign"); Parser.Lex(); - StringRef Arch; - if (Parser.parseIdentifier(Arch)) + StringRef Arch = getParser().parseStringToEndOfStatement().trim(); + if (Arch.empty()) return reportParseError("expected arch identifier"); StringRef ArchFeatureName = @@ -7190,6 +7284,7 @@ bool MipsAsmParser::parseSetArchDirective() { .Case("mips64r5", "mips64r5") .Case("mips64r6", "mips64r6") .Case("octeon", "cnmips") + .Case("octeon+", "cnmipsp") .Case("r4000", "mips3") // This is an implementation of Mips3. .Default(""); @@ -8550,7 +8645,7 @@ bool MipsAsmParser::parseInternalDirectiveReallowModule() { return false; } -extern "C" void LLVMInitializeMipsAsmParser() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsAsmParser() { RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget()); RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget()); RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target()); diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index c3e98fe410c1..6f197e424561 100644 --- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -63,6 +63,8 @@ public: bool hasCnMips() const { return STI.getFeatureBits()[Mips::FeatureCnMips]; } + bool hasCnMipsP() const { return STI.getFeatureBits()[Mips::FeatureCnMipsP]; } + bool hasCOP3() const { // Only present in MIPS-I and MIPS-II return !hasMips32() && !hasMips3(); @@ -70,7 +72,6 @@ public: DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address, - raw_ostream &VStream, raw_ostream &CStream) const override; }; @@ -446,16 +447,16 @@ static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder); template <typename InsnType> -static DecodeStatus DecodeDAHIDATIMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); +static DecodeStatus DecodeDAHIDATIMMR6(MCInst &MI, InsnType insn, + uint64_t Address, const void *Decoder); template <typename InsnType> static DecodeStatus DecodeDAHIDATI(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder); template <typename InsnType> -static DecodeStatus DecodeDAHIDATIMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); +static DecodeStatus DecodeDAHIDATIMMR6(MCInst &MI, InsnType insn, + uint64_t Address, const void *Decoder); template <typename InsnType> static DecodeStatus DecodeDAHIDATI(MCInst &MI, InsnType insn, uint64_t Address, @@ -562,7 +563,7 @@ static MCDisassembler *createMipselDisassembler( return new MipsDisassembler(STI, Ctx, false); } -extern "C" void LLVMInitializeMipsDisassembler() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsDisassembler() { // Register the disassembler. TargetRegistry::RegisterMCDisassembler(getTheMipsTarget(), createMipsDisassembler); @@ -630,8 +631,8 @@ static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, } template <typename InsnType> -static DecodeStatus DecodeDAHIDATIMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder) { +static DecodeStatus DecodeDAHIDATIMMR6(MCInst &MI, InsnType insn, + uint64_t Address, const void *Decoder) { InsnType Rs = fieldFromInstruction(insn, 16, 5); InsnType Imm = fieldFromInstruction(insn, 0, 16); MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, @@ -1091,8 +1092,10 @@ static DecodeStatus DecodeDEXT(MCInst &MI, InsnType Insn, uint64_t Address, InsnType Rs = fieldFromInstruction(Insn, 21, 5); InsnType Rt = fieldFromInstruction(Insn, 16, 5); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rt))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rs))); + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rt))); + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rs))); MI.addOperand(MCOperand::createImm(Pos)); MI.addOperand(MCOperand::createImm(Size)); @@ -1132,8 +1135,10 @@ static DecodeStatus DecodeDINS(MCInst &MI, InsnType Insn, uint64_t Address, InsnType Rt = fieldFromInstruction(Insn, 16, 5); MI.setOpcode(Mips::DINS); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rt))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rs))); + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rt))); + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rs))); MI.addOperand(MCOperand::createImm(Pos)); MI.addOperand(MCOperand::createImm(Size)); @@ -1214,7 +1219,6 @@ static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address, DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address, - raw_ostream &VStream, raw_ostream &CStream) const { uint32_t Insn; DecodeStatus Result; @@ -1256,8 +1260,8 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, LLVM_DEBUG( dbgs() << "Trying MicroMips32r632 table (32-bit instructions):\n"); // Calling the auto-generated decoder function. - Result = decodeInstruction(DecoderTableMicroMipsR632, Instr, Insn, Address, - this, STI); + Result = decodeInstruction(DecoderTableMicroMipsR632, Instr, Insn, + Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; return Result; @@ -1353,6 +1357,14 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, return Result; } + if (hasCnMipsP()) { + LLVM_DEBUG(dbgs() << "Trying CnMipsP table (32-bit opcodes):\n"); + Result = decodeInstruction(DecoderTableCnMipsP32, Instr, Insn, + Address, this, STI); + if (Result != MCDisassembler::Fail) + return Result; + } + if (isGP64()) { LLVM_DEBUG(dbgs() << "Trying Mips64 (GPR64) table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips6432, Instr, Insn, diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h index 239e55495e9d..6091ee24b04d 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -139,7 +139,9 @@ public: template <class PredicateLibrary> void setISAExtensionFromPredicates(const PredicateLibrary &P) { - if (P.hasCnMips()) + if (P.hasCnMipsP()) + ISAExtension = Mips::AFL_EXT_OCTEONP; + else if (P.hasCnMips()) ISAExtension = Mips::AFL_EXT_OCTEON; else ISAExtension = Mips::AFL_EXT_NONE; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index bdd190fc17c9..37e970f2f15b 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 70f2a7bdf10f..94d338746a6c 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -585,6 +585,8 @@ MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options) { - MipsABIInfo ABI = MipsABIInfo::computeTargetABI(STI.getTargetTriple(), STI.getCPU(), Options); - return new MipsAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(), ABI.IsN32()); + MipsABIInfo ABI = MipsABIInfo::computeTargetABI(STI.getTargetTriple(), + STI.getCPU(), Options); + return new MipsAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(), + ABI.IsN32()); } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index 6d8cb264158f..02ab5ede2c1a 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -16,6 +16,7 @@ #include "MipsFixupKinds.h" #include "MipsMCTargetDesc.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInstrDesc.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -123,13 +124,16 @@ namespace MipsII { IsCTI = 1 << 4, /// HasForbiddenSlot - Instruction has a forbidden slot. HasForbiddenSlot = 1 << 5, - /// IsPCRelativeLoad - A Load instruction with implicit source register - /// ($pc) with explicit offset and destination register - IsPCRelativeLoad = 1 << 6, /// HasFCCRegOperand - Instruction uses an $fcc<x> register. - HasFCCRegOperand = 1 << 7 + HasFCCRegOperand = 1 << 6 }; + + enum OperandType : unsigned { + OPERAND_FIRST_MIPS_MEM_IMM = MCOI::OPERAND_FIRST_TARGET, + OPERAND_MEM_SIMM9 = OPERAND_FIRST_MIPS_MEM_IMM, + OPERAND_LAST_MIPS_MEM_IMM = OPERAND_MEM_SIMM9 + }; } } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp index fb290a8e3f26..649ba20324bf 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp @@ -75,8 +75,9 @@ void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { OS << '$' << StringRef(getRegisterName(RegNo)).lower(); } -void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, - StringRef Annot, const MCSubtargetInfo &STI) { +void MipsInstPrinter::printInst(const MCInst *MI, uint64_t Address, + StringRef Annot, const MCSubtargetInfo &STI, + raw_ostream &O) { switch (MI->getOpcode()) { default: break; @@ -109,7 +110,7 @@ void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, // Try to print any aliases first. if (!printAliasInstr(MI, O) && !printAlias(*MI, O)) - printInstruction(MI, O); + printInstruction(MI, Address, O); printAnnotation(O, Annot); switch (MI->getOpcode()) { diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h index a34a5c1d6418..0b1ee800e440 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h @@ -79,12 +79,12 @@ public: : MCInstPrinter(MAI, MII, MRI) {} // Autogenerated by tblgen. - void printInstruction(const MCInst *MI, raw_ostream &O); + void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); void printRegName(raw_ostream &OS, unsigned RegNo) const override; - void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, - const MCSubtargetInfo &STI) override; + void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, + const MCSubtargetInfo &STI, raw_ostream &O) override; bool printAliasInstr(const MCInst *MI, raw_ostream &OS); void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx, diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index ec78158d387d..5182205edaea 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -11,25 +11,27 @@ //===----------------------------------------------------------------------===// #include "MipsMCAsmInfo.h" +#include "MipsABIInfo.h" #include "llvm/ADT/Triple.h" using namespace llvm; void MipsMCAsmInfo::anchor() { } -MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) { +MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple, + const MCTargetOptions &Options) { IsLittleEndian = TheTriple.isLittleEndian(); - if (TheTriple.isMIPS64() && TheTriple.getEnvironment() != Triple::GNUABIN32) + MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TheTriple, "", Options); + + if (TheTriple.isMIPS64() && !ABI.IsN32()) CodePointerSize = CalleeSaveStackSlotSize = 8; - // FIXME: This condition isn't quite right but it's the best we can do until - // this object can identify the ABI. It will misbehave when using O32 - // on a mips64*-* triple. - if (TheTriple.isMIPS32()) { + if (ABI.IsO32()) PrivateGlobalPrefix = "$"; - PrivateLabelPrefix = "$"; - } + else if (ABI.IsN32() || ABI.IsN64()) + PrivateGlobalPrefix = ".L"; + PrivateLabelPrefix = PrivateGlobalPrefix; AlignmentIsInBytes = false; Data16bitsDirective = "\t.2byte\t"; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h index 867f4d223de4..d8bfe58d24a8 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h @@ -22,7 +22,8 @@ class MipsMCAsmInfo : public MCAsmInfoELF { void anchor() override; public: - explicit MipsMCAsmInfo(const Triple &TheTriple); + explicit MipsMCAsmInfo(const Triple &TheTriple, + const MCTargetOptions &Options); }; } // namespace llvm diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 142e9cebb79e..846f508005f5 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -600,7 +600,8 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, } if (Kind == MCExpr::Binary) { - unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI); + unsigned Res = + getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI); Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI); return Res; } @@ -729,7 +730,8 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, default: llvm_unreachable("Unknown fixup kind!"); break; case MCSymbolRefExpr::VK_None: - FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64. + // FIXME: This is ok for O32/N32 but not N64. + FixupKind = Mips::fixup_Mips_32; break; } // switch @@ -768,7 +770,8 @@ unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, const MCSubtargetInfo &STI) const { // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) + << 16; unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); // Apply the scale factor if there is one. @@ -857,7 +860,8 @@ getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, assert(MI.getOperand(OpNo).isReg()); unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI); + unsigned OffBits = + getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI); return (OffBits & 0x1FF) | RegBits; } @@ -892,7 +896,8 @@ getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, // Base register is encoded in bits 20-16, offset is encoded in bits 11-0. assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16; + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) + << 16; unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); return (OffBits & 0x0FFF) | RegBits; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp index 680806c4deb2..a25783b5cf04 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp @@ -211,7 +211,8 @@ MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res, // The value of getKind() that is given to MCValue is only intended to aid // debugging when inspecting MCValue objects. It shouldn't be relied upon // for decision making. - Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); + Res = + MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); return true; } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index 79c47d1b6508..de582bd60cbf 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -12,6 +12,7 @@ #include "MipsMCTargetDesc.h" #include "MipsAsmBackend.h" +#include "MipsBaseInfo.h" #include "MipsELFStreamer.h" #include "MipsInstPrinter.h" #include "MipsMCAsmInfo.h" @@ -44,7 +45,6 @@ using namespace llvm; #include "MipsGenRegisterInfo.inc" /// Select the Mips CPU for the given triple and cpu name. -/// FIXME: Merge with the copy in MipsSubtarget.cpp StringRef MIPS_MC::selectMipsCPU(const Triple &TT, StringRef CPU) { if (CPU.empty() || CPU == "generic") { if (TT.getSubArch() == llvm::Triple::MipsSubArch_r6) { @@ -81,8 +81,9 @@ static MCSubtargetInfo *createMipsMCSubtargetInfo(const Triple &TT, } static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI, - const Triple &TT) { - MCAsmInfo *MAI = new MipsMCAsmInfo(TT); + const Triple &TT, + const MCTargetOptions &Options) { + MCAsmInfo *MAI = new MipsMCAsmInfo(TT, Options); unsigned SP = MRI.getDwarfRegNum(Mips::SP, true); MCCFIInstruction Inst = MCCFIInstruction::createDefCfaRegister(nullptr, SP); @@ -165,7 +166,7 @@ static MCInstrAnalysis *createMipsMCInstrAnalysis(const MCInstrInfo *Info) { return new MipsMCInstrAnalysis(Info); } -extern "C" void LLVMInitializeMipsTargetMC() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTargetMC() { for (Target *T : {&getTheMipsTarget(), &getTheMipselTarget(), &getTheMips64Target(), &getTheMips64elTarget()}) { // Register the MC asm info. diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp index 2d53750ad0ee..0544758f8a25 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp @@ -154,8 +154,8 @@ public: } // Sandbox loads, stores and SP changes. - unsigned AddrIdx; - bool IsStore; + unsigned AddrIdx = 0; + bool IsStore = false; bool IsMemAccess = isBasePlusOffsetMemoryAccess(Inst.getOpcode(), &AddrIdx, &IsStore); bool IsSPFirstOperand = isStackPointerFirstOperand(Inst); diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp index 3ff9c722484b..bdfb70aa9813 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp @@ -74,27 +74,23 @@ void MipsRegInfoRecord::SetPhysRegUsed(unsigned Reg, const MCRegisterInfo *MCRegInfo) { unsigned Value = 0; - for (MCSubRegIterator SubRegIt(Reg, MCRegInfo, true); SubRegIt.isValid(); - ++SubRegIt) { - unsigned CurrentSubReg = *SubRegIt; - - unsigned EncVal = MCRegInfo->getEncodingValue(CurrentSubReg); + for (const MCPhysReg &SubReg : MCRegInfo->subregs_inclusive(Reg)) { + unsigned EncVal = MCRegInfo->getEncodingValue(SubReg); Value |= 1 << EncVal; - if (GPR32RegClass->contains(CurrentSubReg) || - GPR64RegClass->contains(CurrentSubReg)) + if (GPR32RegClass->contains(SubReg) || GPR64RegClass->contains(SubReg)) ri_gprmask |= Value; - else if (COP0RegClass->contains(CurrentSubReg)) + else if (COP0RegClass->contains(SubReg)) ri_cprmask[0] |= Value; // MIPS COP1 is the FPU. - else if (FGR32RegClass->contains(CurrentSubReg) || - FGR64RegClass->contains(CurrentSubReg) || - AFGR64RegClass->contains(CurrentSubReg) || - MSA128BRegClass->contains(CurrentSubReg)) + else if (FGR32RegClass->contains(SubReg) || + FGR64RegClass->contains(SubReg) || + AFGR64RegClass->contains(SubReg) || + MSA128BRegClass->contains(SubReg)) ri_cprmask[1] |= Value; - else if (COP2RegClass->contains(CurrentSubReg)) + else if (COP2RegClass->contains(SubReg)) ri_cprmask[2] |= Value; - else if (COP3RegClass->contains(CurrentSubReg)) + else if (COP3RegClass->contains(SubReg)) ri_cprmask[3] |= Value; } } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index b6dae9f6dea8..054dc79f4aa9 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -34,11 +34,6 @@ static cl::opt<bool> RoundSectionSizes( cl::desc("Round section sizes up to the section alignment"), cl::Hidden); } // end anonymous namespace -static bool isMipsR6(const MCSubtargetInfo *STI) { - return STI->getFeatureBits()[Mips::FeatureMips32r6] || - STI->getFeatureBits()[Mips::FeatureMips64r6]; -} - static bool isMicroMips(const MCSubtargetInfo *STI) { return STI->getFeatureBits()[Mips::FeatureMicroMips]; } @@ -332,36 +327,6 @@ void MipsTargetStreamer::emitStoreWithImmOffset( emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI); } -/// Emit a store instruction with an symbol offset. -void MipsTargetStreamer::emitSCWithSymOffset(unsigned Opcode, unsigned SrcReg, - unsigned BaseReg, - MCOperand &HiOperand, - MCOperand &LoOperand, - unsigned ATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - // sc $8, sym => lui $at, %hi(sym) - // sc $8, %lo(sym)($at) - - // Generate the base address in ATReg. - emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI); - if (!isMicroMips(STI) && isMipsR6(STI)) { - // For non-micromips r6 offset for 'sc' is not in the lower 16 bits so we - // put it in 'at'. - // sc $8, sym => lui $at, %hi(sym) - // addiu $at, $at, %lo(sym) - // sc $8, 0($at) - emitRRX(Mips::ADDiu, ATReg, ATReg, LoOperand, IDLoc, STI); - MCOperand Offset = MCOperand::createImm(0); - // Emit the store with the adjusted base and offset. - emitRRRX(Opcode, SrcReg, SrcReg, ATReg, Offset, IDLoc, STI); - } else { - if (BaseReg != Mips::ZERO) - emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI); - // Emit the store with the adjusted base and offset. - emitRRRX(Opcode, SrcReg, SrcReg, ATReg, LoOperand, IDLoc, STI); - } -} - /// Emit a load instruction with an immediate offset. DstReg and TmpReg are /// permitted to be the same register iff DstReg is distinct from BaseReg and /// DstReg is a GPR. It is the callers responsibility to identify such cases diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td b/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td index dbff0f6200f2..da8a06b0cff8 100644 --- a/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td +++ b/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -234,7 +234,8 @@ class POOL32A_FM_MMR6<bits<10> funct> : MipsR6Inst { let Inst{9-0} = funct; } -class POOL32A_PAUSE_FM_MMR6<string instr_asm, bits<5> op> : MMR6Arch<instr_asm> { +class POOL32A_PAUSE_FM_MMR6<string instr_asm, bits<5> op> + : MMR6Arch<instr_asm> { bits<32> Inst; let Inst{31-26} = 0; @@ -512,7 +513,8 @@ class BARRIER_MMR6_ENC<string instr_asm, bits<5> op> : MMR6Arch<instr_asm> { class POOL32A_EIDI_MMR6_ENC<string instr_asm, bits<10> funct> : MMR6Arch<instr_asm> { bits<32> Inst; - bits<5> rt; // Actually rs but we're sharing code with the standard encodings which call it rt + bits<5> rt; // Actually rs but we're sharing code with the standard encodings + // which call it rt let Inst{31-26} = 0x00; let Inst{25-21} = 0x00; @@ -521,7 +523,8 @@ class POOL32A_EIDI_MMR6_ENC<string instr_asm, bits<10> funct> let Inst{5-0} = 0x3c; } -class SHIFT_MMR6_ENC<string instr_asm, bits<10> funct, bit rotate> : MMR6Arch<instr_asm> { +class SHIFT_MMR6_ENC<string instr_asm, bits<10> funct, bit rotate> + : MMR6Arch<instr_asm> { bits<5> rd; bits<5> rt; bits<5> shamt; @@ -809,8 +812,8 @@ class POOL32F_RECIP_ROUND_FM_MMR6<string instr_asm, bits<1> fmt, bits<8> funct> let Inst{5-0} = 0b111011; } -class POOL32F_RINT_FM_MMR6<string instr_asm, bits<2> fmt> - : MMR6Arch<instr_asm>, MipsR6Inst { +class POOL32F_RINT_FM_MMR6<string instr_asm, bits<2> fmt> : MMR6Arch<instr_asm>, + MipsR6Inst { bits<5> fs; bits<5> fd; @@ -1012,8 +1015,8 @@ class POOL32B_LDWC2_SDWC2_FM_MMR6<string instr_asm, bits<4> funct> } class POOL32C_LL_E_SC_E_FM_MMR6<string instr_asm, bits<4> majorFunc, - bits<3> minorFunc> - : MMR6Arch<instr_asm>, MipsR6Inst { + bits<3> minorFunc> : MMR6Arch<instr_asm>, + MipsR6Inst { bits<5> rt; bits<21> addr; bits<5> base = addr{20-16}; diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td index 425773dc57f1..832124cb3f57 100644 --- a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -341,7 +341,8 @@ class BNEC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bnec", brtarget_lsl2_mm, GPR32Opnd>; class ADD_MMR6_DESC : ArithLogicR<"add", GPR32Opnd, 1, II_ADD>; -class ADDIU_MMR6_DESC : ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU, immSExt16, add>; +class ADDIU_MMR6_DESC + : ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU, immSExt16, add>; class ADDU_MMR6_DESC : ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU>; class MUL_MMR6_DESC : ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>; class MUH_MMR6_DESC : ArithLogicR<"muh", GPR32Opnd, 1, II_MUH, mulhs>; @@ -1045,8 +1046,8 @@ class TRUNC_W_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.w.d", FGR32Opnd, FGR64Opnd, II_TRUNC>; class SQRT_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, fsqrt>; -class SQRT_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.d", AFGR64Opnd, AFGR64Opnd, - II_SQRT_D, fsqrt>; +class SQRT_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.d", AFGR64Opnd, + AFGR64Opnd, II_SQRT_D, fsqrt>; class ROUND_L_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"round.l.s", FGR64Opnd, FGR32Opnd, II_ROUND>; class ROUND_L_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"round.l.d", FGR64Opnd, @@ -1101,14 +1102,16 @@ class SLL16_MMR6_DESC : ShiftIMM16<"sll16", uimm3_shift, GPRMM16Opnd, II_SLL>, MMR6Arch<"sll16">; class SRL16_MMR6_DESC : ShiftIMM16<"srl16", uimm3_shift, GPRMM16Opnd, II_SRL>, MMR6Arch<"srl16">; -class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16", II_BREAK>, MMR6Arch<"break16">; +class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16", II_BREAK>, + MMR6Arch<"break16">; class LI16_MMR6_DESC : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, MMR6Arch<"li16">, IsAsCheapAsAMove; class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"move16">; class MOVEP_MMR6_DESC : MovePMM16<"movep", GPRMM16OpndMovePPairFirst, GPRMM16OpndMovePPairSecond, GPRMM16OpndMoveP>, MMR6Arch<"movep">; -class SDBBP16_MMR6_DESC : BrkSdbbp16MM<"sdbbp16", II_SDBBP>, MMR6Arch<"sdbbp16">; +class SDBBP16_MMR6_DESC : BrkSdbbp16MM<"sdbbp16", II_SDBBP>, + MMR6Arch<"sdbbp16">; class SUBU16_MMR6_DESC : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, MMR6Arch<"subu16"> { int AddedComplexity = 1; @@ -1439,7 +1442,8 @@ def SYNCI_MMR6 : StdMMR6Rel, SYNCI_MMR6_DESC, SYNCI_MMR6_ENC, ISA_MICROMIPS32R6; def RDPGPR_MMR6 : R6MMR6Rel, RDPGPR_MMR6_DESC, RDPGPR_MMR6_ENC, ISA_MICROMIPS32R6; def SDBBP_MMR6 : R6MMR6Rel, SDBBP_MMR6_DESC, SDBBP_MMR6_ENC, ISA_MICROMIPS32R6; -def SIGRIE_MMR6 : R6MMR6Rel, SIGRIE_MMR6_DESC, SIGRIE_MMR6_ENC, ISA_MICROMIPS32R6; +def SIGRIE_MMR6 : R6MMR6Rel, SIGRIE_MMR6_DESC, SIGRIE_MMR6_ENC, + ISA_MICROMIPS32R6; def XOR_MMR6 : StdMMR6Rel, XOR_MMR6_DESC, XOR_MMR6_ENC, ISA_MICROMIPS32R6; def XORI_MMR6 : StdMMR6Rel, XORI_MMR6_DESC, XORI_MMR6_ENC, ISA_MICROMIPS32R6; let DecoderMethod = "DecodeMemMMImm16" in { @@ -1557,7 +1561,8 @@ def INS_MMR6 : StdMMR6Rel, INS_MMR6_ENC, INS_MMR6_DESC, ISA_MICROMIPS32R6; def JALRC_MMR6 : R6MMR6Rel, JALRC_MMR6_ENC, JALRC_MMR6_DESC, ISA_MICROMIPS32R6; def RINT_S_MMR6 : StdMMR6Rel, RINT_S_MMR6_ENC, RINT_S_MMR6_DESC, ISA_MICROMIPS32R6; -def RINT_D_MMR6 : StdMMR6Rel, RINT_D_MMR6_ENC, RINT_D_MMR6_DESC, ISA_MICROMIPS32R6; +def RINT_D_MMR6 : StdMMR6Rel, RINT_D_MMR6_ENC, RINT_D_MMR6_DESC, + ISA_MICROMIPS32R6; def ROUND_L_S_MMR6 : StdMMR6Rel, ROUND_L_S_MMR6_ENC, ROUND_L_S_MMR6_DESC, ISA_MICROMIPS32R6; def ROUND_L_D_MMR6 : StdMMR6Rel, ROUND_L_D_MMR6_ENC, ROUND_L_D_MMR6_DESC, @@ -1751,7 +1756,8 @@ defm S_MMR6 : Cmp_Pats<f32, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6; defm D_MMR6 : Cmp_Pats<f64, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6; def : MipsPat<(f32 fpimm0), (MTC1_MMR6 ZERO)>, ISA_MICROMIPS32R6; -def : MipsPat<(f32 fpimm0neg), (FNEG_S_MMR6 (MTC1_MMR6 ZERO))>, ISA_MICROMIPS32R6; +def : MipsPat<(f32 fpimm0neg), (FNEG_S_MMR6(MTC1_MMR6 ZERO))>, + ISA_MICROMIPS32R6; def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), (TRUNC_W_D_MMR6 FGR64Opnd:$src)>, ISA_MICROMIPS32R6; def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFPU.td b/llvm/lib/Target/Mips/MicroMipsInstrFPU.td index 5d87068ff407..eea4d7746fa6 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrFPU.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrFPU.td @@ -230,7 +230,8 @@ let DecoderNamespace = "MicroMips" in { def FSQRT_S_MM : MMRel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, fsqrt>, ROUND_W_FM_MM<0, 0x28>, ISA_MICROMIPS; - def MTHC1_D32_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, + def MTHC1_D32_MM : MMRel, + MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, MFC1_FM_MM<0xe0>, ISA_MICROMIPS, FGR_32; def MFHC1_D32_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>, MFC1_FM_MM<0xc0>, ISA_MICROMIPS, FGR_32; diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td index 8cc0029fc896..b707f1b96184 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td @@ -116,7 +116,7 @@ def mem_mm_9 : Operand<i32> { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops ptr_rc, simm9); let EncoderMethod = "getMemEncodingMMImm9"; - let ParserMatchClass = MipsMemSimm9AsmOperand; + let ParserMatchClass = MipsMemSimmAsmOperand<9>; let OperandType = "OPERAND_MEMORY"; } @@ -124,7 +124,7 @@ def mem_mm_11 : Operand<i32> { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops GPR32, simm11); let EncoderMethod = "getMemEncodingMMImm11"; - let ParserMatchClass = MipsMemSimm11AsmOperand; + let ParserMatchClass = MipsMemSimmAsmOperand<11>; let OperandType = "OPERAND_MEMORY"; } @@ -141,7 +141,7 @@ def mem_mm_16 : Operand<i32> { let MIOperandInfo = (ops ptr_rc, simm16); let EncoderMethod = "getMemEncodingMMImm16"; let DecoderMethod = "DecodeMemMMImm16"; - let ParserMatchClass = MipsMemSimm16AsmOperand; + let ParserMatchClass = MipsMemSimmAsmOperand<16>; let OperandType = "OPERAND_MEMORY"; } @@ -506,7 +506,8 @@ class LoadWordIndexedScaledMM<string opstr, RegisterOperand RO, class PrefetchIndexed<string opstr> : InstSE<(outs), (ins PtrRC:$base, PtrRC:$index, uimm5:$hint), - !strconcat(opstr, "\t$hint, ${index}(${base})"), [], II_PREF, FrmOther>; + !strconcat(opstr, "\t$hint, ${index}(${base})"), + [], II_PREF, FrmOther>; class AddImmUPC<string opstr, RegisterOperand RO> : InstSE<(outs RO:$rs), (ins simm23_lsl2:$imm), diff --git a/llvm/lib/Target/Mips/Mips.td b/llvm/lib/Target/Mips/Mips.td index a5908362e81f..b8a69815cc12 100644 --- a/llvm/lib/Target/Mips/Mips.td +++ b/llvm/lib/Target/Mips/Mips.td @@ -192,17 +192,22 @@ def FeatureGINV : SubtargetFeature<"ginv", "HasGINV", "true", def FeatureMicroMips : SubtargetFeature<"micromips", "InMicroMipsMode", "true", "microMips mode">; -def FeatureCnMips : SubtargetFeature<"cnmips", "HasCnMips", - "true", "Octeon cnMIPS Support", - [FeatureMips64r2]>; +def FeatureCnMips : SubtargetFeature<"cnmips", "HasCnMips", + "true", "Octeon cnMIPS Support", + [FeatureMips64r2]>; + +def FeatureCnMipsP : SubtargetFeature<"cnmipsp", "HasCnMipsP", + "true", "Octeon+ cnMIPS Support", + [FeatureCnMips]>; def FeatureUseTCCInDIV : SubtargetFeature< "use-tcc-in-div", "UseTCCInDIV", "false", "Force the assembler to use trapping">; -def FeatureMadd4 : SubtargetFeature<"nomadd4", "DisableMadd4", "true", - "Disable 4-operand madd.fmt and related instructions">; +def FeatureMadd4 + : SubtargetFeature<"nomadd4", "DisableMadd4", "true", + "Disable 4-operand madd.fmt and related instructions">; def FeatureMT : SubtargetFeature<"mt", "HasMT", "true", "Mips MT ASE">; @@ -227,6 +232,7 @@ def ImplP5600 : SubtargetFeature<"p5600", "ProcImpl", class Proc<string Name, list<SubtargetFeature> Features> : ProcessorModel<Name, MipsGenericModel, Features>; +def : Proc<"generic", [FeatureMips32]>; def : Proc<"mips1", [FeatureMips1]>; def : Proc<"mips2", [FeatureMips2]>; def : Proc<"mips32", [FeatureMips32]>; @@ -244,6 +250,7 @@ def : Proc<"mips64r3", [FeatureMips64r3]>; def : Proc<"mips64r5", [FeatureMips64r5]>; def : Proc<"mips64r6", [FeatureMips64r6]>; def : Proc<"octeon", [FeatureMips64r2, FeatureCnMips]>; +def : Proc<"octeon+", [FeatureMips64r2, FeatureCnMips, FeatureCnMipsP]>; def : ProcessorModel<"p5600", MipsP5600Model, [ImplP5600]>; def MipsAsmParser : AsmParser { diff --git a/llvm/lib/Target/Mips/Mips16ISelLowering.cpp b/llvm/lib/Target/Mips/Mips16ISelLowering.cpp index 5a5b78c9d5f9..5425df77d9b8 100644 --- a/llvm/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/llvm/lib/Target/Mips/Mips16ISelLowering.cpp @@ -252,9 +252,6 @@ void Mips16TargetLowering::setMips16HardFloatLibCalls() { if (HardFloatLibCalls[I].Libcall != RTLIB::UNKNOWN_LIBCALL) setLibcallName(HardFloatLibCalls[I].Libcall, HardFloatLibCalls[I].Name); } - - setLibcallName(RTLIB::O_F64, "__mips16_unorddf2"); - setLibcallName(RTLIB::O_F32, "__mips16_unordsf2"); } // diff --git a/llvm/lib/Target/Mips/Mips16InstrInfo.cpp b/llvm/lib/Target/Mips/Mips16InstrInfo.cpp index 0d735c20ec2f..d2a1ba39cb0e 100644 --- a/llvm/lib/Target/Mips/Mips16InstrInfo.cpp +++ b/llvm/lib/Target/Mips/Mips16InstrInfo.cpp @@ -68,8 +68,8 @@ unsigned Mips16InstrInfo::isStoreToStackSlot(const MachineInstr &MI, void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - const DebugLoc &DL, unsigned DestReg, - unsigned SrcReg, bool KillSrc) const { + const DebugLoc &DL, MCRegister DestReg, + MCRegister SrcReg, bool KillSrc) const { unsigned Opc = 0; if (Mips::CPU16RegsRegClass.contains(DestReg) && @@ -96,15 +96,11 @@ void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB, MIB.addReg(SrcReg, getKillRegState(KillSrc)); } -bool Mips16InstrInfo::isCopyInstrImpl(const MachineInstr &MI, - const MachineOperand *&Src, - const MachineOperand *&Dest) const { - if (MI.isMoveReg()) { - Dest = &MI.getOperand(0); - Src = &MI.getOperand(1); - return true; - } - return false; +Optional<DestSourcePair> +Mips16InstrInfo::isCopyInstrImpl(const MachineInstr &MI) const { + if (MI.isMoveReg()) + return DestSourcePair{MI.getOperand(0), MI.getOperand(1)}; + return None; } void Mips16InstrInfo::storeRegToStack(MachineBasicBlock &MBB, @@ -418,8 +414,9 @@ unsigned Mips16InstrInfo::loadImmediate(unsigned FrameReg, int64_t Imm, else Available.reset(SpReg); copyPhysReg(MBB, II, DL, SpReg, Mips::SP, false); - BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(SpReg, RegState::Kill) - .addReg(Reg); + BuildMI(MBB, II, DL, get(Mips::AdduRxRyRz16), Reg) + .addReg(SpReg, RegState::Kill) + .addReg(Reg); } else BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(FrameReg) diff --git a/llvm/lib/Target/Mips/Mips16InstrInfo.h b/llvm/lib/Target/Mips/Mips16InstrInfo.h index dadcaa3055b3..2ff849cb2ca2 100644 --- a/llvm/lib/Target/Mips/Mips16InstrInfo.h +++ b/llvm/lib/Target/Mips/Mips16InstrInfo.h @@ -49,7 +49,7 @@ public: int &FrameIndex) const override; void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, + const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc) const override; void storeRegToStack(MachineBasicBlock &MBB, @@ -104,10 +104,9 @@ public: protected: /// If the specific machine instruction is a instruction that moves/copies - /// value from one register to another register return true along with - /// @Source machine operand and @Destination machine operand. - bool isCopyInstrImpl(const MachineInstr &MI, const MachineOperand *&Source, - const MachineOperand *&Destination) const override; + /// value from one register to another register return destination and source + /// registers as machine operands. + Optional<DestSourcePair> isCopyInstrImpl(const MachineInstr &MI) const override; private: unsigned getAnalyzableBrOpc(unsigned Opc) const override; diff --git a/llvm/lib/Target/Mips/Mips16InstrInfo.td b/llvm/lib/Target/Mips/Mips16InstrInfo.td index 36b6c73d1008..19ea50c89b96 100644 --- a/llvm/lib/Target/Mips/Mips16InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips16InstrInfo.td @@ -67,7 +67,7 @@ class FI816_ins_base<bits<3> _func, string asmstr, class FI816_ins<bits<3> _func, string asmstr, InstrItinClass itin>: FI816_ins_base<_func, asmstr, "\t$imm # 16 bit inst", itin>; - + class FI816_SP_ins<bits<3> _func, string asmstr, InstrItinClass itin>: FI816_ins_base<_func, asmstr, "\t$$sp, $imm # 16 bit inst", itin>; @@ -90,7 +90,7 @@ class FRI16_TCP_ins<bits<5> _op, string asmstr, InstrItinClass itin>: FRI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size), !strconcat(asmstr, "\t$rx, $imm\t# 16 bit inst"), [], itin>; - + class FRI16R_ins_base<bits<5> op, string asmstr, string asmstr2, InstrItinClass itin>: FRI16<op, (outs), (ins CPU16Regs:$rx, simm16:$imm), @@ -983,7 +983,7 @@ def RestoreX16: // To set up a stack frame on entry to a subroutine, // saving return address and static registers, and adjusting stack // -def Save16: +def Save16: FI8_SVRS16<0b1, (outs), (ins variable_ops), "", [], II_SAVE >, MayStore { let isCodeGenOnly = 1; @@ -1883,7 +1883,7 @@ def : Mips16Pat<(sext_inreg CPU16Regs:$val, i8), def : Mips16Pat<(sext_inreg CPU16Regs:$val, i16), (SehRx16 CPU16Regs:$val)>; -def GotPrologue16: +def GotPrologue16: MipsPseudo16< (outs CPU16Regs:$rh, CPU16Regs:$rl), (ins simm16:$immHi, simm16:$immLo), diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td index 2c3048411a5c..9607d008bc97 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td @@ -765,12 +765,12 @@ class LL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, InstrItinClass Itinerary = itin; } -class LL_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9, II_LL>; +class LL_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9_exp, II_LL>; class SC_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, InstrItinClass itin> { dag OutOperandList = (outs GPROpnd:$dst); - dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); + dag InOperandList = (ins GPROpnd:$rt, mem_simm9_exp:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; bit mayStore = 1; @@ -996,13 +996,15 @@ def : MipsInstAlias<"evp", (EVP ZERO), 0>, ISA_MIPS32R6; let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"sdbbp", (SDBBP_R6 0)>, ISA_MIPS32R6; def : MipsInstAlias<"sigrie", (SIGRIE 0)>, ISA_MIPS32R6; -def : MipsInstAlias<"jr $rs", (JALR ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS32R6, GPR_32; +def : MipsInstAlias<"jr $rs", (JALR ZERO, GPR32Opnd:$rs), 1>, + ISA_MIPS32R6, GPR_32; } def : MipsInstAlias<"jrc $rs", (JIC GPR32Opnd:$rs, 0), 1>, ISA_MIPS32R6, GPR_32; let AdditionalPredicates = [NotInMicroMips] in { -def : MipsInstAlias<"jalrc $rs", (JIALC GPR32Opnd:$rs, 0), 1>, ISA_MIPS32R6, GPR_32; +def : MipsInstAlias<"jalrc $rs", (JIALC GPR32Opnd:$rs, 0), 1>, + ISA_MIPS32R6, GPR_32; } def : MipsInstAlias<"div $rs, $rt", (DIV GPR32Opnd:$rs, GPR32Opnd:$rs, diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td index cc15949b0d57..306289d56e4b 100644 --- a/llvm/lib/Target/Mips/Mips64InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td @@ -83,6 +83,10 @@ let usesCustomInserter = 1 in { def ATOMIC_LOAD_NAND_I64 : Atomic2Ops<atomic_load_nand_64, GPR64>; def ATOMIC_SWAP_I64 : Atomic2Ops<atomic_swap_64, GPR64>; def ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap<atomic_cmp_swap_64, GPR64>; + def ATOMIC_LOAD_MIN_I64 : Atomic2Ops<atomic_load_min_64, GPR64>; + def ATOMIC_LOAD_MAX_I64 : Atomic2Ops<atomic_load_max_64, GPR64>; + def ATOMIC_LOAD_UMIN_I64 : Atomic2Ops<atomic_load_umin_64, GPR64>; + def ATOMIC_LOAD_UMAX_I64 : Atomic2Ops<atomic_load_umax_64, GPR64>; } def ATOMIC_LOAD_ADD_I64_POSTRA : Atomic2OpsPostRA<GPR64>; @@ -96,6 +100,11 @@ def ATOMIC_SWAP_I64_POSTRA : Atomic2OpsPostRA<GPR64>; def ATOMIC_CMP_SWAP_I64_POSTRA : AtomicCmpSwapPostRA<GPR64>; +def ATOMIC_LOAD_MIN_I64_POSTRA : Atomic2OpsPostRA<GPR64>; +def ATOMIC_LOAD_MAX_I64_POSTRA : Atomic2OpsPostRA<GPR64>; +def ATOMIC_LOAD_UMIN_I64_POSTRA : Atomic2OpsPostRA<GPR64>; +def ATOMIC_LOAD_UMAX_I64_POSTRA : Atomic2OpsPostRA<GPR64>; + /// Pseudo instructions for loading and storing accumulator registers. let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { def LOAD_ACC128 : Load<"", ACC128>; @@ -395,11 +404,11 @@ let AdditionalPredicates = [NotInMicroMips] in { } let isCodeGenOnly = 1, AdditionalPredicates = [NotInMicroMips] in { - def DEXT64_32 : InstSE<(outs GPR64Opnd:$rt), - (ins GPR32Opnd:$rs, uimm5_report_uimm6:$pos, - uimm5_plus1:$size), - "dext $rt, $rs, $pos, $size", [], II_EXT, FrmR, "dext">, - EXT_FM<3>, ISA_MIPS64R2; + def DEXT64_32 + : InstSE<(outs GPR64Opnd:$rt), + (ins GPR32Opnd:$rs, uimm5_report_uimm6:$pos, uimm5_plus1:$size), + "dext $rt, $rs, $pos, $size", [], II_EXT, FrmR, "dext">, + EXT_FM<3>, ISA_MIPS64R2; } let isCodeGenOnly = 1, rs = 0, shamt = 0 in { @@ -586,6 +595,24 @@ def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd, II_DMTC2>, MFC2OP_FM<0x12, 5>, ASE_CNMIPS; } +// Cavium Octeon+ cnMIPS instructions +let DecoderNamespace = "CnMipsP", + // FIXME: The lack of HasStdEnc is probably a bug + EncodingPredicates = []<Predicate> in { + +class Saa<string opstr>: + InstSE<(outs), (ins GPR64Opnd:$rt, GPR64Opnd:$rs), + !strconcat(opstr, "\t$rt, (${rs})"), [], NoItinerary, FrmR, opstr>; + +def SAA : Saa<"saa">, SAA_FM<0x18>, ASE_CNMIPSP; +def SAAD : Saa<"saad">, SAA_FM<0x19>, ASE_CNMIPSP; + +def SaaAddr : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rt, mem:$addr), + "saa\t$rt, $addr">, ASE_CNMIPSP; +def SaadAddr : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rt, mem:$addr), + "saad\t$rt, $addr">, ASE_CNMIPSP; +} + } /// Move between CPU and coprocessor registers @@ -1027,8 +1054,10 @@ let AdditionalPredicates = [NotInMicroMips] in { (DMTGC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>, ISA_MIPS64R5, ASE_VIRT; } -def : MipsInstAlias<"dmfc2 $rt, $rd", (DMFC2 GPR64Opnd:$rt, COP2Opnd:$rd, 0), 0>; -def : MipsInstAlias<"dmtc2 $rt, $rd", (DMTC2 COP2Opnd:$rd, GPR64Opnd:$rt, 0), 0>; +def : MipsInstAlias<"dmfc2 $rt, $rd", + (DMFC2 GPR64Opnd:$rt, COP2Opnd:$rd, 0), 0>; +def : MipsInstAlias<"dmtc2 $rt, $rd", + (DMTC2 COP2Opnd:$rd, GPR64Opnd:$rt, 0), 0>; def : MipsInstAlias<"synciobdma", (SYNC 0x2), 0>, ASE_MIPS64_CNMIPS; def : MipsInstAlias<"syncs", (SYNC 0x6), 0>, ASE_MIPS64_CNMIPS; diff --git a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td index d746bb61f824..33132d9ede92 100644 --- a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td @@ -48,7 +48,8 @@ class CRC32CD_ENC : SPECIAL3_2R_SZ_CRC<3,1>; // //===----------------------------------------------------------------------===// -class AHI_ATI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, InstrItinClass itin> { +class AHI_ATI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin> { dag OutOperandList = (outs GPROpnd:$rs); dag InOperandList = (ins GPROpnd:$rt, uimm16_altrelaxed:$imm); string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $imm"); @@ -74,7 +75,7 @@ class DMUL_R6_DESC : MUL_R6_DESC_BASE<"dmul", GPR64Opnd, II_DMUL, mul>; class DMULU_DESC : MUL_R6_DESC_BASE<"dmulu", GPR64Opnd, II_DMUL>; class LDPC_DESC : PCREL_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3, II_LDPC>; class LWUPC_DESC : PCREL_DESC_BASE<"lwupc", GPR32Opnd, simm19_lsl2, II_LWUPC>; -class LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd, mem_simmptr, II_LLD>; +class LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd, mem_simm9_exp, II_LLD>; class SCD_R6_DESC : SC_R6_DESC_BASE<"scd", GPR64Opnd, II_SCD>; class SELEQZ64_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR64Opnd>; class SELNEZ64_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR64Opnd>; @@ -105,7 +106,7 @@ class JIC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, GPR64Opnd, list<Register> Defs = [AT]; } -class LL64_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9, II_LL>; +class LL64_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9_exp, II_LL>; class SC64_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd, II_SC>; class JR_HB64_R6_DESC : JR_HB_DESC_BASE<"jr.hb", GPR64Opnd> { diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 2201545adc94..8f75336dce5a 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -257,6 +257,10 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { if (emitPseudoExpansionLowering(*OutStreamer, &*I)) continue; + // Skip the BUNDLE pseudo instruction and lower the contents + if (I->isBundle()) + continue; + if (I->getOpcode() == Mips::PseudoReturn || I->getOpcode() == Mips::PseudoReturn64 || I->getOpcode() == Mips::PseudoIndirectBranch || @@ -623,8 +627,10 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); const MachineOperand &BaseMO = MI->getOperand(OpNum); const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); - assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand."); - assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); + assert(BaseMO.isReg() && + "Unexpected base pointer for inline asm memory operand."); + assert(OffsetMO.isImm() && + "Unexpected offset for inline asm memory operand."); int Offset = OffsetMO.getImm(); // Currently we are expecting either no ExtraCode or 'D','M','L'. @@ -1300,7 +1306,7 @@ bool MipsAsmPrinter::isLongBranchPseudo(int Opcode) const { } // Force static initialization. -extern "C" void LLVMInitializeMipsAsmPrinter() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsAsmPrinter() { RegisterAsmPrinter<MipsAsmPrinter> X(getTheMipsTarget()); RegisterAsmPrinter<MipsAsmPrinter> Y(getTheMipselTarget()); RegisterAsmPrinter<MipsAsmPrinter> A(getTheMips64Target()); diff --git a/llvm/lib/Target/Mips/MipsCallLowering.cpp b/llvm/lib/Target/Mips/MipsCallLowering.cpp index cad82953af50..6ba15c232867 100644 --- a/llvm/lib/Target/Mips/MipsCallLowering.cpp +++ b/llvm/lib/Target/Mips/MipsCallLowering.cpp @@ -299,7 +299,7 @@ Register OutgoingValueHandler::getStackAddress(const CCValAssign &VA, MIRBuilder.buildConstant(OffsetReg, Offset); Register AddrReg = MRI.createGenericVirtualRegister(p0); - MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); + MIRBuilder.buildPtrAdd(AddrReg, SPReg, OffsetReg); MachinePointerInfo MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); @@ -655,7 +655,8 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); - CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), Info.OrigRet.Ty, Call); + CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), Info.OrigRet.Ty, + Call); setLocInfo(ArgLocs, Ins); CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); diff --git a/llvm/lib/Target/Mips/MipsCallingConv.td b/llvm/lib/Target/Mips/MipsCallingConv.td index 88236d8e9abd..204f11f1107c 100644 --- a/llvm/lib/Target/Mips/MipsCallingConv.td +++ b/llvm/lib/Target/Mips/MipsCallingConv.td @@ -139,7 +139,8 @@ def CC_MipsN : CallingConv<[ CCIfType<[i8, i16, i32], CCIfOrigArgWasNotFloat<CCPromoteToType<i64>>>, // The only i32's we have left are soft-float arguments. - CCIfSubtarget<"useSoftFloat()", CCIfType<[i32], CCDelegateTo<CC_MipsN_SoftFloat>>>, + CCIfSubtarget<"useSoftFloat()", CCIfType<[i32], + CCDelegateTo<CC_MipsN_SoftFloat>>>, // Integer arguments are passed in integer registers. CCIfType<[i64], CCAssignToRegWithShadow<[A0_64, A1_64, A2_64, A3_64, diff --git a/llvm/lib/Target/Mips/MipsCondMov.td b/llvm/lib/Target/Mips/MipsCondMov.td index 5affbcbc2101..e9e09a188bf5 100644 --- a/llvm/lib/Target/Mips/MipsCondMov.td +++ b/llvm/lib/Target/Mips/MipsCondMov.td @@ -116,8 +116,8 @@ let AdditionalPredicates = [NotInMicroMips] in { ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; } - def MOVN_I_I : MMRel, CMov_I_I_FT<"movn", GPR32Opnd, GPR32Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; + def MOVN_I_I : MMRel, CMov_I_I_FT<"movn", GPR32Opnd, GPR32Opnd, II_MOVN>, + ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; let isCodeGenOnly = 1 in { def MOVN_I_I64 : CMov_I_I_FT<"movn", GPR32Opnd, GPR64Opnd, II_MOVN>, @@ -226,8 +226,8 @@ let AdditionalPredicates = [NotInMicroMips] in { GPR_64; defm : MovnPats<GPR64, GPR32, MOVN_I64_I, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovnPats<GPR64, GPR64, MOVN_I64_I64, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; + defm : MovnPats<GPR64, GPR64, MOVN_I64_I64, XOR64>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; defm : MovzPats0<GPR32, FGR32, MOVZ_I_S, SLT, SLTu, SLTi, SLTiu>, INSN_MIPS4_32_NOT_32R6_64R6; @@ -236,8 +236,8 @@ let AdditionalPredicates = [NotInMicroMips] in { defm : MovzPats0<GPR64, FGR32, MOVZ_I_S, SLT64, SLTu64, SLTi64, SLTiu64>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovzPats1<GPR64, FGR32, MOVZ_I64_S, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; + defm : MovzPats1<GPR64, FGR32, MOVZ_I64_S, XOR64>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; defm : MovnPats<GPR64, FGR32, MOVN_I64_S, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; @@ -258,8 +258,8 @@ let AdditionalPredicates = [NotInMicroMips] in { INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; defm : MovnPats<GPR32, FGR64, MOVN_I_D64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - defm : MovnPats<GPR64, FGR64, MOVN_I64_D64, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_64; + defm : MovnPats<GPR64, FGR64, MOVN_I64_D64, XOR64>, + INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; } // For targets that don't have conditional-move instructions // we have to match SELECT nodes with pseudo instructions. diff --git a/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp b/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp index f50640521738..1f1a1574443c 100644 --- a/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -127,9 +127,9 @@ static unsigned int longformBranchOpcode(unsigned int Opcode) { llvm_unreachable("Unknown branch type"); } -// FIXME: need to go through this whole constant islands port and check the math -// for branch ranges and clean this up and make some functions to calculate things -// that are done many times identically. +// FIXME: need to go through this whole constant islands port and check +// the math for branch ranges and clean this up and make some functions +// to calculate things that are done many times identically. // Need to refactor some of the code to call this routine. static unsigned int branchMaxOffsets(unsigned int Opcode) { unsigned Bits, Scale; @@ -1519,8 +1519,8 @@ MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) { // we know that RA is saved because we always save it right now. // this requirement will be relaxed later but we also have an alternate // way to implement this that I will implement that does not need jal. - // We should have a way to back out this alignment restriction if we "can" later. - // but it is not harmful. + // We should have a way to back out this alignment restriction + // if we "can" later. but it is not harmful. // DestBB->setAlignment(Align(4)); Br.MaxDisp = ((1<<24)-1) * 2; diff --git a/llvm/lib/Target/Mips/MipsDSPInstrInfo.td b/llvm/lib/Target/Mips/MipsDSPInstrInfo.td index d3e68c014fb7..727d47d06ad4 100644 --- a/llvm/lib/Target/Mips/MipsDSPInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsDSPInstrInfo.td @@ -376,7 +376,7 @@ class LX_DESC_BASE<string instr_asm, SDPatternOperator OpNode, class ADDUH_QB_DESC_BASE<string instr_asm, SDPatternOperator OpNode, InstrItinClass itin, RegisterOperand ROD, - RegisterOperand ROS = ROD, RegisterOperand ROT = ROD> { + RegisterOperand ROS = ROD, RegisterOperand ROT = ROD> { dag OutOperandList = (outs ROD:$rd); dag InOperandList = (ins ROS:$rs, ROT:$rt); string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); @@ -386,7 +386,8 @@ class ADDUH_QB_DESC_BASE<string instr_asm, SDPatternOperator OpNode, } class APPEND_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - Operand ImmOp, SDPatternOperator Imm, InstrItinClass itin> { + Operand ImmOp, SDPatternOperator Imm, + InstrItinClass itin> { dag OutOperandList = (outs GPR32Opnd:$rt); dag InOperandList = (ins GPR32Opnd:$rs, ImmOp:$sa, GPR32Opnd:$src); string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $sa"); @@ -511,7 +512,8 @@ class MFHI_DESC_BASE<string instr_asm, RegisterOperand RO, SDNode OpNode, bit isMoveReg = 1; } -class MTHI_DESC_BASE<string instr_asm, RegisterOperand RO, InstrItinClass itin> { +class MTHI_DESC_BASE<string instr_asm, RegisterOperand RO, + InstrItinClass itin> { dag OutOperandList = (outs RO:$ac); dag InOperandList = (ins GPR32Opnd:$rs); string AsmString = !strconcat(instr_asm, "\t$rs, $ac"); @@ -1304,7 +1306,8 @@ let DecoderNamespace = "MipsDSP", Arch = "dsp", // Pseudo CMP and PICK instructions. class PseudoCMP<Instruction RealInst> : PseudoDSP<(outs DSPCC:$cmp), (ins DSPROpnd:$rs, DSPROpnd:$rt), []>, - PseudoInstExpansion<(RealInst DSPROpnd:$rs, DSPROpnd:$rt)>, NeverHasSideEffects; + PseudoInstExpansion<(RealInst DSPROpnd:$rs, DSPROpnd:$rt)>, + NeverHasSideEffects; class PseudoPICK<Instruction RealInst> : PseudoDSP<(outs DSPROpnd:$rd), (ins DSPCC:$cmp, DSPROpnd:$rs, DSPROpnd:$rt), []>, diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp index aa07dac86828..84ff674569cd 100644 --- a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -91,15 +91,14 @@ enum CompactBranchPolicy { }; static cl::opt<CompactBranchPolicy> MipsCompactBranchPolicy( - "mips-compact-branches",cl::Optional, - cl::init(CB_Optimal), - cl::desc("MIPS Specific: Compact branch policy."), - cl::values( - clEnumValN(CB_Never, "never", "Do not use compact branches if possible."), - clEnumValN(CB_Optimal, "optimal", "Use compact branches where appropiate (default)."), - clEnumValN(CB_Always, "always", "Always use compact branches if possible.") - ) -); + "mips-compact-branches", cl::Optional, cl::init(CB_Optimal), + cl::desc("MIPS Specific: Compact branch policy."), + cl::values(clEnumValN(CB_Never, "never", + "Do not use compact branches if possible."), + clEnumValN(CB_Optimal, "optimal", + "Use compact branches where appropiate (default)."), + clEnumValN(CB_Always, "always", + "Always use compact branches if possible."))); namespace { @@ -417,8 +416,14 @@ bool RegDefsUses::update(const MachineInstr &MI, unsigned Begin, unsigned End) { for (unsigned I = Begin; I != End; ++I) { const MachineOperand &MO = MI.getOperand(I); - if (MO.isReg() && MO.getReg()) - HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.getReg(), MO.isDef()); + if (MO.isReg() && MO.getReg()) { + if (checkRegDefsUses(NewDefs, NewUses, MO.getReg(), MO.isDef())) { + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found register hazard for operand " + << I << ": "; + MO.dump()); + HasHazard = true; + } + } } Defs |= NewDefs; @@ -613,12 +618,18 @@ bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) { if (MipsCompactBranchPolicy.getValue() != CB_Always || !TII->getEquivalentCompactForm(I)) { if (searchBackward(MBB, *I)) { + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot" + " in backwards search.\n"); Filled = true; } else if (I->isTerminator()) { if (searchSuccBBs(MBB, I)) { Filled = true; + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot" + " in successor BB search.\n"); } } else if (searchForward(MBB, I)) { + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot" + " in forwards search.\n"); Filled = true; } } @@ -663,6 +674,8 @@ bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) { } // Bundle the NOP to the instruction with the delay slot. + LLVM_DEBUG(dbgs() << DEBUG_TYPE << ": could not fill delay slot for "; + I->dump()); BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); MIBundleBuilder(MBB, I, std::next(I, 2)); ++FilledSlots; @@ -680,13 +693,27 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin, for (IterTy I = Begin; I != End;) { IterTy CurrI = I; ++I; - + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": checking instruction: "; CurrI->dump()); // skip debug value - if (CurrI->isDebugInstr()) + if (CurrI->isDebugInstr()) { + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": ignoring debug instruction: "; + CurrI->dump()); continue; + } + + if (CurrI->isBundle()) { + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": ignoring BUNDLE instruction: "; + CurrI->dump()); + // However, we still need to update the register def-use information. + RegDU.update(*CurrI, 0, CurrI->getNumOperands()); + continue; + } - if (terminateSearch(*CurrI)) + if (terminateSearch(*CurrI)) { + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": should terminate search: "; + CurrI->dump()); break; + } assert((!CurrI->isCall() && !CurrI->isReturn() && !CurrI->isBranch()) && "Cannot put calls, returns or branches in delay slot."); @@ -732,6 +759,9 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin, continue; Filler = CurrI; + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot: "; + CurrI->dump()); + return true; } @@ -752,8 +782,11 @@ bool MipsDelaySlotFiller::searchBackward(MachineBasicBlock &MBB, MachineBasicBlock::iterator SlotI = Slot; if (!searchRange(MBB, ++SlotI.getReverse(), MBB.rend(), RegDU, MemDU, Slot, - Filler)) + Filler)) { + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": could not find instruction for delay " + "slot using backwards search.\n"); return false; + } MBB.splice(std::next(SlotI), &MBB, Filler.getReverse()); MIBundleBuilder(MBB, SlotI, std::next(SlotI, 2)); @@ -773,8 +806,11 @@ bool MipsDelaySlotFiller::searchForward(MachineBasicBlock &MBB, RegDU.setCallerSaved(*Slot); - if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Slot, Filler)) + if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Slot, Filler)) { + LLVM_DEBUG(dbgs() << DEBUG_TYPE ": could not find instruction for delay " + "slot using forwards search.\n"); return false; + } MBB.splice(std::next(Slot), &MBB, Filler); MIBundleBuilder(MBB, Slot, std::next(Slot, 2)); @@ -927,4 +963,6 @@ bool MipsDelaySlotFiller::terminateSearch(const MachineInstr &Candidate) const { /// createMipsDelaySlotFillerPass - Returns a pass that fills in delay /// slots in Mips MachineFunctions -FunctionPass *llvm::createMipsDelaySlotFillerPass() { return new MipsDelaySlotFiller(); } +FunctionPass *llvm::createMipsDelaySlotFillerPass() { + return new MipsDelaySlotFiller(); +} diff --git a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp index 00cd284e7094..b1abf4a33717 100644 --- a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp +++ b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp @@ -308,7 +308,7 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); DebugLoc DL = I->getDebugLoc(); - unsigned LL, SC; + unsigned LL, SC, SLT, SLTu, OR, MOVN, MOVZ, SELNEZ, SELEQZ; unsigned BEQ = Mips::BEQ; unsigned SEOp = Mips::SEH; @@ -316,15 +316,32 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; + SLT = Mips::SLT_MM; + SLTu = Mips::SLTu_MM; + OR = STI->hasMips32r6() ? Mips::OR_MMR6 : Mips::OR_MM; + MOVN = Mips::MOVN_I_MM; + MOVZ = Mips::MOVZ_I_MM; + SELNEZ = STI->hasMips32r6() ? Mips::SELNEZ_MMR6 : Mips::SELNEZ; + SELEQZ = STI->hasMips32r6() ? Mips::SELEQZ_MMR6 : Mips::SELEQZ; } else { LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) : (ArePtrs64bit ? Mips::LL64 : Mips::LL); SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) : (ArePtrs64bit ? Mips::SC64 : Mips::SC); + SLT = Mips::SLT; + SLTu = Mips::SLTu; + OR = Mips::OR; + MOVN = Mips::MOVN_I_I; + MOVZ = Mips::MOVZ_I_I; + SELNEZ = Mips::SELNEZ; + SELEQZ = Mips::SELEQZ; } bool IsSwap = false; bool IsNand = false; + bool IsMin = false; + bool IsMax = false; + bool IsUnsigned = false; unsigned Opcode = 0; switch (I->getOpcode()) { @@ -370,6 +387,22 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( case Mips::ATOMIC_LOAD_XOR_I16_POSTRA: Opcode = Mips::XOR; break; + case Mips::ATOMIC_LOAD_UMIN_I8_POSTRA: + case Mips::ATOMIC_LOAD_UMIN_I16_POSTRA: + IsUnsigned = true; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_LOAD_MIN_I8_POSTRA: + case Mips::ATOMIC_LOAD_MIN_I16_POSTRA: + IsMin = true; + break; + case Mips::ATOMIC_LOAD_UMAX_I8_POSTRA: + case Mips::ATOMIC_LOAD_UMAX_I16_POSTRA: + IsUnsigned = true; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_LOAD_MAX_I8_POSTRA: + case Mips::ATOMIC_LOAD_MAX_I16_POSTRA: + IsMax = true; + break; default: llvm_unreachable("Unknown subword atomic pseudo for expansion!"); } @@ -415,6 +448,68 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) .addReg(BinOpRes) .addReg(Mask); + } else if (IsMin || IsMax) { + + assert(I->getNumOperands() == 10 && + "Atomics min|max|umin|umax use an additional register"); + Register Scratch4 = I->getOperand(9).getReg(); + + unsigned SLTScratch4 = IsUnsigned ? SLTu : SLT; + unsigned SELIncr = IsMax ? SELNEZ : SELEQZ; + unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ; + unsigned MOVIncr = IsMax ? MOVN : MOVZ; + + // For little endian we need to clear uninterested bits. + if (STI->isLittle()) { + // and OldVal, OldVal, Mask + // and Incr, Incr, Mask + BuildMI(loopMBB, DL, TII->get(Mips::AND), OldVal) + .addReg(OldVal) + .addReg(Mask); + BuildMI(loopMBB, DL, TII->get(Mips::AND), Incr).addReg(Incr).addReg(Mask); + } + + // unsigned: sltu Scratch4, oldVal, Incr + // signed: slt Scratch4, oldVal, Incr + BuildMI(loopMBB, DL, TII->get(SLTScratch4), Scratch4) + .addReg(OldVal) + .addReg(Incr); + + if (STI->hasMips64r6() || STI->hasMips32r6()) { + // max: seleqz BinOpRes, OldVal, Scratch4 + // selnez Scratch4, Incr, Scratch4 + // or BinOpRes, BinOpRes, Scratch4 + // min: selnqz BinOpRes, OldVal, Scratch4 + // seleqz Scratch4, Incr, Scratch4 + // or BinOpRes, BinOpRes, Scratch4 + BuildMI(loopMBB, DL, TII->get(SELOldVal), BinOpRes) + .addReg(OldVal) + .addReg(Scratch4); + BuildMI(loopMBB, DL, TII->get(SELIncr), Scratch4) + .addReg(Incr) + .addReg(Scratch4); + BuildMI(loopMBB, DL, TII->get(OR), BinOpRes) + .addReg(BinOpRes) + .addReg(Scratch4); + } else { + // max: move BinOpRes, OldVal + // movn BinOpRes, Incr, Scratch4, BinOpRes + // min: move BinOpRes, OldVal + // movz BinOpRes, Incr, Scratch4, BinOpRes + BuildMI(loopMBB, DL, TII->get(OR), BinOpRes) + .addReg(OldVal) + .addReg(Mips::ZERO); + BuildMI(loopMBB, DL, TII->get(MOVIncr), BinOpRes) + .addReg(Incr) + .addReg(Scratch4) + .addReg(BinOpRes); + } + + // and BinOpRes, BinOpRes, Mask + BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) + .addReg(BinOpRes) + .addReg(Mask); + } else if (!IsSwap) { // <binop> binopres, oldval, incr2 // and newval, binopres, mask @@ -488,13 +583,20 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); DebugLoc DL = I->getDebugLoc(); - unsigned LL, SC, ZERO, BEQ; + unsigned LL, SC, ZERO, BEQ, SLT, SLTu, OR, MOVN, MOVZ, SELNEZ, SELEQZ; if (Size == 4) { if (STI->inMicroMipsMode()) { LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; + SLT = Mips::SLT_MM; + SLTu = Mips::SLTu_MM; + OR = STI->hasMips32r6() ? Mips::OR_MMR6 : Mips::OR_MM; + MOVN = Mips::MOVN_I_MM; + MOVZ = Mips::MOVZ_I_MM; + SELNEZ = STI->hasMips32r6() ? Mips::SELNEZ_MMR6 : Mips::SELNEZ; + SELEQZ = STI->hasMips32r6() ? Mips::SELEQZ_MMR6 : Mips::SELEQZ; } else { LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) @@ -503,6 +605,13 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) : (ArePtrs64bit ? Mips::SC64 : Mips::SC); BEQ = Mips::BEQ; + SLT = Mips::SLT; + SLTu = Mips::SLTu; + OR = Mips::OR; + MOVN = Mips::MOVN_I_I; + MOVZ = Mips::MOVZ_I_I; + SELNEZ = Mips::SELNEZ; + SELEQZ = Mips::SELEQZ; } ZERO = Mips::ZERO; @@ -511,6 +620,13 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; ZERO = Mips::ZERO_64; BEQ = Mips::BEQ64; + SLT = Mips::SLT64; + SLTu = Mips::SLTu64; + OR = Mips::OR64; + MOVN = Mips::MOVN_I64_I64; + MOVZ = Mips::MOVZ_I64_I64; + SELNEZ = Mips::SELNEZ64; + SELEQZ = Mips::SELEQZ64; } Register OldVal = I->getOperand(0).getReg(); @@ -519,10 +635,15 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, Register Scratch = I->getOperand(3).getReg(); unsigned Opcode = 0; - unsigned OR = 0; unsigned AND = 0; unsigned NOR = 0; + + bool IsOr = false; bool IsNand = false; + bool IsMin = false; + bool IsMax = false; + bool IsUnsigned = false; + switch (I->getOpcode()) { case Mips::ATOMIC_LOAD_ADD_I32_POSTRA: Opcode = Mips::ADDu; @@ -545,7 +666,7 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, NOR = Mips::NOR; break; case Mips::ATOMIC_SWAP_I32_POSTRA: - OR = Mips::OR; + IsOr = true; break; case Mips::ATOMIC_LOAD_ADD_I64_POSTRA: Opcode = Mips::DADDu; @@ -568,7 +689,23 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, NOR = Mips::NOR64; break; case Mips::ATOMIC_SWAP_I64_POSTRA: - OR = Mips::OR64; + IsOr = true; + break; + case Mips::ATOMIC_LOAD_UMIN_I32_POSTRA: + case Mips::ATOMIC_LOAD_UMIN_I64_POSTRA: + IsUnsigned = true; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_LOAD_MIN_I32_POSTRA: + case Mips::ATOMIC_LOAD_MIN_I64_POSTRA: + IsMin = true; + break; + case Mips::ATOMIC_LOAD_UMAX_I32_POSTRA: + case Mips::ATOMIC_LOAD_UMAX_I64_POSTRA: + IsUnsigned = true; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_LOAD_MAX_I32_POSTRA: + case Mips::ATOMIC_LOAD_MAX_I64_POSTRA: + IsMax = true; break; default: llvm_unreachable("Unknown pseudo atomic!"); @@ -592,7 +729,59 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); assert((OldVal != Ptr) && "Clobbered the wrong ptr reg!"); assert((OldVal != Incr) && "Clobbered the wrong reg!"); - if (Opcode) { + if (IsMin || IsMax) { + + assert(I->getNumOperands() == 5 && + "Atomics min|max|umin|umax use an additional register"); + Register Scratch2 = I->getOperand(4).getReg(); + + // On Mips64 result of slt is GPR32. + Register Scratch2_32 = + (Size == 8) ? STI->getRegisterInfo()->getSubReg(Scratch2, Mips::sub_32) + : Scratch2; + + unsigned SLTScratch2 = IsUnsigned ? SLTu : SLT; + unsigned SELIncr = IsMax ? SELNEZ : SELEQZ; + unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ; + unsigned MOVIncr = IsMax ? MOVN : MOVZ; + + // unsigned: sltu Scratch2, oldVal, Incr + // signed: slt Scratch2, oldVal, Incr + BuildMI(loopMBB, DL, TII->get(SLTScratch2), Scratch2_32) + .addReg(OldVal) + .addReg(Incr); + + if (STI->hasMips64r6() || STI->hasMips32r6()) { + // max: seleqz Scratch, OldVal, Scratch2 + // selnez Scratch2, Incr, Scratch2 + // or Scratch, Scratch, Scratch2 + // min: selnez Scratch, OldVal, Scratch2 + // seleqz Scratch2, Incr, Scratch2 + // or Scratch, Scratch, Scratch2 + BuildMI(loopMBB, DL, TII->get(SELOldVal), Scratch) + .addReg(OldVal) + .addReg(Scratch2); + BuildMI(loopMBB, DL, TII->get(SELIncr), Scratch2) + .addReg(Incr) + .addReg(Scratch2); + BuildMI(loopMBB, DL, TII->get(OR), Scratch) + .addReg(Scratch) + .addReg(Scratch2); + } else { + // max: move Scratch, OldVal + // movn Scratch, Incr, Scratch2, Scratch + // min: move Scratch, OldVal + // movz Scratch, Incr, Scratch2, Scratch + BuildMI(loopMBB, DL, TII->get(OR), Scratch) + .addReg(OldVal) + .addReg(ZERO); + BuildMI(loopMBB, DL, TII->get(MOVIncr), Scratch) + .addReg(Incr) + .addReg(Scratch2) + .addReg(Scratch); + } + + } else if (Opcode) { BuildMI(loopMBB, DL, TII->get(Opcode), Scratch).addReg(OldVal).addReg(Incr); } else if (IsNand) { assert(AND && NOR && @@ -600,12 +789,19 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, BuildMI(loopMBB, DL, TII->get(AND), Scratch).addReg(OldVal).addReg(Incr); BuildMI(loopMBB, DL, TII->get(NOR), Scratch).addReg(ZERO).addReg(Scratch); } else { - assert(OR && "Unknown instruction for atomic pseudo expansion!"); + assert(IsOr && OR && "Unknown instruction for atomic pseudo expansion!"); + (void)IsOr; BuildMI(loopMBB, DL, TII->get(OR), Scratch).addReg(Incr).addReg(ZERO); } - BuildMI(loopMBB, DL, TII->get(SC), Scratch).addReg(Scratch).addReg(Ptr).addImm(0); - BuildMI(loopMBB, DL, TII->get(BEQ)).addReg(Scratch).addReg(ZERO).addMBB(loopMBB); + BuildMI(loopMBB, DL, TII->get(SC), Scratch) + .addReg(Scratch) + .addReg(Ptr) + .addImm(0); + BuildMI(loopMBB, DL, TII->get(BEQ)) + .addReg(Scratch) + .addReg(ZERO) + .addMBB(loopMBB); NMBBI = BB.end(); I->eraseFromParent(); @@ -644,6 +840,14 @@ bool MipsExpandPseudo::expandMI(MachineBasicBlock &MBB, case Mips::ATOMIC_LOAD_OR_I16_POSTRA: case Mips::ATOMIC_LOAD_XOR_I8_POSTRA: case Mips::ATOMIC_LOAD_XOR_I16_POSTRA: + case Mips::ATOMIC_LOAD_MIN_I8_POSTRA: + case Mips::ATOMIC_LOAD_MIN_I16_POSTRA: + case Mips::ATOMIC_LOAD_MAX_I8_POSTRA: + case Mips::ATOMIC_LOAD_MAX_I16_POSTRA: + case Mips::ATOMIC_LOAD_UMIN_I8_POSTRA: + case Mips::ATOMIC_LOAD_UMIN_I16_POSTRA: + case Mips::ATOMIC_LOAD_UMAX_I8_POSTRA: + case Mips::ATOMIC_LOAD_UMAX_I16_POSTRA: return expandAtomicBinOpSubword(MBB, MBBI, NMBB); case Mips::ATOMIC_LOAD_ADD_I32_POSTRA: case Mips::ATOMIC_LOAD_SUB_I32_POSTRA: @@ -652,6 +856,10 @@ bool MipsExpandPseudo::expandMI(MachineBasicBlock &MBB, case Mips::ATOMIC_LOAD_XOR_I32_POSTRA: case Mips::ATOMIC_LOAD_NAND_I32_POSTRA: case Mips::ATOMIC_SWAP_I32_POSTRA: + case Mips::ATOMIC_LOAD_MIN_I32_POSTRA: + case Mips::ATOMIC_LOAD_MAX_I32_POSTRA: + case Mips::ATOMIC_LOAD_UMIN_I32_POSTRA: + case Mips::ATOMIC_LOAD_UMAX_I32_POSTRA: return expandAtomicBinOp(MBB, MBBI, NMBB, 4); case Mips::ATOMIC_LOAD_ADD_I64_POSTRA: case Mips::ATOMIC_LOAD_SUB_I64_POSTRA: @@ -660,6 +868,10 @@ bool MipsExpandPseudo::expandMI(MachineBasicBlock &MBB, case Mips::ATOMIC_LOAD_XOR_I64_POSTRA: case Mips::ATOMIC_LOAD_NAND_I64_POSTRA: case Mips::ATOMIC_SWAP_I64_POSTRA: + case Mips::ATOMIC_LOAD_MIN_I64_POSTRA: + case Mips::ATOMIC_LOAD_MAX_I64_POSTRA: + case Mips::ATOMIC_LOAD_UMIN_I64_POSTRA: + case Mips::ATOMIC_LOAD_UMAX_I64_POSTRA: return expandAtomicBinOp(MBB, MBBI, NMBB, 8); default: return Modified; diff --git a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp index e5997af3bcc5..8c36bcd5c8f2 100644 --- a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -314,7 +314,6 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, switch(ConstraintID) { default: llvm_unreachable("Unexpected asm memory constraint"); - case InlineAsm::Constraint_i: case InlineAsm::Constraint_m: case InlineAsm::Constraint_R: case InlineAsm::Constraint_ZC: diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index bf1b4756b24f..46b1f35a6fc7 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -111,21 +111,19 @@ static bool isShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) { MVT MipsTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const { - if (VT.isVector()) { - if (Subtarget.isABI_O32()) { - return MVT::i32; - } else { - return (VT.getSizeInBits() == 32) ? MVT::i32 : MVT::i64; - } - } - return MipsTargetLowering::getRegisterType(Context, VT); + if (!VT.isVector()) + return getRegisterType(Context, VT); + + return Subtarget.isABI_O32() || VT.getSizeInBits() == 32 ? MVT::i32 + : MVT::i64; } unsigned MipsTargetLowering::getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const { if (VT.isVector()) - return std::max((VT.getSizeInBits() / (Subtarget.isABI_O32() ? 32 : 64)), + return std::max(((unsigned)VT.getSizeInBits() / + (Subtarget.isABI_O32() ? 32 : 64)), 1U); return MipsTargetLowering::getNumRegisters(Context, VT); } @@ -528,8 +526,9 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, isMicroMips = Subtarget.inMicroMipsMode(); } -const MipsTargetLowering *MipsTargetLowering::create(const MipsTargetMachine &TM, - const MipsSubtarget &STI) { +const MipsTargetLowering * +MipsTargetLowering::create(const MipsTargetMachine &TM, + const MipsSubtarget &STI) { if (STI.inMips16Mode()) return createMips16TargetLowering(TM, STI); @@ -710,7 +709,8 @@ static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, SDValue True = N->getOperand(1); SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), - SetCC.getOperand(1), ISD::getSetCCInverse(CC, true)); + SetCC.getOperand(1), + ISD::getSetCCInverse(CC, SetCC.getValueType())); return DAG.getNode(ISD::SELECT, DL, FalseTy, SetCC, False, True); } @@ -744,7 +744,8 @@ static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, if (Diff == -1) { ISD::CondCode CC = cast<CondCodeSDNode>(SetCC.getOperand(2))->get(); SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), - SetCC.getOperand(1), ISD::getSetCCInverse(CC, true)); + SetCC.getOperand(1), + ISD::getSetCCInverse(CC, SetCC.getValueType())); return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, True); } @@ -1367,6 +1368,43 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, return emitAtomicCmpSwap(MI, BB); case Mips::ATOMIC_CMP_SWAP_I64: return emitAtomicCmpSwap(MI, BB); + + case Mips::ATOMIC_LOAD_MIN_I8: + return emitAtomicBinaryPartword(MI, BB, 1); + case Mips::ATOMIC_LOAD_MIN_I16: + return emitAtomicBinaryPartword(MI, BB, 2); + case Mips::ATOMIC_LOAD_MIN_I32: + return emitAtomicBinary(MI, BB); + case Mips::ATOMIC_LOAD_MIN_I64: + return emitAtomicBinary(MI, BB); + + case Mips::ATOMIC_LOAD_MAX_I8: + return emitAtomicBinaryPartword(MI, BB, 1); + case Mips::ATOMIC_LOAD_MAX_I16: + return emitAtomicBinaryPartword(MI, BB, 2); + case Mips::ATOMIC_LOAD_MAX_I32: + return emitAtomicBinary(MI, BB); + case Mips::ATOMIC_LOAD_MAX_I64: + return emitAtomicBinary(MI, BB); + + case Mips::ATOMIC_LOAD_UMIN_I8: + return emitAtomicBinaryPartword(MI, BB, 1); + case Mips::ATOMIC_LOAD_UMIN_I16: + return emitAtomicBinaryPartword(MI, BB, 2); + case Mips::ATOMIC_LOAD_UMIN_I32: + return emitAtomicBinary(MI, BB); + case Mips::ATOMIC_LOAD_UMIN_I64: + return emitAtomicBinary(MI, BB); + + case Mips::ATOMIC_LOAD_UMAX_I8: + return emitAtomicBinaryPartword(MI, BB, 1); + case Mips::ATOMIC_LOAD_UMAX_I16: + return emitAtomicBinaryPartword(MI, BB, 2); + case Mips::ATOMIC_LOAD_UMAX_I32: + return emitAtomicBinary(MI, BB); + case Mips::ATOMIC_LOAD_UMAX_I64: + return emitAtomicBinary(MI, BB); + case Mips::PseudoSDIV: case Mips::PseudoUDIV: case Mips::DIV: @@ -1428,6 +1466,7 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr &MI, DebugLoc DL = MI.getDebugLoc(); unsigned AtomicOp; + bool NeedsAdditionalReg = false; switch (MI.getOpcode()) { case Mips::ATOMIC_LOAD_ADD_I32: AtomicOp = Mips::ATOMIC_LOAD_ADD_I32_POSTRA; @@ -1471,6 +1510,38 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr &MI, case Mips::ATOMIC_SWAP_I64: AtomicOp = Mips::ATOMIC_SWAP_I64_POSTRA; break; + case Mips::ATOMIC_LOAD_MIN_I32: + AtomicOp = Mips::ATOMIC_LOAD_MIN_I32_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_MAX_I32: + AtomicOp = Mips::ATOMIC_LOAD_MAX_I32_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_UMIN_I32: + AtomicOp = Mips::ATOMIC_LOAD_UMIN_I32_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_UMAX_I32: + AtomicOp = Mips::ATOMIC_LOAD_UMAX_I32_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_MIN_I64: + AtomicOp = Mips::ATOMIC_LOAD_MIN_I64_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_MAX_I64: + AtomicOp = Mips::ATOMIC_LOAD_MAX_I64_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_UMIN_I64: + AtomicOp = Mips::ATOMIC_LOAD_UMIN_I64_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_UMAX_I64: + AtomicOp = Mips::ATOMIC_LOAD_UMAX_I64_POSTRA; + NeedsAdditionalReg = true; + break; default: llvm_unreachable("Unknown pseudo atomic for replacement!"); } @@ -1523,12 +1594,19 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr &MI, BuildMI(*BB, II, DL, TII->get(Mips::COPY), IncrCopy).addReg(Incr); BuildMI(*BB, II, DL, TII->get(Mips::COPY), PtrCopy).addReg(Ptr); - BuildMI(*BB, II, DL, TII->get(AtomicOp)) - .addReg(OldVal, RegState::Define | RegState::EarlyClobber) - .addReg(PtrCopy) - .addReg(IncrCopy) - .addReg(Scratch, RegState::Define | RegState::EarlyClobber | - RegState::Implicit | RegState::Dead); + MachineInstrBuilder MIB = + BuildMI(*BB, II, DL, TII->get(AtomicOp)) + .addReg(OldVal, RegState::Define | RegState::EarlyClobber) + .addReg(PtrCopy) + .addReg(IncrCopy) + .addReg(Scratch, RegState::Define | RegState::EarlyClobber | + RegState::Implicit | RegState::Dead); + if (NeedsAdditionalReg) { + Register Scratch2 = + RegInfo.createVirtualRegister(RegInfo.getRegClass(OldVal)); + MIB.addReg(Scratch2, RegState::Define | RegState::EarlyClobber | + RegState::Implicit | RegState::Dead); + } MI.eraseFromParent(); @@ -1596,6 +1674,7 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( Register Scratch3 = RegInfo.createVirtualRegister(RC); unsigned AtomicOp = 0; + bool NeedsAdditionalReg = false; switch (MI.getOpcode()) { case Mips::ATOMIC_LOAD_NAND_I8: AtomicOp = Mips::ATOMIC_LOAD_NAND_I8_POSTRA; @@ -1639,6 +1718,38 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( case Mips::ATOMIC_LOAD_XOR_I16: AtomicOp = Mips::ATOMIC_LOAD_XOR_I16_POSTRA; break; + case Mips::ATOMIC_LOAD_MIN_I8: + AtomicOp = Mips::ATOMIC_LOAD_MIN_I8_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_MIN_I16: + AtomicOp = Mips::ATOMIC_LOAD_MIN_I16_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_MAX_I8: + AtomicOp = Mips::ATOMIC_LOAD_MAX_I8_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_MAX_I16: + AtomicOp = Mips::ATOMIC_LOAD_MAX_I16_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_UMIN_I8: + AtomicOp = Mips::ATOMIC_LOAD_UMIN_I8_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_UMIN_I16: + AtomicOp = Mips::ATOMIC_LOAD_UMIN_I16_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_UMAX_I8: + AtomicOp = Mips::ATOMIC_LOAD_UMAX_I8_POSTRA; + NeedsAdditionalReg = true; + break; + case Mips::ATOMIC_LOAD_UMAX_I16: + AtomicOp = Mips::ATOMIC_LOAD_UMAX_I16_POSTRA; + NeedsAdditionalReg = true; + break; default: llvm_unreachable("Unknown subword atomic pseudo for expansion!"); } @@ -1693,19 +1804,25 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( // emitAtomicBinary. In summary, we need a scratch register which is going to // be undef, that is unique among registers chosen for the instruction. - BuildMI(BB, DL, TII->get(AtomicOp)) - .addReg(Dest, RegState::Define | RegState::EarlyClobber) - .addReg(AlignedAddr) - .addReg(Incr2) - .addReg(Mask) - .addReg(Mask2) - .addReg(ShiftAmt) - .addReg(Scratch, RegState::EarlyClobber | RegState::Define | - RegState::Dead | RegState::Implicit) - .addReg(Scratch2, RegState::EarlyClobber | RegState::Define | - RegState::Dead | RegState::Implicit) - .addReg(Scratch3, RegState::EarlyClobber | RegState::Define | - RegState::Dead | RegState::Implicit); + MachineInstrBuilder MIB = + BuildMI(BB, DL, TII->get(AtomicOp)) + .addReg(Dest, RegState::Define | RegState::EarlyClobber) + .addReg(AlignedAddr) + .addReg(Incr2) + .addReg(Mask) + .addReg(Mask2) + .addReg(ShiftAmt) + .addReg(Scratch, RegState::EarlyClobber | RegState::Define | + RegState::Dead | RegState::Implicit) + .addReg(Scratch2, RegState::EarlyClobber | RegState::Define | + RegState::Dead | RegState::Implicit) + .addReg(Scratch3, RegState::EarlyClobber | RegState::Define | + RegState::Dead | RegState::Implicit); + if (NeedsAdditionalReg) { + Register Scratch4 = RegInfo.createVirtualRegister(RC); + MIB.addReg(Scratch4, RegState::EarlyClobber | RegState::Define | + RegState::Dead | RegState::Implicit); + } MI.eraseFromParent(); // The instruction is gone now. @@ -2804,7 +2921,8 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, // allocate a register directly. Reg = State.AllocateReg(IntRegs); } - } else if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) { + } else if (ValVT == MVT::i32 || + (ValVT == MVT::f32 && AllocateFloatsInIntReg)) { Reg = State.AllocateReg(IntRegs); // If this is the first part of an i64 arg, // the allocated register must be either A0 or A2. @@ -2993,6 +3111,14 @@ void MipsTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, StringRef Sym; if (const GlobalAddressSDNode *G = dyn_cast_or_null<const GlobalAddressSDNode>(TargetAddr)) { + // We must not emit the R_MIPS_JALR relocation against data symbols + // since this will cause run-time crashes if the linker replaces the + // call instruction with a relative branch to the data symbol. + if (!isa<Function>(G->getGlobal())) { + LLVM_DEBUG(dbgs() << "Not adding R_MIPS_JALR against data symbol " + << G->getGlobal()->getName() << "\n"); + return; + } Sym = G->getGlobal()->getName(); } else if (const ExternalSymbolSDNode *ES = @@ -3005,6 +3131,7 @@ void MipsTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, MachineFunction *MF = MI.getParent()->getParent(); MCSymbol *S = MF->getContext().getOrCreateSymbol(Sym); + LLVM_DEBUG(dbgs() << "Adding R_MIPS_JALR against " << Sym << "\n"); MI.addOperand(MachineOperand::CreateMCSymbol(S, MipsII::MO_JALR)); } } @@ -3625,8 +3752,8 @@ MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv, return CCInfo.CheckReturn(Outs, RetCC_Mips); } -bool -MipsTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { +bool MipsTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, + bool IsSigned) const { if ((ABI.IsN32() || ABI.IsN64()) && Type == MVT::i32) return true; @@ -4006,11 +4133,13 @@ MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, } } - std::pair<unsigned, const TargetRegisterClass *> R; - R = parseRegForInlineAsmConstraint(Constraint, VT); + if (!Constraint.empty()) { + std::pair<unsigned, const TargetRegisterClass *> R; + R = parseRegForInlineAsmConstraint(Constraint, VT); - if (R.second) - return R; + if (R.second) + return R; + } return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); } @@ -4113,7 +4242,8 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, bool MipsTargetLowering::isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, - unsigned AS, Instruction *I) const { + unsigned AS, + Instruction *I) const { // No global is ever allowed as a base. if (AM.BaseGV) return false; @@ -4489,8 +4619,9 @@ MachineBasicBlock *MipsTargetLowering::emitPseudoSELECT(MachineInstr &MI, return BB; } -MachineBasicBlock *MipsTargetLowering::emitPseudoD_SELECT(MachineInstr &MI, - MachineBasicBlock *BB) const { +MachineBasicBlock * +MipsTargetLowering::emitPseudoD_SELECT(MachineInstr &MI, + MachineBasicBlock *BB) const { assert(!(Subtarget.hasMips4() || Subtarget.hasMips32()) && "Subtarget already supports SELECT nodes with the use of" "conditional-move instructions."); @@ -4566,8 +4697,9 @@ MachineBasicBlock *MipsTargetLowering::emitPseudoD_SELECT(MachineInstr &MI, // FIXME? Maybe this could be a TableGen attribute on some registers and // this table could be generated automatically from RegInfo. -Register MipsTargetLowering::getRegisterByName(const char* RegName, EVT VT, - const MachineFunction &MF) const { +Register +MipsTargetLowering::getRegisterByName(const char *RegName, LLT VT, + const MachineFunction &MF) const { // Named registers is expected to be fairly rare. For now, just support $28 // since the linux kernel uses it. if (Subtarget.isGP64bit()) { diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index 0a5cddd45afb..92cbe1d54c5b 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -348,7 +348,7 @@ class TargetRegisterClass; void HandleByVal(CCState *, unsigned &, unsigned) const override; - Register getRegisterByName(const char* RegName, EVT VT, + Register getRegisterByName(const char* RegName, LLT VT, const MachineFunction &MF) const override; /// If a physical register, this returns the register that receives the diff --git a/llvm/lib/Target/Mips/MipsInstrFPU.td b/llvm/lib/Target/Mips/MipsInstrFPU.td index e94e107e64c2..79776998463f 100644 --- a/llvm/lib/Target/Mips/MipsInstrFPU.td +++ b/llvm/lib/Target/Mips/MipsInstrFPU.td @@ -129,8 +129,9 @@ class ABSS_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, HARDFLOAT, NeverHasSideEffects; -class CVT_PS_S_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, InstrItinClass Itin, bit IsComm, - SDPatternOperator OpNode= null_frag> : +class CVT_PS_S_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, + InstrItinClass Itin, bit IsComm, + SDPatternOperator OpNode = null_frag> : InstSE<(outs DstRC:$fd), (ins SrcRC:$fs, SrcRC:$ft), !strconcat(opstr, "\t$fd, $fs, $ft"), [(set DstRC:$fd, (OpNode SrcRC:$fs, SrcRC:$ft))], Itin, FrmFR, opstr>, @@ -142,7 +143,8 @@ multiclass ABSS_M<string opstr, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> { def _D32 : MMRel, ABSS_FT<opstr, AFGR64Opnd, AFGR64Opnd, Itin, OpNode>, FGR_32; - def _D64 : StdMMR6Rel, ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, FGR_64 { + def _D64 : StdMMR6Rel, ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, + FGR_64 { string DecoderNamespace = "MipsFP64"; } } @@ -362,17 +364,21 @@ defm D64 : C_COND_M<"d", FGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6, // Floating Point Instructions //===----------------------------------------------------------------------===// let AdditionalPredicates = [NotInMicroMips] in { - def ROUND_W_S : MMRel, StdMMR6Rel, ABSS_FT<"round.w.s", FGR32Opnd, FGR32Opnd, II_ROUND>, - ABSS_FM<0xc, 16>, ISA_MIPS2; - defm ROUND_W : ROUND_M<"round.w.d", II_ROUND>, ABSS_FM<0xc, 17>, ISA_MIPS2; - def TRUNC_W_S : MMRel, StdMMR6Rel, ABSS_FT<"trunc.w.s", FGR32Opnd, FGR32Opnd, II_TRUNC>, - ABSS_FM<0xd, 16>, ISA_MIPS2; - def CEIL_W_S : MMRel, StdMMR6Rel, ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>, - ABSS_FM<0xe, 16>, ISA_MIPS2; - def FLOOR_W_S : MMRel, StdMMR6Rel, ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd, II_FLOOR>, - ABSS_FM<0xf, 16>, ISA_MIPS2; - def CVT_W_S : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x24, 16>, ISA_MIPS1; + def ROUND_W_S : MMRel, StdMMR6Rel, + ABSS_FT<"round.w.s", FGR32Opnd, FGR32Opnd, II_ROUND>, + ABSS_FM<0xc, 16>, ISA_MIPS2; + defm ROUND_W : ROUND_M<"round.w.d", II_ROUND>, ABSS_FM<0xc, 17>, ISA_MIPS2; + def TRUNC_W_S : MMRel, StdMMR6Rel, + ABSS_FT<"trunc.w.s", FGR32Opnd, FGR32Opnd, II_TRUNC>, + ABSS_FM<0xd, 16>, ISA_MIPS2; + def CEIL_W_S : MMRel, StdMMR6Rel, + ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>, + ABSS_FM<0xe, 16>, ISA_MIPS2; + def FLOOR_W_S : MMRel, StdMMR6Rel, + ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd, II_FLOOR>, + ABSS_FM<0xf, 16>, ISA_MIPS2; + def CVT_W_S : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>, + ABSS_FM<0x24, 16>, ISA_MIPS1; defm TRUNC_W : ROUND_M<"trunc.w.d", II_TRUNC>, ABSS_FM<0xd, 17>, ISA_MIPS2; defm CEIL_W : ROUND_M<"ceil.w.d", II_CEIL>, ABSS_FM<0xe, 17>, ISA_MIPS2; @@ -536,7 +542,8 @@ let AdditionalPredicates = [NotInMicroMips] in { let DecoderNamespace = "MipsFP64"; } - def MTHC1_D32 : MMRel, StdMMR6Rel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, + def MTHC1_D32 : MMRel, StdMMR6Rel, + MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, MFC1_FM<7>, ISA_MIPS32R2, FGR_32; def MTHC1_D64 : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd, II_MTHC1>, MFC1_FM<7>, ISA_MIPS32R2, FGR_64 { @@ -621,7 +628,7 @@ let AdditionalPredicates = [IsNotNaCl, NotInMicroMips], INSN_MIPS5_32R2_NOT_32R6_64R6, FGR_64; } -/// Floating-point Aritmetic +/// Floating-point Arithmetic let AdditionalPredicates = [NotInMicroMips] in { def FADD_S : MMRel, ADDS_FT<"add.s", FGR32Opnd, II_ADD_S, 1, fadd>, ADDS_FM<0x00, 16>, ISA_MIPS1; @@ -950,9 +957,12 @@ multiclass NMADD_NMSUB<Instruction Nmadd, Instruction Nmsub, RegisterOperand RC> } let AdditionalPredicates = [NoNaNsFPMath, HasMadd4, NotInMicroMips] in { - defm : NMADD_NMSUB<NMADD_S, NMSUB_S, FGR32Opnd>, INSN_MIPS4_32R2_NOT_32R6_64R6; - defm : NMADD_NMSUB<NMADD_D32, NMSUB_D32, AFGR64Opnd>, FGR_32, INSN_MIPS4_32R2_NOT_32R6_64R6; - defm : NMADD_NMSUB<NMADD_D64, NMSUB_D64, FGR64Opnd>, FGR_64, INSN_MIPS4_32R2_NOT_32R6_64R6; + defm : NMADD_NMSUB<NMADD_S, NMSUB_S, FGR32Opnd>, + INSN_MIPS4_32R2_NOT_32R6_64R6; + defm : NMADD_NMSUB<NMADD_D32, NMSUB_D32, AFGR64Opnd>, + FGR_32, INSN_MIPS4_32R2_NOT_32R6_64R6; + defm : NMADD_NMSUB<NMADD_D64, NMSUB_D64, FGR64Opnd>, + FGR_64, INSN_MIPS4_32R2_NOT_32R6_64R6; } // Patterns for loads/stores with a reg+imm operand. diff --git a/llvm/lib/Target/Mips/MipsInstrFormats.td b/llvm/lib/Target/Mips/MipsInstrFormats.td index 14f01514f33f..4624c1f2d04a 100644 --- a/llvm/lib/Target/Mips/MipsInstrFormats.td +++ b/llvm/lib/Target/Mips/MipsInstrFormats.td @@ -97,9 +97,6 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern, bit isCTI = 0; // Any form of Control Transfer Instruction. // Required for MIPSR6 bit hasForbiddenSlot = 0; // Instruction has a forbidden slot. - bit IsPCRelativeLoad = 0; // Load instruction with implicit source register - // ($pc) and with explicit offset and destination - // register bit hasFCCRegOperand = 0; // Instruction uses $fcc<X> register and is // present in MIPS-I to MIPS-III. @@ -107,8 +104,7 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern, let TSFlags{3-0} = FormBits; let TSFlags{4} = isCTI; let TSFlags{5} = hasForbiddenSlot; - let TSFlags{6} = IsPCRelativeLoad; - let TSFlags{7} = hasFCCRegOperand; + let TSFlags{6} = hasFCCRegOperand; let DecoderNamespace = "Mips"; @@ -626,6 +622,19 @@ class SEQI_FM<bits<6> funct> : StdArch { let Inst{5-0} = funct; } +class SAA_FM<bits<6> funct> : StdArch { + bits<5> rt; + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = 0x1c; + let Inst{25-21} = rs; + let Inst{20-16} = rt; + let Inst{15-6} = 0; + let Inst{5-0} = funct; +} + //===----------------------------------------------------------------------===// // System calls format <op|code_|funct> //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/llvm/lib/Target/Mips/MipsInstrInfo.cpp index 6bb25ee5754d..25bbe5990827 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.cpp +++ b/llvm/lib/Target/Mips/MipsInstrInfo.cpp @@ -275,7 +275,8 @@ MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch( return BT_CondUncond; } -bool MipsInstrInfo::isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const { +bool MipsInstrInfo::isBranchOffsetInRange(unsigned BranchOpc, + int64_t BrOffset) const { switch (BranchOpc) { case Mips::B: case Mips::BAL: @@ -433,7 +434,6 @@ bool MipsInstrInfo::isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) llvm_unreachable("Unknown branch instruction!"); } - /// Return the corresponding compact (no delay slot) form of a branch. unsigned MipsInstrInfo::getEquivalentCompactForm( const MachineBasicBlock::iterator I) const { diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 58167e0f344d..d9a3ff802708 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -211,6 +211,10 @@ def HasCnMips : Predicate<"Subtarget->hasCnMips()">, AssemblerPredicate<"FeatureCnMips">; def NotCnMips : Predicate<"!Subtarget->hasCnMips()">, AssemblerPredicate<"!FeatureCnMips">; +def HasCnMipsP : Predicate<"Subtarget->hasCnMipsP()">, + AssemblerPredicate<"FeatureCnMipsP">; +def NotCnMipsP : Predicate<"!Subtarget->hasCnMipsP()">, + AssemblerPredicate<"!FeatureCnMipsP">; def IsSym32 : Predicate<"Subtarget->hasSym32()">, AssemblerPredicate<"FeatureSym32">; def IsSym64 : Predicate<"!Subtarget->hasSym32()">, @@ -439,6 +443,14 @@ class NOT_ASE_CNMIPS { list<Predicate> ASEPredicate = [NotCnMips]; } +class ASE_CNMIPSP { + list<Predicate> ASEPredicate = [HasCnMipsP]; +} + +class NOT_ASE_CNMIPSP { + list<Predicate> ASEPredicate = [NotCnMipsP]; +} + class ASE_MIPS64_CNMIPS { list<Predicate> ASEPredicate = [HasMips64, HasCnMips]; } @@ -947,8 +959,7 @@ foreach I = {16} in // Like uimm16_64 but coerces simm16 to uimm16. def uimm16_relaxed : Operand<i32> { let PrintMethod = "printUImm<16>"; - let ParserMatchClass = - !cast<AsmOperandClass>("UImm16RelaxedAsmOperandClass"); + let ParserMatchClass = UImm16RelaxedAsmOperandClass; } foreach I = {5} in @@ -968,14 +979,12 @@ foreach I = {16} in // Like uimm16_64 but coerces simm16 to uimm16. def uimm16_64_relaxed : Operand<i64> { let PrintMethod = "printUImm<16>"; - let ParserMatchClass = - !cast<AsmOperandClass>("UImm16RelaxedAsmOperandClass"); + let ParserMatchClass = UImm16RelaxedAsmOperandClass; } def uimm16_altrelaxed : Operand<i32> { let PrintMethod = "printUImm<16>"; - let ParserMatchClass = - !cast<AsmOperandClass>("UImm16AltRelaxedAsmOperandClass"); + let ParserMatchClass = UImm16AltRelaxedAsmOperandClass; } // Like uimm5 but reports a less confusing error for 32-63 when // an instruction alias permits that. @@ -1048,22 +1057,22 @@ foreach I = {16, 32} in // Like simm16 but coerces uimm16 to simm16. def simm16_relaxed : Operand<i32> { let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; - let ParserMatchClass = !cast<AsmOperandClass>("SImm16RelaxedAsmOperandClass"); + let ParserMatchClass = SImm16RelaxedAsmOperandClass; } def simm16_64 : Operand<i64> { let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; - let ParserMatchClass = !cast<AsmOperandClass>("SImm16AsmOperandClass"); + let ParserMatchClass = SImm16AsmOperandClass; } // like simm32 but coerces simm32 to uimm32. def uimm32_coerced : Operand<i32> { - let ParserMatchClass = !cast<AsmOperandClass>("UImm32CoercedAsmOperandClass"); + let ParserMatchClass = UImm32CoercedAsmOperandClass; } // Like simm32 but coerces uimm32 to simm32. def simm32_relaxed : Operand<i32> { let DecoderMethod = "DecodeSImmWithOffsetAndScale<32>"; - let ParserMatchClass = !cast<AsmOperandClass>("SImm32RelaxedAsmOperandClass"); + let ParserMatchClass = SImm32RelaxedAsmOperandClass; } // This is almost the same as a uimm7 but 0x7f is interpreted as -1. @@ -1077,59 +1086,14 @@ def MipsMemAsmOperand : AsmOperandClass { let ParserMethod = "parseMemOperand"; } -def MipsMemSimm9AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm9"; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<9>"; - let DiagnosticType = "MemSImm9"; -} - -def MipsMemSimm10AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm10"; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<10>"; - let DiagnosticType = "MemSImm10"; -} - -def MipsMemSimm12AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm12"; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<12>"; - let DiagnosticType = "MemSImm12"; -} - -foreach I = {1, 2, 3} in - def MipsMemSimm10Lsl # I # AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm10_" # I; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<10, " # I # ">"; - let DiagnosticType = "MemSImm10Lsl" # I; - } - -def MipsMemSimm11AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm11"; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<11>"; - let DiagnosticType = "MemSImm11"; -} - -def MipsMemSimm16AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm16"; +class MipsMemSimmAsmOperand<int Width, int Shift = 0> : AsmOperandClass { + let Name = "MemOffsetSimm" # Width # "_" # Shift; let SuperClasses = [MipsMemAsmOperand]; let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<16>"; - let DiagnosticType = "MemSImm16"; + let PredicateMethod = "isMemWithSimmOffset<" # Width # ", " # Shift # ">"; + let DiagnosticType = !if(!eq(Shift, 0), "MemSImm" # Width, + "MemSImm" # Width # "Lsl" # Shift); } def MipsMemSimmPtrAsmOperand : AsmOperandClass { @@ -1176,44 +1140,26 @@ def simm12 : Operand<i32> { let DecoderMethod = "DecodeSimm12"; } -def mem_simm9 : mem_generic { +def mem_simm9_exp : mem_generic { let MIOperandInfo = (ops ptr_rc, simm9); - let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemSimm9AsmOperand; + let ParserMatchClass = MipsMemSimmPtrAsmOperand; + let OperandNamespace = "MipsII"; + let OperandType = "OPERAND_MEM_SIMM9"; } -def mem_simm10 : mem_generic { - let MIOperandInfo = (ops ptr_rc, simm10); - let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemSimm10AsmOperand; -} +foreach I = {9, 10, 11, 12, 16} in + def mem_simm # I : mem_generic { + let MIOperandInfo = (ops ptr_rc, !cast<Operand>("simm" # I)); + let ParserMatchClass = MipsMemSimmAsmOperand<I>; + } foreach I = {1, 2, 3} in def mem_simm10_lsl # I : mem_generic { let MIOperandInfo = (ops ptr_rc, !cast<Operand>("simm10_lsl" # I)); let EncoderMethod = "getMemEncoding<" # I # ">"; - let ParserMatchClass = - !cast<AsmOperandClass>("MipsMemSimm10Lsl" # I # "AsmOperand"); + let ParserMatchClass = MipsMemSimmAsmOperand<10, I>; } -def mem_simm11 : mem_generic { - let MIOperandInfo = (ops ptr_rc, simm11); - let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemSimm11AsmOperand; -} - -def mem_simm12 : mem_generic { - let MIOperandInfo = (ops ptr_rc, simm12); - let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemSimm12AsmOperand; -} - -def mem_simm16 : mem_generic { - let MIOperandInfo = (ops ptr_rc, simm16); - let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemSimm16AsmOperand; -} - def mem_simmptr : mem_generic { let ParserMatchClass = MipsMemSimmPtrAsmOperand; } @@ -1260,6 +1206,7 @@ def immSExt8 : PatLeaf<(imm), [{ return isInt<8>(N->getSExtValue()); }]>; // Node immediate fits as 16-bit sign extended on target immediate. // e.g. addi, andi def immSExt16 : PatLeaf<(imm), [{ return isInt<16>(N->getSExtValue()); }]>; +def imm32SExt16 : IntImmLeaf<i32, [{ return isInt<16>(Imm.getSExtValue()); }]>; // Node immediate fits as 7-bit zero extended on target immediate. def immZExt7 : PatLeaf<(imm), [{ return isUInt<7>(N->getZExtValue()); }]>; @@ -1275,6 +1222,9 @@ def immZExt16 : PatLeaf<(imm), [{ else return (uint64_t)N->getZExtValue() == (unsigned short)N->getZExtValue(); }], LO16>; +def imm32ZExt16 : IntImmLeaf<i32, [{ + return (uint32_t)Imm.getZExtValue() == (unsigned short)Imm.getZExtValue(); +}]>; // Immediate can be loaded with LUi (32-bit int with lower 16-bit cleared). def immSExt32Low16Zero : PatLeaf<(imm), [{ @@ -1975,6 +1925,18 @@ let usesCustomInserter = 1 in { def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap<atomic_cmp_swap_16, GPR32>; def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap<atomic_cmp_swap_32, GPR32>; + def ATOMIC_LOAD_MIN_I8 : Atomic2Ops<atomic_load_min_8, GPR32>; + def ATOMIC_LOAD_MIN_I16 : Atomic2Ops<atomic_load_min_16, GPR32>; + def ATOMIC_LOAD_MIN_I32 : Atomic2Ops<atomic_load_min_32, GPR32>; + def ATOMIC_LOAD_MAX_I8 : Atomic2Ops<atomic_load_max_8, GPR32>; + def ATOMIC_LOAD_MAX_I16 : Atomic2Ops<atomic_load_max_16, GPR32>; + def ATOMIC_LOAD_MAX_I32 : Atomic2Ops<atomic_load_max_32, GPR32>; + def ATOMIC_LOAD_UMIN_I8 : Atomic2Ops<atomic_load_umin_8, GPR32>; + def ATOMIC_LOAD_UMIN_I16 : Atomic2Ops<atomic_load_umin_16, GPR32>; + def ATOMIC_LOAD_UMIN_I32 : Atomic2Ops<atomic_load_umin_32, GPR32>; + def ATOMIC_LOAD_UMAX_I8 : Atomic2Ops<atomic_load_umax_8, GPR32>; + def ATOMIC_LOAD_UMAX_I16 : Atomic2Ops<atomic_load_umax_16, GPR32>; + def ATOMIC_LOAD_UMAX_I32 : Atomic2Ops<atomic_load_umax_32, GPR32>; } def ATOMIC_LOAD_ADD_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; @@ -2004,6 +1966,19 @@ def ATOMIC_CMP_SWAP_I8_POSTRA : AtomicCmpSwapSubwordPostRA<GPR32>; def ATOMIC_CMP_SWAP_I16_POSTRA : AtomicCmpSwapSubwordPostRA<GPR32>; def ATOMIC_CMP_SWAP_I32_POSTRA : AtomicCmpSwapPostRA<GPR32>; +def ATOMIC_LOAD_MIN_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_MIN_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_MIN_I32_POSTRA : Atomic2OpsPostRA<GPR32>; +def ATOMIC_LOAD_MAX_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_MAX_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_MAX_I32_POSTRA : Atomic2OpsPostRA<GPR32>; +def ATOMIC_LOAD_UMIN_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_UMIN_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_UMIN_I32_POSTRA : Atomic2OpsPostRA<GPR32>; +def ATOMIC_LOAD_UMAX_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_UMAX_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_UMAX_I32_POSTRA : Atomic2OpsPostRA<GPR32>; + /// Pseudo instructions for loading and storing accumulator registers. let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { def LOAD_ACC64 : Load<"", ACC64>; @@ -2046,17 +2021,17 @@ def LONG_BRANCH_ADDiu2Op : PseudoSE<(outs GPR32Opnd:$dst), /// Arithmetic Instructions (ALU Immediate) let AdditionalPredicates = [NotInMicroMips] in { def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16_relaxed, GPR32Opnd, - II_ADDIU, immSExt16, add>, + II_ADDIU, imm32SExt16, add>, ADDI_FM<0x9>, IsAsCheapAsAMove, ISA_MIPS1; def ANDi : MMRel, StdMMR6Rel, - ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>, + ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, imm32ZExt16, and>, ADDI_FM<0xc>, ISA_MIPS1; def ORi : MMRel, StdMMR6Rel, - ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>, + ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, imm32ZExt16, or>, ADDI_FM<0xd>, ISA_MIPS1; def XORi : MMRel, StdMMR6Rel, - ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>, + ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, imm32ZExt16, xor>, ADDI_FM<0xe>, ISA_MIPS1; def ADDi : MMRel, ArithLogicI<"addi", simm16_relaxed, GPR32Opnd, II_ADDI>, ADDI_FM<0x8>, ISA_MIPS1_NOT_32R6_64R6; @@ -2069,10 +2044,10 @@ let AdditionalPredicates = [NotInMicroMips] in { ISA_MIPS1; /// Arithmetic Instructions (3-Operand, R-Type) - def ADDu : MMRel, StdMMR6Rel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, - ADD_FM<0, 0x21>, ISA_MIPS1; - def SUBu : MMRel, StdMMR6Rel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>, - ADD_FM<0, 0x23>, ISA_MIPS1; + def ADDu : MMRel, StdMMR6Rel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, + ADD_FM<0, 0x21>, ISA_MIPS1; + def SUBu : MMRel, StdMMR6Rel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>, + ADD_FM<0, 0x23>, ISA_MIPS1; let Defs = [HI0, LO0] in def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>, @@ -2137,7 +2112,8 @@ let AdditionalPredicates = [NotInMicroMips] in { LW_FM<0x28>, ISA_MIPS1; def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>, ISA_MIPS1; - def SW : StdMMR6Rel, Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>, ISA_MIPS1; + def SW : StdMMR6Rel, Store<"sw", GPR32Opnd, store, II_SW>, + MMRel, LW_FM<0x2b>, ISA_MIPS1; } /// load/store left/right @@ -2238,7 +2214,8 @@ def J : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>, IsBranch, ISA_MIPS1; let AdditionalPredicates = [NotInMicroMips] in { -def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>, ISA_MIPS1_NOT_32R6_64R6; +def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>, + ISA_MIPS1_NOT_32R6_64R6; def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>, ISA_MIPS1; def BEQL : MMRel, CBranchLikely<"beql", brtarget, GPR32Opnd>, @@ -2396,7 +2373,8 @@ let AdditionalPredicates = [NotInMicroMips] in { // add op with mem ComplexPattern is used and the stack address copy // can be matched. It's similar to Sparc LEA_ADDRi let AdditionalPredicates = [NotInMicroMips] in - def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>, ISA_MIPS1; + def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>, + ISA_MIPS1; // MADD*/MSUB* def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>, @@ -2572,9 +2550,11 @@ def DROLImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), "drol\t$rs, $rt, $imm">, ISA_MIPS64; def : MipsInstAlias<"drol $rd, $rs", - (DROL GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>, ISA_MIPS64; + (DROL GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>, + ISA_MIPS64; def : MipsInstAlias<"drol $rd, $imm", - (DROLImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, ISA_MIPS64; + (DROLImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, + ISA_MIPS64; def DROR : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), @@ -2583,9 +2563,11 @@ def DRORImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), "dror\t$rs, $rt, $imm">, ISA_MIPS64; def : MipsInstAlias<"dror $rd, $rs", - (DROR GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>, ISA_MIPS64; + (DROR GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>, + ISA_MIPS64; def : MipsInstAlias<"dror $rd, $imm", - (DRORImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, ISA_MIPS64; + (DRORImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, + ISA_MIPS64; def ABSMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), "abs\t$rd, $rs">; @@ -2762,7 +2744,8 @@ let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>, ISA_MIPS1; - defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi>, ISA_MIPS1_NOT_32R6_64R6; + defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi>, + ISA_MIPS1_NOT_32R6_64R6; defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu>, ISA_MIPS1; @@ -3089,7 +3072,8 @@ multiclass MaterializeImms<ValueType VT, Register ZEROReg, // observed. // Arbitrary immediates -def : MipsPat<(VT LUiORiPred:$imm), (ORiOp (LUiOp (HI16 imm:$imm)), (LO16 imm:$imm))>; +def : MipsPat<(VT LUiORiPred:$imm), + (ORiOp (LUiOp (HI16 imm:$imm)), (LO16 imm:$imm))>; // Bits 32-16 set, sign/zero extended. def : MipsPat<(VT LUiPred:$imm), (LUiOp (HI16 imm:$imm))>; diff --git a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp index f8fc7cb0898b..2f4c9d74262e 100644 --- a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp +++ b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp @@ -18,6 +18,7 @@ #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/IR/IntrinsicsMips.h" #define DEBUG_TYPE "mips-isel" @@ -39,12 +40,13 @@ public: private: bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const; + bool isRegInGprb(Register Reg, MachineRegisterInfo &MRI) const; + bool isRegInFprb(Register Reg, MachineRegisterInfo &MRI) const; bool materialize32BitImm(Register DestReg, APInt Imm, MachineIRBuilder &B) const; bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const; const TargetRegisterClass * - getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB, - const RegisterBankInfo &RBI) const; + getRegClassForTypeOnBank(Register Reg, MachineRegisterInfo &MRI) const; unsigned selectLoadStoreOpCode(MachineInstr &I, MachineRegisterInfo &MRI) const; @@ -84,24 +86,23 @@ MipsInstructionSelector::MipsInstructionSelector( { } +bool MipsInstructionSelector::isRegInGprb(Register Reg, + MachineRegisterInfo &MRI) const { + return RBI.getRegBank(Reg, MRI, TRI)->getID() == Mips::GPRBRegBankID; +} + +bool MipsInstructionSelector::isRegInFprb(Register Reg, + MachineRegisterInfo &MRI) const { + return RBI.getRegBank(Reg, MRI, TRI)->getID() == Mips::FPRBRegBankID; +} + bool MipsInstructionSelector::selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const { Register DstReg = I.getOperand(0).getReg(); if (Register::isPhysicalRegister(DstReg)) return true; - const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI); - const unsigned DstSize = MRI.getType(DstReg).getSizeInBits(); - - const TargetRegisterClass *RC = &Mips::GPR32RegClass; - if (RegBank->getID() == Mips::FPRBRegBankID) { - if (DstSize == 32) - RC = &Mips::FGR32RegClass; - else if (DstSize == 64) - RC = STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; - else - llvm_unreachable("Unsupported destination size"); - } + const TargetRegisterClass *RC = getRegClassForTypeOnBank(DstReg, MRI); if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) << " operand\n"); @@ -111,19 +112,27 @@ bool MipsInstructionSelector::selectCopy(MachineInstr &I, } const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank( - unsigned OpSize, const RegisterBank &RB, - const RegisterBankInfo &RBI) const { - if (RB.getID() == Mips::GPRBRegBankID) + Register Reg, MachineRegisterInfo &MRI) const { + const LLT Ty = MRI.getType(Reg); + const unsigned TySize = Ty.getSizeInBits(); + + if (isRegInGprb(Reg, MRI)) { + assert((Ty.isScalar() || Ty.isPointer()) && TySize == 32 && + "Register class not available for LLT, register bank combination"); return &Mips::GPR32RegClass; + } - if (RB.getID() == Mips::FPRBRegBankID) - return OpSize == 32 - ? &Mips::FGR32RegClass - : STI.hasMips32r6() || STI.isFP64bit() ? &Mips::FGR64RegClass - : &Mips::AFGR64RegClass; + if (isRegInFprb(Reg, MRI)) { + if (Ty.isScalar()) { + assert((TySize == 32 || TySize == 64) && + "Register class not available for LLT, register bank combination"); + if (TySize == 32) + return &Mips::FGR32RegClass; + return STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; + } + } - llvm_unreachable("getRegClassForTypeOnBank can't find register class."); - return nullptr; + llvm_unreachable("Unsupported register bank."); } bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm, @@ -131,8 +140,9 @@ bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm, assert(Imm.getBitWidth() == 32 && "Unsupported immediate size."); // Ori zero extends immediate. Used for values with zeros in high 16 bits. if (Imm.getHiBits(16).isNullValue()) { - MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)}) - .addImm(Imm.getLoBits(16).getLimitedValue()); + MachineInstr *Inst = + B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)}) + .addImm(Imm.getLoBits(16).getLimitedValue()); return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); } // Lui places immediate in high 16 bits and sets low 16 bits to zero. @@ -143,8 +153,9 @@ bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm, } // ADDiu sign extends immediate. Used for values with 1s in high 17 bits. if (Imm.isSignedIntN(16)) { - MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)}) - .addImm(Imm.getLoBits(16).getLimitedValue()); + MachineInstr *Inst = + B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)}) + .addImm(Imm.getLoBits(16).getLimitedValue()); return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); } // Values that cannot be materialized with single immediate instruction. @@ -160,17 +171,22 @@ bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm, return true; } -/// Returning Opc indicates that we failed to select MIPS instruction opcode. +/// When I.getOpcode() is returned, we failed to select MIPS instruction opcode. unsigned MipsInstructionSelector::selectLoadStoreOpCode(MachineInstr &I, MachineRegisterInfo &MRI) const { - STI.getRegisterInfo(); - const Register DestReg = I.getOperand(0).getReg(); - const unsigned RegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); + const Register ValueReg = I.getOperand(0).getReg(); + const LLT Ty = MRI.getType(ValueReg); + const unsigned TySize = Ty.getSizeInBits(); const unsigned MemSizeInBytes = (*I.memoperands_begin())->getSize(); unsigned Opc = I.getOpcode(); const bool isStore = Opc == TargetOpcode::G_STORE; - if (RegBank == Mips::GPRBRegBankID) { + + if (isRegInGprb(ValueReg, MRI)) { + assert(((Ty.isScalar() && TySize == 32) || + (Ty.isPointer() && TySize == 32 && MemSizeInBytes == 4)) && + "Unsupported register bank, LLT, MemSizeInBytes combination"); + (void)TySize; if (isStore) switch (MemSizeInBytes) { case 4: @@ -196,33 +212,39 @@ MipsInstructionSelector::selectLoadStoreOpCode(MachineInstr &I, } } - if (RegBank == Mips::FPRBRegBankID) { - switch (MemSizeInBytes) { - case 4: - return isStore ? Mips::SWC1 : Mips::LWC1; - case 8: + if (isRegInFprb(ValueReg, MRI)) { + if (Ty.isScalar()) { + assert(((TySize == 32 && MemSizeInBytes == 4) || + (TySize == 64 && MemSizeInBytes == 8)) && + "Unsupported register bank, LLT, MemSizeInBytes combination"); + + if (MemSizeInBytes == 4) + return isStore ? Mips::SWC1 : Mips::LWC1; + if (STI.isFP64bit()) return isStore ? Mips::SDC164 : Mips::LDC164; - else - return isStore ? Mips::SDC1 : Mips::LDC1; - case 16: { + return isStore ? Mips::SDC1 : Mips::LDC1; + } + + if (Ty.isVector()) { assert(STI.hasMSA() && "Vector instructions require target with MSA."); - const unsigned VectorElementSizeInBytes = - MRI.getType(DestReg).getElementType().getSizeInBytes(); - if (VectorElementSizeInBytes == 1) + assert((TySize == 128 && MemSizeInBytes == 16) && + "Unsupported register bank, LLT, MemSizeInBytes combination"); + switch (Ty.getElementType().getSizeInBits()) { + case 8: return isStore ? Mips::ST_B : Mips::LD_B; - if (VectorElementSizeInBytes == 2) + case 16: return isStore ? Mips::ST_H : Mips::LD_H; - if (VectorElementSizeInBytes == 4) + case 32: return isStore ? Mips::ST_W : Mips::LD_W; - if (VectorElementSizeInBytes == 8) + case 64: return isStore ? Mips::ST_D : Mips::LD_D; - return Opc; - } - default: - return Opc; + default: + return Opc; + } } } + return Opc; } @@ -239,7 +261,8 @@ bool MipsInstructionSelector::select(MachineInstr &I) { return true; } - if (I.getOpcode() == Mips::G_MUL) { + if (I.getOpcode() == Mips::G_MUL && + isRegInGprb(I.getOperand(0).getReg(), MRI)) { MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL)) .add(I.getOperand(0)) .add(I.getOperand(1)) @@ -280,7 +303,7 @@ bool MipsInstructionSelector::select(MachineInstr &I) { I.eraseFromParent(); return true; } - case G_GEP: { + case G_PTR_ADD: { MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) .add(I.getOperand(0)) .add(I.getOperand(1)) @@ -367,14 +390,12 @@ bool MipsInstructionSelector::select(MachineInstr &I) { } case G_PHI: { const Register DestReg = I.getOperand(0).getReg(); - const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); const TargetRegisterClass *DefRC = nullptr; if (Register::isPhysicalRegister(DestReg)) DefRC = TRI.getRegClass(DestReg); else - DefRC = getRegClassForTypeOnBank(OpSize, - *RBI.getRegBank(DestReg, MRI, TRI), RBI); + DefRC = getRegClassForTypeOnBank(DestReg, MRI); I.setDesc(TII.get(TargetOpcode::PHI)); return RBI.constrainGenericRegister(DestReg, *DefRC, MRI); @@ -389,15 +410,15 @@ bool MipsInstructionSelector::select(MachineInstr &I) { MachineOperand BaseAddr = I.getOperand(1); int64_t SignedOffset = 0; - // Try to fold load/store + G_GEP + G_CONSTANT + // Try to fold load/store + G_PTR_ADD + G_CONSTANT // %SignedOffset:(s32) = G_CONSTANT i32 16_bit_signed_immediate - // %Addr:(p0) = G_GEP %BaseAddr, %SignedOffset + // %Addr:(p0) = G_PTR_ADD %BaseAddr, %SignedOffset // %LoadResult/%StoreSrc = load/store %Addr(p0) // into: // %LoadResult/%StoreSrc = NewOpc %BaseAddr(p0), 16_bit_signed_immediate MachineInstr *Addr = MRI.getVRegDef(I.getOperand(1).getReg()); - if (Addr->getOpcode() == G_GEP) { + if (Addr->getOpcode() == G_PTR_ADD) { MachineInstr *Offset = MRI.getVRegDef(Addr->getOperand(2).getReg()); if (Offset->getOpcode() == G_CONSTANT) { APInt OffsetValue = Offset->getOperand(1).getCImm()->getValue(); @@ -452,15 +473,12 @@ bool MipsInstructionSelector::select(MachineInstr &I) { break; } case G_IMPLICIT_DEF: { + Register Dst = I.getOperand(0).getReg(); MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::IMPLICIT_DEF)) - .add(I.getOperand(0)); + .addDef(Dst); // Set class based on register bank, there can be fpr and gpr implicit def. - MRI.setRegClass(MI->getOperand(0).getReg(), - getRegClassForTypeOnBank( - MRI.getType(I.getOperand(0).getReg()).getSizeInBits(), - *RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI), - RBI)); + MRI.setRegClass(Dst, getRegClassForTypeOnBank(Dst, MRI)); break; } case G_CONSTANT: { diff --git a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp index bb4a1d902d75..9645aa24dc05 100644 --- a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp +++ b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp @@ -13,6 +13,7 @@ #include "MipsLegalizerInfo.h" #include "MipsTargetMachine.h" #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" +#include "llvm/IR/IntrinsicsMips.h" using namespace llvm; @@ -61,11 +62,7 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { const LLT v2s64 = LLT::vector(2, 64); const LLT p0 = LLT::pointer(0, 32); - getActionDefinitionsBuilder({G_SUB, G_MUL}) - .legalFor({s32}) - .clampScalar(0, s32, s32); - - getActionDefinitionsBuilder(G_ADD) + getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL}) .legalIf([=, &ST](const LegalityQuery &Query) { if (CheckTyN(0, Query, {s32})) return true; @@ -145,8 +142,14 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { .legalFor({s32}) .clampScalar(0, s32, s32); - getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UREM, G_UDIV}) - .legalFor({s32}) + getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UDIV, G_UREM}) + .legalIf([=, &ST](const LegalityQuery &Query) { + if (CheckTyN(0, Query, {s32})) + return true; + if (ST.hasMSA() && CheckTyN(0, Query, {v16s8, v8s16, v4s32, v2s64})) + return true; + return false; + }) .minScalar(0, s32) .libcallFor({s64}); @@ -164,7 +167,7 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { .legalFor({s32}) .clampScalar(0, s32, s32); - getActionDefinitionsBuilder({G_GEP, G_INTTOPTR}) + getActionDefinitionsBuilder({G_PTR_ADD, G_INTTOPTR}) .legalFor({{p0, s32}}); getActionDefinitionsBuilder(G_PTRTOINT) @@ -182,12 +185,35 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { getActionDefinitionsBuilder(G_VASTART) .legalFor({p0}); + getActionDefinitionsBuilder(G_BSWAP) + .legalIf([=, &ST](const LegalityQuery &Query) { + if (ST.hasMips32r2() && CheckTyN(0, Query, {s32})) + return true; + return false; + }) + .lowerIf([=, &ST](const LegalityQuery &Query) { + if (!ST.hasMips32r2() && CheckTyN(0, Query, {s32})) + return true; + return false; + }) + .maxScalar(0, s32); + + getActionDefinitionsBuilder(G_BITREVERSE) + .lowerFor({s32}) + .maxScalar(0, s32); + // FP instructions getActionDefinitionsBuilder(G_FCONSTANT) .legalFor({s32, s64}); getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FABS, G_FSQRT}) - .legalFor({s32, s64}); + .legalIf([=, &ST](const LegalityQuery &Query) { + if (CheckTyN(0, Query, {s32, s64})) + return true; + if (ST.hasMSA() && CheckTyN(0, Query, {v16s8, v8s16, v4s32, v2s64})) + return true; + return false; + }); getActionDefinitionsBuilder(G_FCMP) .legalFor({{s32, s32}, {s32, s64}}) @@ -315,6 +341,17 @@ static bool MSA3OpIntrinsicToGeneric(MachineInstr &MI, unsigned Opcode, return true; } +static bool MSA2OpIntrinsicToGeneric(MachineInstr &MI, unsigned Opcode, + MachineIRBuilder &MIRBuilder, + const MipsSubtarget &ST) { + assert(ST.hasMSA() && "MSA intrinsic not supported on target without MSA."); + MIRBuilder.buildInstr(Opcode) + .add(MI.getOperand(0)) + .add(MI.getOperand(2)); + MI.eraseFromParent(); + return true; +} + bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder) const { @@ -364,6 +401,64 @@ bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr &MI, return SelectMSA3OpIntrinsic(MI, Mips::ADDVI_W, MIRBuilder, ST); case Intrinsic::mips_addvi_d: return SelectMSA3OpIntrinsic(MI, Mips::ADDVI_D, MIRBuilder, ST); + case Intrinsic::mips_subv_b: + case Intrinsic::mips_subv_h: + case Intrinsic::mips_subv_w: + case Intrinsic::mips_subv_d: + return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_SUB, MIRBuilder, ST); + case Intrinsic::mips_subvi_b: + return SelectMSA3OpIntrinsic(MI, Mips::SUBVI_B, MIRBuilder, ST); + case Intrinsic::mips_subvi_h: + return SelectMSA3OpIntrinsic(MI, Mips::SUBVI_H, MIRBuilder, ST); + case Intrinsic::mips_subvi_w: + return SelectMSA3OpIntrinsic(MI, Mips::SUBVI_W, MIRBuilder, ST); + case Intrinsic::mips_subvi_d: + return SelectMSA3OpIntrinsic(MI, Mips::SUBVI_D, MIRBuilder, ST); + case Intrinsic::mips_mulv_b: + case Intrinsic::mips_mulv_h: + case Intrinsic::mips_mulv_w: + case Intrinsic::mips_mulv_d: + return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_MUL, MIRBuilder, ST); + case Intrinsic::mips_div_s_b: + case Intrinsic::mips_div_s_h: + case Intrinsic::mips_div_s_w: + case Intrinsic::mips_div_s_d: + return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_SDIV, MIRBuilder, ST); + case Intrinsic::mips_mod_s_b: + case Intrinsic::mips_mod_s_h: + case Intrinsic::mips_mod_s_w: + case Intrinsic::mips_mod_s_d: + return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_SREM, MIRBuilder, ST); + case Intrinsic::mips_div_u_b: + case Intrinsic::mips_div_u_h: + case Intrinsic::mips_div_u_w: + case Intrinsic::mips_div_u_d: + return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_UDIV, MIRBuilder, ST); + case Intrinsic::mips_mod_u_b: + case Intrinsic::mips_mod_u_h: + case Intrinsic::mips_mod_u_w: + case Intrinsic::mips_mod_u_d: + return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_UREM, MIRBuilder, ST); + case Intrinsic::mips_fadd_w: + case Intrinsic::mips_fadd_d: + return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_FADD, MIRBuilder, ST); + case Intrinsic::mips_fsub_w: + case Intrinsic::mips_fsub_d: + return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_FSUB, MIRBuilder, ST); + case Intrinsic::mips_fmul_w: + case Intrinsic::mips_fmul_d: + return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_FMUL, MIRBuilder, ST); + case Intrinsic::mips_fdiv_w: + case Intrinsic::mips_fdiv_d: + return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_FDIV, MIRBuilder, ST); + case Intrinsic::mips_fmax_a_w: + return SelectMSA3OpIntrinsic(MI, Mips::FMAX_A_W, MIRBuilder, ST); + case Intrinsic::mips_fmax_a_d: + return SelectMSA3OpIntrinsic(MI, Mips::FMAX_A_D, MIRBuilder, ST); + case Intrinsic::mips_fsqrt_w: + return MSA2OpIntrinsicToGeneric(MI, TargetOpcode::G_FSQRT, MIRBuilder, ST); + case Intrinsic::mips_fsqrt_d: + return MSA2OpIntrinsicToGeneric(MI, TargetOpcode::G_FSQRT, MIRBuilder, ST); default: break; } diff --git a/llvm/lib/Target/Mips/MipsMCInstLower.cpp b/llvm/lib/Target/Mips/MipsMCInstLower.cpp index fd984058a2bf..66e04bda2af3 100644 --- a/llvm/lib/Target/Mips/MipsMCInstLower.cpp +++ b/llvm/lib/Target/Mips/MipsMCInstLower.cpp @@ -34,7 +34,7 @@ void MipsMCInstLower::Initialize(MCContext *C) { MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, MachineOperandType MOTy, - unsigned Offset) const { + int64_t Offset) const { MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None; bool IsGpOff = false; @@ -161,9 +161,7 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); if (Offset) { - // Assume offset is never negative. - assert(Offset > 0); - + // Note: Offset can also be negative Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx), *Ctx); } @@ -177,7 +175,7 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, } MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, - unsigned offset) const { + int64_t offset) const { MachineOperandType MOTy = MO.getType(); switch (MOTy) { diff --git a/llvm/lib/Target/Mips/MipsMCInstLower.h b/llvm/lib/Target/Mips/MipsMCInstLower.h index 29af6f21de82..605a124bf102 100644 --- a/llvm/lib/Target/Mips/MipsMCInstLower.h +++ b/llvm/lib/Target/Mips/MipsMCInstLower.h @@ -35,11 +35,11 @@ public: void Initialize(MCContext *C); void Lower(const MachineInstr *MI, MCInst &OutMI) const; - MCOperand LowerOperand(const MachineOperand& MO, unsigned offset = 0) const; + MCOperand LowerOperand(const MachineOperand &MO, int64_t offset = 0) const; private: MCOperand LowerSymbolOperand(const MachineOperand &MO, - MachineOperandType MOTy, unsigned Offset) const; + MachineOperandType MOTy, int64_t Offset) const; MCOperand createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2, MipsMCExpr::MipsExprKind Kind) const; void lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const; diff --git a/llvm/lib/Target/Mips/MipsMSAInstrInfo.td b/llvm/lib/Target/Mips/MipsMSAInstrInfo.td index f585d9c1a148..0fef518c240e 100644 --- a/llvm/lib/Target/Mips/MipsMSAInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsMSAInstrInfo.td @@ -1287,6 +1287,7 @@ class MSA_I10_LDI_DESC_BASE<string instr_asm, RegisterOperand ROWD, // LDI is matched using custom matching code in MipsSEISelDAGToDAG.cpp list<dag> Pattern = []; bit hasSideEffects = 0; + bit isReMaterializable = 1; InstrItinClass Itinerary = itin; } diff --git a/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp b/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp index ace0735652bd..f9d93ca29658 100644 --- a/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp +++ b/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp @@ -17,6 +17,7 @@ #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" #include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/InitializePasses.h" #define DEBUG_TYPE "mips-prelegalizer-combiner" diff --git a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp index d334366e727c..2a3f5a05dfe0 100644 --- a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp +++ b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -76,8 +76,9 @@ using namespace llvm; MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) : MipsGenRegisterBankInfo() {} -const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass( - const TargetRegisterClass &RC) const { +const RegisterBank & +MipsRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, + LLT) const { using namespace Mips; switch (RC.getID()) { @@ -437,12 +438,10 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { switch (Opc) { case G_TRUNC: - case G_SUB: - case G_MUL: case G_UMULH: case G_ZEXTLOAD: case G_SEXTLOAD: - case G_GEP: + case G_PTR_ADD: case G_INTTOPTR: case G_PTRTOINT: case G_AND: @@ -451,15 +450,18 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { case G_SHL: case G_ASHR: case G_LSHR: - case G_SDIV: - case G_UDIV: - case G_SREM: - case G_UREM: case G_BRINDIRECT: case G_VASTART: + case G_BSWAP: OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; break; case G_ADD: + case G_SUB: + case G_MUL: + case G_SDIV: + case G_SREM: + case G_UDIV: + case G_UREM: OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; if (Op0Size == 128) OperandsMapping = getMSAMapping(MF); @@ -546,6 +548,8 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { case G_FABS: case G_FSQRT: OperandsMapping = getFprbMapping(Op0Size); + if (Op0Size == 128) + OperandsMapping = getMSAMapping(MF); break; case G_FCONSTANT: OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr}); @@ -636,7 +640,7 @@ void MipsRegisterBankInfo::setRegBank(MachineInstr &MI, MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID)); break; } - case TargetOpcode::G_GEP: { + case TargetOpcode::G_PTR_ADD: { assert(MRI.getType(Dest).isPointer() && "Unexpected operand type."); MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID)); break; @@ -649,8 +653,9 @@ void MipsRegisterBankInfo::setRegBank(MachineInstr &MI, static void combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner, MachineInstr &MI) { + SmallVector<Register, 4> UpdatedDefs; SmallVector<MachineInstr *, 2> DeadInstrs; - ArtCombiner.tryCombineMerges(MI, DeadInstrs); + ArtCombiner.tryCombineMerges(MI, DeadInstrs, UpdatedDefs); for (MachineInstr *DeadMI : DeadInstrs) DeadMI->eraseFromParent(); } diff --git a/llvm/lib/Target/Mips/MipsRegisterBankInfo.h b/llvm/lib/Target/Mips/MipsRegisterBankInfo.h index fa0f1c7bc941..66267f8d794d 100644 --- a/llvm/lib/Target/Mips/MipsRegisterBankInfo.h +++ b/llvm/lib/Target/Mips/MipsRegisterBankInfo.h @@ -32,8 +32,8 @@ class MipsRegisterBankInfo final : public MipsGenRegisterBankInfo { public: MipsRegisterBankInfo(const TargetRegisterInfo &TRI); - const RegisterBank & - getRegBankFromRegClass(const TargetRegisterClass &RC) const override; + const RegisterBank &getRegBankFromRegClass(const TargetRegisterClass &RC, + LLT) const override; const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override; diff --git a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index c8313240a678..bef1a3657ea5 100644 --- a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -27,6 +27,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IntrinsicsMips.h" #include "llvm/IR/Type.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -234,8 +235,8 @@ void MipsSEDAGToDAGISel::selectAddE(SDNode *Node, const SDLoc &DL) const { SDValue OuFlag = CurDAG->getTargetConstant(20, DL, MVT::i32); - SDNode *DSPCtrlField = - CurDAG->getMachineNode(Mips::RDDSP, DL, MVT::i32, MVT::Glue, CstOne, InFlag); + SDNode *DSPCtrlField = CurDAG->getMachineNode(Mips::RDDSP, DL, MVT::i32, + MVT::Glue, CstOne, InFlag); SDNode *Carry = CurDAG->getMachineNode( Mips::EXT, DL, MVT::i32, SDValue(DSPCtrlField, 0), OuFlag, CstOne); @@ -253,7 +254,8 @@ void MipsSEDAGToDAGISel::selectAddE(SDNode *Node, const SDLoc &DL) const { SDValue Zero = CurDAG->getRegister(Mips::ZERO, MVT::i32); SDValue InsOps[4] = {Zero, OuFlag, CstOne, SDValue(DSPCFWithCarry, 0)}; - SDNode *DSPCtrlFinal = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, InsOps); + SDNode *DSPCtrlFinal = + CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, InsOps); SDNode *WrDSP = CurDAG->getMachineNode(Mips::WRDSP, DL, MVT::Glue, SDValue(DSPCtrlFinal, 0), CstOne); @@ -1074,7 +1076,8 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { Hi ? SDValue(Res, 0) : ZeroVal, LoVal); assert((Hi || Lo) && "Zero case reached 32 bit case splat synthesis!"); - Res = CurDAG->getMachineNode(Mips::FILL_W, DL, MVT::v4i32, SDValue(Res, 0)); + Res = + CurDAG->getMachineNode(Mips::FILL_W, DL, MVT::v4i32, SDValue(Res, 0)); } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 64 && (ABI.IsN32() || ABI.IsN64())) { @@ -1117,8 +1120,8 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { // $res4 = insert.w $res3[1], $res fill.d $res // splat.d $res4, 0 // - // The ability to use dinsu is guaranteed as MSA requires MIPSR5. This saves - // having to materialize the value by shifts and ors. + // The ability to use dinsu is guaranteed as MSA requires MIPSR5. + // This saves having to materialize the value by shifts and ors. // // FIXME: Implement the preferred sequence for MIPS64R6: // @@ -1239,7 +1242,8 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { llvm_unreachable( "Zero splat value handled by non-zero 64bit splat synthesis!"); - Res = CurDAG->getMachineNode(Mips::FILL_D, DL, MVT::v2i64, SDValue(Res, 0)); + Res = CurDAG->getMachineNode(Mips::FILL_D, DL, MVT::v2i64, + SDValue(Res, 0)); } else llvm_unreachable("Unknown ABI in MipsISelDAGToDAG!"); @@ -1278,10 +1282,6 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, default: llvm_unreachable("Unexpected asm memory constraint"); // All memory constraints can at least accept raw pointers. - case InlineAsm::Constraint_i: - OutOps.push_back(Op); - OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); - return false; case InlineAsm::Constraint_m: case InlineAsm::Constraint_o: if (selectAddrRegImm16(Op, Base, Offset)) { diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp index 5bd234f955ba..798e8784405f 100644 --- a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp @@ -34,6 +34,7 @@ #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IntrinsicsMips.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp index 2126a1bda493..d4f09a2f3586 100644 --- a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -82,8 +82,8 @@ unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr &MI, void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - const DebugLoc &DL, unsigned DestReg, - unsigned SrcReg, bool KillSrc) const { + const DebugLoc &DL, MCRegister DestReg, + MCRegister SrcReg, bool KillSrc) const { unsigned Opc = 0, ZeroReg = 0; bool isMicroMips = Subtarget.inMicroMipsMode(); @@ -221,29 +221,24 @@ static bool isReadOrWriteToDSPReg(const MachineInstr &MI, bool &isWrite) { /// We check for the common case of 'or', as it's MIPS' preferred instruction /// for GPRs but we have to check the operands to ensure that is the case. /// Other move instructions for MIPS are directly identifiable. -bool MipsSEInstrInfo::isCopyInstrImpl(const MachineInstr &MI, - const MachineOperand *&Src, - const MachineOperand *&Dest) const { +Optional<DestSourcePair> +MipsSEInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const { bool isDSPControlWrite = false; // Condition is made to match the creation of WRDSP/RDDSP copy instruction // from copyPhysReg function. if (isReadOrWriteToDSPReg(MI, isDSPControlWrite)) { - if (!MI.getOperand(1).isImm() || MI.getOperand(1).getImm() != (1<<4)) - return false; + if (!MI.getOperand(1).isImm() || MI.getOperand(1).getImm() != (1 << 4)) + return None; else if (isDSPControlWrite) { - Src = &MI.getOperand(0); - Dest = &MI.getOperand(2); + return DestSourcePair{MI.getOperand(2), MI.getOperand(0)}; + } else { - Dest = &MI.getOperand(0); - Src = &MI.getOperand(2); + return DestSourcePair{MI.getOperand(0), MI.getOperand(2)}; } - return true; } else if (MI.isMoveReg() || isORCopyInst(MI)) { - Dest = &MI.getOperand(0); - Src = &MI.getOperand(1); - return true; + return DestSourcePair{MI.getOperand(0), MI.getOperand(1)}; } - return false; + return None; } void MipsSEInstrInfo:: diff --git a/llvm/lib/Target/Mips/MipsSEInstrInfo.h b/llvm/lib/Target/Mips/MipsSEInstrInfo.h index 3111d1c21a0a..08c00ec8ccef 100644 --- a/llvm/lib/Target/Mips/MipsSEInstrInfo.h +++ b/llvm/lib/Target/Mips/MipsSEInstrInfo.h @@ -43,7 +43,7 @@ public: int &FrameIndex) const override; void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, + const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc) const override; void storeRegToStack(MachineBasicBlock &MBB, @@ -77,10 +77,10 @@ public: protected: /// If the specific machine instruction is a instruction that moves/copies - /// value from one register to another register return true along with - /// @Source machine operand and @Destination machine operand. - bool isCopyInstrImpl(const MachineInstr &MI, const MachineOperand *&Source, - const MachineOperand *&Destination) const override; + /// value from one register to another register return destination and source + /// registers as machine operands. + Optional<DestSourcePair> + isCopyInstrImpl(const MachineInstr &MI) const override; private: unsigned getAnalyzableBrOpc(unsigned Opc) const override; diff --git a/llvm/lib/Target/Mips/MipsScheduleGeneric.td b/llvm/lib/Target/Mips/MipsScheduleGeneric.td index e8a0a30b8e9b..faccb37c2361 100644 --- a/llvm/lib/Target/Mips/MipsScheduleGeneric.td +++ b/llvm/lib/Target/Mips/MipsScheduleGeneric.td @@ -720,11 +720,16 @@ def : InstRW<[GenericWriteALU], (instrs BADDu, BBIT0, BBIT032, BBIT1, BBIT132, CINS, CINS32, CINS64_32, CINS_i32, DMFC2_OCTEON, DMTC2_OCTEON, DPOP, EXTS, EXTS32, MTM0, MTM1, MTM2, MTP0, MTP1, MTP2, - POP, SEQ, SEQi, SNE, SNEi, V3MULU, VMM0, - VMULU)>; + POP, SEQ, SEQi, SNE, SNEi, + V3MULU, VMM0, VMULU)>; def : InstRW<[GenericWriteMDUtoGPR], (instrs DMUL)>; +// Cavium Networks MIPS (cnMIPSP) - Octeon+, HasCnMipsP +// ================================================= + +def : InstRW<[GenericWriteALU], (instrs SAA, SAAD)>; + // FPU Pipelines // ============= @@ -1610,5 +1615,6 @@ def : InstRW<[GenericWriteAtomic], def : InstRW<[GenericWriteAtomic], (instregex "^ATOMIC_CMP_SWAP_I(8|16|32|64)_POSTRA$")>; def : InstRW<[GenericWriteAtomic], - (instregex "^ATOMIC_LOAD_(ADD|SUB|AND|OR|XOR|NAND)_I(8|16|32|64)_POSTRA$")>; + (instregex "^ATOMIC_LOAD_(ADD|SUB|AND|OR|XOR|NAND|MIN|MAX|UMIN|UMAX)" + "_I(8|16|32|64)_POSTRA$")>; } diff --git a/llvm/lib/Target/Mips/MipsScheduleP5600.td b/llvm/lib/Target/Mips/MipsScheduleP5600.td index f97b03bff08e..7331917baa25 100644 --- a/llvm/lib/Target/Mips/MipsScheduleP5600.td +++ b/llvm/lib/Target/Mips/MipsScheduleP5600.td @@ -18,7 +18,8 @@ def MipsP5600Model : SchedMachineModel { list<Predicate> UnsupportedFeatures = [HasMips3, HasMips32r6, HasMips64, HasMips64r2, HasMips64r5, HasMips64r6, IsGP64bit, IsPTR64bit, - InMicroMips, InMips16Mode, HasCnMips, + InMicroMips, InMips16Mode, + HasCnMips, HasCnMipsP, HasDSP, HasDSPR2, HasMT, HasCRC]; } @@ -631,5 +632,6 @@ def : InstRW<[P5600WriteAtomic], def : InstRW<[P5600WriteAtomic], (instregex "^ATOMIC_CMP_SWAP_I(8|16|32|64)_POSTRA$")>; def : InstRW<[P5600WriteAtomic], - (instregex "^ATOMIC_LOAD_(ADD|SUB|AND|OR|XOR|NAND)_I(8|16|32|64)_POSTRA$")>; + (instregex "^ATOMIC_LOAD_(ADD|SUB|AND|OR|XOR|NAND|MIN|MAX|UMIN|UMAX)" + "_I(8|16|32|64)_POSTRA$")>; } diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index b9245c9fc0eb..133b818114c8 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -74,16 +74,17 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, IsLittle(little), IsSoftFloat(false), IsSingleFloat(false), IsFPXX(false), NoABICalls(false), Abs2008(false), IsFP64bit(false), UseOddSPReg(true), IsNaN2008bit(false), IsGP64bit(false), HasVFPU(false), HasCnMips(false), - HasMips3_32(false), HasMips3_32r2(false), HasMips4_32(false), - HasMips4_32r2(false), HasMips5_32r2(false), InMips16Mode(false), - InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false), - HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 | Mips_Os16), - Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false), - HasEVA(false), DisableMadd4(false), HasMT(false), HasCRC(false), - HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false), - StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT), - TSInfo(), InstrInfo(MipsInstrInfo::create( - initializeSubtargetDependencies(CPU, FS, TM))), + HasCnMipsP(false), HasMips3_32(false), HasMips3_32r2(false), + HasMips4_32(false), HasMips4_32r2(false), HasMips5_32r2(false), + InMips16Mode(false), InMips16HardFloat(Mips16HardFloat), + InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), HasDSPR3(false), + AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), HasMSA(false), + UseTCCInDIV(false), HasSym32(false), HasEVA(false), DisableMadd4(false), + HasMT(false), HasCRC(false), HasVirt(false), HasGINV(false), + UseIndirectJumpsHazard(false), StackAlignOverride(StackAlignOverride), + TM(TM), TargetTriple(TT), TSInfo(), + InstrInfo( + MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))), FrameLowering(MipsFrameLowering::create(*this)), TLInfo(MipsTargetLowering::create(TM, *this)) { @@ -255,6 +256,10 @@ MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, stackAlignment = Align(8); } + if ((isABI_N32() || isABI_N64()) && !isGP64bit()) + report_fatal_error("64-bit code requested on a subtarget that doesn't " + "support it!"); + return *this; } diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h index 0a8c2ef8ae5c..5a1dfec41a47 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/llvm/lib/Target/Mips/MipsSubtarget.h @@ -111,6 +111,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // CPU supports cnMIPS (Cavium Networks Octeon CPU). bool HasCnMips; + // CPU supports cnMIPSP (Cavium Networks Octeon+ CPU). + bool HasCnMipsP; + // isLinux - Target system is Linux. Is false we consider ELFOS for now. bool IsLinux; @@ -270,6 +273,7 @@ public: bool hasMips64r6() const { return MipsArchVersion >= Mips64r6; } bool hasCnMips() const { return HasCnMips; } + bool hasCnMipsP() const { return HasCnMipsP; } bool isLittle() const { return IsLittle; } bool isABICalls() const { return !NoABICalls; } diff --git a/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/llvm/lib/Target/Mips/MipsTargetMachine.cpp index e58f316791ba..8fec6db00cb9 100644 --- a/llvm/lib/Target/Mips/MipsTargetMachine.cpp +++ b/llvm/lib/Target/Mips/MipsTargetMachine.cpp @@ -23,16 +23,17 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/CodeGen/BasicTTIImpl.h" #include "llvm/CodeGen/GlobalISel/IRTranslator.h" +#include "llvm/CodeGen/GlobalISel/InstructionSelect.h" #include "llvm/CodeGen/GlobalISel/Legalizer.h" #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" -#include "llvm/CodeGen/GlobalISel/InstructionSelect.h" -#include "llvm/CodeGen/BasicTTIImpl.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Function.h" +#include "llvm/InitializePasses.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Debug.h" #include "llvm/Support/TargetRegistry.h" @@ -44,7 +45,7 @@ using namespace llvm; #define DEBUG_TYPE "mips" -extern "C" void LLVMInitializeMipsTarget() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTarget() { // Register the target. RegisterTargetMachine<MipsebTargetMachine> X(getTheMipsTarget()); RegisterTargetMachine<MipselTargetMachine> Y(getTheMipselTarget()); diff --git a/llvm/lib/Target/Mips/MipsTargetStreamer.h b/llvm/lib/Target/Mips/MipsTargetStreamer.h index 298d056ce2c3..b389ba8938c4 100644 --- a/llvm/lib/Target/Mips/MipsTargetStreamer.h +++ b/llvm/lib/Target/Mips/MipsTargetStreamer.h @@ -156,10 +156,6 @@ public: unsigned BaseReg, int64_t Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, const MCSubtargetInfo *STI); - void emitSCWithSymOffset(unsigned Opcode, unsigned SrcReg, unsigned BaseReg, - MCOperand &HiOperand, MCOperand &LoOperand, - unsigned ATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI); void emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg, int64_t Offset, unsigned TmpReg, SMLoc IDLoc, const MCSubtargetInfo *STI); diff --git a/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp index 0082ca34cdbd..44041987ec76 100644 --- a/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp +++ b/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp @@ -27,7 +27,7 @@ Target &llvm::getTheMips64elTarget() { return TheMips64elTarget; } -extern "C" void LLVMInitializeMipsTargetInfo() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTargetInfo() { RegisterTarget<Triple::mips, /*HasJIT=*/true> X(getTheMipsTarget(), "mips", "MIPS (32-bit big endian)", "Mips"); |
